Commit b3aaa7a7c887006d38b7262b73575d40f51beca5

Carlos Martín Nieto 2012-07-21T17:52:51

Add a struct for network callbacks Currently only update_tips is used, but it prepares the way for progress output during download.

diff --git a/examples/network/fetch.c b/examples/network/fetch.c
index d275212..73bfbdd 100644
--- a/examples/network/fetch.c
+++ b/examples/network/fetch.c
@@ -4,6 +4,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
+#include <unistd.h>
 
 struct dl_data {
 	git_remote *remote;
@@ -39,7 +40,7 @@ exit:
 	pthread_exit(&data->ret);
 }
 
-int update_cb(const char *refname, const git_oid *a, const git_oid *b)
+int update_cb(const char *refname, const git_oid *a, const git_oid *b, void *data)
 {
 	const char *action;
 	char a_str[GIT_OID_HEXSZ+1], b_str[GIT_OID_HEXSZ+1];
@@ -65,6 +66,7 @@ int fetch(git_repository *repo, int argc, char **argv)
 	git_indexer_stats stats;
 	pthread_t worker;
 	struct dl_data data;
+	git_remote_callbacks callbacks;
 
 	// Figure out whether it's a named remote or a URL
 	printf("Fetching %s\n", argv[1]);
@@ -73,6 +75,11 @@ int fetch(git_repository *repo, int argc, char **argv)
 			return -1;
 	}
 
+	// Set up the callbacks (only update_tips for now)
+	memset(&callbacks, 0, sizeof(callbacks));
+	callbacks.update_tips = &update_cb;
+	git_remote_set_callbacks(remote, &callbacks);
+
 	// Set up the information for the background worker thread
 	data.remote = remote;
 	data.bytes = &bytes;
@@ -101,7 +108,7 @@ int fetch(git_repository *repo, int argc, char **argv)
 	// right commits. This may be needed even if there was no packfile
 	// to download, which can happen e.g. when the branches have been
 	// changed but all the neede objects are available locally.
-	if (git_remote_update_tips(remote, update_cb) < 0)
+	if (git_remote_update_tips(remote) < 0)
 		return -1;
 
 	git_remote_free(remote);
diff --git a/include/git2/remote.h b/include/git2/remote.h
index 5c01949..dc6642c 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -190,7 +190,7 @@ GIT_EXTERN(void) git_remote_free(git_remote *remote);
  * @param remote the remote to update
  * @param cb callback to run on each ref update. 'a' is the old value, 'b' is then new value
  */
-GIT_EXTERN(int) git_remote_update_tips(git_remote *remote, int (*cb)(const char *refname, const git_oid *a, const git_oid *b));
+GIT_EXTERN(int) git_remote_update_tips(git_remote *remote);
 
 /**
  * Return whether a string is a valid remote URL
@@ -238,6 +238,39 @@ GIT_EXTERN(int) git_remote_add(git_remote **out, git_repository *repo, const cha
 
 GIT_EXTERN(void) git_remote_check_cert(git_remote *remote, int check);
 
+/**
+ * Argument to the completion callback which tells it which operation
+ * finished.
+ */
+typedef enum git_remote_completion_type {
+	GIT_REMOTE_COMPLETION_DOWNLOAD,
+	GIT_REMOTE_COMPLETION_INDEXING,
+	GIT_REMOTE_COMPLETION_ERROR,
+} git_remote_completion_type;
+
+/**
+ * The callback settings structure
+ *
+ * Set the calbacks to be called by the remote.
+ */
+struct git_remote_callbacks {
+	int (*progress)(const char *str, void *data);
+	int (*completion)(git_remote_completion_type type, void *data);
+	int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data);
+	void *data;
+};
+
+/**
+ * Set the callbacks for a remote
+ *
+ * Note that the remote keeps its own copy of the data and you need to
+ * call this function again if you want to change the callbacks.
+ *
+ * @param remote the remote to configure
+ * @param callbacks a pointer to the user's callback settings
+ */
+GIT_EXTERN(void) git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks);
+
 /** @} */
 GIT_END_DECL
 #endif
diff --git a/include/git2/types.h b/include/git2/types.h
index 6919030..acd5a73 100644
--- a/include/git2/types.h
+++ b/include/git2/types.h
@@ -179,6 +179,7 @@ typedef struct git_refspec git_refspec;
 typedef struct git_remote git_remote;
 
 typedef struct git_remote_head git_remote_head;
+typedef struct git_remote_callbacks git_remote_callbacks;
 
 /** @} */
 GIT_END_DECL
diff --git a/src/remote.c b/src/remote.c
index 00e108a..e661fff 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -331,7 +331,7 @@ int git_remote_download(git_remote *remote, git_off_t *bytes, git_indexer_stats 
 	return git_fetch_download_pack(remote, bytes, stats);
 }
 
-int git_remote_update_tips(git_remote *remote, int (*cb)(const char *refname, const git_oid *a, const git_oid *b))
+int git_remote_update_tips(git_remote *remote)
 {
 	int error = 0;
 	unsigned int i = 0;
@@ -381,8 +381,8 @@ int git_remote_update_tips(git_remote *remote, int (*cb)(const char *refname, co
 
 		git_reference_free(ref);
 
-		if (cb != NULL) {
-			if (cb(refname.ptr, &old, &head->oid) < 0)
+		if (remote->callbacks.update_tips != NULL) {
+			if (remote->callbacks.update_tips(refname.ptr, &old, &head->oid, remote->callbacks.data) < 0)
 				goto on_error;
 		}
 	}
@@ -525,3 +525,10 @@ void git_remote_check_cert(git_remote *remote, int check)
 
 	remote->check_cert = check;
 }
+
+void git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks)
+{
+	assert(remote && callbacks);
+
+	memcpy(&remote->callbacks, callbacks, sizeof(git_remote_callbacks));
+}
diff --git a/src/remote.h b/src/remote.h
index 0949ad4..3360b62 100644
--- a/src/remote.h
+++ b/src/remote.h
@@ -19,6 +19,7 @@ struct git_remote {
 	struct git_refspec push;
 	git_transport *transport;
 	git_repository *repo;
+	git_remote_callbacks callbacks;
 	unsigned int need_pack:1,
 		check_cert;
 };