diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -64,8 +64,14 @@ 'ArcanistBrowseURIHardpointQuery' => 'browse/query/ArcanistBrowseURIHardpointQuery.php', 'ArcanistBrowseURIRef' => 'browse/ref/ArcanistBrowseURIRef.php', 'ArcanistBrowseWorkflow' => 'browse/workflow/ArcanistBrowseWorkflow.php', - 'ArcanistBuildPlanRef' => 'ref/ArcanistBuildPlanRef.php', - 'ArcanistBuildRef' => 'ref/ArcanistBuildRef.php', + 'ArcanistBuildBuildplanHardpointQuery' => 'ref/build/ArcanistBuildBuildplanHardpointQuery.php', + 'ArcanistBuildPlanRef' => 'ref/buildplan/ArcanistBuildPlanRef.php', + 'ArcanistBuildPlanSymbolRef' => 'ref/buildplan/ArcanistBuildPlanSymbolRef.php', + 'ArcanistBuildRef' => 'ref/build/ArcanistBuildRef.php', + 'ArcanistBuildSymbolRef' => 'ref/build/ArcanistBuildSymbolRef.php', + 'ArcanistBuildableBuildsHardpointQuery' => 'ref/buildable/ArcanistBuildableBuildsHardpointQuery.php', + 'ArcanistBuildableRef' => 'ref/buildable/ArcanistBuildableRef.php', + 'ArcanistBuildableSymbolRef' => 'ref/buildable/ArcanistBuildableSymbolRef.php', 'ArcanistBundle' => 'parser/ArcanistBundle.php', 'ArcanistBundleTestCase' => 'parser/__tests__/ArcanistBundleTestCase.php', 'ArcanistCSSLintLinter' => 'lint/linter/ArcanistCSSLintLinter.php', @@ -401,8 +407,9 @@ 'ArcanistReusedIteratorXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistReusedIteratorXHPASTLinterRule.php', 'ArcanistReusedIteratorXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistReusedIteratorXHPASTLinterRuleTestCase.php', 'ArcanistRevisionAuthorHardpointQuery' => 'ref/revision/ArcanistRevisionAuthorHardpointQuery.php', + 'ArcanistRevisionBuildableHardpointQuery' => 'ref/revision/ArcanistRevisionBuildableHardpointQuery.php', 'ArcanistRevisionCommitMessageHardpointQuery' => 'ref/revision/ArcanistRevisionCommitMessageHardpointQuery.php', - 'ArcanistRevisionParentRevisionRefsHardpointQuery' => 'ref/revision/ArcanistRevisionParentRevisionRefsHardpointQuery.php', + 'ArcanistRevisionParentRevisionsHardpointQuery' => 'ref/revision/ArcanistRevisionParentRevisionsHardpointQuery.php', 'ArcanistRevisionRef' => 'ref/revision/ArcanistRevisionRef.php', 'ArcanistRevisionRefSource' => 'ref/ArcanistRevisionRefSource.php', 'ArcanistRevisionSymbolRef' => 'ref/revision/ArcanistRevisionSymbolRef.php', @@ -1048,8 +1055,23 @@ 'ArcanistBrowseURIHardpointQuery' => 'ArcanistRuntimeHardpointQuery', 'ArcanistBrowseURIRef' => 'ArcanistRef', 'ArcanistBrowseWorkflow' => 'ArcanistArcWorkflow', - 'ArcanistBuildPlanRef' => 'Phobject', - 'ArcanistBuildRef' => 'Phobject', + 'ArcanistBuildBuildplanHardpointQuery' => 'ArcanistRuntimeHardpointQuery', + 'ArcanistBuildPlanRef' => array( + 'ArcanistRef', + 'ArcanistDisplayRefInterface', + ), + 'ArcanistBuildPlanSymbolRef' => 'ArcanistSimpleSymbolRef', + 'ArcanistBuildRef' => array( + 'ArcanistRef', + 'ArcanistDisplayRefInterface', + ), + 'ArcanistBuildSymbolRef' => 'ArcanistSimpleSymbolRef', + 'ArcanistBuildableBuildsHardpointQuery' => 'ArcanistRuntimeHardpointQuery', + 'ArcanistBuildableRef' => array( + 'ArcanistRef', + 'ArcanistDisplayRefInterface', + ), + 'ArcanistBuildableSymbolRef' => 'ArcanistSimpleSymbolRef', 'ArcanistBundle' => 'Phobject', 'ArcanistBundleTestCase' => 'PhutilTestCase', 'ArcanistCSSLintLinter' => 'ArcanistExternalLinter', @@ -1393,8 +1415,9 @@ 'ArcanistReusedIteratorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistReusedIteratorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistRevisionAuthorHardpointQuery' => 'ArcanistRuntimeHardpointQuery', + 'ArcanistRevisionBuildableHardpointQuery' => 'ArcanistRuntimeHardpointQuery', 'ArcanistRevisionCommitMessageHardpointQuery' => 'ArcanistRuntimeHardpointQuery', - 'ArcanistRevisionParentRevisionRefsHardpointQuery' => 'ArcanistRuntimeHardpointQuery', + 'ArcanistRevisionParentRevisionsHardpointQuery' => 'ArcanistRuntimeHardpointQuery', 'ArcanistRevisionRef' => array( 'ArcanistRef', 'ArcanistDisplayRefInterface', diff --git a/src/ref/ArcanistBuildPlanRef.php b/src/ref/ArcanistBuildPlanRef.php deleted file mode 100644 --- a/src/ref/ArcanistBuildPlanRef.php +++ /dev/null @@ -1,25 +0,0 @@ -parameters = $data; - return $ref; - } - - public function getPHID() { - return $this->parameters['phid']; - } - - public function getBehavior($behavior_key, $default = null) { - return idxv( - $this->parameters, - array('fields', 'behaviors', $behavior_key, 'value'), - $default); - } - -} diff --git a/src/ref/ArcanistBuildRef.php b/src/ref/ArcanistBuildRef.php deleted file mode 100644 --- a/src/ref/ArcanistBuildRef.php +++ /dev/null @@ -1,140 +0,0 @@ -parameters = $data; - return $ref; - } - - private function getStatusMap() { - // The modern "harbormaster.build.search" API method returns this in the - // "fields" list; the older API method returns it at the root level. - if (isset($this->parameters['fields']['buildStatus'])) { - $status = $this->parameters['fields']['buildStatus']; - } else if (isset($this->parameters['buildStatus'])) { - $status = $this->parameters['buildStatus']; - } else { - $status = 'unknown'; - } - - // We may either have an array or a scalar here. The array comes from - // "harbormaster.build.search", or from "harbormaster.querybuilds" if - // the server is newer than August 2016. The scalar comes from older - // versions of that method. See PHI261. - if (is_array($status)) { - $map = $status; - } else { - $map = array( - 'value' => $status, - ); - } - - // If we don't have a name, try to fill one in. - if (!isset($map['name'])) { - $name_map = array( - 'inactive' => pht('Inactive'), - 'pending' => pht('Pending'), - 'building' => pht('Building'), - 'passed' => pht('Passed'), - 'failed' => pht('Failed'), - 'aborted' => pht('Aborted'), - 'error' => pht('Error'), - 'paused' => pht('Paused'), - 'deadlocked' => pht('Deadlocked'), - 'unknown' => pht('Unknown'), - ); - - $map['name'] = idx($name_map, $map['value'], $map['value']); - } - - // If we don't have an ANSI color code, try to fill one in. - if (!isset($map['color.ansi'])) { - $color_map = array( - 'failed' => 'red', - 'passed' => 'green', - ); - - $map['color.ansi'] = idx($color_map, $map['value'], 'yellow'); - } - - return $map; - } - - public function getID() { - return $this->parameters['id']; - } - - public function getPHID() { - return $this->parameters['phid']; - } - - public function getName() { - if (isset($this->parameters['fields']['name'])) { - return $this->parameters['fields']['name']; - } - - return $this->parameters['name']; - } - - public function getStatus() { - $map = $this->getStatusMap(); - return $map['value']; - } - - public function getStatusName() { - $map = $this->getStatusMap(); - return $map['name']; - } - - public function getStatusANSIColor() { - $map = $this->getStatusMap(); - return $map['color.ansi']; - } - - public function getObjectName() { - return pht('Build %d', $this->getID()); - } - - public function getBuildPlanPHID() { - return idxv($this->parameters, array('fields', 'buildPlanPHID')); - } - - public function isComplete() { - switch ($this->getStatus()) { - case 'passed': - case 'failed': - case 'aborted': - case 'error': - case 'deadlocked': - return true; - default: - return false; - } - } - - public function isPassed() { - return ($this->getStatus() === 'passed'); - } - - public function getStatusSortVector() { - $status = $this->getStatus(); - - // For now, just sort passed builds first. - if ($this->isPassed()) { - $status_class = 1; - } else { - $status_class = 2; - } - - return id(new PhutilSortVector()) - ->addInt($status_class) - ->addString($status); - } - - -} diff --git a/src/ref/build/ArcanistBuildBuildplanHardpointQuery.php b/src/ref/build/ArcanistBuildBuildplanHardpointQuery.php new file mode 100644 --- /dev/null +++ b/src/ref/build/ArcanistBuildBuildplanHardpointQuery.php @@ -0,0 +1,44 @@ +yieldConduitSearch( + 'harbormaster.buildplan.search', + array( + 'phids' => $plan_phids, + ))); + + $plan_refs = array(); + foreach ($plans as $plan) { + $plan_ref = ArcanistBuildPlanRef::newFromConduit($plan); + $plan_refs[] = $plan_ref; + } + $plan_refs = mpull($plan_refs, 'getPHID'); + + $results = array(); + foreach ($refs as $key => $build_ref) { + $plan_phid = $build_ref->getBuildPlanPHID(); + $plan = idx($plan_refs, $plan_phid); + $results[$key] = $plan; + } + + yield $this->yieldMap($results); + } + +} diff --git a/src/ref/build/ArcanistBuildRef.php b/src/ref/build/ArcanistBuildRef.php new file mode 100644 --- /dev/null +++ b/src/ref/build/ArcanistBuildRef.php @@ -0,0 +1,106 @@ +newHardpoint(self::HARDPOINT_BUILDPLANREF), + ); + } + + public function getRefDisplayName() { + return $this->getDisplayRefObjectName(); + } + + public static function newFromConduit(array $parameters) { + $ref = new self(); + $ref->parameters = $parameters; + return $ref; + } + + public function getID() { + return idx($this->parameters, 'id'); + } + + public function getPHID() { + return idx($this->parameters, 'phid'); + } + + public function getName() { + return idxv($this->parameters, array('fields', 'name')); + } + + public function getDisplayRefObjectName() { + return pht('Build %d', $this->getID()); + } + + public function getDisplayRefTitle() { + return $this->getName(); + } + + public function getBuildPlanRef() { + return $this->getHardpoint(self::HARDPOINT_BUILDPLANREF); + } + + public function getBuildablePHID() { + return idxv($this->parameters, array('fields', 'buildablePHID')); + } + + public function getBuildPlanPHID() { + return idxv($this->parameters, array('fields', 'buildPlanPHID')); + } + + public function getStatus() { + return idxv($this->parameters, array('fields', 'buildStatus', 'value')); + } + + public function getStatusName() { + return idxv($this->parameters, array('fields', 'buildStatus', 'name')); + } + + public function getStatusANSIColor() { + return idxv( + $this->parameters, + array('fields', 'buildStatus', 'color.ansi')); + } + + public function isComplete() { + switch ($this->getStatus()) { + case 'passed': + case 'failed': + case 'aborted': + case 'error': + case 'deadlocked': + return true; + default: + return false; + } + } + + public function isPassed() { + return ($this->getStatus() === 'passed'); + } + + public function getStatusSortVector() { + $status = $this->getStatus(); + + // For now, just sort passed builds first. + if ($this->isPassed()) { + $status_class = 1; + } else { + $status_class = 2; + } + + return id(new PhutilSortVector()) + ->addInt($status_class) + ->addString($status); + } + +} diff --git a/src/ref/build/ArcanistBuildSymbolRef.php b/src/ref/build/ArcanistBuildSymbolRef.php new file mode 100644 --- /dev/null +++ b/src/ref/build/ArcanistBuildSymbolRef.php @@ -0,0 +1,30 @@ +getSymbol()); + } + + protected function getSimpleSymbolPHIDType() { + return 'HMBD'; + } + + public function getSimpleSymbolConduitSearchMethodName() { + return 'harbormaster.build.search'; + } + + public function getSimpleSymbolConduitSearchAttachments() { + return array(); + } + + public function getSimpleSymbolInspectFunctionName() { + return 'build'; + } + + public function newSimpleSymbolObjectRef() { + return new ArcanistBuildRef(); + } + +} diff --git a/src/ref/buildable/ArcanistBuildableBuildsHardpointQuery.php b/src/ref/buildable/ArcanistBuildableBuildsHardpointQuery.php new file mode 100644 --- /dev/null +++ b/src/ref/buildable/ArcanistBuildableBuildsHardpointQuery.php @@ -0,0 +1,43 @@ +yieldConduitSearch( + 'harbormaster.build.search', + array( + 'buildables' => $buildable_phids, + ))); + + $build_refs = array(); + foreach ($builds as $build) { + $build_ref = ArcanistBuildRef::newFromConduit($build); + $build_refs[] = $build_ref; + } + + $build_refs = mgroup($build_refs, 'getBuildablePHID'); + + $results = array(); + foreach ($refs as $key => $buildable_ref) { + $buildable_phid = $buildable_ref->getPHID(); + $buildable_builds = idx($build_refs, $buildable_phid, array()); + $results[$key] = $buildable_builds; + } + + yield $this->yieldMap($results); + } + +} diff --git a/src/ref/buildable/ArcanistBuildableRef.php b/src/ref/buildable/ArcanistBuildableRef.php new file mode 100644 --- /dev/null +++ b/src/ref/buildable/ArcanistBuildableRef.php @@ -0,0 +1,63 @@ +newTemplateHardpoint( + self::HARDPOINT_BUILDREFS, + $object_list), + ); + } + + public function getRefDisplayName() { + return pht('Buildable "%s"', $this->getMonogram()); + } + + public static function newFromConduit(array $parameters) { + $ref = new self(); + $ref->parameters = $parameters; + return $ref; + } + + public function getID() { + return idx($this->parameters, 'id'); + } + + public function getPHID() { + return idx($this->parameters, 'phid'); + } + + public function getName() { + return idxv($this->parameters, array('fields', 'name')); + } + + public function getObjectPHID() { + return idxv($this->parameters, array('fields', 'objectPHID')); + } + + public function getMonogram() { + return 'B'.$this->getID(); + } + + public function getDisplayRefObjectName() { + return $this->getMonogram(); + } + + public function getDisplayRefTitle() { + return $this->getName(); + } + + public function getBuildRefs() { + return $this->getHardpoint(self::HARDPOINT_BUILDREFS); + } + +} diff --git a/src/ref/buildable/ArcanistBuildableSymbolRef.php b/src/ref/buildable/ArcanistBuildableSymbolRef.php new file mode 100644 --- /dev/null +++ b/src/ref/buildable/ArcanistBuildableSymbolRef.php @@ -0,0 +1,30 @@ +getSymbol()); + } + + protected function getSimpleSymbolPHIDType() { + return 'HMBB'; + } + + public function getSimpleSymbolConduitSearchMethodName() { + return 'harbormaster.buildable.search'; + } + + public function getSimpleSymbolConduitSearchAttachments() { + return array(); + } + + public function getSimpleSymbolInspectFunctionName() { + return 'buildable'; + } + + public function newSimpleSymbolObjectRef() { + return new ArcanistBuildableRef(); + } + +} diff --git a/src/ref/buildplan/ArcanistBuildPlanRef.php b/src/ref/buildplan/ArcanistBuildPlanRef.php new file mode 100644 --- /dev/null +++ b/src/ref/buildplan/ArcanistBuildPlanRef.php @@ -0,0 +1,47 @@ +getDisplayRefObjectName(); + } + + public static function newFromConduit(array $parameters) { + $ref = new self(); + $ref->parameters = $parameters; + return $ref; + } + + public function getID() { + return idx($this->parameters, 'id'); + } + + public function getPHID() { + return idx($this->parameters, 'phid'); + } + + public function getName() { + return idxv($this->parameters, array('fields', 'name')); + } + + public function getDisplayRefObjectName() { + return pht('Build Plan %d', $this->getID()); + } + + public function getDisplayRefTitle() { + return $this->getName(); + } + + public function getBehavior($behavior_key, $default = null) { + return idxv( + $this->parameters, + array('fields', 'behaviors', $behavior_key, 'value'), + $default); + } + +} diff --git a/src/ref/buildplan/ArcanistBuildPlanSymbolRef.php b/src/ref/buildplan/ArcanistBuildPlanSymbolRef.php new file mode 100644 --- /dev/null +++ b/src/ref/buildplan/ArcanistBuildPlanSymbolRef.php @@ -0,0 +1,30 @@ +getSymbol()); + } + + protected function getSimpleSymbolPHIDType() { + return 'HMCP'; + } + + public function getSimpleSymbolConduitSearchMethodName() { + return 'harbormaster.buildplan.search'; + } + + public function getSimpleSymbolConduitSearchAttachments() { + return array(); + } + + public function getSimpleSymbolInspectFunctionName() { + return 'buildplan'; + } + + public function newSimpleSymbolObjectRef() { + return new ArcanistBuildPlanRef(); + } + +} diff --git a/src/ref/revision/ArcanistRevisionBuildableHardpointQuery.php b/src/ref/revision/ArcanistRevisionBuildableHardpointQuery.php new file mode 100644 --- /dev/null +++ b/src/ref/revision/ArcanistRevisionBuildableHardpointQuery.php @@ -0,0 +1,60 @@ + $revision_ref) { + $diff_phid = $revision_ref->getDiffPHID(); + if ($diff_phid) { + $diff_map[$key] = $diff_phid; + } + } + + if (!$diff_map) { + yield $this->yieldValue($refs, null); + } + + $buildables = (yield $this->yieldConduitSearch( + 'harbormaster.buildable.search', + array( + 'objectPHIDs' => $diff_map, + 'manual' => false, + ))); + + $buildable_refs = array(); + foreach ($buildables as $buildable) { + $buildable_ref = ArcanistBuildableRef::newFromConduit($buildable); + $object_phid = $buildable_ref->getObjectPHID(); + $buildable_refs[$object_phid] = $buildable_ref; + } + + $results = array_fill_keys(array_keys($refs), null); + foreach ($refs as $key => $revision_ref) { + if (!isset($diff_map[$key])) { + continue; + } + + $diff_phid = $diff_map[$key]; + if (!isset($buildable_refs[$diff_phid])) { + continue; + } + + $results[$key] = $buildable_refs[$diff_phid]; + } + + yield $this->yieldMap($results); + } + +} diff --git a/src/ref/revision/ArcanistRevisionParentRevisionRefsHardpointQuery.php b/src/ref/revision/ArcanistRevisionParentRevisionsHardpointQuery.php rename from src/ref/revision/ArcanistRevisionParentRevisionRefsHardpointQuery.php rename to src/ref/revision/ArcanistRevisionParentRevisionsHardpointQuery.php --- a/src/ref/revision/ArcanistRevisionParentRevisionRefsHardpointQuery.php +++ b/src/ref/revision/ArcanistRevisionParentRevisionsHardpointQuery.php @@ -1,6 +1,6 @@ newHardpoint(self::HARDPOINT_COMMITMESSAGE), $this->newHardpoint(self::HARDPOINT_AUTHORREF), + $this->newHardpoint(self::HARDPOINT_BUILDABLEREF), $this->newTemplateHardpoint( self::HARDPOINT_PARENTREVISIONREFS, $object_list), @@ -124,6 +126,10 @@ return idx($this->parameters, 'phid'); } + public function getDiffPHID() { + return idxv($this->parameters, array('fields', 'diffPHID')); + } + public function getName() { return idxv($this->parameters, array('fields', 'title')); } @@ -153,6 +159,10 @@ return $this->getHardpoint(self::HARDPOINT_PARENTREVISIONREFS); } + public function getBuildableRef() { + return $this->getHardpoint(self::HARDPOINT_BUILDABLEREF); + } + public function getDisplayRefObjectName() { return $this->getMonogram(); } diff --git a/src/ref/simple/ArcanistSimpleSymbolRef.php b/src/ref/simple/ArcanistSimpleSymbolRef.php --- a/src/ref/simple/ArcanistSimpleSymbolRef.php +++ b/src/ref/simple/ArcanistSimpleSymbolRef.php @@ -22,6 +22,10 @@ $matches = null; $prefix_pattern = $this->getSimpleSymbolPrefixPattern(); + if ($prefix_pattern === null) { + $prefix_pattern = ''; + } + $id_pattern = '(^'.$prefix_pattern.'([1-9]\d*)\z)'; $is_id = preg_match($id_pattern, $symbol, $matches); @@ -46,7 +50,10 @@ $symbol)); } - abstract protected function getSimpleSymbolPrefixPattern(); + protected function getSimpleSymbolPrefixPattern() { + return null; + } + abstract protected function getSimpleSymbolPHIDType(); abstract public function getSimpleSymbolConduitSearchMethodName(); abstract public function getSimpleSymbolInspectFunctionName();