fast-import: allow ls or filecopy of the root tree
Commit 178e1de (fast-import: don't allow 'ls' of path with empty components, 2012-03-09) restricted paths which: . contain an empty directory component (e.g. foo//bar is invalid), . end with a directory separator (e.g. foo/ is invalid), . start with a directory separator (e.g. /foo is invalid). However, the implementation also caught the empty path, which should represent the root tree. Relax this restriction so that the empty path is explicitly allowed and refers to the root tree. Reported-by: Dave Abrahams <dave@boostpro.com> Signed-off-by: John Keeping <john@keeping.me.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
John Keeping committed
Jun 23, 2013 at 15:58 UTC
e0eb6b9720db743993d9374e366cb6b7664f0a6d
2 files changed
+24
-15
fast-import.c
+22
-13
@@ -1629,7 +1629,8 @@ del_entry:
1629
static int tree_content_get(
1630
struct tree_entry *root,
1631
const char *p,
1632
- struct tree_entry *leaf)
1632
+ struct tree_entry *leaf,
1633
+ int allow_root)
1634
{
1635
struct tree_content *t;
1636
const char *slash1;
@@ -1641,31 +1642,39 @@ static int tree_content_get(
1642
n = slash1 - p;
1643
else
1644
n = strlen(p);
1644
- if (!n)
1645
+ if (!n && !allow_root)
1646
die("Empty path component found in input");
1647
1648
if (!root->tree)
1649
load_tree(root);
1650
+
1651
+ if (!n) {
1652
+ e = root;
1653
+ goto found_entry;
1654
+ }
1655
+
1656
t = root->tree;
1657
for (i = 0; i < t->entry_count; i++) {
1658
e = t->entries[i];
1659
if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
1653
- if (!slash1) {
1654
- memcpy(leaf, e, sizeof(*leaf));
1655
- if (e->tree && is_null_sha1(e->versions[1].sha1))
1656
- leaf->tree = dup_tree_content(e->tree);
1657
- else
1658
- leaf->tree = NULL;
1659
- return 1;
1660
- }
1660
+ if (!slash1)
1661
+ goto found_entry;
1662
if (!S_ISDIR(e->versions[1].mode))
1663
return 0;
1664
if (!e->tree)
1665
load_tree(e);
1665
- return tree_content_get(e, slash1 + 1, leaf);
1666
+ return tree_content_get(e, slash1 + 1, leaf, 0);
1667
}
1668
}
1669
return 0;
1670
+
1671
+found_entry:
1672
+ memcpy(leaf, e, sizeof(*leaf));
1673
+ if (e->tree && is_null_sha1(e->versions[1].sha1))
1674
+ leaf->tree = dup_tree_content(e->tree);
1675
+ else
1676
+ leaf->tree = NULL;
1677
+ return 1;
1678
}
1679
1680
static int update_branch(struct branch *b)
@@ -2415,7 +2424,7 @@ static void file_change_cr(struct branch *b, int rename)
2424
if (rename)
2425
tree_content_remove(&b->branch_tree, s, &leaf);
2426
else
2418
- tree_content_get(&b->branch_tree, s, &leaf);
2427
+ tree_content_get(&b->branch_tree, s, &leaf, 1);
2428
if (!leaf.versions[1].mode)
2429
die("Path %s not in branch", s);
2430
if (!*d) { /* C "path/to/subdir" "" */
@@ -3067,7 +3076,7 @@ static void parse_ls(struct branch *b)
3076
die("Garbage after path in: %s", command_buf.buf);
3077
p = uq.buf;
3078
}
3070
- tree_content_get(root, p, &leaf);
3079
+ tree_content_get(root, p, &leaf, 1);
3080
/*
3081
* A directory in preparation would have a sha1 of zero
3082
* until it is saved. Save, for simplicity.
t/t9300-fast-import.sh
+2
-2
@@ -1253,7 +1253,7 @@ test_expect_success \
1253
git diff-tree -C --find-copies-harder -r N4 N6 >actual &&
1254
compare_diff_raw expect actual'
1255
1256
-test_expect_failure \
1256
+test_expect_success \
1257
'N: copy root by path' \
1258
'cat >expect <<-\EOF &&
1259
:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100 file2/newf oldroot/file2/newf
@@ -2988,7 +2988,7 @@ test_expect_success 'S: ls with garbage after sha1 must fail' '
2988
###
2989
# Setup is carried over from series S.
2990
2991
-test_expect_failure 'T: ls root tree' '
2991
+test_expect_success 'T: ls root tree' '
2992
sed -e "s/Z\$//" >expect <<-EOF &&
2993
040000 tree $(git rev-parse S^{tree}) Z
2994
EOF