Commit 1c947daa by Vicent Marti

branch: Change `git_branch_delete` to take a ref

parent 17f7bde2
...@@ -55,21 +55,11 @@ GIT_EXTERN(int) git_branch_create( ...@@ -55,21 +55,11 @@ GIT_EXTERN(int) git_branch_create(
/** /**
* Delete an existing branch reference. * Delete an existing branch reference.
* *
* @param repo Repository where lives the branch. * @param branch A valid reference representing a branch
* *
* @param branch_name Name of the branch to be deleted; * @return 0 on success, or an error code.
* 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.
*/ */
GIT_EXTERN(int) git_branch_delete( GIT_EXTERN(int) git_branch_delete(git_reference *branch);
git_repository *repo,
const char *branch_name,
git_branch_t branch_type);
/** /**
* Loop over all the branches and issue a callback for each one. * Loop over all the branches and issue a callback for each one.
......
...@@ -376,6 +376,16 @@ GIT_EXTERN(int) git_reference_has_log(git_reference *ref); ...@@ -376,6 +376,16 @@ GIT_EXTERN(int) git_reference_has_log(git_reference *ref);
*/ */
GIT_EXTERN(int) git_reference_is_branch(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);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
#endif #endif
...@@ -50,6 +50,12 @@ static int create_error_invalid(const char *msg) ...@@ -50,6 +50,12 @@ static int create_error_invalid(const char *msg)
return -1; 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( int git_branch_create(
git_reference **ref_out, git_reference **ref_out,
git_repository *repository, git_repository *repository,
...@@ -106,19 +112,19 @@ cleanup: ...@@ -106,19 +112,19 @@ cleanup:
return error; 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; git_reference *head = NULL;
int error;
assert(repo && branch_name); assert(branch);
assert((branch_type == GIT_BRANCH_LOCAL) || (branch_type == GIT_BRANCH_REMOTE));
if ((error = retrieve_branch_reference(&branch, repo, branch_name, branch_type == GIT_BRANCH_REMOTE)) < 0) if (!git_reference_is_branch(branch) &&
return error; !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."); giterr_set(GITERR_REFERENCE, "Cannot locate HEAD.");
goto on_error; goto on_error;
} }
...@@ -126,7 +132,7 @@ int git_branch_delete(git_repository *repo, const char *branch_name, git_branch_ ...@@ -126,7 +132,7 @@ int git_branch_delete(git_repository *repo, const char *branch_name, git_branch_
if ((git_reference_type(head) == GIT_REF_SYMBOLIC) if ((git_reference_type(head) == GIT_REF_SYMBOLIC)
&& (strcmp(git_reference_target(head), git_reference_name(branch)) == 0)) { && (strcmp(git_reference_target(head), git_reference_name(branch)) == 0)) {
giterr_set(GITERR_REFERENCE, 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; goto on_error;
} }
...@@ -138,7 +144,6 @@ int git_branch_delete(git_repository *repo, const char *branch_name, git_branch_ ...@@ -138,7 +144,6 @@ int git_branch_delete(git_repository *repo, const char *branch_name, git_branch_
on_error: on_error:
git_reference_free(head); git_reference_free(head);
git_reference_free(branch);
return -1; return -1;
} }
...@@ -185,12 +190,6 @@ int git_branch_foreach( ...@@ -185,12 +190,6 @@ int git_branch_foreach(
return git_reference_foreach(repo, GIT_REF_LISTALL, &branch_foreach_cb, (void *)&filter); 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( int git_branch_move(
git_reference *branch, git_reference *branch,
const char *new_branch_name, const char *new_branch_name,
......
...@@ -1804,6 +1804,11 @@ int git_reference_has_log( ...@@ -1804,6 +1804,11 @@ int git_reference_has_log(
int git_reference_is_branch(git_reference *ref) int git_reference_is_branch(git_reference *ref)
{ {
assert(ref); assert(ref);
return git__prefixcmp(ref->name, GIT_REFS_HEADS_DIR) == 0; 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;
}
...@@ -23,37 +23,37 @@ void test_refs_branches_delete__cleanup(void) ...@@ -23,37 +23,37 @@ void test_refs_branches_delete__cleanup(void)
cl_fixture_cleanup("testrepo.git"); 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) void test_refs_branches_delete__can_not_delete_a_branch_pointed_at_by_HEAD(void)
{ {
git_reference *head; git_reference *head;
git_reference *branch;
/* Ensure HEAD targets the local master branch */ /* Ensure HEAD targets the local master branch */
cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE)); cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE));
cl_assert(strcmp("refs/heads/master", git_reference_target(head)) == 0); cl_assert(strcmp("refs/heads/master", git_reference_target(head)) == 0);
git_reference_free(head); 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) void test_refs_branches_delete__can_not_delete_a_branch_if_HEAD_is_missing(void)
{ {
git_reference *head; git_reference *head;
git_reference *branch = NULL;
cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE)); cl_git_pass(git_reference_lookup(&head, repo, GIT_HEAD_FILE));
git_reference_delete(head); 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) 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 */ /* Detach HEAD and make it target the commit that "master" points to */
cl_git_pass(git_reference_lookup(&master, repo, "refs/heads/master")); 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( ...@@ -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(head);
git_reference_free(master); 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) 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) 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment