summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Straub <bs@github.com>2012-12-12 12:15:25 -0800
committerBen Straub <bs@github.com>2012-12-12 12:15:25 -0800
commita71c27ccda7f7118ac2c50789fc1407d4d940b98 (patch)
tree45853babf6545972fd90f3648eb369b18a095cde
parent6cacd44bd036e9987134a4f43fee33dc1acb447b (diff)
downloadlibgit2-a71c27ccda7f7118ac2c50789fc1407d4d940b98.tar.gz
Allow creation of dangling remotes
-rw-r--r--include/git2/remote.h6
-rw-r--r--src/remote.c82
-rw-r--r--tests-clar/network/remotes.c10
3 files changed, 60 insertions, 38 deletions
diff --git a/include/git2/remote.h b/include/git2/remote.h
index 82aff385d..153bd1e42 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -43,10 +43,10 @@ typedef int (*git_remote_rename_problem_cb)(const char *problematic_refspec, voi
* See `git_tag_create()` for rules about valid names.
*
* @param out pointer to the new remote object
- * @param repo the associated repository
- * @param name the optional remote's name
+ * @param repo the associated repository. May be NULL for a "dangling" remote.
+ * @param name the optional remote's name. May be NULL.
* @param url the remote repository's URL
- * @param fetch the fetch refspec to use for this remote
+ * @param fetch the fetch refspec to use for this remote. May be NULL for defaults.
* @return 0, GIT_EINVALIDSPEC or an error code
*/
GIT_EXTERN(int) git_remote_new(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch);
diff --git a/src/remote.c b/src/remote.c
index 670904b17..3101ff7ba 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -88,7 +88,7 @@ int git_remote_new(git_remote **out, git_repository *repo, const char *name, con
git_remote *remote;
/* name is optional */
- assert(out && repo && url);
+ assert(out && url);
remote = git__calloc(1, sizeof(git_remote));
GITERR_CHECK_ALLOC(remote);
@@ -289,6 +289,11 @@ int git_remote_save(const git_remote *remote)
assert(remote);
+ if (!remote->repo) {
+ giterr_set(GITERR_INVALID, "Can't save a dangling remote.");
+ return GIT_ERROR;
+ }
+
if ((error = ensure_remote_name_is_valid(remote->name)) < 0)
return error;
@@ -543,7 +548,7 @@ int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_ur
assert(remote);
- if (!proxy_url)
+ if (!proxy_url || !remote->repo)
return -1;
*proxy_url = NULL;
@@ -745,6 +750,11 @@ int git_remote_update_tips(git_remote *remote)
assert(remote);
+ if (!remote->repo) {
+ giterr_set(GITERR_INVALID, "Can't update tips on a dangling remote.");
+ return GIT_ERROR;
+ }
+
spec = &remote->fetch;
if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
@@ -1293,49 +1303,51 @@ int git_remote_rename(
assert(remote && new_name);
- if ((error = ensure_remote_doesnot_exist(remote->repo, new_name)) < 0)
- return error;
-
if ((error = ensure_remote_name_is_valid(new_name)) < 0)
return error;
- if (!remote->name) {
- if ((error = rename_fetch_refspecs(
- remote,
- new_name,
- callback,
- payload)) < 0)
+ if (remote->repo) {
+ if ((error = ensure_remote_doesnot_exist(remote->repo, new_name)) < 0)
return error;
- remote->name = git__strdup(new_name);
+ if (!remote->name) {
+ if ((error = rename_fetch_refspecs(
+ remote,
+ new_name,
+ callback,
+ payload)) < 0)
+ return error;
- return git_remote_save(remote);
- }
+ remote->name = git__strdup(new_name);
- if ((error = rename_remote_config_section(
- remote->repo,
- remote->name,
- new_name)) < 0)
- return error;
+ return git_remote_save(remote);
+ }
- if ((error = update_branch_remote_config_entry(
- remote->repo,
- remote->name,
- new_name)) < 0)
- return error;
+ if ((error = rename_remote_config_section(
+ remote->repo,
+ remote->name,
+ new_name)) < 0)
+ return error;
- if ((error = rename_remote_references(
- remote->repo,
- remote->name,
- new_name)) < 0)
- return error;
+ if ((error = update_branch_remote_config_entry(
+ remote->repo,
+ remote->name,
+ new_name)) < 0)
+ return error;
- if ((error = rename_fetch_refspecs(
- remote,
- new_name,
- callback,
- payload)) < 0)
- return error;
+ if ((error = rename_remote_references(
+ remote->repo,
+ remote->name,
+ new_name)) < 0)
+ return error;
+
+ if ((error = rename_fetch_refspecs(
+ remote,
+ new_name,
+ callback,
+ payload)) < 0)
+ return error;
+ }
git__free(remote->name);
remote->name = git__strdup(new_name);
diff --git a/tests-clar/network/remotes.c b/tests-clar/network/remotes.c
index 70df001e7..d3f9ff80f 100644
--- a/tests-clar/network/remotes.c
+++ b/tests-clar/network/remotes.c
@@ -326,3 +326,13 @@ void test_network_remotes__check_structure_version(void)
err = giterr_last();
cl_assert_equal_i(GITERR_INVALID, err->klass);
}
+
+void test_network_remotes__dangling(void)
+{
+ cl_git_pass(git_remote_new(&_remote, NULL, "upstream", "git://github.com/libgit2/libgit2", NULL));
+ cl_git_fail(git_remote_save(_remote));
+ cl_git_fail(git_remote_update_tips(_remote));
+
+ cl_git_pass(git_remote_rename(_remote, "newname", NULL, NULL));
+ cl_assert_equal_s(git_remote_name(_remote), "newname");
+}