summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/git2/remote.h37
-rw-r--r--src/clone.c16
-rw-r--r--src/remote.c76
3 files changed, 95 insertions, 34 deletions
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);
@@ -163,8 +166,21 @@ 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
@@ -183,6 +199,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
*
* Remove all configured fetch and push refspecs from the remote.
@@ -209,15 +235,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
*
* The transport is selected based on the URL. The direction argument
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);
-}