mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-12-22 21:40:54 +01:00
Support git-format-patch
format in diff parser
Summary: Fixes T4063. The `git format-patch` command produces a special header and footer which we need to detect, strip, and parse. Test Plan: - Added and ran unit tests. - Submitted a diff with `git format-patch HEAD^ --stdout | arc diff --raw`. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T4063 Differential Revision: https://secure.phabricator.com/D8547
This commit is contained in:
parent
1e6d958b27
commit
46fe94db9f
4 changed files with 98 additions and 0 deletions
|
@ -193,6 +193,22 @@ final class ArcanistDiffParser {
|
|||
throw new Exception("Can't parse an empty diff!");
|
||||
}
|
||||
|
||||
// Detect `git-format-patch`, by looking for a "---" line somewhere in
|
||||
// the file and then a footer with Git version number, which looks like
|
||||
// this:
|
||||
//
|
||||
// --
|
||||
// 1.8.4.2
|
||||
//
|
||||
// Note that `git-format-patch` adds a space after the "--", but we don't
|
||||
// require it when detecting patches, as trailing whitespace can easily be
|
||||
// lost in transit.
|
||||
$detect_patch = '/^---$.*^-- ?[\s\d.]+\z/ms';
|
||||
$message = null;
|
||||
if (preg_match($detect_patch, $diff)) {
|
||||
list($message, $diff) = $this->stripGitFormatPatch($diff);
|
||||
}
|
||||
|
||||
$this->didStartParse($diff);
|
||||
|
||||
// Strip off header comments. While `patch` allows comments anywhere in the
|
||||
|
@ -203,6 +219,14 @@ final class ArcanistDiffParser {
|
|||
$line = $this->nextLine();
|
||||
}
|
||||
|
||||
if (strlen($message)) {
|
||||
// If we found a message during pre-parse steps, add it to the resulting
|
||||
// changes here.
|
||||
$change = $this->buildChange(null)
|
||||
->setType(ArcanistDiffChangeType::TYPE_MESSAGE)
|
||||
->setMetadata('message', $message);
|
||||
}
|
||||
|
||||
do {
|
||||
$patterns = array(
|
||||
// This is a normal SVN text change, probably from "svn diff".
|
||||
|
@ -1346,4 +1370,42 @@ final class ArcanistDiffParser {
|
|||
return array($old, $new);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Strip the header and footer off a `git-format-patch` diff.
|
||||
*
|
||||
* Returns a parseable normal diff and a textual commit message.
|
||||
*/
|
||||
private function stripGitFormatPatch($diff) {
|
||||
|
||||
// We can parse this by splitting it into two pieces over and over again
|
||||
// along different section dividers:
|
||||
//
|
||||
// 1. Mail headers.
|
||||
// 2. ("\n\n")
|
||||
// 3. Mail body.
|
||||
// 4. ("---")
|
||||
// 5. Diff stat section.
|
||||
// 6. ("\n\n")
|
||||
// 7. Actual diff body.
|
||||
// 8. ("--")
|
||||
// 9. Patch footer.
|
||||
|
||||
list($head, $tail) = preg_split("/^---$/m", $diff, 2);
|
||||
list($mail_headers, $mail_body) = explode("\n\n", $head, 2);
|
||||
list($body, $foot) = preg_split('/^-- ?$/m', $tail, 2);
|
||||
list($stat, $diff) = explode("\n\n", $body, 2);
|
||||
|
||||
// Rebuild the commit message by putting the subject line back on top of it,
|
||||
// if we can find one.
|
||||
$matches = null;
|
||||
$pattern = '/^Subject: (?:\[PATCH\] )?(.*)$/mi';
|
||||
if (preg_match($pattern, $mail_headers, $matches)) {
|
||||
$mail_body = $matches[1]."\n\n".$mail_body;
|
||||
$mail_body = rtrim($mail_body);
|
||||
}
|
||||
|
||||
return array($mail_body, $diff);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -575,6 +575,20 @@ EOTEXT
|
|||
case 'svnlook-delete.svndiff':
|
||||
$this->assertEqual(1, count($changes));
|
||||
break;
|
||||
case 'git-format-patch.gitdiff':
|
||||
$this->assertEqual(2, count($changes));
|
||||
|
||||
$change = array_shift($changes);
|
||||
$this->assertEqual(
|
||||
ArcanistDiffChangeType::TYPE_MESSAGE,
|
||||
$change->getType());
|
||||
$this->assertEqual("WIP", $change->getMetadata('message'));
|
||||
|
||||
$change = array_shift($changes);
|
||||
$this->assertEqual(
|
||||
ArcanistDiffChangeType::TYPE_CHANGE,
|
||||
$change->getType());
|
||||
break;
|
||||
default:
|
||||
throw new Exception("No test block for diff file {$diff_file}.");
|
||||
break;
|
||||
|
|
21
src/parser/__tests__/diff/git-format-patch.gitdiff
Normal file
21
src/parser/__tests__/diff/git-format-patch.gitdiff
Normal file
|
@ -0,0 +1,21 @@
|
|||
From 9c68ca45aafefc1f9b9f49a7b380d6159d3e93c1 Mon Sep 17 00:00:00 2001
|
||||
From: epriestley <git@epriestley.com>
|
||||
Date: Sat, 15 Mar 2014 08:54:34 -0700
|
||||
Subject: [PATCH] WIP
|
||||
|
||||
---
|
||||
number_j.txt | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/number_j.txt b/number_j.txt
|
||||
index bd44aa2..d64876d 100644
|
||||
--- a/number_j.txt
|
||||
+++ b/number_j.txt
|
||||
@@ -138,3 +138,4 @@ j
|
||||
j
|
||||
j
|
||||
j
|
||||
+j
|
||||
--
|
||||
1.8.4.2
|
||||
|
|
@ -1574,6 +1574,7 @@ EOTEXT
|
|||
));
|
||||
}
|
||||
}
|
||||
|
||||
$old_message = $template;
|
||||
|
||||
$included = array();
|
||||
|
|
Loading…
Reference in a new issue