Commit 62eafd0620eff3d7ca3659a3f4a4808488f0b2c3

Vicent Marti 2012-08-27T14:54:52

Merge branch 'branch-delete-ref' into development Conflicts: include/git2/refs.h

diff --git a/include/git2/branch.h b/include/git2/branch.h
index 8bf7eb9..bbbdf1c 100644
--- a/include/git2/branch.h
+++ b/include/git2/branch.h
@@ -55,21 +55,13 @@ GIT_EXTERN(int) git_branch_create(
 /**
  * Delete an existing branch reference.
  *
- * @param repo Repository where lives the branch.
+ * If the branch is successfully deleted, the passed reference
+ * object will be freed and invalidated.
  *
- * @param branch_name Name of the branch to be deleted;
- * this name is validated for consistency.
- *
- * @param branch_type Type of the considered branch. This should
- * be valued with either GIT_BRANCH_LOCAL or GIT_BRANCH_REMOTE.
- *
- * @return 0 on success, GIT_ENOTFOUND if the branch
- * doesn't exist or an error code.
+ * @param branch A valid reference representing a branch
+ * @return 0 on success, or an error code.
  */
-GIT_EXTERN(int) git_branch_delete(
-		git_repository *repo,
-		const char *branch_name,
-		git_branch_t branch_type);
+GIT_EXTERN(int) git_branch_delete(git_reference *branch);
 
 /**
  * Loop over all the branches and issue a callback for each one.
diff --git a/include/git2/refs.h b/include/git2/refs.h
index 6a8513b..660b48b 100644
--- a/include/git2/refs.h
+++ b/include/git2/refs.h
@@ -376,6 +376,16 @@ GIT_EXTERN(int) git_reference_has_log(git_reference *ref);
  */
 GIT_EXTERN(int) git_reference_is_branch(git_reference *ref);
 
+/**
+ * Check if a reference is a remote tracking branch
+ *
+ * @param ref A git reference
+ *
+ * @return 1 when the reference lives in the refs/remotes
+ * namespace; 0 otherwise.
+ */
+GIT_EXTERN(int) git_reference_is_remote(git_reference *ref);
+
 enum {
 	GIT_REF_FORMAT_NORMAL = 0,
 
diff --git a/src/branch.c b/src/branch.c
index f6f3140..cd5c10e 100644
--- a/src/branch.c
+++ b/src/branch.c
@@ -50,6 +50,12 @@ static int create_error_invalid(const char *msg)
 	return -1;
 }
 
+static int not_a_local_branch(git_reference *ref)
+{
+	giterr_set(GITERR_INVALID, "Reference '%s' is not a local branch.", git_reference_name(ref));
+	return -1;
+}
+
 int git_branch_create(
 		git_reference **ref_out,
 		git_repository *repository,
@@ -84,19 +90,19 @@ cleanup:
 	return error;
 }
 
-int git_branch_delete(git_repository *repo, const char *branch_name, git_branch_t branch_type)
+int git_branch_delete(git_reference *branch)
 {
-	git_reference *branch = NULL;
 	git_reference *head = NULL;
-	int error;
 
-	assert(repo && branch_name);
-	assert((branch_type == GIT_BRANCH_LOCAL) || (branch_type == GIT_BRANCH_REMOTE));
+	assert(branch);
 
-	if ((error = retrieve_branch_reference(&branch, repo, branch_name, branch_type == GIT_BRANCH_REMOTE)) < 0)
-		return error;
+	if (!git_reference_is_branch(branch) &&
+		!git_reference_is_remote(branch)) {
+		giterr_set(GITERR_INVALID, "Reference '%s' is not a valid branch.", git_reference_name(branch));
+		return -1;
+	}
 
-	if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0) {
+	if (git_reference_lookup(&head, git_reference_owner(branch), GIT_HEAD_FILE) < 0) {
 		giterr_set(GITERR_REFERENCE, "Cannot locate HEAD.");
 		goto on_error;
 	}
@@ -104,7 +110,7 @@ int git_branch_delete(git_repository *repo, const char *branch_name, git_branch_
 	if ((git_reference_type(head) == GIT_REF_SYMBOLIC)
 		&& (strcmp(git_reference_target(head), git_reference_name(branch)) == 0)) {
 			giterr_set(GITERR_REFERENCE,
-					"Cannot delete branch '%s' as it is the current HEAD of the repository.", branch_name);
+					"Cannot delete branch '%s' as it is the current HEAD of the repository.", git_reference_name(branch));
 			goto on_error;
 	}
 
@@ -116,7 +122,6 @@ int git_branch_delete(git_repository *repo, const char *branch_name, git_branch_
 
 on_error:
 	git_reference_free(head);
-	git_reference_free(branch);
 	return -1;
 }
 
@@ -163,12 +168,6 @@ int git_branch_foreach(
 	return git_reference_foreach(repo, GIT_REF_LISTALL, &branch_foreach_cb, (void *)&filter);
 }
 
-static int not_a_local_branch(git_reference *ref)
-{
-	giterr_set(GITERR_INVALID, "Reference '%s' is not a local branch.", git_reference_name(ref));
-	return -1;
-}
-
 int git_branch_move(
 	git_reference *branch,
 	const char *new_branch_name,
diff --git a/src/refs.c b/src/refs.c
index 9fc194c..eb8af58 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -1836,6 +1836,11 @@ int git_reference_has_log(
 int git_reference_is_branch(git_reference *ref)
 {
 	assert(ref);
-
 	return git__prefixcmp(ref->name, GIT_REFS_HEADS_DIR) == 0;
 }
+
+int git_reference_is_remote(git_reference *ref)
+{
+	assert(ref);
+	return git__prefixcmp(ref->name, GIT_REFS_REMOTES_DIR) == 0;
+}
diff --git a/src/unix/map.c b/src/unix/map.c
index 9dcae58..ee7888c 100644
--- a/src/unix/map.c
+++ b/src/unix/map.c
@@ -31,6 +31,8 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
 		mflag = MAP_SHARED;
 	else if ((flags & GIT_MAP_TYPE) == GIT_MAP_PRIVATE)
 		mflag = MAP_PRIVATE;
+	else
+		mflag = MAP_SHARED;
 
 	out->data = mmap(NULL, len, mprot, mflag, fd, offset);
 
diff --git a/tests-clar/refs/branches/delete.c b/tests-clar/refs/branches/delete.c
index 699655f..b261240 100644
--- a/tests-clar/refs/branches/delete.c
+++ b/tests-clar/refs/branches/delete.c
@@ -23,37 +23,37 @@ void test_refs_branches_delete__cleanup(void)
 	cl_fixture_cleanup("testrepo.git");
 }
 
-void test_refs_branches_delete__can_not_delete_a_non_existing_branch(void)
-{
-	cl_git_fail(git_branch_delete(repo, "i-am-not-a-local-branch", GIT_BRANCH_LOCAL));
-	cl_git_fail(git_branch_delete(repo, "neither/a-remote-one", GIT_BRANCH_REMOTE));
-}
-
 void test_refs_branches_delete__can_not_delete_a_branch_pointed_at_by_HEAD(void)
 {
 	git_reference *head;
+	git_reference *branch;
 
 	/* Ensure HEAD targets the local master branch */
 	cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE));
 	cl_assert(strcmp("refs/heads/master", git_reference_target(head)) == 0);
 	git_reference_free(head);
 
-	cl_git_fail(git_branch_delete(repo, "master", GIT_BRANCH_LOCAL));
+	cl_git_pass(git_branch_lookup(&branch, repo, "master", GIT_BRANCH_LOCAL));
+	cl_git_fail(git_branch_delete(branch));
+	git_reference_free(branch);
 }
 
 void test_refs_branches_delete__can_not_delete_a_branch_if_HEAD_is_missing(void)
 {
 	git_reference *head;
+	git_reference *branch = NULL;
 
 	cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE));
 	git_reference_delete(head);
 
-	cl_git_fail(git_branch_delete(repo, "br2", GIT_BRANCH_LOCAL));
+	cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_LOCAL));
+	cl_git_fail(git_branch_delete(branch));
+	git_reference_free(branch);
 }
 
 void test_refs_branches_delete__can_delete_a_branch_pointed_at_by_detached_HEAD(void)
 {
-	git_reference *master, *head;
+	git_reference *master, *head, *branch;
 
 	/* Detach HEAD and make it target the commit that "master" points to */
 	cl_git_pass(git_reference_lookup(&master, repo, "refs/heads/master"));
@@ -61,30 +61,21 @@ void test_refs_branches_delete__can_delete_a_branch_pointed_at_by_detached_HEAD(
 	git_reference_free(head);
 	git_reference_free(master);
 
-	cl_git_pass(git_branch_delete(repo, "master", GIT_BRANCH_LOCAL));
+	cl_git_pass(git_branch_lookup(&branch, repo, "master", GIT_BRANCH_LOCAL));
+	cl_git_pass(git_branch_delete(branch));
 }
 
 void test_refs_branches_delete__can_delete_a_local_branch(void)
 {
-	cl_git_pass(git_branch_delete(repo, "br2", GIT_BRANCH_LOCAL));
+	git_reference *branch;
+	cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_LOCAL));
+	cl_git_pass(git_branch_delete(branch));
 }
 
 void test_refs_branches_delete__can_delete_a_remote_branch(void)
 {
-	cl_git_pass(git_branch_delete(repo, "nulltoken/master", GIT_BRANCH_REMOTE));
+	git_reference *branch;
+	cl_git_pass(git_branch_lookup(&branch, repo, "nulltoken/master", GIT_BRANCH_REMOTE));
+	cl_git_pass(git_branch_delete(branch));
 }
 
-static void assert_non_exisitng_branch_removal(const char *branch_name, git_branch_t branch_type)
-{
-	int error; 
-	error = git_branch_delete(repo, branch_name, branch_type);
-
-	cl_git_fail(error);
-	cl_assert_equal_i(GIT_ENOTFOUND, error);
-}
-
-void test_refs_branches_delete__deleting_a_non_existing_branch_returns_ENOTFOUND(void)
-{
-	assert_non_exisitng_branch_removal("i-do-not-locally-exist", GIT_BRANCH_LOCAL);
-	assert_non_exisitng_branch_removal("neither/remotely", GIT_BRANCH_REMOTE);
-}