Commit 7376ad99275fee606f298e56ac2652c203f8ebe2

Vicent Marti 2011-06-29T11:01:35

refs: Remove duplicate rename method `git_reference_rename` now takes a `force` flag

diff --git a/include/git2/refs.h b/include/git2/refs.h
index 384e8e2..9cefca7 100644
--- a/include/git2/refs.h
+++ b/include/git2/refs.h
@@ -195,21 +195,7 @@ GIT_EXTERN(int) git_reference_set_oid(git_reference *ref, const git_oid *id);
  * and on disk.
  *
  */
-GIT_EXTERN(int) git_reference_rename(git_reference *ref, const char *new_name);
-
-/**
- * Rename an existing reference, overwriting an existing one with the
- * same name, if it exists.
- *
- * This method works for both direct and symbolic references.
- * The new name will be checked for validity and may be
- * modified into a normalized form.
- *
- * The refernece will be immediately renamed in-memory
- * and on disk.
- *
- */
-GIT_EXTERN(int) git_reference_rename_f(git_reference *ref, const char *new_name);
+GIT_EXTERN(int) git_reference_rename(git_reference *ref, const char *new_name, int force);
 
 /**
  * Delete an existing reference
diff --git a/src/refs.c b/src/refs.c
index 1ff7a40..612a779 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -80,7 +80,6 @@ static int packed_sort(const void *a, const void *b);
 static int packed_write(git_repository *repo);
 
 /* internal helpers */
-static int reference_rename(git_reference *ref, const char *new_name, int force);
 static int reference_available(git_repository *repo, const char *ref, const char *old_ref);
 
 /* name normalization */
@@ -962,137 +961,6 @@ static int reference_available(git_repository *repo, const char *ref, const char
 	return error == GIT_SUCCESS ? GIT_SUCCESS : git__throw(GIT_EEXISTS, "Reference name `%s` conflicts with existing reference", ref);
 }
 
-/*
- * Rename a reference
- *
- * If the reference is packed, we need to rewrite the
- * packfile to remove the reference from it and create
- * the reference back as a loose one.
- *
- * If the reference is loose, we just rename it on
- * the filesystem.
- *
- * We also need to re-insert the reference on its corresponding
- * in-memory cache, since the caches are indexed by refname.
- */
-static int reference_rename(git_reference *ref, const char *new_name, int force)
-{
-	int error;
-	char *old_name;
-	char old_path[GIT_PATH_MAX], new_path[GIT_PATH_MAX], normalized_name[GIT_REFNAME_MAX];
-	git_reference *looked_up_ref, *old_ref = NULL;
-
-	assert(ref);
-
-	/* Ensure the name is valid */
-	error = normalize_name(normalized_name, sizeof(normalized_name), new_name, ref->type & GIT_REF_OID);
-	if (error < GIT_SUCCESS)
-		return git__rethrow(error, "Failed to rename reference");
-
-	new_name = normalized_name;
-
-	/* Ensure we're not going to overwrite an existing reference
-	   unless the user has allowed us */
-	error = git_reference_lookup(&looked_up_ref, ref->owner, new_name);
-	if (error == GIT_SUCCESS && !force)
-		return git__throw(GIT_EEXISTS, "Failed to rename reference. Reference already exists");
-
-	if (error < GIT_SUCCESS &&
-	    error != GIT_ENOTFOUND)
-		return git__rethrow(error, "Failed to rename reference");
-
-	if ((error = reference_available(ref->owner, new_name, ref->name)) < GIT_SUCCESS)
-		return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference. Reference already exists");
-
-	old_name = ref->name;
-	ref->name = git__strdup(new_name);
-
-	if (ref->name == NULL) {
-		ref->name = old_name;
-		return GIT_ENOMEM;
-	}
-
-	if (ref->type & GIT_REF_PACKED) {
-		/* write the packfile to disk; note
-		 * that the state of the in-memory cache is not
-		 * consistent, because the reference is indexed
-		 * by its old name but it already has the new one.
-		 * This doesn't affect writing, though, and allows
-		 * us to rollback if writing fails
-		 */
-
-		ref->type &= ~GIT_REF_PACKED;
-
-		/* Create the loose ref under its new name */
-		error = loose_write(ref);
-		if (error < GIT_SUCCESS) {
-			ref->type |= GIT_REF_PACKED;
-			goto cleanup;
-		}
-
-		/* Remove from the packfile cache in order to avoid packing it back
-		 * Note : we do not rely on git_reference_delete() because this would
-		 * invalidate the reference.
-		 */
-		git_hashtable_remove(ref->owner->references.packfile, old_name);
-
-		/* Recreate the packed-refs file without the reference */
-		error = packed_write(ref->owner);
-		if (error < GIT_SUCCESS)
-			goto rename_loose_to_old_name;
-
-	} else {
-		git__joinpath(old_path, ref->owner->path_repository, old_name);
-		git__joinpath(new_path, ref->owner->path_repository, ref->name);
-
-		error = gitfo_mv_force(old_path, new_path);
-		if (error < GIT_SUCCESS)
-			goto cleanup;
-
-		/* Once succesfully renamed, remove from the cache the reference known by its old name*/
-		git_hashtable_remove(ref->owner->references.loose_cache, old_name);
-	}
-
-	/* Store the renamed reference into the loose ref cache */
-	error = git_hashtable_insert2(ref->owner->references.loose_cache, ref->name, ref, (void **) &old_ref);
-
-	/* If we force-replaced, we need to free the old reference */
-	if(old_ref)
-		reference_free(old_ref);
-
-	free(old_name);
-	return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference");
-
-cleanup:
-	/* restore the old name if this failed */
-	free(ref->name);
-	ref->name = old_name;
-	return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference");
-
-rename_loose_to_old_name:
-	/* If we hit this point. Something *bad* happened! Think "Ghostbusters
-	 * crossing the streams" definition of bad.
-	 * Either the packed-refs has been correctly generated and something else
-	 * has gone wrong, or the writing of the new packed-refs has failed, and
-	 * we're stuck with the old one. As a loose ref always takes priority over
-	 * a packed ref, we'll eventually try and rename the generated loose ref to
-	 * its former name. It even that fails, well... we might have lost the reference
-	 * for good. :-/
-	*/
-
-	git__joinpath(old_path, ref->owner->path_repository, ref->name);
-	git__joinpath(new_path, ref->owner->path_repository, old_name);
-
-	/* No error checking. We'll return the initial error */
-	gitfo_mv_force(old_path, new_path);
-
-	/* restore the old name */
-	free(ref->name);
-	ref->name = old_name;
-
-	return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference");
-}
-
 /*****************************************
  * External Library API
  *****************************************/
@@ -1422,6 +1290,138 @@ int git_reference_set_target(git_reference *ref, const char *target)
  */
 
 /*
+ * Rename a reference
+ *
+ * If the reference is packed, we need to rewrite the
+ * packfile to remove the reference from it and create
+ * the reference back as a loose one.
+ *
+ * If the reference is loose, we just rename it on
+ * the filesystem.
+ *
+ * We also need to re-insert the reference on its corresponding
+ * in-memory cache, since the caches are indexed by refname.
+ */
+int git_reference_rename(git_reference *ref, const char *new_name, int force)
+{
+	int error;
+	char *old_name;
+	char old_path[GIT_PATH_MAX], new_path[GIT_PATH_MAX], normalized_name[GIT_REFNAME_MAX];
+	git_reference *looked_up_ref, *old_ref = NULL;
+
+	assert(ref);
+
+	/* Ensure the name is valid */
+	error = normalize_name(normalized_name, sizeof(normalized_name), new_name, ref->type & GIT_REF_OID);
+	if (error < GIT_SUCCESS)
+		return git__rethrow(error, "Failed to rename reference");
+
+	new_name = normalized_name;
+
+	/* Ensure we're not going to overwrite an existing reference
+	   unless the user has allowed us */
+	error = git_reference_lookup(&looked_up_ref, ref->owner, new_name);
+	if (error == GIT_SUCCESS && !force)
+		return git__throw(GIT_EEXISTS, "Failed to rename reference. Reference already exists");
+
+	if (error < GIT_SUCCESS &&
+	    error != GIT_ENOTFOUND)
+		return git__rethrow(error, "Failed to rename reference");
+
+	if ((error = reference_available(ref->owner, new_name, ref->name)) < GIT_SUCCESS)
+		return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference. Reference already exists");
+
+	old_name = ref->name;
+	ref->name = git__strdup(new_name);
+
+	if (ref->name == NULL) {
+		ref->name = old_name;
+		return GIT_ENOMEM;
+	}
+
+	if (ref->type & GIT_REF_PACKED) {
+		/* write the packfile to disk; note
+		 * that the state of the in-memory cache is not
+		 * consistent, because the reference is indexed
+		 * by its old name but it already has the new one.
+		 * This doesn't affect writing, though, and allows
+		 * us to rollback if writing fails
+		 */
+
+		ref->type &= ~GIT_REF_PACKED;
+
+		/* Create the loose ref under its new name */
+		error = loose_write(ref);
+		if (error < GIT_SUCCESS) {
+			ref->type |= GIT_REF_PACKED;
+			goto cleanup;
+		}
+
+		/* Remove from the packfile cache in order to avoid packing it back
+		 * Note : we do not rely on git_reference_delete() because this would
+		 * invalidate the reference.
+		 */
+		git_hashtable_remove(ref->owner->references.packfile, old_name);
+
+		/* Recreate the packed-refs file without the reference */
+		error = packed_write(ref->owner);
+		if (error < GIT_SUCCESS)
+			goto rename_loose_to_old_name;
+
+	} else {
+		git__joinpath(old_path, ref->owner->path_repository, old_name);
+		git__joinpath(new_path, ref->owner->path_repository, ref->name);
+
+		error = gitfo_mv_force(old_path, new_path);
+		if (error < GIT_SUCCESS)
+			goto cleanup;
+
+		/* Once succesfully renamed, remove from the cache the reference known by its old name*/
+		git_hashtable_remove(ref->owner->references.loose_cache, old_name);
+	}
+
+	/* Store the renamed reference into the loose ref cache */
+	error = git_hashtable_insert2(ref->owner->references.loose_cache, ref->name, ref, (void **) &old_ref);
+
+	/* If we force-replaced, we need to free the old reference */
+	if(old_ref)
+		reference_free(old_ref);
+
+	free(old_name);
+	return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference");
+
+cleanup:
+	/* restore the old name if this failed */
+	free(ref->name);
+	ref->name = old_name;
+	return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference");
+
+rename_loose_to_old_name:
+	/* If we hit this point. Something *bad* happened! Think "Ghostbusters
+	 * crossing the streams" definition of bad.
+	 * Either the packed-refs has been correctly generated and something else
+	 * has gone wrong, or the writing of the new packed-refs has failed, and
+	 * we're stuck with the old one. As a loose ref always takes priority over
+	 * a packed ref, we'll eventually try and rename the generated loose ref to
+	 * its former name. It even that fails, well... we might have lost the reference
+	 * for good. :-/
+	*/
+
+	git__joinpath(old_path, ref->owner->path_repository, ref->name);
+	git__joinpath(new_path, ref->owner->path_repository, old_name);
+
+	/* No error checking. We'll return the initial error */
+	gitfo_mv_force(old_path, new_path);
+
+	/* restore the old name */
+	free(ref->name);
+	ref->name = old_name;
+
+	return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to rename reference");
+}
+
+
+/*
  * Delete a reference.
  *
  * If the reference is packed, this is an expensive
@@ -1474,16 +1474,6 @@ cleanup:
 	return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to delete reference");
 }
 
-int git_reference_rename(git_reference *ref, const char *new_name)
-{
-	return reference_rename(ref, new_name, 0);
-}
-
-int git_reference_rename_f(git_reference *ref, const char *new_name)
-{
-	return reference_rename(ref, new_name, 1);
-}
-
 int git_reference_resolve(git_reference **resolved_ref, git_reference *ref)
 {
 	git_repository *repo;
diff --git a/tests/t10-refs.c b/tests/t10-refs.c
index 0ca30d0..7b4ae5e 100644
--- a/tests/t10-refs.c
+++ b/tests/t10-refs.c
@@ -494,7 +494,7 @@ BEGIN_TEST(rename0, "rename a loose reference")
 	must_be_true((looked_up_ref->type & GIT_REF_PACKED) == 0);
 
 	/* Now that the reference is renamed... */
-	must_pass(git_reference_rename(looked_up_ref, new_name));
+	must_pass(git_reference_rename(looked_up_ref, new_name, 0));
 	must_be_true(!strcmp(looked_up_ref->name, new_name));
 
 	/* ...It can't be looked-up with the old name... */
@@ -534,7 +534,7 @@ BEGIN_TEST(rename1, "rename a packed reference (should make it loose)")
 	must_be_true((looked_up_ref->type & GIT_REF_PACKED) != 0);
 
 	/* Now that the reference is renamed... */
-	must_pass(git_reference_rename(looked_up_ref, brand_new_name));
+	must_pass(git_reference_rename(looked_up_ref, brand_new_name, 0));
 	must_be_true(!strcmp(looked_up_ref->name, brand_new_name));
 
 	/* ...It can't be looked-up with the old name... */
@@ -580,7 +580,7 @@ BEGIN_TEST(rename2, "renaming a packed reference does not pack another reference
 	must_be_true((looked_up_ref->type & GIT_REF_PACKED) != 0);
 
 	/* Now that the reference is renamed... */
-	must_pass(git_reference_rename(looked_up_ref, brand_new_name));
+	must_pass(git_reference_rename(looked_up_ref, brand_new_name, 0));
 
 	/* Lookup the other reference */
 	must_pass(git_reference_lookup(&another_looked_up_ref, repo, packed_test_head_name));
@@ -604,7 +604,7 @@ BEGIN_TEST(rename3, "can not rename a reference with the name of an existing ref
 	must_pass(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
 
 	/* Can not be renamed to the name of another existing reference. */
-	must_fail(git_reference_rename(looked_up_ref, packed_test_head_name));
+	must_fail(git_reference_rename(looked_up_ref, packed_test_head_name, 0));
 
 	/* Failure to rename it hasn't corrupted its state */
 	must_pass(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
@@ -623,10 +623,10 @@ BEGIN_TEST(rename4, "can not rename a reference with an invalid name")
 	must_pass(git_reference_lookup(&looked_up_ref, repo, packed_test_head_name));
 
 	/* Can not be renamed with an invalid name. */
-	must_fail(git_reference_rename(looked_up_ref, "Hello! I'm a very invalid name."));
+	must_fail(git_reference_rename(looked_up_ref, "Hello! I'm a very invalid name.", 0));
 
 	/* Can not be renamed outside of the refs hierarchy. */
-	must_fail(git_reference_rename(looked_up_ref, "i-will-sudo-you"));
+	must_fail(git_reference_rename(looked_up_ref, "i-will-sudo-you", 0));
 
 	/* Failure to rename it hasn't corrupted its state */
 	must_pass(git_reference_lookup(&looked_up_ref, repo, packed_test_head_name));
@@ -645,7 +645,7 @@ BEGIN_TEST(rename5, "can force-rename a reference with the name of an existing r
 	must_pass(git_reference_lookup(&looked_up_ref, repo, packed_head_name));
 
 	/* Can be force-renamed to the name of another existing reference. */
-	must_pass(git_reference_rename_f(looked_up_ref, packed_test_head_name));
+	must_pass(git_reference_rename(looked_up_ref, packed_test_head_name, 1));
 
 	/* Check we actually renamed it */
 	must_pass(git_reference_lookup(&looked_up_ref, repo, packed_test_head_name));