[PATCH 2/3] fast-import: treat filemodify with empty tree as delete
From: Jonathan Nieder <hidden>
Date: 2016-06-15 22:50:19
Subsystem:
the rest · Maintainer:
Linus Torvalds
Date: Sat, 11 Dec 2010 16:42:28 -0600
Traditionally, git trees do not contain entries for empty
subdirectories. Generally speaking, subtrees are not created or
destroyed explicitly; instead, they automatically appear when needed
to hold regular files, symlinks, and submodules.
v1.7.3-rc0~75^2 (Teach fast-import to import subtrees named by tree
id, 2010-06-30) changed that, by allowing an empty subtree to be
included in a fast-import stream explicitly:
M 040000 4b825dc642cb6eb9a060e54bf8d69288fbee4904 subdir
That was unintentional. Better and more closely analogous to "git
read-tree --prefix" to treat such an input line as a request to delete
("to empty") subdir.
Noticed-by: David Barr [off-list ref]
Signed-off-by: Jonathan Nieder <redacted>
---
If this seems like a good idea it might be a candidate for v1.7.4.x.
Perhaps fsck.c should learn a "no empty trees" rule, too.
fast-import.c | 10 ++++++++
t/t9300-fast-import.sh | 58 +++++++++++++++++++++++++++++++++++++++++------
2 files changed, 60 insertions(+), 8 deletions(-)
diff --git a/fast-import.c b/fast-import.c
index a5cea45..385d12d 100644
--- a/fast-import.c
+++ b/fast-import.c@@ -2231,6 +2231,16 @@ static void file_change_m(struct branch *b) p = uq.buf; } + /* + * Git does not track empty, non-toplevel directories. + */ + if (S_ISDIR(mode) && + !memcmp(sha1, (const unsigned char *) EMPTY_TREE_SHA1_BIN, 20) && + *p) { + tree_content_remove(&b->branch_tree, p, NULL); + return; + } + if (S_ISGITLINK(mode)) { if (inline_data) die("Git links cannot be specified 'inline': %s",
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 53aad51..b9aa3f0 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh@@ -42,6 +42,14 @@ echo "$@"' >empty +test_expect_success 'setup: have pipes?' ' + rm -f frob && + if mkfifo frob + then + test_set_prereq PIPE + fi +' + ### ### series A ###
@@ -899,6 +907,48 @@ test_expect_success \ compare_diff_raw expect actual' test_expect_success \ + 'N: delete directory by copying' \ + 'cat >expect <<-\EOF && + OBJID + :100644 000000 OBJID OBJID D foo/bar/qux + OBJID + :000000 100644 OBJID OBJID A foo/bar/baz + :000000 100644 OBJID OBJID A foo/bar/qux + EOF + empty_tree=$(git mktree </dev/null) && + cat >input <<-INPUT_END && + commit refs/heads/N-delete + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + collect data to be deleted + COMMIT + + deleteall + M 100644 inline foo/bar/baz + data <<DATA_END + hello + DATA_END + C "foo/bar/baz" "foo/bar/qux" + C "foo/bar/baz" "foo/bar/quux/1" + C "foo/bar/baz" "foo/bar/quuux" + M 040000 $empty_tree foo/bar/quux + M 040000 $empty_tree foo/bar/quuux + + commit refs/heads/N-delete + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <<COMMIT + delete subdirectory + COMMIT + + M 040000 $empty_tree foo/bar/qux + INPUT_END + git fast-import <input && + git rev-list N-delete | + git diff-tree -r --stdin --root --always | + sed -e "s/$_x40/OBJID/g" >actual && + test_cmp expect actual' + +test_expect_success \ 'N: copy root directory by tree hash' \ 'cat >expect <<-\EOF && :100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D file3/newf
@@ -1898,14 +1948,6 @@ test_expect_success 'R: print two blobs to stdout' ' test_cmp expect actual ' -test_expect_success 'setup: have pipes?' ' - rm -f frob && - if mkfifo frob - then - test_set_prereq PIPE - fi -' - test_expect_success PIPE 'R: copy using cat-file' ' expect_id=$(git hash-object big) && expect_len=$(wc -c <big) &&
--
1.7.4.rc0.580.g89dc.dirty