aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Smith <[email protected]>2025-08-18 11:38:18 +0200
committerDaniel Smith <[email protected]>2025-08-18 12:01:37 +0000
commita941ffb3443ed90ceac7cbeff9db1b1ccab1bd3a (patch)
treeb96ad7933d304956cba276df4d6bd28c2b9437a0
parent7b949aea7a4f6534fe6eb3dcca5688dee06231eb (diff)
Allow configurable exceptions to empty-commit staging restrictionsv3.10-based
In the case of [ChangeLog] tagged commits, it can be appropriate to stage/merge an empty commit which acts as an update to Changelog generators, but does not modify code. Fixes: QTQAINFRA-7343 Change-Id: I173e050866e58c357db4020dc80590d5cc1166bc Reviewed-by: Jukka Jokiniva <[email protected]>
-rw-r--r--src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtCherryPickPatch.java31
-rw-r--r--src/test/java/com/googlesource/gerrit/plugins/qtcodereview/QtStageIT.java26
2 files changed, 56 insertions, 1 deletions
diff --git a/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtCherryPickPatch.java b/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtCherryPickPatch.java
index 23ec133..ef9c1e5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtCherryPickPatch.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtCherryPickPatch.java
@@ -26,16 +26,22 @@ import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
+import java.io.IOException;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.SystemReader;
@Singleton
public class QtCherryPickPatch {
@@ -145,7 +151,30 @@ public class QtCherryPickPatch {
false); // allowConflicts
if (cherryPickCommit.getTree().equals(baseCommit.getTree())) {
- throw new IntegrationConflictException("Cannot stage change: The patch set is empty.");
+ Config cfg;
+ try {
+ FileBasedConfig userConfig = SystemReader.getInstance().openUserConfig(null, FS.DETECTED);
+ userConfig.load();
+ cfg = userConfig;
+ } catch (IOException | ConfigInvalidException e) {
+ logger.atWarning().withCause(e).log("Could not load user gitconfig");
+ cfg = new Config();
+ }
+ String exceptions = cfg.getString("qtcodereview", null, "emptyCommitExceptions");
+ logger.atInfo().log(
+ "Found empty commit exceptions: %s", exceptions);
+ boolean allowed = false;
+ if (exceptions != null && !exceptions.isEmpty()) {
+ String originalCommitMessage = commitToCherryPick.getFullMessage();
+ allowed =
+ Arrays.stream(exceptions.split(","))
+ .map(String::trim)
+ .filter(s -> !s.isEmpty())
+ .anyMatch(originalCommitMessage::contains);
+ }
+ if (!allowed) {
+ throw new IntegrationConflictException("Cannot stage change: The patch set is empty.");
+ }
}
boolean patchSetNotChanged = cherryPickCommit.equals(commitToCherryPick);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/qtcodereview/QtStageIT.java b/src/test/java/com/googlesource/gerrit/plugins/qtcodereview/QtStageIT.java
index 5c9b616..dee9a1d 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/qtcodereview/QtStageIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/qtcodereview/QtStageIT.java
@@ -23,8 +23,11 @@ import com.google.gerrit.extensions.client.ChangeStatus;
import java.util.ArrayList;
import org.apache.http.HttpStatus;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RemoteRefUpdate;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.SystemReader;
import org.junit.Before;
import org.junit.Test;
@@ -147,6 +150,29 @@ public class QtStageIT extends QtCodeReviewIT {
}
@Test
+ public void emptyChange_Stage_AllowException() throws Exception {
+
+ // Store exception string
+ FileBasedConfig gitConfig = SystemReader.getInstance().openUserConfig(null, FS.DETECTED);
+ gitConfig.load();
+ gitConfig.setString("qtcodereview", null, "emptyCommitExceptions", "[ChangeLog]");
+ gitConfig.save();
+
+ RevCommit initialHead = getRemoteHead();
+ PushOneCommit.Result c = pushCommit("master", "1st commit]", "afile", "");
+ approve(c.getChangeId());
+ RevCommit stagingHead = qtStage(c);
+ assertApproval(c.getChangeId(), admin);
+
+ // no changes in this commit, but an exception string in commit message
+ c = pushCommit("master", "2nd commit:no content\n[ChangeLog]", "afile", "");
+ approve(c.getChangeId());
+
+ stagingHead = qtStage(c);
+ assertApproval(c.getChangeId(), admin);
+ }
+
+ @Test
public void emptyChange_Stage_expectFail() throws Exception {
RevCommit initialHead = getRemoteHead();
PushOneCommit.Result c = pushCommit("master", "1st commit", "afile", "");