mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-12-01 19:22:41 +01:00
Merge "master" into "experimental".
This picks up a Mercurial parser fix and a handful of other things.
This commit is contained in:
commit
925c60e7b8
9 changed files with 178 additions and 7 deletions
|
@ -425,6 +425,7 @@ phutil_register_library_map(array(
|
||||||
'ArcanistVariableVariableXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistVariableVariableXHPASTLinterRule.php',
|
'ArcanistVariableVariableXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistVariableVariableXHPASTLinterRule.php',
|
||||||
'ArcanistVariableVariableXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistVariableVariableXHPASTLinterRuleTestCase.php',
|
'ArcanistVariableVariableXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistVariableVariableXHPASTLinterRuleTestCase.php',
|
||||||
'ArcanistVersionWorkflow' => 'workflow/ArcanistVersionWorkflow.php',
|
'ArcanistVersionWorkflow' => 'workflow/ArcanistVersionWorkflow.php',
|
||||||
|
'ArcanistWeldWorkflow' => 'workflow/ArcanistWeldWorkflow.php',
|
||||||
'ArcanistWhichWorkflow' => 'workflow/ArcanistWhichWorkflow.php',
|
'ArcanistWhichWorkflow' => 'workflow/ArcanistWhichWorkflow.php',
|
||||||
'ArcanistWorkflow' => 'workflow/ArcanistWorkflow.php',
|
'ArcanistWorkflow' => 'workflow/ArcanistWorkflow.php',
|
||||||
'ArcanistWorkingCopyIdentity' => 'workingcopyidentity/ArcanistWorkingCopyIdentity.php',
|
'ArcanistWorkingCopyIdentity' => 'workingcopyidentity/ArcanistWorkingCopyIdentity.php',
|
||||||
|
@ -872,6 +873,7 @@ phutil_register_library_map(array(
|
||||||
'ArcanistVariableVariableXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
'ArcanistVariableVariableXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||||
'ArcanistVariableVariableXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
'ArcanistVariableVariableXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||||
'ArcanistVersionWorkflow' => 'ArcanistWorkflow',
|
'ArcanistVersionWorkflow' => 'ArcanistWorkflow',
|
||||||
|
'ArcanistWeldWorkflow' => 'ArcanistWorkflow',
|
||||||
'ArcanistWhichWorkflow' => 'ArcanistWorkflow',
|
'ArcanistWhichWorkflow' => 'ArcanistWorkflow',
|
||||||
'ArcanistWorkflow' => 'Phobject',
|
'ArcanistWorkflow' => 'Phobject',
|
||||||
'ArcanistWorkingCopyIdentity' => 'Phobject',
|
'ArcanistWorkingCopyIdentity' => 'Phobject',
|
||||||
|
|
|
@ -174,6 +174,10 @@ final class ArcanistMercurialParser extends Phobject {
|
||||||
case 'bookmark':
|
case 'bookmark':
|
||||||
$commit['bookmark'] = $value;
|
$commit['bookmark'] = $value;
|
||||||
break;
|
break;
|
||||||
|
case 'obsolete':
|
||||||
|
// This is an extra field added by the "evolve" extension even
|
||||||
|
// if HGPLAIN=1 is set. See PHI502.
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
pht("Unknown Mercurial log field '%s'!", $name));
|
pht("Unknown Mercurial log field '%s'!", $name));
|
||||||
|
|
|
@ -68,7 +68,7 @@ final class ArcanistGoTestResultParser extends ArcanistTestResultParser {
|
||||||
if (strncmp($line, 'ok', 2) === 0) {
|
if (strncmp($line, 'ok', 2) === 0) {
|
||||||
$meta = array();
|
$meta = array();
|
||||||
preg_match(
|
preg_match(
|
||||||
'/^ok[\s\t]+(?P<test_name>\w.*)[\s\t]+(?P<time>.*)s.*/',
|
'/^ok[\s]+(?P<test_name>\w.*)[\s]+(?:(?P<time>.*)s|\(cached\))/',
|
||||||
$line,
|
$line,
|
||||||
$meta);
|
$meta);
|
||||||
|
|
||||||
|
@ -84,7 +84,10 @@ final class ArcanistGoTestResultParser extends ArcanistTestResultParser {
|
||||||
$result = new ArcanistUnitTestResult();
|
$result = new ArcanistUnitTestResult();
|
||||||
$result->setName($test_name);
|
$result->setName($test_name);
|
||||||
$result->setResult(ArcanistUnitTestResult::RESULT_PASS);
|
$result->setResult(ArcanistUnitTestResult::RESULT_PASS);
|
||||||
$result->setDuration((float)$meta['time']);
|
|
||||||
|
if (array_key_exists('time', $meta)) {
|
||||||
|
$result->setDuration((float)$meta['time']);
|
||||||
|
}
|
||||||
|
|
||||||
$results[] = $result;
|
$results[] = $result;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -103,6 +103,27 @@ final class ArcanistGoTestResultParserTestCase extends PhutilTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testNonVerboseOutputV110() {
|
||||||
|
$stubbed_results = Filesystem::readFile(
|
||||||
|
dirname(__FILE__).'/testresults/go.nonverbose-go1.10');
|
||||||
|
|
||||||
|
$parsed_results = id(new ArcanistGoTestResultParser())
|
||||||
|
->parseTestResults('package', $stubbed_results);
|
||||||
|
|
||||||
|
$this->assertEqual(2, count($parsed_results));
|
||||||
|
$this->assertEqual(
|
||||||
|
'Go::TestCase::package::subpackage1',
|
||||||
|
$parsed_results[0]->getName());
|
||||||
|
$this->assertEqual(
|
||||||
|
'Go::TestCase::package::subpackage2',
|
||||||
|
$parsed_results[1]->getName());
|
||||||
|
foreach ($parsed_results as $result) {
|
||||||
|
$this->assertEqual(
|
||||||
|
ArcanistUnitTestResult::RESULT_PASS,
|
||||||
|
$result->getResult());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function testSingleTestCaseSuccessfulGo14() {
|
public function testSingleTestCaseSuccessfulGo14() {
|
||||||
$stubbed_results = Filesystem::readFile(
|
$stubbed_results = Filesystem::readFile(
|
||||||
dirname(__FILE__).'/testresults/go.single-test-case-successful-go1.4');
|
dirname(__FILE__).'/testresults/go.single-test-case-successful-go1.4');
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
ok package/subpackage1 (cached)
|
||||||
|
ok package/subpackage2 0.010s
|
|
@ -171,7 +171,7 @@ EOTEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
echo $stdout;
|
echo $stdout;
|
||||||
fprintf(STDERR, $stderr);
|
fprintf(STDERR, '%s', $stderr);
|
||||||
return $err;
|
return $err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,9 @@ EOTEXT
|
||||||
'patches suggested by lint without prompting.'),
|
'patches suggested by lint without prompting.'),
|
||||||
),
|
),
|
||||||
'everything' => array(
|
'everything' => array(
|
||||||
'help' => pht('Lint all files in the project.'),
|
'help' => pht(
|
||||||
|
'Lint all tracked files in the working copy. Ignored files and '.
|
||||||
|
'untracked files will not be linted.'),
|
||||||
'conflicts' => array(
|
'conflicts' => array(
|
||||||
'rev' => pht('%s lints all files', '--everything'),
|
'rev' => pht('%s lints all files', '--everything'),
|
||||||
),
|
),
|
||||||
|
@ -155,7 +157,8 @@ EOTEXT
|
||||||
if ($everything && $paths) {
|
if ($everything && $paths) {
|
||||||
throw new ArcanistUsageException(
|
throw new ArcanistUsageException(
|
||||||
pht(
|
pht(
|
||||||
'You can not specify paths with %s. The %s flag lints every file.',
|
'You can not specify paths with %s. The %s flag lints every '.
|
||||||
|
'tracked file in the working copy.',
|
||||||
'--everything',
|
'--everything',
|
||||||
'--everything'));
|
'--everything'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,9 @@ EOTEXT
|
||||||
'Harbormaster build target.'),
|
'Harbormaster build target.'),
|
||||||
),
|
),
|
||||||
'everything' => array(
|
'everything' => array(
|
||||||
'help' => pht('Run every test.'),
|
'help' => pht(
|
||||||
|
'Run every test associated with a tracked file in the working '.
|
||||||
|
'copy.'),
|
||||||
'conflicts' => array(
|
'conflicts' => array(
|
||||||
'rev' => pht('%s runs all tests.', '--everything'),
|
'rev' => pht('%s runs all tests.', '--everything'),
|
||||||
),
|
),
|
||||||
|
@ -134,7 +136,8 @@ EOTEXT
|
||||||
if ($everything && $paths) {
|
if ($everything && $paths) {
|
||||||
throw new ArcanistUsageException(
|
throw new ArcanistUsageException(
|
||||||
pht(
|
pht(
|
||||||
'You can not specify paths with %s. The %s flag runs every test.',
|
'You can not specify paths with %s. The %s flag runs every test '.
|
||||||
|
'associated with a tracked file in the working copy.',
|
||||||
'--everything',
|
'--everything',
|
||||||
'--everything'));
|
'--everything'));
|
||||||
}
|
}
|
||||||
|
|
133
src/workflow/ArcanistWeldWorkflow.php
Normal file
133
src/workflow/ArcanistWeldWorkflow.php
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistWeldWorkflow extends ArcanistWorkflow {
|
||||||
|
|
||||||
|
public function getWorkflowName() {
|
||||||
|
return 'weld';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommandSynopses() {
|
||||||
|
return phutil_console_format(<<<EOTEXT
|
||||||
|
**weld** [options] __file__ __file__ ...
|
||||||
|
EOTEXT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommandHelp() {
|
||||||
|
return phutil_console_format(<<<EOTEXT
|
||||||
|
Robustly fuse two or more files together. The resulting joint is
|
||||||
|
much stronger than the one created by tools like __cat__.
|
||||||
|
EOTEXT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getArguments() {
|
||||||
|
return array(
|
||||||
|
'*' => 'files',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run() {
|
||||||
|
$files = $this->getArgument('files');
|
||||||
|
if (count($files) < 2) {
|
||||||
|
throw new ArcanistUsageException(
|
||||||
|
pht('Specify two or more files to weld together.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$buffer = array();
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$data = Filesystem::readFile($file);
|
||||||
|
if (!strlen($data)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$lines = phutil_split_lines($data, true);
|
||||||
|
|
||||||
|
$overlap = mt_rand(16, 32);
|
||||||
|
|
||||||
|
if (count($buffer) > 6) {
|
||||||
|
$overlap = min($overlap, ceil(count($buffer) / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($lines) > 6) {
|
||||||
|
$overlap = min($overlap, ceil(count($lines) / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
$overlap = min($overlap, count($buffer));
|
||||||
|
$overlap = min($overlap, count($lines));
|
||||||
|
|
||||||
|
$buffer_len = count($buffer);
|
||||||
|
for ($ii = 0; $ii < $overlap; $ii++) {
|
||||||
|
$buffer[$buffer_len - $overlap + $ii] = $this->weldLines(
|
||||||
|
$buffer[$buffer_len - $overlap + $ii],
|
||||||
|
$lines[$ii],
|
||||||
|
($ii + 0.5) / $overlap);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($ii = $overlap; $ii < count($lines); $ii++) {
|
||||||
|
$buffer[] = $lines[$ii];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo implode('', $buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function weldLines($u, $v, $bias) {
|
||||||
|
$newline = null;
|
||||||
|
$matches = null;
|
||||||
|
|
||||||
|
if (preg_match('/([\r\n]+)\z/', $u, $matches)) {
|
||||||
|
$newline = $matches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('/([\r\n]+)\z/', $v, $matches)) {
|
||||||
|
$newline = $matches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
$u = rtrim($u, "\r\n");
|
||||||
|
$v = rtrim($v, "\r\n");
|
||||||
|
|
||||||
|
$u = phutil_utf8v_combined($u);
|
||||||
|
$v = phutil_utf8v_combined($v);
|
||||||
|
|
||||||
|
$len = max(count($u), count($v));
|
||||||
|
|
||||||
|
while (count($u) < $len) {
|
||||||
|
$u[] = ' ';
|
||||||
|
}
|
||||||
|
while (count($v) < $len) {
|
||||||
|
$v[] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
$rand_max = mt_getrandmax();
|
||||||
|
|
||||||
|
$result = array();
|
||||||
|
for ($ii = 0; $ii < $len; $ii++) {
|
||||||
|
$uc = $u[$ii];
|
||||||
|
$vc = $v[$ii];
|
||||||
|
|
||||||
|
$threshold = $bias;
|
||||||
|
if ($uc == ' ') {
|
||||||
|
$threshold = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($vc == ' ') {
|
||||||
|
$threshold = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mt_rand() / $rand_max) > $threshold) {
|
||||||
|
$r = $uc;
|
||||||
|
} else {
|
||||||
|
$r = $vc;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result[] = $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($newline !== null) {
|
||||||
|
$result[] = $newline;
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode('', $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue