Merge "Fix merged email for direct pushes"
diff --git a/java/com/google/gerrit/httpd/restapi/RestApiServlet.java b/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
index 1fa8de7..3c39ea1 100644
--- a/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
+++ b/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
@@ -1817,6 +1817,10 @@
logger.atFinest().log(
"Received REST request: %s %s (parameters: %s)",
req.getMethod(), req.getRequestURI(), getParameterNames(req));
+ Optional.ofNullable(req.getHeader(X_GERRIT_DEADLINE))
+ .ifPresent(
+ clientProvidedDeadline ->
+ logger.atFine().log("%s = %s", X_GERRIT_DEADLINE, clientProvidedDeadline));
logger.atFinest().log("Calling user: %s", globals.currentUser.get().getLoggableName());
logger.atFinest().log(
"Groups: %s", lazy(() -> globals.currentUser.get().getEffectiveGroups().getKnownGroups()));
diff --git a/java/com/google/gerrit/server/DeadlineChecker.java b/java/com/google/gerrit/server/DeadlineChecker.java
index 9ef5c4c..5662e50 100644
--- a/java/com/google/gerrit/server/DeadlineChecker.java
+++ b/java/com/google/gerrit/server/DeadlineChecker.java
@@ -170,6 +170,26 @@
Optional<ServerDeadline> serverSideDeadline =
getServerSideDeadline(deadlineConfigs, requestInfo);
Optional<Long> clientedProvidedTimeout = parseTimeout(clientProvidedTimeoutValue);
+ logDeadlines(serverSideDeadline, clientedProvidedTimeout);
+
+ this.cancellationReason =
+ clientedProvidedTimeout.isPresent()
+ ? RequestStateProvider.Reason.CLIENT_PROVIDED_DEADLINE_EXCEEDED
+ : RequestStateProvider.Reason.SERVER_DEADLINE_EXCEEDED;
+ this.timeoutName =
+ clientedProvidedTimeout
+ .map(clientTimeout -> "client.timeout")
+ .orElse(
+ serverSideDeadline
+ .map(serverDeadline -> serverDeadline.id() + ".timeout")
+ .orElse("timeout"));
+ this.timeout =
+ clientedProvidedTimeout.orElse(serverSideDeadline.map(ServerDeadline::timeout).orElse(0L));
+ this.deadline = timeout > 0 ? Optional.of(start + timeout) : Optional.empty();
+ }
+
+ private void logDeadlines(
+ Optional<ServerDeadline> serverSideDeadline, Optional<Long> clientedProvidedTimeout) {
if (serverSideDeadline.isPresent()) {
if (clientedProvidedTimeout.isPresent()) {
logger.atFine().log(
@@ -185,21 +205,11 @@
TimeUnit.MILLISECONDS.convert(
serverSideDeadline.get().timeout(), TimeUnit.NANOSECONDS));
}
+ } else if (clientedProvidedTimeout.isPresent()) {
+ logger.atFine().log(
+ "applying client provided deadline (timeout = %sms)",
+ TimeUnit.MILLISECONDS.convert(clientedProvidedTimeout.get(), TimeUnit.NANOSECONDS));
}
- this.cancellationReason =
- clientedProvidedTimeout.isPresent()
- ? RequestStateProvider.Reason.CLIENT_PROVIDED_DEADLINE_EXCEEDED
- : RequestStateProvider.Reason.SERVER_DEADLINE_EXCEEDED;
- this.timeoutName =
- clientedProvidedTimeout
- .map(clientTimeout -> "client.timeout")
- .orElse(
- serverSideDeadline
- .map(serverDeadline -> serverDeadline.id() + ".timeout")
- .orElse("timeout"));
- this.timeout =
- clientedProvidedTimeout.orElse(serverSideDeadline.map(ServerDeadline::timeout).orElse(0L));
- this.deadline = timeout > 0 ? Optional.of(start + timeout) : Optional.empty();
}
private Optional<ServerDeadline> getServerSideDeadline(
diff --git a/java/com/google/gerrit/server/mail/send/ChangeEmail.java b/java/com/google/gerrit/server/mail/send/ChangeEmail.java
index 48ab397..1a2e150 100644
--- a/java/com/google/gerrit/server/mail/send/ChangeEmail.java
+++ b/java/com/google/gerrit/server/mail/send/ChangeEmail.java
@@ -41,11 +41,10 @@
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.mail.send.ProjectWatch.Watchers;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
-import com.google.gerrit.server.patch.PatchList;
-import com.google.gerrit.server.patch.PatchListEntry;
-import com.google.gerrit.server.patch.PatchListNotAvailableException;
-import com.google.gerrit.server.patch.PatchListObjectTooLargeException;
+import com.google.gerrit.server.patch.DiffNotAvailableException;
+import com.google.gerrit.server.patch.FilePathAdapter;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
+import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackendException;
@@ -66,6 +65,7 @@
import org.apache.james.mime4j.dom.field.FieldName;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.TemporaryBuffer;
@@ -269,17 +269,23 @@
if (patchSet != null) {
detail.append("---\n");
- PatchList patchList = getPatchList();
- for (PatchListEntry p : patchList.getPatches()) {
- if (Patch.isMagic(p.getNewName())) {
+ Map<String, FileDiffOutput> modifiedFiles = listModifiedFiles();
+ for (FileDiffOutput fileDiff : modifiedFiles.values()) {
+ if (fileDiff.newPath().isPresent() && Patch.isMagic(fileDiff.newPath().get())) {
continue;
}
detail
- .append(p.getChangeType().getCode())
+ .append(fileDiff.changeType().getCode())
.append(" ")
- .append(p.getNewName())
+ .append(
+ FilePathAdapter.getNewPath(
+ fileDiff.oldPath(), fileDiff.newPath(), fileDiff.changeType()))
.append("\n");
}
+ Integer insertions =
+ modifiedFiles.values().stream().map(FileDiffOutput::insertions).reduce(0, Integer::sum);
+ Integer deletions =
+ modifiedFiles.values().stream().map(FileDiffOutput::deletions).reduce(0, Integer::sum);
detail.append(
MessageFormat.format(
"" //
@@ -287,9 +293,9 @@
+ "{1,choice,0#0 insertions|1#1 insertion|1<{1} insertions}(+), " //
+ "{2,choice,0#0 deletions|1#1 deletion|1<{2} deletions}(-)" //
+ "\n",
- patchList.getPatches().size() - 1, //
- patchList.getInsertions(), //
- patchList.getDeletions()));
+ modifiedFiles.size() - 1, //
+ insertions, //
+ deletions));
detail.append("\n");
}
return detail.toString();
@@ -300,7 +306,8 @@
}
/** Get the patch list corresponding to patch set patchSetId of this change. */
- protected PatchList getPatchList(int patchSetId) throws PatchListNotAvailableException {
+ protected Map<String, FileDiffOutput> listModifiedFiles(int patchSetId)
+ throws DiffNotAvailableException {
PatchSet ps;
if (patchSetId == patchSet.number()) {
ps = patchSet;
@@ -308,18 +315,20 @@
try {
ps = args.patchSetUtil.get(changeData.notes(), PatchSet.id(change.getId(), patchSetId));
} catch (StorageException e) {
- throw new PatchListNotAvailableException("Failed to get patchSet", e);
+ throw new DiffNotAvailableException("Failed to get patchSet", e);
}
}
- return args.patchListCache.get(change, ps);
+ return args.diffOperations.listModifiedFilesAgainstParent(
+ change.getProject(), ps.commitId(), /* parentNum= */ 0);
}
/** Get the patch list corresponding to this patch set. */
- protected PatchList getPatchList() throws PatchListNotAvailableException {
+ protected Map<String, FileDiffOutput> listModifiedFiles() throws DiffNotAvailableException {
if (patchSet != null) {
- return args.patchListCache.get(change, patchSet);
+ return args.diffOperations.listModifiedFilesAgainstParent(
+ change.getProject(), patchSet.commitId(), /* parentNum= */ 0);
}
- throw new PatchListNotAvailableException("no patchSet specified");
+ throw new DiffNotAvailableException("no patchSet specified");
}
/** Get the project entity the change is in; null if its been deleted. */
@@ -566,18 +575,15 @@
/** Show patch set as unified difference. */
public String getUnifiedDiff() {
- PatchList patchList;
+ Map<String, FileDiffOutput> modifiedFiles;
try {
- patchList = getPatchList();
- if (patchList.getOldId() == null) {
+ modifiedFiles = listModifiedFiles();
+ if (modifiedFiles.isEmpty()) {
// Octopus merges are not well supported for diff output by Gerrit.
// Currently these always have a null oldId in the PatchList.
return "[Octopus merge; cannot be formatted as a diff.]\n";
}
- } catch (PatchListObjectTooLargeException e) {
- logger.atWarning().log("Cannot format patch %s", e.getMessage());
- return "";
- } catch (PatchListNotAvailableException e) {
+ } catch (DiffNotAvailableException e) {
logger.atSevere().withCause(e).log("Cannot format patch");
return "";
}
@@ -587,9 +593,11 @@
try (DiffFormatter fmt = new DiffFormatter(buf)) {
try (Repository git = args.server.openRepository(change.getProject())) {
try {
+ ObjectId oldId = modifiedFiles.values().iterator().next().oldCommitId();
+ ObjectId newId = modifiedFiles.values().iterator().next().newCommitId();
fmt.setRepository(git);
fmt.setDetectRenames(true);
- fmt.format(patchList.getOldId(), patchList.getNewId());
+ fmt.format(oldId, newId);
return RawParseUtils.decode(buf.toByteArray());
} catch (IOException e) {
if (JGitText.get().inMemoryBufferLimitExceeded.equals(e.getMessage())) {
diff --git a/java/com/google/gerrit/server/mail/send/CommentSender.java b/java/com/google/gerrit/server/mail/send/CommentSender.java
index ac6c2f3..4593584 100644
--- a/java/com/google/gerrit/server/mail/send/CommentSender.java
+++ b/java/com/google/gerrit/server/mail/send/CommentSender.java
@@ -36,10 +36,9 @@
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.mail.receive.Protocol;
+import com.google.gerrit.server.patch.DiffNotAvailableException;
import com.google.gerrit.server.patch.PatchFile;
-import com.google.gerrit.server.patch.PatchList;
-import com.google.gerrit.server.patch.PatchListNotAvailableException;
-import com.google.gerrit.server.patch.PatchListObjectTooLargeException;
+import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import com.google.gerrit.server.util.LabelVote;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
@@ -198,24 +197,24 @@
currentGroup = new FileCommentGroup();
currentGroup.filename = c.key.filename;
currentGroup.patchSetId = c.key.patchSetId;
- // Get the patch list:
- PatchList patchList = null;
+ // Get the modified files:
+ Map<String, FileDiffOutput> modifiedFiles = 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");
+ modifiedFiles = listModifiedFiles(c.key.patchSetId);
+ } catch (DiffNotAvailableException e) {
+ logger.atSevere().withCause(e).log("Failed to get modified files");
}
groups.add(currentGroup);
- if (patchList != null) {
+ if (modifiedFiles != null && !modifiedFiles.isEmpty()) {
try {
- currentGroup.fileData = new PatchFile(repo, patchList, c.key.filename);
+ currentGroup.fileData = new PatchFile(repo, modifiedFiles, c.key.filename);
} catch (IOException e) {
logger.atWarning().withCause(e).log(
"Cannot load %s from %s in %s",
- c.key.filename, patchList.getNewId().name(), projectState.getName());
+ c.key.filename,
+ modifiedFiles.values().iterator().next().newCommitId().name(),
+ projectState.getName());
currentGroup.fileData = null;
}
}
diff --git a/java/com/google/gerrit/server/mail/send/EmailArguments.java b/java/com/google/gerrit/server/mail/send/EmailArguments.java
index 735e34a..96effc1 100644
--- a/java/com/google/gerrit/server/mail/send/EmailArguments.java
+++ b/java/com/google/gerrit/server/mail/send/EmailArguments.java
@@ -35,7 +35,7 @@
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.mail.EmailSettings;
import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.patch.PatchListCache;
+import com.google.gerrit.server.patch.DiffOperations;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.project.ProjectCache;
@@ -72,7 +72,7 @@
final PermissionBackend permissionBackend;
final GroupBackend groupBackend;
final AccountCache accountCache;
- final PatchListCache patchListCache;
+ final DiffOperations diffOperations;
final PatchSetUtil patchSetUtil;
final ApprovalsUtil approvalsUtil;
final Provider<FromAddressGenerator> fromAddressGenerator;
@@ -106,7 +106,7 @@
PermissionBackend permissionBackend,
GroupBackend groupBackend,
AccountCache accountCache,
- PatchListCache patchListCache,
+ DiffOperations diffOperations,
PatchSetUtil patchSetUtil,
ApprovalsUtil approvalsUtil,
Provider<FromAddressGenerator> fromAddressGenerator,
@@ -137,7 +137,7 @@
this.permissionBackend = permissionBackend;
this.groupBackend = groupBackend;
this.accountCache = accountCache;
- this.patchListCache = patchListCache;
+ this.diffOperations = diffOperations;
this.patchSetUtil = patchSetUtil;
this.approvalsUtil = approvalsUtil;
this.fromAddressGenerator = fromAddressGenerator;
diff --git a/java/com/google/gerrit/server/patch/PatchFile.java b/java/com/google/gerrit/server/patch/PatchFile.java
index ca5223d..3cc89f85 100644
--- a/java/com/google/gerrit/server/patch/PatchFile.java
+++ b/java/com/google/gerrit/server/patch/PatchFile.java
@@ -18,7 +18,9 @@
import com.google.gerrit.entities.Patch;
import com.google.gerrit.exceptions.NoSuchEntityException;
+import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import java.io.IOException;
+import java.util.Map;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
@@ -35,7 +37,7 @@
/** State supporting processing of a single {@link Patch} instance. */
public class PatchFile {
private final Repository repo;
- private final PatchListEntry entry;
+ private final FileDiffOutput diff;
private final RevTree aTree;
private final RevTree bTree;
@@ -51,21 +53,25 @@
private Text a;
private Text b;
- public PatchFile(Repository repo, PatchList patchList, String fileName)
- throws MissingObjectException, IncorrectObjectTypeException, IOException {
+ public PatchFile(Repository repo, Map<String, FileDiffOutput> modifiedFiles, String fileName)
+ throws IOException {
this.repo = repo;
- this.entry = patchList.get(fileName);
+ this.diff =
+ modifiedFiles.values().stream()
+ .filter(f -> f.newPath().isPresent() && f.newPath().get().equals(fileName))
+ .findFirst()
+ .orElse(FileDiffOutput.empty(fileName, ObjectId.zeroId(), ObjectId.zeroId()));
try (ObjectReader reader = repo.newObjectReader();
RevWalk rw = new RevWalk(reader)) {
- final RevCommit bCommit = rw.parseCommit(patchList.getNewId());
+ final RevCommit bCommit = rw.parseCommit(diff.newCommitId());
if (Patch.COMMIT_MSG.equals(fileName)) {
- if (patchList.getComparisonType().isAgainstParentOrAutoMerge()) {
+ if (diff.comparisonType().isAgainstParentOrAutoMerge()) {
a = Text.EMPTY;
} else {
// For the initial commit, we have an empty tree on Side A
- RevObject object = rw.parseAny(patchList.getOldId());
+ RevObject object = rw.parseAny(diff.oldCommitId());
a = object instanceof RevCommit ? Text.forCommit(reader, object) : Text.EMPTY;
}
b = Text.forCommit(reader, bCommit);
@@ -74,18 +80,18 @@
bTree = null;
} else if (Patch.MERGE_LIST.equals(fileName)) {
// For the initial commit, we have an empty tree on Side A
- RevObject object = rw.parseAny(patchList.getOldId());
+ RevObject object = rw.parseAny(diff.oldCommitId());
a =
object instanceof RevCommit
- ? Text.forMergeList(patchList.getComparisonType(), reader, object)
+ ? Text.forMergeList(diff.comparisonType(), reader, object)
: Text.EMPTY;
- b = Text.forMergeList(patchList.getComparisonType(), reader, bCommit);
+ b = Text.forMergeList(diff.comparisonType(), reader, bCommit);
aTree = null;
bTree = null;
} else {
- if (patchList.getOldId() != null) {
- aTree = rw.parseTree(patchList.getOldId());
+ if (diff.oldCommitId() != null) {
+ aTree = rw.parseTree(diff.oldCommitId());
} else {
final RevCommit p = bCommit.getParent(0);
rw.parseHeaders(p);
@@ -97,11 +103,11 @@
}
private String getOldName() {
- String name = entry.getOldName();
+ String name = FilePathAdapter.getOldPath(diff.oldPath(), diff.changeType());
if (name != null) {
return name;
}
- return entry.getNewName();
+ return FilePathAdapter.getNewPath(diff.oldPath(), diff.newPath(), diff.changeType());
}
/**
@@ -123,7 +129,10 @@
case 1:
if (b == null) {
- b = load(bTree, entry.getNewName());
+ b =
+ load(
+ bTree,
+ FilePathAdapter.getNewPath(diff.oldPath(), diff.newPath(), diff.changeType()));
}
return b.getString(line - 1);
diff --git a/java/com/google/gerrit/server/patch/filediff/FileDiffOutput.java b/java/com/google/gerrit/server/patch/filediff/FileDiffOutput.java
index 76f6eb7..242c1a4 100644
--- a/java/com/google/gerrit/server/patch/filediff/FileDiffOutput.java
+++ b/java/com/google/gerrit/server/patch/filediff/FileDiffOutput.java
@@ -37,7 +37,10 @@
public abstract class FileDiffOutput implements Serializable {
private static final long serialVersionUID = 1L;
- /** The 20 bytes SHA-1 object ID of the old git commit used in the diff. */
+ /**
+ * The 20 bytes SHA-1 object ID of the old git commit used in the diff, or {@link
+ * ObjectId#zeroId()} if {@link #newCommitId()} was a root commit.
+ */
public abstract ObjectId oldCommitId();
/** The 20 bytes SHA-1 object ID of the new git commit used in the diff. */
diff --git a/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiff.java b/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiff.java
index a502a46..2f23c8c 100644
--- a/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiff.java
+++ b/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiff.java
@@ -34,6 +34,7 @@
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.patch.FileHeader;
/**
@@ -120,7 +121,10 @@
/** The file name at the new git tree identified by {@link #newId()} */
public abstract Optional<String> newPath();
- /** The 20 bytes SHA-1 object ID of the old git tree of the diff. */
+ /**
+ * The 20 bytes SHA-1 object ID of the old git tree of the diff, or {@link ObjectId#zeroId()} if
+ * {@link #newId()} was a root git tree (i.e. has no parents).
+ */
public abstract AbbreviatedObjectId oldId();
/** The 20 bytes SHA-1 object ID of the new git tree of the diff. */
diff --git a/java/com/google/gerrit/server/project/SubmitRequirementsAdapter.java b/java/com/google/gerrit/server/project/SubmitRequirementsAdapter.java
index 5d8b99a..0383cdc 100644
--- a/java/com/google/gerrit/server/project/SubmitRequirementsAdapter.java
+++ b/java/com/google/gerrit/server/project/SubmitRequirementsAdapter.java
@@ -70,7 +70,7 @@
private static List<SubmitRequirementResult> createFromCustomSubmitRecord(
SubmitRecord record, ObjectId psCommitId) {
- if (record.labels.isEmpty()) {
+ if (record.labels == null || record.labels.isEmpty()) {
SubmitRequirement sr =
SubmitRequirement.builder()
.setName(record.ruleName)
diff --git a/java/com/google/gerrit/server/rules/PrologEnvironment.java b/java/com/google/gerrit/server/rules/PrologEnvironment.java
index 7d626da..bc0bb1a 100644
--- a/java/com/google/gerrit/server/rules/PrologEnvironment.java
+++ b/java/com/google/gerrit/server/rules/PrologEnvironment.java
@@ -22,7 +22,7 @@
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.patch.PatchListCache;
+import com.google.gerrit.server.patch.DiffOperations;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.project.ProjectCache;
@@ -173,7 +173,7 @@
private final PermissionBackend permissionBackend;
private final GitRepositoryManager repositoryManager;
private final PluginConfigFactory pluginConfigFactory;
- private final PatchListCache patchListCache;
+ private final DiffOperations diffOperations;
private final PatchSetInfoFactory patchSetInfoFactory;
private final IdentifiedUser.GenericFactory userFactory;
private final Provider<AnonymousUser> anonymousUser;
@@ -188,7 +188,7 @@
PermissionBackend permissionBackend,
GitRepositoryManager repositoryManager,
PluginConfigFactory pluginConfigFactory,
- PatchListCache patchListCache,
+ DiffOperations diffOperations,
PatchSetInfoFactory patchSetInfoFactory,
IdentifiedUser.GenericFactory userFactory,
Provider<AnonymousUser> anonymousUser,
@@ -199,7 +199,7 @@
this.permissionBackend = permissionBackend;
this.repositoryManager = repositoryManager;
this.pluginConfigFactory = pluginConfigFactory;
- this.patchListCache = patchListCache;
+ this.diffOperations = diffOperations;
this.patchSetInfoFactory = patchSetInfoFactory;
this.userFactory = userFactory;
this.anonymousUser = anonymousUser;
@@ -237,8 +237,8 @@
return pluginConfigFactory;
}
- public PatchListCache getPatchListCache() {
- return patchListCache;
+ public DiffOperations getDiffOperations() {
+ return diffOperations;
}
public PatchSetInfoFactory getPatchSetInfoFactory() {
diff --git a/java/com/google/gerrit/server/rules/StoredValues.java b/java/com/google/gerrit/server/rules/StoredValues.java
index 1e08a24..1d10c1f 100644
--- a/java/com/google/gerrit/server/rules/StoredValues.java
+++ b/java/com/google/gerrit/server/rules/StoredValues.java
@@ -21,7 +21,6 @@
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.StorageException;
-import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
@@ -30,10 +29,9 @@
import com.google.gerrit.server.account.Emails;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.patch.PatchList;
-import com.google.gerrit.server.patch.PatchListCache;
-import com.google.gerrit.server.patch.PatchListKey;
-import com.google.gerrit.server.patch.PatchListNotAvailableException;
+import com.google.gerrit.server.patch.DiffNotAvailableException;
+import com.google.gerrit.server.patch.DiffOperations;
+import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.change.ChangeData;
@@ -87,24 +85,27 @@
}
};
- public static final StoredValue<PatchList> PATCH_LIST =
- new StoredValue<PatchList>() {
+ public static final StoredValue<Map<String, FileDiffOutput>> DIFF_LIST =
+ new StoredValue<Map<String, FileDiffOutput>>() {
@Override
- public PatchList createValue(Prolog engine) {
+ public Map<String, FileDiffOutput> createValue(Prolog engine) {
PrologEnvironment env = (PrologEnvironment) engine.control;
PatchSet ps = getPatchSet(engine);
- PatchListCache plCache = env.getArgs().getPatchListCache();
+ DiffOperations diffOperations = env.getArgs().getDiffOperations();
Change change = getChange(engine);
Project.NameKey project = change.getProject();
- Whitespace ws = Whitespace.IGNORE_NONE;
- PatchListKey plKey = PatchListKey.againstDefaultBase(ps.commitId(), ws);
- PatchList patchList;
+ Map<String, FileDiffOutput> diffList;
try {
- patchList = plCache.get(plKey, project);
- } catch (PatchListNotAvailableException e) {
- throw new SystemException(String.format("Cannot create %s: %s", plKey, e.getMessage()));
+ diffList =
+ diffOperations.listModifiedFilesAgainstParent(
+ project, ps.commitId(), /* parentNum= */ 0);
+ } catch (DiffNotAvailableException e) {
+ throw new SystemException(
+ String.format(
+ "Cannot create modified files for project %s, commit Id %s: %s",
+ project, ps.commitId(), e.getMessage()));
}
- return patchList;
+ return diffList;
}
};
diff --git a/java/gerrit/BUILD b/java/gerrit/BUILD
index db831b7..fea2696 100644
--- a/java/gerrit/BUILD
+++ b/java/gerrit/BUILD
@@ -5,6 +5,7 @@
srcs = glob(["**/*.java"]),
visibility = ["//visibility:public"],
deps = [
+ "//java/com/google/gerrit/common:annotations",
"//java/com/google/gerrit/entities",
"//java/com/google/gerrit/extensions:api",
"//java/com/google/gerrit/server",
diff --git a/java/gerrit/PRED_commit_edits_2.java b/java/gerrit/PRED_commit_edits_2.java
index 12e7086..6083010 100644
--- a/java/gerrit/PRED_commit_edits_2.java
+++ b/java/gerrit/PRED_commit_edits_2.java
@@ -14,10 +14,13 @@
package gerrit;
+import com.google.common.collect.Iterables;
+import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Patch;
-import com.google.gerrit.server.patch.PatchList;
-import com.google.gerrit.server.patch.PatchListEntry;
+import com.google.gerrit.server.patch.FilePathAdapter;
import com.google.gerrit.server.patch.Text;
+import com.google.gerrit.server.patch.filediff.FileDiffOutput;
+import com.google.gerrit.server.patch.filediff.TaggedEdit;
import com.google.gerrit.server.rules.StoredValues;
import com.googlecode.prolog_cafe.exceptions.IllegalTypeException;
import com.googlecode.prolog_cafe.exceptions.JavaException;
@@ -31,7 +34,9 @@
import com.googlecode.prolog_cafe.lang.VariableTerm;
import java.io.IOException;
import java.util.List;
+import java.util.Map;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import org.eclipse.jgit.diff.Edit;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
@@ -40,7 +45,6 @@
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
@@ -69,27 +73,26 @@
Pattern fileRegex = getRegexParameter(a1);
Pattern editRegex = getRegexParameter(a2);
- PatchList pl = StoredValues.PATCH_LIST.get(engine);
+ Map<String, FileDiffOutput> modifiedFiles = StoredValues.DIFF_LIST.get(engine);
+ FileDiffOutput firstDiff = Iterables.getFirst(modifiedFiles.values(), /* defaultValue= */ null);
+ if (firstDiff == null) {
+ // No available diffs. We cannot identify old and new commit IDs.
+ engine.fail();
+ }
Repository repo = StoredValues.REPOSITORY.get(engine);
try (ObjectReader reader = repo.newObjectReader();
RevWalk rw = new RevWalk(reader)) {
- final RevTree aTree;
- final RevTree bTree;
- final RevCommit bCommit = rw.parseCommit(pl.getNewId());
+ final RevTree aTree =
+ firstDiff.oldCommitId().equals(ObjectId.zeroId())
+ ? null
+ : rw.parseTree(firstDiff.oldCommitId());
+ final RevTree bTree = rw.parseCommit(firstDiff.newCommitId()).getTree();
- if (pl.getOldId() != null) {
- aTree = rw.parseTree(pl.getOldId());
- } else {
- // Octopus merge with unknown automatic merge result, since the
- // web UI returns no files to match against, just fail.
- return engine.fail();
- }
- bTree = bCommit.getTree();
-
- for (PatchListEntry entry : pl.getPatches()) {
- String newName = entry.getNewName();
- String oldName = entry.getOldName();
+ for (FileDiffOutput entry : modifiedFiles.values()) {
+ String newName =
+ FilePathAdapter.getNewPath(entry.oldPath(), entry.newPath(), entry.changeType());
+ String oldName = FilePathAdapter.getOldPath(entry.oldPath(), entry.changeType());
if (Patch.isMagic(newName)) {
continue;
@@ -97,7 +100,8 @@
if (fileRegex.matcher(newName).find()
|| (oldName != null && fileRegex.matcher(oldName).find())) {
- List<Edit> edits = entry.getEdits();
+ List<Edit> edits =
+ entry.edits().stream().map(TaggedEdit::jgitEdit).collect(Collectors.toList());
if (edits.isEmpty()) {
continue;
}
@@ -141,10 +145,10 @@
return Pattern.compile(term.name(), Pattern.MULTILINE);
}
- private Text load(ObjectId tree, String path, ObjectReader reader)
+ private Text load(@Nullable ObjectId tree, String path, ObjectReader reader)
throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException,
IOException {
- if (path == null) {
+ if (tree == null || path == null) {
return Text.EMPTY;
}
final TreeWalk tw = TreeWalk.forPath(reader, path, tree);
diff --git a/java/gerrit/PRED_commit_stats_3.java b/java/gerrit/PRED_commit_stats_3.java
index 286bc2c..82fad3d 100644
--- a/java/gerrit/PRED_commit_stats_3.java
+++ b/java/gerrit/PRED_commit_stats_3.java
@@ -15,8 +15,7 @@
package gerrit;
import com.google.gerrit.entities.Patch;
-import com.google.gerrit.server.patch.PatchList;
-import com.google.gerrit.server.patch.PatchListEntry;
+import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import com.google.gerrit.server.rules.StoredValues;
import com.googlecode.prolog_cafe.exceptions.PrologException;
import com.googlecode.prolog_cafe.lang.IntegerTerm;
@@ -24,7 +23,8 @@
import com.googlecode.prolog_cafe.lang.Predicate;
import com.googlecode.prolog_cafe.lang.Prolog;
import com.googlecode.prolog_cafe.lang.Term;
-import java.util.List;
+import java.util.Collection;
+import java.util.Map;
/**
* Exports basic commit statistics.
@@ -49,25 +49,30 @@
Term a2 = arg2.dereference();
Term a3 = arg3.dereference();
- PatchList pl = StoredValues.PATCH_LIST.get(engine);
+ Map<String, FileDiffOutput> modifiedFiles = StoredValues.DIFF_LIST.get(engine);
// Account for magic files
if (!a1.unify(
- new IntegerTerm(pl.getPatches().size() - countMagicFiles(pl.getPatches())), engine.trail)) {
+ new IntegerTerm(modifiedFiles.size() - countMagicFiles(modifiedFiles.values())),
+ engine.trail)) {
return engine.fail();
}
- if (!a2.unify(new IntegerTerm(pl.getInsertions()), engine.trail)) {
+ Integer insertions =
+ modifiedFiles.values().stream().map(FileDiffOutput::insertions).reduce(0, Integer::sum);
+ Integer deletions =
+ modifiedFiles.values().stream().map(FileDiffOutput::deletions).reduce(0, Integer::sum);
+ if (!a2.unify(new IntegerTerm(insertions), engine.trail)) {
return engine.fail();
}
- if (!a3.unify(new IntegerTerm(pl.getDeletions()), engine.trail)) {
+ if (!a3.unify(new IntegerTerm(deletions), engine.trail)) {
return engine.fail();
}
return cont;
}
- private int countMagicFiles(List<PatchListEntry> entries) {
+ private int countMagicFiles(Collection<FileDiffOutput> entries) {
int count = 0;
- for (PatchListEntry e : entries) {
- if (Patch.isMagic(e.getNewName())) {
+ for (FileDiffOutput e : entries) {
+ if (e.newPath().isPresent() && Patch.isMagic(e.newPath().get())) {
count++;
}
}
diff --git a/java/gerrit/PRED_files_1.java b/java/gerrit/PRED_files_1.java
index ac45449..dbf96da 100644
--- a/java/gerrit/PRED_files_1.java
+++ b/java/gerrit/PRED_files_1.java
@@ -15,7 +15,8 @@
package gerrit;
import com.google.gerrit.entities.Patch;
-import com.google.gerrit.server.patch.PatchListEntry;
+import com.google.gerrit.server.patch.FilePathAdapter;
+import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import com.google.gerrit.server.rules.StoredValues;
import com.googlecode.prolog_cafe.exceptions.PrologException;
import com.googlecode.prolog_cafe.lang.ListTerm;
@@ -26,8 +27,8 @@
import com.googlecode.prolog_cafe.lang.SymbolTerm;
import com.googlecode.prolog_cafe.lang.Term;
import java.io.IOException;
+import java.util.Collection;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.jgit.lib.FileMode;
@@ -54,17 +55,20 @@
try (RevWalk revWalk = new RevWalk(StoredValues.REPOSITORY.get(engine))) {
RevCommit commit = revWalk.parseCommit(StoredValues.getPatchSet(engine).commitId());
- List<PatchListEntry> patches = StoredValues.PATCH_LIST.get(engine).getPatches();
+ Collection<FileDiffOutput> modifiedFiles = StoredValues.DIFF_LIST.get(engine).values();
Set<String> submodules =
- getAllSubmodulePaths(StoredValues.REPOSITORY.get(engine), commit, patches);
- for (PatchListEntry entry : patches) {
- if (Patch.isMagic(entry.getNewName())) {
+ getAllSubmodulePaths(StoredValues.REPOSITORY.get(engine), commit, modifiedFiles);
+ for (FileDiffOutput fileDiff : modifiedFiles) {
+ if (fileDiff.newPath().isPresent() && Patch.isMagic(fileDiff.newPath().get())) {
continue;
}
- SymbolTerm fileNameTerm = SymbolTerm.create(entry.getNewName());
- SymbolTerm changeType = SymbolTerm.create(entry.getChangeType().getCode());
+ String newPath =
+ FilePathAdapter.getNewPath(
+ fileDiff.oldPath(), fileDiff.newPath(), fileDiff.changeType());
+ SymbolTerm fileNameTerm = SymbolTerm.create(newPath);
+ SymbolTerm changeType = SymbolTerm.create(fileDiff.changeType().getCode());
SymbolTerm fileType;
- if (submodules.contains(entry.getNewName())) {
+ if (submodules.contains(newPath)) {
fileType = SymbolTerm.create("SUBMODULE");
} else {
fileType = SymbolTerm.create("REGULAR");
@@ -83,14 +87,14 @@
/** Returns the paths for all {@code GITLINK} files. */
private static Set<String> getAllSubmodulePaths(
- Repository repository, RevCommit commit, List<PatchListEntry> patches)
+ Repository repository, RevCommit commit, Collection<FileDiffOutput> modifiedFiles)
throws PrologException, IOException {
Set<String> submodules = new HashSet<>();
try (TreeWalk treeWalk = new TreeWalk(repository)) {
treeWalk.addTree(commit.getTree());
Set<String> allPaths =
- patches.stream()
- .map(PatchListEntry::getNewName)
+ modifiedFiles.stream()
+ .map(f -> FilePathAdapter.getNewPath(f.oldPath(), f.newPath(), f.changeType()))
.filter(f -> !Patch.isMagic(f))
.collect(Collectors.toSet());
treeWalk.setFilter(PathFilterGroup.createFromStrings(allPaths));
diff --git a/javatests/com/google/gerrit/server/project/SubmitRequirementsAdapterTest.java b/javatests/com/google/gerrit/server/project/SubmitRequirementsAdapterTest.java
index 7e1e821..2212fe7 100644
--- a/javatests/com/google/gerrit/server/project/SubmitRequirementsAdapterTest.java
+++ b/javatests/com/google/gerrit/server/project/SubmitRequirementsAdapterTest.java
@@ -17,6 +17,7 @@
import static com.google.common.truth.Truth.assertThat;
import com.google.common.collect.ImmutableList;
+import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.LabelFunction;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.LabelValue;
@@ -72,7 +73,7 @@
}
@Test
- public void defaultSubmitRule_WithLabelsAllPass() {
+ public void defaultSubmitRule_withLabelsAllPass() {
SubmitRecord submitRecord =
createSubmitRecord(
"gerrit~DefaultSubmitRule",
@@ -100,7 +101,7 @@
}
@Test
- public void defaultSubmitRule_WithLabelsAllNeed() {
+ public void defaultSubmitRule_withLabelsAllNeed() {
SubmitRecord submitRecord =
createSubmitRecord(
"gerrit~DefaultSubmitRule",
@@ -128,7 +129,7 @@
}
@Test
- public void customSubmitRule_NoLabels_WithStatusOk() {
+ public void customSubmitRule_noLabels_withStatusOk() {
SubmitRecord submitRecord =
createSubmitRecord("gerrit~IgnoreSelfApprovalRule", Status.OK, Arrays.asList());
@@ -145,7 +146,24 @@
}
@Test
- public void customSubmitRule_NoLabels_WithStatusNotReady() {
+ public void customSubmitRule_nullLabels_withStatusOk() {
+ SubmitRecord submitRecord =
+ createSubmitRecord("gerrit~IgnoreSelfApprovalRule", Status.OK, /* labels= */ null);
+
+ List<SubmitRequirementResult> requirements =
+ SubmitRequirementsAdapter.createResult(submitRecord, labelTypes, psCommitId);
+
+ assertThat(requirements).hasSize(1);
+ assertResult(
+ requirements.get(0),
+ /* reqName= */ "gerrit~IgnoreSelfApprovalRule",
+ /* submitExpression= */ "rule:gerrit~IgnoreSelfApprovalRule",
+ SubmitRequirementResult.Status.SATISFIED,
+ SubmitRequirementExpressionResult.Status.PASS);
+ }
+
+ @Test
+ public void customSubmitRule_noLabels_withStatusNotReady() {
SubmitRecord submitRecord =
createSubmitRecord("gerrit~IgnoreSelfApprovalRule", Status.NOT_READY, Arrays.asList());
@@ -162,7 +180,7 @@
}
@Test
- public void customSubmitRule_WithLabels() {
+ public void customSubmitRule_withLabels() {
SubmitRecord submitRecord =
createSubmitRecord(
"gerrit~PrologRule",
@@ -203,7 +221,7 @@
}
private SubmitRecord createSubmitRecord(
- String ruleName, SubmitRecord.Status status, List<Label> labels) {
+ String ruleName, SubmitRecord.Status status, @Nullable List<Label> labels) {
SubmitRecord record = new SubmitRecord();
record.ruleName = ruleName;
record.status = status;
diff --git a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts
index 1908df0..6dd67e4 100644
--- a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts
+++ b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts
@@ -41,6 +41,7 @@
import {ParsedChangeInfo} from '../../../types/types';
import {GrButton} from '../../shared/gr-button/gr-button';
import {TokenHighlightLayer} from '../gr-diff-builder/token-highlight-layer';
+import {KnownExperimentId} from '../../../services/flags/flags';
export interface GrApplyFixDialog {
$: {
@@ -98,7 +99,11 @@
})
_disableApplyFixButton = false;
- layers = [new TokenHighlightLayer(this)];
+ layers = appContext.flagsService.isEnabled(
+ KnownExperimentId.TOKEN_HIGHLIGHTING
+ )
+ ? [new TokenHighlightLayer(this)]
+ : [];
private refitOverlay?: () => void;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
index fa3ddf4..c4fed53 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
@@ -412,7 +412,11 @@
private _getLayers(path: string): DiffLayer[] {
const layers = [];
- layers.push(new TokenHighlightLayer(this));
+ if (
+ appContext.flagsService.isEnabled(KnownExperimentId.TOKEN_HIGHLIGHTING)
+ ) {
+ layers.push(new TokenHighlightLayer(this));
+ }
layers.push(this.syntaxLayer);
// Get layers from plugins (if any).
layers.push(...this.jsAPI.getDiffLayers(path));
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.js b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.js
index b24b3ba..344f9d8 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.js
@@ -1270,7 +1270,7 @@
test('gr-diff-host provides syntax highlighting layer', async () => {
stubRestApi('getDiff').returns(Promise.resolve({content: []}));
await element.reload();
- assert.equal(element.$.diff.layers[1], element.syntaxLayer);
+ assert.equal(element.$.diff.layers[0], element.syntaxLayer);
});
test('rendering normal-sized diff does not disable syntax', () => {
@@ -1324,7 +1324,7 @@
test('gr-diff-host provides syntax highlighting layer', async () => {
stubRestApi('getDiff').returns(Promise.resolve({content: []}));
await element.reload();
- assert.equal(element.$.diff.layers[1], element.syntaxLayer);
+ assert.equal(element.$.diff.layers[0], element.syntaxLayer);
});
test('syntax layer should be disabled', () => {
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts
index 39a87a2..d6aae5c 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts
@@ -54,6 +54,7 @@
import {CustomKeyboardEvent} from '../../../types/events';
import {LineNumber, FILE} from '../../diff/gr-diff/gr-diff-line';
import {GrButton} from '../gr-button/gr-button';
+import {KnownExperimentId} from '../../../services/flags/flags';
import {DiffInfo, DiffPreferencesInfo} from '../../../types/diff';
import {RenderPreferences} from '../../../api/diff';
import {
@@ -211,6 +212,8 @@
private readonly reporting = appContext.reportingService;
+ private readonly flagsService = appContext.flagsService;
+
private readonly commentsService = appContext.commentsService;
readonly storage = appContext.storageService;
@@ -357,7 +360,9 @@
_getLayers(diff?: DiffInfo) {
if (!diff) return [];
const layers = [];
- layers.push(new TokenHighlightLayer(this));
+ if (this.flagsService.isEnabled(KnownExperimentId.TOKEN_HIGHLIGHTING)) {
+ layers.push(new TokenHighlightLayer(this));
+ }
layers.push(this.syntaxLayer);
return layers;
}
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints.ts
index f7475bf..b039a7e 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints.ts
@@ -104,7 +104,7 @@
* which endpoints to dynamically add to the page.
*/
registerModule(plugin: PluginApi, opts: Options) {
- const endpoint = opts.endpoint!;
+ const endpoint = opts.endpoint;
const dynamicEndpoint = opts.dynamicEndpoint;
if (dynamicEndpoint) {
if (!this._dynamicPlugins.has(dynamicEndpoint)) {
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.js
deleted file mode 100644
index e3475ad..0000000
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.js
+++ /dev/null
@@ -1,166 +0,0 @@
-/**
- * @license
- * Copyright (C) 2020 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.
- */
-
-import '../../../test/common-test-setup-karma.js';
-import {resetPlugins} from '../../../test/test-utils.js';
-import './gr-js-api-interface.js';
-import {GrPluginEndpoints} from './gr-plugin-endpoints.js';
-import {_testOnly_initGerritPluginApi} from './gr-gerrit.js';
-
-const pluginApi = _testOnly_initGerritPluginApi();
-
-suite('gr-plugin-endpoints tests', () => {
- let instance;
- let pluginFoo;
- let pluginBar;
- let domHook;
-
- setup(() => {
- domHook = {};
- instance = new GrPluginEndpoints();
- pluginApi.install(p => { pluginFoo = p; }, '0.1',
- 'http://test.com/plugins/testplugin/static/foo.js');
- instance.registerModule(
- pluginFoo,
- {
- endpoint: 'a-place',
- type: 'decorate',
- moduleName: 'foo-module',
- domHook,
- }
- );
- pluginApi.install(p => { pluginBar = p; }, '0.1',
- 'http://test.com/plugins/testplugin/static/bar.js');
- instance.registerModule(
- pluginBar,
- {
- endpoint: 'a-place',
- type: 'style',
- moduleName: 'bar-module',
- domHook,
- }
- );
- });
-
- teardown(() => {
- resetPlugins();
- });
-
- test('getDetails all', () => {
- assert.deepEqual(instance.getDetails('a-place'), [
- {
- moduleName: 'foo-module',
- plugin: pluginFoo,
- pluginUrl: pluginFoo._url,
- type: 'decorate',
- domHook,
- slot: undefined,
- },
- {
- moduleName: 'bar-module',
- plugin: pluginBar,
- pluginUrl: pluginBar._url,
- type: 'style',
- domHook,
- slot: undefined,
- },
- ]);
- });
-
- test('getDetails by type', () => {
- assert.deepEqual(instance.getDetails('a-place', {type: 'style'}), [
- {
- moduleName: 'bar-module',
- plugin: pluginBar,
- pluginUrl: pluginBar._url,
- type: 'style',
- domHook,
- slot: undefined,
- },
- ]);
- });
-
- test('getDetails by module', () => {
- assert.deepEqual(
- instance.getDetails('a-place', {moduleName: 'foo-module'}),
- [
- {
- moduleName: 'foo-module',
- plugin: pluginFoo,
- pluginUrl: pluginFoo._url,
- type: 'decorate',
- domHook,
- slot: undefined,
- },
- ]);
- });
-
- test('getModules', () => {
- assert.deepEqual(
- instance.getModules('a-place'), ['foo-module', 'bar-module']);
- });
-
- test('getPlugins', () => {
- assert.deepEqual(
- instance.getPlugins('a-place'), [pluginFoo._url]);
- });
-
- test('onNewEndpoint', () => {
- const newModuleStub = sinon.stub();
- instance.setPluginsReady();
- instance.onNewEndpoint('a-place', newModuleStub);
- instance.registerModule(
- pluginFoo,
- {
- endpoint: 'a-place',
- type: 'replace',
- moduleName: 'zaz-module',
- domHook,
- });
- assert.deepEqual(newModuleStub.lastCall.args[0], {
- moduleName: 'zaz-module',
- plugin: pluginFoo,
- pluginUrl: pluginFoo._url,
- type: 'replace',
- domHook,
- slot: undefined,
- });
- });
-
- test('reuse dom hooks', () => {
- instance.registerModule(
- pluginFoo, 'a-place', 'decorate', 'foo-module', domHook);
- assert.deepEqual(instance.getDetails('a-place'), [
- {
- moduleName: 'foo-module',
- plugin: pluginFoo,
- pluginUrl: pluginFoo._url,
- type: 'decorate',
- domHook,
- slot: undefined,
- },
- {
- moduleName: 'bar-module',
- plugin: pluginBar,
- pluginUrl: pluginBar._url,
- type: 'style',
- domHook,
- slot: undefined,
- },
- ]);
- });
-});
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.ts
new file mode 100644
index 0000000..c7bdfb4
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.ts
@@ -0,0 +1,177 @@
+/**
+ * @license
+ * Copyright (C) 2020 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.
+ */
+import '../../../test/common-test-setup-karma';
+import {resetPlugins} from '../../../test/test-utils';
+import './gr-js-api-interface';
+import {GrPluginEndpoints} from './gr-plugin-endpoints';
+import {_testOnly_initGerritPluginApi} from './gr-gerrit';
+import {PluginApi} from '../../../api/plugin';
+import {HookApi, HookCallback, PluginElement} from '../../../api/hook';
+
+const pluginApi = _testOnly_initGerritPluginApi();
+
+export class MockHook<T extends PluginElement> implements HookApi<T> {
+ handleInstanceDetached(_: T) {}
+
+ handleInstanceAttached(_: T) {}
+
+ getLastAttached(): Promise<HTMLElement> {
+ throw new Error('unimplemented in mock');
+ }
+
+ getAllAttached() {
+ return [];
+ }
+
+ onAttached(_: HookCallback<T>) {
+ return this;
+ }
+
+ onDetached(_: HookCallback<T>) {
+ return this;
+ }
+
+ getModuleName() {
+ return 'MockHookApi-ModuleName';
+ }
+}
+
+suite('gr-plugin-endpoints tests', () => {
+ let instance: GrPluginEndpoints;
+ let decoratePlugin: PluginApi;
+ let stylePlugin: PluginApi;
+ let domHook: HookApi<PluginElement>;
+
+ setup(() => {
+ domHook = new MockHook<PluginElement>();
+ instance = new GrPluginEndpoints();
+ pluginApi.install(
+ plugin => (decoratePlugin = plugin),
+ '0.1',
+ 'http://test.com/plugins/testplugin/static/decorate.js'
+ );
+ instance.registerModule(decoratePlugin, {
+ endpoint: 'my-endpoint',
+ type: 'decorate',
+ moduleName: 'decorate-module',
+ domHook,
+ });
+ pluginApi.install(
+ plugin => (stylePlugin = plugin),
+ '0.1',
+ 'http://test.com/plugins/testplugin/static/style.js'
+ );
+ instance.registerModule(stylePlugin, {
+ endpoint: 'my-endpoint',
+ type: 'style',
+ moduleName: 'style-module',
+ domHook,
+ });
+ });
+
+ teardown(() => {
+ resetPlugins();
+ });
+
+ test('getDetails all', () => {
+ assert.deepEqual(instance.getDetails('my-endpoint'), [
+ {
+ moduleName: 'decorate-module',
+ plugin: decoratePlugin,
+ pluginUrl: decoratePlugin._url,
+ type: 'decorate',
+ domHook,
+ slot: undefined,
+ },
+ {
+ moduleName: 'style-module',
+ plugin: stylePlugin,
+ pluginUrl: stylePlugin._url,
+ type: 'style',
+ domHook,
+ slot: undefined,
+ },
+ ]);
+ });
+
+ test('getDetails by type', () => {
+ assert.deepEqual(
+ instance.getDetails('my-endpoint', {endpoint: 'a-place', type: 'style'}),
+ [
+ {
+ moduleName: 'style-module',
+ plugin: stylePlugin,
+ pluginUrl: stylePlugin._url,
+ type: 'style',
+ domHook,
+ slot: undefined,
+ },
+ ]
+ );
+ });
+
+ test('getDetails by module', () => {
+ assert.deepEqual(
+ instance.getDetails('my-endpoint', {
+ endpoint: 'my-endpoint',
+ moduleName: 'decorate-module',
+ }),
+ [
+ {
+ moduleName: 'decorate-module',
+ plugin: decoratePlugin,
+ pluginUrl: decoratePlugin._url,
+ type: 'decorate',
+ domHook,
+ slot: undefined,
+ },
+ ]
+ );
+ });
+
+ test('getModules', () => {
+ assert.deepEqual(instance.getModules('my-endpoint'), [
+ 'decorate-module',
+ 'style-module',
+ ]);
+ });
+
+ test('getPlugins URLs are unique', () => {
+ assert.equal(decoratePlugin._url, stylePlugin._url);
+ assert.deepEqual(instance.getPlugins('my-endpoint'), [decoratePlugin._url]);
+ });
+
+ test('onNewEndpoint', () => {
+ const newModuleStub = sinon.stub();
+ instance.setPluginsReady();
+ instance.onNewEndpoint('my-endpoint', newModuleStub);
+ instance.registerModule(decoratePlugin, {
+ endpoint: 'my-endpoint',
+ type: 'replace',
+ moduleName: 'replace-module',
+ domHook,
+ });
+ assert.deepEqual(newModuleStub.lastCall.args[0], {
+ moduleName: 'replace-module',
+ plugin: decoratePlugin,
+ pluginUrl: decoratePlugin._url,
+ type: 'replace',
+ domHook,
+ slot: undefined,
+ });
+ });
+});
diff --git a/polygerrit-ui/app/services/flags/flags.ts b/polygerrit-ui/app/services/flags/flags.ts
index 21f3aa4..ef5fde2 100644
--- a/polygerrit-ui/app/services/flags/flags.ts
+++ b/polygerrit-ui/app/services/flags/flags.ts
@@ -25,6 +25,7 @@
*/
export enum KnownExperimentId {
NEW_IMAGE_DIFF_UI = 'UiFeature__new_image_diff_ui',
+ TOKEN_HIGHLIGHTING = 'UiFeature__token_highlighting',
CHECKS_DEVELOPER = 'UiFeature__checks_developer',
NEW_REPLY_DIALOG = 'UiFeature__new_reply_dialog',
SUBMIT_REQUIREMENTS_UI = 'UiFeature__submit_requirements_ui',