Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/diffusion/query/lowlevel/DiffusionLowLevelCommitFieldsQuery.php
12242 views
1
<?php
2
3
final class DiffusionLowLevelCommitFieldsQuery
4
extends DiffusionLowLevelQuery {
5
6
private $ref;
7
private $revisionMatchData = array(
8
'usedURI' => null,
9
'foundURI' => null,
10
'validDomain' => null,
11
'matchHashType' => null,
12
'matchHashValue' => null,
13
);
14
15
public function withCommitRef(DiffusionCommitRef $ref) {
16
$this->ref = $ref;
17
return $this;
18
}
19
20
public function getRevisionMatchData() {
21
return $this->revisionMatchData;
22
}
23
24
private function setRevisionMatchData($key, $value) {
25
$this->revisionMatchData[$key] = $value;
26
return $this;
27
}
28
29
protected function executeQuery() {
30
$ref = $this->ref;
31
$message = $ref->getMessage();
32
$hashes = $ref->getHashes();
33
34
$params = array(
35
'corpus' => $message,
36
'partial' => true,
37
);
38
39
$result = id(new ConduitCall('differential.parsecommitmessage', $params))
40
->setUser(PhabricatorUser::getOmnipotentUser())
41
->execute();
42
$fields = $result['fields'];
43
44
$revision_id = idx($fields, 'revisionID');
45
if ($revision_id) {
46
$this->setRevisionMatchData('usedURI', true);
47
} else {
48
$this->setRevisionMatchData('usedURI', false);
49
}
50
$revision_id_info = $result['revisionIDFieldInfo'];
51
$this->setRevisionMatchData('foundURI', $revision_id_info['value']);
52
$this->setRevisionMatchData(
53
'validDomain',
54
$revision_id_info['validDomain']);
55
56
// If there is no "Differential Revision:" field in the message, try to
57
// identify the revision by doing a hash lookup.
58
59
if (!$revision_id && $hashes) {
60
$hash_list = array();
61
foreach ($hashes as $hash) {
62
$hash_list[] = array($hash->getHashType(), $hash->getHashValue());
63
}
64
$revisions = id(new DifferentialRevisionQuery())
65
->setViewer(PhabricatorUser::getOmnipotentUser())
66
->needHashes(true)
67
->withCommitHashes($hash_list)
68
->execute();
69
70
if ($revisions) {
71
$revision = $this->pickBestRevision($revisions);
72
73
$fields['revisionID'] = $revision->getID();
74
$revision_hashes = $revision->getHashes();
75
76
$revision_hashes = DiffusionCommitHash::convertArrayToObjects(
77
$revision_hashes);
78
$revision_hashes = mpull($revision_hashes, null, 'getHashType');
79
80
// sort the hashes in the order the mighty
81
// @{class:ArcanstDifferentialRevisionHash} does; probably unnecessary
82
// but should future proof things nicely.
83
$revision_hashes = array_select_keys(
84
$revision_hashes,
85
ArcanistDifferentialRevisionHash::getTypes());
86
87
foreach ($hashes as $hash) {
88
$revision_hash = idx($revision_hashes, $hash->getHashType());
89
if (!$revision_hash) {
90
continue;
91
}
92
if ($revision_hash->getHashValue() == $hash->getHashValue()) {
93
$this->setRevisionMatchData(
94
'matchHashType',
95
$hash->getHashType());
96
$this->setRevisionMatchData(
97
'matchHashValue',
98
$hash->getHashValue());
99
break;
100
}
101
}
102
}
103
}
104
105
return $fields;
106
}
107
108
109
/**
110
* When querying for revisions by hash, more than one revision may be found.
111
* This function identifies the "best" revision from such a set. Typically,
112
* there is only one revision found. Otherwise, we try to pick an accepted
113
* revision first, followed by an open revision, and otherwise we go with a
114
* closed or abandoned revision as a last resort.
115
*/
116
private function pickBestRevision(array $revisions) {
117
assert_instances_of($revisions, 'DifferentialRevision');
118
119
// If we have more than one revision of a given status, choose the most
120
// recently updated one.
121
$revisions = msort($revisions, 'getDateModified');
122
$revisions = array_reverse($revisions);
123
124
// Try to find an accepted revision first.
125
foreach ($revisions as $revision) {
126
if ($revision->isAccepted()) {
127
return $revision;
128
}
129
}
130
131
// Try to find an open revision.
132
foreach ($revisions as $revision) {
133
if (!$revision->isClosed()) {
134
return $revision;
135
}
136
}
137
138
// Settle for whatever's left.
139
return head($revisions);
140
}
141
142
}
143
144