{"thread":{"id":"24120","subject":"[PATCH 1/2] fast-import: Handle directories changing into symlinks","startedAt":"2010-06-15T16:16:01Z","lastAt":"2010-06-15T16:16:02Z","messageCount":2,"participants":["Elijah Newren"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"143755","messageId":"1276618562-24447-1-git-send-email-newren@gmail.com","threadId":"24120","inReplyTo":null,"subject":"[PATCH 1/2] fast-import: Handle directories changing into symlinks","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2010-06-15T16:16:01Z","receivedAt":"2010-06-15T16:16:01Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"\nSigned-off-by: Elijah Newren <newren@gmail.com>\n---\nI hesitated a bit to put the testcase in t9350-fast-export.sh instead of\nt9300-fast-import.sh.  However, this patch fixes a bug where\n  fast-export <args> | fast-import\naccidentally munges data, and t9300-fast-import.sh has no calls to\nfast-export while t9350-fast-export.sh has calls to both fast-export and\nfast-import.  If I should design a test for t9300-fast-import.sh instead\nof (or in addition to) what I have here, let me know. \n\n fast-import.c          |    5 +++++\n t/t9350-fast-export.sh |   24 ++++++++++++++++++++++++\n 2 files changed, 29 insertions(+), 0 deletions(-)\n\ndiff --git a/fast-import.c b/fast-import.c\nindex 129a786..064348e 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -1528,6 +1528,11 @@ static int tree_content_remove(\n \tfor (i = 0; i < t->entry_count; i++) {\n \t\te = t->entries[i];\n \t\tif (e->name->str_len == n && !strncmp(p, e->name->str_dat, n)) {\n+\t\t\tif (slash1 && S_ISLNK(e->versions[1].mode))\n+\t\t\t\t/* p was already removed by an earlier change\n+\t\t\t\t * of a parent directory to a symlink.\n+\t\t\t\t */\n+\t\t\t\treturn 1;\n \t\t\tif (!slash1 || !S_ISDIR(e->versions[1].mode))\n \t\t\t\tgoto del_entry;\n \t\t\tif (!e->tree)\ndiff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh\nindex d43f37c..1ee1461 100755\n--- a/t/t9350-fast-export.sh\n+++ b/t/t9350-fast-export.sh\n@@ -376,4 +376,28 @@ test_expect_success 'tree_tag-obj'    'git fast-export tree_tag-obj'\n test_expect_success 'tag-obj_tag'     'git fast-export tag-obj_tag'\n test_expect_success 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj'\n \n+test_expect_success 'directory becomes symlink'        '\n+\tgit init dirtosymlink &&\n+\tgit init result &&\n+\t(\n+\t\tcd dirtosymlink &&\n+\t\tmkdir foo &&\n+\t\tmkdir bar &&\n+\t\techo hello > foo/world &&\n+\t\techo hello > bar/world &&\n+\t\tgit add foo/world bar/world &&\n+\t\tgit commit -q -mone &&\n+\t\tgit rm -r foo &&\n+\t\tln -s bar foo &&\n+\t\tgit add foo &&\n+\t\tgit commit -q -mtwo\n+\t) &&\n+\t(\n+\t\tcd dirtosymlink &&\n+\t\tgit fast-export master -- foo |\n+\t\t(cd ../result && git fast-import --quiet)\n+\t) &&\n+\t(cd result && git show master:foo)\n+'\n+\n test_done\n-- \n1.6.6.1\n"},{"id":"143756","messageId":"1276618562-24447-2-git-send-email-newren@gmail.com","threadId":"24120","inReplyTo":"1276618562-24447-1-git-send-email-newren@gmail.com","subject":"[PATCH 2/2] fast-export: Add a --full-tree option","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2010-06-15T16:16:02Z","receivedAt":"2010-06-15T16:16:02Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"This option can be useful when doing incremental exports/imports when\nlater runs of fast-export are passed a larger list of PATHs (for\nlimiting what to export) than prior runs did.\n\nIt's also useful for working around potential bugs in prior incremental\nexports/imports, such as fast-import ignoring symlinks that used to be\ndirectories.\n\nSigned-off-by: Elijah Newren <newren@gmail.com>\n---\n Documentation/git-fast-export.txt |   11 +++++++++++\n builtin/fast-export.c             |    8 +++++++-\n t/t9350-fast-export.sh            |   35 +++++++++++++++++++++++++++++++++++\n 3 files changed, 53 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt\nindex 98ec6b5..5202501 100644\n--- a/Documentation/git-fast-export.txt\n+++ b/Documentation/git-fast-export.txt\n@@ -90,6 +90,17 @@ marks the same across runs.\n \tresulting stream can only be used by a repository which\n \talready contains the necessary objects.\n \n+--full-tree::\n+\tBy default, for each commit that has a parent, only the files\n+\tthat are different between the commit and its parent are\n+\tshown.  By using --full-tree, a \"deleteall\" directive will be\n+\tsent out with each commit followed by a listing of all files\n+\tcontained in the commit.  This can be useful when doing\n+\tincremental exports/imports (making use of --export-marks and\n+\t--import-marks) when later runs of fast-export contain a\n+\tlarger list of PATH limiters in [git-rev-list-args...] than\n+\tprevious runs do.\n+\n [git-rev-list-args...]::\n        A list of arguments, acceptable to 'git rev-parse' and\n        'git rev-list', that specifies the specific objects and references\ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex c6dd71a..d30bed8 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -26,6 +26,7 @@ static int progress;\n static enum { ABORT, VERBATIM, WARN, STRIP } signed_tag_mode = ABORT;\n static enum { ERROR, DROP, REWRITE } tag_of_filtered_mode = ABORT;\n static int fake_missing_tagger;\n+static int full_tree;\n static int no_data;\n \n static int parse_opt_signed_tag_mode(const struct option *opt,\n@@ -241,7 +242,8 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)\n \t\tmessage += 2;\n \n \tif (commit->parents &&\n-\t    get_object_mark(&commit->parents->item->object) != 0) {\n+\t    get_object_mark(&commit->parents->item->object) != 0 &&\n+\t    !full_tree) {\n \t\tparse_commit(commit->parents->item);\n \t\tdiff_tree_sha1(commit->parents->item->tree->object.sha1,\n \t\t\t       commit->tree->object.sha1, \"\", &rev->diffopt);\n@@ -281,6 +283,8 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)\n \t\ti++;\n \t}\n \n+\tif (full_tree)\n+\t\tprintf(\"deleteall\\n\");\n \tlog_tree_diff_flush(rev);\n \trev->diffopt.output_format = saved_output_format;\n \n@@ -584,6 +588,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)\n \t\t\t     \"Import marks from this file\"),\n \t\tOPT_BOOLEAN(0, \"fake-missing-tagger\", &fake_missing_tagger,\n \t\t\t     \"Fake a tagger when tags lack one\"),\n+\t\tOPT_BOOLEAN(0, \"full-tree\", &full_tree,\n+\t\t\t     \"Output full tree for each commit\"),\n \t\t{ OPTION_NEGBIT, 0, \"data\", &no_data, NULL,\n \t\t\t\"Skip output of blob data\",\n \t\t\tPARSE_OPT_NOARG | PARSE_OPT_NEGHELP, NULL, 1 },\ndiff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh\nindex 1ee1461..05c79ea 100755\n--- a/t/t9350-fast-export.sh\n+++ b/t/t9350-fast-export.sh\n@@ -400,4 +400,39 @@ test_expect_success 'directory becomes symlink'        '\n \t(cd result && git show master:foo)\n '\n \n+cat >> dirtosymlink/expected << EOF\n+blob\n+mark :5\n+data 6\n+hello\n+\n+blob\n+mark :6\n+data 7\n+badlink\n+commit refs/heads/master\n+mark :7\n+author A U Thor <author@example.com> 1112912713 -0700\n+committer C O Mitter <committer@example.com> 1112912713 -0700\n+data 6\n+three\n+from :4\n+deleteall\n+M 100644 :5 bar/world\n+M 120000 :6 foo\n+\n+EOF\n+\n+test_expect_success 'full-tree'        '\n+\t(\n+\t\tcd dirtosymlink &&\n+\t\tgit fast-export --export-marks=marks master -- foo > output1 &&\n+\t\trm foo &&\n+\t\tln -s badlink foo &&\n+\t\tgit commit -mthree foo &&\n+\t\tgit fast-export --import-marks=marks --full-tree master -- foo bar > output &&\n+\t\ttest_cmp output expected\n+\t)\n+'\n+\n test_done\n-- \n1.6.6.1\n"}]}