Skip to content

Commit 2794ad5

Browse files
barrbraingitster
authored andcommitted
fast-import: Allow filemodify to set the root
v1.7.3-rc0~75^2 (Teach fast-import to import subtrees named by tree id, 2010-06-30) has a shortcoming - it doesn't allow the root to be set. Extend this behaviour by allowing the root to be referenced as the empty path, "". For a command (like filter-branch --subdirectory-filter) that wants to commit a lot of trees that already exist in the object db, writing undeltified objects as loose files only to repack them later can involve a significant amount of overhead. (23% slow-down observed on Linux 2.6.35, worse on Mac OS X 10.6) Fortunately we have fast-import (which is one of the only git commands that will write to a pack directly) but there is not an advertised way to tell fast-import to commit a given tree without unpacking it. This patch changes that, by allowing M 040000 <tree id> "" as a filemodify line in a commit to reset to a particular tree without any need to parse it. For example, M 040000 4b825dc "" is a synonym for the deleteall command and the fast-import equivalent of git read-tree 4b825dc Signed-off-by: David Barr <[email protected]> Commit-message-by: Jonathan Nieder <[email protected]> Acked-by: Sverre Rabbelier <[email protected]> Tested-by: Ramkumar Ramachandra <[email protected]> Signed-off-by: Ramkumar Ramachandra <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d0af373 commit 2794ad5

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

Documentation/git-fast-import.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,9 @@ start with double quote (`"`).
524524
If an `LF` or double quote must be encoded into `<path>` shell-style
525525
quoting should be used, e.g. `"path/with\n and \" in it"`.
526526

527+
Additionally, in `040000` mode, `<path>` may also be an empty string
528+
(`""`) to specify the root of the tree.
529+
527530
The value of `<path>` must be in canonical form. That is it must not:
528531

529532
* contain an empty directory component (e.g. `foo//bar` is invalid),

fast-import.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,6 +1454,15 @@ static int tree_content_set(
14541454
n = slash1 - p;
14551455
else
14561456
n = strlen(p);
1457+
if (!slash1 && !n) {
1458+
if (!S_ISDIR(mode))
1459+
die("Root cannot be a non-directory");
1460+
hashcpy(root->versions[1].sha1, sha1);
1461+
if (root->tree)
1462+
release_tree_content_recursive(root->tree);
1463+
root->tree = subtree;
1464+
return 1;
1465+
}
14571466
if (!n)
14581467
die("Empty path component found in input");
14591468
if (!slash1 && !S_ISDIR(mode) && subtree)

t/t9300-fast-import.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,27 @@ test_expect_success \
874874
git diff-tree -C --find-copies-harder -r N4^ N4 >actual &&
875875
compare_diff_raw expect actual'
876876

877+
test_expect_success \
878+
'N: copy root directory by tree hash' \
879+
'cat >expect <<-\EOF &&
880+
:100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D file3/newf
881+
:100644 000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 0000000000000000000000000000000000000000 D file3/oldf
882+
EOF
883+
root=$(git rev-parse refs/heads/branch^0^{tree}) &&
884+
cat >input <<-INPUT_END &&
885+
commit refs/heads/N6
886+
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
887+
data <<COMMIT
888+
copy root directory by tree hash
889+
COMMIT
890+
891+
from refs/heads/branch^0
892+
M 040000 $root ""
893+
INPUT_END
894+
git fast-import <input &&
895+
git diff-tree -C --find-copies-harder -r N4 N6 >actual &&
896+
compare_diff_raw expect actual'
897+
877898
test_expect_success \
878899
'N: modify copied tree' \
879900
'cat >expect <<-\EOF &&

0 commit comments

Comments
 (0)