diff --git a/examples/network/Makefile b/examples/network/Makefile index ed0c2099f..c21869ac9 100644 --- a/examples/network/Makefile +++ b/examples/network/Makefile @@ -2,7 +2,7 @@ default: all CC = gcc CFLAGS += -g -CFLAGS += -I../../include -L../../ -lgit2 +CFLAGS += -I../../include -L../../ -lgit2 -lpthread OBJECTS = \ git2.o \ diff --git a/examples/network/fetch.c b/examples/network/fetch.c index f7a60640e..d4a39746f 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -39,6 +39,25 @@ exit: pthread_exit(&data->ret); } +int update_cb(const char *refname, const git_oid *a, const git_oid *b) +{ + const char *action; + char a_str[GIT_OID_HEXSZ+1], b_str[GIT_OID_HEXSZ+1]; + + git_oid_fmt(b_str, b); + b_str[GIT_OID_HEXSZ] = '\0'; + + if (git_oid_iszero(a)) { + printf("[new] %.20s %s\n", b_str, refname); + } else { + git_oid_fmt(a_str, a); + a_str[GIT_OID_HEXSZ] = '\0'; + printf("[updated] %.10s..%.10s %s\n", a_str, b_str, refname); + } + + return 0; +} + int fetch(git_repository *repo, int argc, char **argv) { git_remote *remote = NULL; @@ -78,7 +97,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) < 0) + if (git_remote_update_tips(remote, update_cb) < 0) return -1; git_remote_free(remote); diff --git a/include/git2/remote.h b/include/git2/remote.h index 8f49fddf1..09b927e28 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -183,12 +183,10 @@ GIT_EXTERN(void) git_remote_free(git_remote *remote); /** * Update the tips to the new state * - * Make sure that you only call this once you've successfully indexed - * or expanded the packfile. - * * @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); +GIT_EXTERN(int) git_remote_update_tips(git_remote *remote, int (*cb)(const char *refname, const git_oid *a, const git_oid *b)); /** * Return whether a string is a valid remote URL diff --git a/src/remote.c b/src/remote.c index bbb491dd8..e1937df85 100644 --- a/src/remote.c +++ b/src/remote.c @@ -309,11 +309,12 @@ 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 git_remote_update_tips(git_remote *remote, int (*cb)(const char *refname, const git_oid *a, const git_oid *b)) { int error = 0; unsigned int i = 0; git_buf refname = GIT_BUF_INIT; + git_oid old; git_vector *refs = &remote->refs; git_remote_head *head; git_reference *ref; @@ -338,17 +339,36 @@ int git_remote_update_tips(git_remote *remote) head = refs->contents[i]; if (git_refspec_transform_r(&refname, spec, head->name) < 0) - break; + goto on_error; + + error = git_reference_name_to_oid(&old, remote->repo, refname.ptr); + if (error < 0 && error != GIT_ENOTFOUND) + goto on_error; + + if (error == GIT_ENOTFOUND) + memset(&old, 0, GIT_OID_RAWSZ); + + if (!git_oid_cmp(&old, &head->oid)) + continue; if (git_reference_create_oid(&ref, remote->repo, refname.ptr, &head->oid, 1) < 0) break; git_reference_free(ref); + + if (cb != NULL) { + if (cb(refname.ptr, &old, &head->oid) < 0) + goto on_error; + } } git_buf_free(&refname); + return 0; + +on_error: + git_buf_free(&refname); + return -1; - return error; } int git_remote_connected(git_remote *remote)