@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Move diff extraction from commits to a separate test with a CLI command

Summary:
Ref T9319. When we discover a commit, we sometimes update the corresponding revision with a "this is the actual committed change" diff and send out a link to the changes between review and commit.

This is currently very difficult to test, because it only happens the first time and you have to either go set up a bunch of objects or add a bunch of special casing to the parser to hit the workflow.

I'm making some changes to how it pulls file content. To make those changes easier to test, first start extracting this stuff so the code can be run with `bin/differential extract ...` instead of needing to do a bunch of more complicated setup steps.

Test Plan:
- Ran `bin/differential extract ...` to extract diffs from commits.
- Forced my way through the daemon workflow by faking out a bunch of flags, got a clean extract + attach + update. After this patch, this should rarely be necessary.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9319

Differential Revision: https://secure.phabricator.com/D14967

+195 -60
+1
bin/differential
··· 1 + ../scripts/setup/manage_differential.php
+21
scripts/setup/manage_differential.php
··· 1 + #!/usr/bin/env php 2 + <?php 3 + 4 + $root = dirname(dirname(dirname(__FILE__))); 5 + require_once $root.'/scripts/__init_script__.php'; 6 + 7 + $args = new PhutilArgumentParser($argv); 8 + $args->setTagline(pht('manage hunks')); 9 + $args->setSynopsis(<<<EOSYNOPSIS 10 + **differential** __command__ [__options__] 11 + Manage Differential. 12 + 13 + EOSYNOPSIS 14 + ); 15 + $args->parseStandardArguments(); 16 + 17 + $workflows = id(new PhutilClassMapQuery()) 18 + ->setAncestorClass('PhabricatorDifferentialManagementWorkflow') 19 + ->execute(); 20 + $workflows[] = new PhutilHelpArgumentWorkflow(); 21 + $args->parseWorkflows($workflows);
+6
src/__phutil_library_map__.php
··· 386 386 'DifferentialDiffContentRemovedHeraldField' => 'applications/differential/herald/DifferentialDiffContentRemovedHeraldField.php', 387 387 'DifferentialDiffCreateController' => 'applications/differential/controller/DifferentialDiffCreateController.php', 388 388 'DifferentialDiffEditor' => 'applications/differential/editor/DifferentialDiffEditor.php', 389 + 'DifferentialDiffExtractionEngine' => 'applications/differential/engine/DifferentialDiffExtractionEngine.php', 389 390 'DifferentialDiffHeraldField' => 'applications/differential/herald/DifferentialDiffHeraldField.php', 390 391 'DifferentialDiffHeraldFieldGroup' => 'applications/differential/herald/DifferentialDiffHeraldFieldGroup.php', 391 392 'DifferentialDiffInlineCommentQuery' => 'applications/differential/query/DifferentialDiffInlineCommentQuery.php', ··· 2143 2144 'PhabricatorDifferenceEngine' => 'infrastructure/diff/PhabricatorDifferenceEngine.php', 2144 2145 'PhabricatorDifferentialApplication' => 'applications/differential/application/PhabricatorDifferentialApplication.php', 2145 2146 'PhabricatorDifferentialConfigOptions' => 'applications/differential/config/PhabricatorDifferentialConfigOptions.php', 2147 + 'PhabricatorDifferentialExtractWorkflow' => 'applications/differential/management/PhabricatorDifferentialExtractWorkflow.php', 2148 + 'PhabricatorDifferentialManagementWorkflow' => 'applications/differential/management/PhabricatorDifferentialManagementWorkflow.php', 2146 2149 'PhabricatorDifferentialRevisionTestDataGenerator' => 'applications/differential/lipsum/PhabricatorDifferentialRevisionTestDataGenerator.php', 2147 2150 'PhabricatorDiffusionApplication' => 'applications/diffusion/application/PhabricatorDiffusionApplication.php', 2148 2151 'PhabricatorDiffusionConfigOptions' => 'applications/diffusion/config/PhabricatorDiffusionConfigOptions.php', ··· 4334 4337 'DifferentialDiffContentRemovedHeraldField' => 'DifferentialDiffHeraldField', 4335 4338 'DifferentialDiffCreateController' => 'DifferentialController', 4336 4339 'DifferentialDiffEditor' => 'PhabricatorApplicationTransactionEditor', 4340 + 'DifferentialDiffExtractionEngine' => 'Phobject', 4337 4341 'DifferentialDiffHeraldField' => 'HeraldField', 4338 4342 'DifferentialDiffHeraldFieldGroup' => 'HeraldFieldGroup', 4339 4343 'DifferentialDiffInlineCommentQuery' => 'PhabricatorDiffInlineCommentQuery', ··· 6376 6380 'PhabricatorDifferenceEngine' => 'Phobject', 6377 6381 'PhabricatorDifferentialApplication' => 'PhabricatorApplication', 6378 6382 'PhabricatorDifferentialConfigOptions' => 'PhabricatorApplicationConfigOptions', 6383 + 'PhabricatorDifferentialExtractWorkflow' => 'PhabricatorDifferentialManagementWorkflow', 6384 + 'PhabricatorDifferentialManagementWorkflow' => 'PhabricatorManagementWorkflow', 6379 6385 'PhabricatorDifferentialRevisionTestDataGenerator' => 'PhabricatorTestDataGenerator', 6380 6386 'PhabricatorDiffusionApplication' => 'PhabricatorApplication', 6381 6387 'PhabricatorDiffusionConfigOptions' => 'PhabricatorApplicationConfigOptions',
+90
src/applications/differential/engine/DifferentialDiffExtractionEngine.php
··· 1 + <?php 2 + 3 + final class DifferentialDiffExtractionEngine extends Phobject { 4 + 5 + private $viewer; 6 + private $authorPHID; 7 + 8 + public function setViewer(PhabricatorUser $viewer) { 9 + $this->viewer = $viewer; 10 + return $this; 11 + } 12 + 13 + public function getViewer() { 14 + return $this->viewer; 15 + } 16 + 17 + public function setAuthorPHID($author_phid) { 18 + $this->authorPHID = $author_phid; 19 + return $this; 20 + } 21 + 22 + public function getAuthorPHID() { 23 + return $this->authorPHID; 24 + } 25 + 26 + public function newDiffFromCommit(PhabricatorRepositoryCommit $commit) { 27 + $viewer = $this->getViewer(); 28 + 29 + $repository = $commit->getRepository(); 30 + $identifier = $commit->getCommitIdentifier(); 31 + $monogram = $commit->getMonogram(); 32 + 33 + $drequest = DiffusionRequest::newFromDictionary( 34 + array( 35 + 'user' => $viewer, 36 + 'repository' => $repository, 37 + )); 38 + 39 + $raw_diff = DiffusionQuery::callConduitWithDiffusionRequest( 40 + $viewer, 41 + $drequest, 42 + 'diffusion.rawdiffquery', 43 + array( 44 + 'commit' => $identifier, 45 + )); 46 + 47 + // TODO: Support adds, deletes and moves under SVN. 48 + if (strlen($raw_diff)) { 49 + $changes = id(new ArcanistDiffParser())->parseDiff($raw_diff); 50 + } else { 51 + // This is an empty diff, maybe made with `git commit --allow-empty`. 52 + // NOTE: These diffs have the same tree hash as their ancestors, so 53 + // they may attach to revisions in an unexpected way. Just let this 54 + // happen for now, although it might make sense to special case it 55 + // eventually. 56 + $changes = array(); 57 + } 58 + 59 + $diff = DifferentialDiff::newFromRawChanges($viewer, $changes) 60 + ->setRepositoryPHID($repository->getPHID()) 61 + ->setCreationMethod('commit') 62 + ->setSourceControlSystem($repository->getVersionControlSystem()) 63 + ->setLintStatus(DifferentialLintStatus::LINT_AUTO_SKIP) 64 + ->setUnitStatus(DifferentialUnitStatus::UNIT_AUTO_SKIP) 65 + ->setDateCreated($commit->getEpoch()) 66 + ->setDescription($monogram); 67 + 68 + $author_phid = $this->getAuthorPHID(); 69 + if ($author_phid !== null) { 70 + $diff->setAuthorPHID($author_phid); 71 + } 72 + 73 + $parents = DiffusionQuery::callConduitWithDiffusionRequest( 74 + $viewer, 75 + $drequest, 76 + 'diffusion.commitparentsquery', 77 + array( 78 + 'commit' => $identifier, 79 + )); 80 + 81 + if ($parents) { 82 + $diff->setSourceControlBaseRevision(head($parents)); 83 + } 84 + 85 + // TODO: Attach binary files. 86 + 87 + return $diff->save(); 88 + } 89 + 90 + }
+63
src/applications/differential/management/PhabricatorDifferentialExtractWorkflow.php
··· 1 + <?php 2 + 3 + final class PhabricatorDifferentialExtractWorkflow 4 + extends PhabricatorDifferentialManagementWorkflow { 5 + 6 + protected function didConstruct() { 7 + $this 8 + ->setName('extract') 9 + ->setExamples('**extract** __commit__') 10 + ->setSynopsis(pht('Extract a diff from a commit.')) 11 + ->setArguments( 12 + array( 13 + array( 14 + 'name' => 'extract', 15 + 'wildcard' => true, 16 + 'help' => pht('Commit to extract.'), 17 + ), 18 + )); 19 + } 20 + 21 + public function execute(PhutilArgumentParser $args) { 22 + $viewer = $this->getViewer(); 23 + 24 + $extract = $args->getArg('extract'); 25 + 26 + if (!$extract) { 27 + throw new PhutilArgumentUsageException( 28 + pht('Specify a commit to extract the diff from.')); 29 + } 30 + 31 + if (count($extract) > 1) { 32 + throw new PhutilArgumentUsageException( 33 + pht('Specify exactly one commit to extract.')); 34 + } 35 + 36 + $extract = head($extract); 37 + 38 + $commit = id(new DiffusionCommitQuery()) 39 + ->setViewer($viewer) 40 + ->withIdentifiers(array($extract)) 41 + ->executeOne(); 42 + 43 + if (!$commit) { 44 + throw new PhutilArgumentUsageException( 45 + pht( 46 + 'Commit "%s" is not valid.', 47 + $extract)); 48 + } 49 + 50 + $diff = id(new DifferentialDiffExtractionEngine()) 51 + ->setViewer($viewer) 52 + ->newDiffFromCommit($commit); 53 + 54 + $uri = PhabricatorEnv::getProductionURI($diff->getURI()); 55 + 56 + echo tsprintf( 57 + "%s\n\n %s\n", 58 + pht('Extracted diff from "%s":', $extract), 59 + $uri); 60 + } 61 + 62 + 63 + }
+4
src/applications/differential/management/PhabricatorDifferentialManagementWorkflow.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorDifferentialManagementWorkflow 4 + extends PhabricatorManagementWorkflow {}
+6
src/applications/differential/storage/DifferentialDiff.php
··· 385 385 return $map; 386 386 } 387 387 388 + public function getURI() { 389 + $id = $this->getID(); 390 + return "/differential/diff/{$id}/"; 391 + } 392 + 393 + 388 394 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 389 395 390 396
+4 -60
src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php
··· 216 216 $low_level_query->getRevisionMatchData()); 217 217 } 218 218 219 - $diff = $this->generateFinalDiff($revision, $acting_as_phid); 219 + $diff = id(new DifferentialDiffExtractionEngine()) 220 + ->setViewer($actor) 221 + ->setAuthorPHID($acting_as_phid) 222 + ->newDiffFromCommit($commit); 220 223 221 224 $vs_diff = $this->loadChangedByCommit($revision, $diff); 222 225 $changed_uri = null; ··· 277 280 PhabricatorRepositoryCommit::IMPORTED_MESSAGE); 278 281 } 279 282 280 - private function generateFinalDiff( 281 - DifferentialRevision $revision, 282 - $actor_phid) { 283 - 284 - $viewer = PhabricatorUser::getOmnipotentUser(); 285 - 286 - $drequest = DiffusionRequest::newFromDictionary(array( 287 - 'user' => $viewer, 288 - 'repository' => $this->repository, 289 - )); 290 - 291 - $raw_diff = DiffusionQuery::callConduitWithDiffusionRequest( 292 - $viewer, 293 - $drequest, 294 - 'diffusion.rawdiffquery', 295 - array( 296 - 'commit' => $this->commit->getCommitIdentifier(), 297 - )); 298 - 299 - // TODO: Support adds, deletes and moves under SVN. 300 - if (strlen($raw_diff)) { 301 - $changes = id(new ArcanistDiffParser())->parseDiff($raw_diff); 302 - } else { 303 - // This is an empty diff, maybe made with `git commit --allow-empty`. 304 - // NOTE: These diffs have the same tree hash as their ancestors, so 305 - // they may attach to revisions in an unexpected way. Just let this 306 - // happen for now, although it might make sense to special case it 307 - // eventually. 308 - $changes = array(); 309 - } 310 - 311 - $diff = DifferentialDiff::newFromRawChanges($viewer, $changes) 312 - ->setRepositoryPHID($this->repository->getPHID()) 313 - ->setAuthorPHID($actor_phid) 314 - ->setCreationMethod('commit') 315 - ->setSourceControlSystem($this->repository->getVersionControlSystem()) 316 - ->setLintStatus(DifferentialLintStatus::LINT_AUTO_SKIP) 317 - ->setUnitStatus(DifferentialUnitStatus::UNIT_AUTO_SKIP) 318 - ->setDateCreated($this->commit->getEpoch()) 319 - ->setDescription( 320 - pht( 321 - 'Commit %s', 322 - $this->commit->getMonogram())); 323 - 324 - $parents = DiffusionQuery::callConduitWithDiffusionRequest( 325 - $viewer, 326 - $drequest, 327 - 'diffusion.commitparentsquery', 328 - array( 329 - 'commit' => $this->commit->getCommitIdentifier(), 330 - )); 331 - if ($parents) { 332 - $diff->setSourceControlBaseRevision(head($parents)); 333 - } 334 - 335 - // TODO: Attach binary files. 336 - 337 - return $diff->save(); 338 - } 339 283 340 284 private function loadChangedByCommit( 341 285 DifferentialRevision $revision,