@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+134 -48
+82 -39
src/applications/diffusion/conduit/ConduitAPI_diffusion_tagsquery_Method.php
··· 7 7 extends ConduitAPI_diffusion_abstractquery_Method { 8 8 9 9 public function getMethodDescription() { 10 - return 11 - 'Find tags for a given commit or list tags in the repository.'; 10 + return pht('Retrieve information about tags in a repository.'); 12 11 } 13 12 14 13 public function defineReturnType() { ··· 17 16 18 17 protected function defineCustomParamTypes() { 19 18 return array( 19 + 'names' => 'optional list<string>', 20 20 'commit' => 'optional string', 21 + 'needMessages' => 'optional bool', 21 22 'offset' => 'optional int', 22 23 'limit' => 'optional int', 23 24 ); ··· 28 29 $repository = $drequest->getRepository(); 29 30 $commit = $drequest->getRawCommit(); 30 31 31 - $offset = $request->getValue('offset'); 32 - $limit = $request->getValue('limit'); 33 - 34 - if (!$commit) { 35 - return $this->loadGitTagList($offset, $limit); 32 + $commit_filter = null; 33 + if ($commit) { 34 + $commit_filter = $this->loadTagNamesForCommit($commit); 36 35 } 37 36 38 - list($err, $stdout) = $repository->execLocalCommand( 39 - 'tag -l --contains %s', 40 - $commit); 37 + $name_filter = $request->getValue('names', null); 41 38 42 - if ($err) { 43 - // Git exits with an error code if the commit is bogus. 44 - return array(); 39 + $all_tags = $this->loadGitTagList(); 40 + $all_tags = mpull($all_tags, null, 'getName'); 41 + if ($name_filter !== null) { 42 + $all_tags = array_intersect_key($all_tags, array_fuse($name_filter)); 43 + } 44 + if ($commit_filter !== null) { 45 + $all_tags = array_intersect_key($all_tags, array_fuse($commit_filter)); 45 46 } 47 + $tags = array_values($all_tags); 46 48 47 - $stdout = trim($stdout); 48 - if (!strlen($stdout)) { 49 - return array(); 49 + $offset = $request->getValue('offset'); 50 + $limit = $request->getValue('limit'); 51 + if ($offset) { 52 + $tags = array_slice($tags, $offset); 50 53 } 51 54 52 - $tag_names = explode("\n", $stdout); 53 - $tag_names = array_fill_keys($tag_names, true); 54 - 55 - $tags = $this->loadGitTagList($offset = 0, $limit = 0, $serialize = false); 56 - 57 - $result = array(); 58 - foreach ($tags as $tag) { 59 - if (isset($tag_names[$tag->getName()])) { 60 - $result[] = $tag->toDictionary(); 61 - } 55 + if ($limit) { 56 + $tags = array_slice($tags, 0, $limit); 62 57 } 63 58 64 - if ($offset) { 65 - $result = array_slice($result, $offset); 66 - } 67 - if ($limit) { 68 - $result = array_slice($result, 0, $limit); 59 + if ($request->getValue('needMessages')) { 60 + $this->loadMessagesForTags($all_tags); 69 61 } 70 62 71 - return $result; 63 + return mpull($tags, 'toDictionary'); 72 64 } 73 65 74 - private function loadGitTagList($offset, $limit, $serialize=true) { 66 + private function loadGitTagList() { 75 67 $drequest = $this->getDiffusionRequest(); 76 68 $repository = $drequest->getRepository(); 77 69 ··· 94 86 $tags[] = $tag; 95 87 } 96 88 97 - if ($offset) { 98 - $tags = array_slice($tags, $offset); 89 + return $tags; 90 + } 91 + 92 + private function loadTagNamesForCommit($commit) { 93 + $drequest = $this->getDiffusionRequest(); 94 + $repository = $drequest->getRepository(); 95 + 96 + list($err, $stdout) = $repository->execLocalCommand( 97 + 'tag -l --contains %s', 98 + $commit); 99 + 100 + if ($err) { 101 + // Git exits with an error code if the commit is bogus. 102 + return array(); 99 103 } 100 104 101 - if ($limit) { 102 - $tags = array_slice($tags, 0, $limit); 105 + $stdout = rtrim($stdout, "\n"); 106 + if (!strlen($stdout)) { 107 + return array(); 103 108 } 104 109 105 - if ($serialize) { 106 - $tags = mpull($tags, 'toDictionary'); 110 + $tag_names = explode("\n", $stdout); 111 + $tag_names = array_fill_keys($tag_names, true); 112 + 113 + return $tag_names; 114 + } 115 + 116 + private function loadMessagesForTags(array $tags) { 117 + assert_instances_of($tags, 'DiffusionRepositoryTag'); 118 + 119 + $drequest = $this->getDiffusionRequest(); 120 + $repository = $drequest->getRepository(); 121 + 122 + $futures = array(); 123 + foreach ($tags as $key => $tag) { 124 + $futures[$key] = $repository->getLocalCommandFuture( 125 + 'cat-file tag %s', 126 + $tag->getName()); 107 127 } 128 + 129 + Futures($futures)->resolveAll(); 130 + 131 + foreach ($tags as $key => $tag) { 132 + $future = $futures[$key]; 133 + list($err, $stdout) = $future->resolve(); 134 + 135 + $message = null; 136 + if ($err) { 137 + // Not all tags are actually "tag" objects: a "tag" object is only 138 + // created if you provide a message or sign the tag. Tags created with 139 + // `git tag x [commit]` are "lightweight tags" and `git cat-file tag` 140 + // will fail on them. This is fine: they don't have messages. 141 + } else { 142 + $parts = explode("\n\n", $stdout, 2); 143 + if (count($parts) == 2) { 144 + $message = last($parts); 145 + } 146 + } 147 + 148 + $tag->attachMessage($message); 149 + } 150 + 108 151 return $tags; 109 152 } 110 153
+18 -6
src/applications/diffusion/controller/DiffusionBrowseController.php
··· 146 146 ), 147 147 $drequest->getRepository()->formatCommitName($stable_commit))); 148 148 149 - if ($drequest->getTagContent()) { 150 - $view->addProperty( 151 - pht('Tag'), 152 - $drequest->getSymbolicCommit()); 149 + if ($drequest->getCommitType() == 'tag') { 150 + $symbolic = $drequest->getSymbolicCommit(); 151 + $view->addProperty(pht('Tag'), $symbolic); 153 152 154 - $view->addSectionHeader(pht('Tag Content')); 155 - $view->addTextContent($this->markupText($drequest->getTagContent())); 153 + $tags = $this->callConduitWithDiffusionRequest( 154 + 'diffusion.tagsquery', 155 + array( 156 + 'names' => array($symbolic), 157 + 'needMessages' => true, 158 + )); 159 + $tags = DiffusionRepositoryTag::newFromConduit($tags); 160 + 161 + $tags = mpull($tags, null, 'getName'); 162 + $tag = idx($tags, $symbolic); 163 + 164 + if ($tag && strlen($tag->getMessage())) { 165 + $view->addSectionHeader(pht('Tag Content')); 166 + $view->addTextContent($this->markupText($tag->getMessage())); 167 + } 156 168 } 157 169 158 170 return $view;
+30 -3
src/applications/diffusion/data/DiffusionRepositoryTag.php
··· 9 9 private $description; 10 10 private $type; 11 11 12 + private $message = false; 13 + 12 14 public function setType($type) { 13 15 $this->type = $type; 14 16 return $this; ··· 63 65 return $this->author; 64 66 } 65 67 68 + public function attachMessage($message) { 69 + $this->message = $message; 70 + return $this; 71 + } 72 + 73 + public function getMessage() { 74 + if ($this->message === false) { 75 + throw new Exception("Message is not attached!"); 76 + } 77 + return $this->message; 78 + } 79 + 66 80 public function toDictionary() { 67 - return array( 81 + $dict = array( 68 82 'author' => $this->getAuthor(), 69 83 'epoch' => $this->getEpoch(), 70 84 'commitIdentifier' => $this->getCommitIdentifier(), 71 85 'name' => $this->getName(), 72 86 'description' => $this->getDescription(), 73 - 'type' => $this->getType()); 87 + 'type' => $this->getType(), 88 + ); 89 + 90 + if ($this->message !== false) { 91 + $dict['message'] = $this->message; 92 + } 93 + 94 + return $dict; 74 95 } 75 96 76 97 public static function newFromConduit(array $dicts) { 77 98 $tags = array(); 78 99 foreach ($dicts as $dict) { 79 - $tags[] = id(new DiffusionRepositoryTag()) 100 + $tag = id(new DiffusionRepositoryTag()) 80 101 ->setAuthor($dict['author']) 81 102 ->setEpoch($dict['epoch']) 82 103 ->setCommitIdentifier($dict['commitIdentifier']) 83 104 ->setName($dict['name']) 84 105 ->setDescription($dict['description']) 85 106 ->setType($dict['type']); 107 + 108 + if (array_key_exists('message', $dict)) { 109 + $tag->attachMessage($dict['message']); 110 + } 111 + 112 + $tags[] = $tag; 86 113 } 87 114 return $tags; 88 115 }
+4
src/applications/diffusion/request/DiffusionRequest.php
··· 646 646 $this->tagContent = $commit_data['tagContent']; 647 647 } 648 648 649 + public function getCommitType() { 650 + return $this->commitType; 651 + } 652 + 649 653 private function queryStableCommitName() { 650 654 if ($this->commit) { 651 655 $this->stableCommitName = $this->commit;