mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-25 08:12:40 +01:00
Add bin/repository edit
for CLI repository editing
Summary: Ref T4039. This is mostly to deal with that, to prevent the security issues associated with mutable local paths. The next diff will lock them in the web UI. I also added a confirmation prompt to `bin/repository delete`, which was a little scary without one. See one comment inline about the `--as` flag. I don't love this, but when I started adding all the stuff we'd need to let this transaction show up as "Administrator" it quickly got pretty big. Test Plan: Ran `bin/repository edit ...`, saw an edit with a transaction show up on the web UI. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T4039 Differential Revision: https://secure.phabricator.com/D7579
This commit is contained in:
parent
626b3dab3b
commit
f5ca647d2c
5 changed files with 128 additions and 1 deletions
|
@ -18,6 +18,7 @@ $args->parseStandardArguments();
|
|||
$workflows = array(
|
||||
new PhabricatorRepositoryManagementPullWorkflow(),
|
||||
new PhabricatorRepositoryManagementDiscoverWorkflow(),
|
||||
new PhabricatorRepositoryManagementEditWorkflow(),
|
||||
new PhabricatorRepositoryManagementListWorkflow(),
|
||||
new PhabricatorRepositoryManagementDeleteWorkflow(),
|
||||
new PhabricatorRepositoryManagementMarkImportedWorkflow(),
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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'),
|
||||
);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorRepositoryManagementEditWorkflow
|
||||
extends PhabricatorRepositoryManagementWorkflow {
|
||||
|
||||
public function didConstruct() {
|
||||
$this
|
||||
->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 <username>."));
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue