diff --git a/bin/differential b/bin/differential new file mode 120000 --- /dev/null +++ b/bin/differential @@ -0,0 +1 @@ +../scripts/setup/manage_differential.php \ No newline at end of file diff --git a/scripts/setup/manage_differential.php b/scripts/setup/manage_differential.php new file mode 100755 --- /dev/null +++ b/scripts/setup/manage_differential.php @@ -0,0 +1,21 @@ +#!/usr/bin/env php +setTagline(pht('manage hunks')); +$args->setSynopsis(<<parseStandardArguments(); + +$workflows = id(new PhutilClassMapQuery()) + ->setAncestorClass('PhabricatorDifferentialManagementWorkflow') + ->execute(); +$workflows[] = new PhutilHelpArgumentWorkflow(); +$args->parseWorkflows($workflows); 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 @@ -386,6 +386,7 @@ 'DifferentialDiffContentRemovedHeraldField' => 'applications/differential/herald/DifferentialDiffContentRemovedHeraldField.php', 'DifferentialDiffCreateController' => 'applications/differential/controller/DifferentialDiffCreateController.php', 'DifferentialDiffEditor' => 'applications/differential/editor/DifferentialDiffEditor.php', + 'DifferentialDiffExtractionEngine' => 'applications/differential/engine/DifferentialDiffExtractionEngine.php', 'DifferentialDiffHeraldField' => 'applications/differential/herald/DifferentialDiffHeraldField.php', 'DifferentialDiffHeraldFieldGroup' => 'applications/differential/herald/DifferentialDiffHeraldFieldGroup.php', 'DifferentialDiffInlineCommentQuery' => 'applications/differential/query/DifferentialDiffInlineCommentQuery.php', @@ -2143,6 +2144,8 @@ 'PhabricatorDifferenceEngine' => 'infrastructure/diff/PhabricatorDifferenceEngine.php', 'PhabricatorDifferentialApplication' => 'applications/differential/application/PhabricatorDifferentialApplication.php', 'PhabricatorDifferentialConfigOptions' => 'applications/differential/config/PhabricatorDifferentialConfigOptions.php', + 'PhabricatorDifferentialExtractWorkflow' => 'applications/differential/management/PhabricatorDifferentialExtractWorkflow.php', + 'PhabricatorDifferentialManagementWorkflow' => 'applications/differential/management/PhabricatorDifferentialManagementWorkflow.php', 'PhabricatorDifferentialRevisionTestDataGenerator' => 'applications/differential/lipsum/PhabricatorDifferentialRevisionTestDataGenerator.php', 'PhabricatorDiffusionApplication' => 'applications/diffusion/application/PhabricatorDiffusionApplication.php', 'PhabricatorDiffusionConfigOptions' => 'applications/diffusion/config/PhabricatorDiffusionConfigOptions.php', @@ -4334,6 +4337,7 @@ 'DifferentialDiffContentRemovedHeraldField' => 'DifferentialDiffHeraldField', 'DifferentialDiffCreateController' => 'DifferentialController', 'DifferentialDiffEditor' => 'PhabricatorApplicationTransactionEditor', + 'DifferentialDiffExtractionEngine' => 'Phobject', 'DifferentialDiffHeraldField' => 'HeraldField', 'DifferentialDiffHeraldFieldGroup' => 'HeraldFieldGroup', 'DifferentialDiffInlineCommentQuery' => 'PhabricatorDiffInlineCommentQuery', @@ -6376,6 +6380,8 @@ 'PhabricatorDifferenceEngine' => 'Phobject', 'PhabricatorDifferentialApplication' => 'PhabricatorApplication', 'PhabricatorDifferentialConfigOptions' => 'PhabricatorApplicationConfigOptions', + 'PhabricatorDifferentialExtractWorkflow' => 'PhabricatorDifferentialManagementWorkflow', + 'PhabricatorDifferentialManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorDifferentialRevisionTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorDiffusionApplication' => 'PhabricatorApplication', 'PhabricatorDiffusionConfigOptions' => 'PhabricatorApplicationConfigOptions', diff --git a/src/applications/differential/engine/DifferentialDiffExtractionEngine.php b/src/applications/differential/engine/DifferentialDiffExtractionEngine.php new file mode 100644 --- /dev/null +++ b/src/applications/differential/engine/DifferentialDiffExtractionEngine.php @@ -0,0 +1,90 @@ +viewer = $viewer; + return $this; + } + + public function getViewer() { + return $this->viewer; + } + + public function setAuthorPHID($author_phid) { + $this->authorPHID = $author_phid; + return $this; + } + + public function getAuthorPHID() { + return $this->authorPHID; + } + + public function newDiffFromCommit(PhabricatorRepositoryCommit $commit) { + $viewer = $this->getViewer(); + + $repository = $commit->getRepository(); + $identifier = $commit->getCommitIdentifier(); + $monogram = $commit->getMonogram(); + + $drequest = DiffusionRequest::newFromDictionary( + array( + 'user' => $viewer, + 'repository' => $repository, + )); + + $raw_diff = DiffusionQuery::callConduitWithDiffusionRequest( + $viewer, + $drequest, + 'diffusion.rawdiffquery', + array( + 'commit' => $identifier, + )); + + // TODO: Support adds, deletes and moves under SVN. + if (strlen($raw_diff)) { + $changes = id(new ArcanistDiffParser())->parseDiff($raw_diff); + } else { + // This is an empty diff, maybe made with `git commit --allow-empty`. + // NOTE: These diffs have the same tree hash as their ancestors, so + // they may attach to revisions in an unexpected way. Just let this + // happen for now, although it might make sense to special case it + // eventually. + $changes = array(); + } + + $diff = DifferentialDiff::newFromRawChanges($viewer, $changes) + ->setRepositoryPHID($repository->getPHID()) + ->setCreationMethod('commit') + ->setSourceControlSystem($repository->getVersionControlSystem()) + ->setLintStatus(DifferentialLintStatus::LINT_AUTO_SKIP) + ->setUnitStatus(DifferentialUnitStatus::UNIT_AUTO_SKIP) + ->setDateCreated($commit->getEpoch()) + ->setDescription($monogram); + + $author_phid = $this->getAuthorPHID(); + if ($author_phid !== null) { + $diff->setAuthorPHID($author_phid); + } + + $parents = DiffusionQuery::callConduitWithDiffusionRequest( + $viewer, + $drequest, + 'diffusion.commitparentsquery', + array( + 'commit' => $identifier, + )); + + if ($parents) { + $diff->setSourceControlBaseRevision(head($parents)); + } + + // TODO: Attach binary files. + + return $diff->save(); + } + +} diff --git a/src/applications/differential/management/PhabricatorDifferentialExtractWorkflow.php b/src/applications/differential/management/PhabricatorDifferentialExtractWorkflow.php new file mode 100644 --- /dev/null +++ b/src/applications/differential/management/PhabricatorDifferentialExtractWorkflow.php @@ -0,0 +1,63 @@ +setName('extract') + ->setExamples('**extract** __commit__') + ->setSynopsis(pht('Extract a diff from a commit.')) + ->setArguments( + array( + array( + 'name' => 'extract', + 'wildcard' => true, + 'help' => pht('Commit to extract.'), + ), + )); + } + + public function execute(PhutilArgumentParser $args) { + $viewer = $this->getViewer(); + + $extract = $args->getArg('extract'); + + if (!$extract) { + throw new PhutilArgumentUsageException( + pht('Specify a commit to extract the diff from.')); + } + + if (count($extract) > 1) { + throw new PhutilArgumentUsageException( + pht('Specify exactly one commit to extract.')); + } + + $extract = head($extract); + + $commit = id(new DiffusionCommitQuery()) + ->setViewer($viewer) + ->withIdentifiers(array($extract)) + ->executeOne(); + + if (!$commit) { + throw new PhutilArgumentUsageException( + pht( + 'Commit "%s" is not valid.', + $extract)); + } + + $diff = id(new DifferentialDiffExtractionEngine()) + ->setViewer($viewer) + ->newDiffFromCommit($commit); + + $uri = PhabricatorEnv::getProductionURI($diff->getURI()); + + echo tsprintf( + "%s\n\n %s\n", + pht('Extracted diff from "%s":', $extract), + $uri); + } + + +} diff --git a/src/applications/differential/management/PhabricatorDifferentialManagementWorkflow.php b/src/applications/differential/management/PhabricatorDifferentialManagementWorkflow.php new file mode 100644 --- /dev/null +++ b/src/applications/differential/management/PhabricatorDifferentialManagementWorkflow.php @@ -0,0 +1,4 @@ +getID(); + return "/differential/diff/{$id}/"; + } + + /* -( PhabricatorPolicyInterface )----------------------------------------- */ diff --git a/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php b/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php --- a/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php +++ b/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php @@ -216,7 +216,10 @@ $low_level_query->getRevisionMatchData()); } - $diff = $this->generateFinalDiff($revision, $acting_as_phid); + $diff = id(new DifferentialDiffExtractionEngine()) + ->setViewer($actor) + ->setAuthorPHID($acting_as_phid) + ->newDiffFromCommit($commit); $vs_diff = $this->loadChangedByCommit($revision, $diff); $changed_uri = null; @@ -277,65 +280,6 @@ PhabricatorRepositoryCommit::IMPORTED_MESSAGE); } - private function generateFinalDiff( - DifferentialRevision $revision, - $actor_phid) { - - $viewer = PhabricatorUser::getOmnipotentUser(); - - $drequest = DiffusionRequest::newFromDictionary(array( - 'user' => $viewer, - 'repository' => $this->repository, - )); - - $raw_diff = DiffusionQuery::callConduitWithDiffusionRequest( - $viewer, - $drequest, - 'diffusion.rawdiffquery', - array( - 'commit' => $this->commit->getCommitIdentifier(), - )); - - // TODO: Support adds, deletes and moves under SVN. - if (strlen($raw_diff)) { - $changes = id(new ArcanistDiffParser())->parseDiff($raw_diff); - } else { - // This is an empty diff, maybe made with `git commit --allow-empty`. - // NOTE: These diffs have the same tree hash as their ancestors, so - // they may attach to revisions in an unexpected way. Just let this - // happen for now, although it might make sense to special case it - // eventually. - $changes = array(); - } - - $diff = DifferentialDiff::newFromRawChanges($viewer, $changes) - ->setRepositoryPHID($this->repository->getPHID()) - ->setAuthorPHID($actor_phid) - ->setCreationMethod('commit') - ->setSourceControlSystem($this->repository->getVersionControlSystem()) - ->setLintStatus(DifferentialLintStatus::LINT_AUTO_SKIP) - ->setUnitStatus(DifferentialUnitStatus::UNIT_AUTO_SKIP) - ->setDateCreated($this->commit->getEpoch()) - ->setDescription( - pht( - 'Commit %s', - $this->commit->getMonogram())); - - $parents = DiffusionQuery::callConduitWithDiffusionRequest( - $viewer, - $drequest, - 'diffusion.commitparentsquery', - array( - 'commit' => $this->commit->getCommitIdentifier(), - )); - if ($parents) { - $diff->setSourceControlBaseRevision(head($parents)); - } - - // TODO: Attach binary files. - - return $diff->save(); - } private function loadChangedByCommit( DifferentialRevision $revision,