Merge "Mention --secure-store-lib in pgm-init doc as links to SecureStore docs"
diff --git a/Documentation/cmd-index-activate.txt b/Documentation/cmd-index-activate.txt
index 37783ef..6cb7781 100644
--- a/Documentation/cmd-index-activate.txt
+++ b/Documentation/cmd-index-activate.txt
@@ -5,7 +5,7 @@
== SYNOPSIS
--
-'ssh' -p @SSH_PORT@ @SSH_HOST@ 'gerrit index activate <index>'
+'ssh' -p <port> <host> 'gerrit index activate <index>'
--
== DESCRIPTION
diff --git a/Documentation/cmd-index-start.txt b/Documentation/cmd-index-start.txt
index cee283e..0a481e5 100644
--- a/Documentation/cmd-index-start.txt
+++ b/Documentation/cmd-index-start.txt
@@ -5,7 +5,7 @@
== SYNOPSIS
--
-'ssh' -p @SSH_PORT@ @SSH_HOST@ 'gerrit index start <index>'
+'ssh' -p <port> <host> 'gerrit index start <index>'
--
== DESCRIPTION
diff --git a/Documentation/cmd-query.txt b/Documentation/cmd-query.txt
index 0ff59d4..090781b 100644
--- a/Documentation/cmd-query.txt
+++ b/Documentation/cmd-query.txt
@@ -54,15 +54,17 @@
--current-patch-set::
Include information about the current patch set in the results.
+ Note that the information will only be included when the current
+ patch set is visible to the caller.
--patch-sets::
- Include information about all patch sets. If combined with
- the --current-patch-set flag then the current patch set
- information will be output twice, once in each field.
+ Include information about all patch sets visible to the caller.
+ If combined with the --current-patch-set flag then the current patch
+ set information will be output twice, once in each field.
--all-approvals::
- Include information about all patch sets along with the
- approval information for each patch set. If combined with
+ Include information about all patch sets visible to the caller along
+ with the approval information for each patch set. If combined with
the --current-patch-set flag then the current patch set
information will be output twice, once in each field.
@@ -76,7 +78,7 @@
--comments::
Include comments for all changes. If combined with the
--patch-sets flag then all inline/file comments are included for
- each patch set.
+ each patch set that is visible to the caller.
--commit-message::
Include the full commit message in the change description.
diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index fd49487..1955c39 100644
--- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -496,6 +496,11 @@
revision(r).submit();
}
+ protected PushOneCommit.Result amendChangeAsDraft(String changeId)
+ throws Exception {
+ return amendChange(changeId, "refs/drafts/master");
+ }
+
protected ChangeInfo info(String id)
throws RestApiException {
return gApi.changes().id(id).info();
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java
index cbaf789..bc206b4 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java
@@ -32,6 +32,7 @@
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.ReviewInput.NotifyHandling;
+import com.google.gerrit.extensions.api.projects.BranchInput;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
@@ -46,12 +47,14 @@
import com.google.gerrit.testutil.TestTimeUtil;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.transport.PushResult;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.Collection;
+import java.util.List;
import java.util.Set;
public abstract class AbstractPushForReview extends AbstractDaemonTest {
@@ -488,4 +491,37 @@
r.assertErrorStatus(
"not Signed-off-by author/committer/uploader in commit message footer");
}
+
+ @Test
+ public void testPushSameCommitTwiceUsingMagicBranchBaseOption()
+ throws Exception {
+ grant(Permission.PUSH, project, "refs/heads/master");
+ PushOneCommit.Result rBase = pushTo("refs/heads/master");
+ rBase.assertOkStatus();
+
+ gApi.projects()
+ .name(project.get())
+ .branch("foo")
+ .create(new BranchInput());
+
+ PushOneCommit push =
+ pushFactory.create(db, admin.getIdent(), testRepo, PushOneCommit.SUBJECT,
+ "b.txt", "anotherContent");
+
+ PushOneCommit.Result r = push.to("refs/for/master");
+ r.assertOkStatus();
+
+ PushResult pr = GitUtil.pushHead(
+ testRepo, "refs/for/foo%base=" + rBase.getCommit().name(), false, false);
+ assertThat(pr.getMessages()).contains("changes: new: 1, refs: 1, done");
+
+ List<ChangeInfo> changes = query(r.getCommit().name());
+ assertThat(changes).hasSize(2);
+ ChangeInfo c1 = get(changes.get(0).id);
+ ChangeInfo c2 = get(changes.get(1).id);
+ assertThat(c1.project).isEqualTo(c2.project);
+ assertThat(c1.branch).isNotEqualTo(c2.branch);
+ assertThat(c1.changeId).isEqualTo(c2.changeId);
+ assertThat(c1.currentRevision).isEqualTo(c2.currentRevision);
+ }
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
index 24d0e097..a6ea4d2 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
@@ -28,10 +28,11 @@
import com.google.gerrit.server.config.AnonymousCowardNameProvider;
import com.google.gerrit.server.config.GetServerInfo.ServerInfo;
-import java.nio.file.Path;
-import java.nio.file.Files;
import org.junit.Test;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
public class ServerInfoIT extends AbstractDaemonTest {
@Test
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/AccessIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/AccessIT.java
index 057d902..9a5dfeb 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/AccessIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/AccessIT.java
@@ -14,6 +14,7 @@
package com.google.gerrit.acceptance.rest.project;
import static com.google.common.truth.Truth.assertThat;
+
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.server.config.AllProjectsNameProvider;
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/QueryIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/QueryIT.java
index 3733cd1..2865ff87 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/QueryIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/QueryIT.java
@@ -16,11 +16,13 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assert_;
+import static com.google.gerrit.acceptance.GitUtil.initSsh;
import com.google.common.collect.Lists;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.SshSession;
import com.google.gerrit.extensions.api.changes.AddReviewerInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.client.Side;
@@ -300,13 +302,39 @@
assertThat(changes.get(0).submitRecords.size()).isEqualTo(1);
}
+ @Test
+ public void testQueryWithNonVisibleCurrentPatchSet() throws Exception {
+ String changeId = createChange().getChangeId();
+ amendChangeAsDraft(changeId);
+ String query = "--current-patch-set --patch-sets " + changeId;
+ List<ChangeAttribute> changes = executeSuccessfulQuery(query);
+ assertThat(changes.size()).isEqualTo(1);
+ assertThat(changes.get(0).patchSets).isNotNull();
+ assertThat(changes.get(0).patchSets).hasSize(2);
+ assertThat(changes.get(0).currentPatchSet).isNotNull();
+
+ SshSession userSession = new SshSession(server, user);
+ initSsh(user);
+ userSession.open();
+ changes = executeSuccessfulQuery(query, userSession);
+ assertThat(changes.size()).isEqualTo(1);
+ assertThat(changes.get(0).patchSets).hasSize(1);
+ assertThat(changes.get(0).currentPatchSet).isNull();
+ userSession.close();
+ }
+
+ private List<ChangeAttribute> executeSuccessfulQuery(String params,
+ SshSession session) throws Exception {
+ String rawResponse =
+ session.exec("gerrit query --format=JSON " + params);
+ assert_().withFailureMessage(session.getError())
+ .that(session.hasError()).isFalse();
+ return getChanges(rawResponse);
+ }
+
private List<ChangeAttribute> executeSuccessfulQuery(String params)
throws Exception {
- String rawResponse =
- adminSshSession.exec("gerrit query --format=JSON " + params);
- assert_().withFailureMessage(adminSshSession.getError())
- .that(adminSshSession.hasError()).isFalse();
- return getChanges(rawResponse);
+ return executeSuccessfulQuery(params, adminSshSession);
}
private static List<ChangeAttribute> getChanges(String rawResponse) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java
index b499530..e29048a 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java
@@ -46,6 +46,8 @@
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
@@ -139,6 +141,14 @@
}
},
KeyDownEvent.getType());
+ addDomHandler(
+ new KeyPressHandler() {
+ @Override
+ public void onKeyPress(KeyPressEvent e) {
+ e.stopPropagation();
+ }
+ },
+ KeyPressEvent.getType());
}
@Override
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PatchSetSelectBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PatchSetSelectBox.java
index d2b740e..39b85cf 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PatchSetSelectBox.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PatchSetSelectBox.java
@@ -42,6 +42,7 @@
import com.google.gwt.user.client.ui.ImageResourceRenderer;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtorm.client.KeyUtil;
+
import net.codemirror.lib.CodeMirror;
import java.util.List;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/ProjectApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/ProjectApiImpl.java
index 0e2f811..b8bd905 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/ProjectApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/projects/ProjectApiImpl.java
@@ -16,10 +16,10 @@
import static com.google.gerrit.server.account.CapabilityUtils.checkRequiresCapability;
+import com.google.gerrit.extensions.api.access.ProjectAccessInfo;
import com.google.gerrit.extensions.api.projects.BranchApi;
import com.google.gerrit.extensions.api.projects.BranchInfo;
import com.google.gerrit.extensions.api.projects.ChildProjectApi;
-import com.google.gerrit.extensions.api.access.ProjectAccessInfo;
import com.google.gerrit.extensions.api.projects.ProjectApi;
import com.google.gerrit.extensions.api.projects.ProjectInput;
import com.google.gerrit.extensions.api.projects.PutDescriptionInput;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
index efa6174..7984c76b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
@@ -1503,8 +1503,8 @@
private void selectNewAndReplacedChangesFromMagicBranch() {
newChanges = Lists.newArrayList();
- SetMultimap<ObjectId, Ref> existing = changeRefsById();
- GroupCollector groupCollector = GroupCollector.create(refsById, db, psUtil,
+ SetMultimap<ObjectId, Ref> existing = HashMultimap.create();
+ GroupCollector groupCollector = GroupCollector.create(changeRefsById(), db, psUtil,
notesFactory, project.getNameKey());
rp.getRevWalk().reset();
@@ -1525,6 +1525,7 @@
} else {
markHeadsAsUninteresting(
rp.getRevWalk(),
+ existing,
magicBranch.ctl != null ? magicBranch.ctl.getRefName() : null);
}
@@ -1681,15 +1682,23 @@
}
}
- private void markHeadsAsUninteresting(RevWalk rw, @Nullable String forRef) {
+ private void markHeadsAsUninteresting(
+ final RevWalk walk,
+ SetMultimap<ObjectId, Ref> existing,
+ @Nullable String forRef) {
for (Ref ref : allRefs.values()) {
- if ((ref.getName().startsWith(R_HEADS) || ref.getName().equals(forRef))
- && ref.getObjectId() != null) {
+ if (ref.getObjectId() == null) {
+ continue;
+ } else if (ref.getName().startsWith(REFS_CHANGES)) {
+ existing.put(ref.getObjectId(), ref);
+ } else if (ref.getName().startsWith(R_HEADS)
+ || (forRef != null && forRef.equals(ref.getName()))) {
try {
- rw.markUninteresting(rw.parseCommit(ref.getObjectId()));
+ walk.markUninteresting(walk.parseCommit(ref.getObjectId()));
} catch (IOException e) {
log.warn(String.format("Invalid ref %s in %s",
ref.getName(), project.getName()), e);
+ continue;
}
}
}
@@ -2332,11 +2341,11 @@
if (!(parsedObject instanceof RevCommit)) {
return;
}
+ SetMultimap<ObjectId, Ref> existing = HashMultimap.create();
walk.markStart((RevCommit)parsedObject);
- markHeadsAsUninteresting(walk, cmd.getRefName());
- Set<ObjectId> existing = changeRefsById().keySet();
+ markHeadsAsUninteresting(walk, existing, cmd.getRefName());
for (RevCommit c; (c = walk.next()) != null;) {
- if (existing.contains(c)) {
+ if (existing.keySet().contains(c)) {
continue;
} else if (!validCommit(walk, ctl, cmd, c)) {
break;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/strategy/SubmitStrategyFactory.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/strategy/SubmitStrategyFactory.java
index ce34a53..1e3fdbe 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/strategy/SubmitStrategyFactory.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/strategy/SubmitStrategyFactory.java
@@ -14,8 +14,8 @@
package com.google.gerrit.server.git.strategy;
-import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.api.changes.ReviewInput.NotifyHandling;
+import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.IdentifiedUser;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
index efd0a4e..55b8556 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
@@ -26,6 +26,7 @@
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.notedb.ChangeNotesCommit.ChangeNotesRevWalk;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -35,7 +36,6 @@
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevWalk;
import java.io.IOException;
@@ -76,7 +76,7 @@
@AutoValue
public abstract static class LoadHandle implements AutoCloseable {
- public static LoadHandle create(RevWalk walk, ObjectId id) {
+ public static LoadHandle create(ChangeNotesRevWalk walk, ObjectId id) {
return new AutoValue_AbstractChangeNotes_LoadHandle(
checkNotNull(walk), id != null ? id.copy() : null);
}
@@ -85,7 +85,7 @@
return new AutoValue_AbstractChangeNotes_LoadHandle(null, null);
}
- @Nullable public abstract RevWalk walk();
+ @Nullable public abstract ChangeNotesRevWalk walk();
@Nullable public abstract ObjectId id();
@Override
@@ -145,7 +145,7 @@
}
protected LoadHandle openHandle(Repository repo) throws IOException {
- return LoadHandle.create(new RevWalk(repo), readRef(repo));
+ return LoadHandle.create(ChangeNotesCommit.newRevWalk(repo), readRef(repo));
}
public T reload() throws OrmException {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotes.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotes.java
index 24256bf..b685485 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotes.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotes.java
@@ -69,7 +69,6 @@
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevWalk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -642,7 +641,8 @@
return super.openHandle(repo); // May be null in tests.
}
repo.scanForRepoChanges();
- return LoadHandle.create(new RevWalk(repo), newState.getChangeMetaId());
+ return LoadHandle.create(
+ ChangeNotesCommit.newRevWalk(repo), newState.getChangeMetaId());
} catch (NoSuchChangeException e) {
return super.openHandle(repo);
} catch (OrmException | ConfigInvalidException e) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotesCommit.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotesCommit.java
new file mode 100644
index 0000000..5d28454
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotesCommit.java
@@ -0,0 +1,106 @@
+// Copyright (C) 2016 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.server.notedb;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.FooterKey;
+import org.eclipse.jgit.revwalk.FooterLine;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Commit implementation with some optimizations for change notes parsing.
+ * <p>
+ * <ul>
+ * <li>Caches the result of {@link #getFooterLines()}, which is
+ * otherwise very wasteful with allocations.</li>
+ * </ul>
+ */
+public class ChangeNotesCommit extends RevCommit {
+ public static ChangeNotesRevWalk newRevWalk(Repository repo) {
+ return new ChangeNotesRevWalk(repo);
+ }
+
+ public static class ChangeNotesRevWalk extends RevWalk {
+ private ChangeNotesRevWalk(Repository repo) {
+ super(repo);
+ }
+
+ @Override
+ protected ChangeNotesCommit createCommit(AnyObjectId id) {
+ return new ChangeNotesCommit(id);
+ }
+
+ @Override
+ public ChangeNotesCommit next() throws MissingObjectException,
+ IncorrectObjectTypeException, IOException {
+ return (ChangeNotesCommit) super.next();
+ }
+
+ @Override
+ public void markStart(RevCommit c) throws MissingObjectException,
+ IncorrectObjectTypeException, IOException {
+ checkArgument(c instanceof ChangeNotesCommit);
+ super.markStart(c);
+ }
+
+ @Override
+ public void markUninteresting(RevCommit c) throws MissingObjectException,
+ IncorrectObjectTypeException, IOException {
+ checkArgument(c instanceof ChangeNotesCommit);
+ super.markUninteresting(c);
+ }
+
+ @Override
+ public ChangeNotesCommit lookupCommit(AnyObjectId id) {
+ return (ChangeNotesCommit) super.lookupCommit(id);
+ }
+
+ @Override
+ public ChangeNotesCommit parseCommit(AnyObjectId id)
+ throws MissingObjectException, IncorrectObjectTypeException,
+ IOException {
+ return (ChangeNotesCommit) super.parseCommit(id);
+ }
+ }
+
+ private ListMultimap<String, String> footerLines;
+
+ public ChangeNotesCommit(AnyObjectId id) {
+ super(id);
+ }
+
+ public List<String> getFooterLineValues(FooterKey key) {
+ if (footerLines == null) {
+ List<FooterLine> src = getFooterLines();
+ footerLines = ArrayListMultimap.create(src.size(), 1);
+ for (FooterLine fl : src) {
+ footerLines.put(fl.getKey().toLowerCase(), fl.getValue());
+ }
+ }
+ return footerLines.get(key.getName().toLowerCase());
+ }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotesParser.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
index 69209b9..604c866 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
@@ -62,6 +62,7 @@
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.server.ReviewDbUtil;
import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.notedb.ChangeNotesCommit.ChangeNotesRevWalk;
import com.google.gerrit.server.util.LabelVote;
import org.eclipse.jgit.errors.ConfigInvalidException;
@@ -73,8 +74,6 @@
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.FooterKey;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.RawParseUtils;
import java.io.IOException;
@@ -123,7 +122,7 @@
private final NoteDbMetrics metrics;
private final Change.Id id;
private final ObjectId tip;
- private final RevWalk walk;
+ private final ChangeNotesRevWalk walk;
private final Repository repo;
private final Map<PatchSet.Id,
Table<Account.Id, Entry<String, String>, Optional<PatchSetApproval>>> approvals;
@@ -131,7 +130,7 @@
private final Multimap<PatchSet.Id, ChangeMessage> changeMessagesByPatchSet;
ChangeNotesParser(Project.NameKey project, Change.Id changeId, ObjectId tip,
- RevWalk walk, GitRepositoryManager repoManager,
+ ChangeNotesRevWalk walk, GitRepositoryManager repoManager,
ChangeNoteUtil noteUtil, NoteDbMetrics metrics)
throws RepositoryNotFoundException, IOException {
this.id = changeId;
@@ -163,7 +162,8 @@
walk.markStart(walk.parseCommit(tip));
try (Timer1.Context timer = metrics.parseLatency.start(CHANGES)) {
- for (RevCommit commit : walk) {
+ ChangeNotesCommit commit;
+ while ((commit = walk.next()) != null) {
parse(commit);
}
parseNotes();
@@ -203,7 +203,7 @@
return ImmutableListMultimap.copyOf(changeMessagesByPatchSet);
}
- private void parse(RevCommit commit) throws ConfigInvalidException {
+ private void parse(ChangeNotesCommit commit) throws ConfigInvalidException {
Timestamp ts =
new Timestamp(commit.getCommitterIdent().getWhen().getTime());
@@ -275,17 +275,17 @@
if (submitRecords.isEmpty()) {
// Only parse the most recent set of submit records; any older ones are
// still there, but not currently used.
- parseSubmitRecords(commit.getFooterLines(FOOTER_SUBMITTED_WITH));
+ parseSubmitRecords(commit.getFooterLineValues(FOOTER_SUBMITTED_WITH));
updateTs |= !submitRecords.isEmpty();
}
- for (String line : commit.getFooterLines(FOOTER_LABEL)) {
+ for (String line : commit.getFooterLineValues(FOOTER_LABEL)) {
parseApproval(psId, accountId, ts, line);
updateTs = true;
}
for (ReviewerStateInternal state : ReviewerStateInternal.values()) {
- for (String line : commit.getFooterLines(state.getFooterKey())) {
+ for (String line : commit.getFooterLineValues(state.getFooterKey())) {
parseReviewer(state, line);
}
// Don't update timestamp when a reviewer was added, matching RevewDb
@@ -299,31 +299,35 @@
}
}
- private String parseSubmissionId(RevCommit commit)
+ private String parseSubmissionId(ChangeNotesCommit commit)
throws ConfigInvalidException {
return parseOneFooter(commit, FOOTER_SUBMISSION_ID);
}
- private String parseBranch(RevCommit commit) throws ConfigInvalidException {
+ private String parseBranch(ChangeNotesCommit commit)
+ throws ConfigInvalidException {
String branch = parseOneFooter(commit, FOOTER_BRANCH);
return branch != null ? RefNames.fullName(branch) : null;
}
- private String parseChangeId(RevCommit commit) throws ConfigInvalidException {
+ private String parseChangeId(ChangeNotesCommit commit)
+ throws ConfigInvalidException {
return parseOneFooter(commit, FOOTER_CHANGE_ID);
}
- private String parseSubject(RevCommit commit) throws ConfigInvalidException {
+ private String parseSubject(ChangeNotesCommit commit)
+ throws ConfigInvalidException {
return parseOneFooter(commit, FOOTER_SUBJECT);
}
- private String parseTopic(RevCommit commit) throws ConfigInvalidException {
+ private String parseTopic(ChangeNotesCommit commit)
+ throws ConfigInvalidException {
return parseOneFooter(commit, FOOTER_TOPIC);
}
- private String parseOneFooter(RevCommit commit, FooterKey footerKey)
+ private String parseOneFooter(ChangeNotesCommit commit, FooterKey footerKey)
throws ConfigInvalidException {
- List<String> footerLines = commit.getFooterLines(footerKey);
+ List<String> footerLines = commit.getFooterLineValues(footerKey);
if (footerLines.isEmpty()) {
return null;
} else if (footerLines.size() > 1) {
@@ -332,8 +336,8 @@
return footerLines.get(0);
}
- private String parseExactlyOneFooter(RevCommit commit, FooterKey footerKey)
- throws ConfigInvalidException {
+ private String parseExactlyOneFooter(ChangeNotesCommit commit,
+ FooterKey footerKey) throws ConfigInvalidException {
String line = parseOneFooter(commit, footerKey);
if (line == null) {
throw expectedOneFooter(footerKey, Collections.<String> emptyList());
@@ -341,7 +345,7 @@
return line;
}
- private ObjectId parseRevision(RevCommit commit)
+ private ObjectId parseRevision(ChangeNotesCommit commit)
throws ConfigInvalidException {
String sha = parseOneFooter(commit, FOOTER_COMMIT);
if (sha == null) {
@@ -377,7 +381,7 @@
ps.setCreatedOn(ts);
}
- private void parseGroups(PatchSet.Id psId, RevCommit commit)
+ private void parseGroups(PatchSet.Id psId, ChangeNotesCommit commit)
throws ConfigInvalidException {
String groupsStr = parseOneFooter(commit, FOOTER_GROUPS);
if (groupsStr == null) {
@@ -394,12 +398,14 @@
ps.setGroups(PatchSet.splitGroups(groupsStr));
}
- private void parseHashtags(RevCommit commit) throws ConfigInvalidException {
- // Commits are parsed in reverse order and only the last set of hashtags should be used.
+ private void parseHashtags(ChangeNotesCommit commit)
+ throws ConfigInvalidException {
+ // Commits are parsed in reverse order and only the last set of hashtags
+ // should be used.
if (hashtags != null) {
return;
}
- List<String> hashtagsLines = commit.getFooterLines(FOOTER_HASHTAGS);
+ List<String> hashtagsLines = commit.getFooterLineValues(FOOTER_HASHTAGS);
if (hashtagsLines.isEmpty()) {
return;
} else if (hashtagsLines.size() > 1) {
@@ -411,9 +417,10 @@
}
}
- private void parseTag(RevCommit commit) throws ConfigInvalidException {
+ private void parseTag(ChangeNotesCommit commit)
+ throws ConfigInvalidException {
tag = null;
- List<String> tagLines = commit.getFooterLines(FOOTER_TAG);
+ List<String> tagLines = commit.getFooterLineValues(FOOTER_TAG);
if (tagLines.isEmpty()) {
return;
} else if (tagLines.size() == 1) {
@@ -423,9 +430,9 @@
}
}
- private Change.Status parseStatus(RevCommit commit)
+ private Change.Status parseStatus(ChangeNotesCommit commit)
throws ConfigInvalidException {
- List<String> statusLines = commit.getFooterLines(FOOTER_STATUS);
+ List<String> statusLines = commit.getFooterLineValues(FOOTER_STATUS);
if (statusLines.isEmpty()) {
return null;
} else if (statusLines.size() > 1) {
@@ -439,7 +446,7 @@
return status.get();
}
- private PatchSet.Id parsePatchSetId(RevCommit commit)
+ private PatchSet.Id parsePatchSetId(ChangeNotesCommit commit)
throws ConfigInvalidException {
String psIdLine = parseExactlyOneFooter(commit, FOOTER_PATCH_SET);
int s = psIdLine.indexOf(' ');
@@ -451,7 +458,7 @@
return new PatchSet.Id(id, psId);
}
- private PatchSetState parsePatchSetState(RevCommit commit)
+ private PatchSetState parsePatchSetState(ChangeNotesCommit commit)
throws ConfigInvalidException {
String psIdLine = parseExactlyOneFooter(commit, FOOTER_PATCH_SET);
int s = psIdLine.indexOf(' ');
@@ -470,7 +477,7 @@
}
private ChangeMessage parseChangeMessage(PatchSet.Id psId,
- Account.Id accountId, RevCommit commit, Timestamp ts) {
+ Account.Id accountId, ChangeNotesCommit commit, Timestamp ts) {
byte[] raw = commit.getRawBuffer();
int size = raw.length;
Charset enc = RawParseUtils.parseEncoding(raw);
@@ -532,7 +539,7 @@
private void parseNotes()
throws IOException, ConfigInvalidException {
ObjectReader reader = walk.getObjectReader();
- RevCommit tipCommit = walk.parseCommit(tip);
+ ChangeNotesCommit tipCommit = walk.parseCommit(tip);
revisionNoteMap = RevisionNoteMap.parse(
noteUtil, id, reader, NoteMap.read(reader, tipCommit), false);
Map<RevId, RevisionNote> rns = revisionNoteMap.revisionNotes;
@@ -705,7 +712,7 @@
}
}
- private Account.Id parseIdent(RevCommit commit)
+ private Account.Id parseIdent(ChangeNotesCommit commit)
throws ConfigInvalidException {
// Check if the author name/email is the same as the committer name/email,
// i.e. was the server ident at the time this commit was made.
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/DraftCommentNotes.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/DraftCommentNotes.java
index ba824a0..43f58a5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/DraftCommentNotes.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/DraftCommentNotes.java
@@ -35,7 +35,6 @@
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevWalk;
import java.io.IOException;
@@ -169,7 +168,7 @@
}
ObjectId draftsId = newState.getDraftIds().get(author);
repo.scanForRepoChanges();
- return LoadHandle.create(new RevWalk(repo), draftsId);
+ return LoadHandle.create(ChangeNotesCommit.newRevWalk(repo), draftsId);
} catch (NoSuchChangeException e) {
return super.openHandle(repo);
} catch (OrmException | ConfigInvalidException e) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
index a4c10ee..76dd030 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -21,6 +21,8 @@
import com.google.auto.value.AutoValue;
import com.google.common.base.MoreObjects;
import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
@@ -833,13 +835,29 @@
return patchSets;
}
- public void setPatchSets(List<PatchSet> patchSets) {
+ /**
+ * @return patches for the change visible to the current user.
+ * @throws OrmException an error occurred reading the database.
+ */
+ public Collection<PatchSet> visiblePatchSets() throws OrmException {
+ return FluentIterable.from(patchSets()).filter(new Predicate<PatchSet>() {
+ @Override
+ public boolean apply(PatchSet input) {
+ try {
+ return changeControl().isPatchVisible(input, db);
+ } catch (OrmException e) {
+ return false;
+ }
+ }}).toList();
+ }
+
+public void setPatchSets(Collection<PatchSet> patchSets) {
this.currentPatchSet = null;
this.patchSets = patchSets;
}
/**
- * @return patch set with the given ID, or null if it does not exist.
+ * @return patch with the given ID, or null if it does not exist.
* @throws OrmException an error occurred reading the database.
*/
public PatchSet patchSet(PatchSet.Id psId) throws OrmException {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/LabelPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/LabelPredicate.java
index 83364c3..2e2454d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/LabelPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/LabelPredicate.java
@@ -141,10 +141,10 @@
List<Predicate<ChangeData>> r =
Lists.newArrayListWithCapacity(2 * MAX_LABEL_VALUE);
for (int i = 1; i <= MAX_LABEL_VALUE; i++) {
- r.add(not(equalsLabelPredicate(args, label, i)));
- r.add(not(equalsLabelPredicate(args, label, -i)));
+ r.add(equalsLabelPredicate(args, label, i));
+ r.add(equalsLabelPredicate(args, label, -i));
}
- return and(r);
+ return not(or(r));
}
private static Predicate<ChangeData> equalsLabelPredicate(Args args,
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OutputStreamQuery.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
index 8f1e48f..00ecdb2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
@@ -275,14 +275,14 @@
}
if (includePatchSets) {
- eventFactory.addPatchSets(db, rw, c, d.patchSets(),
+ eventFactory.addPatchSets(db, rw, c, d.visiblePatchSets(),
includeApprovals ? d.approvals().asMap() : null,
includeFiles, d.change(), labelTypes);
}
if (includeCurrentPatchSet) {
PatchSet current = d.currentPatchSet();
- if (current != null) {
+ if (current != null && cc.isPatchVisible(current, d.db())) {
c.currentPatchSet =
eventFactory.asPatchSetAttribute(db, rw, d.change(), current);
eventFactory.addApprovals(c.currentPatchSet,
@@ -302,7 +302,7 @@
if (includeComments) {
eventFactory.addComments(c, d.messages());
if (includePatchSets) {
- eventFactory.addPatchSets(db, rw, c, d.patchSets(),
+ eventFactory.addPatchSets(db, rw, c, d.visiblePatchSets(),
includeApprovals ? d.approvals().asMap() : null,
includeFiles, d.change(), labelTypes);
for (PatchSetAttribute attribute : c.patchSets) {
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesParserTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesParserTest.java
index dc00eaa..d4d7d19 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesParserTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesParserTest.java
@@ -18,6 +18,7 @@
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.server.notedb.ChangeNotesCommit.ChangeNotesRevWalk;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
@@ -27,19 +28,18 @@
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class ChangeNotesParserTest extends AbstractChangeNotesTest {
private TestRepository<InMemoryRepository> testRepo;
- private RevWalk walk;
+ private ChangeNotesRevWalk walk;
@Before
public void setUpTestRepo() throws Exception {
testRepo = new TestRepository<>(repo);
- walk = new RevWalk(repo);
+ walk = ChangeNotesCommit.newRevWalk(repo);
}
@After
@@ -53,16 +53,16 @@
+ "\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Subject: This is a test change\n");
assertParseFails(writeCommit("Update change\n"
+ "\n"
- + "Patch-Set: 1\n",
+ + "Patch-set: 1\n",
new PersonIdent("Change Owner", "owner@example.com",
serverIdent.getWhen(), serverIdent.getTimeZone())));
assertParseFails(writeCommit("Update change\n"
+ "\n"
- + "Patch-Set: 1\n",
+ + "Patch-set: 1\n",
new PersonIdent("Change Owner", "x@gerrit",
serverIdent.getWhen(), serverIdent.getTimeZone())));
}
@@ -73,23 +73,23 @@
+ "\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Status: NEW\n"
+ "Subject: This is a test change\n");
assertParseSucceeds("Update change\n"
+ "\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Status: new\n"
+ "Subject: This is a test change\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Status: OOPS\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Status: NEW\n"
+ "Status: NEW\n");
}
@@ -100,23 +100,23 @@
+ "\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Subject: This is a test change\n");
assertParseFails("Update change\n"
+ "\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
- + "Patch-Set: 1\n");
+ + "Patch-set: 1\n"
+ + "Patch-set: 1\n");
assertParseSucceeds("Update change\n"
+ "\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Subject: This is a test change\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: x\n");
+ + "Patch-set: x\n");
}
@Test
@@ -125,7 +125,7 @@
+ "\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Label: Label1=+1\n"
+ "Label: Label2=1\n"
+ "Label: Label3=0\n"
@@ -135,33 +135,33 @@
+ "\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Label: -Label1\n"
+ "Label: -Label1 Other Account <2@gerrit>\n"
+ "Subject: This is a test change\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Label: Label1=X\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Label: Label1 = 1\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Label: X+Y\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Label: Label1 Other Account <2@gerrit>\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Label: -Label!1\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Label: -Label!1 Other Account <2@gerrit>\n");
}
@@ -171,7 +171,7 @@
+ "\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Subject: This is a test change\n"
+ "Submitted-with: NOT_READY\n"
+ "Submitted-with: OK: Verified: Change Owner <1@gerrit>\n"
@@ -181,19 +181,19 @@
+ "Submitted-with: NEED: Alternative-Code-Review\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Submitted-with: OOPS\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Submitted-with: NEED: X+Y\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Submitted-with: OK: X+Y: Change Owner <1@gerrit>\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Submitted-with: OK: Code-Review: 1@gerrit\n");
}
@@ -203,12 +203,12 @@
+ "\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Subject: This is a test change\n"
+ "Submission-id: 1-1453387607626-96fabc25");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Submission-id: 1-1453387607626-96fabc25\n"
+ "Submission-id: 1-1453387901516-5d1e2450");
}
@@ -219,13 +219,13 @@
+ "\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Reviewer: Change Owner <1@gerrit>\n"
+ "CC: Other Account <2@gerrit>\n"
+ "Subject: This is a test change\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Reviewer: 1@gerrit\n");
}
@@ -235,19 +235,19 @@
+ "\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Topic: Some Topic\n"
+ "Subject: This is a test change\n");
assertParseSucceeds("Update change\n"
+ "\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Topic:\n"
+ "Subject: This is a test change\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Topic: Some Topic\n"
+ "Topic: Other Topic");
}
@@ -258,17 +258,17 @@
+ "\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Subject: This is a test change\n");
assertParseSucceeds("Update change\n"
+ "\n"
+ "Branch: master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Subject: This is a test change\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Branch: refs/heads/master\n"
+ "Branch: refs/heads/stable");
}
@@ -279,11 +279,11 @@
+ "\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Subject: This is a test change\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
+ "Change-id: I159532ef4844d7c18f7f3fd37a0b275590d41b1b");
}
@@ -292,13 +292,13 @@
public void parseSubject() throws Exception {
assertParseSucceeds("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
+ "Subject: Some subject of a change\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Subject: Some subject of a change\n"
+ "Subject: Some other subject\n");
}
@@ -418,21 +418,21 @@
public void parseTag() throws Exception {
assertParseSucceeds("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
+ "Subject: Change subject\n"
+ "Tag:\n");
assertParseSucceeds("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
+ "Subject: Change subject\n"
+ "Tag: jenkins\n");
assertParseFails("Update change\n"
+ "\n"
- + "Patch-Set: 1\n"
+ + "Patch-set: 1\n"
+ "Branch: refs/heads/master\n"
+ "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
+ "Subject: Change subject\n"
@@ -440,6 +440,16 @@
+ "Tag: jenkins\n");
}
+ @Test
+ public void caseInsensitiveFooters() throws Exception {
+ assertParseSucceeds("Update change\n"
+ + "\n"
+ + "BRaNch: refs/heads/master\n"
+ + "Change-ID: I577fb248e474018276351785930358ec0450e9f7\n"
+ + "patcH-set: 1\n"
+ + "subject: This is a test change\n");
+ }
+
private RevCommit writeCommit(String body) throws Exception {
return writeCommit(body, noteUtil.newIdent(
changeOwner.getAccount(), TimeUtil.nowTs(), serverIdent,
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesTest.java
index 44fa6f5..4d80866 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesTest.java
@@ -46,6 +46,7 @@
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.server.notedb.ChangeNotesCommit.ChangeNotesRevWalk;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -1020,7 +1021,7 @@
RevCommit commitWithComments = commitWithApprovals.getParent(0);
assertThat(commitWithComments).isNotNull();
- try (RevWalk rw = new RevWalk(repo)) {
+ try (ChangeNotesRevWalk rw = ChangeNotesCommit.newRevWalk(repo)) {
try (ChangeNotesParser notesWithComments = new ChangeNotesParser(
project, c.getId(), commitWithComments.copy(), rw, repoManager,
noteUtil, args.metrics)) {
@@ -1032,7 +1033,7 @@
}
}
- try (RevWalk rw = new RevWalk(repo)) {
+ try (ChangeNotesRevWalk rw = ChangeNotesCommit.newRevWalk(repo)) {
try (ChangeNotesParser notesWithApprovals = new ChangeNotesParser(project,
c.getId(), commitWithApprovals.copy(), rw, repoManager,
noteUtil, args.metrics)) {
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index 6e2f9c9..97776f1 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -95,6 +95,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@@ -536,47 +537,97 @@
public void byLabel() throws Exception {
accountManager.authenticate(AuthRequest.forUser("anotheruser"));
TestRepository<Repo> repo = createProject("repo");
- ChangeInserter ins = newChange(repo);
- Change change = insert(repo, ins);
+ ChangeInserter ins = newChange(repo, null, null, null, null);
+ ChangeInserter ins2 = newChange(repo, null, null, null, null);
+ ChangeInserter ins3 = newChange(repo, null, null, null, null);
+ ChangeInserter ins4 = newChange(repo, null, null, null, null);
+ ChangeInserter ins5 = newChange(repo, null, null, null, null);
- gApi.changes().id(change.getId().get()).current()
- .review(new ReviewInput().label("Code-Review", 1));
+ Change reviewMinus2Change = insert(repo, ins);
+ gApi.changes().id(reviewMinus2Change.getId().get()).current()
+ .review(ReviewInput.reject());
+
+ Change reviewMinus1Change = insert(repo, ins2);
+ gApi.changes().id(reviewMinus1Change.getId().get()).current()
+ .review(ReviewInput.dislike());
+
+ Change noLabelChange = insert(repo, ins3);
+
+ Change reviewPlus1Change = insert(repo, ins4);
+ gApi.changes().id(reviewPlus1Change.getId().get()).current()
+ .review(ReviewInput.recommend());
+
+ Change reviewPlus2Change = insert(repo, ins5);
+ gApi.changes().id(reviewPlus2Change.getId().get()).current()
+ .review(ReviewInput.approve());
+
Map<String, Short> m = gApi.changes()
- .id(change.getId().get())
+ .id(reviewPlus1Change.getId().get())
.reviewer(user.getAccountId().toString())
.votes();
assertThat(m).hasSize(1);
assertThat(m).containsEntry("Code-Review", new Short((short)1));
- assertQuery("label:Code-Review=-2");
- assertQuery("label:Code-Review-2");
- assertQuery("label:Code-Review=-1");
- assertQuery("label:Code-Review-1");
- assertQuery("label:Code-Review=0");
- assertQuery("label:Code-Review=+1", change);
- assertQuery("label:Code-Review=1", change);
- assertQuery("label:Code-Review+1", change);
- assertQuery("label:Code-Review=+2");
- assertQuery("label:Code-Review=2");
- assertQuery("label:Code-Review+2");
+ Map<Integer, Change> changes = new LinkedHashMap<>(5);
+ changes.put(2, reviewPlus2Change);
+ changes.put(1, reviewPlus1Change);
+ changes.put(0, noLabelChange);
+ changes.put(-1, reviewMinus1Change);
+ changes.put(-2, reviewMinus2Change);
- assertQuery("label:Code-Review>=0", change);
- assertQuery("label:Code-Review>0", change);
- assertQuery("label:Code-Review>=1", change);
- assertQuery("label:Code-Review>1");
- assertQuery("label:Code-Review>=2");
+ assertQuery("label:Code-Review=-2", reviewMinus2Change);
+ assertQuery("label:Code-Review-2", reviewMinus2Change);
+ assertQuery("label:Code-Review=-1", reviewMinus1Change);
+ assertQuery("label:Code-Review-1", reviewMinus1Change);
+ assertQuery("label:Code-Review=0", noLabelChange);
+ assertQuery("label:Code-Review=+1", reviewPlus1Change);
+ assertQuery("label:Code-Review=1", reviewPlus1Change);
+ assertQuery("label:Code-Review+1", reviewPlus1Change);
+ assertQuery("label:Code-Review=+2", reviewPlus2Change);
+ assertQuery("label:Code-Review=2", reviewPlus2Change);
+ assertQuery("label:Code-Review+2", reviewPlus2Change);
- assertQuery("label: Code-Review<=2", change);
- assertQuery("label: Code-Review<2", change);
- assertQuery("label: Code-Review<=1", change);
- assertQuery("label:Code-Review<1");
- assertQuery("label:Code-Review<=0");
+ assertQuery("label:Code-Review>-3", codeReviewInRange(changes, -2, 2));
+ assertQuery("label:Code-Review>=-2", codeReviewInRange(changes, -2, 2));
+ assertQuery("label:Code-Review>-2", codeReviewInRange(changes, -1, 2));
+ assertQuery("label:Code-Review>=-1", codeReviewInRange(changes, -1, 2));
+ assertQuery("label:Code-Review>-1", codeReviewInRange(changes, 0, 2));
+ assertQuery("label:Code-Review>=0", codeReviewInRange(changes, 0, 2));
+ assertQuery("label:Code-Review>0", codeReviewInRange(changes, 1, 2));
+ assertQuery("label:Code-Review>=1", codeReviewInRange(changes, 1, 2));
+ assertQuery("label:Code-Review>1", reviewPlus2Change);
+ assertQuery("label:Code-Review>=2", reviewPlus2Change);
+ assertQuery("label:Code-Review>2");
+
+ assertQuery("label:Code-Review<=2", codeReviewInRange(changes, -2, 2));
+ assertQuery("label:Code-Review<2", codeReviewInRange(changes, -2, 1));
+ assertQuery("label:Code-Review<=1", codeReviewInRange(changes, -2, 1));
+ assertQuery("label:Code-Review<1", codeReviewInRange(changes, -2, 0));
+ assertQuery("label:Code-Review<=0", codeReviewInRange(changes, -2, 0));
+ assertQuery("label:Code-Review<0", codeReviewInRange(changes, -2, -1));
+ assertQuery("label:Code-Review<=-1", codeReviewInRange(changes, -2, -1));
+ assertQuery("label:Code-Review<-1", reviewMinus2Change);
+ assertQuery("label:Code-Review<=-2", reviewMinus2Change);
+ assertQuery("label:Code-Review<-2");
assertQuery("label:Code-Review=+1,anotheruser");
- assertQuery("label:Code-Review=+1,user", change);
- assertQuery("label:Code-Review=+1,user=user", change);
- assertQuery("label:Code-Review=+1,Administrators", change);
- assertQuery("label:Code-Review=+1,group=Administrators", change);
+ assertQuery("label:Code-Review=+1,user", reviewPlus1Change);
+ assertQuery("label:Code-Review=+1,user=user", reviewPlus1Change);
+ assertQuery("label:Code-Review=+1,Administrators", reviewPlus1Change);
+ assertQuery("label:Code-Review=+1,group=Administrators", reviewPlus1Change);
+ }
+
+ private Change[] codeReviewInRange(Map<Integer, Change> changes, int start,
+ int end) {
+ int size = 0;
+ Change[] range = new Change[end - start + 1];
+ for (int i : changes.keySet()) {
+ if (i >= start && i <= end) {
+ range[size] = changes.get(i);
+ size++;
+ }
+ }
+ return range;
}
private String createGroup(String name, String owner) throws Exception {
diff --git a/plugins/replication b/plugins/replication
index d5cd908..b80cd81 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit d5cd908c0d7938a5d253d49f68ed352bbc7449cf
+Subproject commit b80cd8168ae8ba065c0186b1ddfec366a6368cb6