diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1205,7 +1205,7 @@ 'ArcanistLanguageConstructParenthesesXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistLesscLinter' => 'ArcanistExternalLinter', 'ArcanistLesscLinterTestCase' => 'ArcanistExternalLinterTestCase', - 'ArcanistLiberateWorkflow' => 'ArcanistWorkflow', + 'ArcanistLiberateWorkflow' => 'ArcanistArcWorkflow', 'ArcanistLintEngine' => 'Phobject', 'ArcanistLintMessage' => 'Phobject', 'ArcanistLintMessageTestCase' => 'PhutilTestCase', diff --git a/src/toolset/workflow/ArcanistArcWorkflow.php b/src/toolset/workflow/ArcanistArcWorkflow.php --- a/src/toolset/workflow/ArcanistArcWorkflow.php +++ b/src/toolset/workflow/ArcanistArcWorkflow.php @@ -5,7 +5,7 @@ public function supportsToolset(ArcanistToolset $toolset) { $key = $toolset->getToolsetKey(); - return ($key === 'arc'); + return ($key === ArcanistArcToolset::TOOLSETKEY); } } diff --git a/src/workflow/ArcanistLiberateWorkflow.php b/src/workflow/ArcanistLiberateWorkflow.php --- a/src/workflow/ArcanistLiberateWorkflow.php +++ b/src/workflow/ArcanistLiberateWorkflow.php @@ -1,141 +1,106 @@ newWorkflowInformation() + ->addExample(pht('**liberate**')) + ->addExample(pht('**liberate** [__path__]')) + ->setHelp($help); } - public function getArguments() { + public function getWorkflowArguments() { return array( - 'all' => array( - 'help' => pht( - 'Drop the module cache before liberating. This will completely '. - 'reanalyze the entire library. Thorough, but slow!'), - ), - 'force-update' => array( - 'help' => pht( - 'Force the library map to be updated, even in the presence of '. - 'lint errors.'), - ), - 'library-name' => array( - 'param' => 'name', - 'help' => - pht('Use a flag for library name rather than awaiting user input.'), - ), - 'remap' => array( - 'hide' => true, - 'help' => pht( - 'Internal. Run the remap step of liberation. You do not need to '. - 'run this unless you are debugging the workflow.'), - ), - 'verify' => array( - 'hide' => true, - 'help' => pht( - 'Internal. Run the verify step of liberation. You do not need to '. - 'run this unless you are debugging the workflow.'), - ), - 'upgrade' => array( - 'hide' => true, - 'help' => pht('Experimental. Upgrade library to v2.'), - ), - '*' => 'argv', + $this->newWorkflowArgument('clean') + ->setHelp( + pht('Perform a clean rebuild, ignoring caches. Thorough, but slow.')), + $this->newWorkflowArgument('argv') + ->setWildcard(true), ); } - public function run() { + public function runWorkflow() { + $log = $this->getLogEngine(); + $argv = $this->getArgument('argv'); if (count($argv) > 1) { throw new ArcanistUsageException( pht( - "Provide only one path to '%s'. The path should be a directory ". - "where you want to create or update a libphutil library.", - 'arc liberate')); - } else if (count($argv) == 0) { - $path = getcwd(); - } else { - $path = reset($argv); - } - - $is_remap = $this->getArgument('remap'); - $is_verify = $this->getArgument('verify'); - - $path = Filesystem::resolvePath($path); - - if (Filesystem::pathExists($path) && is_dir($path)) { - $init = id(new FileFinder($path)) + 'Provide only one path to "arc liberate". The path should identify '. + 'a directory where you want to create or update a library.')); + } else if (!$argv) { + $log->writeStatus( + pht('SCAN'), + pht('Searching for libraries in the current working directory...')); + + $init_files = id(new FileFinder(getcwd())) ->withPath('*/__phutil_library_init__.php') ->find(); - } else { - $init = null; - } - if ($init) { - if (count($init) > 1) { + if (!$init_files) { throw new ArcanistUsageException( pht( - 'Specified directory contains more than one libphutil library. '. - 'Use a more specific path.')); - } - $path = Filesystem::resolvePath(dirname(reset($init)), $path); - } else { - $found = false; - foreach (Filesystem::walkToRoot($path) as $dir) { - if (Filesystem::pathExists($dir.'/__phutil_library_init__.php')) { - $path = $dir; - $found = true; - break; - } + 'Unable to find any libraries under the current working '. + 'directory. To create a library, provide a path.')); } - if (!$found) { - echo pht("No library currently exists at that path...\n"); - $this->liberateCreateDirectory($path); - $this->liberateCreateLibrary($path); - return; + + $paths = array(); + foreach ($init_files as $init) { + $paths[] = Filesystem::resolvePath(dirname($init)); } + } else { + $paths = array( + Filesystem::resolvePath(head($argv)), + ); + } + + foreach ($paths as $path) { + $log->writeStatus( + pht('WORK'), + pht( + 'Updating library: %s', + Filesystem::readablePath($path).DIRECTORY_SEPARATOR)); + $this->liberatePath($path); + } + + $log->writeSuccess( + pht('DONE'), + pht('Updated %s librarie(s).', phutil_count($paths))); + + return 0; + } + + private function liberatePath($path) { + if (!Filesystem::pathExists($path.'/__phutil_library_init__.php')) { + echo tsprintf( + "%s\n", + pht( + 'No library currently exists at the path "%s"...', + $path)); + $this->liberateCreateDirectory($path); + $this->liberateCreateLibrary($path); + return; } $version = $this->getLibraryFormatVersion($path); switch ($version) { case 1: - if ($this->getArgument('upgrade')) { - return $this->upgradeLibrary($path); - } throw new ArcanistUsageException( pht( - "This library is using libphutil v1, which is no ". - "longer supported. Run '%s' to upgrade to v2.", - 'arc liberate --upgrade')); + 'This very old library is no longer supported.')); case 2: - if ($this->getArgument('upgrade')) { - throw new ArcanistUsageException( - pht("Can't upgrade a v2 library!")); - } return $this->liberateVersion2($path); default: throw new ArcanistUsageException( @@ -166,32 +131,17 @@ $bin = $this->getScriptPath('support/lib/rebuild-map.php'); $argv = array(); - if ($this->getArgument('all')) { + if ($this->getArgument('clean')) { $argv[] = '--drop-cache'; } return phutil_passthru( - 'php -f %s -- %Ls %s', + 'php -f %R -- %Ls %R', $bin, $argv, $path); } - private function upgradeLibrary($path) { - $inits = id(new FileFinder($path)) - ->withPath('*/__init__.php') - ->withType('f') - ->find(); - - echo pht('Removing %s files...', '__init__.php')."\n"; - foreach ($inits as $init) { - Filesystem::remove($path.'/'.$init); - } - - echo pht('Upgrading library to v2...')."\n"; - $this->liberateVersion2($path); - } - private function liberateCreateDirectory($path) { if (Filesystem::pathExists($path)) { if (!is_dir($path)) { @@ -204,10 +154,10 @@ echo pht("The directory '%s' does not exist.", $path); if (!phutil_console_confirm(pht('Do you want to create it?'))) { - throw new ArcanistUsageException(pht('Canceled.')); + throw new ArcanistUsageException(pht('Cancelled.')); } - execx('mkdir -p %s', $path); + execx('mkdir -p %R', $path); } private function liberateCreateLibrary($path) { @@ -219,14 +169,10 @@ echo pht("Creating new libphutil library in '%s'.", $path)."\n"; do { - $name = $this->getArgument('library-name'); - if ($name === null) { - echo pht('Choose a name for the new library.')."\n"; - $name = phutil_console_prompt( - pht('What do you want to name this library?')); - } else { - echo pht('Using library name %s.', $name)."\n"; - } + echo pht('Choose a name for the new library.')."\n"; + $name = phutil_console_prompt( + pht('What do you want to name this library?')); + if (preg_match('/^[a-z-]+$/', $name)) { break; } else { diff --git a/src/workflow/ArcanistWorkflow.php b/src/workflow/ArcanistWorkflow.php --- a/src/workflow/ArcanistWorkflow.php +++ b/src/workflow/ArcanistWorkflow.php @@ -115,6 +115,86 @@ return $this->configurationSourceList; } + public function newPhutilWorkflow() { + $arguments = $this->getWorkflowArguments(); + assert_instances_of($arguments, 'ArcanistWorkflowArgument'); + + $specs = mpull($arguments, 'getPhutilSpecification'); + + $phutil_workflow = id(new ArcanistPhutilWorkflow()) + ->setName($this->getWorkflowName()) + ->setWorkflow($this) + ->setArguments($specs); + + $information = $this->getWorkflowInformation(); + if ($information) { + + $examples = $information->getExamples(); + if ($examples) { + $examples = implode("\n", $examples); + $phutil_workflow->setExamples($examples); + } + + $help = $information->getHelp(); + if (strlen($help)) { + // Unwrap linebreaks in the help text so we don't get weird formatting. + $help = preg_replace("/(?<=\S)\n(?=\S)/", ' ', $help); + + $phutil_workflow->setHelp($help); + } + + } + + return $phutil_workflow; + } + + final protected function newWorkflowArgument($key) { + return id(new ArcanistWorkflowArgument()) + ->setKey($key); + } + + final protected function newWorkflowInformation() { + return new ArcanistWorkflowInformation(); + } + + final public function executeWorkflow(PhutilArgumentParser $args) { + $runtime = $this->getRuntime(); + + $this->arguments = $args; + $caught = null; + + $runtime->pushWorkflow($this); + + try { + $err = $this->runWorkflow($args); + } catch (Exception $ex) { + $caught = $ex; + } + + try { + $this->runWorkflowCleanup(); + } catch (Exception $ex) { + phlog($ex); + } + + $runtime->popWorkflow(); + + if ($caught) { + throw $caught; + } + + return $err; + } + + final protected function getLogEngine() { + return $this->getRuntime()->getLogEngine(); + } + + protected function runWorkflowCleanup() { + // TOOLSETS: Do we need this? + return; + } + public function __construct() {} public function run() { @@ -662,7 +742,12 @@ } final public function getArgument($key, $default = null) { - return idx($this->arguments, $key, $default); + // TOOLSETS: Remove this legacy code. + if (is_array($this->arguments)) { + return idx($this->arguments, $key, $default); + } + + return $this->arguments->getArg($key); } final public function getPassedArguments() {