fast-export: avoid stripping encoding header if we cannot reencode
authorElijah Newren <newren@gmail.com>
Tue, 14 May 2019 04:31:00 +0000 (21:31 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 14 May 2019 07:48:56 +0000 (16:48 +0900)
When fast-export encounters a commit with an 'encoding' header, it tries
to reencode in UTF-8 and then drops the encoding header. However, if it
fails to reencode in UTF-8 because e.g. one of the characters in the
commit message was invalid in the old encoding, then we need to retain
the original encoding or otherwise we lose information needed to
understand all the other (valid) characters in the original commit
message.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/fast-export.c
t/t9350-fast-export.sh
t/t9350/broken-iso-8859-7-commit-message.txt [new file with mode: 0644]
index 9e283482efcfa6de0376cc9306061cea149b12df..7734a9f5a5df4f7ca497534883bf85e3c827b4f5 100644 (file)
@@ -642,9 +642,12 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
        printf("commit %s\nmark :%"PRIu32"\n", refname, last_idnum);
        if (show_original_ids)
                printf("original-oid %s\n", oid_to_hex(&commit->object.oid));
-       printf("%.*s\n%.*s\ndata %u\n%s",
+       printf("%.*s\n%.*s\n",
               (int)(author_end - author), author,
-              (int)(committer_end - committer), committer,
+              (int)(committer_end - committer), committer);
+       if (!reencoded && encoding)
+               printf("encoding %s\n", encoding);
+       printf("data %u\n%s",
               (unsigned)(reencoded
                          ? strlen(reencoded) : message
                          ? strlen(message) : 0),
index 756d6a9905e6bb38e7dbf0d5a39a5d63849816e6..e2ab8eddc06509a25a25062760ca9ff8cb0000c5 100755 (executable)
@@ -118,6 +118,27 @@ test_expect_success 'iso-8859-7' '
                 ! grep ^encoding actual)
 '
 
+test_expect_success 'encoding preserved if reencoding fails' '
+
+       test_when_finished "git reset --hard HEAD~1" &&
+       test_config i18n.commitencoding iso-8859-7 &&
+       echo rosten >file &&
+       git commit -s -F "$TEST_DIRECTORY/t9350/broken-iso-8859-7-commit-message.txt" file &&
+       git fast-export wer^..wer >iso-8859-7.fi &&
+       sed "s/wer/i18n-invalid/" iso-8859-7.fi |
+               (cd new &&
+                git fast-import &&
+                git cat-file commit i18n-invalid >actual &&
+                # Make sure the commit still has the encoding header
+                grep ^encoding actual &&
+                # Verify that the commit has the expected size; i.e.
+                # that no bytes were re-encoded to a different encoding.
+                test 252 -eq "$(git cat-file -s i18n-invalid)" &&
+                # ...and check for the original special bytes
+                grep $(printf "\360") actual &&
+                grep $(printf "\377") actual)
+'
+
 test_expect_success 'import/export-marks' '
 
        git checkout -b marks master &&
diff --git a/t/t9350/broken-iso-8859-7-commit-message.txt b/t/t9350/broken-iso-8859-7-commit-message.txt
new file mode 100644 (file)
index 0000000..d06ad75
--- /dev/null
@@ -0,0 +1 @@
+Pi: ð; Invalid: ÿ
\ No newline at end of file