зеркало из https://github.com/microsoft/git.git
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
This commit is contained in:
Коммит
5fc9df08b5
134
fast-import.c
134
fast-import.c
|
@ -245,6 +245,7 @@ struct branch
|
|||
const char *name;
|
||||
struct tree_entry branch_tree;
|
||||
uintmax_t last_commit;
|
||||
uintmax_t num_notes;
|
||||
unsigned active : 1;
|
||||
unsigned pack_id : PACK_ID_BITS;
|
||||
unsigned char sha1[20];
|
||||
|
@ -702,6 +703,7 @@ static struct branch *new_branch(const char *name)
|
|||
b->table_next_branch = branch_table[hc];
|
||||
b->branch_tree.versions[0].mode = S_IFDIR;
|
||||
b->branch_tree.versions[1].mode = S_IFDIR;
|
||||
b->num_notes = 0;
|
||||
b->active = 0;
|
||||
b->pack_id = MAX_PACK_ID;
|
||||
branch_table[hc] = b;
|
||||
|
@ -1911,6 +1913,109 @@ static void load_branch(struct branch *b)
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned char convert_num_notes_to_fanout(uintmax_t num_notes)
|
||||
{
|
||||
unsigned char fanout = 0;
|
||||
while ((num_notes >>= 8))
|
||||
fanout++;
|
||||
return fanout;
|
||||
}
|
||||
|
||||
static void construct_path_with_fanout(const char *hex_sha1,
|
||||
unsigned char fanout, char *path)
|
||||
{
|
||||
unsigned int i = 0, j = 0;
|
||||
if (fanout >= 20)
|
||||
die("Too large fanout (%u)", fanout);
|
||||
while (fanout) {
|
||||
path[i++] = hex_sha1[j++];
|
||||
path[i++] = hex_sha1[j++];
|
||||
path[i++] = '/';
|
||||
fanout--;
|
||||
}
|
||||
memcpy(path + i, hex_sha1 + j, 40 - j);
|
||||
path[i + 40 - j] = '\0';
|
||||
}
|
||||
|
||||
static uintmax_t do_change_note_fanout(
|
||||
struct tree_entry *orig_root, struct tree_entry *root,
|
||||
char *hex_sha1, unsigned int hex_sha1_len,
|
||||
char *fullpath, unsigned int fullpath_len,
|
||||
unsigned char fanout)
|
||||
{
|
||||
struct tree_content *t = root->tree;
|
||||
struct tree_entry *e, leaf;
|
||||
unsigned int i, tmp_hex_sha1_len, tmp_fullpath_len;
|
||||
uintmax_t num_notes = 0;
|
||||
unsigned char sha1[20];
|
||||
char realpath[60];
|
||||
|
||||
for (i = 0; t && i < t->entry_count; i++) {
|
||||
e = t->entries[i];
|
||||
tmp_hex_sha1_len = hex_sha1_len + e->name->str_len;
|
||||
tmp_fullpath_len = fullpath_len;
|
||||
|
||||
/*
|
||||
* We're interested in EITHER existing note entries (entries
|
||||
* with exactly 40 hex chars in path, not including directory
|
||||
* separators), OR directory entries that may contain note
|
||||
* entries (with < 40 hex chars in path).
|
||||
* Also, each path component in a note entry must be a multiple
|
||||
* of 2 chars.
|
||||
*/
|
||||
if (!e->versions[1].mode ||
|
||||
tmp_hex_sha1_len > 40 ||
|
||||
e->name->str_len % 2)
|
||||
continue;
|
||||
|
||||
/* This _may_ be a note entry, or a subdir containing notes */
|
||||
memcpy(hex_sha1 + hex_sha1_len, e->name->str_dat,
|
||||
e->name->str_len);
|
||||
if (tmp_fullpath_len)
|
||||
fullpath[tmp_fullpath_len++] = '/';
|
||||
memcpy(fullpath + tmp_fullpath_len, e->name->str_dat,
|
||||
e->name->str_len);
|
||||
tmp_fullpath_len += e->name->str_len;
|
||||
fullpath[tmp_fullpath_len] = '\0';
|
||||
|
||||
if (tmp_hex_sha1_len == 40 && !get_sha1_hex(hex_sha1, sha1)) {
|
||||
/* This is a note entry */
|
||||
construct_path_with_fanout(hex_sha1, fanout, realpath);
|
||||
if (!strcmp(fullpath, realpath)) {
|
||||
/* Note entry is in correct location */
|
||||
num_notes++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Rename fullpath to realpath */
|
||||
if (!tree_content_remove(orig_root, fullpath, &leaf))
|
||||
die("Failed to remove path %s", fullpath);
|
||||
tree_content_set(orig_root, realpath,
|
||||
leaf.versions[1].sha1,
|
||||
leaf.versions[1].mode,
|
||||
leaf.tree);
|
||||
} else if (S_ISDIR(e->versions[1].mode)) {
|
||||
/* This is a subdir that may contain note entries */
|
||||
if (!e->tree)
|
||||
load_tree(e);
|
||||
num_notes += do_change_note_fanout(orig_root, e,
|
||||
hex_sha1, tmp_hex_sha1_len,
|
||||
fullpath, tmp_fullpath_len, fanout);
|
||||
}
|
||||
|
||||
/* The above may have reallocated the current tree_content */
|
||||
t = root->tree;
|
||||
}
|
||||
return num_notes;
|
||||
}
|
||||
|
||||
static uintmax_t change_note_fanout(struct tree_entry *root,
|
||||
unsigned char fanout)
|
||||
{
|
||||
char hex_sha1[40], path[60];
|
||||
return do_change_note_fanout(root, root, hex_sha1, 0, path, 0, fanout);
|
||||
}
|
||||
|
||||
static void file_change_m(struct branch *b)
|
||||
{
|
||||
const char *p = command_buf.buf + 2;
|
||||
|
@ -2061,14 +2166,16 @@ static void file_change_cr(struct branch *b, int rename)
|
|||
leaf.tree);
|
||||
}
|
||||
|
||||
static void note_change_n(struct branch *b)
|
||||
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;
|
||||
struct object_entry *oe = oe;
|
||||
struct branch *s;
|
||||
unsigned char sha1[20], commit_sha1[20];
|
||||
char path[60];
|
||||
uint16_t inline_data = 0;
|
||||
unsigned char new_fanout;
|
||||
|
||||
/* <dataref> or 'inline' */
|
||||
if (*p == ':') {
|
||||
|
@ -2122,7 +2229,7 @@ static void note_change_n(struct branch *b)
|
|||
if (oe->type != OBJ_BLOB)
|
||||
die("Not a blob (actually a %s): %s",
|
||||
typename(oe->type), command_buf.buf);
|
||||
} else {
|
||||
} else if (!is_null_sha1(sha1)) {
|
||||
enum object_type type = sha1_object_info(sha1, NULL);
|
||||
if (type < 0)
|
||||
die("Blob not found: %s", command_buf.buf);
|
||||
|
@ -2131,8 +2238,17 @@ static void note_change_n(struct branch *b)
|
|||
typename(type), command_buf.buf);
|
||||
}
|
||||
|
||||
tree_content_set(&b->branch_tree, sha1_to_hex(commit_sha1), sha1,
|
||||
S_IFREG | 0644, NULL);
|
||||
construct_path_with_fanout(sha1_to_hex(commit_sha1), old_fanout, path);
|
||||
if (tree_content_remove(&b->branch_tree, path, NULL))
|
||||
b->num_notes--;
|
||||
|
||||
if (is_null_sha1(sha1))
|
||||
return; /* nothing to insert */
|
||||
|
||||
b->num_notes++;
|
||||
new_fanout = convert_num_notes_to_fanout(b->num_notes);
|
||||
construct_path_with_fanout(sha1_to_hex(commit_sha1), new_fanout, path);
|
||||
tree_content_set(&b->branch_tree, path, sha1, S_IFREG | 0644, NULL);
|
||||
}
|
||||
|
||||
static void file_change_deleteall(struct branch *b)
|
||||
|
@ -2141,6 +2257,7 @@ static void file_change_deleteall(struct branch *b)
|
|||
hashclr(b->branch_tree.versions[0].sha1);
|
||||
hashclr(b->branch_tree.versions[1].sha1);
|
||||
load_tree(&b->branch_tree);
|
||||
b->num_notes = 0;
|
||||
}
|
||||
|
||||
static void parse_from_commit(struct branch *b, char *buf, unsigned long size)
|
||||
|
@ -2264,6 +2381,7 @@ static void parse_new_commit(void)
|
|||
char *committer = NULL;
|
||||
struct hash_list *merge_list = NULL;
|
||||
unsigned int merge_count;
|
||||
unsigned char prev_fanout, new_fanout;
|
||||
|
||||
/* Obtain the branch name from the rest of our command */
|
||||
sp = strchr(command_buf.buf, ' ') + 1;
|
||||
|
@ -2294,6 +2412,8 @@ static void parse_new_commit(void)
|
|||
load_branch(b);
|
||||
}
|
||||
|
||||
prev_fanout = convert_num_notes_to_fanout(b->num_notes);
|
||||
|
||||
/* file_change* */
|
||||
while (command_buf.len > 0) {
|
||||
if (!prefixcmp(command_buf.buf, "M "))
|
||||
|
@ -2305,7 +2425,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);
|
||||
note_change_n(b, prev_fanout);
|
||||
else if (!strcmp("deleteall", command_buf.buf))
|
||||
file_change_deleteall(b);
|
||||
else {
|
||||
|
@ -2316,6 +2436,10 @@ static void parse_new_commit(void)
|
|||
break;
|
||||
}
|
||||
|
||||
new_fanout = convert_num_notes_to_fanout(b->num_notes);
|
||||
if (new_fanout != prev_fanout)
|
||||
b->num_notes = change_note_fanout(&b->branch_tree, new_fanout);
|
||||
|
||||
/* build the tree and the commit */
|
||||
store_tree(&b->branch_tree);
|
||||
hashcpy(b->branch_tree.versions[0].sha1,
|
||||
|
|
|
@ -1092,9 +1092,12 @@ test_expect_success 'P: fail on blob mark in gitlink' '
|
|||
### series Q (notes)
|
||||
###
|
||||
|
||||
note1_data="Note for the first commit"
|
||||
note2_data="Note for the second commit"
|
||||
note3_data="Note for the third commit"
|
||||
note1_data="The first note for the first commit"
|
||||
note2_data="The first note for the second commit"
|
||||
note3_data="The first note for the third commit"
|
||||
note1b_data="The second note for the first commit"
|
||||
note1c_data="The third note for the first commit"
|
||||
note2b_data="The second note for the second commit"
|
||||
|
||||
test_tick
|
||||
cat >input <<INPUT_END
|
||||
|
@ -1169,7 +1172,45 @@ data <<EOF
|
|||
$note3_data
|
||||
EOF
|
||||
|
||||
commit refs/notes/foobar
|
||||
mark :10
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
notes (:10)
|
||||
COMMIT
|
||||
|
||||
N inline :3
|
||||
data <<EOF
|
||||
$note1b_data
|
||||
EOF
|
||||
|
||||
commit refs/notes/foobar2
|
||||
mark :11
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
notes (:11)
|
||||
COMMIT
|
||||
|
||||
N inline :3
|
||||
data <<EOF
|
||||
$note1c_data
|
||||
EOF
|
||||
|
||||
commit refs/notes/foobar
|
||||
mark :12
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
notes (:12)
|
||||
COMMIT
|
||||
|
||||
deleteall
|
||||
N inline :5
|
||||
data <<EOF
|
||||
$note2b_data
|
||||
EOF
|
||||
|
||||
INPUT_END
|
||||
|
||||
test_expect_success \
|
||||
'Q: commit notes' \
|
||||
'git fast-import <input &&
|
||||
|
@ -1224,8 +1265,8 @@ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
|||
notes (:9)
|
||||
EOF
|
||||
test_expect_success \
|
||||
'Q: verify notes commit' \
|
||||
'git cat-file commit refs/notes/foobar | sed 1d >actual &&
|
||||
'Q: verify first notes commit' \
|
||||
'git cat-file commit refs/notes/foobar~2 | sed 1d >actual &&
|
||||
test_cmp expect actual'
|
||||
|
||||
cat >expect.unsorted <<EOF
|
||||
|
@ -1235,24 +1276,113 @@ cat >expect.unsorted <<EOF
|
|||
EOF
|
||||
cat expect.unsorted | sort >expect
|
||||
test_expect_success \
|
||||
'Q: verify notes tree' \
|
||||
'git cat-file -p refs/notes/foobar^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
|
||||
'Q: verify first notes tree' \
|
||||
'git cat-file -p refs/notes/foobar~2^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
|
||||
test_cmp expect actual'
|
||||
|
||||
echo "$note1_data" >expect
|
||||
test_expect_success \
|
||||
'Q: verify note for first commit' \
|
||||
'git cat-file blob refs/notes/foobar:$commit1 >actual && test_cmp expect actual'
|
||||
'Q: verify first note for first commit' \
|
||||
'git cat-file blob refs/notes/foobar~2:$commit1 >actual && test_cmp expect actual'
|
||||
|
||||
echo "$note2_data" >expect
|
||||
test_expect_success \
|
||||
'Q: verify note for second commit' \
|
||||
'git cat-file blob refs/notes/foobar:$commit2 >actual && test_cmp expect actual'
|
||||
'Q: verify first note for second commit' \
|
||||
'git cat-file blob refs/notes/foobar~2:$commit2 >actual && test_cmp expect actual'
|
||||
|
||||
echo "$note3_data" >expect
|
||||
test_expect_success \
|
||||
'Q: verify note for third commit' \
|
||||
'git cat-file blob refs/notes/foobar:$commit3 >actual && test_cmp expect actual'
|
||||
'Q: verify first note for third commit' \
|
||||
'git cat-file blob refs/notes/foobar~2:$commit3 >actual && test_cmp expect actual'
|
||||
|
||||
cat >expect <<EOF
|
||||
parent `git rev-parse --verify refs/notes/foobar~2`
|
||||
author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
|
||||
notes (:10)
|
||||
EOF
|
||||
test_expect_success \
|
||||
'Q: verify second notes commit' \
|
||||
'git cat-file commit refs/notes/foobar^ | sed 1d >actual &&
|
||||
test_cmp expect actual'
|
||||
|
||||
cat >expect.unsorted <<EOF
|
||||
100644 blob $commit1
|
||||
100644 blob $commit2
|
||||
100644 blob $commit3
|
||||
EOF
|
||||
cat expect.unsorted | sort >expect
|
||||
test_expect_success \
|
||||
'Q: verify second notes tree' \
|
||||
'git cat-file -p refs/notes/foobar^^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
|
||||
test_cmp expect actual'
|
||||
|
||||
echo "$note1b_data" >expect
|
||||
test_expect_success \
|
||||
'Q: verify second note for first commit' \
|
||||
'git cat-file blob refs/notes/foobar^:$commit1 >actual && test_cmp expect actual'
|
||||
|
||||
echo "$note2_data" >expect
|
||||
test_expect_success \
|
||||
'Q: verify first note for second commit' \
|
||||
'git cat-file blob refs/notes/foobar^:$commit2 >actual && test_cmp expect actual'
|
||||
|
||||
echo "$note3_data" >expect
|
||||
test_expect_success \
|
||||
'Q: verify first note for third commit' \
|
||||
'git cat-file blob refs/notes/foobar^:$commit3 >actual && test_cmp expect actual'
|
||||
|
||||
cat >expect <<EOF
|
||||
author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
|
||||
notes (:11)
|
||||
EOF
|
||||
test_expect_success \
|
||||
'Q: verify third notes commit' \
|
||||
'git cat-file commit refs/notes/foobar2 | sed 1d >actual &&
|
||||
test_cmp expect actual'
|
||||
|
||||
cat >expect.unsorted <<EOF
|
||||
100644 blob $commit1
|
||||
EOF
|
||||
cat expect.unsorted | sort >expect
|
||||
test_expect_success \
|
||||
'Q: verify third notes tree' \
|
||||
'git cat-file -p refs/notes/foobar2^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
|
||||
test_cmp expect actual'
|
||||
|
||||
echo "$note1c_data" >expect
|
||||
test_expect_success \
|
||||
'Q: verify third note for first commit' \
|
||||
'git cat-file blob refs/notes/foobar2:$commit1 >actual && test_cmp expect actual'
|
||||
|
||||
cat >expect <<EOF
|
||||
parent `git rev-parse --verify refs/notes/foobar^`
|
||||
author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
|
||||
notes (:12)
|
||||
EOF
|
||||
test_expect_success \
|
||||
'Q: verify fourth notes commit' \
|
||||
'git cat-file commit refs/notes/foobar | sed 1d >actual &&
|
||||
test_cmp expect actual'
|
||||
|
||||
cat >expect.unsorted <<EOF
|
||||
100644 blob $commit2
|
||||
EOF
|
||||
cat expect.unsorted | sort >expect
|
||||
test_expect_success \
|
||||
'Q: verify fourth notes tree' \
|
||||
'git cat-file -p refs/notes/foobar^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
|
||||
test_cmp expect actual'
|
||||
|
||||
echo "$note2b_data" >expect
|
||||
test_expect_success \
|
||||
'Q: verify second note for second commit' \
|
||||
'git cat-file blob refs/notes/foobar:$commit2 >actual && test_cmp expect actual'
|
||||
|
||||
###
|
||||
### series R (feature and option)
|
||||
|
|
|
@ -0,0 +1,623 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2009 Johan Herland
|
||||
#
|
||||
|
||||
test_description='test git fast-import of notes objects'
|
||||
. ./test-lib.sh
|
||||
|
||||
|
||||
test_tick
|
||||
cat >input <<INPUT_END
|
||||
commit refs/heads/master
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
first commit
|
||||
COMMIT
|
||||
|
||||
M 644 inline foo
|
||||
data <<EOF
|
||||
file foo in first commit
|
||||
EOF
|
||||
|
||||
M 755 inline bar
|
||||
data <<EOF
|
||||
file bar in first commit
|
||||
EOF
|
||||
|
||||
M 644 inline baz/xyzzy
|
||||
data <<EOF
|
||||
file baz/xyzzy in first commit
|
||||
EOF
|
||||
|
||||
commit refs/heads/master
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
second commit
|
||||
COMMIT
|
||||
|
||||
M 644 inline foo
|
||||
data <<EOF
|
||||
file foo in second commit
|
||||
EOF
|
||||
|
||||
M 755 inline baz/xyzzy
|
||||
data <<EOF
|
||||
file baz/xyzzy in second commit
|
||||
EOF
|
||||
|
||||
commit refs/heads/master
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
third commit
|
||||
COMMIT
|
||||
|
||||
M 644 inline foo
|
||||
data <<EOF
|
||||
file foo in third commit
|
||||
EOF
|
||||
|
||||
commit refs/heads/master
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
fourth commit
|
||||
COMMIT
|
||||
|
||||
M 755 inline bar
|
||||
data <<EOF
|
||||
file bar in fourth commit
|
||||
EOF
|
||||
|
||||
INPUT_END
|
||||
|
||||
test_expect_success 'set up master branch' '
|
||||
|
||||
git fast-import <input &&
|
||||
git whatchanged master
|
||||
'
|
||||
|
||||
commit4=$(git rev-parse refs/heads/master)
|
||||
commit3=$(git rev-parse "$commit4^")
|
||||
commit2=$(git rev-parse "$commit4~2")
|
||||
commit1=$(git rev-parse "$commit4~3")
|
||||
|
||||
test_tick
|
||||
cat >input <<INPUT_END
|
||||
commit refs/notes/test
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
first notes commit
|
||||
COMMIT
|
||||
|
||||
M 644 inline $commit1
|
||||
data <<EOF
|
||||
first note for first commit
|
||||
EOF
|
||||
|
||||
M 755 inline $commit2
|
||||
data <<EOF
|
||||
first note for second commit
|
||||
EOF
|
||||
|
||||
INPUT_END
|
||||
|
||||
cat >expect <<EXPECT_END
|
||||
fourth commit
|
||||
third commit
|
||||
second commit
|
||||
first note for second commit
|
||||
first commit
|
||||
first note for first commit
|
||||
EXPECT_END
|
||||
|
||||
test_expect_success 'add notes with simple M command' '
|
||||
|
||||
git fast-import <input &&
|
||||
GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
|
||||
test_cmp expect actual
|
||||
|
||||
'
|
||||
|
||||
test_tick
|
||||
cat >input <<INPUT_END
|
||||
commit refs/notes/test
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
second notes commit
|
||||
COMMIT
|
||||
|
||||
from refs/notes/test^0
|
||||
N inline $commit3
|
||||
data <<EOF
|
||||
first note for third commit
|
||||
EOF
|
||||
|
||||
N inline $commit4
|
||||
data <<EOF
|
||||
first note for fourth commit
|
||||
EOF
|
||||
|
||||
INPUT_END
|
||||
|
||||
cat >expect <<EXPECT_END
|
||||
fourth commit
|
||||
first note for fourth commit
|
||||
third commit
|
||||
first note for third commit
|
||||
second commit
|
||||
first note for second commit
|
||||
first commit
|
||||
first note for first commit
|
||||
EXPECT_END
|
||||
|
||||
test_expect_success 'add notes with simple N command' '
|
||||
|
||||
git fast-import <input &&
|
||||
GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
|
||||
test_cmp expect actual
|
||||
|
||||
'
|
||||
|
||||
test_tick
|
||||
cat >input <<INPUT_END
|
||||
commit refs/notes/test
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
third notes commit
|
||||
COMMIT
|
||||
|
||||
from refs/notes/test^0
|
||||
N inline $commit1
|
||||
data <<EOF
|
||||
second note for first commit
|
||||
EOF
|
||||
|
||||
N inline $commit2
|
||||
data <<EOF
|
||||
second note for second commit
|
||||
EOF
|
||||
|
||||
N inline $commit3
|
||||
data <<EOF
|
||||
second note for third commit
|
||||
EOF
|
||||
|
||||
N inline $commit4
|
||||
data <<EOF
|
||||
second note for fourth commit
|
||||
EOF
|
||||
|
||||
INPUT_END
|
||||
|
||||
cat >expect <<EXPECT_END
|
||||
fourth commit
|
||||
second note for fourth commit
|
||||
third commit
|
||||
second note for third commit
|
||||
second commit
|
||||
second note for second commit
|
||||
first commit
|
||||
second note for first commit
|
||||
EXPECT_END
|
||||
|
||||
test_expect_success 'update existing notes with N command' '
|
||||
|
||||
git fast-import <input &&
|
||||
GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
|
||||
test_cmp expect actual
|
||||
|
||||
'
|
||||
|
||||
test_tick
|
||||
cat >input <<INPUT_END
|
||||
commit refs/notes/test
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
fourth notes commit
|
||||
COMMIT
|
||||
|
||||
from refs/notes/test^0
|
||||
M 644 inline $(echo "$commit3" | sed "s|^..|&/|")
|
||||
data <<EOF
|
||||
prefix of note for third commit
|
||||
EOF
|
||||
|
||||
M 644 inline $(echo "$commit4" | sed "s|^..|&/|")
|
||||
data <<EOF
|
||||
prefix of note for fourth commit
|
||||
EOF
|
||||
|
||||
M 644 inline $(echo "$commit4" | sed "s|^\(..\)\(..\)|\1/\2/|")
|
||||
data <<EOF
|
||||
pre-prefix of note for fourth commit
|
||||
EOF
|
||||
|
||||
N inline $commit1
|
||||
data <<EOF
|
||||
third note for first commit
|
||||
EOF
|
||||
|
||||
N inline $commit2
|
||||
data <<EOF
|
||||
third note for second commit
|
||||
EOF
|
||||
|
||||
N inline $commit3
|
||||
data <<EOF
|
||||
third note for third commit
|
||||
EOF
|
||||
|
||||
N inline $commit4
|
||||
data <<EOF
|
||||
third note for fourth commit
|
||||
EOF
|
||||
|
||||
|
||||
INPUT_END
|
||||
|
||||
cat >expect <<EXPECT_END
|
||||
fourth commit
|
||||
pre-prefix of note for fourth commit
|
||||
prefix of note for fourth commit
|
||||
third note for fourth commit
|
||||
third commit
|
||||
prefix of note for third commit
|
||||
third note for third commit
|
||||
second commit
|
||||
third note for second commit
|
||||
first commit
|
||||
third note for first commit
|
||||
EXPECT_END
|
||||
|
||||
test_expect_success 'add concatentation notes with M command' '
|
||||
|
||||
git fast-import <input &&
|
||||
GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
|
||||
test_cmp expect actual
|
||||
|
||||
'
|
||||
|
||||
test_tick
|
||||
cat >input <<INPUT_END
|
||||
commit refs/notes/test
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
fifth notes commit
|
||||
COMMIT
|
||||
|
||||
from refs/notes/test^0
|
||||
deleteall
|
||||
|
||||
INPUT_END
|
||||
|
||||
cat >expect <<EXPECT_END
|
||||
fourth commit
|
||||
third commit
|
||||
second commit
|
||||
first commit
|
||||
EXPECT_END
|
||||
|
||||
test_expect_success 'verify that deleteall also removes notes' '
|
||||
|
||||
git fast-import <input &&
|
||||
GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
|
||||
test_cmp expect actual
|
||||
|
||||
'
|
||||
|
||||
test_tick
|
||||
cat >input <<INPUT_END
|
||||
commit refs/notes/test
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
sixth notes commit
|
||||
COMMIT
|
||||
|
||||
from refs/notes/test^0
|
||||
M 644 inline $commit1
|
||||
data <<EOF
|
||||
third note for first commit
|
||||
EOF
|
||||
|
||||
M 644 inline $commit3
|
||||
data <<EOF
|
||||
third note for third commit
|
||||
EOF
|
||||
|
||||
N inline $commit1
|
||||
data <<EOF
|
||||
fourth note for first commit
|
||||
EOF
|
||||
|
||||
N inline $commit3
|
||||
data <<EOF
|
||||
fourth note for third commit
|
||||
EOF
|
||||
|
||||
INPUT_END
|
||||
|
||||
cat >expect <<EXPECT_END
|
||||
fourth commit
|
||||
third commit
|
||||
fourth note for third commit
|
||||
second commit
|
||||
first commit
|
||||
fourth note for first commit
|
||||
EXPECT_END
|
||||
|
||||
test_expect_success 'verify that later N commands override earlier M commands' '
|
||||
|
||||
git fast-import <input &&
|
||||
GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
|
||||
test_cmp expect actual
|
||||
|
||||
'
|
||||
|
||||
# Write fast-import commands to create the given number of commits
|
||||
fast_import_commits () {
|
||||
my_ref=$1
|
||||
my_num_commits=$2
|
||||
my_append_to_file=$3
|
||||
my_i=0
|
||||
while test $my_i -lt $my_num_commits
|
||||
do
|
||||
my_i=$(($my_i + 1))
|
||||
test_tick
|
||||
cat >>"$my_append_to_file" <<INPUT_END
|
||||
commit $my_ref
|
||||
mark :$my_i
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
commit #$my_i
|
||||
COMMIT
|
||||
|
||||
M 644 inline file
|
||||
data <<EOF
|
||||
file contents in commit #$my_i
|
||||
EOF
|
||||
|
||||
INPUT_END
|
||||
done
|
||||
}
|
||||
|
||||
# Write fast-import commands to create the given number of notes annotating
|
||||
# the commits created by fast_import_commits()
|
||||
fast_import_notes () {
|
||||
my_notes_ref=$1
|
||||
my_num_commits=$2
|
||||
my_append_to_file=$3
|
||||
my_note_append=$4
|
||||
test_tick
|
||||
cat >>"$my_append_to_file" <<INPUT_END
|
||||
commit $my_notes_ref
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
committing $my_num_commits notes
|
||||
COMMIT
|
||||
|
||||
INPUT_END
|
||||
|
||||
my_i=0
|
||||
while test $my_i -lt $my_num_commits
|
||||
do
|
||||
my_i=$(($my_i + 1))
|
||||
cat >>"$my_append_to_file" <<INPUT_END
|
||||
N inline :$my_i
|
||||
data <<EOF
|
||||
note for commit #$my_i$my_note_append
|
||||
EOF
|
||||
|
||||
INPUT_END
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
rm input expect
|
||||
num_commits=400
|
||||
# Create lots of commits
|
||||
fast_import_commits "refs/heads/many_commits" $num_commits input
|
||||
# Create one note per above commit
|
||||
fast_import_notes "refs/notes/many_notes" $num_commits input
|
||||
# Add a couple of non-notes as well
|
||||
test_tick
|
||||
cat >>input <<INPUT_END
|
||||
commit refs/notes/many_notes
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
committing some non-notes to the notes tree
|
||||
COMMIT
|
||||
|
||||
M 755 inline foobar/non-note.txt
|
||||
data <<EOF
|
||||
This is not a note, but rather a regular file residing in a notes tree
|
||||
EOF
|
||||
|
||||
M 644 inline deadbeef
|
||||
data <<EOF
|
||||
Non-note file
|
||||
EOF
|
||||
|
||||
M 644 inline de/adbeef
|
||||
data <<EOF
|
||||
Another non-note file
|
||||
EOF
|
||||
|
||||
INPUT_END
|
||||
# Finally create the expected output from all these notes and commits
|
||||
i=$num_commits
|
||||
while test $i -gt 0
|
||||
do
|
||||
cat >>expect <<EXPECT_END
|
||||
commit #$i
|
||||
note for commit #$i
|
||||
EXPECT_END
|
||||
i=$(($i - 1))
|
||||
done
|
||||
|
||||
test_expect_success 'add lots of commits and notes' '
|
||||
|
||||
git fast-import <input &&
|
||||
GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
|
||||
grep "^ " > actual &&
|
||||
test_cmp expect actual
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'verify that lots of notes trigger a fanout scheme' '
|
||||
|
||||
# None of the entries in the top-level notes tree should be a full SHA1
|
||||
git ls-tree --name-only refs/notes/many_notes |
|
||||
while read path
|
||||
do
|
||||
if test $(expr length "$path") -ge 40
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
'
|
||||
|
||||
cat >>expect_non-note1 << EOF
|
||||
This is not a note, but rather a regular file residing in a notes tree
|
||||
EOF
|
||||
|
||||
cat >>expect_non-note2 << EOF
|
||||
Non-note file
|
||||
EOF
|
||||
|
||||
cat >>expect_non-note3 << EOF
|
||||
Another non-note file
|
||||
EOF
|
||||
|
||||
test_expect_success 'verify that non-notes are untouched by a fanout change' '
|
||||
|
||||
git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
|
||||
test_cmp expect_non-note1 actual &&
|
||||
git cat-file -p refs/notes/many_notes:deadbeef > actual &&
|
||||
test_cmp expect_non-note2 actual &&
|
||||
git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
|
||||
test_cmp expect_non-note3 actual
|
||||
|
||||
'
|
||||
remaining_notes=10
|
||||
test_tick
|
||||
cat >>input <<INPUT_END
|
||||
commit refs/notes/many_notes
|
||||
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||
data <<COMMIT
|
||||
removing all notes but $remaining_notes
|
||||
COMMIT
|
||||
from refs/notes/many_notes^0
|
||||
INPUT_END
|
||||
|
||||
i=$remaining_notes
|
||||
while test $i -lt $num_commits
|
||||
do
|
||||
i=$(($i + 1))
|
||||
cat >>input <<INPUT_END
|
||||
N 0000000000000000000000000000000000000000 :$i
|
||||
INPUT_END
|
||||
done
|
||||
|
||||
i=$num_commits
|
||||
rm expect
|
||||
while test $i -gt 0
|
||||
do
|
||||
cat >>expect <<EXPECT_END
|
||||
commit #$i
|
||||
EXPECT_END
|
||||
if test $i -le $remaining_notes
|
||||
then
|
||||
cat >>expect <<EXPECT_END
|
||||
note for commit #$i
|
||||
EXPECT_END
|
||||
fi
|
||||
i=$(($i - 1))
|
||||
done
|
||||
|
||||
test_expect_success 'remove lots of notes' '
|
||||
|
||||
git fast-import <input &&
|
||||
GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
|
||||
grep "^ " > actual &&
|
||||
test_cmp expect actual
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'verify that removing notes trigger fanout consolidation' '
|
||||
|
||||
# All entries in the top-level notes tree should be a full SHA1
|
||||
git ls-tree --name-only -r refs/notes/many_notes |
|
||||
while read path
|
||||
do
|
||||
# Explicitly ignore the non-note paths
|
||||
test "$path" = "foobar/non-note.txt" && continue
|
||||
test "$path" = "deadbeef" && continue
|
||||
test "$path" = "de/adbeef" && continue
|
||||
|
||||
if test $(expr length "$path") -ne 40
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'verify that non-notes are untouched by a fanout change' '
|
||||
|
||||
git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
|
||||
test_cmp expect_non-note1 actual &&
|
||||
git cat-file -p refs/notes/many_notes:deadbeef > actual &&
|
||||
test_cmp expect_non-note2 actual &&
|
||||
git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
|
||||
test_cmp expect_non-note3 actual
|
||||
|
||||
'
|
||||
|
||||
|
||||
rm input expect
|
||||
num_notes_refs=10
|
||||
num_commits=16
|
||||
some_commits=8
|
||||
# Create commits
|
||||
fast_import_commits "refs/heads/more_commits" $num_commits input
|
||||
# Create one note per above commit per notes ref
|
||||
i=0
|
||||
while test $i -lt $num_notes_refs
|
||||
do
|
||||
i=$(($i + 1))
|
||||
fast_import_notes "refs/notes/more_notes_$i" $num_commits input
|
||||
done
|
||||
# Trigger branch reloading in git-fast-import by repeating the note creation
|
||||
i=0
|
||||
while test $i -lt $num_notes_refs
|
||||
do
|
||||
i=$(($i + 1))
|
||||
fast_import_notes "refs/notes/more_notes_$i" $some_commits input " (2)"
|
||||
done
|
||||
# Finally create the expected output from the notes in refs/notes/more_notes_1
|
||||
i=$num_commits
|
||||
while test $i -gt 0
|
||||
do
|
||||
note_data="note for commit #$i"
|
||||
if test $i -le $some_commits
|
||||
then
|
||||
note_data="$note_data (2)"
|
||||
fi
|
||||
cat >>expect <<EXPECT_END
|
||||
commit #$i
|
||||
$note_data
|
||||
EXPECT_END
|
||||
i=$(($i - 1))
|
||||
done
|
||||
|
||||
test_expect_success "add notes to $num_commits commits in each of $num_notes_refs refs" '
|
||||
|
||||
git fast-import --active-branches=5 <input &&
|
||||
GIT_NOTES_REF=refs/notes/more_notes_1 git log refs/heads/more_commits |
|
||||
grep "^ " > actual &&
|
||||
test_cmp expect actual
|
||||
|
||||
'
|
||||
|
||||
test_done
|
Загрузка…
Ссылка в новой задаче