Skip to content

Commit 3164e6b

Browse files
newrengitster
authored andcommitted
fast-import: fix handling of deleted tags
If our input stream includes a tag which is later deleted, we were not properly deleting it. We did have a step which would delete it, but we left a tag in the tag list noting that it needed to be updated, and the updating of annotated tags occurred AFTER ref deletion. So, when we record that a tag needs to be deleted, also remove it from the list of annotated tags to update. While this has likely been something that has not happened in practice, it will come up more in order to support nested tags. For nested tags, we either need to give temporary names to the intermediate tags and then delete them, or else we need to use the final name for the intermediate tags. If we use the final name for the intermediate tags, then in order to keep the sanity check that someone doesn't try to update the same tag twice, we need to delete the ref after creating the intermediate tag. So, either way nested tags imply the need to delete temporary inner tag references. Helped-by: René Scharfe <[email protected]> Signed-off-by: Elijah Newren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent af2abd8 commit 3164e6b

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

fast-import.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2778,6 +2778,7 @@ static void parse_new_tag(const char *arg)
27782778
static void parse_reset_branch(const char *arg)
27792779
{
27802780
struct branch *b;
2781+
const char *tag_name;
27812782

27822783
b = lookup_branch(arg);
27832784
if (b) {
@@ -2793,6 +2794,32 @@ static void parse_reset_branch(const char *arg)
27932794
b = new_branch(arg);
27942795
read_next_command();
27952796
parse_from(b);
2797+
if (b->delete && skip_prefix(b->name, "refs/tags/", &tag_name)) {
2798+
/*
2799+
* Elsewhere, we call dump_branches() before dump_tags(),
2800+
* and dump_branches() will handle ref deletions first, so
2801+
* in order to make sure the deletion actually takes effect,
2802+
* we need to remove the tag from our list of tags to update.
2803+
*
2804+
* NEEDSWORK: replace list of tags with hashmap for faster
2805+
* deletion?
2806+
*/
2807+
struct tag *t, *prev = NULL;
2808+
for (t = first_tag; t; t = t->next_tag) {
2809+
if (!strcmp(t->name, tag_name))
2810+
break;
2811+
prev = t;
2812+
}
2813+
if (t) {
2814+
if (prev)
2815+
prev->next_tag = t->next_tag;
2816+
else
2817+
first_tag = t->next_tag;
2818+
if (!t->next_tag)
2819+
last_tag = prev;
2820+
/* There is no mem_pool_free(t) function to call. */
2821+
}
2822+
}
27962823
if (command_buf.len > 0)
27972824
unread_command_buf = 1;
27982825
}

t/t9300-fast-import.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,15 @@ test_expect_success 'A: create pack from stdin' '
8585
An annotated tag that annotates a blob.
8686
EOF
8787
88+
tag to-be-deleted
89+
from :3
90+
data <<EOF
91+
Another annotated tag that annotates a blob.
92+
EOF
93+
94+
reset refs/tags/to-be-deleted
95+
from 0000000000000000000000000000000000000000
96+
8897
INPUT_END
8998
git fast-import --export-marks=marks.out <input &&
9099
git whatchanged master
@@ -157,6 +166,10 @@ test_expect_success 'A: verify tag/series-A-blob' '
157166
test_cmp expect actual
158167
'
159168

169+
test_expect_success 'A: verify tag deletion is successful' '
170+
test_must_fail git rev-parse --verify refs/tags/to-be-deleted
171+
'
172+
160173
test_expect_success 'A: verify marks output' '
161174
cat >expect <<-EOF &&
162175
:2 $(git rev-parse --verify master:file2)

0 commit comments

Comments
 (0)