aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
authorTerry Parker <tparker@google.com>2016-07-22 19:27:17 -0400
committerGerrit Code Review @ Eclipse.org <gerrit@eclipse.org>2016-07-22 19:27:20 -0400
commite9e2f7e6b5c075518bb4a744513558956dd099bf (patch)
tree7d6fca089a9ffb1318e51bf2dd625d11317e402d /org.eclipse.jgit
parentecb2aa05030529b7ecdfe9ff4b7a3effce0a6821 (diff)
parent7f9fb8000252ac57b1613539927e34c9cdb9ef9b (diff)
downloadjgit-e9e2f7e6b5c075518bb4a744513558956dd099bf.tar.gz
jgit-e9e2f7e6b5c075518bb4a744513558956dd099bf.zip
Merge "Push implementation of option strings"
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java24
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java46
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java46
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java75
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/PushProcess.java15
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java13
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java22
10 files changed, 244 insertions, 6 deletions
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index e68bca0322..ebe1befee1 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -498,6 +498,7 @@ pushCertificateInvalidHeader=Push certificate has invalid header format
pushCertificateInvalidSignature=Push certificate has invalid signature format
pushIsNotSupportedForBundleTransport=Push is not supported for bundle transport
pushNotPermitted=push not permitted
+pushOptionsNotSupported=Push options not supported; received {0}
rawLogMessageDoesNotParseAsLogEntry=Raw log message does not parse as log entry
readingObjectsFromLocalRepositoryFailed=reading objects from local repository failed: {0}
readTimedOut=Read timed out after {0} ms
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java
index 0a49f78069..bd4521b517 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/PushCommand.java
@@ -96,6 +96,8 @@ public class PushCommand extends
private OutputStream out;
+ private List<String> pushOptions;
+
/**
* @param repo
*/
@@ -149,6 +151,7 @@ public class PushCommand extends
if (receivePack != null)
transport.setOptionReceivePack(receivePack);
transport.setDryRun(dryRun);
+ transport.setPushOptions(pushOptions);
configure(transport);
final Collection<RemoteRefUpdate> toPush = transport
@@ -189,7 +192,6 @@ public class PushCommand extends
}
return pushResults;
-
}
/**
@@ -453,4 +455,24 @@ public class PushCommand extends
this.out = out;
return this;
}
+
+ /**
+ * @return the option strings associated with the push operation
+ * @since 4.5
+ */
+ public List<String> getPushOptions() {
+ return pushOptions;
+ }
+
+ /**
+ * Sets the option strings associated with the push operation.
+ *
+ * @param pushOptions
+ * @return {@code this}
+ * @since 4.5
+ */
+ public PushCommand setPushOptions(List<String> pushOptions) {
+ this.pushOptions = pushOptions;
+ return this;
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
index b7ef0854c9..313512f990 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -557,6 +557,7 @@ public class JGitText extends TranslationBundle {
/***/ public String pushCertificateInvalidSignature;
/***/ public String pushIsNotSupportedForBundleTransport;
/***/ public String pushNotPermitted;
+ /***/ public String pushOptionsNotSupported;
/***/ public String rawLogMessageDoesNotParseAsLogEntry;
/***/ public String readingObjectsFromLocalRepositoryFailed;
/***/ public String readTimedOut;
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 266ca7b060..8550ec3a3f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchRefUpdate.java
@@ -92,6 +92,9 @@ public class BatchRefUpdate {
/** Whether updates should be atomic. */
private boolean atomic;
+ /** Push options associated with this update. */
+ private List<String> pushOptions;
+
/**
* Initialize a new batch update.
*
@@ -301,27 +304,40 @@ public class BatchRefUpdate {
}
/**
+ * Gets the list of option strings associated with this update.
+ *
+ * @return pushOptions
+ * @since 4.5
+ */
+ public List<String> getPushOptions() {
+ return pushOptions;
+ }
+
+ /**
* Execute this batch update.
* <p>
* The default implementation of this method performs a sequential reference
* update over each reference.
* <p>
* Implementations must respect the atomicity requirements of the underlying
- * database as described in {@link #setAtomic(boolean)} and {@link
- * RefDatabase#performsAtomicTransactions()}.
+ * database as described in {@link #setAtomic(boolean)} and
+ * {@link RefDatabase#performsAtomicTransactions()}.
*
* @param walk
* a RevWalk to parse tags in case the storage system wants to
* store them pre-peeled, a common performance optimization.
* @param monitor
* progress monitor to receive update status on.
+ * @param options
+ * a list of option strings; set null to execute without
* @throws IOException
* the database is unable to accept the update. Individual
* command status must be tested to determine if there is a
* partial failure, or a total failure.
+ * @since 4.5
*/
- public void execute(RevWalk walk, ProgressMonitor monitor)
- throws IOException {
+ public void execute(RevWalk walk, ProgressMonitor monitor,
+ List<String> options) throws IOException {
if (atomic && !refdb.performsAtomicTransactions()) {
for (ReceiveCommand c : commands) {
@@ -333,6 +349,10 @@ public class BatchRefUpdate {
return;
}
+ if (options != null) {
+ pushOptions = options;
+ }
+
monitor.beginTask(JGitText.get().updatingReferences, commands.size());
List<ReceiveCommand> commands2 = new ArrayList<ReceiveCommand>(
commands.size());
@@ -412,6 +432,24 @@ public class BatchRefUpdate {
monitor.endTask();
}
+ /**
+ * Execute this batch update without option strings.
+ *
+ * @param walk
+ * a RevWalk to parse tags in case the storage system wants to
+ * store them pre-peeled, a common performance optimization.
+ * @param monitor
+ * progress monitor to receive update status on.
+ * @throws IOException
+ * the database is unable to accept the update. Individual
+ * command status must be tested to determine if there is a
+ * partial failure, or a total failure.
+ */
+ public void execute(RevWalk walk, ProgressMonitor monitor)
+ throws IOException {
+ execute(walk, monitor, null);
+ }
+
private static Collection<String> getTakenPrefixes(
final Collection<String> names) {
Collection<String> ref = new HashSet<String>();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java
index 0cbbdc77e3..86cc484e34 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java
@@ -52,6 +52,7 @@ import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -113,14 +114,24 @@ public abstract class BasePackPushConnection extends BasePackConnection implemen
*/
public static final String CAPABILITY_SIDE_BAND_64K = GitProtocolConstants.CAPABILITY_SIDE_BAND_64K;
+ /**
+ * The server supports the receiving of push options.
+ * @since 4.5
+ */
+ public static final String CAPABILITY_PUSH_OPTIONS = GitProtocolConstants.CAPABILITY_PUSH_OPTIONS;
+
private final boolean thinPack;
private final boolean atomic;
+ /** A list of option strings associated with this push. */
+ private List<String> pushOptions;
+
private boolean capableAtomic;
private boolean capableDeleteRefs;
private boolean capableReport;
private boolean capableSideBand;
private boolean capableOfsDelta;
+ private boolean capablePushOptions;
private boolean sentCommand;
private boolean writePack;
@@ -138,6 +149,7 @@ public abstract class BasePackPushConnection extends BasePackConnection implemen
super(packTransport);
thinPack = transport.isPushThin();
atomic = transport.isPushAtomic();
+ pushOptions = transport.getPushOptions();
}
public void push(final ProgressMonitor monitor,
@@ -197,6 +209,9 @@ public abstract class BasePackPushConnection extends BasePackConnection implemen
OutputStream outputStream) throws TransportException {
try {
writeCommands(refUpdates.values(), monitor, outputStream);
+
+ if (pushOptions != null && capablePushOptions)
+ transmitOptions();
if (writePack)
writePack(refUpdates, monitor);
if (sentCommand) {
@@ -232,6 +247,12 @@ public abstract class BasePackPushConnection extends BasePackConnection implemen
JGitText.get().atomicPushNotSupported);
}
+ if (pushOptions != null && !capablePushOptions) {
+ throw new TransportException(uri,
+ MessageFormat.format(JGitText.get().pushOptionsNotSupported,
+ pushOptions.toString()));
+ }
+
for (final RemoteRefUpdate rru : refUpdates) {
if (!capableDeleteRefs && rru.isDelete()) {
rru.setStatus(Status.REJECTED_NODELETE);
@@ -269,6 +290,14 @@ public abstract class BasePackPushConnection extends BasePackConnection implemen
outNeedsEnd = false;
}
+ private void transmitOptions() throws IOException {
+ for (final String pushOption : pushOptions) {
+ pckOut.writeString(pushOption);
+ }
+
+ pckOut.end();
+ }
+
private String enableCapabilities(final ProgressMonitor monitor,
OutputStream outputStream) {
final StringBuilder line = new StringBuilder();
@@ -278,6 +307,10 @@ public abstract class BasePackPushConnection extends BasePackConnection implemen
capableDeleteRefs = wantCapability(line, CAPABILITY_DELETE_REFS);
capableOfsDelta = wantCapability(line, CAPABILITY_OFS_DELTA);
+ if (pushOptions != null) {
+ capablePushOptions = wantCapability(line, CAPABILITY_PUSH_OPTIONS);
+ }
+
capableSideBand = wantCapability(line, CAPABILITY_SIDE_BAND_64K);
if (capableSideBand) {
in = new SideBandInputStream(in, monitor, getMessageWriter(),
@@ -333,7 +366,8 @@ public abstract class BasePackPushConnection extends BasePackConnection implemen
throws IOException {
final String unpackLine = readStringLongTimeout();
if (!unpackLine.startsWith("unpack ")) //$NON-NLS-1$
- throw new PackProtocolException(uri, MessageFormat.format(JGitText.get().unexpectedReportLine, unpackLine));
+ throw new PackProtocolException(uri, MessageFormat
+ .format(JGitText.get().unexpectedReportLine, unpackLine));
final String unpackStatus = unpackLine.substring("unpack ".length()); //$NON-NLS-1$
if (unpackStatus.startsWith("error Pack exceeds the limit of")) {//$NON-NLS-1$
throw new TooLargePackException(uri,
@@ -404,6 +438,16 @@ public abstract class BasePackPushConnection extends BasePackConnection implemen
}
}
+ /**
+ * Gets the list of option strings associated with this push.
+ *
+ * @return pushOptions
+ * @since 4.5
+ */
+ public List<String> getPushOptions() {
+ return pushOptions;
+ }
+
private static class CheckingSideBandOutputStream extends OutputStream {
private final InputStream in;
private final OutputStream out;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java
index aae4bd9c3c..b9923b95e2 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java
@@ -48,6 +48,7 @@ import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_DELETE_
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_OFS_DELTA;
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_QUIET;
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_REPORT_STATUS;
+import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_PUSH_OPTIONS;
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_SIDE_BAND_64K;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;
import static org.eclipse.jgit.transport.SideBandOutputStream.CH_DATA;
@@ -178,6 +179,9 @@ public abstract class BaseReceivePack {
/** Should an incoming transfer permit non-fast-forward requests? */
private boolean allowNonFastForwards;
+ /** Should an incoming transfer permit push options? **/
+ private boolean allowPushOptions;
+
/**
* Should the requested ref updates be performed as a single atomic
* transaction?
@@ -247,6 +251,18 @@ public abstract class BaseReceivePack {
private boolean quiet;
+ /**
+ * A list of option strings associated with a push.
+ * @since 4.5
+ */
+ protected List<String> pushOptions;
+
+ /**
+ * Whether the client intends to use push options.
+ * @since 4.5
+ */
+ protected boolean usePushOptions;
+
/** Lock around the received pack file, while updating refs. */
private PackLock packLock;
@@ -311,6 +327,7 @@ public abstract class BaseReceivePack {
allowBranchDeletes = rc.allowDeletes;
allowNonFastForwards = rc.allowNonFastForwards;
allowOfsDelta = rc.allowOfsDelta;
+ allowPushOptions = rc.allowPushOptions;
advertiseRefsHook = AdvertiseRefsHook.DEFAULT;
refFilter = RefFilter.DEFAULT;
advertisedHaves = new HashSet<ObjectId>();
@@ -330,6 +347,8 @@ public abstract class BaseReceivePack {
final boolean allowDeletes;
final boolean allowNonFastForwards;
final boolean allowOfsDelta;
+ final boolean allowPushOptions;
+
final SignedPushConfig signedPush;
ReceiveConfig(final Config config) {
@@ -339,6 +358,8 @@ public abstract class BaseReceivePack {
"denynonfastforwards", false); //$NON-NLS-1$
allowOfsDelta = config.getBoolean("repack", "usedeltabaseoffset", //$NON-NLS-1$ //$NON-NLS-2$
true);
+ allowPushOptions = config.getBoolean("receive", "pushoptions", //$NON-NLS-1$ //$NON-NLS-2$
+ false);
signedPush = SignedPushConfig.KEY.parse(config);
}
}
@@ -788,6 +809,25 @@ public abstract class BaseReceivePack {
}
/**
+ * @return true if the server supports the receiving of push options.
+ * @since 4.5
+ */
+ public boolean isAllowPushOptions() {
+ return allowPushOptions;
+ }
+
+ /**
+ * Configure if the server supports the receiving of push options.
+ *
+ * @param allow
+ * true to permit option strings.
+ * @since 4.5
+ */
+ public void setAllowPushOptions(boolean allow) {
+ allowPushOptions = allow;
+ }
+
+ /**
* True if the client wants less verbose output.
*
* @return true if the client has requested the server to be less verbose.
@@ -805,6 +845,24 @@ public abstract class BaseReceivePack {
}
/**
+ * Gets the list of string options associated with this push.
+ *
+ * @return pushOptions
+ * @throws RequestNotYetReadException
+ * if the client's request has not yet been read from the wire,
+ * so we do not know if they expect push options. Note that the
+ * client may have already written the request, it just has not
+ * been read.
+ * @since 4.5
+ */
+ public List<String> getPushOptions() throws RequestNotYetReadException {
+ if (enabledCapabilities == null) {
+ throw new RequestNotYetReadException();
+ }
+ return Collections.unmodifiableList(pushOptions);
+ }
+
+ /**
* Set the configuration for push certificate verification.
*
* @param cfg
@@ -1076,6 +1134,10 @@ public abstract class BaseReceivePack {
adv.advertiseCapability(CAPABILITY_ATOMIC);
if (allowOfsDelta)
adv.advertiseCapability(CAPABILITY_OFS_DELTA);
+ if (allowPushOptions) {
+ adv.advertiseCapability(CAPABILITY_PUSH_OPTIONS);
+ pushOptions = new ArrayList<>();
+ }
adv.advertiseCapability(OPTION_AGENT, UserAgent.get());
adv.send(getAdvertisedOrDefaultRefs());
for (ObjectId obj : advertisedHaves)
@@ -1192,6 +1254,8 @@ public abstract class BaseReceivePack {
protected void enableCapabilities() {
sideBand = isCapabilityEnabled(CAPABILITY_SIDE_BAND_64K);
quiet = allowQuiet && isCapabilityEnabled(CAPABILITY_QUIET);
+ usePushOptions = allowPushOptions
+ && isCapabilityEnabled(CAPABILITY_PUSH_OPTIONS);
if (sideBand) {
OutputStream out = rawOut;
@@ -1205,6 +1269,17 @@ public abstract class BaseReceivePack {
}
/**
+ * Sets the client's intention regarding push options.
+ *
+ * @param usePushOptions
+ * whether the client intends to use push options
+ * @since 4.5
+ */
+ public void setUsePushOptions(boolean usePushOptions) {
+ this.usePushOptions = usePushOptions;
+ }
+
+ /**
* Check if the peer requested a capability.
*
* @param name
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java
index efde062621..2031147820 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java
@@ -208,6 +208,13 @@ public class GitProtocolConstants {
*/
public static final String OPTION_AGENT = "agent"; //$NON-NLS-1$
+ /**
+ * The server supports the receiving of push options.
+ *
+ * @since 4.5
+ */
+ public static final String CAPABILITY_PUSH_OPTIONS = "push-options"; //$NON-NLS-1$
+
static enum MultiAck {
OFF, CONTINUE, DETAILED;
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushProcess.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushProcess.java
index 5cea88215a..5590c2d256 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushProcess.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushProcess.java
@@ -49,6 +49,7 @@ import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.eclipse.jgit.errors.MissingObjectException;
@@ -87,6 +88,9 @@ class PushProcess {
/** an outputstream to write messages to */
private final OutputStream out;
+ /** A list of option strings associated with this push */
+ private List<String> pushOptions;
+
/**
* Create process for specified transport and refs updates specification.
*
@@ -122,6 +126,7 @@ class PushProcess {
this.transport = transport;
this.toPush = new HashMap<String, RemoteRefUpdate>();
this.out = out;
+ this.pushOptions = transport.getPushOptions();
for (final RemoteRefUpdate rru : toPush) {
if (this.toPush.put(rru.getRemoteName(), rru) != null)
throw new TransportException(MessageFormat.format(
@@ -294,4 +299,14 @@ class PushProcess {
}
}
}
+
+ /**
+ * Gets the list of option strings associated with this push.
+ *
+ * @return pushOptions
+ * @since 4.5
+ */
+ public List<String> getPushOptions() {
+ return pushOptions;
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
index 2477806bd9..d16b723ff8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java
@@ -174,6 +174,15 @@ public class ReceivePack extends BaseReceivePack {
super.enableCapabilities();
}
+ private void readPushOptions() throws IOException {
+ String pushOption = pckIn.readString();
+
+ while (pushOption != PacketLineIn.END) {
+ pushOptions.add(pushOption);
+ pushOption = pckIn.readString();
+ }
+ }
+
private void service() throws IOException {
if (isBiDirectionalPipe()) {
sendAdvertisedRefs(new PacketLineOutRefAdvertiser(pckOut));
@@ -184,6 +193,10 @@ public class ReceivePack extends BaseReceivePack {
return;
recvCommands();
if (hasCommands()) {
+ if (usePushOptions) {
+ readPushOptions();
+ }
+
Throwable unpackError = null;
if (needPack()) {
try {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
index 862b3bdeb0..bc4843a8af 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Transport.java
@@ -773,6 +773,9 @@ public abstract class Transport implements AutoCloseable {
/** Assists with authentication the connection. */
private CredentialsProvider credentialsProvider;
+ /** The option strings associated with the push operation. */
+ private List<String> pushOptions;
+
private PrintStream hookOutRedirect;
private PrePushHook prePush;
@@ -1121,6 +1124,25 @@ public abstract class Transport implements AutoCloseable {
}
/**
+ * @return the option strings associated with the push operation
+ * @since 4.5
+ */
+ public List<String> getPushOptions() {
+ return pushOptions;
+ }
+
+ /**
+ * Sets the option strings associated with the push operation.
+ *
+ * @param pushOptions
+ * null if push options are unsupported
+ * @since 4.5
+ */
+ public void setPushOptions(final List<String> pushOptions) {
+ this.pushOptions = pushOptions;
+ }
+
+ /**
* Fetch objects and refs from the remote repository to the local one.
* <p>
* This is a utility function providing standard fetch behavior. Local