From: Alexander Gavrilov Date: Sat, 26 Jul 2008 20:52:54 +0000 (+0400) Subject: Support copy and rename detection in fast-export. X-Git-Tag: v1.6.0-rc2~54 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=ae7c5dcef92d46cfc8987fde2c264614fe475bd1;p=git.git Support copy and rename detection in fast-export. Although it does not matter for Git itself, tools that export to systems that explicitly track copies and renames can benefit from such information. This patch makes fast-export output correct action logs when -M or -C are enabled. Signed-off-by: Alexander Gavrilov Signed-off-by: Junio C Hamano --- diff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt index 4956964d8..b974e2115 100644 --- a/Documentation/git-fast-export.txt +++ b/Documentation/git-fast-export.txt @@ -36,6 +36,15 @@ when encountering a signed tag. With 'strip', the tags will be made unsigned, with 'verbatim', they will be silently exported and with 'warn', they will be exported, but you will see a warning. +-M:: +-C:: + Perform move and/or copy detection, as described in the + linkgit:git-diff[1] manual page, and use it to generate + rename and copy commands in the output dump. ++ +Note that earlier versions of this command did not complain and +produced incorrect results if you gave these options. + --export-marks=:: Dumps the internal marks table to when complete. Marks are written one per line as `:markid SHA-1`. Only marks diff --git a/builtin-fast-export.c b/builtin-fast-export.c index e508ced6b..070971616 100644 --- a/builtin-fast-export.c +++ b/builtin-fast-export.c @@ -132,10 +132,27 @@ static void show_filemodify(struct diff_queue_struct *q, { int i; for (i = 0; i < q->nr; i++) { + struct diff_filespec *ospec = q->queue[i]->one; struct diff_filespec *spec = q->queue[i]->two; - if (is_null_sha1(spec->sha1)) + + switch (q->queue[i]->status) { + case DIFF_STATUS_DELETED: printf("D %s\n", spec->path); - else { + break; + + case DIFF_STATUS_COPIED: + case DIFF_STATUS_RENAMED: + printf("%c \"%s\" \"%s\"\n", q->queue[i]->status, + ospec->path, spec->path); + + if (!hashcmp(ospec->sha1, spec->sha1) && + ospec->mode == spec->mode) + break; + /* fallthrough */ + + case DIFF_STATUS_TYPE_CHANGED: + case DIFF_STATUS_MODIFIED: + case DIFF_STATUS_ADDED: /* * Links refer to objects in another repositories; * output the SHA-1 verbatim. @@ -148,6 +165,13 @@ static void show_filemodify(struct diff_queue_struct *q, printf("M %06o :%d %s\n", spec->mode, get_object_mark(object), spec->path); } + break; + + default: + die("Unexpected comparison status '%c' for %s, %s", + q->queue[i]->status, + ospec->path ? ospec->path : "none", + spec->path ? spec->path : "none"); } } } diff --git a/t/t9301-fast-export.sh b/t/t9301-fast-export.sh index 8324f6e3b..c19b4a2ba 100755 --- a/t/t9301-fast-export.sh +++ b/t/t9301-fast-export.sh @@ -185,4 +185,50 @@ test_expect_success 'submodule fast-export | fast-import' ' ' +export GIT_AUTHOR_NAME='A U Thor' +export GIT_COMMITTER_NAME='C O Mitter' + +test_expect_success 'setup copies' ' + + git config --unset i18n.commitencoding && + git checkout -b copy rein && + git mv file file3 && + git commit -m move1 && + test_tick && + cp file2 file4 && + git add file4 && + git mv file2 file5 && + git commit -m copy1 && + test_tick && + cp file3 file6 && + git add file6 && + git commit -m copy2 && + test_tick && + echo more text >> file6 && + echo even more text >> file6 && + git add file6 && + git commit -m modify && + test_tick && + cp file6 file7 && + echo test >> file7 && + git add file7 && + git commit -m copy_modify + +' + +test_expect_success 'fast-export -C -C | fast-import' ' + + ENTRY=$(git rev-parse --verify copy) && + rm -rf new && + mkdir new && + git --git-dir=new/.git init && + git fast-export -C -C --signed-tags=strip --all > output && + grep "^C \"file6\" \"file7\"\$" output && + cat output | + (cd new && + git fast-import && + test $ENTRY = $(git rev-parse --verify refs/heads/copy)) + +' + test_done