Add support for tag web links

Change-Id: If431ad869e53d97e1f479edaf24e17f3b9ecbda2
This commit is contained in:
Paladox none
2017-07-01 14:49:10 +00:00
committed by David Pursehouse
parent e067dc8af9
commit 433e1a9102
12 changed files with 151 additions and 19 deletions

View File

@@ -2193,6 +2193,8 @@ BranchWebLinks will appear in the branch list in the last column.
FileHistoryWebLinks will appear on the access rights screen. FileHistoryWebLinks will appear on the access rights screen.
TagWebLinks will appear in the tag list in the last column.
[[lfs-extension]] [[lfs-extension]]
== LFS Storage Plugins == LFS Storage Plugins

View File

@@ -2882,6 +2882,9 @@ the signature.
link:rest-api-changes.html#git-person-info[GitPersonInfo] entity. link:rest-api-changes.html#git-person-info[GitPersonInfo] entity.
|`can_delete`|`false` if not set| |`can_delete`|`false` if not set|
Whether the calling user can delete this tag. Whether the calling user can delete this tag.
|`web_links` |optional|
Links to the tag in external sites as a list of
link:rest-api-changes.html#web-link-info[WebLinkInfo] entries.
|========================= |=========================
[[tag-input]] [[tag-input]]

View File

@@ -24,6 +24,7 @@ public class GitwebType {
private String project; private String project;
private String revision; private String revision;
private String rootTree; private String rootTree;
private String tag;
private char pathSeparator = '/'; private char pathSeparator = '/';
private boolean urlEncode = true; private boolean urlEncode = true;
@@ -56,6 +57,20 @@ public class GitwebType {
branch = str; branch = str;
} }
/** @return parameterized string for the tag URL. */
public String getTag() {
return tag;
}
/**
* Set the parameterized string for the tag URL.
*
* @param str new string.
*/
public void setTag(String str) {
tag = str;
}
/** @return parameterized string for the file URL. */ /** @return parameterized string for the file URL. */
public String getFile() { public String getFile() {
return file; return file;

View File

@@ -15,16 +15,20 @@
package com.google.gerrit.extensions.api.projects; package com.google.gerrit.extensions.api.projects;
import com.google.gerrit.extensions.common.GitPerson; import com.google.gerrit.extensions.common.GitPerson;
import com.google.gerrit.extensions.common.WebLinkInfo;
import java.util.List;
public class TagInfo extends RefInfo { public class TagInfo extends RefInfo {
public String object; public String object;
public String message; public String message;
public GitPerson tagger; public GitPerson tagger;
public List<WebLinkInfo> webLinks;
public TagInfo(String ref, String revision, boolean canDelete) { public TagInfo(String ref, String revision, boolean canDelete, List<WebLinkInfo> webLinks) {
this.ref = ref; this.ref = ref;
this.revision = revision; this.revision = revision;
this.canDelete = canDelete; this.canDelete = canDelete;
this.webLinks = webLinks;
} }
public TagInfo( public TagInfo(
@@ -33,10 +37,12 @@ public class TagInfo extends RefInfo {
String object, String object,
String message, String message,
GitPerson tagger, GitPerson tagger,
boolean canDelete) { boolean canDelete,
this(ref, revision, canDelete); List<WebLinkInfo> webLinks) {
this(ref, revision, canDelete, webLinks);
this.object = object; this.object = object;
this.message = message; this.message = message;
this.tagger = tagger; this.tagger = tagger;
this.webLinks = webLinks;
} }
} }

View File

@@ -0,0 +1,38 @@
// Copyright (C) 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.extensions.webui;
import com.google.gerrit.extensions.annotations.ExtensionPoint;
import com.google.gerrit.extensions.common.WebLinkInfo;
@ExtensionPoint
public interface TagWebLink extends WebLink {
/**
* {@link com.google.gerrit.extensions.common.WebLinkInfo} describing a link from a tag to an
* external service.
*
* <p>In order for the web link to be visible {@link
* com.google.gerrit.extensions.common.WebLinkInfo#url} and {@link
* com.google.gerrit.extensions.common.WebLinkInfo#name} must be set.
*
* <p>
*
* @param projectName Name of the project
* @param tagName Name of the tag
* @return WebLinkInfo that links to tag in external service, null if there should be no link.
*/
WebLinkInfo getTagWebLink(String projectName, String tagName);
}

View File

@@ -23,6 +23,7 @@ import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.VoidResult; import com.google.gerrit.client.VoidResult;
import com.google.gerrit.client.access.AccessMap; import com.google.gerrit.client.access.AccessMap;
import com.google.gerrit.client.access.ProjectAccessInfo; import com.google.gerrit.client.access.ProjectAccessInfo;
import com.google.gerrit.client.info.WebLinkInfo;
import com.google.gerrit.client.projects.ProjectApi; import com.google.gerrit.client.projects.ProjectApi;
import com.google.gerrit.client.projects.TagInfo; import com.google.gerrit.client.projects.TagInfo;
import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.GerritCallback;
@@ -301,6 +302,7 @@ public class ProjectTagsScreen extends PaginatedProjectScreen {
fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().iconHeader()); fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().iconHeader());
fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader()); fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader()); fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
fmt.addStyleName(0, 4, Gerrit.RESOURCES.css().dataHeader());
updateDeleteHandler = updateDeleteHandler =
new ValueChangeHandler<Boolean>() { new ValueChangeHandler<Boolean>() {
@@ -431,12 +433,21 @@ public class ProjectTagsScreen extends PaginatedProjectScreen {
table.setText(row, 3, ""); table.setText(row, 3, "");
} }
FlowPanel actionsPanel = new FlowPanel();
if (k.webLinks() != null) {
for (WebLinkInfo webLink : Natives.asList(k.webLinks())) {
actionsPanel.add(webLink.toAnchor());
}
}
table.setWidget(row, 4, actionsPanel);
FlexCellFormatter fmt = table.getFlexCellFormatter(); FlexCellFormatter fmt = table.getFlexCellFormatter();
String iconCellStyle = Gerrit.RESOURCES.css().iconCell(); String iconCellStyle = Gerrit.RESOURCES.css().iconCell();
String dataCellStyle = Gerrit.RESOURCES.css().dataCell(); String dataCellStyle = Gerrit.RESOURCES.css().dataCell();
fmt.addStyleName(row, 1, iconCellStyle); fmt.addStyleName(row, 1, iconCellStyle);
fmt.addStyleName(row, 2, dataCellStyle); fmt.addStyleName(row, 2, dataCellStyle);
fmt.addStyleName(row, 3, dataCellStyle); fmt.addStyleName(row, 3, dataCellStyle);
fmt.addStyleName(row, 4, dataCellStyle);
setRowItem(row, k); setRowItem(row, k);
} }

View File

@@ -14,9 +14,14 @@
package com.google.gerrit.client.projects; package com.google.gerrit.client.projects;
import com.google.gerrit.client.info.WebLinkInfo;
import com.google.gwt.core.client.JsArray;
public class TagInfo extends RefInfo { public class TagInfo extends RefInfo {
public final native boolean canDelete() /*-{ return this['can_delete'] ? true : false; }-*/; public final native boolean canDelete() /*-{ return this['can_delete'] ? true : false; }-*/;
public final native JsArray<WebLinkInfo> webLinks() /*-{ return this.web_links; }-*/;
// TODO(dpursehouse) add extra tag-related fields (message, tagger, etc) // TODO(dpursehouse) add extra tag-related fields (message, tagger, etc)
protected TagInfo() {} protected TagInfo() {}
} }

View File

@@ -29,6 +29,7 @@ import com.google.gerrit.extensions.webui.FileWebLink;
import com.google.gerrit.extensions.webui.ParentWebLink; import com.google.gerrit.extensions.webui.ParentWebLink;
import com.google.gerrit.extensions.webui.PatchSetWebLink; import com.google.gerrit.extensions.webui.PatchSetWebLink;
import com.google.gerrit.extensions.webui.ProjectWebLink; import com.google.gerrit.extensions.webui.ProjectWebLink;
import com.google.gerrit.extensions.webui.TagWebLink;
import com.google.gerrit.extensions.webui.WebLink; import com.google.gerrit.extensions.webui.WebLink;
import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project;
import com.google.inject.Inject; import com.google.inject.Inject;
@@ -70,6 +71,7 @@ public class WebLinks {
private final DynamicSet<DiffWebLink> diffLinks; private final DynamicSet<DiffWebLink> diffLinks;
private final DynamicSet<ProjectWebLink> projectLinks; private final DynamicSet<ProjectWebLink> projectLinks;
private final DynamicSet<BranchWebLink> branchLinks; private final DynamicSet<BranchWebLink> branchLinks;
private final DynamicSet<TagWebLink> tagLinks;
@Inject @Inject
public WebLinks( public WebLinks(
@@ -79,7 +81,8 @@ public class WebLinks {
DynamicSet<FileHistoryWebLink> fileLogLinks, DynamicSet<FileHistoryWebLink> fileLogLinks,
DynamicSet<DiffWebLink> diffLinks, DynamicSet<DiffWebLink> diffLinks,
DynamicSet<ProjectWebLink> projectLinks, DynamicSet<ProjectWebLink> projectLinks,
DynamicSet<BranchWebLink> branchLinks) { DynamicSet<BranchWebLink> branchLinks,
DynamicSet<TagWebLink> tagLinks) {
this.patchSetLinks = patchSetLinks; this.patchSetLinks = patchSetLinks;
this.parentLinks = parentLinks; this.parentLinks = parentLinks;
this.fileLinks = fileLinks; this.fileLinks = fileLinks;
@@ -87,6 +90,7 @@ public class WebLinks {
this.diffLinks = diffLinks; this.diffLinks = diffLinks;
this.projectLinks = projectLinks; this.projectLinks = projectLinks;
this.branchLinks = branchLinks; this.branchLinks = branchLinks;
this.tagLinks = tagLinks;
} }
/** /**
@@ -194,6 +198,15 @@ public class WebLinks {
return filterLinks(branchLinks, webLink -> webLink.getBranchWebLink(project, branch)); return filterLinks(branchLinks, webLink -> webLink.getBranchWebLink(project, branch));
} }
/**
* @param project Project name
* @param tag Tag name
* @return Links for tags.
*/
public List<WebLinkInfo> getTagLinks(String project, String tag) {
return filterLinks(tagLinks, webLink -> webLink.getTagWebLink(project, tag));
}
private <T extends WebLink> List<WebLinkInfo> filterLinks( private <T extends WebLink> List<WebLinkInfo> filterLinks(
DynamicSet<T> links, Function<T, WebLinkInfo> transformer) { DynamicSet<T> links, Function<T, WebLinkInfo> transformer) {
return FluentIterable.from(links).transform(transformer).filter(INVALID_WEBLINK).toList(); return FluentIterable.from(links).transform(transformer).filter(INVALID_WEBLINK).toList();

View File

@@ -67,6 +67,7 @@ import com.google.gerrit.extensions.webui.FileWebLink;
import com.google.gerrit.extensions.webui.ParentWebLink; import com.google.gerrit.extensions.webui.ParentWebLink;
import com.google.gerrit.extensions.webui.PatchSetWebLink; import com.google.gerrit.extensions.webui.PatchSetWebLink;
import com.google.gerrit.extensions.webui.ProjectWebLink; import com.google.gerrit.extensions.webui.ProjectWebLink;
import com.google.gerrit.extensions.webui.TagWebLink;
import com.google.gerrit.extensions.webui.TopMenu; import com.google.gerrit.extensions.webui.TopMenu;
import com.google.gerrit.extensions.webui.WebUiPlugin; import com.google.gerrit.extensions.webui.WebUiPlugin;
import com.google.gerrit.rules.PrologModule; import com.google.gerrit.rules.PrologModule;
@@ -366,6 +367,7 @@ public class GerritGlobalModule extends FactoryModule {
DynamicSet.setOf(binder(), DiffWebLink.class); DynamicSet.setOf(binder(), DiffWebLink.class);
DynamicSet.setOf(binder(), ProjectWebLink.class); DynamicSet.setOf(binder(), ProjectWebLink.class);
DynamicSet.setOf(binder(), BranchWebLink.class); DynamicSet.setOf(binder(), BranchWebLink.class);
DynamicSet.setOf(binder(), TagWebLink.class);
DynamicMap.mapOf(binder(), OAuthLoginProvider.class); DynamicMap.mapOf(binder(), OAuthLoginProvider.class);
DynamicItem.itemOf(binder(), OAuthTokenEncrypter.class); DynamicItem.itemOf(binder(), OAuthTokenEncrypter.class);
DynamicSet.setOf(binder(), AccountExternalIdCreator.class); DynamicSet.setOf(binder(), AccountExternalIdCreator.class);

View File

@@ -31,6 +31,7 @@ import com.google.gerrit.extensions.webui.FileWebLink;
import com.google.gerrit.extensions.webui.ParentWebLink; import com.google.gerrit.extensions.webui.ParentWebLink;
import com.google.gerrit.extensions.webui.PatchSetWebLink; import com.google.gerrit.extensions.webui.PatchSetWebLink;
import com.google.gerrit.extensions.webui.ProjectWebLink; import com.google.gerrit.extensions.webui.ProjectWebLink;
import com.google.gerrit.extensions.webui.TagWebLink;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Singleton; import com.google.inject.Singleton;
@@ -64,6 +65,10 @@ public class GitwebConfig {
DynamicSet.bind(binder(), BranchWebLink.class).to(GitwebLinks.class); DynamicSet.bind(binder(), BranchWebLink.class).to(GitwebLinks.class);
} }
if (!isNullOrEmpty(type.getTag())) {
DynamicSet.bind(binder(), TagWebLink.class).to(GitwebLinks.class);
}
if (!isNullOrEmpty(type.getFile()) || !isNullOrEmpty(type.getRootTree())) { if (!isNullOrEmpty(type.getFile()) || !isNullOrEmpty(type.getRootTree())) {
DynamicSet.bind(binder(), FileWebLink.class).to(GitwebLinks.class); DynamicSet.bind(binder(), FileWebLink.class).to(GitwebLinks.class);
} }
@@ -101,6 +106,7 @@ public class GitwebConfig {
type.setLinkName( type.setLinkName(
firstNonNull(cfg.getString("gitweb", null, "linkname"), defaultType.getLinkName())); firstNonNull(cfg.getString("gitweb", null, "linkname"), defaultType.getLinkName()));
type.setBranch(firstNonNull(cfg.getString("gitweb", null, "branch"), defaultType.getBranch())); type.setBranch(firstNonNull(cfg.getString("gitweb", null, "branch"), defaultType.getBranch()));
type.setTag(firstNonNull(cfg.getString("gitweb", null, "tag"), defaultType.getTag()));
type.setProject( type.setProject(
firstNonNull(cfg.getString("gitweb", null, "project"), defaultType.getProject())); firstNonNull(cfg.getString("gitweb", null, "project"), defaultType.getProject()));
type.setRevision( type.setRevision(
@@ -135,6 +141,7 @@ public class GitwebConfig {
type.setProject("?p=${project}.git;a=summary"); type.setProject("?p=${project}.git;a=summary");
type.setRevision("?p=${project}.git;a=commit;h=${commit}"); type.setRevision("?p=${project}.git;a=commit;h=${commit}");
type.setBranch("?p=${project}.git;a=shortlog;h=${branch}"); type.setBranch("?p=${project}.git;a=shortlog;h=${branch}");
type.setTag("?p=${project}.git;a=tag;h=${tag}");
type.setRootTree("?p=${project}.git;a=tree;hb=${commit}"); type.setRootTree("?p=${project}.git;a=tree;hb=${commit}");
type.setFile("?p=${project}.git;hb=${commit};f=${file}"); type.setFile("?p=${project}.git;hb=${commit};f=${file}");
type.setFileHistory("?p=${project}.git;a=history;hb=${branch};f=${file}"); type.setFileHistory("?p=${project}.git;a=history;hb=${branch};f=${file}");
@@ -144,6 +151,7 @@ public class GitwebConfig {
type.setProject("${project}.git/summary"); type.setProject("${project}.git/summary");
type.setRevision("${project}.git/commit/?id=${commit}"); type.setRevision("${project}.git/commit/?id=${commit}");
type.setBranch("${project}.git/log/?h=${branch}"); type.setBranch("${project}.git/log/?h=${branch}");
type.setTag("${project}.git/tag/?h=${tag}");
type.setRootTree("${project}.git/tree/?h=${commit}"); type.setRootTree("${project}.git/tree/?h=${commit}");
type.setFile("${project}.git/tree/${file}?h=${commit}"); type.setFile("${project}.git/tree/${file}?h=${commit}");
type.setFileHistory("${project}.git/log/${file}?h=${branch}"); type.setFileHistory("${project}.git/log/${file}?h=${branch}");
@@ -154,6 +162,7 @@ public class GitwebConfig {
type.setProject(""); type.setProject("");
type.setRevision(""); type.setRevision("");
type.setBranch(""); type.setBranch("");
type.setTag("");
type.setRootTree(""); type.setRootTree("");
type.setFile(""); type.setFile("");
type.setFileHistory(""); type.setFileHistory("");
@@ -236,7 +245,8 @@ public class GitwebConfig {
FileWebLink, FileWebLink,
PatchSetWebLink, PatchSetWebLink,
ParentWebLink, ParentWebLink,
ProjectWebLink { ProjectWebLink,
TagWebLink {
private final String url; private final String url;
private final GitwebType type; private final GitwebType type;
private final ParameterizedString branch; private final ParameterizedString branch;
@@ -244,6 +254,7 @@ public class GitwebConfig {
private final ParameterizedString fileHistory; private final ParameterizedString fileHistory;
private final ParameterizedString project; private final ParameterizedString project;
private final ParameterizedString revision; private final ParameterizedString revision;
private final ParameterizedString tag;
@Inject @Inject
GitwebLinks(GitwebConfig config, GitwebType type) { GitwebLinks(GitwebConfig config, GitwebType type) {
@@ -254,6 +265,7 @@ public class GitwebConfig {
this.fileHistory = parse(type.getFileHistory()); this.fileHistory = parse(type.getFileHistory());
this.project = parse(type.getProject()); this.project = parse(type.getProject());
this.revision = parse(type.getRevision()); this.revision = parse(type.getRevision());
this.tag = parse(type.getTag());
} }
@Override @Override
@@ -268,6 +280,15 @@ public class GitwebConfig {
return null; return null;
} }
@Override
public WebLinkInfo getTagWebLink(String projectName, String tagName) {
if (tag != null) {
return link(
tag.replace("project", encode(projectName)).replace("tag", encode(tagName)).toString());
}
return null;
}
@Override @Override
public WebLinkInfo getFileHistoryWebLink(String projectName, String revision, String fileName) { public WebLinkInfo getFileHistoryWebLink(String projectName, String revision, String fileName) {
if (fileHistory != null) { if (fileHistory != null) {

View File

@@ -28,6 +28,7 @@ import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestApiException; import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestModifyView; import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.WebLinks;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated; import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.TagCache; import com.google.gerrit.server.git.TagCache;
@@ -60,6 +61,7 @@ public class CreateTag implements RestModifyView<ProjectResource, TagInput> {
private final GitRepositoryManager repoManager; private final GitRepositoryManager repoManager;
private final TagCache tagCache; private final TagCache tagCache;
private final GitReferenceUpdated referenceUpdated; private final GitReferenceUpdated referenceUpdated;
private final WebLinks links;
private String ref; private String ref;
@Inject @Inject
@@ -68,11 +70,13 @@ public class CreateTag implements RestModifyView<ProjectResource, TagInput> {
GitRepositoryManager repoManager, GitRepositoryManager repoManager,
TagCache tagCache, TagCache tagCache,
GitReferenceUpdated referenceUpdated, GitReferenceUpdated referenceUpdated,
WebLinks webLinks,
@Assisted String ref) { @Assisted String ref) {
this.identifiedUser = identifiedUser; this.identifiedUser = identifiedUser;
this.repoManager = repoManager; this.repoManager = repoManager;
this.tagCache = tagCache; this.tagCache = tagCache;
this.referenceUpdated = referenceUpdated; this.referenceUpdated = referenceUpdated;
this.links = webLinks;
this.ref = ref; this.ref = ref;
} }
@@ -134,7 +138,8 @@ public class CreateTag implements RestModifyView<ProjectResource, TagInput> {
result.getObjectId(), result.getObjectId(),
identifiedUser.get().getAccount()); identifiedUser.get().getAccount());
try (RevWalk w = new RevWalk(repo)) { try (RevWalk w = new RevWalk(repo)) {
return ListTags.createTagInfo(result, w, refControl); ProjectControl pctl = resource.getControl();
return ListTags.createTagInfo(result, w, refControl, pctl, links);
} }
} }
} catch (InvalidRevisionException e) { } catch (InvalidRevisionException e) {

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.server.project;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.gerrit.common.Nullable; import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.api.projects.TagInfo; import com.google.gerrit.extensions.api.projects.TagInfo;
import com.google.gerrit.extensions.common.WebLinkInfo;
import com.google.gerrit.extensions.restapi.BadRequestException; import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.IdString; import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
@@ -24,6 +25,7 @@ import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CommonConverters; import com.google.gerrit.server.CommonConverters;
import com.google.gerrit.server.WebLinks;
import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.SearchingChangeCacheImpl; import com.google.gerrit.server.git.SearchingChangeCacheImpl;
import com.google.gerrit.server.git.TagCache; import com.google.gerrit.server.git.TagCache;
@@ -54,6 +56,7 @@ public class ListTags implements RestReadView<ProjectResource> {
private final TagCache tagCache; private final TagCache tagCache;
private final ChangeNotes.Factory changeNotesFactory; private final ChangeNotes.Factory changeNotesFactory;
@Nullable private final SearchingChangeCacheImpl changeCache; @Nullable private final SearchingChangeCacheImpl changeCache;
private final WebLinks links;
@Option( @Option(
name = "--limit", name = "--limit",
@@ -106,12 +109,14 @@ public class ListTags implements RestReadView<ProjectResource> {
Provider<ReviewDb> dbProvider, Provider<ReviewDb> dbProvider,
TagCache tagCache, TagCache tagCache,
ChangeNotes.Factory changeNotesFactory, ChangeNotes.Factory changeNotesFactory,
@Nullable SearchingChangeCacheImpl changeCache) { @Nullable SearchingChangeCacheImpl changeCache,
WebLinks webLinks) {
this.repoManager = repoManager; this.repoManager = repoManager;
this.dbProvider = dbProvider; this.dbProvider = dbProvider;
this.tagCache = tagCache; this.tagCache = tagCache;
this.changeNotesFactory = changeNotesFactory; this.changeNotesFactory = changeNotesFactory;
this.changeCache = changeCache; this.changeCache = changeCache;
this.links = webLinks;
} }
@Override @Override
@@ -121,11 +126,11 @@ public class ListTags implements RestReadView<ProjectResource> {
try (Repository repo = getRepository(resource.getNameKey()); try (Repository repo = getRepository(resource.getNameKey());
RevWalk rw = new RevWalk(repo)) { RevWalk rw = new RevWalk(repo)) {
ProjectControl control = resource.getControl(); ProjectControl pctl = resource.getControl();
Map<String, Ref> all = Map<String, Ref> all =
visibleTags(control, repo, repo.getRefDatabase().getRefs(Constants.R_TAGS)); visibleTags(pctl, repo, repo.getRefDatabase().getRefs(Constants.R_TAGS));
for (Ref ref : all.values()) { for (Ref ref : all.values()) {
tags.add(createTagInfo(ref, rw, control.controlForRef(ref.getName()))); tags.add(createTagInfo(ref, rw, pctl.controlForRef(ref.getName()), pctl, links));
} }
} }
@@ -155,18 +160,19 @@ public class ListTags implements RestReadView<ProjectResource> {
tagName = Constants.R_TAGS + tagName; tagName = Constants.R_TAGS + tagName;
} }
Ref ref = repo.getRefDatabase().exactRef(tagName); Ref ref = repo.getRefDatabase().exactRef(tagName);
ProjectControl control = resource.getControl(); ProjectControl pctl = resource.getControl();
if (ref != null if (ref != null && !visibleTags(pctl, repo, ImmutableMap.of(ref.getName(), ref)).isEmpty()) {
&& !visibleTags(control, repo, ImmutableMap.of(ref.getName(), ref)).isEmpty()) { return createTagInfo(ref, rw, pctl.controlForRef(ref.getName()), pctl, links);
return createTagInfo(ref, rw, control.controlForRef(ref.getName()));
} }
} }
throw new ResourceNotFoundException(id); throw new ResourceNotFoundException(id);
} }
public static TagInfo createTagInfo(Ref ref, RevWalk rw, RefControl control) public static TagInfo createTagInfo(
Ref ref, RevWalk rw, RefControl control, ProjectControl pctl, WebLinks links)
throws MissingObjectException, IOException { throws MissingObjectException, IOException {
RevObject object = rw.parseAny(ref.getObjectId()); RevObject object = rw.parseAny(ref.getObjectId());
List<WebLinkInfo> webLinks = links.getTagLinks(pctl.getProject().getName(), ref.getName());
if (object instanceof RevTag) { if (object instanceof RevTag) {
// Annotated or signed tag // Annotated or signed tag
RevTag tag = (RevTag) object; RevTag tag = (RevTag) object;
@@ -177,10 +183,15 @@ public class ListTags implements RestReadView<ProjectResource> {
tag.getObject().getName(), tag.getObject().getName(),
tag.getFullMessage().trim(), tag.getFullMessage().trim(),
tagger != null ? CommonConverters.toGitPerson(tag.getTaggerIdent()) : null, tagger != null ? CommonConverters.toGitPerson(tag.getTaggerIdent()) : null,
control.canDelete()); control.canDelete(),
webLinks.isEmpty() ? null : webLinks);
} }
// Lightweight tag // Lightweight tag
return new TagInfo(ref.getName(), ref.getObjectId().getName(), control.canDelete()); return new TagInfo(
ref.getName(),
ref.getObjectId().getName(),
control.canDelete(),
webLinks.isEmpty() ? null : webLinks);
} }
private Repository getRepository(Project.NameKey project) private Repository getRepository(Project.NameKey project)
@@ -193,9 +204,9 @@ public class ListTags implements RestReadView<ProjectResource> {
} }
private Map<String, Ref> visibleTags( private Map<String, Ref> visibleTags(
ProjectControl control, Repository repo, Map<String, Ref> tags) { ProjectControl pctl, Repository repo, Map<String, Ref> tags) {
return new VisibleRefFilter( return new VisibleRefFilter(
tagCache, changeNotesFactory, changeCache, repo, control, dbProvider.get(), false) tagCache, changeNotesFactory, changeCache, repo, pctl, dbProvider.get(), false)
.filter(tags, true); .filter(tags, true);
} }
} }