Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/differential/controller/DifferentialController.php
12256 views
1
<?php
2
3
abstract class DifferentialController extends PhabricatorController {
4
5
private $packageChangesetMap;
6
private $pathPackageMap;
7
private $authorityPackages;
8
9
public function buildSideNavView($for_app = false) {
10
$viewer = $this->getRequest()->getUser();
11
12
$nav = new AphrontSideNavFilterView();
13
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
14
15
id(new DifferentialRevisionSearchEngine())
16
->setViewer($viewer)
17
->addNavigationItems($nav->getMenu());
18
19
$nav->selectFilter(null);
20
21
return $nav;
22
}
23
24
public function buildApplicationMenu() {
25
return $this->buildSideNavView(true)->getMenu();
26
}
27
28
protected function buildPackageMaps(array $changesets) {
29
assert_instances_of($changesets, 'DifferentialChangeset');
30
31
$this->packageChangesetMap = array();
32
$this->pathPackageMap = array();
33
$this->authorityPackages = array();
34
35
if (!$changesets) {
36
return;
37
}
38
39
$viewer = $this->getViewer();
40
41
$have_owners = PhabricatorApplication::isClassInstalledForViewer(
42
'PhabricatorOwnersApplication',
43
$viewer);
44
if (!$have_owners) {
45
return;
46
}
47
48
$changeset = head($changesets);
49
$diff = $changeset->getDiff();
50
$repository_phid = $diff->getRepositoryPHID();
51
if (!$repository_phid) {
52
return;
53
}
54
55
if ($viewer->getPHID()) {
56
$packages = id(new PhabricatorOwnersPackageQuery())
57
->setViewer($viewer)
58
->withStatuses(array(PhabricatorOwnersPackage::STATUS_ACTIVE))
59
->withAuthorityPHIDs(array($viewer->getPHID()))
60
->execute();
61
$this->authorityPackages = $packages;
62
}
63
64
$paths = mpull($changesets, 'getOwnersFilename');
65
66
$control_query = id(new PhabricatorOwnersPackageQuery())
67
->setViewer($viewer)
68
->withStatuses(array(PhabricatorOwnersPackage::STATUS_ACTIVE))
69
->withControl($repository_phid, $paths);
70
$control_query->execute();
71
72
foreach ($changesets as $changeset) {
73
$changeset_path = $changeset->getOwnersFilename();
74
75
$packages = $control_query->getControllingPackagesForPath(
76
$repository_phid,
77
$changeset_path);
78
79
// If this particular changeset is generated code and the package does
80
// not match generated code, remove it from the list.
81
if ($changeset->isGeneratedChangeset()) {
82
foreach ($packages as $key => $package) {
83
if ($package->getMustMatchUngeneratedPaths()) {
84
unset($packages[$key]);
85
}
86
}
87
}
88
89
$this->pathPackageMap[$changeset_path] = $packages;
90
foreach ($packages as $package) {
91
$this->packageChangesetMap[$package->getPHID()][] = $changeset;
92
}
93
}
94
}
95
96
protected function getAuthorityPackages() {
97
if ($this->authorityPackages === null) {
98
throw new PhutilInvalidStateException('buildPackageMaps');
99
}
100
return $this->authorityPackages;
101
}
102
103
protected function getChangesetPackages(DifferentialChangeset $changeset) {
104
if ($this->pathPackageMap === null) {
105
throw new PhutilInvalidStateException('buildPackageMaps');
106
}
107
108
$path = $changeset->getOwnersFilename();
109
return idx($this->pathPackageMap, $path, array());
110
}
111
112
protected function getPackageChangesets($package_phid) {
113
if ($this->packageChangesetMap === null) {
114
throw new PhutilInvalidStateException('buildPackageMaps');
115
}
116
117
return idx($this->packageChangesetMap, $package_phid, array());
118
}
119
120
protected function buildTableOfContents(
121
array $changesets,
122
array $visible_changesets,
123
array $coverage) {
124
$viewer = $this->getViewer();
125
126
$toc_view = id(new PHUIDiffTableOfContentsListView())
127
->setViewer($viewer)
128
->setBare(true)
129
->setAuthorityPackages($this->getAuthorityPackages());
130
131
foreach ($changesets as $changeset_id => $changeset) {
132
$is_visible = isset($visible_changesets[$changeset_id]);
133
$anchor = $changeset->getAnchorName();
134
135
$filename = $changeset->getFilename();
136
$coverage_id = 'differential-mcoverage-'.md5($filename);
137
138
$item = id(new PHUIDiffTableOfContentsItemView())
139
->setChangeset($changeset)
140
->setIsVisible($is_visible)
141
->setAnchor($anchor)
142
->setCoverage(idx($coverage, $filename))
143
->setCoverageID($coverage_id);
144
145
$packages = $this->getChangesetPackages($changeset);
146
$item->setPackages($packages);
147
148
$toc_view->addItem($item);
149
}
150
151
return $toc_view;
152
}
153
154
protected function loadDiffProperties(array $diffs) {
155
$diffs = mpull($diffs, null, 'getID');
156
157
$properties = id(new DifferentialDiffProperty())->loadAllWhere(
158
'diffID IN (%Ld)',
159
array_keys($diffs));
160
$properties = mgroup($properties, 'getDiffID');
161
162
foreach ($diffs as $id => $diff) {
163
$values = idx($properties, $id, array());
164
$values = mpull($values, 'getData', 'getName');
165
$diff->attachDiffProperties($values);
166
}
167
}
168
169
170
protected function loadHarbormasterData(array $diffs) {
171
$viewer = $this->getViewer();
172
173
$diffs = mpull($diffs, null, 'getPHID');
174
175
$buildables = id(new HarbormasterBuildableQuery())
176
->setViewer($viewer)
177
->withBuildablePHIDs(array_keys($diffs))
178
->withManualBuildables(false)
179
->needBuilds(true)
180
->needTargets(true)
181
->execute();
182
183
$buildables = mpull($buildables, null, 'getBuildablePHID');
184
foreach ($diffs as $phid => $diff) {
185
$diff->attachBuildable(idx($buildables, $phid));
186
}
187
188
$target_map = array();
189
foreach ($diffs as $phid => $diff) {
190
$target_map[$phid] = $diff->getBuildTargetPHIDs();
191
}
192
$all_target_phids = array_mergev($target_map);
193
194
if ($all_target_phids) {
195
$unit_messages = id(new HarbormasterBuildUnitMessageQuery())
196
->setViewer($viewer)
197
->withBuildTargetPHIDs($all_target_phids)
198
->execute();
199
$unit_messages = mgroup($unit_messages, 'getBuildTargetPHID');
200
} else {
201
$unit_messages = array();
202
}
203
204
foreach ($diffs as $phid => $diff) {
205
$target_phids = idx($target_map, $phid, array());
206
$messages = array_select_keys($unit_messages, $target_phids);
207
$messages = array_mergev($messages);
208
$diff->attachUnitMessages($messages);
209
}
210
211
// For diffs with no messages, look for legacy unit messages stored on the
212
// diff itself.
213
foreach ($diffs as $phid => $diff) {
214
if ($diff->getUnitMessages()) {
215
continue;
216
}
217
218
if (!$diff->hasDiffProperty('arc:unit')) {
219
continue;
220
}
221
222
$legacy_messages = $diff->getProperty('arc:unit');
223
if (!$legacy_messages) {
224
continue;
225
}
226
227
// Show the top 100 legacy lint messages. Previously, we showed some
228
// by default and let the user toggle the rest. With modern messages,
229
// we can send the user to the Harbormaster detail page. Just show
230
// "a lot" of messages in legacy cases to try to strike a balance
231
// between implementation simplicity and compatibility.
232
$legacy_messages = array_slice($legacy_messages, 0, 100);
233
234
$messages = array();
235
foreach ($legacy_messages as $message) {
236
$messages[] = HarbormasterBuildUnitMessage::newFromDictionary(
237
new HarbormasterBuildTarget(),
238
$this->getModernUnitMessageDictionary($message));
239
}
240
241
$diff->attachUnitMessages($messages);
242
}
243
}
244
245
private function getModernUnitMessageDictionary(array $map) {
246
// Strip out `null` values to satisfy stricter typechecks.
247
foreach ($map as $key => $value) {
248
if ($value === null) {
249
unset($map[$key]);
250
}
251
}
252
253
// Cast duration to a float since it used to be a string in some
254
// cases.
255
if (isset($map['duration'])) {
256
$map['duration'] = (double)$map['duration'];
257
}
258
259
return $map;
260
}
261
262
protected function getDiffTabLabels(array $diffs) {
263
// Make sure we're only going to render unique diffs.
264
$diffs = mpull($diffs, null, 'getID');
265
$labels = array(pht('Left'), pht('Right'));
266
267
$results = array();
268
269
foreach ($diffs as $diff) {
270
if (count($diffs) == 2) {
271
$label = array_shift($labels);
272
$label = pht('%s (Diff %d)', $label, $diff->getID());
273
} else {
274
$label = pht('Diff %d', $diff->getID());
275
}
276
277
$results[] = array(
278
$label,
279
$diff,
280
);
281
}
282
283
return $results;
284
}
285
286
287
}
288
289