Merge "WorkQueue: Skip `isReadyToStart` invocation for CANCELLED tasks" into stable-3.11
diff --git a/java/com/google/gerrit/extensions/api/changes/RevertInput.java b/java/com/google/gerrit/extensions/api/changes/RevertInput.java
index 613e48e..b16c75e 100644
--- a/java/com/google/gerrit/extensions/api/changes/RevertInput.java
+++ b/java/com/google/gerrit/extensions/api/changes/RevertInput.java
@@ -35,7 +35,11 @@
* Mark the change as work-in-progress. This will also override the {@link #notify} value to
* {@link NotifyHandling#OWNER}
*/
- public boolean workInProgress;
+ public Boolean workInProgress;
public Map<String, String> validationOptions;
+
+ public boolean getWorkInProgress() {
+ return workInProgress != null ? workInProgress : false;
+ }
}
diff --git a/java/com/google/gerrit/server/git/CommitUtil.java b/java/com/google/gerrit/server/git/CommitUtil.java
index 8a7840b..4a5e1b0 100644
--- a/java/com/google/gerrit/server/git/CommitUtil.java
+++ b/java/com/google/gerrit/server/git/CommitUtil.java
@@ -315,7 +315,7 @@
throws IOException, RestApiException, UpdateException, ConfigInvalidException {
RevCommit revertCommit = revWalk.parseCommit(revertCommitId);
Change.Id changeId = Change.id(seq.nextChangeId());
- if (input.workInProgress) {
+ if (input.getWorkInProgress()) {
input.notify = firstNonNull(input.notify, NotifyHandling.NONE);
}
NotifyResolver.Result notify =
@@ -340,13 +340,13 @@
ccs.remove(user.getAccountId());
ins.setReviewersAndCcsIgnoreVisibility(reviewers, ccs);
ins.setRevertOf(notes.getChangeId());
- ins.setWorkInProgress(input.workInProgress);
+ ins.setWorkInProgress(input.getWorkInProgress());
try (BatchUpdate bu = updateFactory.create(notes.getProjectName(), user, ts)) {
bu.setRepository(git, revWalk, oi);
bu.setNotify(notify);
bu.insertChange(ins);
- if (!input.workInProgress) {
+ if (!input.getWorkInProgress()) {
addChangeRevertedNotificationOps(
bu, changeToRevert.getId(), changeId, generatedChangeId.name());
}
diff --git a/java/com/google/gerrit/server/restapi/change/ApplyProvidedFix.java b/java/com/google/gerrit/server/restapi/change/ApplyProvidedFix.java
index 4e05420..be1bced 100644
--- a/java/com/google/gerrit/server/restapi/change/ApplyProvidedFix.java
+++ b/java/com/google/gerrit/server/restapi/change/ApplyProvidedFix.java
@@ -56,6 +56,7 @@
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.patch.PatchApplier;
+import org.eclipse.jgit.patch.PatchApplier.Result.Error;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
@@ -86,8 +87,13 @@
@Override
public Response<EditInfo> apply(
RevisionResource revisionResource, ApplyProvidedFixInput applyProvidedFixInput)
- throws AuthException, BadRequestException, ResourceConflictException, IOException,
- ResourceNotFoundException, PermissionBackendException, RestApiException {
+ throws AuthException,
+ BadRequestException,
+ ResourceConflictException,
+ IOException,
+ ResourceNotFoundException,
+ PermissionBackendException,
+ RestApiException {
if (applyProvidedFixInput == null) {
throw new BadRequestException("applyProvidedFixInput is required");
}
@@ -173,7 +179,8 @@
String targetCommitMessage = targetCommitMessageFile.modifiableContent();
if (!originCommitMessage.equals(targetCommitMessage)) {
throw new ResourceConflictException(
- "The fix attempts to modify commit message of an older patchset, but commit message has been updated in a newer patchset. The fix can't be applied.");
+ "The fix attempts to modify commit message of an older patchset, but commit message"
+ + " has been updated in a newer patchset. The fix can't be applied.");
}
resultBuilder.newCommitMessage(originCommitModification.newCommitMessage().get());
}
@@ -185,9 +192,20 @@
try (ObjectInserter oi = repository.newObjectInserter()) {
ApplyPatchInput inp = new ApplyPatchInput();
inp.patch = patch;
- inp.allowConflicts = false;
+ // Allow conflicts for showing more precise error message.
+ inp.allowConflicts = true;
result =
ApplyPatchUtil.applyPatch(repository, oi, inp, repository.parseCommit(targetCommit));
+ if (!result.getErrors().isEmpty()) {
+ String errorMessage =
+ (result.getErrors().stream().anyMatch(Error::isGitConflict)
+ ? "Merge conflict while applying a fix:\n"
+ : "Error while applying a fix:\n")
+ + result.getErrors().stream()
+ .map(Error::toString)
+ .collect(Collectors.joining("\n"));
+ throw new ResourceConflictException(errorMessage);
+ }
oi.flush();
for (String path : result.getPaths()) {
try (TreeWalk tw = TreeWalk.forPath(rw.getObjectReader(), path, result.getTreeId())) {
diff --git a/java/com/google/gerrit/server/restapi/change/Revert.java b/java/com/google/gerrit/server/restapi/change/Revert.java
index f9ac958..2add133 100644
--- a/java/com/google/gerrit/server/restapi/change/Revert.java
+++ b/java/com/google/gerrit/server/restapi/change/Revert.java
@@ -14,6 +14,7 @@
package com.google.gerrit.server.restapi.change;
+import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.gerrit.extensions.conditions.BooleanCondition.and;
import static com.google.gerrit.server.permissions.ChangePermission.REVERT;
import static com.google.gerrit.server.permissions.RefPermission.CREATE_CHANGE;
@@ -91,10 +92,9 @@
contributorAgreements.check(rsrc.getProject(), rsrc.getUser());
permissionBackend.user(rsrc.getUser()).ref(change.getDest()).check(CREATE_CHANGE);
- projectCache
- .get(rsrc.getProject())
- .orElseThrow(illegalState(rsrc.getProject()))
- .checkStatePermitsWrite();
+ ProjectState projectState =
+ projectCache.get(rsrc.getProject()).orElseThrow(illegalState(rsrc.getProject()));
+ projectState.checkStatePermitsWrite();
rsrc.permissions().check(REVERT);
ChangeNotes notes = rsrc.getNotes();
Change.Id changeIdToRevert = notes.getChangeId();
@@ -103,6 +103,18 @@
if (patch == null) {
throw new ResourceNotFoundException(changeIdToRevert.toString());
}
+
+ if (input.workInProgress == null) {
+ input.workInProgress =
+ firstNonNull(
+ rsrc.getUser()
+ .asIdentifiedUser()
+ .state()
+ .generalPreferences()
+ .workInProgressByDefault,
+ false);
+ }
+
return Response.ok(
json.noOptions()
.format(
diff --git a/java/com/google/gerrit/server/restapi/change/RevertSubmission.java b/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
index f04042c..9cd7908 100644
--- a/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
+++ b/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
@@ -169,8 +169,13 @@
@Override
public Response<RevertSubmissionInfo> apply(ChangeResource changeResource, RevertInput input)
- throws RestApiException, IOException, UpdateException, PermissionBackendException,
- NoSuchProjectException, ConfigInvalidException, StorageException {
+ throws RestApiException,
+ IOException,
+ UpdateException,
+ PermissionBackendException,
+ NoSuchProjectException,
+ ConfigInvalidException,
+ StorageException {
if (!changeResource.getChange().isMerged()) {
throw new ResourceConflictException(
@@ -232,8 +237,12 @@
private RevertSubmissionInfo revertSubmission(
List<ChangeData> changeData, RevertInput revertInput)
- throws RestApiException, IOException, UpdateException, ConfigInvalidException,
- StorageException, PermissionBackendException {
+ throws RestApiException,
+ IOException,
+ UpdateException,
+ ConfigInvalidException,
+ StorageException,
+ PermissionBackendException {
ListMultimap<BranchNameKey, ChangeData> changesPerProjectAndBranch = ArrayListMultimap.create();
changeData.stream().forEach(c -> changesPerProjectAndBranch.put(c.change().getDest(), c));
@@ -278,7 +287,10 @@
Iterator<PatchSetData> sortedChangesInProjectAndBranch,
Set<ObjectId> commitIdsInProjectAndBranch,
Instant timestamp)
- throws IOException, RestApiException, UpdateException, ConfigInvalidException,
+ throws IOException,
+ RestApiException,
+ UpdateException,
+ ConfigInvalidException,
PermissionBackendException {
while (sortedChangesInProjectAndBranch.hasNext()) {
ChangeNotes changeNotes = sortedChangesInProjectAndBranch.next().data().notes();
@@ -329,9 +341,9 @@
generatedChangeId,
cherryPickRevertChangeId,
timestamp,
- revertInput.workInProgress,
+ revertInput.getWorkInProgress(),
baseCommit));
- if (!revertInput.workInProgress) {
+ if (!revertInput.getWorkInProgress()) {
commitUtil.addChangeRevertedNotificationOps(
bu, changeNotes.getChangeId(), cherryPickRevertChangeId, generatedChangeId.name());
}
@@ -361,7 +373,7 @@
// change is created for the cherry-picked commit. Notifications are sent only for this change,
// but not for the intermediately created revert commit.
cherryPickInput.notify = revertInput.notify;
- if (revertInput.workInProgress) {
+ if (revertInput.getWorkInProgress()) {
cherryPickInput.notify = firstNonNull(cherryPickInput.notify, NotifyHandling.NONE);
}
cherryPickInput.notifyDetails = revertInput.notifyDetails;
diff --git a/javatests/com/google/gerrit/acceptance/api/change/RevertIT.java b/javatests/com/google/gerrit/acceptance/api/change/RevertIT.java
index 10dd5e3..1f3a6eb 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/RevertIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/RevertIT.java
@@ -40,6 +40,7 @@
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.api.changes.RevertInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
+import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gerrit.extensions.client.ProjectState;
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.common.AccountInfo;
@@ -203,6 +204,7 @@
String.format("Created a revert of this change as %s", revertChange.changeId);
assertThat(sourceMessages.get(3).message).isEqualTo(expectedMessage);
+ assertThat(revertChange.workInProgress).isNull();
assertThat(revertChange.messages).hasSize(1);
assertThat(revertChange.messages.iterator().next().message).isEqualTo("Uploaded patch set 1.");
assertThat(revertChange.revertOf).isEqualTo(gApi.changes().id(r.getChangeId()).get()._number);
@@ -235,6 +237,36 @@
}
@Test
+ public void revertChangeWithWipByUserPreference() throws Exception {
+ GeneralPreferencesInfo generalPreferencesInfo = new GeneralPreferencesInfo();
+ generalPreferencesInfo.workInProgressByDefault = true;
+ gApi.accounts().id(admin.id().get()).setPreferences(generalPreferencesInfo);
+ requestScopeOperations.resetCurrentApiUser();
+
+ PushOneCommit.Result r = createChange();
+ gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).review(ReviewInput.approve());
+ gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).submit();
+ ChangeInfo revertChange = gApi.changes().id(r.getChangeId()).revert().get();
+ assertThat(revertChange.workInProgress).isTrue();
+ }
+
+ @Test
+ public void revertChangeOverrideWipByUserPreference() throws Exception {
+ GeneralPreferencesInfo generalPreferencesInfo = new GeneralPreferencesInfo();
+ generalPreferencesInfo.workInProgressByDefault = true;
+ gApi.accounts().id(admin.id().get()).setPreferences(generalPreferencesInfo);
+ requestScopeOperations.resetCurrentApiUser();
+
+ PushOneCommit.Result r = createChange();
+ gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).review(ReviewInput.approve());
+ gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).submit();
+ RevertInput revertInput = new RevertInput();
+ revertInput.workInProgress = false;
+ ChangeInfo revertChange = gApi.changes().id(r.getChangeId()).revert(revertInput).get();
+ assertThat(revertChange.workInProgress).isNull();
+ }
+
+ @Test
public void revertWithDefaultTopic() throws Exception {
PushOneCommit.Result result = createChange();
gApi.changes().id(result.getChangeId()).current().review(ReviewInput.approve());
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/ApplyProvidedFixIT.java b/javatests/com/google/gerrit/acceptance/api/revision/ApplyProvidedFixIT.java
index d66a0a5..effd96f 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/ApplyProvidedFixIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/ApplyProvidedFixIT.java
@@ -378,8 +378,17 @@
.value()
.asString()
.isEqualTo(
- "New line at the start\nFirst line\nSecond line\nTModified contentrd line\nFourth line\nFifth line\n"
- + "Sixth line\nSeventh line\nEighth line\nNinth line\nTenth line\n");
+ "New line at the start\n"
+ + "First line\n"
+ + "Second line\n"
+ + "TModified contentrd line\n"
+ + "Fourth line\n"
+ + "Fifth line\n"
+ + "Sixth line\n"
+ + "Seventh line\n"
+ + "Eighth line\n"
+ + "Ninth line\n"
+ + "Tenth line\n");
applyProvidedFixInput = createApplyProvidedFixInput(FILE_NAME, "(1st)", 1, 5, 1, 5);
applyProvidedFixInput.originalPatchsetForFix = previousRevision;
@@ -390,8 +399,17 @@
.value()
.asString()
.isEqualTo(
- "New line at the start\nFirst(1st) line\nSecond line\nTModified contentrd line\nFourth line\nFifth line\n"
- + "Sixth line\nSeventh line\nEighth line\nNinth line\nTenth line\n");
+ "New line at the start\n"
+ + "First(1st) line\n"
+ + "Second line\n"
+ + "TModified contentrd line\n"
+ + "Fourth line\n"
+ + "Fifth line\n"
+ + "Sixth line\n"
+ + "Seventh line\n"
+ + "Eighth line\n"
+ + "Ninth line\n"
+ + "Tenth line\n");
}
@Test
@@ -440,8 +458,15 @@
.value()
.asString()
.isEqualTo(
- "Third line\nFourth line\nFifth line\n"
- + "Sixth line\nSeventh line\nEighth line\nNinth line\nFirst modification\nTenth line\n");
+ "Third line\n"
+ + "Fourth line\n"
+ + "Fifth line\n"
+ + "Sixth line\n"
+ + "Seventh line\n"
+ + "Eighth line\n"
+ + "Ninth line\n"
+ + "First modification\n"
+ + "Tenth line\n");
Optional<BinaryResult> file2 = gApi.changes().id(changeId).edit().getFile(FILE_NAME2);
BinaryResultSubject.assertThat(file2)
.value()
@@ -450,6 +475,44 @@
}
@Test
+ public void applyProvidedFixOnNewerPatchset_mergeConflictThrowsResourceConflictException()
+ throws Exception {
+ // Remember patch set and add another one.
+ int previousRevision = gApi.changes().id(changeId).get().currentRevisionNumber;
+ // Change first 2 lines;
+ String modifiedContent =
+ "abc\ndef\n"
+ + FILE_CONTENT.substring(
+ FILE_CONTENT.indexOf("\n", FILE_CONTENT.indexOf("\n") + 1) + 1);
+ amendChange(
+ changeId,
+ "refs/for/master",
+ admin,
+ testRepo,
+ PushOneCommit.SUBJECT,
+ FILE_NAME,
+ modifiedContent);
+ FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
+ fixReplacementInfo1.path = FILE_NAME;
+ fixReplacementInfo1.range = createRange(2, 0, 2, 0);
+ fixReplacementInfo1.replacement = "First modification\n";
+
+ ApplyProvidedFixInput applyProvidedFixInput = new ApplyProvidedFixInput();
+
+ applyProvidedFixInput.fixReplacementInfos = Arrays.asList(fixReplacementInfo1);
+ applyProvidedFixInput.originalPatchsetForFix = previousRevision;
+
+ ResourceConflictException thrown =
+ assertThrows(
+ ResourceConflictException.class,
+ () -> gApi.changes().id(changeId).current().applyFix(applyProvidedFixInput));
+
+ assertThat(thrown.getMessage()).contains("Merge conflict");
+ // Change edit must not be created
+ assertThat(gApi.changes().id(changeId).edit().get()).isEmpty();
+ }
+
+ @Test
public void applyProvidedFixOnCommitMessageCanBeAppliedToNewerPatchset() throws Exception {
// Set a dedicated commit message.
String footer = "\nChange-Id: " + changeId + "\n";
diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts
index ac2e7cc..beec0b5 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts
+++ b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts
@@ -110,6 +110,9 @@
.hide {
display: none;
}
+ #messageInput {
+ min-width: calc(72ch + 2px + 2 * var(--spacing-m) + 0.4px);
+ }
@media only screen and (max-width: 40em) {
.value {
width: 29em;
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
index f1ef362..72e8667 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -683,7 +683,7 @@
);
subscribe(
this,
- () => this.getChangeModel().latestRevision$,
+ () => this.getChangeModel().latestRevisionWithEdit$,
revision => {
this.latestCommitMessage = this.prepareCommitMsgForLinkify(
revision?.commit?.message ?? ''
diff --git a/polygerrit-ui/app/elements/shared/gr-suggestion-diff-preview/gr-suggestion-diff-preview.ts b/polygerrit-ui/app/elements/shared/gr-suggestion-diff-preview/gr-suggestion-diff-preview.ts
index 136979d..7c33764 100644
--- a/polygerrit-ui/app/elements/shared/gr-suggestion-diff-preview/gr-suggestion-diff-preview.ts
+++ b/polygerrit-ui/app/elements/shared/gr-suggestion-diff-preview/gr-suggestion-diff-preview.ts
@@ -130,6 +130,14 @@
);
subscribe(
this,
+ () => this.getChangeModel().revisions$,
+ revisions =>
+ (this.hasEdit = Object.values(revisions).some(
+ info => info._number === EDIT
+ ))
+ );
+ subscribe(
+ this,
() => this.getChangeModel().latestPatchNum$,
x => (this.latestPatchNum = x)
);
diff --git a/polygerrit-ui/app/models/change/change-model.ts b/polygerrit-ui/app/models/change/change-model.ts
index 04fa0d6..dd292e6 100644
--- a/polygerrit-ui/app/models/change/change-model.ts
+++ b/polygerrit-ui/app/models/change/change-model.ts
@@ -353,6 +353,10 @@
public readonly latestRevision$ = this.selectRevision(this.latestPatchNum$);
+ public readonly latestRevisionWithEdit$ = this.selectRevision(
+ this.latestPatchNumWithEdit$
+ );
+
public readonly isOwner$: Observable<boolean> = select(
combineLatest([this.change$, this.userModel.account$]),
([change, account]) => isOwner(change, account)
diff --git a/resources/com/google/gerrit/pgm/init/gerrit.sh b/resources/com/google/gerrit/pgm/init/gerrit.sh
index dc56fae..4dc8881 100755
--- a/resources/com/google/gerrit/pgm/init/gerrit.sh
+++ b/resources/com/google/gerrit/pgm/init/gerrit.sh
@@ -371,7 +371,7 @@
GERRIT_USER=`get_config --get container.user`
-if test "$(uname -s)" == "Darwin" ; then
+if test "$(uname -s)" = "Darwin" ; then
JAVA_OPTIONS="$JAVA_OPTIONS -XX:-MaxFDLimit"
fi
diff --git a/tools/run_gjf.sh b/tools/run_gjf.sh
index c6eea0f..2e10dc8 100755
--- a/tools/run_gjf.sh
+++ b/tools/run_gjf.sh
@@ -16,10 +16,10 @@
set -eu
-GJF_VERSION=$(grep -o "^VERSION=.*$" tools/setup_gjf.sh | grep -o "[0-9][0-9]*\.[0-9][0-9]*")
-GJF=$(find 'tools/format' -regex '.*/google-java-format-[0-9][0-9]*\.[0-9][0-9]*')
+GJF_VERSION=$(grep -o "^VERSION=.*$" tools/setup_gjf.sh | grep -o '[0-9][0-9]*\.[0-9][0-9]*[\.0-9]*')
+GJF="tools/format/google-java-format-$GJF_VERSION"
if [ ! -f "$GJF" ]; then
- ./setup_gjf.sh
+ tools/setup_gjf.sh
GJF=$(find 'tools/format' -regex '.*/google-java-format-[0-9][0-9]*\.[0-9][0-9]*')
fi
echo 'Running google-java-format check...'