diff --git a/include/git2/remote.h b/include/git2/remote.h index 15a92f3df..1f33c92e8 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -145,8 +145,11 @@ GIT_EXTERN(int) git_remote_set_pushurl(git_remote *remote, const char* url); /** * Add a fetch refspec to the remote * + * Convenience function for adding a single fetch refspec to the + * current list in the remote. + * * @param remote the remote - * @apram refspec the new fetch refspec + * @param refspec the new fetch refspec * @return 0 or an error value */ GIT_EXTERN(int) git_remote_add_fetch(git_remote *remote, const char *refspec); @@ -162,9 +165,22 @@ GIT_EXTERN(int) git_remote_add_fetch(git_remote *remote, const char *refspec); */ GIT_EXTERN(int) git_remote_get_fetch_refspecs(git_strarray *array, git_remote *remote); +/** + * Set the remote's list of fetch refspecs + * + * The contents of the string array are copied. + * + * @param remote the remote to modify + * @param array the new list of fetch resfpecs + */ +GIT_EXTERN(int) git_remote_set_fetch_refspecs(git_remote *remote, git_strarray *array); + /** * Add a push refspec to the remote * + * Convenience function for adding a single push refspec to the + * current list in the remote. + * * @param remote the remote * @param refspec the new push refspec * @return 0 or an error value @@ -182,6 +198,16 @@ GIT_EXTERN(int) git_remote_add_push(git_remote *remote, const char *refspec); */ GIT_EXTERN(int) git_remote_get_push_refspecs(git_strarray *array, git_remote *remote); +/** + * Set the remote's list of push refspecs + * + * The contents of the string array are copied. + * + * @param remote the remote to modify + * @param array the new list of push resfpecs + */ +GIT_EXTERN(int) git_remote_set_push_refspecs(git_remote *remote, git_strarray *array); + /** * Clear the refspecs * @@ -208,15 +234,6 @@ GIT_EXTERN(size_t) git_remote_refspec_count(git_remote *remote); */ GIT_EXTERN(const git_refspec *)git_remote_get_refspec(git_remote *remote, size_t n); -/** - * Remove a refspec from the remote - * - * @param remote the remote to query - * @param n the refspec to remove - * @return 0 or GIT_ENOTFOUND - */ -GIT_EXTERN(int) git_remote_remove_refspec(git_remote *remote, size_t n); - /** * Open a connection to a remote * diff --git a/src/clone.c b/src/clone.c index 657243945..f9338b746 100644 --- a/src/clone.c +++ b/src/clone.c @@ -349,7 +349,7 @@ static bool should_checkout( int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_opts *co_opts, const char *branch) { int error = 0, old_fetchhead; - size_t nspecs; + git_strarray refspecs; assert(repo && remote); @@ -358,6 +358,10 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_ return -1; } + + if ((error = git_remote_get_fetch_refspecs(&refspecs, remote)) < 0) + return error; + if ((error = git_remote_add_fetch(remote, "refs/tags/*:refs/tags/*")) < 0) return error; @@ -378,9 +382,13 @@ int git_clone_into(git_repository *repo, git_remote *remote, const git_checkout_ cleanup: git_remote_set_update_fetchhead(remote, old_fetchhead); - /* Remove the tags refspec */ - nspecs = git_remote_refspec_count(remote); - git_remote_remove_refspec(remote, nspecs); + /* Go back to the original refspecs */ + if (git_remote_set_fetch_refspecs(remote, &refspecs) < 0) { + git_strarray_free(&refspecs); + return -1; + } + + git_strarray_free(&refspecs); return error; } diff --git a/src/remote.c b/src/remote.c index 49de5fa25..a2fd21007 100644 --- a/src/remote.c +++ b/src/remote.c @@ -1047,9 +1047,6 @@ void git_remote_disconnect(git_remote *remote) void git_remote_free(git_remote *remote) { - git_refspec *spec; - size_t i; - if (remote == NULL) return; @@ -1515,14 +1512,68 @@ void git_remote_clear_refspecs(git_remote *remote) git_vector_clear(&remote->refspecs); } +static int add_and_dwim(git_remote *remote, const char *str, int push) +{ + git_refspec *spec; + git_vector *vec; + + if (add_refspec(remote, str, !push) < 0) + return -1; + + vec = &remote->refspecs; + spec = git_vector_get(vec, vec->length - 1); + return git_refspec__dwim_one(&remote->active_refspecs, spec, &remote->refs); +} + int git_remote_add_fetch(git_remote *remote, const char *refspec) { - return add_refspec(remote, refspec, true); + return add_and_dwim(remote, refspec, false); } int git_remote_add_push(git_remote *remote, const char *refspec) { - return add_refspec(remote, refspec, false); + return add_and_dwim(remote, refspec, true); +} + +static int set_refspecs(git_remote *remote, git_strarray *array, int push) +{ + git_vector *vec = &remote->refspecs; + git_refspec *spec; + size_t i; + + /* Start by removing any refspecs of the same type */ + for (i = 0; i < vec->length; i++) { + spec = git_vector_get(vec, i); + if (spec->push != push) + continue; + + git_refspec__free(spec); + git__free(spec); + git_vector_remove(vec, i); + i--; + } + + /* And now we add the new ones */ + + for (i = 0; i < array->count; i++) { + if (add_refspec(remote, array->strings[i], !push) < 0) + return -1; + } + + free_refspecs(&remote->active_refspecs); + git_vector_clear(&remote->active_refspecs); + + return dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs); +} + +int git_remote_set_fetch_refspecs(git_remote *remote, git_strarray *array) +{ + return set_refspecs(remote, array, false); +} + +int git_remote_set_push_refspecs(git_remote *remote, git_strarray *array) +{ + return set_refspecs(remote, array, true); } static int copy_refspecs(git_strarray *array, git_remote *remote, unsigned int push) @@ -1580,18 +1631,3 @@ const git_refspec *git_remote_get_refspec(git_remote *remote, size_t n) { return git_vector_get(&remote->refspecs, n); } - -int git_remote_remove_refspec(git_remote *remote, size_t n) -{ - git_refspec *spec; - - assert(remote); - - spec = git_vector_get(&remote->refspecs, n); - if (spec) { - git_refspec__free(spec); - git__free(spec); - } - - return git_vector_remove(&remote->refspecs, n); -}