1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-25 16:22:42 +01:00

Added support for 'hg export' diff format

Summary: This diff format is used by de-facto mercurial GUI called "TortoiseHG".
It is available as the only way to copy diff into clipboard (right click commit,
select "export", select "copy patch". I added this format support into arcanist
so revisions in Differential can be created from TortoiseHG via simple copy-
paste. Unit test added, manually tested.

See: https://github.com/facebook/arcanist/pull/46

Reviewed by: epriestley
This commit is contained in:
Grigory 2012-07-26 10:06:16 -07:00 committed by epriestley
parent 8d9e1d8479
commit 414e1e3e40
3 changed files with 76 additions and 13 deletions

View file

@ -26,6 +26,7 @@ final class ArcanistDiffParser {
protected $api; protected $api;
protected $text; protected $text;
protected $line; protected $line;
protected $lineSaved;
protected $isGit; protected $isGit;
protected $isMercurial; protected $isMercurial;
protected $detectBinaryFiles = false; protected $detectBinaryFiles = false;
@ -234,22 +235,28 @@ final class ArcanistDiffParser {
'(?P<type>diff -r) (?P<hgrev>[a-f0-9]+) (?:-r [a-f0-9]+ )?(?P<cur>.+)', '(?P<type>diff -r) (?P<hgrev>[a-f0-9]+) (?:-r [a-f0-9]+ )?(?P<cur>.+)',
); );
$ok = false;
$line = $this->getLine(); $line = $this->getLine();
$match = null; $match = null;
foreach ($patterns as $pattern) { $ok = $this->tryMatchHeader($patterns, $line, $match);
$ok = preg_match('@^'.$pattern.'$@', $line, $match);
if ($ok) {
break;
}
}
if (!$ok) { if (!$ok && $this->isFirstNonEmptyLine()) {
$this->didFailParse( // 'hg export' command creates so called "extended diff" that
"Expected a hunk header, like 'Index: /path/to/file.ext' (svn), ". // contains some meta information and comment at the beginning
"'Property changes on: /path/to/file.ext' (svn properties), ". // (isFirstNonEmptyLine() to check for beginning). Actual mercurial
"'commit 59bcc3ad6775562f845953cf01624225' (git show), ". // code detects where comment ends and unified diff starts by
"'diff --git' (git diff), or '--- filename' (unified diff)."); // searching "diff -r" in the text.
$this->saveLine();
$line = $this->nextLineThatLooksLikeDiffStart();
if (!$this->tryMatchHeader($patterns, $line, $match)) {
// Restore line before guessing to display correct error.
$this->restoreLine();
$this->didFailParse(
"Expected a hunk header, like 'Index: /path/to/file.ext' (svn), ".
"'Property changes on: /path/to/file.ext' (svn properties), ".
"'commit 59bcc3ad6775562f845953cf01624225' (git show), ".
"'diff --git' (git diff), '--- filename' (unified diff), or " .
"'diff -r' (hg diff or patch).");
}
} }
if (isset($match['type'])) { if (isset($match['type'])) {
@ -325,6 +332,15 @@ final class ArcanistDiffParser {
return $this->changes; return $this->changes;
} }
protected function tryMatchHeader($patterns, $line, &$match) {
foreach ($patterns as $pattern) {
if (preg_match('@^'.$pattern.'$@', $line, $match)) {
return true;
}
}
return false;
}
protected function parseCommitMessage(ArcanistDiffChange $change) { protected function parseCommitMessage(ArcanistDiffChange $change) {
$change->setType(ArcanistDiffChangeType::TYPE_MESSAGE); $change->setType(ArcanistDiffChangeType::TYPE_MESSAGE);
@ -1026,6 +1042,34 @@ final class ArcanistDiffParser {
return $this->getLine(); return $this->getLine();
} }
protected function nextLineThatLooksLikeDiffStart() {
while (($line = $this->nextLine()) !== null) {
if (preg_match('/^\s*diff\s+-r/', $line)) {
break;
}
}
return $this->getLine();
}
protected function saveLine() {
$this->lineSaved = $this->line;
}
protected function restoreLine() {
$this->line = $this->lineSaved;
}
protected function isFirstNonEmptyLine() {
$count = count($this->text);
for ($i = 0; $i < $count; $i++) {
if (strlen(trim($this->text[$i])) != 0) {
return ($i == $this->line);
}
}
// Entire file is empty.
return false;
}
protected function didFinishParse() { protected function didFinishParse() {
$this->text = null; $this->text = null;
} }

View file

@ -537,6 +537,9 @@ EOTEXT
'Test.java', 'Test.java',
$change->getCurrentPath()); $change->getCurrentPath());
break; break;
case 'hg-patch.hgdiff':
$this->assertEqual(1, count($changes));
break;
default: default:
throw new Exception("No test block for diff file {$diff_file}."); throw new Exception("No test block for diff file {$diff_file}.");
break; break;

View file

@ -0,0 +1,16 @@
# Some meta information
Some
multiline comment
with empty strings.
diff -r b073ee763933 -r 36fbb0c6c48a vim_nix.rb
--- a/vim_nix.rb Wed Jul 04 11:28:53 2012 +0400
+++ b/vim_nix.rb Wed Jul 25 23:14:44 2012 +0400
@@ -11,6 +11,3 @@
`sudo apt-get install vim-gtk`
end
-File.delete( File.expand_path( "~/.vimrc" ) ) rescue
-File.link( "#{DirDropbox()}/cfg/vim/_vimrc", File.expand_path( "~/.vimrc" ) )
-