From f5d0e162c49320d5069a63a05960fc5a38d72423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Thu, 18 Oct 2012 14:02:51 +0200 Subject: branch: factor out check_branch_commit() Move the code to perform checks on the tip commit of a branch to its own function. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- builtin/branch.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'builtin') diff --git a/builtin/branch.c b/builtin/branch.c index ffd26849c..852019ed8 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -154,10 +154,28 @@ static int branch_merged(int kind, const char *name, return merged; } +static int check_branch_commit(const char *branchname, const char *refname, + unsigned char *sha1, struct commit *head_rev, + int kinds, int force) +{ + struct commit *rev = lookup_commit_reference(sha1); + if (!rev) { + error(_("Couldn't look up commit object for '%s'"), refname); + return -1; + } + if (!force && !branch_merged(kinds, branchname, rev, head_rev)) { + error(_("The branch '%s' is not fully merged.\n" + "If you are sure you want to delete it, " + "run 'git branch -D %s'."), branchname, branchname); + return -1; + } + return 0; +} + static int delete_branches(int argc, const char **argv, int force, int kinds, int quiet) { - struct commit *rev, *head_rev = NULL; + struct commit *head_rev = NULL; unsigned char sha1[20]; char *name = NULL; const char *fmt; @@ -206,17 +224,8 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, continue; } - rev = lookup_commit_reference(sha1); - if (!rev) { - error(_("Couldn't look up commit object for '%s'"), name); - ret = 1; - continue; - } - - if (!force && !branch_merged(kinds, bname.buf, rev, head_rev)) { - error(_("The branch '%s' is not fully merged.\n" - "If you are sure you want to delete it, " - "run 'git branch -D %s'."), bname.buf, bname.buf); + if (check_branch_commit(bname.buf, name, sha1, head_rev, kinds, + force)) { ret = 1; continue; } -- cgit v1.2.1 From 22ed79275360a3dbb480e2c510a94c4b817afad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Thu, 18 Oct 2012 14:04:08 +0200 Subject: branch: factor out delete_branch_config() Provide a small helper function for deleting branch config sections. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- builtin/branch.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'builtin') diff --git a/builtin/branch.c b/builtin/branch.c index 852019ed8..97c736115 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -172,6 +172,15 @@ static int check_branch_commit(const char *branchname, const char *refname, return 0; } +static void delete_branch_config(const char *branchname) +{ + struct strbuf buf = STRBUF_INIT; + strbuf_addf(&buf, "branch.%s", branchname); + if (git_config_rename_section(buf.buf, NULL) < 0) + warning(_("Update of config-file failed")); + strbuf_release(&buf); +} + static int delete_branches(int argc, const char **argv, int force, int kinds, int quiet) { @@ -237,17 +246,13 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, bname.buf); ret = 1; } else { - struct strbuf buf = STRBUF_INIT; if (!quiet) printf(remote_branch ? _("Deleted remote branch %s (was %s).\n") : _("Deleted branch %s (was %s).\n"), bname.buf, find_unique_abbrev(sha1, DEFAULT_ABBREV)); - strbuf_addf(&buf, "branch.%s", bname.buf); - if (git_config_rename_section(buf.buf, NULL) < 0) - warning(_("Update of config-file failed")); - strbuf_release(&buf); + delete_branch_config(bname.buf); } } -- cgit v1.2.1 From 566c7707db4eb18a116659b08d6ff7ad79fcfefd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Thu, 18 Oct 2012 14:05:17 +0200 Subject: branch: delete symref branch, not its target If a branch that is to be deleted happens to be a symref to another branch, the current code removes the targeted branch instead of the one it was called for. Change this surprising behaviour and delete the symref branch instead. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- builtin/branch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin') diff --git a/builtin/branch.c b/builtin/branch.c index 97c736115..5e1e5b4d6 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -239,7 +239,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, continue; } - if (delete_ref(name, sha1, 0)) { + if (delete_ref(name, sha1, REF_NODEREF)) { error(remote_branch ? _("Error deleting remote branch '%s'") : _("Error deleting branch '%s'"), -- cgit v1.2.1 From 0fe700e311f2d7e55eb23fe941fab9155d7f91df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Thu, 18 Oct 2012 14:07:11 +0200 Subject: branch: skip commit checks when deleting symref branches Before a branch is deleted, we check that it points to a valid commit. With -d we also check that the commit is a merged; this check is not done with -D. The reason for that is that commits pointed to by branches should never go missing; if they do then something broke and it's better to stop instead of adding to the mess. And a non-merged commit may contain changes that are worth preserving, so we require the stronger option -D instead of -d to get rid of them. If a branch consists of a symref, these concerns don't apply. Deleting such a branch can't make a commit become unreferenced, so we don't need to check if it is merged, or even if it is actually a valid commit. Skip them in that case. This allows us to delete dangling symref branches. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- builtin/branch.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'builtin') diff --git a/builtin/branch.c b/builtin/branch.c index 5e1e5b4d6..d87035a2f 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -214,6 +214,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, die(_("Couldn't look up commit object for HEAD")); } for (i = 0; i < argc; i++, strbuf_release(&bname)) { + const char *target; + int flags = 0; + strbuf_branchname(&bname, argv[i]); if (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) { error(_("Cannot delete the branch '%s' " @@ -225,7 +228,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, free(name); name = mkpathdup(fmt, bname.buf); - if (read_ref(name, sha1)) { + target = resolve_ref_unsafe(name, sha1, 0, &flags); + if (!target || + (!(flags & REF_ISSYMREF) && is_null_sha1(sha1))) { error(remote_branch ? _("remote branch '%s' not found.") : _("branch '%s' not found."), bname.buf); @@ -233,7 +238,8 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, continue; } - if (check_branch_commit(bname.buf, name, sha1, head_rev, kinds, + if (!(flags & REF_ISSYMREF) && + check_branch_commit(bname.buf, name, sha1, head_rev, kinds, force)) { ret = 1; continue; -- cgit v1.2.1 From 13baa9fe866f63311af5a5ee318beddb16eb5df4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Thu, 18 Oct 2012 14:08:03 +0200 Subject: branch: show targets of deleted symrefs, not sha1s git branch reports the abbreviated hash of the head commit of a deleted branch to make it easier for a user to undo the operation. For symref branches this doesn't help. Print the symref target instead for them. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- builtin/branch.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'builtin') diff --git a/builtin/branch.c b/builtin/branch.c index d87035a2f..1ec9c0261 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -251,15 +251,18 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, : _("Error deleting branch '%s'"), bname.buf); ret = 1; - } else { - if (!quiet) - printf(remote_branch - ? _("Deleted remote branch %s (was %s).\n") - : _("Deleted branch %s (was %s).\n"), - bname.buf, - find_unique_abbrev(sha1, DEFAULT_ABBREV)); - delete_branch_config(bname.buf); + continue; + } + if (!quiet) { + printf(remote_branch + ? _("Deleted remote branch %s (was %s).\n") + : _("Deleted branch %s (was %s).\n"), + bname.buf, + (flags & REF_ISSYMREF) + ? target + : find_unique_abbrev(sha1, DEFAULT_ABBREV)); } + delete_branch_config(bname.buf); } free(name); -- cgit v1.2.1