From b50acb512922920d7a7e6f695ee865678e9f5416 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 18 Feb 2011 22:17:41 -0800 Subject: [PATCH 1/3] Provide a "--conduit-uri" override for testing, and tweak some documentation. Summary: Test Plan: Reviewers: CC: --- scripts/arcanist.php | 11 ++++++++++- src/workflow/help/ArcanistHelpWorkflow.php | 8 ++++++++ .../mark-committed/ArcanistMarkCommittedWorkflow.php | 2 +- .../shell-complete/ArcanistShellCompleteWorkflow.php | 7 +++---- .../ArcanistSvnHookPreCommitWorkflow.php | 4 +++- 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/scripts/arcanist.php b/scripts/arcanist.php index 83eebff2..b4de5327 100755 --- a/scripts/arcanist.php +++ b/scripts/arcanist.php @@ -31,6 +31,7 @@ phutil_require_module('arcanist', 'workingcopyidentity'); phutil_require_module('arcanist', 'repository/api/base'); $config_trace_mode = false; +$force_conduit = null; $args = array_slice($argv, 1); $load = array(); $matches = null; @@ -46,6 +47,9 @@ foreach ($args as $key => $arg) { } else if (preg_match('/^--load-phutil-library=(.*)$/', $arg, $matches)) { unset($args[$key]); $load['?'] = $matches[1]; + } else if (preg_match('/^--conduit-uri=(.*)$/', $arg, $matches)) { + unset($args[$key]); + $force_conduit = $matches[1]; } } @@ -135,7 +139,12 @@ try { $set_guid = false; if ($need_conduit) { - $conduit_uri = $working_copy->getConduitURI(); + + if ($force_conduit) { + $conduit_uri = $force_conduit; + } else { + $conduit_uri = $working_copy->getConduitURI(); + } if (!$conduit_uri) { throw new ArcanistUsageException( "No Conduit URI is specified in the .arcconfig file for this project. ". diff --git a/src/workflow/help/ArcanistHelpWorkflow.php b/src/workflow/help/ArcanistHelpWorkflow.php index 4427610d..7ebb9ac3 100644 --- a/src/workflow/help/ArcanistHelpWorkflow.php +++ b/src/workflow/help/ArcanistHelpWorkflow.php @@ -157,6 +157,14 @@ EOTEXT __--no-ansi__ Output in plain ASCII text only, without color or style. + __--load-phutil-library=/path/to/library__ + Ignore libraries listed in .arcconfig and explicitly load specified + libraries instead. Mostly useful for Arcanist development. + + __--conduit-uri=...__ + Ignore configured Conduit URI and use an explicit one instead. Mostly + useful for Arcanist development. + EOTEXT ); diff --git a/src/workflow/mark-committed/ArcanistMarkCommittedWorkflow.php b/src/workflow/mark-committed/ArcanistMarkCommittedWorkflow.php index 97197541..6aa64a53 100644 --- a/src/workflow/mark-committed/ArcanistMarkCommittedWorkflow.php +++ b/src/workflow/mark-committed/ArcanistMarkCommittedWorkflow.php @@ -26,7 +26,7 @@ class ArcanistMarkCommittedWorkflow extends ArcanistBaseWorkflow { to do this; arc commit (svn), arc amend (git) or commit hooks in the master remote repository should do it for you. However, if these mechanisms have failed for some reason you can use this command to - manually change a revision status from "accepted" to "committed". + manually change a revision status from "Accepted" to "Committed". EOTEXT ); } diff --git a/src/workflow/shell-complete/ArcanistShellCompleteWorkflow.php b/src/workflow/shell-complete/ArcanistShellCompleteWorkflow.php index 9ce06663..b2973752 100644 --- a/src/workflow/shell-complete/ArcanistShellCompleteWorkflow.php +++ b/src/workflow/shell-complete/ArcanistShellCompleteWorkflow.php @@ -24,7 +24,6 @@ class ArcanistShellCompleteWorkflow extends ArcanistBaseWorkflow { Supports: bash, etc. Implements shell completion. To use shell completion, source the appropriate script from 'resources/shell/' in your .shellrc. - EOTEXT ); } @@ -123,7 +122,7 @@ EOTEXT } return 0; } else { - + $output = array(); foreach ($arguments as $argument => $spec) { if ($argument == '*') { @@ -136,7 +135,7 @@ EOTEXT } $output[] = '--'.$argument; } - + $cur = idx($argv, $pos, ''); $any_match = false; foreach ($output as $possible) { @@ -144,7 +143,7 @@ EOTEXT $any_match = true; } } - + if (!$any_match && isset($arguments['*'])) { // TODO: the '*' specifier should probably have more details about // whether or not it is a list of files. Since it almost always is in diff --git a/src/workflow/svn-hook-pre-commit/ArcanistSvnHookPreCommitWorkflow.php b/src/workflow/svn-hook-pre-commit/ArcanistSvnHookPreCommitWorkflow.php index 23f85133..398920f6 100644 --- a/src/workflow/svn-hook-pre-commit/ArcanistSvnHookPreCommitWorkflow.php +++ b/src/workflow/svn-hook-pre-commit/ArcanistSvnHookPreCommitWorkflow.php @@ -22,7 +22,9 @@ class ArcanistSvnHookPreCommitWorkflow extends ArcanistBaseWorkflow { return phutil_console_format(<< Date: Sat, 19 Feb 2011 11:36:08 -0800 Subject: [PATCH 2/3] Some documentation. Summary: Test Plan: Reviewers: CC: --- .divinerconfig | 12 ++- scripts/arcanist.php | 2 + scripts/phutil_analyzer.php | 13 ++- src/__phutil_library_map__.php | 2 +- src/configuration/ArcanistConfiguration.php | 22 +++++ src/difference/ArcanistDiffUtils.php | 5 ++ .../ArcanistDifferentialCommitMessage.php | 5 ++ ...fferentialCommitMessageParserException.php | 5 ++ .../ArcanistDifferentialRevisionRef.php | 5 ++ src/docs/arcconfig.diviner | 3 +- ...building_new_configuration_classes.diviner | 83 +++++++++++++++++++ src/docs/overview.diviner | 6 +- src/docs/svn_hooks.diviner | 2 + ...ArcanistChooseInvalidRevisionException.php | 5 ++ .../ArcanistChooseNoRevisionsException.php | 6 ++ .../usage/ArcanistUsageException.php | 6 ++ .../noeffect/ArcanistNoEffectException.php | 6 ++ .../noengine/ArcanistNoEngineException.php | 5 ++ .../userabort/ArcanistUserAbortException.php | 6 ++ src/lint/engine/base/ArcanistLintEngine.php | 5 ++ src/lint/engine/phutil/PhutilLintEngine.php | 5 ++ .../test/UnitTestableArcanistLintEngine.php | 6 ++ .../ArcanistApacheLicenseLinter.php | 5 ++ .../ArcanistApacheLicenseLinterTestCase.php | 5 ++ src/lint/linter/base/ArcanistLinter.php | 5 ++ .../base/test/ArcanistLinterTestCase.php | 5 ++ .../filename/ArcanistFilenameLinter.php | 5 ++ .../generated/ArcanistGeneratedLinter.php | 5 +- .../linter/license/ArcanistLicenseLinter.php | 5 ++ src/lint/linter/pep8/ArcanistPEP8Linter.php | 5 ++ .../ArcanistPhutilModuleLinter.php | 5 ++ src/lint/linter/text/ArcanistTextLinter.php | 5 ++ .../__tests__/ArcanistTextLinterTestCase.php | 5 ++ .../linter/xhpast/ArcanistXHPASTLinter.php | 5 ++ .../ArcanistXHPASTLinterTestCase.php | 5 ++ src/lint/message/ArcanistLintMessage.php | 5 ++ src/lint/patcher/ArcanistLintPatcher.php | 5 ++ src/lint/renderer/ArcanistLintRenderer.php | 5 ++ src/lint/result/ArcanistLintResult.php | 5 ++ src/lint/severity/ArcanistLintSeverity.php | 5 ++ src/parser/bundle/ArcanistBundle.php | 5 ++ src/parser/diff/ArcanistDiffParser.php | 5 ++ .../__tests__/ArcanistDiffParserTestCase.php | 5 ++ src/parser/diff/change/ArcanistDiffChange.php | 5 ++ .../changetype/ArcanistDiffChangeType.php | 5 ++ src/parser/diff/hunk/ArcanistDiffHunk.php | 5 +- .../phutilmodule/PhutilModuleRequirements.php | 5 ++ .../phutilmodule/__init__.php | 0 .../api/base/ArcanistRepositoryAPI.php | 5 ++ src/repository/api/git/ArcanistGitAPI.php | 5 ++ .../api/subversion/ArcanistSubversionAPI.php | 5 ++ .../base/ArcanistBaseUnitTestEngine.php | 5 ++ .../engine/phutil/PhutilUnitTestEngine.php | 5 ++ .../PhutilUnitTestEngineTestCase.php | 5 ++ .../testcase/ArcanistPhutilTestCase.php | 5 ++ .../ArcanistPhutilTestTerminatedException.php | 5 ++ src/unit/result/ArcanistUnitTestResult.php | 5 ++ src/workflow/amend/ArcanistAmendWorkflow.php | 5 ++ src/workflow/base/ArcanistBaseWorkflow.php | 5 ++ .../commit/ArcanistCommitWorkflow.php | 5 ++ src/workflow/cover/ArcanistCoverWorkflow.php | 5 ++ src/workflow/diff/ArcanistDiffWorkflow.php | 5 ++ .../export/ArcanistExportWorkflow.php | 5 ++ .../ArcanistGitHookPreReceiveWorkflow.php | 5 ++ src/workflow/help/ArcanistHelpWorkflow.php | 5 ++ src/workflow/lint/ArcanistLintWorkflow.php | 5 ++ src/workflow/list/ArcanistListWorkflow.php | 5 ++ .../ArcanistMarkCommittedWorkflow.php | 5 ++ src/workflow/patch/ArcanistPatchWorkflow.php | 5 ++ .../ArcanistShellCompleteWorkflow.php | 5 ++ .../ArcanistSvnHookPreCommitWorkflow.php | 5 ++ src/workflow/unit/ArcanistUnitWorkflow.php | 5 ++ src/workflow/unit/__init__.php | 1 + .../ArcanistWorkingCopyIdentity.php | 5 ++ 74 files changed, 451 insertions(+), 15 deletions(-) create mode 100644 src/docs/building_new_configuration_classes.diviner rename src/{staticanalysis/parsers => parser}/phutilmodule/PhutilModuleRequirements.php (98%) rename src/{staticanalysis/parsers => parser}/phutilmodule/__init__.php (100%) diff --git a/.divinerconfig b/.divinerconfig index 11a99d8c..f36ed9c8 100644 --- a/.divinerconfig +++ b/.divinerconfig @@ -3,7 +3,17 @@ "src_base" : "https://github.com/facebook/arcanist/blob/master", "groups" : { "intro" : "Introduction", - "config" : "Setup & Configuration" + "config" : "Setup & Configuration", + "workflow" : "Workflows", + "lint" : "Lint Integration", + "linter" : "Linters", + "unit" : "Unit Test Integration", + "unitrun" : "Unit Test Runners", + "diff" : "Diff and Changeset APIs", + "differential" : "Differential Integration", + "workingcopy" : "Working Copy APIs", + "module" : "Phutil Module System", + "testcase" : "Test Cases" } } diff --git a/scripts/arcanist.php b/scripts/arcanist.php index b4de5327..dfd7309e 100755 --- a/scripts/arcanist.php +++ b/scripts/arcanist.php @@ -30,6 +30,8 @@ phutil_require_module('arcanist', 'configuration'); phutil_require_module('arcanist', 'workingcopyidentity'); phutil_require_module('arcanist', 'repository/api/base'); +ini_set('memory_limit', -1); + $config_trace_mode = false; $force_conduit = null; $args = array_slice($argv, 1); diff --git a/scripts/phutil_analyzer.php b/scripts/phutil_analyzer.php index 3e89ff3d..c5dc4ea1 100755 --- a/scripts/phutil_analyzer.php +++ b/scripts/phutil_analyzer.php @@ -53,7 +53,7 @@ phutil_require_module('phutil', 'parser/xhpast/api/tree'); phutil_require_module('arcanist', 'lint/linter/phutilmodule'); phutil_require_module('arcanist', 'lint/message'); -phutil_require_module('arcanist', 'staticanalysis/parsers/phutilmodule'); +phutil_require_module('arcanist', 'parser/phutilmodule'); $data = array(); @@ -114,7 +114,7 @@ foreach (Futures($futures) as $file => $future) { } $requirements->addSourceDependency($name, $value); } else if ($call_name == 'phutil_require_module') { - analyze_require_module($call, $requirements); + analyze_phutil_require_module($call, $requirements); } } } else { @@ -146,7 +146,7 @@ foreach (Futures($futures) as $file => $future) { $call_name = $name->getConcreteString(); if ($call_name == 'phutil_require_module') { - analyze_require_module($call, $requirements); + analyze_phutil_require_module($call, $requirements); } else if ($call_name == 'call_user_func' || $call_name == 'call_user_func_array') { $params = $call->getChildByIndex(1)->getChildren(); @@ -307,7 +307,12 @@ if (!$has_init && $has_files) { echo json_encode($requirements->toDictionary()); -function analyze_require_module( +/** + * Parses meaning from calls to phutil_require_module() in __init__.php files. + * + * @group module + */ +function analyze_phutil_require_module( XHPASTNode $call, PhutilModuleRequirements $requirements) { diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index d0d784a4..f9fe6907 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -68,7 +68,7 @@ phutil_register_library_map(array( 'ArcanistXHPASTLinter' => 'lint/linter/xhpast', 'ArcanistXHPASTLinterTestCase' => 'lint/linter/xhpast/__tests__', 'PhutilLintEngine' => 'lint/engine/phutil', - 'PhutilModuleRequirements' => 'staticanalysis/parsers/phutilmodule', + 'PhutilModuleRequirements' => 'parser/phutilmodule', 'PhutilUnitTestEngine' => 'unit/engine/phutil', 'PhutilUnitTestEngineTestCase' => 'unit/engine/phutil/__tests__', 'UnitTestableArcanistLintEngine' => 'lint/engine/test', diff --git a/src/configuration/ArcanistConfiguration.php b/src/configuration/ArcanistConfiguration.php index 1f5c2389..64cb22cc 100644 --- a/src/configuration/ArcanistConfiguration.php +++ b/src/configuration/ArcanistConfiguration.php @@ -16,6 +16,28 @@ * limitations under the License. */ +/** + * Runtime workflow configuration. In Arcanist, commands you type like + * "arc diff" or "arc lint" are called "workflows". This class allows you to add + * new workflows (and extend existing workflows) by subclassing it and then + * pointing to your subclass in your project configuration. + * + * For instructions on how to extend this class and customize Arcanist in your + * project, see @{article:Building New Configuration Classes}. + * + * When specified as the **arcanist_configuration** class in your project's + * ##.arcconfig##, your subclass will be instantiated (instead of this class) + * and be able to handle all the method calls. In particular, you can: + * + * - create, replace, or disable workflows by overriding buildWorkflow() + * and buildAllWorkflows(); + * - add additional steps before or after workflows run by overriding + * willRunWorkflow() or didRunWorkflow(); and + * - add new flags to existing workflows by overriding + * getCustomArgumentsForCommand(). + * + * @group config + */ class ArcanistConfiguration { public function buildWorkflow($command) { diff --git a/src/difference/ArcanistDiffUtils.php b/src/difference/ArcanistDiffUtils.php index 9ff4f040..e1534cfb 100644 --- a/src/difference/ArcanistDiffUtils.php +++ b/src/difference/ArcanistDiffUtils.php @@ -16,6 +16,11 @@ * limitations under the License. */ +/** + * Dumping ground for diff- and diff-algorithm-related miscellany. + * + * @group diff + */ final class ArcanistDiffUtils { public static function renderDifferences( diff --git a/src/differential/commitmessage/ArcanistDifferentialCommitMessage.php b/src/differential/commitmessage/ArcanistDifferentialCommitMessage.php index 728397ca..3b0328ef 100644 --- a/src/differential/commitmessage/ArcanistDifferentialCommitMessage.php +++ b/src/differential/commitmessage/ArcanistDifferentialCommitMessage.php @@ -16,6 +16,11 @@ * limitations under the License. */ +/** + * Represents a parsed commit message. + * + * @group differential + */ class ArcanistDifferentialCommitMessage { private $rawCorpus; diff --git a/src/differential/commitmessage/ArcanistDifferentialCommitMessageParserException.php b/src/differential/commitmessage/ArcanistDifferentialCommitMessageParserException.php index 37122995..41ea5cd2 100644 --- a/src/differential/commitmessage/ArcanistDifferentialCommitMessageParserException.php +++ b/src/differential/commitmessage/ArcanistDifferentialCommitMessageParserException.php @@ -16,6 +16,11 @@ * limitations under the License. */ +/** + * Thrown when a commit message isn't parseable. + * + * @group differential + */ class ArcanistDifferentialCommitMessageParserException extends Exception { } diff --git a/src/differential/revision/ArcanistDifferentialRevisionRef.php b/src/differential/revision/ArcanistDifferentialRevisionRef.php index da866c24..8e6c19ff 100644 --- a/src/differential/revision/ArcanistDifferentialRevisionRef.php +++ b/src/differential/revision/ArcanistDifferentialRevisionRef.php @@ -16,6 +16,11 @@ * limitations under the License. */ +/** + * Reference to a Differential revision. + * + * @group differential + */ class ArcanistDifferentialRevisionRef { protected $id; diff --git a/src/docs/arcconfig.diviner b/src/docs/arcconfig.diviner index c7085e4c..0ae197e2 100644 --- a/src/docs/arcconfig.diviner +++ b/src/docs/arcconfig.diviner @@ -1,8 +1,7 @@ @title Setting Up .arcconfig @group config -This document describes how to configure Arcanist projects with ##.arcconfig## -files. +Explains how to configure Arcanist projects with ##.arcconfig## files. = .arcconfig Basics = diff --git a/src/docs/building_new_configuration_classes.diviner b/src/docs/building_new_configuration_classes.diviner new file mode 100644 index 00000000..6fb31617 --- /dev/null +++ b/src/docs/building_new_configuration_classes.diviner @@ -0,0 +1,83 @@ +@title Building New Configuration Classes +@group config + +Explains how to build new classes to control how Arcanist behaves. + += Overview = + +Arcanist has some basic configuration options available in the ##.arcconfig## +file (see @{article:Setting Up .arcconfig}), but it can't handle everything. If +you want to customize Arcanist at a deeper level, you need to build new classes. +For instance: + + - if you want to configure linters, or add new linters, you need to create a + new class which extends @{class:ArcanistLintEngine}. + - if you want to integrate with a unit testing framework, you need to create a + new class which extends @{class:ArcanistBaseUnitTestEngine}. + - if you you want to change how workflows behave, or add new workflows, you + need to create a new class which extends @{class:ArcanistConfiguration}. + +Arcanist works through a sort of dependency-injection approach. For example, +Arcanist does not run lint rules by default, but you can set **lint_engine** +in your ##.arcconfig## to the name of a class which extends +@{class:ArcanistLintEngine}. When running from inside your project, Arcanist +will load this class and call methods on it in order to run lint. To make this +work, you need to do three things: + + - actually write the class; + - add the library where the class exists to your ##.arcconfig##; + - add the class name to your ##.arcconfig## as the **lint_engine**, + **unit_engine**, or **arcanist_configuration**. + += Write the Class = + +(TODO) + += Load the Class = + +To make the class loadable, you need to put the path to it in your +##.arcconfig##, under **phutil_libraries**: + + { + // ... + "phutil_libraries" : { + // ... + "my-library" : "/path/to/my/library", + // ... + } + // ... + } + +You can either specify an absolute path, or a path relative to the project root. +When you run ##arc --trace##, you should see a message to the effect that it has +loaded your library. + +For debugging or testing, you can also run Arcanist with the +##--load-phutil-library## flag: + + arc --load-phutil-library=/path/to/library + +You can specify this flag more than once to load several libraries. Note that +if you use this flag, Arcanist will ignore any libraries listed in +##.arcconfig##. + += Use the Class = + +This step is easy: just edit ##.arcconfig## to specify your class name as +the appropriate configuration value. + + { + // ... + "lint_engine" : "MyCustomArcanistLintEngine", + // ... + } + +Now, when you run Arcanist in your project, it will invoke your class when +appropriate. + +For lint and unit tests, you can also use the ##--engine## flag override the +default engine: + + arc lint --engine MyCustomArcanistLintEngine + +This is mostly useful for debugging and testing. diff --git a/src/docs/overview.diviner b/src/docs/overview.diviner index 0bc22578..f785ad97 100644 --- a/src/docs/overview.diviner +++ b/src/docs/overview.diviner @@ -1,10 +1,10 @@ @title Arcanist Overview @group intro -This document provides an overview of Arcanist, a code workflow tool. Arcanist -(commonly, "arc") is the command-line frontend to Differential. +Overview of Arcanist, a code workflow tool. -A detailed command reference is available by running ##arc help##. +Arcanist (commonly, "arc") is the command-line frontend to Differential. A +detailed command reference is available by running ##arc help##. = Overview = diff --git a/src/docs/svn_hooks.diviner b/src/docs/svn_hooks.diviner index 3605299f..27c4d908 100644 --- a/src/docs/svn_hooks.diviner +++ b/src/docs/svn_hooks.diviner @@ -1,6 +1,8 @@ @title Installing Arcanist SVN Hooks @group config +Describes how to set up Arcanist as an SVN pre-commit hook. + = Installing Arcanist SVN Hooks = You can install Arcanist as an SVN pre-commit hook, to reject commits which diff --git a/src/exception/ArcanistChooseInvalidRevisionException.php b/src/exception/ArcanistChooseInvalidRevisionException.php index 85664e25..f49558d3 100644 --- a/src/exception/ArcanistChooseInvalidRevisionException.php +++ b/src/exception/ArcanistChooseInvalidRevisionException.php @@ -16,6 +16,11 @@ * limitations under the License. */ +/** + * Thrown when the user chooses an invalid revision when prompted by a workflow. + * + * @group workflow + */ class ArcanistChooseInvalidRevisionException extends Exception { } diff --git a/src/exception/ArcanistChooseNoRevisionsException.php b/src/exception/ArcanistChooseNoRevisionsException.php index 95842572..cc8d1a73 100644 --- a/src/exception/ArcanistChooseNoRevisionsException.php +++ b/src/exception/ArcanistChooseNoRevisionsException.php @@ -16,6 +16,12 @@ * limitations under the License. */ +/** + * Thrown when there are no valid revisions to choose from, in a workflow which + * prompts the user to choose a revision. + * + * @group workflow + */ class ArcanistChooseNoRevisionsException extends Exception { } diff --git a/src/exception/usage/ArcanistUsageException.php b/src/exception/usage/ArcanistUsageException.php index b2054dbe..1948c69b 100644 --- a/src/exception/usage/ArcanistUsageException.php +++ b/src/exception/usage/ArcanistUsageException.php @@ -16,6 +16,12 @@ * limitations under the License. */ +/** + * Thrown when there is a problem with how a user is invoking a command, rather + * than a technical problem. + * + * @group workflow + */ class ArcanistUsageException extends Exception { } diff --git a/src/exception/usage/noeffect/ArcanistNoEffectException.php b/src/exception/usage/noeffect/ArcanistNoEffectException.php index 4324fb35..fed8371e 100644 --- a/src/exception/usage/noeffect/ArcanistNoEffectException.php +++ b/src/exception/usage/noeffect/ArcanistNoEffectException.php @@ -16,5 +16,11 @@ * limitations under the License. */ +/** + * Thrown when lint or unit tests have no effect, i.e. no paths are affected + * by any linter or no unit tests provide coverage. + * + * @group workflow + */ class ArcanistNoEffectException extends ArcanistUsageException { } diff --git a/src/exception/usage/noengine/ArcanistNoEngineException.php b/src/exception/usage/noengine/ArcanistNoEngineException.php index 416963ce..5a118af9 100644 --- a/src/exception/usage/noengine/ArcanistNoEngineException.php +++ b/src/exception/usage/noengine/ArcanistNoEngineException.php @@ -16,5 +16,10 @@ * limitations under the License. */ +/** + * Thrown when no engine is configured for linting or running unit tests. + * + * @group workflow + */ class ArcanistNoEngineException extends ArcanistUsageException { } diff --git a/src/exception/usage/userabort/ArcanistUserAbortException.php b/src/exception/usage/userabort/ArcanistUserAbortException.php index a22ccd08..43b6c05f 100644 --- a/src/exception/usage/userabort/ArcanistUserAbortException.php +++ b/src/exception/usage/userabort/ArcanistUserAbortException.php @@ -16,6 +16,12 @@ * limitations under the License. */ +/** + * Thrown when the user chooses not to continue when warned that they're about + * to do something dangerous. + * + * @group workflow + */ class ArcanistUserAbortException extends ArcanistUsageException { public function __construct() { parent::__construct('User aborted the workflow.'); diff --git a/src/lint/engine/base/ArcanistLintEngine.php b/src/lint/engine/base/ArcanistLintEngine.php index 2f4071b3..7d51b603 100644 --- a/src/lint/engine/base/ArcanistLintEngine.php +++ b/src/lint/engine/base/ArcanistLintEngine.php @@ -16,6 +16,11 @@ * limitations under the License. */ +/** + * Manages lint execution. + * + * @group lint + */ abstract class ArcanistLintEngine { protected $workingCopy; diff --git a/src/lint/engine/phutil/PhutilLintEngine.php b/src/lint/engine/phutil/PhutilLintEngine.php index d393c8c9..d923c166 100644 --- a/src/lint/engine/phutil/PhutilLintEngine.php +++ b/src/lint/engine/phutil/PhutilLintEngine.php @@ -16,6 +16,11 @@ * limitations under the License. */ +/** + * Lint engine which enforces libphutil rules. + * + * @group linter + */ class PhutilLintEngine extends ArcanistLintEngine { public function buildLinters() { diff --git a/src/lint/engine/test/UnitTestableArcanistLintEngine.php b/src/lint/engine/test/UnitTestableArcanistLintEngine.php index 84246d8b..cbb71bec 100644 --- a/src/lint/engine/test/UnitTestableArcanistLintEngine.php +++ b/src/lint/engine/test/UnitTestableArcanistLintEngine.php @@ -16,6 +16,12 @@ * limitations under the License. */ +/** + * Lint engine for use in constructing test cases. See + * @{class:ArcanistLinterTestCase}. + * + * @group testcase + */ final class UnitTestableArcanistLintEngine extends ArcanistLintEngine { protected $linters = array(); diff --git a/src/lint/linter/apachelicense/ArcanistApacheLicenseLinter.php b/src/lint/linter/apachelicense/ArcanistApacheLicenseLinter.php index 3029b3b4..f150572a 100644 --- a/src/lint/linter/apachelicense/ArcanistApacheLicenseLinter.php +++ b/src/lint/linter/apachelicense/ArcanistApacheLicenseLinter.php @@ -16,6 +16,11 @@ * limitations under the License. */ +/** + * Adds the Apache license to source files. + * + * @group linter + */ class ArcanistApacheLicenseLinter extends ArcanistLicenseLinter { public function getLinterName() { return 'APACHELICENSE'; diff --git a/src/lint/linter/apachelicense/__tests__/ArcanistApacheLicenseLinterTestCase.php b/src/lint/linter/apachelicense/__tests__/ArcanistApacheLicenseLinterTestCase.php index 96643aea..9015e2e2 100644 --- a/src/lint/linter/apachelicense/__tests__/ArcanistApacheLicenseLinterTestCase.php +++ b/src/lint/linter/apachelicense/__tests__/ArcanistApacheLicenseLinterTestCase.php @@ -16,6 +16,11 @@ * limitations under the License. */ +/** + * Test cases for @{class:ArcanistApacheLicenseLinter}. + * + * @group testcase + */ class ArcanistApacheLicenseLinterTestCase extends ArcanistLinterTestCase { public function testApacheLicenseLint() { diff --git a/src/lint/linter/base/ArcanistLinter.php b/src/lint/linter/base/ArcanistLinter.php index 4474418b..b704c41d 100644 --- a/src/lint/linter/base/ArcanistLinter.php +++ b/src/lint/linter/base/ArcanistLinter.php @@ -16,6 +16,11 @@ * limitations under the License. */ +/** + * Implements lint rules, like syntax checks for a specific language. + * + * @group linter + */ abstract class ArcanistLinter { protected $paths = array(); diff --git a/src/lint/linter/base/test/ArcanistLinterTestCase.php b/src/lint/linter/base/test/ArcanistLinterTestCase.php index 8b02bdf1..0a4bff4a 100644 --- a/src/lint/linter/base/test/ArcanistLinterTestCase.php +++ b/src/lint/linter/base/test/ArcanistLinterTestCase.php @@ -16,6 +16,11 @@ * limitations under the License. */ +/** + * Facilitiates implementation of test cases for @{class:ArcanistLinter}s. + * + * @group testcase + */ abstract class ArcanistLinterTestCase extends ArcanistPhutilTestCase { public function executeTestsInDirectory($root, $linter, $working_copy) { diff --git a/src/lint/linter/filename/ArcanistFilenameLinter.php b/src/lint/linter/filename/ArcanistFilenameLinter.php index bd5659c6..f5630c03 100644 --- a/src/lint/linter/filename/ArcanistFilenameLinter.php +++ b/src/lint/linter/filename/ArcanistFilenameLinter.php @@ -16,6 +16,11 @@ * limitations under the License. */ +/** + * Stifles creativity in choosing imaginative file names. + * + * @group linter + */ class ArcanistFilenameLinter extends ArcanistLinter { const LINT_BAD_FILENAME = 1; diff --git a/src/lint/linter/generated/ArcanistGeneratedLinter.php b/src/lint/linter/generated/ArcanistGeneratedLinter.php index 15116302..db739091 100644 --- a/src/lint/linter/generated/ArcanistGeneratedLinter.php +++ b/src/lint/linter/generated/ArcanistGeneratedLinter.php @@ -1,8 +1,9 @@ Date: Sat, 19 Feb 2011 22:07:12 -0800 Subject: [PATCH 3/3] Partially restore --edit to stop it from stomping all over everything. Summary: We sync from local right now, which is fairly terrible. But fixing this correctly is also not trivial and I don't have the right primitives yet. Test Plan: Reviewers: CC: --- .../ArcanistDifferentialCommitMessage.php | 12 +++++ src/workflow/diff/ArcanistDiffWorkflow.php | 44 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/differential/commitmessage/ArcanistDifferentialCommitMessage.php b/src/differential/commitmessage/ArcanistDifferentialCommitMessage.php index 3b0328ef..04a188cb 100644 --- a/src/differential/commitmessage/ArcanistDifferentialCommitMessage.php +++ b/src/differential/commitmessage/ArcanistDifferentialCommitMessage.php @@ -80,6 +80,11 @@ class ArcanistDifferentialCommitMessage { return null; } + public function setFieldValue($key, $value) { + $this->fields[$key] = $value; + return $this; + } + public function getFields() { return $this->fields; } @@ -96,4 +101,11 @@ class ArcanistDifferentialCommitMessage { return $this->gitSVNUUID; } + public function getChecksum() { + $fields = array_filter($this->fields); + ksort($fields); + $fields = json_encode($fields); + return md5($fields); + } + } diff --git a/src/workflow/diff/ArcanistDiffWorkflow.php b/src/workflow/diff/ArcanistDiffWorkflow.php index 1b4bb42b..f31d6279 100644 --- a/src/workflow/diff/ArcanistDiffWorkflow.php +++ b/src/workflow/diff/ArcanistDiffWorkflow.php @@ -328,6 +328,50 @@ EOTEXT ); if ($message->getRevisionID()) { + // TODO: This is silly -- we're getting a text corpus from the server + // and then sending it right back to be parsed. This should be a + // single call. + $remote_corpus = $conduit->callMethodSynchronous( + 'differential.getcommitmessage', + array( + 'revision_id' => $message->getRevisionID(), + )); + $remote_message = ArcanistDifferentialCommitMessage::newFromRawCorpus( + $remote_corpus); + $remote_message->pullDataFromConduit($conduit); + + // TODO: We should throw here if you deleted the 'testPlan'. + + $sync = array('title', 'summary', 'testPlan'); + foreach ($sync as $field) { + $local = $message->getFieldValue($field); + $remote_message->setFieldValue($field, $local); + } + + $should_edit = $this->getArgument('edit'); + if (!$should_edit) { + $local_sum = $message->getChecksum(); + $remote_sum = $remote_message->getChecksum(); + if ($local_sum != $remote_sum) { + $prompt = + "You have made local changes to your commit message. Arcanist ". + "ignores most local changes. Instead, use the '--edit' flag to ". + "edit revision information. Edit revision information now?"; + $should_edit = phutil_console_confirm( + $prompt, + $default_no = false); + } + } + + if ($should_edit) { + // TODO: lol. But we need differential.unparsecommitmessage or + // something. + throw new ArcanistUsageException( + '--edit is not supported yet. Edit revisions from the web '. + 'UI.'); + } + + $revision['fields'] = $remote_message->getFields(); $update_message = $this->getUpdateMessage();