-
Notifications
You must be signed in to change notification settings - Fork 463
/
Copy pathArcanistDifferentialCommitMessage.php
134 lines (108 loc) · 3.21 KB
/
ArcanistDifferentialCommitMessage.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<?php
/**
* Represents a parsed commit message.
*/
final class ArcanistDifferentialCommitMessage extends Phobject {
private $rawCorpus;
private $revisionID;
private $fields = array();
private $gitSVNBaseRevision;
private $gitSVNBasePath;
private $gitSVNUUID;
public static function newFromRawCorpus($corpus) {
$obj = new ArcanistDifferentialCommitMessage();
$obj->rawCorpus = $corpus;
$obj->revisionID = $obj->parseRevisionIDFromRawCorpus($corpus);
$pattern = '/^git-svn-id:\s*([^@]+)@(\d+)\s+(.*)$/m';
$match = null;
if (preg_match($pattern, $corpus, $match)) {
$obj->gitSVNBaseRevision = $match[1].'@'.$match[2];
$obj->gitSVNBasePath = $match[1];
$obj->gitSVNUUID = $match[3];
}
return $obj;
}
public function getRawCorpus() {
return $this->rawCorpus;
}
public function getRevisionID() {
return $this->revisionID;
}
public function pullDataFromConduit(
ConduitClient $conduit,
$partial = false) {
$result = $conduit->callMethodSynchronous(
'differential.parsecommitmessage',
array(
'corpus' => $this->rawCorpus,
'partial' => $partial,
));
$this->fields = $result['fields'];
if (!empty($result['errors'])) {
throw new ArcanistDifferentialCommitMessageParserException(
$result['errors']);
}
return $this;
}
public function getFieldValue($key) {
if (array_key_exists($key, $this->fields)) {
return $this->fields[$key];
}
return null;
}
public function setFieldValue($key, $value) {
$this->fields[$key] = $value;
return $this;
}
public function getFields() {
return $this->fields;
}
public function getGitSVNBaseRevision() {
return $this->gitSVNBaseRevision;
}
public function getGitSVNBasePath() {
return $this->gitSVNBasePath;
}
public function getGitSVNUUID() {
return $this->gitSVNUUID;
}
public function getChecksum() {
$fields = array_filter($this->fields);
ksort($fields);
$fields = json_encode($fields);
return md5($fields);
}
/**
* Extract the revision ID from a commit message.
*
* @param string Raw commit message.
* @return int|null Revision ID, if the commit message contains one.
*/
private function parseRevisionIDFromRawCorpus($corpus) {
$match = null;
if (!preg_match('/^Differential Revision:\s*(.+)/im', $corpus, $match)) {
return null;
}
$revision_value = trim($match[1]);
$revision_pattern = '/^[dD]([1-9]\d*)\z/';
// Accept a bare revision ID like "D123".
if (preg_match($revision_pattern, $revision_value, $match)) {
return (int)$match[1];
}
// Otherwise, try to find a full URI.
$uri = new PhutilURI($revision_value);
$path = $uri->getPath();
$path = trim($path, '/');
if (preg_match($revision_pattern, $path, $match)) {
return (int)$match[1];
}
throw new ArcanistUsageException(
pht(
'Invalid "Differential Revision" field in commit message. This field '.
'should have a revision identifier like "%s" or a Phabricator URI '.
'like "%s", but has "%s".',
'D123',
'https://phabricator.example.com/D123',
$revision_value));
}
}