diff --git a/scripts/repository/manage_repositories.php b/scripts/repository/manage_repositories.php index 359186f9dd..4f7131d112 100755 --- a/scripts/repository/manage_repositories.php +++ b/scripts/repository/manage_repositories.php @@ -18,6 +18,7 @@ $args->parseStandardArguments(); $workflows = array( new PhabricatorRepositoryManagementPullWorkflow(), new PhabricatorRepositoryManagementDiscoverWorkflow(), + new PhabricatorRepositoryManagementEditWorkflow(), new PhabricatorRepositoryManagementListWorkflow(), new PhabricatorRepositoryManagementDeleteWorkflow(), new PhabricatorRepositoryManagementMarkImportedWorkflow(), diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index abb8fe9348..2ede86787e 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1731,6 +1731,7 @@ phutil_register_library_map(array( 'PhabricatorRepositoryListController' => 'applications/repository/controller/PhabricatorRepositoryListController.php', 'PhabricatorRepositoryManagementDeleteWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDeleteWorkflow.php', 'PhabricatorRepositoryManagementDiscoverWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDiscoverWorkflow.php', + 'PhabricatorRepositoryManagementEditWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementEditWorkflow.php', 'PhabricatorRepositoryManagementImportingWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementImportingWorkflow.php', 'PhabricatorRepositoryManagementListWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListWorkflow.php', 'PhabricatorRepositoryManagementMarkImportedWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMarkImportedWorkflow.php', @@ -4174,6 +4175,7 @@ phutil_register_library_map(array( 'PhabricatorRepositoryListController' => 'PhabricatorRepositoryController', 'PhabricatorRepositoryManagementDeleteWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementDiscoverWorkflow' => 'PhabricatorRepositoryManagementWorkflow', + 'PhabricatorRepositoryManagementEditWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementImportingWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementListWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementMarkImportedWorkflow' => 'PhabricatorRepositoryManagementWorkflow', diff --git a/src/applications/metamta/contentsource/PhabricatorContentSource.php b/src/applications/metamta/contentsource/PhabricatorContentSource.php index 21d2caa0e4..8c062ba880 100644 --- a/src/applications/metamta/contentsource/PhabricatorContentSource.php +++ b/src/applications/metamta/contentsource/PhabricatorContentSource.php @@ -9,6 +9,7 @@ final class PhabricatorContentSource { const SOURCE_MOBILE = 'mobile'; const SOURCE_TABLET = 'tablet'; const SOURCE_FAX = 'fax'; + const SOURCE_CONSOLE = 'console'; const SOURCE_LEGACY = 'legacy'; private $source; @@ -39,6 +40,12 @@ final class PhabricatorContentSource { return $obj; } + public static function newConsoleSource() { + return self::newForSource( + PhabricatorContentSource::SOURCE_CONSOLE, + array()); + } + public static function newFromRequest(AphrontRequest $request) { return self::newForSource( PhabricatorContentSource::SOURCE_WEB, @@ -61,6 +68,7 @@ final class PhabricatorContentSource { self::SOURCE_MOBILE => pht('Mobile'), self::SOURCE_TABLET => pht('Tablet'), self::SOURCE_FAX => pht('Fax'), + self::SOURCE_CONSOLE => pht('Console'), self::SOURCE_LEGACY => pht('Legacy'), self::SOURCE_UNKNOWN => pht('Other'), ); diff --git a/src/applications/repository/management/PhabricatorRepositoryManagementDeleteWorkflow.php b/src/applications/repository/management/PhabricatorRepositoryManagementDeleteWorkflow.php index 111bd6e100..dd97df8d55 100644 --- a/src/applications/repository/management/PhabricatorRepositoryManagementDeleteWorkflow.php +++ b/src/applications/repository/management/PhabricatorRepositoryManagementDeleteWorkflow.php @@ -14,6 +14,10 @@ final class PhabricatorRepositoryManagementDeleteWorkflow 'name' => 'verbose', 'help' => 'Show additional debugging information.', ), + array( + 'name' => 'force', + 'help' => 'Do not prompt for confirmation.', + ), array( 'name' => 'repos', 'wildcard' => true, @@ -30,9 +34,25 @@ final class PhabricatorRepositoryManagementDeleteWorkflow } $console = PhutilConsole::getConsole(); + + if (!$args->getArg('force')) { + $console->writeOut("%s\n\n", pht('These repositories will be deleted:')); + + foreach ($repos as $repo) { + $console->writeOut( + " %s %s\n", + 'r'.$repo->getCallsign(), + $repo->getName()); + } + + $prompt = pht('Permanently delete these repositories?'); + if (!$console->confirm($prompt)) { + return 1; + } + } + foreach ($repos as $repo) { $console->writeOut("Deleting '%s'...\n", $repo->getCallsign()); - $repo->delete(); } diff --git a/src/applications/repository/management/PhabricatorRepositoryManagementEditWorkflow.php b/src/applications/repository/management/PhabricatorRepositoryManagementEditWorkflow.php new file mode 100644 index 0000000000..4225fe481b --- /dev/null +++ b/src/applications/repository/management/PhabricatorRepositoryManagementEditWorkflow.php @@ -0,0 +1,96 @@ +setName('edit') + ->setExamples('**edit** --as __username__ __repository__ ...') + ->setSynopsis('Edit __repository__, named by callsign.') + ->setArguments( + array( + array( + 'name' => 'repos', + 'wildcard' => true, + ), + array( + 'name' => 'as', + 'param' => 'user', + 'help' => 'Edit as user.', + ), + array( + 'name' => 'local-path', + 'param' => 'path', + 'help' => 'Edit the local path.', + ), + )); + } + + public function execute(PhutilArgumentParser $args) { + $repos = $this->loadRepositories($args, 'repos'); + + if (!$repos) { + throw new PhutilArgumentUsageException( + "Specify one or more repositories to edit, by callsign."); + } + + $console = PhutilConsole::getConsole(); + + // TODO: It would be nice to just take this action as "Administrator" or + // similar, since that would make it easier to use this script, harder to + // impersonate users, and more clear to viewers what happened. However, + // the omnipotent user doesn't have a PHID right now, can't be loaded, + // doesn't have a handle, etc. Adding all of that is fairly involved, and + // I want to wait for stronger use cases first. + + $username = $args->getArg('as'); + if (!$username) { + throw new PhutilArgumentUsageException( + pht("Specify a user to edit as with --as .")); + } + + $actor = id(new PhabricatorPeopleQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withUsernames(array($username)) + ->executeOne(); + + if (!$actor) { + throw new PhutilArgumentUsageException( + pht("No such user '%s'!", $username)); + } + + foreach ($repos as $repo) { + $console->writeOut("Editing '%s'...\n", $repo->getCallsign()); + + $xactions = array(); + + $type_local_path = PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH; + + if ($args->getArg('local-path')) { + $xactions[] = id(new PhabricatorRepositoryTransaction()) + ->setTransactionType($type_local_path) + ->setNewValue($args->getArg('local-path')); + } + + if (!$xactions) { + throw new PhutilArgumentUsageException( + pht("Specify one or more fields to edit!")); + } + + $content_source = PhabricatorContentSource::newConsoleSource(); + + $editor = id(new PhabricatorRepositoryEditor()) + ->setActor($actor) + ->setContentSource($content_source) + ->setContinueOnNoEffect(true) + ->setContinueOnMissingFields(true) + ->applyTransactions($repo, $xactions); + } + + $console->writeOut("Done.\n"); + + return 0; + } + +}