|
|
|
|
|
|
|
|
import org.eclipse.jgit.revwalk.RevSort; |
|
|
import org.eclipse.jgit.revwalk.RevSort; |
|
|
import org.eclipse.jgit.revwalk.RevTree; |
|
|
import org.eclipse.jgit.revwalk.RevTree; |
|
|
import org.eclipse.jgit.revwalk.RevWalk; |
|
|
import org.eclipse.jgit.revwalk.RevWalk; |
|
|
|
|
|
import org.eclipse.jgit.transport.PacketLineIn.InputOverLimitIOException; |
|
|
import org.eclipse.jgit.transport.ReceiveCommand.Result; |
|
|
import org.eclipse.jgit.transport.ReceiveCommand.Result; |
|
|
import org.eclipse.jgit.util.io.InterruptTimer; |
|
|
import org.eclipse.jgit.util.io.InterruptTimer; |
|
|
import org.eclipse.jgit.util.io.LimitedInputStream; |
|
|
import org.eclipse.jgit.util.io.LimitedInputStream; |
|
|
|
|
|
|
|
|
String userAgent; |
|
|
String userAgent; |
|
|
private Set<ObjectId> clientShallowCommits; |
|
|
private Set<ObjectId> clientShallowCommits; |
|
|
private List<ReceiveCommand> commands; |
|
|
private List<ReceiveCommand> commands; |
|
|
|
|
|
private long maxCommandBytes; |
|
|
|
|
|
private long maxDiscardBytes; |
|
|
|
|
|
|
|
|
private StringBuilder advertiseError; |
|
|
private StringBuilder advertiseError; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
allowNonFastForwards = rc.allowNonFastForwards; |
|
|
allowNonFastForwards = rc.allowNonFastForwards; |
|
|
allowOfsDelta = rc.allowOfsDelta; |
|
|
allowOfsDelta = rc.allowOfsDelta; |
|
|
allowPushOptions = rc.allowPushOptions; |
|
|
allowPushOptions = rc.allowPushOptions; |
|
|
|
|
|
maxCommandBytes = rc.maxCommandBytes; |
|
|
|
|
|
maxDiscardBytes = rc.maxDiscardBytes; |
|
|
advertiseRefsHook = AdvertiseRefsHook.DEFAULT; |
|
|
advertiseRefsHook = AdvertiseRefsHook.DEFAULT; |
|
|
refFilter = RefFilter.DEFAULT; |
|
|
refFilter = RefFilter.DEFAULT; |
|
|
advertisedHaves = new HashSet<ObjectId>(); |
|
|
advertisedHaves = new HashSet<ObjectId>(); |
|
|
|
|
|
|
|
|
final boolean allowNonFastForwards; |
|
|
final boolean allowNonFastForwards; |
|
|
final boolean allowOfsDelta; |
|
|
final boolean allowOfsDelta; |
|
|
final boolean allowPushOptions; |
|
|
final boolean allowPushOptions; |
|
|
|
|
|
|
|
|
|
|
|
final long maxCommandBytes; |
|
|
|
|
|
final long maxDiscardBytes; |
|
|
final SignedPushConfig signedPush; |
|
|
final SignedPushConfig signedPush; |
|
|
|
|
|
|
|
|
ReceiveConfig(final Config config) { |
|
|
ReceiveConfig(final Config config) { |
|
|
|
|
|
|
|
|
true); |
|
|
true); |
|
|
allowPushOptions = config.getBoolean("receive", "pushoptions", //$NON-NLS-1$ //$NON-NLS-2$ |
|
|
allowPushOptions = config.getBoolean("receive", "pushoptions", //$NON-NLS-1$ //$NON-NLS-2$ |
|
|
false); |
|
|
false); |
|
|
|
|
|
maxCommandBytes = config.getLong("receive", //$NON-NLS-1$ |
|
|
|
|
|
"maxCommandBytes", //$NON-NLS-1$ |
|
|
|
|
|
3 << 20); |
|
|
|
|
|
maxDiscardBytes = config.getLong("receive", //$NON-NLS-1$ |
|
|
|
|
|
"maxCommandDiscardBytes", //$NON-NLS-1$ |
|
|
|
|
|
-1); |
|
|
signedPush = SignedPushConfig.KEY.parse(config); |
|
|
signedPush = SignedPushConfig.KEY.parse(config); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
timeout = seconds; |
|
|
timeout = seconds; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Set the maximum number of command bytes to read from the client. |
|
|
|
|
|
* |
|
|
|
|
|
* @param limit |
|
|
|
|
|
* command limit in bytes; if 0 there is no limit. |
|
|
|
|
|
* @since 4.7 |
|
|
|
|
|
*/ |
|
|
|
|
|
public void setMaxCommandBytes(long limit) { |
|
|
|
|
|
maxCommandBytes = limit; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Set the maximum number of command bytes to discard from the client. |
|
|
|
|
|
* <p> |
|
|
|
|
|
* Discarding remaining bytes allows this instance to consume the rest of |
|
|
|
|
|
* the command block and send a human readable over-limit error via the |
|
|
|
|
|
* side-band channel. If the client sends an excessive number of bytes this |
|
|
|
|
|
* limit kicks in and the instance disconnects, resulting in a non-specific |
|
|
|
|
|
* 'pipe closed', 'end of stream', or similar generic error at the client. |
|
|
|
|
|
* <p> |
|
|
|
|
|
* When the limit is set to {@code -1} the implementation will default to |
|
|
|
|
|
* the larger of {@code 3 * maxCommandBytes} or {@code 3 MiB}. |
|
|
|
|
|
* |
|
|
|
|
|
* @param limit |
|
|
|
|
|
* discard limit in bytes; if 0 there is no limit; if -1 the |
|
|
|
|
|
* implementation tries to set a reasonable default. |
|
|
|
|
|
* @since 4.7 |
|
|
|
|
|
*/ |
|
|
|
|
|
public void setMaxCommandDiscardBytes(long limit) { |
|
|
|
|
|
maxDiscardBytes = limit; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Set the maximum allowed Git object size. |
|
|
* Set the maximum allowed Git object size. |
|
|
* <p> |
|
|
* <p> |
|
|
|
|
|
|
|
|
maxObjectSizeLimit = limit; |
|
|
maxObjectSizeLimit = limit; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Set the maximum allowed pack size. |
|
|
* Set the maximum allowed pack size. |
|
|
* <p> |
|
|
* <p> |
|
|
|
|
|
|
|
|
* @throws IOException |
|
|
* @throws IOException |
|
|
*/ |
|
|
*/ |
|
|
protected void recvCommands() throws IOException { |
|
|
protected void recvCommands() throws IOException { |
|
|
|
|
|
PacketLineIn pck = maxCommandBytes > 0 |
|
|
|
|
|
? new PacketLineIn(rawIn, maxCommandBytes) |
|
|
|
|
|
: pckIn; |
|
|
PushCertificateParser certParser = getPushCertificateParser(); |
|
|
PushCertificateParser certParser = getPushCertificateParser(); |
|
|
boolean firstPkt = true; |
|
|
boolean firstPkt = true; |
|
|
try { |
|
|
try { |
|
|
for (;;) { |
|
|
for (;;) { |
|
|
String line; |
|
|
String line; |
|
|
try { |
|
|
try { |
|
|
line = pckIn.readString(); |
|
|
|
|
|
|
|
|
line = pck.readString(); |
|
|
} catch (EOFException eof) { |
|
|
} catch (EOFException eof) { |
|
|
if (commands.isEmpty()) |
|
|
if (commands.isEmpty()) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
enableCapabilities(); |
|
|
enableCapabilities(); |
|
|
|
|
|
|
|
|
if (line.equals(GitProtocolConstants.OPTION_PUSH_CERT)) { |
|
|
if (line.equals(GitProtocolConstants.OPTION_PUSH_CERT)) { |
|
|
certParser.receiveHeader(pckIn, !isBiDirectionalPipe()); |
|
|
|
|
|
|
|
|
certParser.receiveHeader(pck, !isBiDirectionalPipe()); |
|
|
continue; |
|
|
continue; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (line.equals(PushCertificateParser.BEGIN_SIGNATURE)) { |
|
|
if (line.equals(PushCertificateParser.BEGIN_SIGNATURE)) { |
|
|
certParser.receiveSignature(pckIn); |
|
|
|
|
|
|
|
|
certParser.receiveSignature(pck); |
|
|
continue; |
|
|
continue; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
pushCert = certParser.build(); |
|
|
pushCert = certParser.build(); |
|
|
if (hasCommands()) { |
|
|
if (hasCommands()) { |
|
|
readPostCommands(pckIn); |
|
|
|
|
|
|
|
|
readPostCommands(pck); |
|
|
} |
|
|
} |
|
|
} catch (PackProtocolException e) { |
|
|
} catch (PackProtocolException e) { |
|
|
if (sideBand) { |
|
|
|
|
|
try { |
|
|
|
|
|
pckIn.discardUntilEnd(); |
|
|
|
|
|
} catch (IOException e2) { |
|
|
|
|
|
// Ignore read failures attempting to discard. |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
discardCommands(); |
|
|
fatalError(e.getMessage()); |
|
|
fatalError(e.getMessage()); |
|
|
throw e; |
|
|
throw e; |
|
|
|
|
|
} catch (InputOverLimitIOException e) { |
|
|
|
|
|
String msg = JGitText.get().tooManyCommands; |
|
|
|
|
|
discardCommands(); |
|
|
|
|
|
fatalError(msg); |
|
|
|
|
|
throw new PackProtocolException(msg); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void discardCommands() { |
|
|
|
|
|
if (sideBand) { |
|
|
|
|
|
long max = maxDiscardBytes; |
|
|
|
|
|
if (max < 0) { |
|
|
|
|
|
max = Math.max(3 * maxCommandBytes, 3L << 20); |
|
|
|
|
|
} |
|
|
|
|
|
try { |
|
|
|
|
|
new PacketLineIn(rawIn, max).discardUntilEnd(); |
|
|
|
|
|
} catch (IOException e) { |
|
|
|
|
|
// Ignore read failures attempting to discard. |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|