Skip to content

Commit 5fc9df0

Browse files
committed
Merge branch 'jh/notes' (early part)
* 'jh/notes' (early part): Add more testcases to test fast-import of notes Rename t9301 to t9350, to make room for more fast-import tests fast-import: Proper notes tree manipulation
2 parents 9ca8f83 + a8b59ef commit 5fc9df0

File tree

4 files changed

+895
-18
lines changed

4 files changed

+895
-18
lines changed

fast-import.c

Lines changed: 129 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ struct branch
245245
const char *name;
246246
struct tree_entry branch_tree;
247247
uintmax_t last_commit;
248+
uintmax_t num_notes;
248249
unsigned active : 1;
249250
unsigned pack_id : PACK_ID_BITS;
250251
unsigned char sha1[20];
@@ -702,6 +703,7 @@ static struct branch *new_branch(const char *name)
702703
b->table_next_branch = branch_table[hc];
703704
b->branch_tree.versions[0].mode = S_IFDIR;
704705
b->branch_tree.versions[1].mode = S_IFDIR;
706+
b->num_notes = 0;
705707
b->active = 0;
706708
b->pack_id = MAX_PACK_ID;
707709
branch_table[hc] = b;
@@ -1911,6 +1913,109 @@ static void load_branch(struct branch *b)
19111913
}
19121914
}
19131915

1916+
static unsigned char convert_num_notes_to_fanout(uintmax_t num_notes)
1917+
{
1918+
unsigned char fanout = 0;
1919+
while ((num_notes >>= 8))
1920+
fanout++;
1921+
return fanout;
1922+
}
1923+
1924+
static void construct_path_with_fanout(const char *hex_sha1,
1925+
unsigned char fanout, char *path)
1926+
{
1927+
unsigned int i = 0, j = 0;
1928+
if (fanout >= 20)
1929+
die("Too large fanout (%u)", fanout);
1930+
while (fanout) {
1931+
path[i++] = hex_sha1[j++];
1932+
path[i++] = hex_sha1[j++];
1933+
path[i++] = '/';
1934+
fanout--;
1935+
}
1936+
memcpy(path + i, hex_sha1 + j, 40 - j);
1937+
path[i + 40 - j] = '\0';
1938+
}
1939+
1940+
static uintmax_t do_change_note_fanout(
1941+
struct tree_entry *orig_root, struct tree_entry *root,
1942+
char *hex_sha1, unsigned int hex_sha1_len,
1943+
char *fullpath, unsigned int fullpath_len,
1944+
unsigned char fanout)
1945+
{
1946+
struct tree_content *t = root->tree;
1947+
struct tree_entry *e, leaf;
1948+
unsigned int i, tmp_hex_sha1_len, tmp_fullpath_len;
1949+
uintmax_t num_notes = 0;
1950+
unsigned char sha1[20];
1951+
char realpath[60];
1952+
1953+
for (i = 0; t && i < t->entry_count; i++) {
1954+
e = t->entries[i];
1955+
tmp_hex_sha1_len = hex_sha1_len + e->name->str_len;
1956+
tmp_fullpath_len = fullpath_len;
1957+
1958+
/*
1959+
* We're interested in EITHER existing note entries (entries
1960+
* with exactly 40 hex chars in path, not including directory
1961+
* separators), OR directory entries that may contain note
1962+
* entries (with < 40 hex chars in path).
1963+
* Also, each path component in a note entry must be a multiple
1964+
* of 2 chars.
1965+
*/
1966+
if (!e->versions[1].mode ||
1967+
tmp_hex_sha1_len > 40 ||
1968+
e->name->str_len % 2)
1969+
continue;
1970+
1971+
/* This _may_ be a note entry, or a subdir containing notes */
1972+
memcpy(hex_sha1 + hex_sha1_len, e->name->str_dat,
1973+
e->name->str_len);
1974+
if (tmp_fullpath_len)
1975+
fullpath[tmp_fullpath_len++] = '/';
1976+
memcpy(fullpath + tmp_fullpath_len, e->name->str_dat,
1977+
e->name->str_len);
1978+
tmp_fullpath_len += e->name->str_len;
1979+
fullpath[tmp_fullpath_len] = '\0';
1980+
1981+
if (tmp_hex_sha1_len == 40 && !get_sha1_hex(hex_sha1, sha1)) {
1982+
/* This is a note entry */
1983+
construct_path_with_fanout(hex_sha1, fanout, realpath);
1984+
if (!strcmp(fullpath, realpath)) {
1985+
/* Note entry is in correct location */
1986+
num_notes++;
1987+
continue;
1988+
}
1989+
1990+
/* Rename fullpath to realpath */
1991+
if (!tree_content_remove(orig_root, fullpath, &leaf))
1992+
die("Failed to remove path %s", fullpath);
1993+
tree_content_set(orig_root, realpath,
1994+
leaf.versions[1].sha1,
1995+
leaf.versions[1].mode,
1996+
leaf.tree);
1997+
} else if (S_ISDIR(e->versions[1].mode)) {
1998+
/* This is a subdir that may contain note entries */
1999+
if (!e->tree)
2000+
load_tree(e);
2001+
num_notes += do_change_note_fanout(orig_root, e,
2002+
hex_sha1, tmp_hex_sha1_len,
2003+
fullpath, tmp_fullpath_len, fanout);
2004+
}
2005+
2006+
/* The above may have reallocated the current tree_content */
2007+
t = root->tree;
2008+
}
2009+
return num_notes;
2010+
}
2011+
2012+
static uintmax_t change_note_fanout(struct tree_entry *root,
2013+
unsigned char fanout)
2014+
{
2015+
char hex_sha1[40], path[60];
2016+
return do_change_note_fanout(root, root, hex_sha1, 0, path, 0, fanout);
2017+
}
2018+
19142019
static void file_change_m(struct branch *b)
19152020
{
19162021
const char *p = command_buf.buf + 2;
@@ -2061,14 +2166,16 @@ static void file_change_cr(struct branch *b, int rename)
20612166
leaf.tree);
20622167
}
20632168

2064-
static void note_change_n(struct branch *b)
2169+
static void note_change_n(struct branch *b, unsigned char old_fanout)
20652170
{
20662171
const char *p = command_buf.buf + 2;
20672172
static struct strbuf uq = STRBUF_INIT;
20682173
struct object_entry *oe = oe;
20692174
struct branch *s;
20702175
unsigned char sha1[20], commit_sha1[20];
2176+
char path[60];
20712177
uint16_t inline_data = 0;
2178+
unsigned char new_fanout;
20722179

20732180
/* <dataref> or 'inline' */
20742181
if (*p == ':') {
@@ -2122,7 +2229,7 @@ static void note_change_n(struct branch *b)
21222229
if (oe->type != OBJ_BLOB)
21232230
die("Not a blob (actually a %s): %s",
21242231
typename(oe->type), command_buf.buf);
2125-
} else {
2232+
} else if (!is_null_sha1(sha1)) {
21262233
enum object_type type = sha1_object_info(sha1, NULL);
21272234
if (type < 0)
21282235
die("Blob not found: %s", command_buf.buf);
@@ -2131,8 +2238,17 @@ static void note_change_n(struct branch *b)
21312238
typename(type), command_buf.buf);
21322239
}
21332240

2134-
tree_content_set(&b->branch_tree, sha1_to_hex(commit_sha1), sha1,
2135-
S_IFREG | 0644, NULL);
2241+
construct_path_with_fanout(sha1_to_hex(commit_sha1), old_fanout, path);
2242+
if (tree_content_remove(&b->branch_tree, path, NULL))
2243+
b->num_notes--;
2244+
2245+
if (is_null_sha1(sha1))
2246+
return; /* nothing to insert */
2247+
2248+
b->num_notes++;
2249+
new_fanout = convert_num_notes_to_fanout(b->num_notes);
2250+
construct_path_with_fanout(sha1_to_hex(commit_sha1), new_fanout, path);
2251+
tree_content_set(&b->branch_tree, path, sha1, S_IFREG | 0644, NULL);
21362252
}
21372253

21382254
static void file_change_deleteall(struct branch *b)
@@ -2141,6 +2257,7 @@ static void file_change_deleteall(struct branch *b)
21412257
hashclr(b->branch_tree.versions[0].sha1);
21422258
hashclr(b->branch_tree.versions[1].sha1);
21432259
load_tree(&b->branch_tree);
2260+
b->num_notes = 0;
21442261
}
21452262

21462263
static void parse_from_commit(struct branch *b, char *buf, unsigned long size)
@@ -2264,6 +2381,7 @@ static void parse_new_commit(void)
22642381
char *committer = NULL;
22652382
struct hash_list *merge_list = NULL;
22662383
unsigned int merge_count;
2384+
unsigned char prev_fanout, new_fanout;
22672385

22682386
/* Obtain the branch name from the rest of our command */
22692387
sp = strchr(command_buf.buf, ' ') + 1;
@@ -2294,6 +2412,8 @@ static void parse_new_commit(void)
22942412
load_branch(b);
22952413
}
22962414

2415+
prev_fanout = convert_num_notes_to_fanout(b->num_notes);
2416+
22972417
/* file_change* */
22982418
while (command_buf.len > 0) {
22992419
if (!prefixcmp(command_buf.buf, "M "))
@@ -2305,7 +2425,7 @@ static void parse_new_commit(void)
23052425
else if (!prefixcmp(command_buf.buf, "C "))
23062426
file_change_cr(b, 0);
23072427
else if (!prefixcmp(command_buf.buf, "N "))
2308-
note_change_n(b);
2428+
note_change_n(b, prev_fanout);
23092429
else if (!strcmp("deleteall", command_buf.buf))
23102430
file_change_deleteall(b);
23112431
else {
@@ -2316,6 +2436,10 @@ static void parse_new_commit(void)
23162436
break;
23172437
}
23182438

2439+
new_fanout = convert_num_notes_to_fanout(b->num_notes);
2440+
if (new_fanout != prev_fanout)
2441+
b->num_notes = change_note_fanout(&b->branch_tree, new_fanout);
2442+
23192443
/* build the tree and the commit */
23202444
store_tree(&b->branch_tree);
23212445
hashcpy(b->branch_tree.versions[0].sha1,

0 commit comments

Comments
 (0)