Merge branch 'jn/fast-import-fix'
* jn/fast-import-fix: fast-import: do not clear notes in do_change_note_fanout() t9300 (fast-import): another test for the "replace root" feature fast-import: tighten M 040000 syntax fast-import: filemodify after M 040000 <tree> "" crashesmaint
commit
ed8298dc34
|
@ -1437,6 +1437,20 @@ static void store_tree(struct tree_entry *root)
|
||||||
t->entry_count -= del;
|
t->entry_count -= del;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tree_content_replace(
|
||||||
|
struct tree_entry *root,
|
||||||
|
const unsigned char *sha1,
|
||||||
|
const uint16_t mode,
|
||||||
|
struct tree_content *newtree)
|
||||||
|
{
|
||||||
|
if (!S_ISDIR(mode))
|
||||||
|
die("Root cannot be a non-directory");
|
||||||
|
hashcpy(root->versions[1].sha1, sha1);
|
||||||
|
if (root->tree)
|
||||||
|
release_tree_content_recursive(root->tree);
|
||||||
|
root->tree = newtree;
|
||||||
|
}
|
||||||
|
|
||||||
static int tree_content_set(
|
static int tree_content_set(
|
||||||
struct tree_entry *root,
|
struct tree_entry *root,
|
||||||
const char *p,
|
const char *p,
|
||||||
|
@ -1444,7 +1458,7 @@ static int tree_content_set(
|
||||||
const uint16_t mode,
|
const uint16_t mode,
|
||||||
struct tree_content *subtree)
|
struct tree_content *subtree)
|
||||||
{
|
{
|
||||||
struct tree_content *t = root->tree;
|
struct tree_content *t;
|
||||||
const char *slash1;
|
const char *slash1;
|
||||||
unsigned int i, n;
|
unsigned int i, n;
|
||||||
struct tree_entry *e;
|
struct tree_entry *e;
|
||||||
|
@ -1454,20 +1468,14 @@ static int tree_content_set(
|
||||||
n = slash1 - p;
|
n = slash1 - p;
|
||||||
else
|
else
|
||||||
n = strlen(p);
|
n = strlen(p);
|
||||||
if (!slash1 && !n) {
|
|
||||||
if (!S_ISDIR(mode))
|
|
||||||
die("Root cannot be a non-directory");
|
|
||||||
hashcpy(root->versions[1].sha1, sha1);
|
|
||||||
if (root->tree)
|
|
||||||
release_tree_content_recursive(root->tree);
|
|
||||||
root->tree = subtree;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (!n)
|
if (!n)
|
||||||
die("Empty path component found in input");
|
die("Empty path component found in input");
|
||||||
if (!slash1 && !S_ISDIR(mode) && subtree)
|
if (!slash1 && !S_ISDIR(mode) && subtree)
|
||||||
die("Non-directories cannot have subtrees");
|
die("Non-directories cannot have subtrees");
|
||||||
|
|
||||||
|
if (!root->tree)
|
||||||
|
load_tree(root);
|
||||||
|
t = root->tree;
|
||||||
for (i = 0; i < t->entry_count; i++) {
|
for (i = 0; i < t->entry_count; i++) {
|
||||||
e = t->entries[i];
|
e = t->entries[i];
|
||||||
if (e->name->str_len == n && !strncmp(p, e->name->str_dat, n)) {
|
if (e->name->str_len == n && !strncmp(p, e->name->str_dat, n)) {
|
||||||
|
@ -1523,7 +1531,7 @@ static int tree_content_remove(
|
||||||
const char *p,
|
const char *p,
|
||||||
struct tree_entry *backup_leaf)
|
struct tree_entry *backup_leaf)
|
||||||
{
|
{
|
||||||
struct tree_content *t = root->tree;
|
struct tree_content *t;
|
||||||
const char *slash1;
|
const char *slash1;
|
||||||
unsigned int i, n;
|
unsigned int i, n;
|
||||||
struct tree_entry *e;
|
struct tree_entry *e;
|
||||||
|
@ -1534,6 +1542,9 @@ static int tree_content_remove(
|
||||||
else
|
else
|
||||||
n = strlen(p);
|
n = strlen(p);
|
||||||
|
|
||||||
|
if (!root->tree)
|
||||||
|
load_tree(root);
|
||||||
|
t = root->tree;
|
||||||
for (i = 0; i < t->entry_count; i++) {
|
for (i = 0; i < t->entry_count; i++) {
|
||||||
e = t->entries[i];
|
e = t->entries[i];
|
||||||
if (e->name->str_len == n && !strncmp(p, e->name->str_dat, n)) {
|
if (e->name->str_len == n && !strncmp(p, e->name->str_dat, n)) {
|
||||||
|
@ -1581,7 +1592,7 @@ static int tree_content_get(
|
||||||
const char *p,
|
const char *p,
|
||||||
struct tree_entry *leaf)
|
struct tree_entry *leaf)
|
||||||
{
|
{
|
||||||
struct tree_content *t = root->tree;
|
struct tree_content *t;
|
||||||
const char *slash1;
|
const char *slash1;
|
||||||
unsigned int i, n;
|
unsigned int i, n;
|
||||||
struct tree_entry *e;
|
struct tree_entry *e;
|
||||||
|
@ -1592,6 +1603,9 @@ static int tree_content_get(
|
||||||
else
|
else
|
||||||
n = strlen(p);
|
n = strlen(p);
|
||||||
|
|
||||||
|
if (!root->tree)
|
||||||
|
load_tree(root);
|
||||||
|
t = root->tree;
|
||||||
for (i = 0; i < t->entry_count; i++) {
|
for (i = 0; i < t->entry_count; i++) {
|
||||||
e = t->entries[i];
|
e = t->entries[i];
|
||||||
if (e->name->str_len == n && !strncmp(p, e->name->str_dat, n)) {
|
if (e->name->str_len == n && !strncmp(p, e->name->str_dat, n)) {
|
||||||
|
@ -2218,6 +2232,10 @@ static void file_change_m(struct branch *b)
|
||||||
command_buf.buf);
|
command_buf.buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!*p) {
|
||||||
|
tree_content_replace(&b->branch_tree, sha1, mode, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
tree_content_set(&b->branch_tree, p, sha1, mode, NULL);
|
tree_content_set(&b->branch_tree, p, sha1, mode, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2276,6 +2294,13 @@ static void file_change_cr(struct branch *b, int rename)
|
||||||
tree_content_get(&b->branch_tree, s, &leaf);
|
tree_content_get(&b->branch_tree, s, &leaf);
|
||||||
if (!leaf.versions[1].mode)
|
if (!leaf.versions[1].mode)
|
||||||
die("Path %s not in branch", s);
|
die("Path %s not in branch", s);
|
||||||
|
if (!*d) { /* C "path/to/subdir" "" */
|
||||||
|
tree_content_replace(&b->branch_tree,
|
||||||
|
leaf.versions[1].sha1,
|
||||||
|
leaf.versions[1].mode,
|
||||||
|
leaf.tree);
|
||||||
|
return;
|
||||||
|
}
|
||||||
tree_content_set(&b->branch_tree, d,
|
tree_content_set(&b->branch_tree, d,
|
||||||
leaf.versions[1].sha1,
|
leaf.versions[1].sha1,
|
||||||
leaf.versions[1].mode,
|
leaf.versions[1].mode,
|
||||||
|
|
|
@ -928,6 +928,114 @@ test_expect_success \
|
||||||
git diff-tree -C --find-copies-harder -r N5^^ N5 >actual &&
|
git diff-tree -C --find-copies-harder -r N5^^ N5 >actual &&
|
||||||
compare_diff_raw expect actual'
|
compare_diff_raw expect actual'
|
||||||
|
|
||||||
|
test_expect_success \
|
||||||
|
'N: reject foo/ syntax' \
|
||||||
|
'subdir=$(git rev-parse refs/heads/branch^0:file2) &&
|
||||||
|
test_must_fail git fast-import <<-INPUT_END
|
||||||
|
commit refs/heads/N5B
|
||||||
|
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||||
|
data <<COMMIT
|
||||||
|
copy with invalid syntax
|
||||||
|
COMMIT
|
||||||
|
|
||||||
|
from refs/heads/branch^0
|
||||||
|
M 040000 $subdir file3/
|
||||||
|
INPUT_END'
|
||||||
|
|
||||||
|
test_expect_success \
|
||||||
|
'N: copy to root by id and modify' \
|
||||||
|
'echo "hello, world" >expect.foo &&
|
||||||
|
echo hello >expect.bar &&
|
||||||
|
git fast-import <<-SETUP_END &&
|
||||||
|
commit refs/heads/N7
|
||||||
|
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||||
|
data <<COMMIT
|
||||||
|
hello, tree
|
||||||
|
COMMIT
|
||||||
|
|
||||||
|
deleteall
|
||||||
|
M 644 inline foo/bar
|
||||||
|
data <<EOF
|
||||||
|
hello
|
||||||
|
EOF
|
||||||
|
SETUP_END
|
||||||
|
|
||||||
|
tree=$(git rev-parse --verify N7:) &&
|
||||||
|
git fast-import <<-INPUT_END &&
|
||||||
|
commit refs/heads/N8
|
||||||
|
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||||
|
data <<COMMIT
|
||||||
|
copy to root by id and modify
|
||||||
|
COMMIT
|
||||||
|
|
||||||
|
M 040000 $tree ""
|
||||||
|
M 644 inline foo/foo
|
||||||
|
data <<EOF
|
||||||
|
hello, world
|
||||||
|
EOF
|
||||||
|
INPUT_END
|
||||||
|
git show N8:foo/foo >actual.foo &&
|
||||||
|
git show N8:foo/bar >actual.bar &&
|
||||||
|
test_cmp expect.foo actual.foo &&
|
||||||
|
test_cmp expect.bar actual.bar'
|
||||||
|
|
||||||
|
test_expect_success \
|
||||||
|
'N: extract subtree' \
|
||||||
|
'branch=$(git rev-parse --verify refs/heads/branch^{tree}) &&
|
||||||
|
cat >input <<-INPUT_END &&
|
||||||
|
commit refs/heads/N9
|
||||||
|
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||||
|
data <<COMMIT
|
||||||
|
extract subtree branch:newdir
|
||||||
|
COMMIT
|
||||||
|
|
||||||
|
M 040000 $branch ""
|
||||||
|
C "newdir" ""
|
||||||
|
INPUT_END
|
||||||
|
git fast-import <input &&
|
||||||
|
git diff --exit-code branch:newdir N9'
|
||||||
|
|
||||||
|
test_expect_success \
|
||||||
|
'N: modify subtree, extract it, and modify again' \
|
||||||
|
'echo hello >expect.baz &&
|
||||||
|
echo hello, world >expect.qux &&
|
||||||
|
git fast-import <<-SETUP_END &&
|
||||||
|
commit refs/heads/N10
|
||||||
|
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||||
|
data <<COMMIT
|
||||||
|
hello, tree
|
||||||
|
COMMIT
|
||||||
|
|
||||||
|
deleteall
|
||||||
|
M 644 inline foo/bar/baz
|
||||||
|
data <<EOF
|
||||||
|
hello
|
||||||
|
EOF
|
||||||
|
SETUP_END
|
||||||
|
|
||||||
|
tree=$(git rev-parse --verify N10:) &&
|
||||||
|
git fast-import <<-INPUT_END &&
|
||||||
|
commit refs/heads/N11
|
||||||
|
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||||
|
data <<COMMIT
|
||||||
|
copy to root by id and modify
|
||||||
|
COMMIT
|
||||||
|
|
||||||
|
M 040000 $tree ""
|
||||||
|
M 100644 inline foo/bar/qux
|
||||||
|
data <<EOF
|
||||||
|
hello, world
|
||||||
|
EOF
|
||||||
|
R "foo" ""
|
||||||
|
C "bar/qux" "bar/quux"
|
||||||
|
INPUT_END
|
||||||
|
git show N11:bar/baz >actual.baz &&
|
||||||
|
git show N11:bar/qux >actual.qux &&
|
||||||
|
git show N11:bar/quux >actual.quux &&
|
||||||
|
test_cmp expect.baz actual.baz &&
|
||||||
|
test_cmp expect.qux actual.qux &&
|
||||||
|
test_cmp expect.qux actual.quux'
|
||||||
|
|
||||||
###
|
###
|
||||||
### series O
|
### series O
|
||||||
###
|
###
|
||||||
|
|
Loading…
Reference in New Issue