From 104107bf437e3fc8348cac99ffe069c7da404154 Mon Sep 17 00:00:00 2001 From: Dave Borowitz Date: Wed, 19 Jul 2017 13:55:30 -0400 Subject: [PATCH] Support overriding a batch's reflog on a per-ReceiveCommand basis Change-Id: I86a4b8f6b4f85b2bae64c1b121e4ee527d46de83 --- .../storage/file/BatchRefUpdateTest.java | 45 +++++++++ .../storage/file/PackedBatchRefUpdate.java | 12 +-- .../org/eclipse/jgit/lib/BatchRefUpdate.java | 53 ++++++++++- .../jgit/transport/ReceiveCommand.java | 92 +++++++++++++++++++ 4 files changed, 193 insertions(+), 9 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java index a51a910fb..5a4090722 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/BatchRefUpdateTest.java @@ -539,6 +539,51 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase { } } + @Test + public void overrideRefLogMessage() throws Exception { + writeRef("refs/heads/master", A); + + List cmds = Arrays.asList( + new ReceiveCommand(A, B, "refs/heads/master", UPDATE), + new ReceiveCommand(zeroId(), B, "refs/heads/branch", CREATE)); + cmds.get(0).setRefLogMessage("custom log", false); + PersonIdent ident = new PersonIdent(diskRepo); + execute( + newBatchUpdate(cmds) + .setRefLogIdent(ident) + .setRefLogMessage("a reflog", true)); + + assertResults(cmds, OK, OK); + assertReflogEquals( + reflog(A, B, ident, "custom log"), + getLastReflog("refs/heads/master"), + true); + assertReflogEquals( + reflog(zeroId(), B, ident, "a reflog: created"), + getLastReflog("refs/heads/branch"), + true); + } + + @Test + public void overrideDisableRefLog() throws Exception { + writeRef("refs/heads/master", A); + + Map oldLogs = + getLastReflogs("refs/heads/master", "refs/heads/branch"); + + List cmds = Arrays.asList( + new ReceiveCommand(A, B, "refs/heads/master", UPDATE), + new ReceiveCommand(zeroId(), B, "refs/heads/branch", CREATE)); + cmds.get(0).disableRefLog(); + execute(newBatchUpdate(cmds).setRefLogMessage("a reflog", true)); + + assertResults(cmds, OK, OK); + assertReflogUnchanged(oldLogs, "refs/heads/master"); + assertReflogEquals( + reflog(zeroId(), B, new PersonIdent(diskRepo), "a reflog: created"), + getLastReflog("refs/heads/branch")); + } + private void writeLooseRef(String name, AnyObjectId id) throws IOException { write(new File(diskRepo.getDirectory(), name), id.name() + "\n"); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackedBatchRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackedBatchRefUpdate.java index 90155cbac..06c31f2c2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackedBatchRefUpdate.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackedBatchRefUpdate.java @@ -349,10 +349,6 @@ class PackedBatchRefUpdate extends BatchRefUpdate { } private void writeReflog(List commands) { - if (isRefLogDisabled()) { - return; - } - PersonIdent ident = getRefLogIdent(); if (ident == null) { ident = new PersonIdent(refdb.getRepository()); @@ -374,8 +370,12 @@ class PackedBatchRefUpdate extends BatchRefUpdate { continue; } - String msg = getRefLogMessage(); - if (isRefLogIncludingResult()) { + if (isRefLogDisabled(cmd)) { + continue; + } + + String msg = getRefLogMessage(cmd); + if (isRefLogIncludingResult(cmd)) { String strResult = toResultString(cmd); if (strResult != null) { msg = msg.isEmpty() diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java index 4f1299a6c..956607c9a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java @@ -185,6 +185,9 @@ public class BatchRefUpdate { /** * Check whether the reflog message should include the result of the update, * such as fast-forward or force-update. + *

+ * Describes the default for commands in this batch that do not override it + * with {@link ReceiveCommand#setRefLogMessage(String, boolean)}. * * @return true if the message should include the result. */ @@ -194,6 +197,9 @@ public class BatchRefUpdate { /** * Set the message to include in the reflog. + *

+ * Describes the default for commands in this batch that do not override it + * with {@link ReceiveCommand#setRefLogMessage(String, boolean)}. * * @param msg * the message to describe this change. If null and appendStatus is @@ -624,11 +630,11 @@ public class BatchRefUpdate { */ protected RefUpdate newUpdate(ReceiveCommand cmd) throws IOException { RefUpdate ru = refdb.newUpdate(cmd.getRefName(), false); - if (isRefLogDisabled()) + if (isRefLogDisabled(cmd)) { ru.disableRefLog(); - else { + } else { ru.setRefLogIdent(refLogIdent); - ru.setRefLogMessage(refLogMessage, refLogIncludeResult); + ru.setRefLogMessage(getRefLogMessage(cmd), isRefLogIncludingResult(cmd)); } ru.setPushCertificate(pushCert); switch (cmd.getType()) { @@ -649,6 +655,47 @@ public class BatchRefUpdate { } } + /** + * Check whether reflog is disabled for a command. + * + * @param cmd + * specific command. + * @return whether the reflog is disabled, taking into account the state from + * this instance as well as overrides in the given command. + * @since 4.9 + */ + protected boolean isRefLogDisabled(ReceiveCommand cmd) { + return cmd.hasCustomRefLog() ? cmd.isRefLogDisabled() : isRefLogDisabled(); + } + + /** + * Get reflog message for a command. + * + * @param cmd + * specific command. + * @return reflog message, taking into account the state from this instance as + * well as overrides in the given command. + * @since 4.9 + */ + protected String getRefLogMessage(ReceiveCommand cmd) { + return cmd.hasCustomRefLog() ? cmd.getRefLogMessage() : getRefLogMessage(); + } + + /** + * Check whether the reflog message for a command should include the result. + * + * @param cmd + * specific command. + * @return whether the reflog message should show the result, taking into + * account the state from this instance as well as overrides in the + * given command. + * @since 4.9 + */ + protected boolean isRefLogIncludingResult(ReceiveCommand cmd) { + return cmd.hasCustomRefLog() + ? cmd.isRefLogIncludingResult() : isRefLogIncludingResult(); + } + @Override public String toString() { StringBuilder r = new StringBuilder(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java index a37cdd42a..14b35c9bf 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java @@ -52,6 +52,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.ObjectId; @@ -218,6 +219,12 @@ public class ReceiveCommand { private String message; + private boolean customRefLog; + + private String refLogMessage; + + private boolean refLogIncludeResult; + private boolean typeIsCorrect; /** @@ -342,6 +349,90 @@ public class ReceiveCommand { return message; } + /** + * Set the message to include in the reflog. + *

+ * Overrides the default set by {@code setRefLogMessage} on any containing + * {@link org.eclipse.jgit.lib.BatchRefUpdate}. + * + * @param msg + * the message to describe this change. If null and appendStatus is + * false, the reflog will not be updated. + * @param appendStatus + * true if the status of the ref change (fast-forward or + * forced-update) should be appended to the user supplied message. + * @since 4.9 + */ + public void setRefLogMessage(String msg, boolean appendStatus) { + customRefLog = true; + if (msg == null && !appendStatus) { + disableRefLog(); + } else if (msg == null && appendStatus) { + refLogMessage = ""; //$NON-NLS-1$ + refLogIncludeResult = true; + } else { + refLogMessage = msg; + refLogIncludeResult = appendStatus; + } + } + + /** + * Don't record this update in the ref's associated reflog. + *

+ * Equivalent to {@code setRefLogMessage(null, false)}. + * + * @since 4.9 + */ + public void disableRefLog() { + customRefLog = true; + refLogMessage = null; + refLogIncludeResult = false; + } + + /** + * Check whether this command has a custom reflog setting that should override + * defaults in any containing {@link org.eclipse.jgit.lib.BatchRefUpdate}. + * + * @return whether a custom reflog is set. + * @since 4.9 + */ + public boolean hasCustomRefLog() { + return customRefLog; + } + + /** + * Check whether log has been disabled by {@link #disableRefLog()}. + * + * @return true if disabled. + * @since 4.9 + */ + public boolean isRefLogDisabled() { + return refLogMessage == null; + } + + /** + * Get the message to include in the reflog. + * + * @return message the caller wants to include in the reflog; null if the + * update should not be logged. + * @since 4.9 + */ + @Nullable + public String getRefLogMessage() { + return refLogMessage; + } + + /** + * Check whether the reflog message should include the result of the update, + * such as fast-forward or force-update. + * + * @return true if the message should include the result. + * @since 4.9 + */ + public boolean isRefLogIncludingResult() { + return refLogIncludeResult; + } + /** * Set the status of this command. * @@ -408,6 +499,7 @@ public class ReceiveCommand { try { final RefUpdate ru = rp.getRepository().updateRef(getRefName()); ru.setRefLogIdent(rp.getRefLogIdent()); + ru.setRefLogMessage(refLogMessage, refLogIncludeResult); switch (getType()) { case DELETE: if (!ObjectId.zeroId().equals(getOldId())) {