diff --git a/scripts/differential/destroy_revision.php b/scripts/differential/destroy_revision.php index 0752dd30f4..95fe0a0034 100755 --- a/scripts/differential/destroy_revision.php +++ b/scripts/differential/destroy_revision.php @@ -1,68 +1,68 @@ #!/usr/bin/env php setTagline('permanently destroy a Differential Revision'); $args->setSynopsis(<<parseStandardArguments(); $args->parse( array( array( 'name' => 'revision', 'wildcard' => true, ), )); $revisions = $args->getArg('revision'); if (count($revisions) != 1) { $args->printHelpAndExit(); } $id = trim(strtolower(head($revisions)), 'd '); $revision = id(new DifferentialRevision())->load($id); -if (!$id) { +if (!$revision) { throw new Exception("No revision '{$id}' exists!"); } $title = $revision->getTitle(); $ok = phutil_console_confirm("Really destroy 'D{$id}: {$title}' forever?"); if (!$ok) { throw new Exception("User aborted workflow."); } $revision->delete(); echo "OK, destroyed revision.\n"; diff --git a/scripts/repository/reparse.php b/scripts/repository/reparse.php index 15039bae05..192ade758a 100755 --- a/scripts/repository/reparse.php +++ b/scripts/repository/reparse.php @@ -1,263 +1,251 @@ #!/usr/bin/env php setSynopsis(<<parseStandardArguments(); +$args->parse( + array( + // what + array( + 'name' => 'revision', + 'wildcard' => true, + ), + array( + 'name' => 'all', + 'param' => 'callsign or phid', + 'help' => 'Reparse all commits in the specified repository. This '. + 'mode queues parsers into the task queue; you must run '. + 'taskmasters to actually do the parses. Use with '. + '__--force-local__ to run the tasks locally instead of '. + 'with taskmasters.', + ), + array( + 'name' => 'min-date', + 'param' => 'date', + 'help' => 'When used with __--all__, this will restrict to '. + 'reparsing only the commits that are newer than __date__.', + ), + // which parts + array( + 'name' => 'message', + 'help' => 'Reparse commit messages.', + ), + array( + 'name' => 'change', + 'help' => 'Reparse changes.', + ), + array( + 'name' => 'herald', + 'help' => 'Reevaluate Herald rules (may send huge amounts of email!)', + ), + array( + 'name' => 'owners', + 'help' => 'Reevaluate related commits for owners packages (may '. + 'delete existing relationship entries between your '. + 'package and some old commits!)', + ), + // misc options + array( + 'name' => 'force', + 'short' => 'f', + 'help' => 'Act noninteractively, without prompting.', + ), + array( + 'name' => 'force-local', + 'help' => 'Only used with __--all__, use this to run the tasks '. + 'locally instead of deferring them to taskmaster daemons.', + ), + )); + +$all_from_repo = $args->getArg('all'); +$reparse_message = $args->getArg('message'); +$reparse_change = $args->getArg('change'); +$reparse_herald = $args->getArg('herald'); +$reparse_owners = $args->getArg('owners'); +$reparse_what = $args->getArg('revision'); +$force = $args->getArg('force'); +$force_local = $args->getArg('force-local'); +$min_date = $args->getArg('min-date'); + +if (count($reparse_what) > 1 || !($all_from_repo xor count($reparse_what))) { + usage("Specify a commit or repository to reparse."); } -if (!$reparse_what) { - usage("Specify a commit or repository to reparse."); +if ($args->getArg('trace')) { + PhutilServiceProfiler::installEchoListener(); } + if (!$reparse_message && !$reparse_change && !$reparse_herald && !$reparse_owners) { usage("Specify what information to reparse with --message, --change, ". "--herald, and/or --owners"); } if ($reparse_owners && !$force) { echo phutil_console_wrap( "You are about to recreate the relationship entries between the commits ". "and the packages they touch. This might delete some existing ". "relationship entries for some old commits."); if (!phutil_console_confirm('Are you ready to continue?')) { echo "Cancelled.\n"; exit(1); } } $commits = array(); -if ($is_all) { +if ($all_from_repo) { $repository = id(new PhabricatorRepository())->loadOneWhere( 'callsign = %s OR phid = %s', - $reparse_what, - $reparse_what); + $all_from_repo, + $all_from_repo); if (!$repository) { - throw new Exception("Unknown repository '{$reparse_what}'!"); + throw new Exception("Unknown repository {$all_from_repo}!"); + } + $constraint = ''; + if ($min_date) { + $table = new PhabricatorRepositoryCommit(); + $conn_r = $table->establishConnection('r'); + $constraint = qsprintf( + $conn_r, + 'AND epoch > unix_timestamp(%s)', + $min_date); } $commits = id(new PhabricatorRepositoryCommit())->loadAllWhere( - 'repositoryID = %d', - $repository->getID()); + 'repositoryID = %d %Q', + $repository->getID(), + $constraint); if (!$commits) { throw new Exception("No commits have been discovered in that repository!"); } $callsign = $repository->getCallsign(); } else { $matches = null; if (!preg_match('/r([A-Z]+)([a-z0-9]+)/', $reparse_what, $matches)) { throw new Exception("Can't parse commit identifier!"); } $callsign = $matches[1]; $commit_identifier = $matches[2]; $repository = id(new PhabricatorRepository())->loadOneWhere( 'callsign = %s', $callsign); if (!$repository) { throw new Exception("No repository with callsign '{$callsign}'!"); } $commit = id(new PhabricatorRepositoryCommit())->loadOneWhere( 'repositoryID = %d AND commitIdentifier = %s', $repository->getID(), $commit_identifier); if (!$commit) { throw new Exception( "No matching commit '{$commit_identifier}' in repository '{$callsign}'. ". "(For git and mercurial repositories, you must specify the entire ". "commit hash.)"); } $commits = array($commit); } -if ($is_all) { +if ($all_from_repo && !$force_local) { echo phutil_console_format( '**NOTE**: This script will queue tasks to reparse the data. Once the '. 'tasks have been queued, you need to run Taskmaster daemons to execute '. 'them.'); echo "\n\n"; echo "QUEUEING TASKS (".number_format(count($commits))." Commits):\n"; } $tasks = array(); foreach ($commits as $commit) { $classes = array(); switch ($repository->getVersionControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: if ($reparse_message) { $classes[] = 'PhabricatorRepositoryGitCommitMessageParserWorker'; } if ($reparse_change) { $classes[] = 'PhabricatorRepositoryGitCommitChangeParserWorker'; } break; case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: if ($reparse_message) { $classes[] = 'PhabricatorRepositoryMercurialCommitMessageParserWorker'; } if ($reparse_change) { $classes[] = 'PhabricatorRepositoryMercurialCommitChangeParserWorker'; } break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: if ($reparse_message) { $classes[] = 'PhabricatorRepositorySvnCommitMessageParserWorker'; } if ($reparse_change) { $classes[] = 'PhabricatorRepositorySvnCommitChangeParserWorker'; } break; } if ($reparse_herald) { $classes[] = 'PhabricatorRepositoryCommitHeraldWorker'; } if ($reparse_owners) { $classes[] = 'PhabricatorRepositoryCommitOwnersWorker'; } $spec = array( 'commitID' => $commit->getID(), 'only' => true, ); - if ($is_all) { + if ($all_from_repo && !$force_local) { foreach ($classes as $class) { $task = new PhabricatorWorkerTask(); $task->setTaskClass($class); $task->setData($spec); $task->save(); $commit_name = 'r'.$callsign.$commit->getCommitIdentifier(); echo " Queued '{$class}' for commit '{$commit_name}'.\n"; } } else { foreach ($classes as $class) { $worker = newv($class, array($spec)); echo "Running '{$class}'...\n"; $worker->doWork(); } } } echo "\nDone.\n"; function usage($message) { - echo "Usage Error: {$message}"; - echo "\n\n"; - echo "Run 'reparse.php --help' for detailed help.\n"; - exit(1); -} - -function help() { - $help = <<