@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<?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}