diff --git a/scripts/arcanist.php b/scripts/arcanist.php index ff0875f7..f29311f6 100755 --- a/scripts/arcanist.php +++ b/scripts/arcanist.php @@ -422,7 +422,7 @@ try { } } - echo fwrite(STDERR, phutil_console_format( + fwrite(STDERR, phutil_console_format( "(%s)\n", pht('Run with `%s` for a full exception trace.', '--trace'))); } @@ -620,9 +620,9 @@ function arcanist_load_libraries( throw new ArcanistUsageException($error); } else { fwrite(STDERR, phutil_console_wrap( - "%s: %s\n\n", - pht('WARNING'), - $error)); + phutil_console_format("%s: %s\n", + pht('WARNING'), + $error))); } } catch (PhutilLibraryConflictException $ex) { if ($ex->getLibrary() != 'arcanist') { diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 722bea0a..96d7da91 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -90,6 +90,7 @@ phutil_register_library_map(array( 'ArcanistDuplicateSwitchCaseXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDuplicateSwitchCaseXHPASTLinterRule.php', 'ArcanistDynamicDefineXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDynamicDefineXHPASTLinterRule.php', 'ArcanistElseIfUsageXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistElseIfUsageXHPASTLinterRule.php', + 'ArcanistEmptyFileXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistEmptyFileXHPASTLinterRule.php', 'ArcanistEmptyStatementXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistEmptyStatementXHPASTLinterRule.php', 'ArcanistEventType' => 'events/constant/ArcanistEventType.php', 'ArcanistExitExpressionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistExitExpressionXHPASTLinterRule.php', @@ -171,6 +172,7 @@ phutil_register_library_map(array( 'ArcanistMissingLinterException' => 'lint/linter/exception/ArcanistMissingLinterException.php', 'ArcanistModifierOrderingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistModifierOrderingXHPASTLinterRule.php', 'ArcanistNamingConventionsXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistNamingConventionsXHPASTLinterRule.php', + 'ArcanistNewlineAfterOpenTagXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistNewlineAfterOpenTagXHPASTLinterRule.php', 'ArcanistNoEffectException' => 'exception/usage/ArcanistNoEffectException.php', 'ArcanistNoEngineException' => 'exception/usage/ArcanistNoEngineException.php', 'ArcanistNoLintLinter' => 'lint/linter/ArcanistNoLintLinter.php', @@ -374,6 +376,7 @@ phutil_register_library_map(array( 'ArcanistDuplicateSwitchCaseXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistDynamicDefineXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistElseIfUsageXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', + 'ArcanistEmptyFileXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistEmptyStatementXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistEventType' => 'PhutilEventType', 'ArcanistExitExpressionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', @@ -455,6 +458,7 @@ phutil_register_library_map(array( 'ArcanistMissingLinterException' => 'Exception', 'ArcanistModifierOrderingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistNamingConventionsXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', + 'ArcanistNewlineAfterOpenTagXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistNoEffectException' => 'ArcanistUsageException', 'ArcanistNoEngineException' => 'ArcanistUsageException', 'ArcanistNoLintLinter' => 'ArcanistLinter', diff --git a/src/lint/engine/ArcanistLintEngine.php b/src/lint/engine/ArcanistLintEngine.php index 8add0a88..4a092fdb 100644 --- a/src/lint/engine/ArcanistLintEngine.php +++ b/src/lint/engine/ArcanistLintEngine.php @@ -57,7 +57,6 @@ abstract class ArcanistLintEngine extends Phobject { private $changedLines = array(); private $enableAsyncLint = false; - private $postponedLinters = array(); private $configurationManager; private $linterResources = array(); @@ -403,15 +402,6 @@ abstract class ArcanistLintEngine extends Phobject { return array($line, $char); } - final public function getPostponedLinters() { - return $this->postponedLinters; - } - - final public function setPostponedLinters(array $linters) { - $this->postponedLinters = $linters; - return $this; - } - protected function getCacheVersion() { return 1; } diff --git a/src/lint/linter/ArcanistTextLinter.php b/src/lint/linter/ArcanistTextLinter.php index 78d86a40..2f81b039 100644 --- a/src/lint/linter/ArcanistTextLinter.php +++ b/src/lint/linter/ArcanistTextLinter.php @@ -13,6 +13,7 @@ final class ArcanistTextLinter extends ArcanistLinter { const LINT_TRAILING_WHITESPACE = 6; const LINT_BOF_WHITESPACE = 8; const LINT_EOF_WHITESPACE = 9; + const LINT_EMPTY_FILE = 10; private $maxLineLength = 80; @@ -85,16 +86,23 @@ final class ArcanistTextLinter extends ArcanistLinter { self::LINT_TRAILING_WHITESPACE => pht('Trailing Whitespace'), self::LINT_BOF_WHITESPACE => pht('Leading Whitespace at BOF'), self::LINT_EOF_WHITESPACE => pht('Trailing Whitespace at EOF'), + self::LINT_EMPTY_FILE => pht('Empty File'), ); } public function lintPath($path) { + $this->lintEmptyFile($path); + if (!strlen($this->getData($path))) { // If the file is empty, don't bother; particularly, don't require // the user to add a newline. return; } + if ($this->didStopAllLinters()) { + return; + } + $this->lintNewlines($path); $this->lintTabs($path); @@ -116,6 +124,29 @@ final class ArcanistTextLinter extends ArcanistLinter { $this->lintEOFWhitespace($path); } + protected function lintEmptyFile($path) { + $data = $this->getData($path); + + // It is reasonable for certain file types to be completely empty, + // so they are excluded here. + switch ($filename = basename($this->getActivePath())) { + case '__init__.py': + return; + + default: + if (strlen($filename) && $filename[0] == '.') { + return; + } + } + + if (preg_match('/^\s*$/', $data)) { + $this->raiseLintAtPath( + self::LINT_EMPTY_FILE, + pht("Empty files usually don't serve any useful purpose.")); + $this->stopAllLinters(); + } + } + protected function lintNewlines($path) { $data = $this->getData($path); $pos = strpos($this->getData($path), "\r"); diff --git a/src/lint/linter/__tests__/text/empty-file.lint-test b/src/lint/linter/__tests__/text/empty.lint-test similarity index 52% rename from src/lint/linter/__tests__/text/empty-file.lint-test rename to src/lint/linter/__tests__/text/empty.lint-test index 383e5ae1..546b0f1e 100644 --- a/src/lint/linter/__tests__/text/empty-file.lint-test +++ b/src/lint/linter/__tests__/text/empty.lint-test @@ -1 +1,4 @@ + + ~~~~~~~~~~ +error:: diff --git a/src/lint/linter/__tests__/xhpast/array-comma.lint-test b/src/lint/linter/__tests__/xhpast/array-comma.lint-test index 6945002c..51128f2e 100644 --- a/src/lint/linter/__tests__/xhpast/array-comma.lint-test +++ b/src/lint/linter/__tests__/xhpast/array-comma.lint-test @@ -1,4 +1,5 @@ 'val1', $a => 'val2', @@ -34,9 +35,9 @@ $f = array( $a => 'var2', ); ~~~~~~~~~~ -error:5:3 -error:8:3 -error:15:3 -error:20:3 -error:25:3 -error:34:3 +error:6:3 +error:9:3 +error:16:3 +error:21:3 +error:26:3 +error:35:3 diff --git a/src/lint/linter/__tests__/xhpast/duplicate-switch-case.lint-test b/src/lint/linter/__tests__/xhpast/duplicate-switch-case.lint-test index 309e04d6..2c8e5c5c 100644 --- a/src/lint/linter/__tests__/xhpast/duplicate-switch-case.lint-test +++ b/src/lint/linter/__tests__/xhpast/duplicate-switch-case.lint-test @@ -1,4 +1,5 @@ +~~~~~~~~~~ +warning:: diff --git a/src/lint/linter/__tests__/xhpast/exit-expression.lint-test b/src/lint/linter/__tests__/xhpast/exit-expression.lint-test index c9724096..b7a4f4f9 100644 --- a/src/lint/linter/__tests__/xhpast/exit-expression.lint-test +++ b/src/lint/linter/__tests__/xhpast/exit-expression.lint-test @@ -1,4 +1,5 @@ + + + + + + + + + + doSomething(); id(new Something()) ->doSomething(); ~~~~~~~~~~ -warning:2:3 -warning:2:6 +warning:3:3 +warning:3:6 ~~~~~~~~~~ doSomething(); id(new Something()) ->doSomething(); diff --git a/src/lint/linter/__tests__/xhpast/parens-hug-contents.lint-test b/src/lint/linter/__tests__/xhpast/parens-hug-contents.lint-test index c0058bc0..d6a38e88 100644 --- a/src/lint/linter/__tests__/xhpast/parens-hug-contents.lint-test +++ b/src/lint/linter/__tests__/xhpast/parens-hug-contents.lint-test @@ -1,4 +1,5 @@ $y, ); ~~~~~~~~~~ -warning:3:3 -warning:3:5 -warning:4:4 -warning:5:3 -warning:12:9 -warning:13:10 -warning:14:9 -warning:24:5 +warning:4:3 +warning:4:5 +warning:5:4 +warning:6:3 +warning:13:9 +warning:14:10 +warning:15:9 +warning:25:5 ~~~~~~~~~~ 500) of string concatenations. We emit n_CONCATENATION_LIST instead of // n_BINARY_EXPRESSION to avoid various call-depth traps in PHP, HPHP, and the @@ -43,6 +44,7 @@ ~~~~~~~~~~ ~~~~~~~~~~ 500) of string concatenations. We emit n_CONCATENATION_LIST instead of // n_BINARY_EXPRESSION to avoid various call-depth traps in PHP, HPHP, and the diff --git a/src/lint/linter/__tests__/xhpast/use-of-this-in-static-method.lint-test b/src/lint/linter/__tests__/xhpast/use-of-this-in-static-method.lint-test index 3ae1214b..395939bb 100644 --- a/src/lint/linter/__tests__/xhpast/use-of-this-in-static-method.lint-test +++ b/src/lint/linter/__tests__/xhpast/use-of-this-in-static-method.lint-test @@ -8,7 +8,6 @@ final class A { $this->f(); } } - ~~~~~~~~~~ error:3:13 XHP19 Class-Filename Mismatch error:8:5 Use of $this in a static method. diff --git a/src/lint/linter/__tests__/xhpast/variable-variables.lint-test b/src/lint/linter/__tests__/xhpast/variable-variables.lint-test index d3e9a2f1..60c06632 100644 --- a/src/lint/linter/__tests__/xhpast/variable-variables.lint-test +++ b/src/lint/linter/__tests__/xhpast/variable-variables.lint-test @@ -1,5 +1,6 @@ $bar; // okay ~~~~~~~~~~ -error:2:1 +error:3:1 diff --git a/src/lint/linter/__tests__/xhpast/wrong-concat-operator.lint-test b/src/lint/linter/__tests__/xhpast/wrong-concat-operator.lint-test index 70f2450d..3910c597 100644 --- a/src/lint/linter/__tests__/xhpast/wrong-concat-operator.lint-test +++ b/src/lint/linter/__tests__/xhpast/wrong-concat-operator.lint-test @@ -1,9 +1,10 @@ linter->raiseLintAtPath($this->getLintID(), $desc); + } + final protected function raiseLintAtToken( XHPASTToken $token, $desc, diff --git a/src/lint/linter/xhpast/rules/ArcanistEmptyFileXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistEmptyFileXHPASTLinterRule.php new file mode 100644 index 00000000..28d6b4e3 --- /dev/null +++ b/src/lint/linter/xhpast/rules/ArcanistEmptyFileXHPASTLinterRule.php @@ -0,0 +1,35 @@ +getTokens(); + + foreach ($tokens as $token) { + switch ($token->getTypeName()) { + case 'T_OPEN_TAG': + case 'T_CLOSE_TAG': + case 'T_WHITESPACE': + break; + + default: + return; + } + } + + $this->raiseLintAtPath( + pht("Empty files usually don't serve any useful purpose.")); + } + +} diff --git a/src/lint/linter/xhpast/rules/ArcanistNewlineAfterOpenTagXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistNewlineAfterOpenTagXHPASTLinterRule.php new file mode 100644 index 00000000..63bed628 --- /dev/null +++ b/src/lint/linter/xhpast/rules/ArcanistNewlineAfterOpenTagXHPASTLinterRule.php @@ -0,0 +1,46 @@ +selectTokensOfType('T_OPEN_TAG'); + + foreach ($tokens as $token) { + for ($next = $token->getNextToken(); + $next; + $next = $next->getNextToken()) { + + if ($next->getTypeName() == 'T_WHITESPACE' && + preg_match('/\n\s*\n/', $next->getValue())) { + continue 2; + } + + if ($token->getLineNumber() != $next->getLineNumber()) { + break; + } + + if ($next->getTypeName() == 'T_CLOSE_TAG') { + continue 2; + } + } + + $next = $token->getNextToken(); + $this->raiseLintAtToken( + $next, + pht('`%s` should be separated from code by an empty line.', 'getValue()); + } + } + +} diff --git a/src/unit/ArcanistUnitTestResult.php b/src/unit/ArcanistUnitTestResult.php index a0dc2f72..a9061bd0 100644 --- a/src/unit/ArcanistUnitTestResult.php +++ b/src/unit/ArcanistUnitTestResult.php @@ -10,7 +10,6 @@ final class ArcanistUnitTestResult extends Phobject { const RESULT_SKIP = 'skip'; const RESULT_BROKEN = 'broken'; const RESULT_UNSOUND = 'unsound'; - const RESULT_POSTPONED = 'postponed'; private $namespace; private $name; diff --git a/src/unit/renderer/ArcanistUnitConsoleRenderer.php b/src/unit/renderer/ArcanistUnitConsoleRenderer.php index 16441f3c..fa646fc5 100644 --- a/src/unit/renderer/ArcanistUnitConsoleRenderer.php +++ b/src/unit/renderer/ArcanistUnitConsoleRenderer.php @@ -28,13 +28,6 @@ final class ArcanistUnitConsoleRenderer extends ArcanistUnitRenderer { return $return; } - public function renderPostponedResult($count) { - return sprintf( - "%s %s\n", - $this->getFormattedResult(ArcanistUnitTestResult::RESULT_POSTPONED), - pht('%d test(s)', $count)); - } - private function getFormattedResult($result) { switch ($result) { case ArcanistUnitTestResult::RESULT_PASS: @@ -54,11 +47,6 @@ final class ArcanistUnitConsoleRenderer extends ArcanistUnitRenderer { '** %s **', pht('UNSOUND')); - case ArcanistUnitTestResult::RESULT_POSTPONED: - return phutil_console_format( - '** %s **', - pht('POSTPONED')); - default: return null; } diff --git a/src/unit/renderer/ArcanistUnitRenderer.php b/src/unit/renderer/ArcanistUnitRenderer.php index 4dd936c3..cc8031d1 100644 --- a/src/unit/renderer/ArcanistUnitRenderer.php +++ b/src/unit/renderer/ArcanistUnitRenderer.php @@ -2,5 +2,4 @@ abstract class ArcanistUnitRenderer extends Phobject { abstract public function renderUnitResult(ArcanistUnitTestResult $result); - abstract public function renderPostponedResult($count); } diff --git a/src/upload/ArcanistFileUploader.php b/src/upload/ArcanistFileUploader.php index 955cdbdc..ba960775 100644 --- a/src/upload/ArcanistFileUploader.php +++ b/src/upload/ArcanistFileUploader.php @@ -27,6 +27,7 @@ final class ArcanistFileUploader extends Phobject { private $conduit; private $files; + private $config = array(); /* -( Configuring the Uploader )------------------------------------------- */ @@ -78,6 +79,33 @@ final class ArcanistFileUploader extends Phobject { } + /** + * Configure a file to be temporary instead of permanent. + * + * By default, files are retained indefinitely until explicitly deleted. If + * you want to upload a temporary file instead, you can specify an epoch + * timestamp. The file will be deleted after this time. + * + * @param string Key identifying the file you want to make temporary, as + * passed to @{method:addFile}. + * @param int Epoch timestamp to retain the file until. + * @return this + * @task add + */ + public function setDeleteFileAfterEpoch($file_key, $epoch) { + if (empty($this->files[$file_key])) { + throw new Exception( + pht( + 'No file with given key ("%s") has been added to this uploader.', + $file_key)); + } + + $this->config[$file_key]['deleteAfterEpoch'] = $epoch; + + return $this; + } + + /* -( Uploading Files )---------------------------------------------------- */ @@ -116,13 +144,20 @@ final class ArcanistFileUploader extends Phobject { $conduit = $this->conduit; $futures = array(); foreach ($files as $key => $file) { - $futures[$key] = $conduit->callMethod( - 'file.allocate', - array( - 'name' => $file->getName(), - 'contentLength' => $file->getByteSize(), - 'contentHash' => $file->getContentHash(), - )); + $config = idx($this->config, $key, array()); + + $params = array( + 'name' => $file->getName(), + 'contentLength' => $file->getByteSize(), + 'contentHash' => $file->getContentHash(), + ); + + $delete_after = idx($config, 'deleteAfterEpoch'); + if ($delete_after !== null) { + $params['deleteAfterEpoch'] = $delete_after; + } + + $futures[$key] = $conduit->callMethod('file.allocate', $params); } $iterator = id(new FutureIterator($futures))->limit(4); diff --git a/src/workflow/ArcanistDiffWorkflow.php b/src/workflow/ArcanistDiffWorkflow.php index 4f017d64..3074c166 100644 --- a/src/workflow/ArcanistDiffWorkflow.php +++ b/src/workflow/ArcanistDiffWorkflow.php @@ -17,7 +17,6 @@ final class ArcanistDiffWorkflow extends ArcanistWorkflow { private $testResults; private $diffID; private $revisionID; - private $postponedLinters; private $haveUncommittedChanges = false; private $diffPropertyFutures = array(); private $commitMessageFromRevision; @@ -476,7 +475,6 @@ EOTEXT $lint_result = $data['lintResult']; $this->unresolvedLint = $data['unresolvedLint']; - $this->postponedLinters = $data['postponedLinters']; $unit_result = $data['unitResult']; $this->testResults = $data['testResults']; @@ -1032,9 +1030,8 @@ EOTEXT } catch (ConduitClientException $e) { if ($e->getErrorCode() == 'ERR-BAD-ARCANIST-PROJECT') { echo phutil_console_wrap( - "%s\n", - pht('Lookup of encoding in arcanist project failed'), - $e->getMessage()); + pht('Lookup of encoding in arcanist project failed: %s', + $e->getMessage())."\n"); } else { throw $e; } @@ -1222,7 +1219,6 @@ EOTEXT return array( 'lintResult' => $lint_result, 'unresolvedLint' => $this->unresolvedLint, - 'postponedLinters' => $this->postponedLinters, 'unitResult' => $unit_result, 'testResults' => $this->testResults, ); @@ -1290,12 +1286,6 @@ EOTEXT pht('Lint issued unresolved errors!'), 'lint-excuses'); break; - case ArcanistLintWorkflow::RESULT_POSTPONED: - $this->console->writeOut( - "** %s ** %s\n", - pht('LINT POSTPONED'), - pht('Lint results are postponed.')); - break; } $this->unresolvedLint = array(); @@ -1303,8 +1293,6 @@ EOTEXT $this->unresolvedLint[] = $message->toDictionary(); } - $this->postponedLinters = $lint_workflow->getPostponedLinters(); - return $lint_result; } catch (ArcanistNoEngineException $ex) { $this->console->writeOut( @@ -2260,7 +2248,6 @@ EOTEXT ArcanistLintWorkflow::RESULT_ERRORS => 'fail', ArcanistLintWorkflow::RESULT_WARNINGS => 'warn', ArcanistLintWorkflow::RESULT_SKIP => 'skip', - ArcanistLintWorkflow::RESULT_POSTPONED => 'postponed', ); return idx($map, $lint_result, 'none'); } @@ -2275,7 +2262,6 @@ EOTEXT ArcanistUnitWorkflow::RESULT_FAIL => 'fail', ArcanistUnitWorkflow::RESULT_UNSOUND => 'warn', ArcanistUnitWorkflow::RESULT_SKIP => 'skip', - ArcanistUnitWorkflow::RESULT_POSTPONED => 'postponed', ); return idx($map, $unit_result, 'none'); } @@ -2680,8 +2666,13 @@ EOTEXT pht('PUSH STAGING'), pht('Pushing changes to staging area...')); + $push_flags = array(); + if (version_compare($api->getGitVersion(), '1.8.2', '>=')) { + $push_flags[] = '--no-verify'; + } $err = phutil_passthru( - 'git push --no-verify -- %s %s:refs/tags/%s', + 'git push %Ls -- %s %s:refs/tags/%s', + $push_flags, $staging_uri, $commit, $tag); diff --git a/src/workflow/ArcanistLintWorkflow.php b/src/workflow/ArcanistLintWorkflow.php index 27db427d..bb53cde7 100644 --- a/src/workflow/ArcanistLintWorkflow.php +++ b/src/workflow/ArcanistLintWorkflow.php @@ -9,7 +9,6 @@ final class ArcanistLintWorkflow extends ArcanistWorkflow { const RESULT_WARNINGS = 1; const RESULT_ERRORS = 2; const RESULT_SKIP = 3; - const RESULT_POSTPONED = 4; const DEFAULT_SEVERITY = ArcanistLintSeverity::SEVERITY_ADVICE; @@ -19,7 +18,6 @@ final class ArcanistLintWorkflow extends ArcanistWorkflow { private $shouldAmendWithoutPrompt = false; private $shouldAmendAutofixesWithoutPrompt = false; private $engine; - private $postponedLinters; public function getWorkflowName() { return 'lint'; @@ -399,12 +397,6 @@ EOTEXT } } - // It'd be nice to just return a single result from the run method above - // which contains both the lint messages and the postponed linters. - // However, to maintain compatibility with existing lint subclasses, use - // a separate method call to grab the postponed linters. - $this->postponedLinters = $engine->getPostponedLinters(); - if ($this->getArgument('never-apply-patches')) { $apply_patches = false; } else { @@ -650,8 +642,6 @@ EOTEXT $result_code = self::RESULT_ERRORS; } else if ($has_warnings) { $result_code = self::RESULT_WARNINGS; - } else if (!empty($this->postponedLinters)) { - $result_code = self::RESULT_POSTPONED; } else { $result_code = self::RESULT_OKAY; } @@ -669,8 +659,4 @@ EOTEXT return $this->unresolvedMessages; } - public function getPostponedLinters() { - return $this->postponedLinters; - } - } diff --git a/src/workflow/ArcanistUnitWorkflow.php b/src/workflow/ArcanistUnitWorkflow.php index a97bbdeb..1fcee32a 100644 --- a/src/workflow/ArcanistUnitWorkflow.php +++ b/src/workflow/ArcanistUnitWorkflow.php @@ -9,7 +9,6 @@ final class ArcanistUnitWorkflow extends ArcanistWorkflow { const RESULT_UNSOUND = 1; const RESULT_FAIL = 2; const RESULT_SKIP = 3; - const RESULT_POSTPONED = 4; private $unresolvedTests; private $testResults; @@ -175,19 +174,13 @@ EOTEXT $unresolved = array(); $coverage = array(); - $postponed_count = 0; foreach ($results as $result) { $result_code = $result->getResult(); - if ($result_code == ArcanistUnitTestResult::RESULT_POSTPONED) { - $postponed_count++; + if ($this->engine->shouldEchoTestResults()) { + $console->writeOut('%s', $renderer->renderUnitResult($result)); + } + if ($result_code != ArcanistUnitTestResult::RESULT_PASS) { $unresolved[] = $result; - } else { - if ($this->engine->shouldEchoTestResults()) { - $console->writeOut('%s', $renderer->renderUnitResult($result)); - } - if ($result_code != ArcanistUnitTestResult::RESULT_PASS) { - $unresolved[] = $result; - } } if ($result->getCoverage()) { foreach ($result->getCoverage() as $file => $report) { @@ -195,11 +188,6 @@ EOTEXT } } } - if ($postponed_count) { - $console->writeOut( - '%s', - $renderer->renderPostponedResult($postponed_count)); - } if ($coverage) { $file_coverage = array_fill_keys( @@ -252,9 +240,6 @@ EOTEXT break; } else if ($result_code == ArcanistUnitTestResult::RESULT_UNSOUND) { $overall_result = self::RESULT_UNSOUND; - } else if ($result_code == ArcanistUnitTestResult::RESULT_POSTPONED && - $overall_result != self::RESULT_UNSOUND) { - $overall_result = self::RESULT_POSTPONED; } } diff --git a/src/workflow/ArcanistUploadWorkflow.php b/src/workflow/ArcanistUploadWorkflow.php index 64c5260d..b4414a39 100644 --- a/src/workflow/ArcanistUploadWorkflow.php +++ b/src/workflow/ArcanistUploadWorkflow.php @@ -32,6 +32,11 @@ EOTEXT 'json' => array( 'help' => pht('Output upload information in JSON format.'), ), + 'temporary' => array( + 'help' => pht( + 'Mark the file as temporary. Temporary files will be deleted '. + 'automatically after 24 hours.'), + ), '*' => 'paths', ); } @@ -51,18 +56,26 @@ EOTEXT } public function run() { + $is_temporary = $this->getArgument('temporary'); + $conduit = $this->getConduit(); $results = array(); $uploader = id(new ArcanistFileUploader()) ->setConduitClient($conduit); - foreach ($this->paths as $path) { + foreach ($this->paths as $key => $path) { $file = id(new ArcanistFileDataRef()) ->setName(basename($path)) ->setPath($path); - $uploader->addFile($file); + $uploader->addFile($file, $key); + + if ($is_temporary) { + $uploader->setDeleteFileAfterEpoch( + $key, + time() + phutil_units('24 hours in seconds')); + } } $files = $uploader->uploadFiles(); diff --git a/src/workflow/ArcanistWorkflow.php b/src/workflow/ArcanistWorkflow.php index 87b37605..047477e5 100644 --- a/src/workflow/ArcanistWorkflow.php +++ b/src/workflow/ArcanistWorkflow.php @@ -1585,12 +1585,11 @@ abstract class ArcanistWorkflow extends Phobject { } catch (ConduitClientException $ex) { if ($ex->getErrorCode() == 'ERR-CONDUIT-CALL') { echo phutil_console_wrap( - "%s\n\n", pht( 'This feature requires a newer version of Phabricator. Please '. 'update it using these instructions: %s', 'https://secure.phabricator.com/book/phabricator/article/'. - 'upgrading/')); + 'upgrading/')."\n\n"); } throw $ex; }