1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-01 09:28:22 +01:00

Fix tag content display in Git

Summary: Fixes the junk I broke in D7484. Before that, tag content was a side effect of resolving the ref name. Now, fetch it explicitly in `diffusion.tagsquery`.

Test Plan: Looked at a tag, saw the annotation/message.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Differential Revision: https://secure.phabricator.com/D7485
This commit is contained in:
epriestley 2013-11-04 12:16:53 -08:00
parent 90a9e90675
commit 8f3ae81143
4 changed files with 140 additions and 54 deletions

View file

@ -7,8 +7,7 @@ final class ConduitAPI_diffusion_tagsquery_Method
extends ConduitAPI_diffusion_abstractquery_Method { extends ConduitAPI_diffusion_abstractquery_Method {
public function getMethodDescription() { public function getMethodDescription() {
return return pht('Retrieve information about tags in a repository.');
'Find tags for a given commit or list tags in the repository.';
} }
public function defineReturnType() { public function defineReturnType() {
@ -17,7 +16,9 @@ final class ConduitAPI_diffusion_tagsquery_Method
protected function defineCustomParamTypes() { protected function defineCustomParamTypes() {
return array( return array(
'names' => 'optional list<string>',
'commit' => 'optional string', 'commit' => 'optional string',
'needMessages' => 'optional bool',
'offset' => 'optional int', 'offset' => 'optional int',
'limit' => 'optional int', 'limit' => 'optional int',
); );
@ -28,50 +29,41 @@ final class ConduitAPI_diffusion_tagsquery_Method
$repository = $drequest->getRepository(); $repository = $drequest->getRepository();
$commit = $drequest->getRawCommit(); $commit = $drequest->getRawCommit();
$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, array_fuse($commit_filter));
}
$tags = array_values($all_tags);
$offset = $request->getValue('offset'); $offset = $request->getValue('offset');
$limit = $request->getValue('limit'); $limit = $request->getValue('limit');
if (!$commit) {
return $this->loadGitTagList($offset, $limit);
}
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 = trim($stdout);
if (!strlen($stdout)) {
return array();
}
$tag_names = explode("\n", $stdout);
$tag_names = array_fill_keys($tag_names, true);
$tags = $this->loadGitTagList($offset = 0, $limit = 0, $serialize = false);
$result = array();
foreach ($tags as $tag) {
if (isset($tag_names[$tag->getName()])) {
$result[] = $tag->toDictionary();
}
}
if ($offset) { if ($offset) {
$result = array_slice($result, $offset); $tags = array_slice($tags, $offset);
}
if ($limit) {
$result = array_slice($result, 0, $limit);
} }
return $result; if ($limit) {
$tags = array_slice($tags, 0, $limit);
}
if ($request->getValue('needMessages')) {
$this->loadMessagesForTags($all_tags);
}
return mpull($tags, 'toDictionary');
} }
private function loadGitTagList($offset, $limit, $serialize=true) { private function loadGitTagList() {
$drequest = $this->getDiffusionRequest(); $drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository(); $repository = $drequest->getRepository();
@ -94,17 +86,68 @@ final class ConduitAPI_diffusion_tagsquery_Method
$tags[] = $tag; $tags[] = $tag;
} }
if ($offset) { return $tags;
$tags = array_slice($tags, $offset); }
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();
} }
if ($limit) { $stdout = rtrim($stdout, "\n");
$tags = array_slice($tags, 0, $limit); if (!strlen($stdout)) {
return array();
} }
if ($serialize) { $tag_names = explode("\n", $stdout);
$tags = mpull($tags, 'toDictionary'); $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());
} }
Futures($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; return $tags;
} }

View file

@ -146,13 +146,25 @@ abstract class DiffusionBrowseController extends DiffusionController {
), ),
$drequest->getRepository()->formatCommitName($stable_commit))); $drequest->getRepository()->formatCommitName($stable_commit)));
if ($drequest->getTagContent()) { if ($drequest->getCommitType() == 'tag') {
$view->addProperty( $symbolic = $drequest->getSymbolicCommit();
pht('Tag'), $view->addProperty(pht('Tag'), $symbolic);
$drequest->getSymbolicCommit());
$view->addSectionHeader(pht('Tag Content')); $tags = $this->callConduitWithDiffusionRequest(
$view->addTextContent($this->markupText($drequest->getTagContent())); 'diffusion.tagsquery',
array(
'names' => array($symbolic),
'needMessages' => true,
));
$tags = DiffusionRepositoryTag::newFromConduit($tags);
$tags = mpull($tags, null, 'getName');
$tag = idx($tags, $symbolic);
if ($tag && strlen($tag->getMessage())) {
$view->addSectionHeader(pht('Tag Content'));
$view->addTextContent($this->markupText($tag->getMessage()));
}
} }
return $view; return $view;

View file

@ -9,6 +9,8 @@ final class DiffusionRepositoryTag {
private $description; private $description;
private $type; private $type;
private $message = false;
public function setType($type) { public function setType($type) {
$this->type = $type; $this->type = $type;
return $this; return $this;
@ -63,26 +65,51 @@ final class DiffusionRepositoryTag {
return $this->author; return $this->author;
} }
public function attachMessage($message) {
$this->message = $message;
return $this;
}
public function getMessage() {
if ($this->message === false) {
throw new Exception("Message is not attached!");
}
return $this->message;
}
public function toDictionary() { public function toDictionary() {
return array( $dict = array(
'author' => $this->getAuthor(), 'author' => $this->getAuthor(),
'epoch' => $this->getEpoch(), 'epoch' => $this->getEpoch(),
'commitIdentifier' => $this->getCommitIdentifier(), 'commitIdentifier' => $this->getCommitIdentifier(),
'name' => $this->getName(), 'name' => $this->getName(),
'description' => $this->getDescription(), 'description' => $this->getDescription(),
'type' => $this->getType()); 'type' => $this->getType(),
);
if ($this->message !== false) {
$dict['message'] = $this->message;
}
return $dict;
} }
public static function newFromConduit(array $dicts) { public static function newFromConduit(array $dicts) {
$tags = array(); $tags = array();
foreach ($dicts as $dict) { foreach ($dicts as $dict) {
$tags[] = id(new DiffusionRepositoryTag()) $tag = id(new DiffusionRepositoryTag())
->setAuthor($dict['author']) ->setAuthor($dict['author'])
->setEpoch($dict['epoch']) ->setEpoch($dict['epoch'])
->setCommitIdentifier($dict['commitIdentifier']) ->setCommitIdentifier($dict['commitIdentifier'])
->setName($dict['name']) ->setName($dict['name'])
->setDescription($dict['description']) ->setDescription($dict['description'])
->setType($dict['type']); ->setType($dict['type']);
if (array_key_exists('message', $dict)) {
$tag->attachMessage($dict['message']);
}
$tags[] = $tag;
} }
return $tags; return $tags;
} }

View file

@ -646,6 +646,10 @@ abstract class DiffusionRequest {
$this->tagContent = $commit_data['tagContent']; $this->tagContent = $commit_data['tagContent'];
} }
public function getCommitType() {
return $this->commitType;
}
private function queryStableCommitName() { private function queryStableCommitName() {
if ($this->commit) { if ($this->commit) {
$this->stableCommitName = $this->commit; $this->stableCommitName = $this->commit;