Merge branch 'stable-2.16'

* stable-2.16:
  Consume JGit artifacts from Maven Central
  Consume JGit artifacts from Maven Central
  gr-related-changes: Don't show "Same topic" for only one change
  RelatedChanges: Don't show "Same Topic" for only one change
  ChangeEditApi: Allow to set options on change edit detail request
  JS API: Expose invalidateReposCache method
  restAPI.invalidateGroupsCache: Remove unused parameters
  restAPI.invalidateReposCache: Remove unused parameters
  Add Javadoc to clarify behavior of {Accounts|Changes|Groups}#withOptions
  Update highlight.js to master branch
  Docs: Add use-case for Private changes
  OnlineNoteDbMigrationIT: improve readability of some tests
  Update git submodules
  migrate-to-note-db: add --skip-project option
  OnlineNoteDbMigrationIT: Reuse existing constant
  Do not crash if permitted labels array is empty
  Fix '/' getting typed in search bar when pressed
  Encode project name in download commands
  ProjectResetter: Avoid Repository#getAllRefs
  AbstractDaemonTest: Avoid Repository#getAllRefs
  ChangeUtil: Remove javadoc references to deprecated JGit methods
  Set version to 2.16.4-SNAPSHOT
  AccountManagerIT: Fix failing authentication tests
  ChangeEditApiImpl: Access non-Singleton change edit classes via Provider
  ListChangesOption: Add missing word in Javadoc
  Update git submodules
  Update git submodules
  Fix broken links in gr-icons.html
  Add release notes for Gerrit v2.10.8
  AccountIT#updateDisplayName: Rewrite to work with updated account manager
  Add release notes for Gerrit v2.9.5
  AccountApiImpl: Fix message in exception
  RelatedChangeAndCommitInfo: Use default CommitInfo#toString
  Support Get Related in extension API
  CommitInfo: Use ToStringHelper
  CommitInfo: Handle root commits in toString()
  Implement equals/hashCode/toString in CommitInfo and friends
  Set version to 2.15.9-SNAPSHOT
  AccountIT: Disable failing updateDisplayName test
  Set version to 2.16.3
  Set version to 2.13.12
  Set version to 2.12.9
  Set version to 2.11.12
  Set version to 2.10.8
  Upgrade JGit to 5.1.5.201812261915-r
  Set version to 2.15.8
  Upgrade JGit to 4.9.8.201812241815-r
  Set version to 2.9.5
  Set version to 2.14.18
  Revert "Fix the missing DB entry in Gerrit DB"
  Upgrade JGit to 4.7.7.201812240805-r
  maven_jar: Add repo.eclipse.org to supported repositories
  Update git submodules
  ChangeApi: Add method to list change reviewers
  Bazel: Automatically fix lint errors with buildifier 0.20.0
  Revert "Temp fix for projects list ordering in PolyGerrit"
  Do not center the "By User" column in the Group Audit Log table
  Bazel: Fix more buildifier warnings
  Bazel: Automatically fix lint errors with buildifier 0.20.0
  Fix typo in documentation of edit preferences
  Add MIME type for favicons to list of allowed image types.
  Bazel: Automatically fix lint errors with buildifier
  Mail: Use correct patch set when reading line from file
  Upgrade JGit to 4.5.5.201812240535-r

Change-Id: I15dd15a2e3a1171ddfb792a3f17c43861d434421
This commit is contained in:
David Pursehouse
2019-01-21 13:14:11 +09:00
57 changed files with 420 additions and 245 deletions

4
BUILD
View File

@@ -1,8 +1,8 @@
package(default_visibility = ["//visibility:public"])
load("//tools/bzl:genrule2.bzl", "genrule2")
load("//tools/bzl:pkg_war.bzl", "pkg_war")
package(default_visibility = ["//visibility:public"])
config_setting(
name = "java9",
values = {

View File

@@ -1,10 +1,8 @@
package(default_visibility = ["//visibility:public"])
load("//tools/bzl:asciidoc.bzl", "documentation_attributes")
load("//tools/bzl:asciidoc.bzl", "genasciidoc")
load("//tools/bzl:asciidoc.bzl", "genasciidoc_zip")
load("//tools/bzl:asciidoc.bzl", "documentation_attributes", "genasciidoc", "genasciidoc_zip")
load("//tools/bzl:license.bzl", "license_map")
package(default_visibility = ["//visibility:public"])
exports_files([
"replace_macros.py",
])

View File

@@ -200,7 +200,7 @@ The parameter names match the names that are used in the preferences REST API:
* link:rest-api-accounts.html#edit-preferences-info[Edit Preferences]
If the value for a preference is the same as the default value for this
preference, it can be omitted in the `preference.config` file.
preference, it can be omitted in the `preferences.config` file.
Defaults for preferences that apply for all accounts can be configured
in the `refs/users/default` branch in the `All-Users` repository.

View File

@@ -565,6 +565,11 @@ and users with the link:access-control.html#category_view_private_changes[
View Private Changes] global capability. Private changes are useful in a number
of cases:
* You want a set of collaborators to review the change before formal review
starts. By creating a Private change and adding only a selected few as
reviewers you can control who can see the change and get a first opinion
before opening up for all reviewers.
* You want to check what the change looks like before formal review starts.
By marking the change private without reviewers, nobody can
prematurely comment on your changes.

View File

@@ -1,4 +1,5 @@
load("//tools/bzl:java.bzl", "java_library2")
load("//tools/bzl:javadoc.bzl", "java_doc")
java_library(
name = "lib",
@@ -129,8 +130,6 @@ java_library2(
],
)
load("//tools/bzl:javadoc.bzl", "java_doc")
java_doc(
name = "framework-javadoc",
testonly = True,

View File

@@ -1,5 +1,3 @@
load("//tools/bzl:genrule2.bzl", "genrule2")
ANNOTATIONS = [
"Nullable.java",
"audit/Audit.java",

View File

@@ -1,5 +1,6 @@
load("//lib:guava.bzl", "GUAVA_DOC_URL")
load("//lib/jgit:jgit.bzl", "JGIT_DOC_URL")
load("//lib:guava.bzl", "GUAVA_DOC_URL")
load("//tools/bzl:javadoc.bzl", "java_doc")
java_binary(
name = "extension-api",
@@ -34,8 +35,6 @@ java_library(
],
)
load("//tools/bzl:javadoc.bzl", "java_doc")
java_doc(
name = "extension-api-javadoc",
external_docs = [

View File

@@ -172,16 +172,19 @@ public interface Accounts {
return this;
}
/** Set an option on the request, appending to existing options. */
public QueryRequest withOption(ListAccountsOption options) {
this.options.add(options);
return this;
}
/** Set options on the request, appending to existing options. */
public QueryRequest withOptions(ListAccountsOption... options) {
this.options.addAll(Arrays.asList(options));
return this;
}
/** Set options on the request, replacing existing options. */
public QueryRequest withOptions(EnumSet<ListAccountsOption> options) {
this.options = options;
return this;

View File

@@ -215,6 +215,11 @@ public interface ChangeApi {
return suggestReviewers().withQuery(query);
}
/**
* Retrieve reviewers ({@code ReviewerState.REVIEWER} and {@code ReviewerState.CC}) on the change.
*/
List<ReviewerInfo> reviewers() throws RestApiException;
ChangeInfo get(EnumSet<ListChangesOption> options) throws RestApiException;
default ChangeInfo get(Iterable<ListChangesOption> options) throws RestApiException {
@@ -472,6 +477,16 @@ public interface ChangeApi {
throw new NotImplementedException();
}
@Override
public SuggestedReviewersRequest suggestReviewers(String query) throws RestApiException {
throw new NotImplementedException();
}
@Override
public List<ReviewerInfo> reviewers() throws RestApiException {
throw new NotImplementedException();
}
@Override
public ChangeInfo get(EnumSet<ListChangesOption> options) throws RestApiException {
throw new NotImplementedException();

View File

@@ -14,11 +14,13 @@
package com.google.gerrit.extensions.api.changes;
import com.google.gerrit.extensions.client.ChangeEditDetailOption;
import com.google.gerrit.extensions.common.EditInfo;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.NotImplementedException;
import com.google.gerrit.extensions.restapi.RawInput;
import com.google.gerrit.extensions.restapi.RestApiException;
import java.util.EnumSet;
import java.util.Optional;
/**
@@ -29,6 +31,33 @@ import java.util.Optional;
*/
public interface ChangeEditApi {
abstract class ChangeEditDetailRequest {
private String base;
private EnumSet<ChangeEditDetailOption> options = EnumSet.noneOf(ChangeEditDetailOption.class);
public abstract Optional<EditInfo> get() throws RestApiException;
public ChangeEditDetailRequest withBase(String base) {
this.base = base;
return this;
}
public ChangeEditDetailRequest withOption(ChangeEditDetailOption option) {
this.options.add(option);
return this;
}
public String getBase() {
return base;
}
public EnumSet<ChangeEditDetailOption> options() {
return options;
}
}
ChangeEditDetailRequest detail() throws RestApiException;
/**
* Retrieves details regarding the change edit.
*
@@ -155,6 +184,11 @@ public interface ChangeEditApi {
* interface.
*/
class NotImplemented implements ChangeEditApi {
@Override
public ChangeEditDetailRequest detail() throws RestApiException {
throw new NotImplementedException();
}
@Override
public Optional<EditInfo> get() throws RestApiException {
throw new NotImplementedException();

View File

@@ -94,16 +94,19 @@ public interface Changes {
return this;
}
/** Set an option on the request, appending to existing options. */
public QueryRequest withOption(ListChangesOption options) {
this.options.add(options);
return this;
}
/** Set options on the request, appending to existing options. */
public QueryRequest withOptions(ListChangesOption... options) {
this.options.addAll(Arrays.asList(options));
return this;
}
/** Set options on the request, replacing existing options. */
public QueryRequest withOptions(EnumSet<ListChangesOption> options) {
this.options = options;
return this;

View File

@@ -253,16 +253,19 @@ public interface Groups {
return this;
}
/** Set an option on the request, appending to existing options. */
public QueryRequest withOption(ListGroupsOption options) {
this.options.add(options);
return this;
}
/** Set options on the request, appending to existing options. */
public QueryRequest withOptions(ListGroupsOption... options) {
this.options.addAll(Arrays.asList(options));
return this;
}
/** Set options on the request, replacing existing options. */
public QueryRequest withOptions(EnumSet<ListGroupsOption> options) {
this.options = options;
return this;

View File

@@ -0,0 +1,20 @@
// Copyright (C) 2019 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.client;
public enum ChangeEditDetailOption {
LIST_FILES,
DOWNLOAD_COMMANDS
}

View File

@@ -17,7 +17,7 @@ package com.google.gerrit.extensions.client;
import java.util.EnumSet;
import java.util.Set;
/** Output options available for retrieval change details. */
/** Output options available for retrieval of change details. */
public enum ListChangesOption {
LABELS(0),
DETAILED_LABELS(8),

View File

@@ -1,5 +1,3 @@
load("//tools/bzl:genrule2.bzl", "genrule2")
QUERY_PARSE_EXCEPTION_SRCS = [
"query/QueryParseException.java",
"query/QueryRequiresAuthException.java",

View File

@@ -1,3 +1,5 @@
load("//tools/bzl:javadoc.bzl", "java_doc")
CONSTANTS_SRC = [
"documentation/Constants.java",
]
@@ -143,8 +145,6 @@ java_library(
],
)
load("//tools/bzl:javadoc.bzl", "java_doc")
java_doc(
name = "doc",
libs = [":server"],

View File

@@ -136,21 +136,7 @@ public class AccountManager {
try {
Optional<ExternalId> optionalExtId = externalIds.get(who.getExternalIdKey());
if (!optionalExtId.isPresent()) {
if (who.getUserName().isPresent()) {
ExternalId.Key key = ExternalId.Key.create(SCHEME_USERNAME, who.getUserName().get());
Optional<ExternalId> existingId = externalIds.get(key);
if (existingId.isPresent()) {
// An inconsistency is detected in the database, having a record for scheme "username:"
// but no record for scheme "gerrit:". Try to recover by linking
// "gerrit:" identity to the existing account.
logger.atWarning().log(
"User %s already has an account; link new identity to the existing account.",
who.getUserName());
return link(existingId.get().accountId(), who);
}
}
// New account, automatically create and return.
logger.atFine().log("External ID not found. Attempting to create new account.");
return create(who);
}
@@ -416,7 +402,6 @@ public class AccountManager {
public AuthResult link(Account.Id to, AuthRequest who)
throws AccountException, OrmException, IOException, ConfigInvalidException {
Optional<ExternalId> optionalExtId = externalIds.get(who.getExternalIdKey());
logger.atFine().log("Link another authentication identity to an existing account");
if (optionalExtId.isPresent()) {
ExternalId extId = optionalExtId.get();
if (!extId.accountId().equals(to)) {
@@ -425,7 +410,6 @@ public class AccountManager {
}
update(who, extId);
} else {
logger.atFine().log("Linking new external ID to the existing account");
ExternalId newExtId =
ExternalId.createWithEmail(who.getExternalIdKey(), to, who.getEmailAddress());
checkEmailNotUsed(newExtId);

View File

@@ -228,7 +228,7 @@ public class AccountApiImpl implements AccountApi {
accountLoader.fill();
return ai;
} catch (Exception e) {
throw asRestApiException("Cannot parse change", e);
throw asRestApiException("Cannot parse account", e);
}
}

View File

@@ -33,6 +33,7 @@ import com.google.gerrit.extensions.api.changes.RebaseInput;
import com.google.gerrit.extensions.api.changes.RestoreInput;
import com.google.gerrit.extensions.api.changes.RevertInput;
import com.google.gerrit.extensions.api.changes.ReviewerApi;
import com.google.gerrit.extensions.api.changes.ReviewerInfo;
import com.google.gerrit.extensions.api.changes.RevisionApi;
import com.google.gerrit.extensions.api.changes.SubmittedTogetherInfo;
import com.google.gerrit.extensions.api.changes.SubmittedTogetherOption;
@@ -75,6 +76,7 @@ import com.google.gerrit.server.restapi.change.Index;
import com.google.gerrit.server.restapi.change.ListChangeComments;
import com.google.gerrit.server.restapi.change.ListChangeDrafts;
import com.google.gerrit.server.restapi.change.ListChangeRobotComments;
import com.google.gerrit.server.restapi.change.ListReviewers;
import com.google.gerrit.server.restapi.change.MarkAsReviewed;
import com.google.gerrit.server.restapi.change.MarkAsUnreviewed;
import com.google.gerrit.server.restapi.change.Move;
@@ -117,6 +119,7 @@ class ChangeApiImpl implements ChangeApi {
private final ChangeMessageApiImpl.Factory changeMessageApi;
private final ChangeMessages changeMessages;
private final SuggestChangeReviewers suggestReviewers;
private final ListReviewers listReviewers;
private final ChangeResource change;
private final Abandon abandon;
private final Revert revert;
@@ -165,6 +168,7 @@ class ChangeApiImpl implements ChangeApi {
ChangeMessageApiImpl.Factory changeMessageApi,
ChangeMessages changeMessages,
SuggestChangeReviewers suggestReviewers,
ListReviewers listReviewers,
Abandon abandon,
Revert revert,
Restore restore,
@@ -211,6 +215,7 @@ class ChangeApiImpl implements ChangeApi {
this.changeMessageApi = changeMessageApi;
this.changeMessages = changeMessages;
this.suggestReviewers = suggestReviewers;
this.listReviewers = listReviewers;
this.abandon = abandon;
this.restore = restore;
this.updateByMerge = updateByMerge;
@@ -437,6 +442,15 @@ class ChangeApiImpl implements ChangeApi {
}
}
@Override
public List<ReviewerInfo> reviewers() throws RestApiException {
try {
return listReviewers.apply(change);
} catch (Exception e) {
throw asRestApiException("Cannot retrieve reviewers", e);
}
}
@Override
public ChangeInfo get(EnumSet<ListChangesOption> s) throws RestApiException {
try {

View File

@@ -18,6 +18,7 @@ import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
import com.google.gerrit.extensions.api.changes.ChangeEditApi;
import com.google.gerrit.extensions.api.changes.PublishChangeEditInput;
import com.google.gerrit.extensions.client.ChangeEditDetailOption;
import com.google.gerrit.extensions.common.EditInfo;
import com.google.gerrit.extensions.common.Input;
import com.google.gerrit.extensions.restapi.AuthException;
@@ -35,6 +36,7 @@ import com.google.gerrit.server.restapi.change.PublishChangeEdit;
import com.google.gerrit.server.restapi.change.RebaseChangeEdit;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.util.Optional;
@@ -44,51 +46,79 @@ public class ChangeEditApiImpl implements ChangeEditApi {
ChangeEditApiImpl create(ChangeResource changeResource);
}
private final ChangeEdits.Detail editDetail;
private final Provider<ChangeEdits.Detail> editDetailProvider;
private final ChangeEdits.Post changeEditsPost;
private final DeleteChangeEdit deleteChangeEdit;
private final RebaseChangeEdit rebaseChangeEdit;
private final PublishChangeEdit publishChangeEdit;
private final ChangeEdits.Get changeEditsGet;
private final Provider<ChangeEdits.Get> changeEditsGetProvider;
private final ChangeEdits.Put changeEditsPut;
private final ChangeEdits.DeleteContent changeEditDeleteContent;
private final ChangeEdits.GetMessage getChangeEditCommitMessage;
private final Provider<ChangeEdits.GetMessage> getChangeEditCommitMessageProvider;
private final ChangeEdits.EditMessage modifyChangeEditCommitMessage;
private final ChangeEdits changeEdits;
private final ChangeResource changeResource;
@Inject
public ChangeEditApiImpl(
ChangeEdits.Detail editDetail,
Provider<ChangeEdits.Detail> editDetailProvider,
ChangeEdits.Post changeEditsPost,
DeleteChangeEdit deleteChangeEdit,
RebaseChangeEdit rebaseChangeEdit,
PublishChangeEdit publishChangeEdit,
ChangeEdits.Get changeEditsGet,
Provider<ChangeEdits.Get> changeEditsGetProvider,
ChangeEdits.Put changeEditsPut,
ChangeEdits.DeleteContent changeEditDeleteContent,
ChangeEdits.GetMessage getChangeEditCommitMessage,
Provider<ChangeEdits.GetMessage> getChangeEditCommitMessageProvider,
ChangeEdits.EditMessage modifyChangeEditCommitMessage,
ChangeEdits changeEdits,
@Assisted ChangeResource changeResource) {
this.editDetail = editDetail;
this.editDetailProvider = editDetailProvider;
this.changeEditsPost = changeEditsPost;
this.deleteChangeEdit = deleteChangeEdit;
this.rebaseChangeEdit = rebaseChangeEdit;
this.publishChangeEdit = publishChangeEdit;
this.changeEditsGet = changeEditsGet;
this.changeEditsGetProvider = changeEditsGetProvider;
this.changeEditsPut = changeEditsPut;
this.changeEditDeleteContent = changeEditDeleteContent;
this.getChangeEditCommitMessage = getChangeEditCommitMessage;
this.getChangeEditCommitMessageProvider = getChangeEditCommitMessageProvider;
this.modifyChangeEditCommitMessage = modifyChangeEditCommitMessage;
this.changeEdits = changeEdits;
this.changeResource = changeResource;
}
@Override
public ChangeEditDetailRequest detail() throws RestApiException {
try {
return new ChangeEditDetailRequest() {
@Override
public Optional<EditInfo> get() throws RestApiException {
return ChangeEditApiImpl.this.get(this);
}
};
} catch (Exception e) {
throw asRestApiException("Cannot retrieve change edit", e);
}
}
private Optional<EditInfo> get(ChangeEditDetailRequest r) throws RestApiException {
try {
ChangeEdits.Detail editDetail = editDetailProvider.get();
editDetail.setBase(r.getBase());
editDetail.setList(r.options().contains(ChangeEditDetailOption.LIST_FILES));
editDetail.setDownloadCommands(
r.options().contains(ChangeEditDetailOption.DOWNLOAD_COMMANDS));
Response<EditInfo> edit = editDetail.apply(changeResource);
return edit.isNone() ? Optional.empty() : Optional.of(edit.value());
} catch (Exception e) {
throw asRestApiException("Cannot retrieve change edit", e);
}
}
@Override
public Optional<EditInfo> get() throws RestApiException {
try {
Response<EditInfo> edit = editDetail.apply(changeResource);
Response<EditInfo> edit = editDetailProvider.get().apply(changeResource);
return edit.isNone() ? Optional.empty() : Optional.of(edit.value());
} catch (Exception e) {
throw asRestApiException("Cannot retrieve change edit", e);
@@ -140,7 +170,7 @@ public class ChangeEditApiImpl implements ChangeEditApi {
public Optional<BinaryResult> getFile(String filePath) throws RestApiException {
try {
ChangeEditResource changeEditResource = getChangeEditResource(filePath);
Response<BinaryResult> fileResponse = changeEditsGet.apply(changeEditResource);
Response<BinaryResult> fileResponse = changeEditsGetProvider.get().apply(changeEditResource);
return fileResponse.isNone() ? Optional.empty() : Optional.of(fileResponse.value());
} catch (Exception e) {
throw asRestApiException("Cannot retrieve file of change edit", e);
@@ -191,7 +221,8 @@ public class ChangeEditApiImpl implements ChangeEditApi {
@Override
public String getCommitMessage() throws RestApiException {
try {
try (BinaryResult binaryResult = getChangeEditCommitMessage.apply(changeResource)) {
try (BinaryResult binaryResult =
getChangeEditCommitMessageProvider.get().apply(changeResource)) {
return binaryResult.asString();
}
} catch (Exception e) {

View File

@@ -283,6 +283,21 @@ public abstract class ChangeEmail extends NotificationEmail {
}
}
/** Get the patch list corresponding to patch set patchSetId of this change. */
protected PatchList getPatchList(int patchSetId) throws PatchListNotAvailableException {
PatchSet ps;
if (patchSetId == patchSet.getPatchSetId()) {
ps = patchSet;
} else {
try {
ps = args.patchSetUtil.get(changeData.notes(), new PatchSet.Id(change.getId(), patchSetId));
} catch (OrmException e) {
throw new PatchListNotAvailableException("Failed to get patchSet");
}
}
return args.patchListCache.get(change, ps);
}
/** Get the patch list corresponding to this patch set. */
protected PatchList getPatchList() throws PatchListNotAvailableException {
if (patchSet != null) {

View File

@@ -198,17 +198,6 @@ public class CommentSender extends ReplyToChangeSender {
*/
private List<CommentSender.FileCommentGroup> getGroupedInlineComments(Repository repo) {
List<CommentSender.FileCommentGroup> groups = new ArrayList<>();
// Get the patch list:
PatchList patchList = null;
if (repo != null) {
try {
patchList = getPatchList();
} catch (PatchListObjectTooLargeException e) {
logger.atWarning().log("Failed to get patch list: %s", e.getMessage());
} catch (PatchListNotAvailableException e) {
logger.atSevere().withCause(e).log("Failed to get patch list");
}
}
// Loop over the comments and collect them into groups based on the file
// location of the comment.
@@ -221,6 +210,16 @@ public class CommentSender extends ReplyToChangeSender {
currentGroup = new FileCommentGroup();
currentGroup.filename = c.key.filename;
currentGroup.patchSetId = c.key.patchSetId;
// Get the patch list:
PatchList patchList = null;
try {
patchList = getPatchList(c.key.patchSetId);
} catch (PatchListObjectTooLargeException e) {
logger.atWarning().log("Failed to get patch list: %s", e.getMessage());
} catch (PatchListNotAvailableException e) {
logger.atSevere().withCause(e).log("Failed to get patch list");
}
groups.add(currentGroup);
if (patchList != null) {
try {

View File

@@ -20,6 +20,7 @@ import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.GerritPersonIdentProvider;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.IdentifiedUser.GenericFactory;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.UsedAt;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.GroupBackend;
@@ -56,6 +57,7 @@ public class EmailArguments {
final GroupBackend groupBackend;
final AccountCache accountCache;
final PatchListCache patchListCache;
final PatchSetUtil patchSetUtil;
final ApprovalsUtil approvalsUtil;
final FromAddressGenerator fromAddressGenerator;
final EmailSender emailSender;
@@ -88,6 +90,7 @@ public class EmailArguments {
GroupBackend groupBackend,
AccountCache accountCache,
PatchListCache patchListCache,
PatchSetUtil patchSetUtil,
ApprovalsUtil approvalsUtil,
FromAddressGenerator fromAddressGenerator,
EmailSender emailSender,
@@ -116,6 +119,7 @@ public class EmailArguments {
this.groupBackend = groupBackend;
this.accountCache = accountCache;
this.patchListCache = patchListCache;
this.patchSetUtil = patchSetUtil;
this.approvalsUtil = approvalsUtil;
this.fromAddressGenerator = fromAddressGenerator;
this.emailSender = emailSender;

View File

@@ -151,14 +151,24 @@ public class ChangeEdits implements ChildCollection<ChangeResource, ChangeEditRe
private final FileInfoJson fileInfoJson;
private final Revisions revisions;
private String base;
private boolean list;
private boolean downloadCommands;
@Option(name = "--base", metaVar = "revision-id")
String base;
public void setBase(String base) {
this.base = base;
}
@Option(name = "--list")
boolean list;
public void setList(boolean list) {
this.list = list;
}
@Option(name = "--download-commands")
boolean downloadCommands;
public void setDownloadCommands(boolean downloadCommands) {
this.downloadCommands = downloadCommands;
}
@Inject
Detail(

View File

@@ -31,7 +31,7 @@ import java.util.List;
import java.util.Map;
@Singleton
class ListReviewers implements RestReadView<ChangeResource> {
public class ListReviewers implements RestReadView<ChangeResource> {
private final ApprovalsUtil approvalsUtil;
private final ReviewerJson json;
private final ReviewerResource.Factory resourceFactory;

View File

@@ -108,11 +108,9 @@ import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.ServerInitiated;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AccountProperties;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.AccountsUpdate;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.Emails;
import com.google.gerrit.server.account.ProjectWatches;
import com.google.gerrit.server.account.ProjectWatches.NotifyType;
@@ -224,8 +222,6 @@ public class AccountIT extends AbstractDaemonTest {
@Inject
private DynamicSet<AccountActivationValidationListener> accountActivationValidationListeners;
@Inject private AccountManager accountManager;
@Inject protected GroupOperations groupOperations;
private AccountIndexedCounter accountIndexedCounter;
@@ -2712,18 +2708,6 @@ public class AccountIT extends AbstractDaemonTest {
}
}
@Test
public void updateDisplayName() throws Exception {
String name = name("test");
gApi.accounts().create(name);
AuthRequest who = AuthRequest.forUser(name);
accountManager.authenticate(who);
assertThat(gApi.accounts().id(name).get().name).isEqualTo(name);
who.setDisplayName("Something Else");
accountManager.authenticate(who);
assertThat(gApi.accounts().id(name).get().name).isEqualTo("Something Else");
}
private void createDraft(PushOneCommit.Result r, String path, String message) throws Exception {
DraftInput in = new DraftInput();
in.path = path;

View File

@@ -193,25 +193,28 @@ public class AccountManagerIT extends AbstractDaemonTest {
}
@Test
public void authenticateWhenUsernameExtIdAlreadyExists() throws Exception {
public void authenticateWithUsernameAndUpdateDisplayName() throws Exception {
String username = "foo";
ExternalId.Key gerritExtIdKey = ExternalId.Key.create(ExternalId.SCHEME_GERRIT, username);
ExternalId.Key usernameExtIdKey = ExternalId.Key.create(ExternalId.SCHEME_USERNAME, username);
assertNoSuchExternalIds(gerritExtIdKey, usernameExtIdKey);
// Create account with SCHEME_USERNAME external ID, but no SCHEME_GERRIT external ID.
String email = "foo@example.com";
Account.Id accountId = new Account.Id(seq.nextAccountId());
ExternalId.Key gerritExtIdKey = ExternalId.Key.create(ExternalId.SCHEME_GERRIT, username);
accountsUpdate.insert(
"Create Test Account",
accountId,
u -> u.setFullName("Foo").addExternalId(ExternalId.create(usernameExtIdKey, accountId)));
u ->
u.setFullName("Initial Name")
.setPreferredEmail(email)
.addExternalId(ExternalId.createWithEmail(gerritExtIdKey, accountId, email)));
AuthRequest who = AuthRequest.forUser(username);
String newName = "Updated Name";
who.setDisplayName(newName);
AuthResult authResult = accountManager.authenticate(who);
// Expect that the missing SCHEME_GERRIT external ID was created.
assertAuthResultForExistingAccount(authResult, accountId, gerritExtIdKey);
assertExternalIdsWithoutEmail(gerritExtIdKey, usernameExtIdKey);
Optional<AccountState> accountState = accounts.get(accountId);
assertThat(accountState).isPresent();
assertThat(accountState.get().getAccount().getFullName()).isEqualTo(newName);
}
@Test

View File

@@ -1744,6 +1744,29 @@ public class ChangeIT extends AbstractDaemonTest {
assertThat(rsrc.getETag()).isNotEqualTo(oldETag);
}
@Test
public void listReviewers() throws Exception {
PushOneCommit.Result r = createChange();
AddReviewerInput in = new AddReviewerInput();
in.reviewer = user.email;
gApi.changes().id(r.getChangeId()).addReviewer(in);
assertThat(gApi.changes().id(r.getChangeId()).reviewers()).hasSize(1);
String username1 = name("user1");
String email1 = username1 + "@example.com";
accountOperations
.newAccount()
.username(username1)
.preferredEmail(email1)
.fullname("User 1")
.create();
in.reviewer = email1;
in.state = ReviewerState.CC;
gApi.changes().id(r.getChangeId()).addReviewer(in);
assertThat(gApi.changes().id(r.getChangeId()).reviewers().stream().map(a -> a.username))
.containsExactly(user.username, username1);
}
@Test
public void notificationsForAddedWorkInProgressReviewers() throws Exception {
AddReviewerInput in = new AddReviewerInput();

View File

@@ -22,6 +22,7 @@ import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_LAB
import static com.google.gerrit.extensions.client.ListChangesOption.MESSAGES;
import static com.google.gerrit.extensions.common.testing.EditInfoSubject.assertThat;
import static com.google.gerrit.extensions.restapi.testing.BinaryResultSubject.assertThat;
import static com.google.gerrit.reviewdb.client.Patch.COMMIT_MSG;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -43,6 +44,7 @@ import com.google.gerrit.extensions.api.changes.AddReviewerInput;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.api.changes.PublishChangeEditInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.client.ChangeEditDetailOption;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.ApprovalInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
@@ -52,7 +54,6 @@ import com.google.gerrit.extensions.common.FileInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.ChangeMessagesUtil;
@@ -400,7 +401,9 @@ public class ChangeEditIT extends AbstractDaemonTest {
public void retrieveEdit() throws Exception {
adminRestSession.get(urlEdit(changeId)).assertNoContent();
createArbitraryEditFor(changeId);
EditInfo editInfo = getEditInfo(changeId, false);
Optional<EditInfo> maybeEditInfo = gApi.changes().id(changeId).edit().get();
assertThat(maybeEditInfo).isPresent();
EditInfo editInfo = maybeEditInfo.get();
ChangeInfo changeInfo = get(changeId, CURRENT_REVISION, CURRENT_COMMIT);
assertThat(editInfo.commit.commit).isNotEqualTo(changeInfo.currentRevision);
assertThat(editInfo).commit().parents().hasSize(1);
@@ -414,11 +417,7 @@ public class ChangeEditIT extends AbstractDaemonTest {
@Test
public void retrieveFilesInEdit() throws Exception {
createEmptyEditFor(changeId);
gApi.changes().id(changeId).edit().modifyFile(FILE_NAME, RawInputUtil.create(CONTENT_NEW));
EditInfo info = getEditInfo(changeId, true);
assertThat(info.files).isNotNull();
assertThat(info.files.keySet()).containsExactly(Patch.COMMIT_MSG, FILE_NAME, FILE_NAME2);
assertFiles(changeId, ImmutableList.of(COMMIT_MSG, FILE_NAME, FILE_NAME2));
}
@Test
@@ -559,8 +558,10 @@ public class ChangeEditIT extends AbstractDaemonTest {
@Test
public void addNewFile() throws Exception {
createEmptyEditFor(changeId);
assertFiles(changeId, ImmutableList.of(COMMIT_MSG, FILE_NAME, FILE_NAME2));
gApi.changes().id(changeId).edit().modifyFile(FILE_NAME3, RawInputUtil.create(CONTENT_NEW));
ensureSameBytes(getFileContentOfEdit(changeId, FILE_NAME3), CONTENT_NEW);
assertFiles(changeId, ImmutableList.of(COMMIT_MSG, FILE_NAME, FILE_NAME2, FILE_NAME3));
}
@Test
@@ -767,6 +768,19 @@ public class ChangeEditIT extends AbstractDaemonTest {
assertThat(fileContent).value().bytes().isEqualTo(expectedFileBytes);
}
private void assertFiles(String changeId, List<String> expected) throws Exception {
Optional<EditInfo> info =
gApi.changes()
.id(changeId)
.edit()
.detail()
.withOption(ChangeEditDetailOption.LIST_FILES)
.get();
assertThat(info).isPresent();
assertThat(info.get().files).isNotNull();
assertThat(info.get().files.keySet()).containsExactlyElementsIn(expected);
}
private String urlEdit(String changeId) {
return "/changes/" + changeId + "/edit";
}
@@ -783,10 +797,6 @@ public class ChangeEditIT extends AbstractDaemonTest {
return urlEdit(changeId) + "/" + fileName + (base ? "?base" : "");
}
private String urlGetFiles(String changeId) {
return urlEdit(changeId) + "?list";
}
private String urlRevisionFiles(String changeId, String revisionId) {
return "/changes/" + changeId + "/revisions/" + revisionId + "/files";
}
@@ -821,11 +831,6 @@ public class ChangeEditIT extends AbstractDaemonTest {
+ "/diff?context=ALL&intraline";
}
private EditInfo getEditInfo(String changeId, boolean files) throws Exception {
RestResponse r = adminRestSession.get(files ? urlGetFiles(changeId) : urlEdit(changeId));
return readContentFromJson(r, EditInfo.class);
}
private <T> T readContentFromJson(RestResponse r, Class<T> clazz) throws Exception {
r.assertOK();
try (JsonReader jsonReader = new JsonReader(r.getReader())) {

View File

@@ -526,18 +526,26 @@ public class CommentsIT extends AbstractDaemonTest {
@Test
public void publishCommentsAllRevisions() throws Exception {
PushOneCommit.Result r1 = createChange();
PushOneCommit.Result r1 =
pushFactory
.create(admin.getIdent(), testRepo, SUBJECT, FILE_NAME, "old boring content\n")
.to("refs/for/master");
PushOneCommit.Result r2 =
pushFactory
.create(
admin.getIdent(), testRepo, SUBJECT, FILE_NAME, "new\ncntent\n", r1.getChangeId())
admin.getIdent(),
testRepo,
SUBJECT,
FILE_NAME,
"new interesting\ncntent\n",
r1.getChangeId())
.to("refs/for/master");
addDraft(
r1.getChangeId(),
r1.getCommit().getName(),
newDraft(FILE_NAME, Side.REVISION, 1, "nit: trailing whitespace"));
newDraft(FILE_NAME, Side.REVISION, createLineRange(1, 4, 10), "Is it that bad?"));
addDraft(
r1.getChangeId(),
r1.getCommit().getName(),
@@ -545,7 +553,7 @@ public class CommentsIT extends AbstractDaemonTest {
addDraft(
r2.getChangeId(),
r2.getCommit().getName(),
newDraft(FILE_NAME, Side.REVISION, 1, "join lines"));
newDraft(FILE_NAME, Side.REVISION, createLineRange(1, 4, 15), "better now"));
addDraft(
r2.getChangeId(),
r2.getCommit().getName(),
@@ -586,7 +594,7 @@ public class CommentsIT extends AbstractDaemonTest {
assertThat(ps1List).hasSize(2);
assertThat(ps1List.get(0).message).isEqualTo("what happened to this?");
assertThat(ps1List.get(0).side).isEqualTo(Side.PARENT);
assertThat(ps1List.get(1).message).isEqualTo("nit: trailing whitespace");
assertThat(ps1List.get(1).message).isEqualTo("Is it that bad?");
assertThat(ps1List.get(1).side).isNull();
assertThat(gApi.changes().id(r2.getChangeId()).revision(r2.getCommit().name()).drafts())
@@ -598,7 +606,7 @@ public class CommentsIT extends AbstractDaemonTest {
assertThat(ps2List).hasSize(4);
assertThat(ps2List.get(0).message).isEqualTo("comment 1 on base");
assertThat(ps2List.get(1).message).isEqualTo("comment 2 on base");
assertThat(ps2List.get(2).message).isEqualTo("join lines");
assertThat(ps2List.get(2).message).isEqualTo("better now");
assertThat(ps2List.get(3).message).isEqualTo("typo: content");
List<Message> messages = email.getMessages(r2.getChangeId(), "comment");
@@ -631,8 +639,8 @@ public class CommentsIT extends AbstractDaemonTest {
+ "#/c/"
+ c
+ "/1/a.txt@1 \n"
+ "PS1, Line 1: ew\n"
+ "nit: trailing whitespace\n"
+ "PS1, Line 1: boring\n"
+ "Is it that bad?\n"
+ "\n"
+ "\n"
+ url
@@ -661,8 +669,8 @@ public class CommentsIT extends AbstractDaemonTest {
+ "#/c/"
+ c
+ "/2/a.txt@1 \n"
+ "PS2, Line 1: ew\n"
+ "join lines\n"
+ "PS2, Line 1: interesting\n"
+ "better now\n"
+ "\n"
+ "\n"
+ url
@@ -1093,30 +1101,49 @@ public class CommentsIT extends AbstractDaemonTest {
return populate(d, path, side, null, line, message, false);
}
private DraftInput newDraft(String path, Side side, Comment.Range range, String message) {
DraftInput d = new DraftInput();
return populate(d, path, side, null, range, message, false);
}
private DraftInput newDraftOnParent(String path, int parent, int line, String message) {
DraftInput d = new DraftInput();
return populate(d, path, Side.PARENT, Integer.valueOf(parent), line, message, false);
}
private static <C extends Comment> C populate(
C c, String path, Side side, Integer parent, int line, String message, Boolean unresolved) {
C c,
String path,
Side side,
Integer parent,
Comment.Range range,
String message,
Boolean unresolved) {
int line = range.startLine;
c.path = path;
c.side = side;
c.parent = parent;
c.line = line != 0 ? line : null;
c.message = message;
c.unresolved = unresolved;
if (line != 0) {
Comment.Range range = new Comment.Range();
range.startLine = line;
range.startCharacter = 1;
range.endLine = line;
range.endCharacter = 5;
c.range = range;
}
if (line != 0) c.range = range;
return c;
}
private static <C extends Comment> C populate(
C c, String path, Side side, Integer parent, int line, String message, Boolean unresolved) {
return populate(c, path, side, parent, createLineRange(line, 1, 5), message, unresolved);
}
private static Comment.Range createLineRange(int line, int startChar, int endChar) {
Comment.Range range = new Comment.Range();
range.startLine = line;
range.startCharacter = startChar;
range.endLine = line;
range.endCharacter = endChar;
return range;
}
private static Function<CommentInfo, CommentInput> infoToInput(String path) {
return infoToInput(path, CommentInput::new);
}

View File

@@ -1,7 +1,6 @@
load("//tools/bzl:genrule2.bzl", "genrule2")
# Roboto Mono. Version 2.136
# https://github.com/google/roboto/releases/tag/v2.136
filegroup(
name = "robotofonts",
srcs = [

View File

@@ -1,4 +1,4 @@
load("//tools/bzl:maven_jar.bzl", "ECLIPSE", "GERRIT", "MAVEN_CENTRAL", "MAVEN_LOCAL", "maven_jar")
load("//tools/bzl:maven_jar.bzl", "MAVEN_CENTRAL", "maven_jar")
_JGIT_VERS = "5.2.1.201812262042-r"
@@ -6,7 +6,7 @@ _DOC_VERS = _JGIT_VERS # Set to _JGIT_VERS unless using a snapshot
JGIT_DOC_URL = "http://download.eclipse.org/jgit/site/" + _DOC_VERS + "/apidocs"
_JGIT_REPO = ECLIPSE # Leave here even if set to MAVEN_CENTRAL.
_JGIT_REPO = MAVEN_CENTRAL # Leave here even if set to MAVEN_CENTRAL.
# set this to use a local version.
# "/home/<user>/projects/jgit"
@@ -67,11 +67,11 @@ def jgit_maven_repos():
def jgit_dep(name):
mapping = {
"@jgit-junit//jar": "@jgit//org.eclipse.jgit.junit:junit",
"@jgit-lib//jar:src": "@jgit//org.eclipse.jgit:libjgit-src.jar",
"@jgit-lib//jar": "@jgit//org.eclipse.jgit:jgit",
"@jgit-servlet//jar": "@jgit//org.eclipse.jgit.http.server:jgit-servlet",
"@jgit-archive//jar": "@jgit//org.eclipse.jgit.archive:jgit-archive",
"@jgit-junit//jar": "@jgit//org.eclipse.jgit.junit:junit",
"@jgit-lib//jar": "@jgit//org.eclipse.jgit:jgit",
"@jgit-lib//jar:src": "@jgit//org.eclipse.jgit:libjgit-src.jar",
"@jgit-servlet//jar": "@jgit//org.eclipse.jgit.http.server:jgit-servlet",
}
if LOCAL_JGIT_REPO:

View File

@@ -1,7 +1,8 @@
package(default_visibility = ["//visibility:public"])
load("//lib/js:bower_components.bzl", "define_bower_components")
load("//tools/bzl:js.bzl", "bower_component", "js_component")
package(default_visibility = ["//visibility:public"])
# For importing new versions of existing bower packages,
#
# 1) edit the versions of 'seed' components in WORKSPACE as desired
@@ -20,8 +21,6 @@ load("//tools/bzl:js.bzl", "bower_component", "js_component")
# 4) remove bower_component(name="my_new_dependency", .. ) here
#
load("//lib/js:bower_components.bzl", "define_bower_components")
define_bower_components()
js_component(

View File

@@ -1,7 +1,7 @@
package(default_visibility = ["//visibility:public"])
load("//tools/bzl:maven.bzl", "merge_maven_jars")
package(default_visibility = ["//visibility:public"])
# core and backward-codecs both provide
# META-INF/services/org.apache.lucene.codecs.Codec, so they must be merged.
merge_maven_jars(

View File

@@ -12,10 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
package(default_visibility = ["//visibility:public"])
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_library")
package(default_visibility = ["//visibility:public"])
closure_js_library(
name = "polymer_closure",
srcs = ["@polymer_closure//file"],

View File

@@ -1,4 +1,5 @@
load("//tools/bzl:genrule2.bzl", "genrule2")
load("//tools/bzl:javadoc.bzl", "java_doc")
load(
"//tools/bzl:plugins.bzl",
"CORE_PLUGINS",
@@ -123,8 +124,6 @@ java_binary(
],
)
load("//tools/bzl:javadoc.bzl", "java_doc")
java_doc(
name = "plugin-api-javadoc",
libs = PLUGIN_API + [

View File

@@ -1,8 +1,8 @@
package(default_visibility = ["//visibility:public"])
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
load("//tools/bzl:js.bzl", "bower_component_bundle")
load("//tools/bzl:genrule2.bzl", "genrule2")
load("//tools/bzl:js.bzl", "bower_component_bundle")
package(default_visibility = ["//visibility:public"])
bower_component_bundle(
name = "polygerrit_components.bower_components",

View File

@@ -1,8 +1,8 @@
package(default_visibility = ["//visibility:public"])
load(":rules.bzl", "polygerrit_bundle")
load("//tools/bzl:genrule2.bzl", "genrule2")
load("//tools/bzl:js.bzl", "bower_component_bundle")
load(":rules.bzl", "polygerrit_bundle")
package(default_visibility = ["//visibility:public"])
polygerrit_bundle(
name = "polygerrit_ui",

View File

@@ -129,8 +129,7 @@
},
_refreshGroupsList() {
this.$.restAPI.invalidateGroupsCache(this._filter,
this._groupsPerPage, this._offset);
this.$.restAPI.invalidateGroupsCache();
return this._getGroups(this._filter, this._groupsPerPage,
this._offset);
},

View File

@@ -130,8 +130,7 @@
},
_refreshReposList() {
this.$.restAPI.invalidateReposCache(this._filter,
this._reposPerPage, this._offset);
this.$.restAPI.invalidateReposCache();
return this._getRepos(this._filter, this._reposPerPage,
this._offset);
},

View File

@@ -190,7 +190,8 @@
},
_getChangesWithSameTopic() {
return this.$.restAPI.getChangesWithSameTopic(this.change.topic);
return this.$.restAPI.getChangesWithSameTopic(this.change.topic,
this.change._number);
},
/**

View File

@@ -20,29 +20,29 @@ limitations under the License.
<iron-iconset-svg name="gr-icons" size="24">
<svg>
<defs>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.html -->
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
<g id="expand-less"><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"/></g>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.html -->
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
<g id="expand-more"><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"/></g>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.html -->
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
<g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></g>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.html -->
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
<g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></g>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.html -->
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
<g id="create"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></g>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.html -->
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
<g id="star"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></g>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.html -->
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
<g id="star-border"><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z"/></g>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.html -->
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
<g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></g>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.html -->
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
<g id="chevron-left"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></g>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.html -->
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
<g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></g>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.html -->
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
<g id="more-vert"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></g>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.html -->
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/iron-icons.js -->
<g id="deleteEdit"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></g>
<!-- This SVG is a copy from iron-icons https://github.com/PolymerElements/iron-icons/blob/master/editor-icons.html -->
<g id="publishEdit"><path d="M5 4v2h14V4H5zm0 10h4v6h6v-6h4l-7-7-7 7z"/></g>

View File

@@ -38,6 +38,10 @@
return getRestApi().getVersion();
};
GrPluginRestApi.prototype.invalidateReposCache = function() {
getRestApi().invalidateReposCache();
};
/**
* Fetch and return native browser REST API Response.
* @param {string} method HTTP Method (GET, POST, etc)

View File

@@ -1605,7 +1605,7 @@
this._invalidateSharedFetchPromisesPrefix('/groups/?');
},
invalidateReposCache(filter, reposPerPage, opt_offset) {
invalidateReposCache() {
this._invalidateSharedFetchPromisesPrefix('/projects/?');
},
@@ -1886,16 +1886,21 @@
});
},
getChangesWithSameTopic(topic) {
getChangesWithSameTopic(topic, changeNum) {
const options = this.listChangesOptionsToHex(
this.ListChangesOption.LABELS,
this.ListChangesOption.CURRENT_REVISION,
this.ListChangesOption.CURRENT_COMMIT,
this.ListChangesOption.DETAILED_LABELS
);
const query = [
'status:open',
'-change:' + changeNum,
'topic:' + topic,
].join(' ');
const params = {
O: options,
q: 'status:open topic:' + topic,
q: query,
};
return this._fetchJSON({
url: '/changes/',

View File

@@ -956,7 +956,7 @@ limitations under the License.
element._cache.set(url, {});
element.invalidateReposCache('test', 25);
element.invalidateReposCache();
assert.isUndefined(element._sharedFetchPromises[url]);
@@ -1043,7 +1043,7 @@ limitations under the License.
element._cache.set(url, {});
element.invalidateGroupsCache('test', 25);
element.invalidateGroupsCache();
assert.isUndefined(element._sharedFetchPromises[url]);

View File

@@ -12,12 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_library")
package(
default_visibility = ["//visibility:public"],
)
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_library")
closure_js_library(
name = "plugin",
srcs = ["plugin.js"],

View File

@@ -1,10 +1,8 @@
load("//tools/bzl:genrule2.bzl", "genrule2")
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_binary", "closure_js_library")
load("//tools/bzl:genrule2.bzl", "genrule2")
load(
"//tools/bzl:js.bzl",
"bower_component",
"bundle_assets",
"js_component",
)
def polygerrit_bundle(name, srcs, outs, app):

View File

@@ -41,17 +41,17 @@ def _replace_macros_impl(ctx):
_replace_macros = rule(
attrs = {
"_exe": attr.label(
default = Label("//Documentation:replace_macros.py"),
allow_single_file = True,
),
"src": attr.label(
mandatory = True,
allow_single_file = [".txt"],
),
"suffix": attr.string(mandatory = True),
"searchbox": attr.bool(default = True),
"out": attr.output(mandatory = True),
"searchbox": attr.bool(default = True),
"suffix": attr.string(mandatory = True),
"_exe": attr.label(
default = Label("//Documentation:replace_macros.py"),
allow_single_file = True,
),
},
implementation = _replace_macros_impl,
)
@@ -108,23 +108,23 @@ def _asciidoc_impl(ctx):
)
_asciidoc_attrs = {
"srcs": attr.label_list(
mandatory = True,
allow_files = True,
),
"attributes": attr.string_list(),
"backend": attr.string(),
"suffix": attr.string(mandatory = True),
"version": attr.label(
default = Label("//:version.txt"),
allow_single_file = True,
),
"_exe": attr.label(
default = Label("//java/com/google/gerrit/asciidoctor:asciidoc"),
cfg = "host",
allow_files = True,
executable = True,
),
"srcs": attr.label_list(
mandatory = True,
allow_files = True,
),
"version": attr.label(
default = Label("//:version.txt"),
allow_single_file = True,
),
"suffix": attr.string(mandatory = True),
"backend": attr.string(),
"attributes": attr.string_list(),
}
_asciidoc = rule(
@@ -279,11 +279,11 @@ _asciidoc_zip = rule(
mandatory = True,
allow_single_file = [".zip"],
),
"directory": attr.string(mandatory = True),
"resources": attr.label_list(
mandatory = True,
allow_files = True,
),
"directory": attr.string(mandatory = True),
},
outputs = {
"out": "%{name}.zip",

View File

@@ -8,8 +8,8 @@ def _classpath_collector(ctx):
elif hasattr(d, "files"):
all += d.files
as_strs = [c.path for c in all]
ctx.file_action(
as_strs = [c.path for c in all.to_list()]
ctx.actions.write(
output = ctx.outputs.runtime,
content = "\n".join(sorted(as_strs)),
)

View File

@@ -23,7 +23,7 @@ def _impl(ctx):
source_jars += l.java.source_jars
transitive_jar_set += l.java.transitive_deps
transitive_jar_paths = [j.path for j in transitive_jar_set]
transitive_jar_paths = [j.path for j in transitive_jar_set.to_list()]
dir = ctx.outputs.zip.path + ".dir"
source = ctx.outputs.zip.path + ".source"
external_docs = ["http://docs.oracle.com/javase/8/docs/api"] + ctx.attr.external_docs
@@ -32,7 +32,7 @@ def _impl(ctx):
"export TZ",
"rm -rf %s" % source,
"mkdir %s" % source,
" && ".join(["unzip -qud %s %s" % (source, j.path) for j in source_jars]),
" && ".join(["unzip -qud %s %s" % (source, j.path) for j in source_jars.to_list()]),
"rm -rf %s" % dir,
"mkdir %s" % dir,
" ".join([
@@ -56,17 +56,17 @@ def _impl(ctx):
"(cd %s && zip -Xqr ../%s *)" % (dir, ctx.outputs.zip.basename),
]
ctx.actions.run_shell(
inputs = list(transitive_jar_set) + list(source_jars) + ctx.files._jdk,
inputs = transitive_jar_set.to_list() + source_jars.to_list() + ctx.files._jdk,
outputs = [zip_output],
command = " && ".join(cmd),
)
java_doc = rule(
attrs = {
"external_docs": attr.string_list(),
"libs": attr.label_list(allow_files = False),
"pkgs": attr.string_list(),
"title": attr.string(),
"external_docs": attr.string_list(),
"_jdk": attr.label(
default = Label("@bazel_tools//tools/jdk:current_java_runtime"),
allow_files = True,

View File

@@ -1,10 +1,10 @@
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_binary", "closure_js_library")
load("//lib/js:npm.bzl", "NPM_SHA1S", "NPM_VERSIONS")
NPMJS = "NPMJS"
GERRIT = "GERRIT:"
load("//lib/js:npm.bzl", "NPM_SHA1S", "NPM_VERSIONS")
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_binary", "closure_js_library")
def _npm_tarball(name):
return "%s@%s.npm_binary.tgz" % (name, NPM_VERSIONS[name])
@@ -37,9 +37,9 @@ def _npm_binary_impl(ctx):
npm_binary = repository_rule(
attrs = {
"repository": attr.string(default = NPMJS),
# Label resolves within repo of the .bzl file.
"_download_script": attr.label(default = Label("//tools:download_file.py")),
"repository": attr.string(default = NPMJS),
},
local = True,
implementation = _npm_binary_impl,
@@ -120,13 +120,13 @@ def _bash(ctx, cmd):
bower_archive = repository_rule(
_bower_archive,
attrs = {
"_bower_archive": attr.label(default = Label("@bower//:%s" % _npm_tarball("bower"))),
"_run_npm": attr.label(default = Label("//tools/js:run_npm_binary.py")),
"_download_bower": attr.label(default = Label("//tools/js:download_bower.py")),
"sha1": attr.string(mandatory = True),
"version": attr.string(mandatory = True),
"package": attr.string(mandatory = True),
"semver": attr.string(),
"sha1": attr.string(mandatory = True),
"version": attr.string(mandatory = True),
"_bower_archive": attr.label(default = Label("@bower//:%s" % _npm_tarball("bower"))),
"_download_bower": attr.label(default = Label("//tools/js:download_bower.py")),
"_run_npm": attr.label(default = Label("//tools/js:run_npm_binary.py")),
},
)
@@ -207,12 +207,12 @@ js_component = rule(
_bower_component = rule(
_bower_component_impl,
attrs = dict(_common_attrs.items() + {
"zipfile": attr.label(allow_single_file = [".zip"]),
"license": attr.label(allow_single_file = True),
"version_json": attr.label(allow_files = [".json"]),
# If set, define by hand, and don't regenerate this entry in bower2bazel.
"seed": attr.bool(default = False),
"version_json": attr.label(allow_files = [".json"]),
"zipfile": attr.label(allow_single_file = [".zip"]),
}.items()),
)
@@ -247,7 +247,7 @@ def _bower_component_bundle_impl(ctx):
out_versions = ctx.outputs.version_json
ctx.actions.run_shell(
inputs = list(zips),
inputs = zips.to_list(),
outputs = [out_zip],
command = " && ".join([
"p=$PWD",
@@ -256,7 +256,7 @@ def _bower_component_bundle_impl(ctx):
"rm -rf %s.dir" % out_zip.path,
"mkdir -p %s.dir/bower_components" % out_zip.path,
"cd %s.dir/bower_components" % out_zip.path,
"for z in %s; do unzip -q $p/$z ; done" % " ".join(sorted([z.path for z in zips])),
"for z in %s; do unzip -q $p/$z ; done" % " ".join(sorted([z.path for z in zips.to_list()])),
"cd ..",
"find . -exec touch -t 198001010000 '{}' ';'",
"zip -Xqr $p/%s bower_components/*" % out_zip.path,
@@ -265,10 +265,10 @@ def _bower_component_bundle_impl(ctx):
)
ctx.actions.run_shell(
inputs = list(versions),
inputs = versions.to_list(),
outputs = [out_versions],
mnemonic = "BowerVersions",
command = "(echo '{' ; for j in %s ; do cat $j; echo ',' ; done ; echo \\\"\\\":\\\"\\\"; echo '}') > %s" % (" ".join([v.path for v in versions]), out_versions.path),
command = "(echo '{' ; for j in %s ; do cat $j; echo ',' ; done ; echo \\\"\\\":\\\"\\\"; echo '}') > %s" % (" ".join([v.path for v in versions.to_list()]), out_versions.path),
)
return struct(
@@ -281,8 +281,8 @@ bower_component_bundle = rule(
_bower_component_bundle_impl,
attrs = _common_attrs,
outputs = {
"zip": "%{name}.zip",
"version_json": "%{name}-versions.json",
"zip": "%{name}.zip",
},
)
@@ -394,11 +394,6 @@ def _bundle_output_func(name, split):
_bundle_rule = rule(
_bundle_impl,
attrs = {
"deps": attr.label_list(providers = ["transitive_zipfiles"]),
"app": attr.label(
mandatory = True,
allow_single_file = True,
),
"srcs": attr.label_list(allow_files = [
".js",
".html",
@@ -406,12 +401,13 @@ _bundle_rule = rule(
".css",
".ico",
]),
"pkg": attr.string(mandatory = True),
"split": attr.bool(default = True),
"_run_npm": attr.label(
default = Label("//tools/js:run_npm_binary.py"),
"app": attr.label(
mandatory = True,
allow_single_file = True,
),
"pkg": attr.string(mandatory = True),
"split": attr.bool(default = True),
"deps": attr.label_list(providers = ["transitive_zipfiles"]),
"_bundler_archive": attr.label(
default = Label("@polymer-bundler//:%s" % _npm_tarball("polymer-bundler")),
allow_single_file = True,
@@ -420,13 +416,17 @@ _bundle_rule = rule(
default = Label("@crisper//:%s" % _npm_tarball("crisper")),
allow_single_file = True,
),
"_run_npm": attr.label(
default = Label("//tools/js:run_npm_binary.py"),
allow_single_file = True,
),
},
outputs = _bundle_output_func,
)
def bundle_assets(*args, **kwargs):
"""Combine html, js, css files and optionally split into js and html bundles."""
_bundle_rule(*args, pkg = native.package_name(), **kwargs)
_bundle_rule(pkg = native.package_name(), *args, **kwargs)
def polygerrit_plugin(name, app, srcs = [], assets = None, plugin_name = None, **kwargs):
"""Bundles plugin dependencies for deployment.

View File

@@ -50,7 +50,7 @@ def _impl(ctx):
classes = ",".join(
[_AsClassName(x) for x in ctx.attr.srcs],
)
ctx.file_action(output = ctx.outputs.out, content = _OUTPUT % (
ctx.actions.write(output = ctx.outputs.out, content = _OUTPUT % (
classes,
ctx.attr.outname,
))

View File

@@ -166,15 +166,15 @@ def _maven_jar_impl(ctx):
maven_jar = repository_rule(
attrs = {
"artifact": attr.string(mandatory = True),
"attach_source": attr.bool(default = True),
"exclude": attr.string_list(),
"repository": attr.string(default = MAVEN_CENTRAL),
"sha1": attr.string(),
"src_sha1": attr.string(),
"_download_script": attr.label(default = Label("//tools:download_file.py")),
"repository": attr.string(default = MAVEN_CENTRAL),
"attach_source": attr.bool(default = True),
"unsign": attr.bool(default = False),
"deps": attr.string_list(),
"exports": attr.string_list(),
"exclude": attr.string_list(),
"deps": attr.string_list(),
"_download_script": attr.label(default = Label("//tools:download_file.py")),
},
local = True,
implementation = _maven_jar_impl,

View File

@@ -82,7 +82,7 @@ def _war_impl(ctx):
elif hasattr(l, "files"):
transitive_lib_deps += l.files
for dep in transitive_lib_deps:
for dep in transitive_lib_deps.to_list():
cmd += _add_file(dep, build_output + "/WEB-INF/lib/")
inputs.append(dep)
@@ -91,7 +91,7 @@ def _war_impl(ctx):
for l in ctx.attr.pgmlibs:
transitive_pgmlib_deps += l.java.transitive_runtime_deps
for dep in transitive_pgmlib_deps:
for dep in transitive_pgmlib_deps.to_list():
if dep not in inputs:
cmd += _add_file(dep, build_output + "/WEB-INF/pgm-lib/")
inputs.append(dep)
@@ -104,7 +104,7 @@ def _war_impl(ctx):
transitive_context_deps += jar.java.transitive_runtime_deps
elif hasattr(jar, "files"):
transitive_context_deps += jar.files
for dep in transitive_context_deps:
for dep in transitive_context_deps.to_list():
cmd += _add_context(dep, build_output)
inputs.append(dep)

View File

@@ -1,5 +1,5 @@
load("//tools/bzl:pkg_war.bzl", "LIBS", "PGMLIBS")
load("//tools/bzl:classpath.bzl", "classpath_collector")
load("//tools/bzl:pkg_war.bzl", "LIBS", "PGMLIBS")
load(
"//tools/bzl:plugins.bzl",
"CORE_PLUGINS",

View File

@@ -15,14 +15,12 @@
from os import path
REPO_ROOTS = {
'ECLIPSE': 'https://repo.eclipse.org/content/groups/releases',
'GERRIT': 'http://gerrit-maven.storage.googleapis.com',
'GERRIT_API':
'https://gerrit-api.commondatastorage.googleapis.com/release',
'MAVEN_CENTRAL': 'http://repo1.maven.org/maven2',
'MAVEN_LOCAL': 'file://' + path.expanduser('~/.m2/repository'),
'MAVEN_SNAPSHOT':
'https://oss.sonatype.org/content/repositories/snapshots',
'ECLIPSE': 'https://repo.eclipse.org/content/groups/releases',
'GERRIT': 'http://gerrit-maven.storage.googleapis.com',
'GERRIT_API': 'https://gerrit-api.commondatastorage.googleapis.com/release',
'MAVEN_CENTRAL': 'http://repo1.maven.org/maven2',
'MAVEN_LOCAL': 'file://' + path.expanduser('~/.m2/repository'),
'MAVEN_SNAPSHOT': 'https://oss.sonatype.org/content/repositories/snapshots',
}