1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-25 08:12:40 +01:00

Parse 'hg status -C' to show file move/copy sources

Summary: For Mercurial parsing in Diffusion, it looks like the only command we
can use to get move/copy information is "hg status -C --rev <rev>", so add a
parser for it.

Test Plan: Ran unit tests.

Reviewers: Makinde, jungejason, nh, tuomaspelkonen, aran

Reviewed By: Makinde

CC: aran, Makinde

Differential Revision: 958
This commit is contained in:
epriestley 2011-09-25 09:59:41 -07:00
parent 752ef65020
commit ef0a9cbb79
4 changed files with 65 additions and 7 deletions

View file

@ -30,13 +30,15 @@ final class ArcanistMercurialParser {
/** /**
* Parse the output of "hg status". * Parse the output of "hg status". This provides detailed information, you
* can get less detailed information with @{method:parseMercurialStatus}. In
* particular, this will parse copy sources as per "hg status -C".
* *
* @param string The stdout from running an "hg status" command. * @param string The stdout from running an "hg status" command.
* @return dict Map of paths to ArcanistRepositoryAPI status flags. * @return dict Map of paths to status dictionaries.
* @task parse * @task parse
*/ */
public static function parseMercurialStatus($stdout) { public static function parseMercurialStatusDetails($stdout) {
$result = array(); $result = array();
$stdout = trim($stdout); $stdout = trim($stdout);
@ -44,16 +46,21 @@ final class ArcanistMercurialParser {
return $result; return $result;
} }
$last_path = null;
$lines = explode("\n", $stdout); $lines = explode("\n", $stdout);
foreach ($lines as $line) { foreach ($lines as $line) {
$flags = 0; $flags = 0;
list($code, $path) = explode(' ', $line, 2); if ($line[1] !== ' ') {
throw new Exception("Unparsable Mercurial status line '{$line}'.");
}
$code = $line[0];
$path = substr($line, 2);
switch ($code) { switch ($code) {
case 'A': case 'A':
$flags |= ArcanistRepositoryAPI::FLAG_ADDED; $flags |= ArcanistRepositoryAPI::FLAG_ADDED;
break; break;
case 'R': case 'R':
$flags |= ArcanistRepositoryAPI::FLAG_REMOVED; $flags |= ArcanistRepositoryAPI::FLAG_DELETED;
break; break;
case 'M': case 'M':
$flags |= ArcanistRepositoryAPI::FLAG_MODIFIED; $flags |= ArcanistRepositoryAPI::FLAG_MODIFIED;
@ -71,17 +78,45 @@ final class ArcanistMercurialParser {
case 'I': case 'I':
// This is "ignored" and included only for completeness. // This is "ignored" and included only for completeness.
break; break;
case ' ':
// This shows the source of a file move, so update the last file we
// parsed to set its source.
if ($last_path === null) {
throw new Exception(
"Unexpected copy source in hg status, '{$line}'.");
}
$result[$last_path]['from'] = $path;
continue 2;
default: default:
throw new Exception("Unknown Mercurial status '{$code}'."); throw new Exception("Unknown Mercurial status '{$code}'.");
} }
$result[$path] = $flags; $result[$path] = array(
'flags' => $flags,
'from' => null,
);
$last_path = $path;
} }
return $result; return $result;
} }
/**
* Parse the output of "hg status". This provides only basic information, you
* can get more detailed information by invoking
* @{method:parseMercurialStatusDetails}.
*
* @param string The stdout from running an "hg status" command.
* @return dict Map of paths to ArcanistRepositoryAPI status flags.
* @task parse
*/
public static function parseMercurialStatus($stdout) {
$result = self::parseMercurialStatusDetails($stdout);
return ipull($result, 'flags');
}
/** /**
* Parse the output of "hg log". This also parses "hg outgoing", "hg parents", * Parse the output of "hg log". This also parses "hg outgoing", "hg parents",
* and other similar commands. This assumes "--style default". * and other similar commands. This assumes "--style default".

View file

@ -8,5 +8,7 @@
phutil_require_module('arcanist', 'repository/api/base'); phutil_require_module('arcanist', 'repository/api/base');
phutil_require_module('phutil', 'utils');
phutil_require_source('ArcanistMercurialParser.php'); phutil_require_source('ArcanistMercurialParser.php');

View file

@ -20,7 +20,7 @@ final class ArcanistMercurialParserTestCase extends ArcanistPhutilTestCase {
public function testParseAll() { public function testParseAll() {
$root = dirname(__FILE__).'/data/'; $root = dirname(__FILE__).'/data/';
foreach (Filesystem::listDirectory($root) as $file) { foreach (Filesystem::listDirectory($root, $hidden = false) as $file) {
$this->parseData( $this->parseData(
basename($file), basename($file),
Filesystem::readFile($root.'/'.$file)); Filesystem::readFile($root.'/'.$file));
@ -64,6 +64,21 @@ final class ArcanistMercurialParserTestCase extends ArcanistPhutilTestCase {
array('changed', 'added', 'removed', 'untracked'), array('changed', 'added', 'removed', 'untracked'),
array_keys($output)); array_keys($output));
break; break;
case 'status-moves.txt':
$output = ArcanistMercurialParser::parseMercurialStatusDetails($data);
$this->assertEqual(
'move_source',
$output['moved_file']['from']);
$this->assertEqual(
null,
$output['changed_file']['from']);
$this->assertEqual(
'copy_source',
$output['copied_file']['from']);
$this->assertEqual(
null,
idx($output, 'copy_source'));
break;
default: default:
throw new Exception("No test information for test data '{$name}'!"); throw new Exception("No test information for test data '{$name}'!");
} }

View file

@ -0,0 +1,6 @@
M changed_file
A moved_file
move_source
R moved_source
A copied_file
copy_source