Add `git_remote_dup`.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
diff --git a/include/git2/remote.h b/include/git2/remote.h
index 7410909..d3e6caa 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -108,6 +108,18 @@ GIT_EXTERN(int) git_remote_load(git_remote **out, git_repository *repo, const ch
GIT_EXTERN(int) git_remote_save(const git_remote *remote);
/**
+ * Create a copy of an existing remote. All internal strings are also
+ * duplicated. Callbacks are not duplicated.
+ *
+ * Call `git_remote_free` to free the data.
+ *
+ * @param dest pointer where to store the copy
+ * @param source object to copy
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_remote_dup(git_remote **dest, const git_remote *source);
+
+/**
* Get the remote's repository
*
* @param remote the remote
diff --git a/src/remote.c b/src/remote.c
index 294a870..6a4a707 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -248,6 +248,47 @@ int git_remote_create_inmemory(git_remote **out, git_repository *repo, const cha
return 0;
}
+int git_remote_dup(git_remote **dest, const git_remote *source)
+{
+ int error;
+ git_remote *remote = git__calloc(1, sizeof(git_remote));
+ GITERR_CHECK_ALLOC(remote);
+
+ memset(remote, 0x0, sizeof(git_remote));
+
+ if (source->name != NULL) {
+ remote->name = git__strdup(source->name);
+ GITERR_CHECK_ALLOC(remote->name);
+ }
+
+ if (source->url != NULL) {
+ remote->url = git__strdup(source->url);
+ GITERR_CHECK_ALLOC(remote->url);
+ }
+
+ if (source->pushurl != NULL) {
+ remote->pushurl = git__strdup(source->pushurl);
+ GITERR_CHECK_ALLOC(remote->pushurl);
+ }
+
+ remote->repo = source->repo;
+ remote->need_pack = source->need_pack;
+ remote->download_tags = source->download_tags;
+ remote->check_cert = source->check_cert;
+ remote->update_fetchhead = source->update_fetchhead;
+
+ if ((error = git_vector_dup(&remote->refs, &source->refs, NULL)) < 0 ||
+ (error = git_vector_dup(&remote->refspecs, &source->refspecs, NULL)) < 0 ||
+ (error = git_vector_dup(&remote->active_refspecs, &source->active_refspecs, NULL))) {
+ git__free(remote);
+ return error;
+ }
+
+ *dest = remote;
+
+ return 0;
+}
+
struct refspec_cb_data {
git_remote *remote;
int fetch;
diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c
index 954ded8..235a102 100644
--- a/tests/network/remote/remotes.c
+++ b/tests/network/remote/remotes.c
@@ -129,6 +129,27 @@ void test_network_remote_remotes__add_fetchspec(void)
cl_assert_equal_b(_refspec->push, false);
}
+void test_network_remote_remotes__dup(void)
+{
+ git_strarray array;
+ git_remote *dup;
+
+ cl_git_pass(git_remote_dup(&dup, _remote));
+
+ cl_assert_equal_s(git_remote_name(dup), git_remote_name(_remote));
+ cl_assert_equal_s(git_remote_url(dup), git_remote_url(_remote));
+ cl_assert_equal_s(git_remote_pushurl(dup), git_remote_pushurl(_remote));
+
+ cl_git_pass(git_remote_get_fetch_refspecs(&array, _remote));
+ cl_assert_equal_i(1, (int)array.count);
+ cl_assert_equal_s("+refs/heads/*:refs/remotes/test/*", array.strings[0]);
+ git_strarray_free(&array);
+
+ cl_git_pass(git_remote_get_push_refspecs(&array, _remote));
+ cl_assert_equal_i(0, (int)array.count);
+ git_strarray_free(&array);
+}
+
void test_network_remote_remotes__add_pushspec(void)
{
size_t size;