View Javadoc
1   /*
2    * Copyright (C) 2008-2010, Google Inc.
3    * and other copyright owners as documented in the project's IP log.
4    *
5    * This program and the accompanying materials are made available
6    * under the terms of the Eclipse Distribution License v1.0 which
7    * accompanies this distribution, is reproduced below, and is
8    * available at http://www.eclipse.org/org/documents/edl-v10.php
9    *
10   * All rights reserved.
11   *
12   * Redistribution and use in source and binary forms, with or
13   * without modification, are permitted provided that the following
14   * conditions are met:
15   *
16   * - Redistributions of source code must retain the above copyright
17   *   notice, this list of conditions and the following disclaimer.
18   *
19   * - Redistributions in binary form must reproduce the above
20   *   copyright notice, this list of conditions and the following
21   *   disclaimer in the documentation and/or other materials provided
22   *   with the distribution.
23   *
24   * - Neither the name of the Eclipse Foundation, Inc. nor the
25   *   names of its contributors may be used to endorse or promote
26   *   products derived from this software without specific prior
27   *   written permission.
28   *
29   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42   */
43  
44  package org.eclipse.jgit.transport;
45  
46  import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_ATOMIC;
47  import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_DELETE_REFS;
48  import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_OFS_DELTA;
49  import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_PUSH_OPTIONS;
50  import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_QUIET;
51  import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_REPORT_STATUS;
52  import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_SIDE_BAND_64K;
53  import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;
54  import static org.eclipse.jgit.transport.SideBandOutputStream.CH_DATA;
55  import static org.eclipse.jgit.transport.SideBandOutputStream.CH_ERROR;
56  import static org.eclipse.jgit.transport.SideBandOutputStream.CH_PROGRESS;
57  import static org.eclipse.jgit.transport.SideBandOutputStream.MAX_BUF;
58  
59  import java.io.EOFException;
60  import java.io.IOException;
61  import java.io.InputStream;
62  import java.io.OutputStream;
63  import java.text.MessageFormat;
64  import java.util.ArrayList;
65  import java.util.Collections;
66  import java.util.HashSet;
67  import java.util.List;
68  import java.util.Map;
69  import java.util.Set;
70  import java.util.concurrent.TimeUnit;
71  
72  import org.eclipse.jgit.annotations.Nullable;
73  import org.eclipse.jgit.errors.InvalidObjectIdException;
74  import org.eclipse.jgit.errors.MissingObjectException;
75  import org.eclipse.jgit.errors.PackProtocolException;
76  import org.eclipse.jgit.errors.TooLargePackException;
77  import org.eclipse.jgit.internal.JGitText;
78  import org.eclipse.jgit.internal.storage.file.PackLock;
79  import org.eclipse.jgit.lib.BatchRefUpdate;
80  import org.eclipse.jgit.lib.Config;
81  import org.eclipse.jgit.lib.Config.SectionParser;
82  import org.eclipse.jgit.lib.Constants;
83  import org.eclipse.jgit.lib.NullProgressMonitor;
84  import org.eclipse.jgit.lib.ObjectChecker;
85  import org.eclipse.jgit.lib.ObjectId;
86  import org.eclipse.jgit.lib.ObjectIdSubclassMap;
87  import org.eclipse.jgit.lib.ObjectInserter;
88  import org.eclipse.jgit.lib.PersonIdent;
89  import org.eclipse.jgit.lib.ProgressMonitor;
90  import org.eclipse.jgit.lib.Ref;
91  import org.eclipse.jgit.lib.Repository;
92  import org.eclipse.jgit.revwalk.ObjectWalk;
93  import org.eclipse.jgit.revwalk.RevBlob;
94  import org.eclipse.jgit.revwalk.RevCommit;
95  import org.eclipse.jgit.revwalk.RevFlag;
96  import org.eclipse.jgit.revwalk.RevObject;
97  import org.eclipse.jgit.revwalk.RevSort;
98  import org.eclipse.jgit.revwalk.RevTree;
99  import org.eclipse.jgit.revwalk.RevWalk;
100 import org.eclipse.jgit.transport.PacketLineIn.InputOverLimitIOException;
101 import org.eclipse.jgit.transport.ReceiveCommand.Result;
102 import org.eclipse.jgit.util.io.InterruptTimer;
103 import org.eclipse.jgit.util.io.LimitedInputStream;
104 import org.eclipse.jgit.util.io.TimeoutInputStream;
105 import org.eclipse.jgit.util.io.TimeoutOutputStream;
106 
107 /**
108  * Base implementation of the side of a push connection that receives objects.
109  * <p>
110  * Contains high-level operations for initializing and closing streams,
111  * advertising refs, reading commands, and receiving and applying a pack.
112  * Subclasses compose these operations into full service implementations.
113  */
114 public abstract class BaseReceivePack {
115 	/** Data in the first line of a request, the line itself plus capabilities. */
116 	public static class FirstLine {
117 		private final String line;
118 		private final Set<String> capabilities;
119 
120 		/**
121 		 * Parse the first line of a receive-pack request.
122 		 *
123 		 * @param line
124 		 *            line from the client.
125 		 */
126 		public FirstLine(String line) {
127 			final HashSet<String> caps = new HashSet<>();
128 			final int nul = line.indexOf('\0');
129 			if (nul >= 0) {
130 				for (String c : line.substring(nul + 1).split(" ")) //$NON-NLS-1$
131 					caps.add(c);
132 				this.line = line.substring(0, nul);
133 			} else
134 				this.line = line;
135 			this.capabilities = Collections.unmodifiableSet(caps);
136 		}
137 
138 		/** @return non-capabilities part of the line. */
139 		public String getLine() {
140 			return line;
141 		}
142 
143 		/** @return capabilities parsed from the line. */
144 		public Set<String> getCapabilities() {
145 			return capabilities;
146 		}
147 	}
148 
149 	/** Database we write the stored objects into. */
150 	private final Repository db;
151 
152 	/** Revision traversal support over {@link #db}. */
153 	private final RevWalk walk;
154 
155 	/**
156 	 * Is the client connection a bi-directional socket or pipe?
157 	 * <p>
158 	 * If true, this class assumes it can perform multiple read and write cycles
159 	 * with the client over the input and output streams. This matches the
160 	 * functionality available with a standard TCP/IP connection, or a local
161 	 * operating system or in-memory pipe.
162 	 * <p>
163 	 * If false, this class runs in a read everything then output results mode,
164 	 * making it suitable for single round-trip systems RPCs such as HTTP.
165 	 */
166 	private boolean biDirectionalPipe = true;
167 
168 	/** Expecting data after the pack footer */
169 	private boolean expectDataAfterPackFooter;
170 
171 	/** Should an incoming transfer validate objects? */
172 	private ObjectChecker objectChecker;
173 
174 	/** Should an incoming transfer permit create requests? */
175 	private boolean allowCreates;
176 
177 	/** Should an incoming transfer permit delete requests? */
178 	private boolean allowAnyDeletes;
179 	private boolean allowBranchDeletes;
180 
181 	/** Should an incoming transfer permit non-fast-forward requests? */
182 	private boolean allowNonFastForwards;
183 
184 	/** Should an incoming transfer permit push options? **/
185 	private boolean allowPushOptions;
186 
187 	/**
188 	 * Should the requested ref updates be performed as a single atomic
189 	 * transaction?
190 	 */
191 	private boolean atomic;
192 
193 	private boolean allowOfsDelta;
194 	private boolean allowQuiet = true;
195 
196 	/** Identity to record action as within the reflog. */
197 	private PersonIdent refLogIdent;
198 
199 	/** Hook used while advertising the refs to the client. */
200 	private AdvertiseRefsHook advertiseRefsHook;
201 
202 	/** Filter used while advertising the refs to the client. */
203 	private RefFilter refFilter;
204 
205 	/** Timeout in seconds to wait for client interaction. */
206 	private int timeout;
207 
208 	/** Timer to manage {@link #timeout}. */
209 	private InterruptTimer timer;
210 
211 	private TimeoutInputStream timeoutIn;
212 
213 	// Original stream passed to init(), since rawOut may be wrapped in a
214 	// sideband.
215 	private OutputStream origOut;
216 
217 	/** Raw input stream. */
218 	protected InputStream rawIn;
219 
220 	/** Raw output stream. */
221 	protected OutputStream rawOut;
222 
223 	/** Optional message output stream. */
224 	protected OutputStream msgOut;
225 	private SideBandOutputStream errOut;
226 
227 	/** Packet line input stream around {@link #rawIn}. */
228 	protected PacketLineIn pckIn;
229 
230 	/** Packet line output stream around {@link #rawOut}. */
231 	protected PacketLineOut pckOut;
232 
233 	private final MessageOutputWrapper msgOutWrapper = new MessageOutputWrapper();
234 
235 	private PackParser parser;
236 
237 	/** The refs we advertised as existing at the start of the connection. */
238 	private Map<String, Ref> refs;
239 
240 	/** All SHA-1s shown to the client, which can be possible edges. */
241 	private Set<ObjectId> advertisedHaves;
242 
243 	/** Capabilities requested by the client. */
244 	private Set<String> enabledCapabilities;
245 	String userAgent;
246 	private Set<ObjectId> clientShallowCommits;
247 	private List<ReceiveCommand> commands;
248 	private long maxCommandBytes;
249 	private long maxDiscardBytes;
250 
251 	private StringBuilder advertiseError;
252 
253 	/** If {@link BasePackPushConnection#CAPABILITY_SIDE_BAND_64K} is enabled. */
254 	private boolean sideBand;
255 
256 	private boolean quiet;
257 
258 	/** Lock around the received pack file, while updating refs. */
259 	private PackLock packLock;
260 
261 	private boolean checkReferencedIsReachable;
262 
263 	/** Git object size limit */
264 	private long maxObjectSizeLimit;
265 
266 	/** Total pack size limit */
267 	private long maxPackSizeLimit = -1;
268 
269 	/** The size of the received pack, including index size */
270 	private Long packSize;
271 
272 	private PushCertificateParser pushCertificateParser;
273 	private SignedPushConfig signedPushConfig;
274 	private PushCertificate pushCert;
275 	private ReceivedPackStatistics stats;
276 
277 	/**
278 	 * Get the push certificate used to verify the pusher's identity.
279 	 * <p>
280 	 * Only valid after commands are read from the wire.
281 	 *
282 	 * @return the parsed certificate, or null if push certificates are disabled
283 	 *         or no cert was presented by the client.
284 	 * @since 4.1
285 	 */
286 	public PushCertificate getPushCertificate() {
287 		return pushCert;
288 	}
289 
290 	/**
291 	 * Set the push certificate used to verify the pusher's identity.
292 	 * <p>
293 	 * Should only be called if reconstructing an instance without going through
294 	 * the normal {@link #recvCommands()} flow.
295 	 *
296 	 * @param cert
297 	 *            the push certificate to set.
298 	 * @since 4.1
299 	 */
300 	public void setPushCertificate(PushCertificate cert) {
301 		pushCert = cert;
302 	}
303 
304 	/**
305 	 * Create a new pack receive for an open repository.
306 	 *
307 	 * @param into
308 	 *            the destination repository.
309 	 */
310 	protected BaseReceivePack(final Repository into) {
311 		db = into;
312 		walk = new RevWalk(db);
313 
314 		TransferConfig tc = db.getConfig().get(TransferConfig.KEY);
315 		objectChecker = tc.newReceiveObjectChecker();
316 
317 		ReceiveConfig rc = db.getConfig().get(ReceiveConfig.KEY);
318 		allowCreates = rc.allowCreates;
319 		allowAnyDeletes = true;
320 		allowBranchDeletes = rc.allowDeletes;
321 		allowNonFastForwards = rc.allowNonFastForwards;
322 		allowOfsDelta = rc.allowOfsDelta;
323 		allowPushOptions = rc.allowPushOptions;
324 		maxCommandBytes = rc.maxCommandBytes;
325 		maxDiscardBytes = rc.maxDiscardBytes;
326 		advertiseRefsHook = AdvertiseRefsHook.DEFAULT;
327 		refFilter = RefFilter.DEFAULT;
328 		advertisedHaves = new HashSet<>();
329 		clientShallowCommits = new HashSet<>();
330 		signedPushConfig = rc.signedPush;
331 	}
332 
333 	/** Configuration for receive operations. */
334 	protected static class ReceiveConfig {
335 		static final SectionParser<ReceiveConfig> KEY = new SectionParser<ReceiveConfig>() {
336 			@Override
337 			public ReceiveConfig parse(final Config cfg) {
338 				return new ReceiveConfig(cfg);
339 			}
340 		};
341 
342 		final boolean allowCreates;
343 		final boolean allowDeletes;
344 		final boolean allowNonFastForwards;
345 		final boolean allowOfsDelta;
346 		final boolean allowPushOptions;
347 		final long maxCommandBytes;
348 		final long maxDiscardBytes;
349 		final SignedPushConfig signedPush;
350 
351 		ReceiveConfig(final Config config) {
352 			allowCreates = true;
353 			allowDeletes = !config.getBoolean("receive", "denydeletes", false); //$NON-NLS-1$ //$NON-NLS-2$
354 			allowNonFastForwards = !config.getBoolean("receive", //$NON-NLS-1$
355 					"denynonfastforwards", false); //$NON-NLS-1$
356 			allowOfsDelta = config.getBoolean("repack", "usedeltabaseoffset", //$NON-NLS-1$ //$NON-NLS-2$
357 					true);
358 			allowPushOptions = config.getBoolean("receive", "pushoptions", //$NON-NLS-1$ //$NON-NLS-2$
359 					false);
360 			maxCommandBytes = config.getLong("receive", //$NON-NLS-1$
361 					"maxCommandBytes", //$NON-NLS-1$
362 					3 << 20);
363 			maxDiscardBytes = config.getLong("receive", //$NON-NLS-1$
364 					"maxCommandDiscardBytes", //$NON-NLS-1$
365 					-1);
366 			signedPush = SignedPushConfig.KEY.parse(config);
367 		}
368 	}
369 
370 	/**
371 	 * Output stream that wraps the current {@link #msgOut}.
372 	 * <p>
373 	 * We don't want to expose {@link #msgOut} directly because it can change
374 	 * several times over the course of a session.
375 	 */
376 	class MessageOutputWrapper extends OutputStream {
377 		@Override
378 		public void write(int ch) {
379 			if (msgOut != null) {
380 				try {
381 					msgOut.write(ch);
382 				} catch (IOException e) {
383 					// Ignore write failures.
384 				}
385 			}
386 		}
387 
388 		@Override
389 		public void write(byte[] b, int off, int len) {
390 			if (msgOut != null) {
391 				try {
392 					msgOut.write(b, off, len);
393 				} catch (IOException e) {
394 					// Ignore write failures.
395 				}
396 			}
397 		}
398 
399 		@Override
400 		public void write(byte[] b) {
401 			write(b, 0, b.length);
402 		}
403 
404 		@Override
405 		public void flush() {
406 			if (msgOut != null) {
407 				try {
408 					msgOut.flush();
409 				} catch (IOException e) {
410 					// Ignore write failures.
411 				}
412 			}
413 		}
414 	}
415 
416 	/** @return the process name used for pack lock messages. */
417 	protected abstract String getLockMessageProcessName();
418 
419 	/** @return the repository this receive completes into. */
420 	public final Repository getRepository() {
421 		return db;
422 	}
423 
424 	/** @return the RevWalk instance used by this connection. */
425 	public final RevWalk getRevWalk() {
426 		return walk;
427 	}
428 
429 	/**
430 	 * Get refs which were advertised to the client.
431 	 *
432 	 * @return all refs which were advertised to the client, or null if
433 	 *         {@link #setAdvertisedRefs(Map, Set)} has not been called yet.
434 	 */
435 	public final Map<String, Ref> getAdvertisedRefs() {
436 		return refs;
437 	}
438 
439 	/**
440 	 * Set the refs advertised by this ReceivePack.
441 	 * <p>
442 	 * Intended to be called from a {@link PreReceiveHook}.
443 	 *
444 	 * @param allRefs
445 	 *            explicit set of references to claim as advertised by this
446 	 *            ReceivePack instance. This overrides any references that
447 	 *            may exist in the source repository. The map is passed
448 	 *            to the configured {@link #getRefFilter()}. If null, assumes
449 	 *            all refs were advertised.
450 	 * @param additionalHaves
451 	 *            explicit set of additional haves to claim as advertised. If
452 	 *            null, assumes the default set of additional haves from the
453 	 *            repository.
454 	 */
455 	public void setAdvertisedRefs(Map<String, Ref> allRefs, Set<ObjectId> additionalHaves) {
456 		refs = allRefs != null ? allRefs : db.getAllRefs();
457 		refs = refFilter.filter(refs);
458 
459 		Ref head = refs.get(Constants.HEAD);
460 		if (head != null && head.isSymbolic())
461 			refs.remove(Constants.HEAD);
462 
463 		for (Ref ref : refs.values()) {
464 			if (ref.getObjectId() != null)
465 				advertisedHaves.add(ref.getObjectId());
466 		}
467 		if (additionalHaves != null)
468 			advertisedHaves.addAll(additionalHaves);
469 		else
470 			advertisedHaves.addAll(db.getAdditionalHaves());
471 	}
472 
473 	/**
474 	 * Get objects advertised to the client.
475 	 *
476 	 * @return the set of objects advertised to the as present in this repository,
477 	 *         or null if {@link #setAdvertisedRefs(Map, Set)} has not been called
478 	 *         yet.
479 	 */
480 	public final Set<ObjectId> getAdvertisedObjects() {
481 		return advertisedHaves;
482 	}
483 
484 	/**
485 	 * @return true if this instance will validate all referenced, but not
486 	 *         supplied by the client, objects are reachable from another
487 	 *         reference.
488 	 */
489 	public boolean isCheckReferencedObjectsAreReachable() {
490 		return checkReferencedIsReachable;
491 	}
492 
493 	/**
494 	 * Validate all referenced but not supplied objects are reachable.
495 	 * <p>
496 	 * If enabled, this instance will verify that references to objects not
497 	 * contained within the received pack are already reachable through at least
498 	 * one other reference displayed as part of {@link #getAdvertisedRefs()}.
499 	 * <p>
500 	 * This feature is useful when the application doesn't trust the client to
501 	 * not provide a forged SHA-1 reference to an object, in an attempt to
502 	 * access parts of the DAG that they aren't allowed to see and which have
503 	 * been hidden from them via the configured {@link AdvertiseRefsHook} or
504 	 * {@link RefFilter}.
505 	 * <p>
506 	 * Enabling this feature may imply at least some, if not all, of the same
507 	 * functionality performed by {@link #setCheckReceivedObjects(boolean)}.
508 	 * Applications are encouraged to enable both features, if desired.
509 	 *
510 	 * @param b
511 	 *            {@code true} to enable the additional check.
512 	 */
513 	public void setCheckReferencedObjectsAreReachable(boolean b) {
514 		this.checkReferencedIsReachable = b;
515 	}
516 
517 	/**
518 	 * @return true if this class expects a bi-directional pipe opened between
519 	 *         the client and itself. The default is true.
520 	 */
521 	public boolean isBiDirectionalPipe() {
522 		return biDirectionalPipe;
523 	}
524 
525 	/**
526 	 * @param twoWay
527 	 *            if true, this class will assume the socket is a fully
528 	 *            bidirectional pipe between the two peers and takes advantage
529 	 *            of that by first transmitting the known refs, then waiting to
530 	 *            read commands. If false, this class assumes it must read the
531 	 *            commands before writing output and does not perform the
532 	 *            initial advertising.
533 	 */
534 	public void setBiDirectionalPipe(final boolean twoWay) {
535 		biDirectionalPipe = twoWay;
536 	}
537 
538 	/** @return true if there is data expected after the pack footer. */
539 	public boolean isExpectDataAfterPackFooter() {
540 		return expectDataAfterPackFooter;
541 	}
542 
543 	/**
544 	 * @param e
545 	 *            true if there is additional data in InputStream after pack.
546 	 */
547 	public void setExpectDataAfterPackFooter(boolean e) {
548 		expectDataAfterPackFooter = e;
549 	}
550 
551 	/**
552 	 * @return true if this instance will verify received objects are formatted
553 	 *         correctly. Validating objects requires more CPU time on this side
554 	 *         of the connection.
555 	 */
556 	public boolean isCheckReceivedObjects() {
557 		return objectChecker != null;
558 	}
559 
560 	/**
561 	 * @param check
562 	 *            true to enable checking received objects; false to assume all
563 	 *            received objects are valid.
564 	 * @see #setObjectChecker(ObjectChecker)
565 	 */
566 	public void setCheckReceivedObjects(final boolean check) {
567 		if (check && objectChecker == null)
568 			setObjectChecker(new ObjectChecker());
569 		else if (!check && objectChecker != null)
570 			setObjectChecker(null);
571 	}
572 
573 	/**
574 	 * @param impl if non-null the object checking instance to verify each
575 	 *        received object with; null to disable object checking.
576 	 * @since 3.4
577 	 */
578 	public void setObjectChecker(ObjectChecker impl) {
579 		objectChecker = impl;
580 	}
581 
582 	/** @return true if the client can request refs to be created. */
583 	public boolean isAllowCreates() {
584 		return allowCreates;
585 	}
586 
587 	/**
588 	 * @param canCreate
589 	 *            true to permit create ref commands to be processed.
590 	 */
591 	public void setAllowCreates(final boolean canCreate) {
592 		allowCreates = canCreate;
593 	}
594 
595 	/** @return true if the client can request refs to be deleted. */
596 	public boolean isAllowDeletes() {
597 		return allowAnyDeletes;
598 	}
599 
600 	/**
601 	 * @param canDelete
602 	 *            true to permit delete ref commands to be processed.
603 	 */
604 	public void setAllowDeletes(final boolean canDelete) {
605 		allowAnyDeletes = canDelete;
606 	}
607 
608 	/**
609 	 * @return true if the client can delete from {@code refs/heads/}.
610 	 * @since 3.6
611 	 */
612 	public boolean isAllowBranchDeletes() {
613 		return allowBranchDeletes;
614 	}
615 
616 	/**
617 	 * @param canDelete
618 	 *            true to permit deletion of branches from the
619 	 *            {@code refs/heads/} namespace.
620 	 * @since 3.6
621 	 */
622 	public void setAllowBranchDeletes(boolean canDelete) {
623 		allowBranchDeletes = canDelete;
624 	}
625 
626 	/**
627 	 * @return true if the client can request non-fast-forward updates of a ref,
628 	 *         possibly making objects unreachable.
629 	 */
630 	public boolean isAllowNonFastForwards() {
631 		return allowNonFastForwards;
632 	}
633 
634 	/**
635 	 * @param canRewind
636 	 *            true to permit the client to ask for non-fast-forward updates
637 	 *            of an existing ref.
638 	 */
639 	public void setAllowNonFastForwards(final boolean canRewind) {
640 		allowNonFastForwards = canRewind;
641 	}
642 
643 	/**
644 	 * @return true if the client's commands should be performed as a single
645 	 *         atomic transaction.
646 	 * @since 4.4
647 	 */
648 	public boolean isAtomic() {
649 		return atomic;
650 	}
651 
652 	/**
653 	 * @param atomic
654 	 *            true to perform the client's commands as a single atomic
655 	 *            transaction.
656 	 * @since 4.4
657 	 */
658 	public void setAtomic(boolean atomic) {
659 		this.atomic = atomic;
660 	}
661 
662 	/** @return identity of the user making the changes in the reflog. */
663 	public PersonIdent getRefLogIdent() {
664 		return refLogIdent;
665 	}
666 
667 	/**
668 	 * Set the identity of the user appearing in the affected reflogs.
669 	 * <p>
670 	 * The timestamp portion of the identity is ignored. A new identity with the
671 	 * current timestamp will be created automatically when the updates occur
672 	 * and the log records are written.
673 	 *
674 	 * @param pi
675 	 *            identity of the user. If null the identity will be
676 	 *            automatically determined based on the repository
677 	 *            configuration.
678 	 */
679 	public void setRefLogIdent(final PersonIdent pi) {
680 		refLogIdent = pi;
681 	}
682 
683 	/** @return the hook used while advertising the refs to the client */
684 	public AdvertiseRefsHook getAdvertiseRefsHook() {
685 		return advertiseRefsHook;
686 	}
687 
688 	/** @return the filter used while advertising the refs to the client */
689 	public RefFilter getRefFilter() {
690 		return refFilter;
691 	}
692 
693 	/**
694 	 * Set the hook used while advertising the refs to the client.
695 	 * <p>
696 	 * If the {@link AdvertiseRefsHook} chooses to call
697 	 * {@link #setAdvertisedRefs(Map,Set)}, only refs set by this hook
698 	 * <em>and</em> selected by the {@link RefFilter} will be shown to the client.
699 	 * Clients may still attempt to create or update a reference not advertised by
700 	 * the configured {@link AdvertiseRefsHook}. These attempts should be rejected
701 	 * by a matching {@link PreReceiveHook}.
702 	 *
703 	 * @param advertiseRefsHook
704 	 *            the hook; may be null to show all refs.
705 	 */
706 	public void setAdvertiseRefsHook(final AdvertiseRefsHook advertiseRefsHook) {
707 		if (advertiseRefsHook != null)
708 			this.advertiseRefsHook = advertiseRefsHook;
709 		else
710 			this.advertiseRefsHook = AdvertiseRefsHook.DEFAULT;
711 	}
712 
713 	/**
714 	 * Set the filter used while advertising the refs to the client.
715 	 * <p>
716 	 * Only refs allowed by this filter will be shown to the client.
717 	 * The filter is run against the refs specified by the
718 	 * {@link AdvertiseRefsHook} (if applicable).
719 	 *
720 	 * @param refFilter
721 	 *            the filter; may be null to show all refs.
722 	 */
723 	public void setRefFilter(final RefFilter refFilter) {
724 		this.refFilter = refFilter != null ? refFilter : RefFilter.DEFAULT;
725 	}
726 
727 	/** @return timeout (in seconds) before aborting an IO operation. */
728 	public int getTimeout() {
729 		return timeout;
730 	}
731 
732 	/**
733 	 * Set the timeout before willing to abort an IO call.
734 	 *
735 	 * @param seconds
736 	 *            number of seconds to wait (with no data transfer occurring)
737 	 *            before aborting an IO read or write operation with the
738 	 *            connected client.
739 	 */
740 	public void setTimeout(final int seconds) {
741 		timeout = seconds;
742 	}
743 
744 	/**
745 	 * Set the maximum number of command bytes to read from the client.
746 	 *
747 	 * @param limit
748 	 *            command limit in bytes; if 0 there is no limit.
749 	 * @since 4.7
750 	 */
751 	public void setMaxCommandBytes(long limit) {
752 		maxCommandBytes = limit;
753 	}
754 
755 	/**
756 	 * Set the maximum number of command bytes to discard from the client.
757 	 * <p>
758 	 * Discarding remaining bytes allows this instance to consume the rest of
759 	 * the command block and send a human readable over-limit error via the
760 	 * side-band channel. If the client sends an excessive number of bytes this
761 	 * limit kicks in and the instance disconnects, resulting in a non-specific
762 	 * 'pipe closed', 'end of stream', or similar generic error at the client.
763 	 * <p>
764 	 * When the limit is set to {@code -1} the implementation will default to
765 	 * the larger of {@code 3 * maxCommandBytes} or {@code 3 MiB}.
766 	 *
767 	 * @param limit
768 	 *            discard limit in bytes; if 0 there is no limit; if -1 the
769 	 *            implementation tries to set a reasonable default.
770 	 * @since 4.7
771 	 */
772 	public void setMaxCommandDiscardBytes(long limit) {
773 		maxDiscardBytes = limit;
774 	}
775 
776 	/**
777 	 * Set the maximum allowed Git object size.
778 	 * <p>
779 	 * If an object is larger than the given size the pack-parsing will throw an
780 	 * exception aborting the receive-pack operation.
781 	 *
782 	 * @param limit
783 	 *            the Git object size limit. If zero then there is not limit.
784 	 */
785 	public void setMaxObjectSizeLimit(final long limit) {
786 		maxObjectSizeLimit = limit;
787 	}
788 
789 	/**
790 	 * Set the maximum allowed pack size.
791 	 * <p>
792 	 * A pack exceeding this size will be rejected.
793 	 *
794 	 * @param limit
795 	 *            the pack size limit, in bytes
796 	 *
797 	 * @since 3.3
798 	 */
799 	public void setMaxPackSizeLimit(final long limit) {
800 		if (limit < 0)
801 			throw new IllegalArgumentException(MessageFormat.format(
802 					JGitText.get().receivePackInvalidLimit, Long.valueOf(limit)));
803 		maxPackSizeLimit = limit;
804 	}
805 
806 	/**
807 	 * Check whether the client expects a side-band stream.
808 	 *
809 	 * @return true if the client has advertised a side-band capability, false
810 	 *     otherwise.
811 	 * @throws RequestNotYetReadException
812 	 *             if the client's request has not yet been read from the wire, so
813 	 *             we do not know if they expect side-band. Note that the client
814 	 *             may have already written the request, it just has not been
815 	 *             read.
816 	 */
817 	public boolean isSideBand() throws RequestNotYetReadException {
818 		checkRequestWasRead();
819 		return enabledCapabilities.contains(CAPABILITY_SIDE_BAND_64K);
820 	}
821 
822 	/**
823 	 * @return true if clients may request avoiding noisy progress messages.
824 	 * @since 4.0
825 	 */
826 	public boolean isAllowQuiet() {
827 		return allowQuiet;
828 	}
829 
830 	/**
831 	 * Configure if clients may request the server skip noisy messages.
832 	 *
833 	 * @param allow
834 	 *            true to allow clients to request quiet behavior; false to
835 	 *            refuse quiet behavior and send messages anyway. This may be
836 	 *            necessary if processing is slow and the client-server network
837 	 *            connection can timeout.
838 	 * @since 4.0
839 	 */
840 	public void setAllowQuiet(boolean allow) {
841 		allowQuiet = allow;
842 	}
843 
844 	/**
845 	 * @return true if the server supports receiving push options.
846 	 * @since 4.5
847 	 */
848 	public boolean isAllowPushOptions() {
849 		return allowPushOptions;
850 	}
851 
852 	/**
853 	 * Configure if the server supports receiving push options.
854 	 *
855 	 * @param allow
856 	 *            true to optionally accept option strings from the client.
857 	 * @since 4.5
858 	 */
859 	public void setAllowPushOptions(boolean allow) {
860 		allowPushOptions = allow;
861 	}
862 
863 	/**
864 	 * True if the client wants less verbose output.
865 	 *
866 	 * @return true if the client has requested the server to be less verbose.
867 	 * @throws RequestNotYetReadException
868 	 *             if the client's request has not yet been read from the wire,
869 	 *             so we do not know if they expect side-band. Note that the
870 	 *             client may have already written the request, it just has not
871 	 *             been read.
872 	 * @since 4.0
873 	 */
874 	public boolean isQuiet() throws RequestNotYetReadException {
875 		checkRequestWasRead();
876 		return quiet;
877 	}
878 
879 	/**
880 	 * Set the configuration for push certificate verification.
881 	 *
882 	 * @param cfg
883 	 *            new configuration; if this object is null or its {@link
884 	 *            SignedPushConfig#getCertNonceSeed()} is null, push certificate
885 	 *            verification will be disabled.
886 	 * @since 4.1
887 	 */
888 	public void setSignedPushConfig(SignedPushConfig cfg) {
889 		signedPushConfig = cfg;
890 	}
891 
892 	private PushCertificateParser getPushCertificateParser() {
893 		if (pushCertificateParser == null) {
894 			pushCertificateParser = new PushCertificateParser(db, signedPushConfig);
895 		}
896 		return pushCertificateParser;
897 	}
898 
899 	/**
900 	 * Get the user agent of the client.
901 	 * <p>
902 	 * If the client is new enough to use {@code agent=} capability that value
903 	 * will be returned. Older HTTP clients may also supply their version using
904 	 * the HTTP {@code User-Agent} header. The capability overrides the HTTP
905 	 * header if both are available.
906 	 * <p>
907 	 * When an HTTP request has been received this method returns the HTTP
908 	 * {@code User-Agent} header value until capabilities have been parsed.
909 	 *
910 	 * @return user agent supplied by the client. Available only if the client
911 	 *         is new enough to advertise its user agent.
912 	 * @since 4.0
913 	 */
914 	public String getPeerUserAgent() {
915 		return UserAgent.getAgent(enabledCapabilities, userAgent);
916 	}
917 
918 	/** @return all of the command received by the current request. */
919 	public List<ReceiveCommand> getAllCommands() {
920 		return Collections.unmodifiableList(commands);
921 	}
922 
923 	/**
924 	 * Send an error message to the client.
925 	 * <p>
926 	 * If any error messages are sent before the references are advertised to
927 	 * the client, the errors will be sent instead of the advertisement and the
928 	 * receive operation will be aborted. All clients should receive and display
929 	 * such early stage errors.
930 	 * <p>
931 	 * If the reference advertisements have already been sent, messages are sent
932 	 * in a side channel. If the client doesn't support receiving messages, the
933 	 * message will be discarded, with no other indication to the caller or to
934 	 * the client.
935 	 * <p>
936 	 * {@link PreReceiveHook}s should always try to use
937 	 * {@link ReceiveCommand#setResult(Result, String)} with a result status of
938 	 * {@link Result#REJECTED_OTHER_REASON} to indicate any reasons for
939 	 * rejecting an update. Messages attached to a command are much more likely
940 	 * to be returned to the client.
941 	 *
942 	 * @param what
943 	 *            string describing the problem identified by the hook. The
944 	 *            string must not end with an LF, and must not contain an LF.
945 	 */
946 	public void sendError(final String what) {
947 		if (refs == null) {
948 			if (advertiseError == null)
949 				advertiseError = new StringBuilder();
950 			advertiseError.append(what).append('\n');
951 		} else {
952 			msgOutWrapper.write(Constants.encode("error: " + what + "\n")); //$NON-NLS-1$ //$NON-NLS-2$
953 		}
954 	}
955 
956 	private void fatalError(String msg) {
957 		if (errOut != null) {
958 			try {
959 				errOut.write(Constants.encode(msg));
960 				errOut.flush();
961 			} catch (IOException e) {
962 				// Ignore write failures
963 			}
964 		} else {
965 			sendError(msg);
966 		}
967 	}
968 
969 	/**
970 	 * Send a message to the client, if it supports receiving them.
971 	 * <p>
972 	 * If the client doesn't support receiving messages, the message will be
973 	 * discarded, with no other indication to the caller or to the client.
974 	 *
975 	 * @param what
976 	 *            string describing the problem identified by the hook. The
977 	 *            string must not end with an LF, and must not contain an LF.
978 	 */
979 	public void sendMessage(final String what) {
980 		msgOutWrapper.write(Constants.encode(what + "\n")); //$NON-NLS-1$
981 	}
982 
983 	/** @return an underlying stream for sending messages to the client. */
984 	public OutputStream getMessageOutputStream() {
985 		return msgOutWrapper;
986 	}
987 
988 	/**
989 	 * Get the size of the received pack file including the index size.
990 	 *
991 	 * This can only be called if the pack is already received.
992 	 *
993 	 * @return the size of the received pack including index size
994 	 * @throws IllegalStateException
995 	 *             if called before the pack has been received
996 	 * @since 3.3
997 	 */
998 	public long getPackSize() {
999 		if (packSize != null)
1000 			return packSize.longValue();
1001 		throw new IllegalStateException(JGitText.get().packSizeNotSetYet);
1002 	}
1003 
1004 	/**
1005 	 * Get the commits from the client's shallow file.
1006 	 *
1007 	 * @return if the client is a shallow repository, the list of edge commits
1008 	 *     that define the client's shallow boundary. Empty set if the client
1009 	 *     is earlier than Git 1.9, or is a full clone.
1010 	 * @since 3.5
1011 	 */
1012 	protected Set<ObjectId> getClientShallowCommits() {
1013 		return clientShallowCommits;
1014 	}
1015 
1016 	/** @return true if any commands to be executed have been read. */
1017 	protected boolean hasCommands() {
1018 		return !commands.isEmpty();
1019 	}
1020 
1021 	/** @return true if an error occurred that should be advertised. */
1022 	protected boolean hasError() {
1023 		return advertiseError != null;
1024 	}
1025 
1026 	/**
1027 	 * Initialize the instance with the given streams.
1028 	 *
1029 	 * @param input
1030 	 *            raw input to read client commands and pack data from. Caller
1031 	 *            must ensure the input is buffered, otherwise read performance
1032 	 *            may suffer.
1033 	 * @param output
1034 	 *            response back to the Git network client. Caller must ensure
1035 	 *            the output is buffered, otherwise write performance may
1036 	 *            suffer.
1037 	 * @param messages
1038 	 *            secondary "notice" channel to send additional messages out
1039 	 *            through. When run over SSH this should be tied back to the
1040 	 *            standard error channel of the command execution. For most
1041 	 *            other network connections this should be null.
1042 	 */
1043 	protected void init(final InputStream input, final OutputStream output,
1044 			final OutputStream messages) {
1045 		origOut = output;
1046 		rawIn = input;
1047 		rawOut = output;
1048 		msgOut = messages;
1049 
1050 		if (timeout > 0) {
1051 			final Thread caller = Thread.currentThread();
1052 			timer = new InterruptTimer(caller.getName() + "-Timer"); //$NON-NLS-1$
1053 			timeoutIn = new TimeoutInputStream(rawIn, timer);
1054 			TimeoutOutputStream o = new TimeoutOutputStream(rawOut, timer);
1055 			timeoutIn.setTimeout(timeout * 1000);
1056 			o.setTimeout(timeout * 1000);
1057 			rawIn = timeoutIn;
1058 			rawOut = o;
1059 		}
1060 
1061 		pckIn = new PacketLineIn(rawIn);
1062 		pckOut = new PacketLineOut(rawOut);
1063 		pckOut.setFlushOnEnd(false);
1064 
1065 		enabledCapabilities = new HashSet<>();
1066 		commands = new ArrayList<>();
1067 	}
1068 
1069 	/** @return advertised refs, or the default if not explicitly advertised. */
1070 	protected Map<String, Ref> getAdvertisedOrDefaultRefs() {
1071 		if (refs == null)
1072 			setAdvertisedRefs(null, null);
1073 		return refs;
1074 	}
1075 
1076 	/**
1077 	 * Receive a pack from the stream and check connectivity if necessary.
1078 	 *
1079 	 * @throws IOException
1080 	 *             an error occurred during unpacking or connectivity checking.
1081 	 */
1082 	protected void receivePackAndCheckConnectivity() throws IOException {
1083 		receivePack();
1084 		if (needCheckConnectivity())
1085 			checkConnectivity();
1086 		parser = null;
1087 	}
1088 
1089 	/**
1090 	 * Unlock the pack written by this object.
1091 	 *
1092 	 * @throws IOException
1093 	 *             the pack could not be unlocked.
1094 	 */
1095 	protected void unlockPack() throws IOException {
1096 		if (packLock != null) {
1097 			packLock.unlock();
1098 			packLock = null;
1099 		}
1100 	}
1101 
1102 	/**
1103 	 * Generate an advertisement of available refs and capabilities.
1104 	 *
1105 	 * @param adv
1106 	 *            the advertisement formatter.
1107 	 * @throws IOException
1108 	 *             the formatter failed to write an advertisement.
1109 	 * @throws ServiceMayNotContinueException
1110 	 *             the hook denied advertisement.
1111 	 */
1112 	public void sendAdvertisedRefs(final RefAdvertiser adv)
1113 			throws IOException, ServiceMayNotContinueException {
1114 		if (advertiseError != null) {
1115 			adv.writeOne("ERR " + advertiseError); //$NON-NLS-1$
1116 			return;
1117 		}
1118 
1119 		try {
1120 			advertiseRefsHook.advertiseRefs(this);
1121 		} catch (ServiceMayNotContinueException fail) {
1122 			if (fail.getMessage() != null) {
1123 				adv.writeOne("ERR " + fail.getMessage()); //$NON-NLS-1$
1124 				fail.setOutput();
1125 			}
1126 			throw fail;
1127 		}
1128 
1129 		adv.init(db);
1130 		adv.advertiseCapability(CAPABILITY_SIDE_BAND_64K);
1131 		adv.advertiseCapability(CAPABILITY_DELETE_REFS);
1132 		adv.advertiseCapability(CAPABILITY_REPORT_STATUS);
1133 		if (allowQuiet)
1134 			adv.advertiseCapability(CAPABILITY_QUIET);
1135 		String nonce = getPushCertificateParser().getAdvertiseNonce();
1136 		if (nonce != null) {
1137 			adv.advertiseCapability(nonce);
1138 		}
1139 		if (db.getRefDatabase().performsAtomicTransactions())
1140 			adv.advertiseCapability(CAPABILITY_ATOMIC);
1141 		if (allowOfsDelta)
1142 			adv.advertiseCapability(CAPABILITY_OFS_DELTA);
1143 		if (allowPushOptions) {
1144 			adv.advertiseCapability(CAPABILITY_PUSH_OPTIONS);
1145 		}
1146 		adv.advertiseCapability(OPTION_AGENT, UserAgent.get());
1147 		adv.send(getAdvertisedOrDefaultRefs());
1148 		for (ObjectId obj : advertisedHaves)
1149 			adv.advertiseHave(obj);
1150 		if (adv.isEmpty())
1151 			adv.advertiseId(ObjectId.zeroId(), "capabilities^{}"); //$NON-NLS-1$
1152 		adv.end();
1153 	}
1154 
1155 	/**
1156 	 * Returns the statistics on the received pack if available. This should be
1157 	 * called after {@link #receivePack} is called.
1158 	 *
1159 	 * @return ReceivedPackStatistics
1160 	 * @since 4.6
1161 	 */
1162 	@Nullable
1163 	public ReceivedPackStatistics getReceivedPackStatistics() {
1164 		return stats;
1165 	}
1166 
1167 	/**
1168 	 * Receive a list of commands from the input.
1169 	 *
1170 	 * @throws IOException
1171 	 */
1172 	protected void recvCommands() throws IOException {
1173 		PacketLineIn pck = maxCommandBytes > 0
1174 				? new PacketLineIn(rawIn, maxCommandBytes)
1175 				: pckIn;
1176 		PushCertificateParser certParser = getPushCertificateParser();
1177 		boolean firstPkt = true;
1178 		try {
1179 			for (;;) {
1180 				String line;
1181 				try {
1182 					line = pck.readString();
1183 				} catch (EOFException eof) {
1184 					if (commands.isEmpty())
1185 						return;
1186 					throw eof;
1187 				}
1188 				if (line == PacketLineIn.END) {
1189 					break;
1190 				}
1191 
1192 				if (line.length() >= 48 && line.startsWith("shallow ")) { //$NON-NLS-1$
1193 					parseShallow(line.substring(8, 48));
1194 					continue;
1195 				}
1196 
1197 				if (firstPkt) {
1198 					firstPkt = false;
1199 					FirstLine firstLine = new FirstLine(line);
1200 					enabledCapabilities = firstLine.getCapabilities();
1201 					line = firstLine.getLine();
1202 					enableCapabilities();
1203 
1204 					if (line.equals(GitProtocolConstants.OPTION_PUSH_CERT)) {
1205 						certParser.receiveHeader(pck, !isBiDirectionalPipe());
1206 						continue;
1207 					}
1208 				}
1209 
1210 				if (line.equals(PushCertificateParser.BEGIN_SIGNATURE)) {
1211 					certParser.receiveSignature(pck);
1212 					continue;
1213 				}
1214 
1215 				ReceiveCommand cmd = parseCommand(line);
1216 				if (cmd.getRefName().equals(Constants.HEAD)) {
1217 					cmd.setResult(Result.REJECTED_CURRENT_BRANCH);
1218 				} else {
1219 					cmd.setRef(refs.get(cmd.getRefName()));
1220 				}
1221 				commands.add(cmd);
1222 				if (certParser.enabled()) {
1223 					certParser.addCommand(cmd);
1224 				}
1225 			}
1226 			pushCert = certParser.build();
1227 			if (hasCommands()) {
1228 				readPostCommands(pck);
1229 			}
1230 		} catch (PackProtocolException e) {
1231 			discardCommands();
1232 			fatalError(e.getMessage());
1233 			throw e;
1234 		} catch (InputOverLimitIOException e) {
1235 			String msg = JGitText.get().tooManyCommands;
1236 			discardCommands();
1237 			fatalError(msg);
1238 			throw new PackProtocolException(msg);
1239 		}
1240 	}
1241 
1242 	private void discardCommands() {
1243 		if (sideBand) {
1244 			long max = maxDiscardBytes;
1245 			if (max < 0) {
1246 				max = Math.max(3 * maxCommandBytes, 3L << 20);
1247 			}
1248 			try {
1249 				new PacketLineIn(rawIn, max).discardUntilEnd();
1250 			} catch (IOException e) {
1251 				// Ignore read failures attempting to discard.
1252 			}
1253 		}
1254 	}
1255 
1256 	private void parseShallow(String idStr) throws PackProtocolException {
1257 		ObjectId id;
1258 		try {
1259 			id = ObjectId.fromString(idStr);
1260 		} catch (InvalidObjectIdException e) {
1261 			throw new PackProtocolException(e.getMessage(), e);
1262 		}
1263 		clientShallowCommits.add(id);
1264 	}
1265 
1266 	static ReceiveCommand parseCommand(String line) throws PackProtocolException {
1267           if (line == null || line.length() < 83) {
1268 			throw new PackProtocolException(
1269 					JGitText.get().errorInvalidProtocolWantedOldNewRef);
1270 		}
1271 		String oldStr = line.substring(0, 40);
1272 		String newStr = line.substring(41, 81);
1273 		ObjectId oldId, newId;
1274 		try {
1275 			oldId = ObjectId.fromString(oldStr);
1276 			newId = ObjectId.fromString(newStr);
1277 		} catch (InvalidObjectIdException e) {
1278 			throw new PackProtocolException(
1279 					JGitText.get().errorInvalidProtocolWantedOldNewRef, e);
1280 		}
1281 		String name = line.substring(82);
1282 		if (!Repository.isValidRefName(name)) {
1283 			throw new PackProtocolException(
1284 					JGitText.get().errorInvalidProtocolWantedOldNewRef);
1285 		}
1286 		return new ReceiveCommand(oldId, newId, name);
1287 	}
1288 
1289 	/**
1290 	 * @param in
1291 	 *            request stream.
1292 	 * @throws IOException
1293 	 *             request line cannot be read.
1294 	 */
1295 	void readPostCommands(PacketLineIn in) throws IOException {
1296 		// Do nothing by default.
1297 	}
1298 
1299 	/** Enable capabilities based on a previously read capabilities line. */
1300 	protected void enableCapabilities() {
1301 		sideBand = isCapabilityEnabled(CAPABILITY_SIDE_BAND_64K);
1302 		quiet = allowQuiet && isCapabilityEnabled(CAPABILITY_QUIET);
1303 		if (sideBand) {
1304 			OutputStream out = rawOut;
1305 
1306 			rawOut = new SideBandOutputStream(CH_DATA, MAX_BUF, out);
1307 			msgOut = new SideBandOutputStream(CH_PROGRESS, MAX_BUF, out);
1308 			errOut = new SideBandOutputStream(CH_ERROR, MAX_BUF, out);
1309 
1310 			pckOut = new PacketLineOut(rawOut);
1311 			pckOut.setFlushOnEnd(false);
1312 		}
1313 	}
1314 
1315 	/**
1316 	 * Check if the peer requested a capability.
1317 	 *
1318 	 * @param name
1319 	 *            protocol name identifying the capability.
1320 	 * @return true if the peer requested the capability to be enabled.
1321 	 */
1322 	protected boolean isCapabilityEnabled(String name) {
1323 		return enabledCapabilities.contains(name);
1324 	}
1325 
1326 	void checkRequestWasRead() {
1327 		if (enabledCapabilities == null)
1328 			throw new RequestNotYetReadException();
1329 	}
1330 
1331 	/** @return true if a pack is expected based on the list of commands. */
1332 	protected boolean needPack() {
1333 		for (final ReceiveCommand cmd : commands) {
1334 			if (cmd.getType() != ReceiveCommand.Type.DELETE)
1335 				return true;
1336 		}
1337 		return false;
1338 	}
1339 
1340 	/**
1341 	 * Receive a pack from the input and store it in the repository.
1342 	 *
1343 	 * @throws IOException
1344 	 *             an error occurred reading or indexing the pack.
1345 	 */
1346 	private void receivePack() throws IOException {
1347 		// It might take the client a while to pack the objects it needs
1348 		// to send to us.  We should increase our timeout so we don't
1349 		// abort while the client is computing.
1350 		//
1351 		if (timeoutIn != null)
1352 			timeoutIn.setTimeout(10 * timeout * 1000);
1353 
1354 		ProgressMonitor receiving = NullProgressMonitor.INSTANCE;
1355 		ProgressMonitor resolving = NullProgressMonitor.INSTANCE;
1356 		if (sideBand && !quiet)
1357 			resolving = new SideBandProgressMonitor(msgOut);
1358 
1359 		try (ObjectInserter ins = db.newObjectInserter()) {
1360 			String lockMsg = "jgit receive-pack"; //$NON-NLS-1$
1361 			if (getRefLogIdent() != null)
1362 				lockMsg += " from " + getRefLogIdent().toExternalString(); //$NON-NLS-1$
1363 
1364 			parser = ins.newPackParser(packInputStream());
1365 			parser.setAllowThin(true);
1366 			parser.setNeedNewObjectIds(checkReferencedIsReachable);
1367 			parser.setNeedBaseObjectIds(checkReferencedIsReachable);
1368 			parser.setCheckEofAfterPackFooter(!biDirectionalPipe
1369 					&& !isExpectDataAfterPackFooter());
1370 			parser.setExpectDataAfterPackFooter(isExpectDataAfterPackFooter());
1371 			parser.setObjectChecker(objectChecker);
1372 			parser.setLockMessage(lockMsg);
1373 			parser.setMaxObjectSizeLimit(maxObjectSizeLimit);
1374 			packLock = parser.parse(receiving, resolving);
1375 			packSize = Long.valueOf(parser.getPackSize());
1376 			stats = parser.getReceivedPackStatistics();
1377 			ins.flush();
1378 		}
1379 
1380 		if (timeoutIn != null)
1381 			timeoutIn.setTimeout(timeout * 1000);
1382 	}
1383 
1384 	private InputStream packInputStream() {
1385 		InputStream packIn = rawIn;
1386 		if (maxPackSizeLimit >= 0) {
1387 			packIn = new LimitedInputStream(packIn, maxPackSizeLimit) {
1388 				@Override
1389 				protected void limitExceeded() throws TooLargePackException {
1390 					throw new TooLargePackException(limit);
1391 				}
1392 			};
1393 		}
1394 		return packIn;
1395 	}
1396 
1397 	private boolean needCheckConnectivity() {
1398 		return isCheckReceivedObjects()
1399 				|| isCheckReferencedObjectsAreReachable()
1400 				|| !getClientShallowCommits().isEmpty();
1401 	}
1402 
1403 	private void checkConnectivity() throws IOException {
1404 		ObjectIdSubclassMap<ObjectId> baseObjects = null;
1405 		ObjectIdSubclassMap<ObjectId> providedObjects = null;
1406 		ProgressMonitor checking = NullProgressMonitor.INSTANCE;
1407 		if (sideBand && !quiet) {
1408 			SideBandProgressMonitor m = new SideBandProgressMonitor(msgOut);
1409 			m.setDelayStart(750, TimeUnit.MILLISECONDS);
1410 			checking = m;
1411 		}
1412 
1413 		if (checkReferencedIsReachable) {
1414 			baseObjects = parser.getBaseObjectIds();
1415 			providedObjects = parser.getNewObjectIds();
1416 		}
1417 		parser = null;
1418 
1419 		try (final ObjectWalk ow = new ObjectWalk(db)) {
1420 			if (baseObjects != null) {
1421 				ow.sort(RevSort.TOPO);
1422 				if (!baseObjects.isEmpty())
1423 					ow.sort(RevSort.BOUNDARY, true);
1424 			}
1425 
1426 			for (final ReceiveCommand cmd : commands) {
1427 				if (cmd.getResult() != Result.NOT_ATTEMPTED)
1428 					continue;
1429 				if (cmd.getType() == ReceiveCommand.Type.DELETE)
1430 					continue;
1431 				ow.markStart(ow.parseAny(cmd.getNewId()));
1432 			}
1433 			for (final ObjectId have : advertisedHaves) {
1434 				RevObject o = ow.parseAny(have);
1435 				ow.markUninteresting(o);
1436 
1437 				if (baseObjects != null && !baseObjects.isEmpty()) {
1438 					o = ow.peel(o);
1439 					if (o instanceof RevCommit)
1440 						o = ((RevCommit) o).getTree();
1441 					if (o instanceof RevTree)
1442 						ow.markUninteresting(o);
1443 				}
1444 			}
1445 
1446 			checking.beginTask(JGitText.get().countingObjects,
1447 					ProgressMonitor.UNKNOWN);
1448 			RevCommit c;
1449 			while ((c = ow.next()) != null) {
1450 				checking.update(1);
1451 				if (providedObjects != null //
1452 						&& !c.has(RevFlag.UNINTERESTING) //
1453 						&& !providedObjects.contains(c))
1454 					throw new MissingObjectException(c, Constants.TYPE_COMMIT);
1455 			}
1456 
1457 			RevObject o;
1458 			while ((o = ow.nextObject()) != null) {
1459 				checking.update(1);
1460 				if (o.has(RevFlag.UNINTERESTING))
1461 					continue;
1462 
1463 				if (providedObjects != null) {
1464 					if (providedObjects.contains(o))
1465 						continue;
1466 					else
1467 						throw new MissingObjectException(o, o.getType());
1468 				}
1469 
1470 				if (o instanceof RevBlob && !db.hasObject(o))
1471 					throw new MissingObjectException(o, Constants.TYPE_BLOB);
1472 			}
1473 			checking.endTask();
1474 
1475 			if (baseObjects != null) {
1476 				for (ObjectId id : baseObjects) {
1477 					o = ow.parseAny(id);
1478 					if (!o.has(RevFlag.UNINTERESTING))
1479 						throw new MissingObjectException(o, o.getType());
1480 				}
1481 			}
1482 		}
1483 	}
1484 
1485 	/** Validate the command list. */
1486 	protected void validateCommands() {
1487 		for (final ReceiveCommand cmd : commands) {
1488 			final Ref ref = cmd.getRef();
1489 			if (cmd.getResult() != Result.NOT_ATTEMPTED)
1490 				continue;
1491 
1492 			if (cmd.getType() == ReceiveCommand.Type.DELETE) {
1493 				if (!isAllowDeletes()) {
1494 					// Deletes are not supported on this repository.
1495 					cmd.setResult(Result.REJECTED_NODELETE);
1496 					continue;
1497 				}
1498 				if (!isAllowBranchDeletes()
1499 						&& ref.getName().startsWith(Constants.R_HEADS)) {
1500 					// Branches cannot be deleted, but other refs can.
1501 					cmd.setResult(Result.REJECTED_NODELETE);
1502 					continue;
1503 				}
1504 			}
1505 
1506 			if (cmd.getType() == ReceiveCommand.Type.CREATE) {
1507 				if (!isAllowCreates()) {
1508 					cmd.setResult(Result.REJECTED_NOCREATE);
1509 					continue;
1510 				}
1511 
1512 				if (ref != null && !isAllowNonFastForwards()) {
1513 					// Creation over an existing ref is certainly not going
1514 					// to be a fast-forward update. We can reject it early.
1515 					//
1516 					cmd.setResult(Result.REJECTED_NONFASTFORWARD);
1517 					continue;
1518 				}
1519 
1520 				if (ref != null) {
1521 					// A well behaved client shouldn't have sent us a
1522 					// create command for a ref we advertised to it.
1523 					//
1524 					cmd.setResult(Result.REJECTED_OTHER_REASON,
1525 							JGitText.get().refAlreadyExists);
1526 					continue;
1527 				}
1528 			}
1529 
1530 			if (cmd.getType() == ReceiveCommand.Type.DELETE && ref != null) {
1531 				ObjectId id = ref.getObjectId();
1532 				if (id == null) {
1533 					id = ObjectId.zeroId();
1534 				}
1535 				if (!ObjectId.zeroId().equals(cmd.getOldId())
1536 						&& !id.equals(cmd.getOldId())) {
1537 					// Delete commands can be sent with the old id matching our
1538 					// advertised value, *OR* with the old id being 0{40}. Any
1539 					// other requested old id is invalid.
1540 					//
1541 					cmd.setResult(Result.REJECTED_OTHER_REASON,
1542 							JGitText.get().invalidOldIdSent);
1543 					continue;
1544 				}
1545 			}
1546 
1547 			if (cmd.getType() == ReceiveCommand.Type.UPDATE) {
1548 				if (ref == null) {
1549 					// The ref must have been advertised in order to be updated.
1550 					//
1551 					cmd.setResult(Result.REJECTED_OTHER_REASON, JGitText.get().noSuchRef);
1552 					continue;
1553 				}
1554 				ObjectId id = ref.getObjectId();
1555 				if (id == null) {
1556 					// We cannot update unborn branch
1557 					cmd.setResult(Result.REJECTED_OTHER_REASON,
1558 							JGitText.get().cannotUpdateUnbornBranch);
1559 					continue;
1560 				}
1561 
1562 				if (!id.equals(cmd.getOldId())) {
1563 					// A properly functioning client will send the same
1564 					// object id we advertised.
1565 					//
1566 					cmd.setResult(Result.REJECTED_OTHER_REASON,
1567 							JGitText.get().invalidOldIdSent);
1568 					continue;
1569 				}
1570 
1571 				// Is this possibly a non-fast-forward style update?
1572 				//
1573 				RevObject oldObj, newObj;
1574 				try {
1575 					oldObj = walk.parseAny(cmd.getOldId());
1576 				} catch (IOException e) {
1577 					cmd.setResult(Result.REJECTED_MISSING_OBJECT, cmd
1578 							.getOldId().name());
1579 					continue;
1580 				}
1581 
1582 				try {
1583 					newObj = walk.parseAny(cmd.getNewId());
1584 				} catch (IOException e) {
1585 					cmd.setResult(Result.REJECTED_MISSING_OBJECT, cmd
1586 							.getNewId().name());
1587 					continue;
1588 				}
1589 
1590 				if (oldObj instanceof RevCommit && newObj instanceof RevCommit) {
1591 					try {
1592 						if (walk.isMergedInto((RevCommit) oldObj,
1593 								(RevCommit) newObj))
1594 							cmd.setTypeFastForwardUpdate();
1595 						else
1596 							cmd.setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
1597 					} catch (MissingObjectException e) {
1598 						cmd.setResult(Result.REJECTED_MISSING_OBJECT, e
1599 								.getMessage());
1600 					} catch (IOException e) {
1601 						cmd.setResult(Result.REJECTED_OTHER_REASON);
1602 					}
1603 				} else {
1604 					cmd.setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
1605 				}
1606 
1607 				if (cmd.getType() == ReceiveCommand.Type.UPDATE_NONFASTFORWARD
1608 						&& !isAllowNonFastForwards()) {
1609 					cmd.setResult(Result.REJECTED_NONFASTFORWARD);
1610 					continue;
1611 				}
1612 			}
1613 
1614 			if (!cmd.getRefName().startsWith(Constants.R_REFS)
1615 					|| !Repository.isValidRefName(cmd.getRefName())) {
1616 				cmd.setResult(Result.REJECTED_OTHER_REASON, JGitText.get().funnyRefname);
1617 			}
1618 		}
1619 	}
1620 
1621 	/**
1622 	 * @return if any commands have been rejected so far.
1623 	 * @since 3.6
1624 	 */
1625 	protected boolean anyRejects() {
1626 		for (ReceiveCommand cmd : commands) {
1627 			if (cmd.getResult() != Result.NOT_ATTEMPTED && cmd.getResult() != Result.OK)
1628 				return true;
1629 		}
1630 		return false;
1631 	}
1632 
1633 	/**
1634 	 * Set the result to fail for any command that was not processed yet.
1635 	 * @since 3.6
1636 	 */
1637 	protected void failPendingCommands() {
1638 		ReceiveCommand.abort(commands);
1639 	}
1640 
1641 	/**
1642 	 * Filter the list of commands according to result.
1643 	 *
1644 	 * @param want
1645 	 *            desired status to filter by.
1646 	 * @return a copy of the command list containing only those commands with the
1647 	 *         desired status.
1648 	 */
1649 	protected List<ReceiveCommand> filterCommands(final Result want) {
1650 		return ReceiveCommand.filter(commands, want);
1651 	}
1652 
1653 	/** Execute commands to update references. */
1654 	protected void executeCommands() {
1655 		List<ReceiveCommand> toApply = filterCommands(Result.NOT_ATTEMPTED);
1656 		if (toApply.isEmpty())
1657 			return;
1658 
1659 		ProgressMonitor updating = NullProgressMonitor.INSTANCE;
1660 		if (sideBand) {
1661 			SideBandProgressMonitor pm = new SideBandProgressMonitor(msgOut);
1662 			pm.setDelayStart(250, TimeUnit.MILLISECONDS);
1663 			updating = pm;
1664 		}
1665 
1666 		BatchRefUpdate batch = db.getRefDatabase().newBatchUpdate();
1667 		batch.setAllowNonFastForwards(isAllowNonFastForwards());
1668 		batch.setAtomic(isAtomic());
1669 		batch.setRefLogIdent(getRefLogIdent());
1670 		batch.setRefLogMessage("push", true); //$NON-NLS-1$
1671 		batch.addCommand(toApply);
1672 		try {
1673 			batch.setPushCertificate(getPushCertificate());
1674 			batch.execute(walk, updating);
1675 		} catch (IOException err) {
1676 			for (ReceiveCommand cmd : toApply) {
1677 				if (cmd.getResult() == Result.NOT_ATTEMPTED)
1678 					cmd.reject(err);
1679 			}
1680 		}
1681 	}
1682 
1683 	/**
1684 	 * Send a status report.
1685 	 *
1686 	 * @param forClient
1687 	 *            true if this report is for a Git client, false if it is for an
1688 	 *            end-user.
1689 	 * @param unpackError
1690 	 *            an error that occurred during unpacking, or {@code null}
1691 	 * @param out
1692 	 *            the reporter for sending the status strings.
1693 	 * @throws IOException
1694 	 *             an error occurred writing the status report.
1695 	 */
1696 	protected void sendStatusReport(final boolean forClient,
1697 			final Throwable unpackError, final Reporter out) throws IOException {
1698 		if (unpackError != null) {
1699 			out.sendString("unpack error " + unpackError.getMessage()); //$NON-NLS-1$
1700 			if (forClient) {
1701 				for (final ReceiveCommand cmd : commands) {
1702 					out.sendString("ng " + cmd.getRefName() //$NON-NLS-1$
1703 							+ " n/a (unpacker error)"); //$NON-NLS-1$
1704 				}
1705 			}
1706 			return;
1707 		}
1708 
1709 		if (forClient)
1710 			out.sendString("unpack ok"); //$NON-NLS-1$
1711 		for (final ReceiveCommand cmd : commands) {
1712 			if (cmd.getResult() == Result.OK) {
1713 				if (forClient)
1714 					out.sendString("ok " + cmd.getRefName()); //$NON-NLS-1$
1715 				continue;
1716 			}
1717 
1718 			final StringBuilder r = new StringBuilder();
1719 			if (forClient)
1720 				r.append("ng ").append(cmd.getRefName()).append(" "); //$NON-NLS-1$ //$NON-NLS-2$
1721 			else
1722 				r.append(" ! [rejected] ").append(cmd.getRefName()).append(" ("); //$NON-NLS-1$ //$NON-NLS-2$
1723 
1724 			switch (cmd.getResult()) {
1725 			case NOT_ATTEMPTED:
1726 				r.append("server bug; ref not processed"); //$NON-NLS-1$
1727 				break;
1728 
1729 			case REJECTED_NOCREATE:
1730 				r.append("creation prohibited"); //$NON-NLS-1$
1731 				break;
1732 
1733 			case REJECTED_NODELETE:
1734 				r.append("deletion prohibited"); //$NON-NLS-1$
1735 				break;
1736 
1737 			case REJECTED_NONFASTFORWARD:
1738 				r.append("non-fast forward"); //$NON-NLS-1$
1739 				break;
1740 
1741 			case REJECTED_CURRENT_BRANCH:
1742 				r.append("branch is currently checked out"); //$NON-NLS-1$
1743 				break;
1744 
1745 			case REJECTED_MISSING_OBJECT:
1746 				if (cmd.getMessage() == null)
1747 					r.append("missing object(s)"); //$NON-NLS-1$
1748 				else if (cmd.getMessage().length() == Constants.OBJECT_ID_STRING_LENGTH) {
1749 					r.append("object "); //$NON-NLS-1$
1750 					r.append(cmd.getMessage());
1751 					r.append(" missing"); //$NON-NLS-1$
1752 				} else
1753 					r.append(cmd.getMessage());
1754 				break;
1755 
1756 			case REJECTED_OTHER_REASON:
1757 				if (cmd.getMessage() == null)
1758 					r.append("unspecified reason"); //$NON-NLS-1$
1759 				else
1760 					r.append(cmd.getMessage());
1761 				break;
1762 
1763 			case LOCK_FAILURE:
1764 				r.append("failed to lock"); //$NON-NLS-1$
1765 				break;
1766 
1767 			case OK:
1768 				// We shouldn't have reached this case (see 'ok' case above).
1769 				continue;
1770 			}
1771 			if (!forClient)
1772 				r.append(")"); //$NON-NLS-1$
1773 			out.sendString(r.toString());
1774 		}
1775 	}
1776 
1777 	/**
1778 	 * Close and flush (if necessary) the underlying streams.
1779 	 *
1780 	 * @throws IOException
1781 	 */
1782 	protected void close() throws IOException {
1783 		if (sideBand) {
1784 			// If we are using side band, we need to send a final
1785 			// flush-pkt to tell the remote peer the side band is
1786 			// complete and it should stop decoding. We need to
1787 			// use the original output stream as rawOut is now the
1788 			// side band data channel.
1789 			//
1790 			((SideBandOutputStream) msgOut).flushBuffer();
1791 			((SideBandOutputStream) rawOut).flushBuffer();
1792 
1793 			PacketLineOut plo = new PacketLineOut(origOut);
1794 			plo.setFlushOnEnd(false);
1795 			plo.end();
1796 		}
1797 
1798 		if (biDirectionalPipe) {
1799 			// If this was a native git connection, flush the pipe for
1800 			// the caller. For smart HTTP we don't do this flush and
1801 			// instead let the higher level HTTP servlet code do it.
1802 			//
1803 			if (!sideBand && msgOut != null)
1804 				msgOut.flush();
1805 			rawOut.flush();
1806 		}
1807 	}
1808 
1809 	/**
1810 	 * Release any resources used by this object.
1811 	 *
1812 	 * @throws IOException
1813 	 *             the pack could not be unlocked.
1814 	 */
1815 	protected void release() throws IOException {
1816 		walk.close();
1817 		unlockPack();
1818 		timeoutIn = null;
1819 		rawIn = null;
1820 		rawOut = null;
1821 		msgOut = null;
1822 		pckIn = null;
1823 		pckOut = null;
1824 		refs = null;
1825 		// Keep the capabilities. If responses are sent after this release
1826 		// we need to remember at least whether sideband communication has to be
1827 		// used
1828 		commands = null;
1829 		if (timer != null) {
1830 			try {
1831 				timer.terminate();
1832 			} finally {
1833 				timer = null;
1834 			}
1835 		}
1836 	}
1837 
1838 	/** Interface for reporting status messages. */
1839 	static abstract class Reporter {
1840 			abstract void sendString(String s) throws IOException;
1841 	}
1842 }