Page MenuHomec4science

DiffusionTagsQueryConduitAPIMethod.php
No OneTemporary

File Metadata

Created
Thu, Aug 15, 12:28

DiffusionTagsQueryConduitAPIMethod.php

<?php
final class DiffusionTagsQueryConduitAPIMethod
extends DiffusionQueryConduitAPIMethod {
public function getAPIMethodName() {
return 'diffusion.tagsquery';
}
public function getMethodDescription() {
return pht('Retrieve information about tags in a repository.');
}
protected function defineReturnType() {
return 'array';
}
protected function defineCustomParamTypes() {
return array(
'names' => 'optional list<string>',
'commit' => 'optional string',
'needMessages' => 'optional bool',
'offset' => 'optional int',
'limit' => 'optional int',
);
}
protected function getGitResult(ConduitAPIRequest $request) {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$commit = $drequest->getSymbolicCommit();
$commit_filter = null;
if ($commit) {
$commit_filter = $this->loadTagNamesForCommit($commit);
}
$name_filter = $request->getValue('names', null);
$all_tags = $this->loadGitTagList();
$all_tags = mpull($all_tags, null, 'getName');
if ($name_filter !== null) {
$all_tags = array_intersect_key($all_tags, array_fuse($name_filter));
}
if ($commit_filter !== null) {
$all_tags = array_intersect_key($all_tags, $commit_filter);
}
$tags = array_values($all_tags);
$offset = $request->getValue('offset');
$limit = $request->getValue('limit');
if ($offset) {
$tags = array_slice($tags, $offset);
}
if ($limit) {
$tags = array_slice($tags, 0, $limit);
}
if ($request->getValue('needMessages')) {
$this->loadMessagesForTags($all_tags);
}
return mpull($tags, 'toDictionary');
}
private function loadGitTagList() {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$refs = id(new DiffusionLowLevelGitRefQuery())
->setRepository($repository)
->withIsTag(true)
->execute();
$tags = array();
foreach ($refs as $ref) {
$fields = $ref->getRawFields();
$tag = id(new DiffusionRepositoryTag())
->setAuthor($fields['author'])
->setEpoch($fields['epoch'])
->setCommitIdentifier($ref->getCommitIdentifier())
->setName($ref->getShortName())
->setDescription($fields['subject'])
->setType('git/'.$fields['objecttype']);
$tags[] = $tag;
}
return $tags;
}
private function loadTagNamesForCommit($commit) {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
list($err, $stdout) = $repository->execLocalCommand(
'tag -l --contains %s',
$commit);
if ($err) {
// Git exits with an error code if the commit is bogus.
return array();
}
$stdout = rtrim($stdout, "\n");
if (!strlen($stdout)) {
return array();
}
$tag_names = explode("\n", $stdout);
$tag_names = array_fill_keys($tag_names, true);
return $tag_names;
}
private function loadMessagesForTags(array $tags) {
assert_instances_of($tags, 'DiffusionRepositoryTag');
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$futures = array();
foreach ($tags as $key => $tag) {
$futures[$key] = $repository->getLocalCommandFuture(
'cat-file tag %s',
$tag->getName());
}
id(new FutureIterator($futures))
->resolveAll();
foreach ($tags as $key => $tag) {
$future = $futures[$key];
list($err, $stdout) = $future->resolve();
$message = null;
if ($err) {
// Not all tags are actually "tag" objects: a "tag" object is only
// created if you provide a message or sign the tag. Tags created with
// `git tag x [commit]` are "lightweight tags" and `git cat-file tag`
// will fail on them. This is fine: they don't have messages.
} else {
$parts = explode("\n\n", $stdout, 2);
if (count($parts) == 2) {
$message = last($parts);
}
}
$tag->attachMessage($message);
}
return $tags;
}
protected function getMercurialResult(ConduitAPIRequest $request) {
// For now, we don't support Mercurial tags via API.
return array();
}
protected function getSVNResult(ConduitAPIRequest $request) {
// Subversion has no meaningful concept of tags.
return array();
}
}

Event Timeline