>From c1bad54b29ae1c1d8548d248f6ecaa5959e55f7b Mon Sep 17 00:00:00 2001 From: Kenneth Cochran <kenneth.cochran101@xxxxxxxxx> Date: Mon, 4 Mar 2019 01:08:46 -0600 Subject: [RFC PATCH 4/4] branch: disallow accidentally breaking symrefs Cc: Sahil Dua <sahildua2305@xxxxxxxxx>, Duy Nguyen <pclouds@xxxxxxxxx>, Jeff King <peff@xxxxxxxx> Currently, symrefs are ignored when deleting a branch, making it possible to accidentally create dangling symrefs without any warning. These changes give an error if a branch deletion operation would create a dangling symref, unless the user specifies to force the delete anyways. Signed-off-by: Kenneth Cochran <kenneth.cochran101@xxxxxxxxx> --- builtin/branch.c | 20 ++++++++++++++++++++ t/t3207-branch-alias.sh | 12 ++++++++++++ 2 files changed, 32 insertions(+) diff --git a/builtin/branch.c b/builtin/branch.c index 4b8b8fc08f..5c05ccd5e9 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -233,6 +233,11 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, if (kinds == FILTER_REFS_BRANCHES) { const struct worktree *wt = find_shared_symref("HEAD", name); + char *buf; + size_t len; + FILE *memstream; + int cont = 0; + if (wt) { error(_("Cannot delete branch '%s' " "checked out at '%s'"), @@ -240,6 +245,21 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, ret = 1; continue; } + + memstream = open_memstream(&buf, &len); + warn_dangling_symref(memstream, "%s", name); + fclose(memstream); + buf[strcspn(buf, "\n")] = '\0'; + if (len > 0 && !force) { + cont = 1; + error(_("Deleting branch '%s' would leave dangling symrefs.\n" + "If you're sure you want to delete it, run 'git branch -D %s'\n" + "The following symrefs would be left dangling:\n%s"), + bname.buf, bname.buf, buf); + } + free(buf); + if (cont) + continue; } target = resolve_refdup(name, diff --git a/t/t3207-branch-alias.sh b/t/t3207-branch-alias.sh index c1edeed4eb..2f3a7b398b 100755 --- a/t/t3207-branch-alias.sh +++ b/t/t3207-branch-alias.sh @@ -68,4 +68,16 @@ test_expect_success 'git branch -d refuses to delete an indirectly checked out s test_must_fail git branch -d symd ' +test_expect_success 'git branch -d refuses to create a dangling symref' ' + git branch dangling_parent && + git branch --alias dangling dangling_parent && + git branch -d dangling_parent && + test_path_is_file .git/refs/heads/dangling_parent +' + +test_expect_success 'git branch -D forces creation of dangling symref' ' + git branch -D dangling_parent && + test_must_fail test_path_is_file .git/refs/heads/dangling_parent +' + test_done -- 2.17.1