diff options
author | Junio C Hamano <gitster@pobox.com> | 2011-12-16 22:33:34 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2011-12-16 22:33:34 -0800 |
commit | e9bba5340e1ba370bb2f64a514c87fdaf417d6d7 (patch) | |
tree | b49fc2cf8f3507e11e50c663948a92e693e7f899 /fast-import.c | |
parent | 0bbaa5c076f51a0eb3ab4f53bbc5a32ce66cf954 (diff) | |
parent | 183868578049f5a28f7166716a4b00768d148958 (diff) | |
download | git-e9bba5340e1ba370bb2f64a514c87fdaf417d6d7.tar.gz |
Merge branch 'jh/fast-import-notes'
* jh/fast-import-notes:
fast-import: Fix incorrect fanout level when modifying existing notes refs
t9301: Add 2nd testcase exposing bugs in fast-import's notes fanout handling
t9301: Fix testcase covering up a bug in fast-import's notes fanout handling
Diffstat (limited to 'fast-import.c')
-rw-r--r-- | fast-import.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/fast-import.c b/fast-import.c index 8d8ea3c45c..f4bfe0f665 100644 --- a/fast-import.c +++ b/fast-import.c @@ -2173,6 +2173,11 @@ static uintmax_t do_change_note_fanout( if (tmp_hex_sha1_len == 40 && !get_sha1_hex(hex_sha1, sha1)) { /* This is a note entry */ + if (fanout == 0xff) { + /* Counting mode, no rename */ + num_notes++; + continue; + } construct_path_with_fanout(hex_sha1, fanout, realpath); if (!strcmp(fullpath, realpath)) { /* Note entry is in correct location */ @@ -2379,7 +2384,7 @@ static void file_change_cr(struct branch *b, int rename) leaf.tree); } -static void note_change_n(struct branch *b, unsigned char old_fanout) +static void note_change_n(struct branch *b, unsigned char *old_fanout) { const char *p = command_buf.buf + 2; static struct strbuf uq = STRBUF_INIT; @@ -2390,6 +2395,23 @@ static void note_change_n(struct branch *b, unsigned char old_fanout) uint16_t inline_data = 0; unsigned char new_fanout; + /* + * When loading a branch, we don't traverse its tree to count the real + * number of notes (too expensive to do this for all non-note refs). + * This means that recently loaded notes refs might incorrectly have + * b->num_notes == 0, and consequently, old_fanout might be wrong. + * + * Fix this by traversing the tree and counting the number of notes + * when b->num_notes == 0. If the notes tree is truly empty, the + * calculation should not take long. + */ + if (b->num_notes == 0 && *old_fanout == 0) { + /* Invoke change_note_fanout() in "counting mode". */ + b->num_notes = change_note_fanout(&b->branch_tree, 0xff); + *old_fanout = convert_num_notes_to_fanout(b->num_notes); + } + + /* Now parse the notemodify command. */ /* <dataref> or 'inline' */ if (*p == ':') { char *x; @@ -2450,7 +2472,7 @@ static void note_change_n(struct branch *b, unsigned char old_fanout) typename(type), command_buf.buf); } - construct_path_with_fanout(sha1_to_hex(commit_sha1), old_fanout, path); + construct_path_with_fanout(sha1_to_hex(commit_sha1), *old_fanout, path); if (tree_content_remove(&b->branch_tree, path, NULL)) b->num_notes--; @@ -2637,7 +2659,7 @@ static void parse_new_commit(void) else if (!prefixcmp(command_buf.buf, "C ")) file_change_cr(b, 0); else if (!prefixcmp(command_buf.buf, "N ")) - note_change_n(b, prev_fanout); + note_change_n(b, &prev_fanout); else if (!strcmp("deleteall", command_buf.buf)) file_change_deleteall(b); else if (!prefixcmp(command_buf.buf, "ls ")) |