@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
at recaptime-dev/main 142 lines 4.0 kB view raw
1<?php 2 3final class DiffusionCommitRevisionQuery 4 extends Phobject { 5 6 /** 7 * @param PhabricatorUser $viewer 8 * @param array<PhabricatorRepositoryCommit> $commits 9 */ 10 public static function loadRevisionMapForCommits( 11 PhabricatorUser $viewer, 12 array $commits) { 13 assert_instances_of($commits, PhabricatorRepositoryCommit::class); 14 15 if (!$commits) { 16 return array(); 17 } 18 19 $commit_phids = mpull($commits, 'getPHID'); 20 21 $edge_query = id(new PhabricatorEdgeQuery()) 22 ->withSourcePHIDs($commit_phids) 23 ->withEdgeTypes( 24 array( 25 DiffusionCommitHasRevisionEdgeType::EDGECONST, 26 )); 27 $edge_query->execute(); 28 29 $revision_phids = $edge_query->getDestinationPHIDs(); 30 if (!$revision_phids) { 31 return array(); 32 } 33 34 $revisions = id(new DifferentialRevisionQuery()) 35 ->setViewer($viewer) 36 ->withPHIDs($revision_phids) 37 ->execute(); 38 $revisions = mpull($revisions, null, 'getPHID'); 39 40 $map = array(); 41 foreach ($commit_phids as $commit_phid) { 42 $revision_phids = $edge_query->getDestinationPHIDs( 43 array( 44 $commit_phid, 45 )); 46 47 $map[$commit_phid] = array_select_keys($revisions, $revision_phids); 48 } 49 50 return $map; 51 } 52 53 public static function loadRevisionForCommit( 54 PhabricatorUser $viewer, 55 PhabricatorRepositoryCommit $commit) { 56 57 $data = $commit->getCommitData(); 58 59 $revision_id = $data->getCommitDetail('differential.revisionID'); 60 if (!$revision_id) { 61 return null; 62 } 63 64 return id(new DifferentialRevisionQuery()) 65 ->setViewer($viewer) 66 ->withIDs(array($revision_id)) 67 ->needReviewers(true) 68 ->executeOne(); 69 } 70 71 public static function loadRevertedObjects( 72 PhabricatorUser $viewer, 73 $source_object, 74 array $object_names, 75 ?PhabricatorRepository $repository_scope = null) { 76 77 // Fetch commits first, since we need to load data on commits in order 78 // to identify associated revisions later on. 79 $commit_query = id(new DiffusionCommitQuery()) 80 ->setViewer($viewer) 81 ->withIdentifiers($object_names) 82 ->needCommitData(true); 83 84 // If we're acting in a specific repository, only allow commits in that 85 // repository to be affected: when commit X reverts commit Y by hash, we 86 // only want to revert commit Y in the same repository, even if other 87 // repositories have a commit with the same hash. 88 if ($repository_scope) { 89 $commit_query->withRepository($repository_scope); 90 } 91 92 $objects = $commit_query->execute(); 93 94 $more_objects = id(new PhabricatorObjectQuery()) 95 ->setViewer($viewer) 96 ->withNames($object_names) 97 ->withTypes( 98 array( 99 DifferentialRevisionPHIDType::TYPECONST, 100 )) 101 ->execute(); 102 foreach ($more_objects as $object) { 103 $objects[] = $object; 104 } 105 106 // See PHI1008 and T13276. If something reverts commit X, we also revert 107 // any associated revision. 108 109 // For now, we don't try to find associated commits if something reverts 110 // revision Y. This is less common, although we could make more of an 111 // effort in the future. 112 113 foreach ($objects as $object) { 114 if (!($object instanceof PhabricatorRepositoryCommit)) { 115 continue; 116 } 117 118 // NOTE: If our object "reverts X", where "X" is a commit hash, it is 119 // possible that "X" will not have parsed yet, so we'll fail to find 120 // a revision even though one exists. 121 122 // For now, do nothing. It's rare to push a commit which reverts some 123 // commit "X" before "X" has parsed, so we expect this to be unusual. 124 125 $revision = self::loadRevisionForCommit( 126 $viewer, 127 $object); 128 if ($revision) { 129 $objects[] = $revision; 130 } 131 } 132 133 $objects = mpull($objects, null, 'getPHID'); 134 135 // Prevent an object from reverting itself, although this would be very 136 // clever in Git or Mercurial. 137 unset($objects[$source_object->getPHID()]); 138 139 return $objects; 140 } 141 142}