mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-12-23 05:50:54 +01:00
Add trailing tabs when generating synthetic Git diffs for files with spaces
Summary: Fixes T8768. See PHI294. See that task for more details. Git, Mercurial, `diff`, and `patch` have conspired to make things weird. To correctly handle files with spaces in the way everything else does and expects, we need to emit semantic trailing whitespace literals. Test Plan: - Created a file with spaces in it in a Mercurial repositroy, committed it, diffed it into a revision. - Used `arc patch` to apply the change to a clean copy of the repository. - Before patch: Mercurial incorrectly creates a file named `X`, not a file named `X Y.txt`. - After patch: `arc patch` commit is identical to genuine commit. - Also added test coverage. The other general behaviors here are fairly well covered already. Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T8768 Differential Revision: https://secure.phabricator.com/D18869
This commit is contained in:
parent
3d06bd4c56
commit
2e02332216
2 changed files with 52 additions and 0 deletions
|
@ -424,6 +424,9 @@ final class ArcanistBundle extends Phobject {
|
|||
$cur_target = 'b/'.$cur_path;
|
||||
}
|
||||
|
||||
$old_target = $this->encodeGitTargetPath($old_target);
|
||||
$cur_target = $this->encodeGitTargetPath($cur_target);
|
||||
|
||||
$result[] = "diff --git {$old_index} {$cur_index}".$eol;
|
||||
|
||||
if ($type == ArcanistDiffChangeType::TYPE_ADD) {
|
||||
|
@ -591,6 +594,24 @@ final class ArcanistBundle extends Phobject {
|
|||
return $results;
|
||||
}
|
||||
|
||||
private function encodeGitTargetPath($path) {
|
||||
// See T8768. If a target path contains spaces, it must be terminated with
|
||||
// a tab. If we don't do this, Mercurial has the wrong behavior when
|
||||
// applying the patch. This results in a semantic trailing whitespace
|
||||
// character:
|
||||
//
|
||||
// +++ b/X Y.txt\t
|
||||
//
|
||||
// Everyone is at fault here and there are no winners.
|
||||
|
||||
if (strpos($path, ' ') !== false) {
|
||||
$path = $path."\t";
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
|
||||
private function getOldPath(ArcanistDiffChange $change) {
|
||||
$old_path = $change->getOldPath();
|
||||
$type = $change->getType();
|
||||
|
|
|
@ -33,6 +33,37 @@ final class ArcanistBundleTestCase extends PhutilTestCase {
|
|||
return ArcanistBundle::newFromDiff($diff);
|
||||
}
|
||||
|
||||
public function testTabEncoding() {
|
||||
// See T8768. Test that we add semantic trailing tab literals to diffs
|
||||
// touching files with spaces in them. This is a pain to encode using the
|
||||
// support toolset here so just do it manually.
|
||||
|
||||
// Note that the "b/X Y.txt" line has a trailing tab literal.
|
||||
|
||||
$diff = <<<EODIFF
|
||||
diff --git a/X Y.txt b/X Y.txt
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/X Y.txt\t
|
||||
@@ -0,0 +1 @@
|
||||
+quack
|
||||
|
||||
|
||||
EODIFF;
|
||||
|
||||
$bundle = ArcanistBundle::newFromDiff($diff);
|
||||
|
||||
$changes = $bundle->getChanges();
|
||||
$this->assertEqual(1, count($changes));
|
||||
|
||||
// The path should parse as "X Y.txt" despite the trailing tab.
|
||||
$change = head($changes);
|
||||
$this->assertEqual('X Y.txt', $change->getCurrentPath());
|
||||
|
||||
// The tab should be restored when the diff is output again.
|
||||
$this->assertEqual($diff, $bundle->toGitPatch());
|
||||
}
|
||||
|
||||
/**
|
||||
* Unarchive a saved git repository and apply each commit as though via
|
||||
* "arc patch", verifying that the resulting tree hash is identical to the
|
||||
|
|
Loading…
Reference in a new issue