View Javadoc
1   /*
2    * Copyright (C) 2008-2010, Google Inc. and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  
11  package org.eclipse.jgit.transport;
12  
13  import static java.nio.charset.StandardCharsets.UTF_8;
14  import static org.eclipse.jgit.lib.Constants.HEAD;
15  import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_ATOMIC;
16  import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_DELETE_REFS;
17  import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_OFS_DELTA;
18  import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_PUSH_OPTIONS;
19  import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_QUIET;
20  import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_REPORT_STATUS;
21  import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_SIDE_BAND_64K;
22  import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;
23  import static org.eclipse.jgit.transport.SideBandOutputStream.CH_DATA;
24  import static org.eclipse.jgit.transport.SideBandOutputStream.CH_ERROR;
25  import static org.eclipse.jgit.transport.SideBandOutputStream.CH_PROGRESS;
26  import static org.eclipse.jgit.transport.SideBandOutputStream.MAX_BUF;
27  
28  import java.io.EOFException;
29  import java.io.IOException;
30  import java.io.InputStream;
31  import java.io.OutputStream;
32  import java.text.MessageFormat;
33  import java.util.ArrayList;
34  import java.util.Collections;
35  import java.util.HashSet;
36  import java.util.List;
37  import java.util.Map;
38  import java.util.Set;
39  import java.util.concurrent.TimeUnit;
40  
41  import org.eclipse.jgit.annotations.Nullable;
42  import org.eclipse.jgit.errors.InvalidObjectIdException;
43  import org.eclipse.jgit.errors.LargeObjectException;
44  import org.eclipse.jgit.errors.PackProtocolException;
45  import org.eclipse.jgit.errors.TooLargePackException;
46  import org.eclipse.jgit.errors.UnpackException;
47  import org.eclipse.jgit.internal.JGitText;
48  import org.eclipse.jgit.internal.storage.file.PackLock;
49  import org.eclipse.jgit.internal.submodule.SubmoduleValidator;
50  import org.eclipse.jgit.internal.submodule.SubmoduleValidator.SubmoduleValidationException;
51  import org.eclipse.jgit.internal.transport.connectivity.FullConnectivityChecker;
52  import org.eclipse.jgit.internal.transport.parser.FirstCommand;
53  import org.eclipse.jgit.lib.AnyObjectId;
54  import org.eclipse.jgit.lib.BatchRefUpdate;
55  import org.eclipse.jgit.lib.Config;
56  import org.eclipse.jgit.lib.ConfigConstants;
57  import org.eclipse.jgit.lib.Constants;
58  import org.eclipse.jgit.lib.GitmoduleEntry;
59  import org.eclipse.jgit.lib.NullProgressMonitor;
60  import org.eclipse.jgit.lib.ObjectChecker;
61  import org.eclipse.jgit.lib.ObjectDatabase;
62  import org.eclipse.jgit.lib.ObjectId;
63  import org.eclipse.jgit.lib.ObjectInserter;
64  import org.eclipse.jgit.lib.ObjectLoader;
65  import org.eclipse.jgit.lib.PersonIdent;
66  import org.eclipse.jgit.lib.ProgressMonitor;
67  import org.eclipse.jgit.lib.Ref;
68  import org.eclipse.jgit.lib.Repository;
69  import org.eclipse.jgit.revwalk.RevCommit;
70  import org.eclipse.jgit.revwalk.RevObject;
71  import org.eclipse.jgit.revwalk.RevWalk;
72  import org.eclipse.jgit.transport.ConnectivityChecker.ConnectivityCheckInfo;
73  import org.eclipse.jgit.transport.PacketLineIn.InputOverLimitIOException;
74  import org.eclipse.jgit.transport.ReceiveCommand.Result;
75  import org.eclipse.jgit.transport.RefAdvertiser.PacketLineOutRefAdvertiser;
76  import org.eclipse.jgit.util.io.InterruptTimer;
77  import org.eclipse.jgit.util.io.LimitedInputStream;
78  import org.eclipse.jgit.util.io.TimeoutInputStream;
79  import org.eclipse.jgit.util.io.TimeoutOutputStream;
80  
81  /**
82   * Implements the server side of a push connection, receiving objects.
83   */
84  public class ReceivePack {
85  	/**
86  	 * Data in the first line of a request, the line itself plus capabilities.
87  	 *
88  	 * @deprecated Use {@link FirstCommand} instead.
89  	 * @since 5.6
90  	 */
91  	@Deprecated
92  	public static class FirstLine {
93  		private final FirstCommand command;
94  
95  		/**
96  		 * Parse the first line of a receive-pack request.
97  		 *
98  		 * @param line
99  		 *            line from the client.
100 		 */
101 		public FirstLine(String line) {
102 			command = FirstCommand.fromLine(line);
103 		}
104 
105 		/** @return non-capabilities part of the line. */
106 		public String getLine() {
107 			return command.getLine();
108 		}
109 
110 		/** @return capabilities parsed from the line. */
111 		public Set<String> getCapabilities() {
112 			return command.getCapabilities();
113 		}
114 	}
115 
116 	/** Database we write the stored objects into. */
117 	private final Repository db;
118 
119 	/** Revision traversal support over {@link #db}. */
120 	private final RevWalk walk;
121 
122 	/**
123 	 * Is the client connection a bi-directional socket or pipe?
124 	 * <p>
125 	 * If true, this class assumes it can perform multiple read and write cycles
126 	 * with the client over the input and output streams. This matches the
127 	 * functionality available with a standard TCP/IP connection, or a local
128 	 * operating system or in-memory pipe.
129 	 * <p>
130 	 * If false, this class runs in a read everything then output results mode,
131 	 * making it suitable for single round-trip systems RPCs such as HTTP.
132 	 */
133 	private boolean biDirectionalPipe = true;
134 
135 	/** Expecting data after the pack footer */
136 	private boolean expectDataAfterPackFooter;
137 
138 	/** Should an incoming transfer validate objects? */
139 	private ObjectChecker objectChecker;
140 
141 	/** Should an incoming transfer permit create requests? */
142 	private boolean allowCreates;
143 
144 	/** Should an incoming transfer permit delete requests? */
145 	private boolean allowAnyDeletes;
146 
147 	private boolean allowBranchDeletes;
148 
149 	/** Should an incoming transfer permit non-fast-forward requests? */
150 	private boolean allowNonFastForwards;
151 
152 	/** Should an incoming transfer permit push options? **/
153 	private boolean allowPushOptions;
154 
155 	/**
156 	 * Should the requested ref updates be performed as a single atomic
157 	 * transaction?
158 	 */
159 	private boolean atomic;
160 
161 	private boolean allowOfsDelta;
162 
163 	private boolean allowQuiet = true;
164 
165 	/** Identity to record action as within the reflog. */
166 	private PersonIdent refLogIdent;
167 
168 	/** Hook used while advertising the refs to the client. */
169 	private AdvertiseRefsHook advertiseRefsHook;
170 
171 	/** Filter used while advertising the refs to the client. */
172 	private RefFilter refFilter;
173 
174 	/** Timeout in seconds to wait for client interaction. */
175 	private int timeout;
176 
177 	/** Timer to manage {@link #timeout}. */
178 	private InterruptTimer timer;
179 
180 	private TimeoutInputStream timeoutIn;
181 
182 	// Original stream passed to init(), since rawOut may be wrapped in a
183 	// sideband.
184 	private OutputStream origOut;
185 
186 	/** Raw input stream. */
187 	private InputStream rawIn;
188 
189 	/** Raw output stream. */
190 	private OutputStream rawOut;
191 
192 	/** Optional message output stream. */
193 	private OutputStream msgOut;
194 
195 	private SideBandOutputStream errOut;
196 
197 	/** Packet line input stream around {@link #rawIn}. */
198 	private PacketLineIn pckIn;
199 
200 	/** Packet line output stream around {@link #rawOut}. */
201 	private PacketLineOut pckOut;
202 
203 	private final MessageOutputWrapper msgOutWrapper = new MessageOutputWrapper();
204 
205 	private PackParser parser;
206 
207 	/** The refs we advertised as existing at the start of the connection. */
208 	private Map<String, Ref> refs;
209 
210 	/** All SHA-1s shown to the client, which can be possible edges. */
211 	private Set<ObjectId> advertisedHaves;
212 
213 	/** Capabilities requested by the client. */
214 	private Set<String> enabledCapabilities;
215 
216 	String userAgent;
217 
218 	private Set<ObjectId> clientShallowCommits;
219 
220 	private List<ReceiveCommand> commands;
221 
222 	private long maxCommandBytes;
223 
224 	private long maxDiscardBytes;
225 
226 	private StringBuilder advertiseError;
227 
228 	/**
229 	 * If {@link BasePackPushConnection#CAPABILITY_SIDE_BAND_64K} is enabled.
230 	 */
231 	private boolean sideBand;
232 
233 	private boolean quiet;
234 
235 	/** Lock around the received pack file, while updating refs. */
236 	private PackLock packLock;
237 
238 	private boolean checkReferencedAreReachable;
239 
240 	/** Git object size limit */
241 	private long maxObjectSizeLimit;
242 
243 	/** Total pack size limit */
244 	private long maxPackSizeLimit = -1;
245 
246 	/** The size of the received pack, including index size */
247 	private Long packSize;
248 
249 	private PushCertificateParser pushCertificateParser;
250 
251 	private SignedPushConfig signedPushConfig;
252 
253 	private PushCertificate pushCert;
254 
255 	private ReceivedPackStatistics stats;
256 
257 	/**
258 	 * Connectivity checker to use.
259 	 * @since 5.7
260 	 */
261 	protected ConnectivityChecker connectivityChecker = new FullConnectivityChecker();
262 
263 	/** Hook to validate the update commands before execution. */
264 	private PreReceiveHook preReceive;
265 
266 	private ReceiveCommandErrorHandlermmandErrorHandler">ReceiveCommandErrorHandler receiveCommandErrorHandler = new ReceiveCommandErrorHandler() {
267 		// Use the default implementation.
268 	};
269 
270 	private UnpackErrorHandler unpackErrorHandler = new DefaultUnpackErrorHandler();
271 
272 	/** Hook to report on the commands after execution. */
273 	private PostReceiveHook postReceive;
274 
275 	/** If {@link BasePackPushConnection#CAPABILITY_REPORT_STATUS} is enabled. */
276 	private boolean reportStatus;
277 
278 	/** Whether the client intends to use push options. */
279 	private boolean usePushOptions;
280 	private List<String> pushOptions;
281 
282 	/**
283 	 * Create a new pack receive for an open repository.
284 	 *
285 	 * @param into
286 	 *            the destination repository.
287 	 */
288 	public ReceivePack(Repository into) {
289 		db = into;
290 		walk = new RevWalk(db);
291 		walk.setRetainBody(false);
292 
293 		TransferConfig tc = db.getConfig().get(TransferConfig.KEY);
294 		objectChecker = tc.newReceiveObjectChecker();
295 
296 		ReceiveConfig rc = db.getConfig().get(ReceiveConfig::new);
297 		allowCreates = rc.allowCreates;
298 		allowAnyDeletes = true;
299 		allowBranchDeletes = rc.allowDeletes;
300 		allowNonFastForwards = rc.allowNonFastForwards;
301 		allowOfsDelta = rc.allowOfsDelta;
302 		allowPushOptions = rc.allowPushOptions;
303 		maxCommandBytes = rc.maxCommandBytes;
304 		maxDiscardBytes = rc.maxDiscardBytes;
305 		advertiseRefsHook = AdvertiseRefsHook.DEFAULT;
306 		refFilter = RefFilter.DEFAULT;
307 		advertisedHaves = new HashSet<>();
308 		clientShallowCommits = new HashSet<>();
309 		signedPushConfig = rc.signedPush;
310 		preReceive = PreReceiveHook.NULL;
311 		postReceive = PostReceiveHook.NULL;
312 	}
313 
314 	/** Configuration for receive operations. */
315 	private static class ReceiveConfig {
316 		final boolean allowCreates;
317 
318 		final boolean allowDeletes;
319 
320 		final boolean allowNonFastForwards;
321 
322 		final boolean allowOfsDelta;
323 
324 		final boolean allowPushOptions;
325 
326 		final long maxCommandBytes;
327 
328 		final long maxDiscardBytes;
329 
330 		final SignedPushConfig signedPush;
331 
332 		ReceiveConfig(Config config) {
333 			allowCreates = true;
334 			allowDeletes = !config.getBoolean("receive", "denydeletes", false); //$NON-NLS-1$ //$NON-NLS-2$
335 			allowNonFastForwards = !config.getBoolean("receive", //$NON-NLS-1$
336 					"denynonfastforwards", false); //$NON-NLS-1$
337 			allowOfsDelta = config.getBoolean("repack", "usedeltabaseoffset", //$NON-NLS-1$ //$NON-NLS-2$
338 					true);
339 			allowPushOptions = config.getBoolean("receive", "pushoptions", //$NON-NLS-1$ //$NON-NLS-2$
340 					false);
341 			maxCommandBytes = config.getLong("receive", //$NON-NLS-1$
342 					"maxCommandBytes", //$NON-NLS-1$
343 					3 << 20);
344 			maxDiscardBytes = config.getLong("receive", //$NON-NLS-1$
345 					"maxCommandDiscardBytes", //$NON-NLS-1$
346 					-1);
347 			signedPush = SignedPushConfig.KEY.parse(config);
348 		}
349 	}
350 
351 	/**
352 	 * Output stream that wraps the current {@link #msgOut}.
353 	 * <p>
354 	 * We don't want to expose {@link #msgOut} directly because it can change
355 	 * several times over the course of a session.
356 	 */
357 	class MessageOutputWrapper extends OutputStream {
358 		@Override
359 		public void write(int ch) {
360 			if (msgOut != null) {
361 				try {
362 					msgOut.write(ch);
363 				} catch (IOException e) {
364 					// Ignore write failures.
365 				}
366 			}
367 		}
368 
369 		@Override
370 		public void write(byte[] b, int off, int len) {
371 			if (msgOut != null) {
372 				try {
373 					msgOut.write(b, off, len);
374 				} catch (IOException e) {
375 					// Ignore write failures.
376 				}
377 			}
378 		}
379 
380 		@Override
381 		public void write(byte[] b) {
382 			write(b, 0, b.length);
383 		}
384 
385 		@Override
386 		public void flush() {
387 			if (msgOut != null) {
388 				try {
389 					msgOut.flush();
390 				} catch (IOException e) {
391 					// Ignore write failures.
392 				}
393 			}
394 		}
395 	}
396 
397 	/**
398 	 * Get the repository this receive completes into.
399 	 *
400 	 * @return the repository this receive completes into.
401 	 */
402 	public Repository getRepository() {
403 		return db;
404 	}
405 
406 	/**
407 	 * Get the RevWalk instance used by this connection.
408 	 *
409 	 * @return the RevWalk instance used by this connection.
410 	 */
411 	public RevWalk getRevWalk() {
412 		return walk;
413 	}
414 
415 	/**
416 	 * Get refs which were advertised to the client.
417 	 *
418 	 * @return all refs which were advertised to the client, or null if
419 	 *         {@link #setAdvertisedRefs(Map, Set)} has not been called yet.
420 	 */
421 	public Map<String, Ref> getAdvertisedRefs() {
422 		return refs;
423 	}
424 
425 	/**
426 	 * Set the refs advertised by this ReceivePack.
427 	 * <p>
428 	 * Intended to be called from a
429 	 * {@link org.eclipse.jgit.transport.PreReceiveHook}.
430 	 *
431 	 * @param allRefs
432 	 *            explicit set of references to claim as advertised by this
433 	 *            ReceivePack instance. This overrides any references that may
434 	 *            exist in the source repository. The map is passed to the
435 	 *            configured {@link #getRefFilter()}. If null, assumes all refs
436 	 *            were advertised.
437 	 * @param additionalHaves
438 	 *            explicit set of additional haves to claim as advertised. If
439 	 *            null, assumes the default set of additional haves from the
440 	 *            repository.
441 	 */
442 	public void setAdvertisedRefs(Map<String, Ref> allRefs,
443 			Set<ObjectId> additionalHaves) {
444 		refs = allRefs != null ? allRefs : db.getAllRefs();
445 		refs = refFilter.filter(refs);
446 		advertisedHaves.clear();
447 
448 		Ref head = refs.get(HEAD);
449 		if (head != null && head.isSymbolic()) {
450 			refs.remove(HEAD);
451 		}
452 
453 		for (Ref ref : refs.values()) {
454 			if (ref.getObjectId() != null) {
455 				advertisedHaves.add(ref.getObjectId());
456 			}
457 		}
458 		if (additionalHaves != null) {
459 			advertisedHaves.addAll(additionalHaves);
460 		} else {
461 			advertisedHaves.addAll(db.getAdditionalHaves());
462 		}
463 	}
464 
465 	/**
466 	 * Get objects advertised to the client.
467 	 *
468 	 * @return the set of objects advertised to the as present in this
469 	 *         repository, or null if {@link #setAdvertisedRefs(Map, Set)} has
470 	 *         not been called yet.
471 	 */
472 	public final Set<ObjectId> getAdvertisedObjects() {
473 		return advertisedHaves;
474 	}
475 
476 	/**
477 	 * Whether this instance will validate all referenced, but not supplied by
478 	 * the client, objects are reachable from another reference.
479 	 *
480 	 * @return true if this instance will validate all referenced, but not
481 	 *         supplied by the client, objects are reachable from another
482 	 *         reference.
483 	 */
484 	public boolean isCheckReferencedObjectsAreReachable() {
485 		return checkReferencedAreReachable;
486 	}
487 
488 	/**
489 	 * Validate all referenced but not supplied objects are reachable.
490 	 * <p>
491 	 * If enabled, this instance will verify that references to objects not
492 	 * contained within the received pack are already reachable through at least
493 	 * one other reference displayed as part of {@link #getAdvertisedRefs()}.
494 	 * <p>
495 	 * This feature is useful when the application doesn't trust the client to
496 	 * not provide a forged SHA-1 reference to an object, in an attempt to
497 	 * access parts of the DAG that they aren't allowed to see and which have
498 	 * been hidden from them via the configured
499 	 * {@link org.eclipse.jgit.transport.AdvertiseRefsHook} or
500 	 * {@link org.eclipse.jgit.transport.RefFilter}.
501 	 * <p>
502 	 * Enabling this feature may imply at least some, if not all, of the same
503 	 * functionality performed by {@link #setCheckReceivedObjects(boolean)}.
504 	 * Applications are encouraged to enable both features, if desired.
505 	 *
506 	 * @param b
507 	 *            {@code true} to enable the additional check.
508 	 */
509 	public void setCheckReferencedObjectsAreReachable(boolean b) {
510 		this.checkReferencedAreReachable = b;
511 	}
512 
513 	/**
514 	 * Whether this class expects a bi-directional pipe opened between the
515 	 * client and itself.
516 	 *
517 	 * @return true if this class expects a bi-directional pipe opened between
518 	 *         the client and itself. The default is true.
519 	 */
520 	public boolean isBiDirectionalPipe() {
521 		return biDirectionalPipe;
522 	}
523 
524 	/**
525 	 * Whether this class will assume the socket is a fully bidirectional pipe
526 	 * between the two peers and takes advantage of that by first transmitting
527 	 * the known refs, then waiting to read commands.
528 	 *
529 	 * @param twoWay
530 	 *            if true, this class will assume the socket is a fully
531 	 *            bidirectional pipe between the two peers and takes advantage
532 	 *            of that by first transmitting the known refs, then waiting to
533 	 *            read commands. If false, this class assumes it must read the
534 	 *            commands before writing output and does not perform the
535 	 *            initial advertising.
536 	 */
537 	public void setBiDirectionalPipe(boolean twoWay) {
538 		biDirectionalPipe = twoWay;
539 	}
540 
541 	/**
542 	 * Whether there is data expected after the pack footer.
543 	 *
544 	 * @return {@code true} if there is data expected after the pack footer.
545 	 */
546 	public boolean isExpectDataAfterPackFooter() {
547 		return expectDataAfterPackFooter;
548 	}
549 
550 	/**
551 	 * Whether there is additional data in InputStream after pack.
552 	 *
553 	 * @param e
554 	 *            {@code true} if there is additional data in InputStream after
555 	 *            pack.
556 	 */
557 	public void setExpectDataAfterPackFooter(boolean e) {
558 		expectDataAfterPackFooter = e;
559 	}
560 
561 	/**
562 	 * Whether this instance will verify received objects are formatted
563 	 * correctly.
564 	 *
565 	 * @return {@code true} if this instance will verify received objects are
566 	 *         formatted correctly. Validating objects requires more CPU time on
567 	 *         this side of the connection.
568 	 */
569 	public boolean isCheckReceivedObjects() {
570 		return objectChecker != null;
571 	}
572 
573 	/**
574 	 * Whether to enable checking received objects
575 	 *
576 	 * @param check
577 	 *            {@code true} to enable checking received objects; false to
578 	 *            assume all received objects are valid.
579 	 * @see #setObjectChecker(ObjectChecker)
580 	 */
581 	public void setCheckReceivedObjects(boolean check) {
582 		if (check && objectChecker == null)
583 			setObjectChecker(new ObjectChecker());
584 		else if (!check && objectChecker != null)
585 			setObjectChecker(null);
586 	}
587 
588 	/**
589 	 * Set the object checking instance to verify each received object with
590 	 *
591 	 * @param impl
592 	 *            if non-null the object checking instance to verify each
593 	 *            received object with; null to disable object checking.
594 	 * @since 3.4
595 	 */
596 	public void setObjectChecker(ObjectChecker impl) {
597 		objectChecker = impl;
598 	}
599 
600 	/**
601 	 * Whether the client can request refs to be created.
602 	 *
603 	 * @return {@code true} if the client can request refs to be created.
604 	 */
605 	public boolean isAllowCreates() {
606 		return allowCreates;
607 	}
608 
609 	/**
610 	 * Whether to permit create ref commands to be processed.
611 	 *
612 	 * @param canCreate
613 	 *            {@code true} to permit create ref commands to be processed.
614 	 */
615 	public void setAllowCreates(boolean canCreate) {
616 		allowCreates = canCreate;
617 	}
618 
619 	/**
620 	 * Whether the client can request refs to be deleted.
621 	 *
622 	 * @return {@code true} if the client can request refs to be deleted.
623 	 */
624 	public boolean isAllowDeletes() {
625 		return allowAnyDeletes;
626 	}
627 
628 	/**
629 	 * Whether to permit delete ref commands to be processed.
630 	 *
631 	 * @param canDelete
632 	 *            {@code true} to permit delete ref commands to be processed.
633 	 */
634 	public void setAllowDeletes(boolean canDelete) {
635 		allowAnyDeletes = canDelete;
636 	}
637 
638 	/**
639 	 * Whether the client can delete from {@code refs/heads/}.
640 	 *
641 	 * @return {@code true} if the client can delete from {@code refs/heads/}.
642 	 * @since 3.6
643 	 */
644 	public boolean isAllowBranchDeletes() {
645 		return allowBranchDeletes;
646 	}
647 
648 	/**
649 	 * Configure whether to permit deletion of branches from the
650 	 * {@code refs/heads/} namespace.
651 	 *
652 	 * @param canDelete
653 	 *            {@code true} to permit deletion of branches from the
654 	 *            {@code refs/heads/} namespace.
655 	 * @since 3.6
656 	 */
657 	public void setAllowBranchDeletes(boolean canDelete) {
658 		allowBranchDeletes = canDelete;
659 	}
660 
661 	/**
662 	 * Whether the client can request non-fast-forward updates of a ref,
663 	 * possibly making objects unreachable.
664 	 *
665 	 * @return {@code true} if the client can request non-fast-forward updates
666 	 *         of a ref, possibly making objects unreachable.
667 	 */
668 	public boolean isAllowNonFastForwards() {
669 		return allowNonFastForwards;
670 	}
671 
672 	/**
673 	 * Configure whether to permit the client to ask for non-fast-forward
674 	 * updates of an existing ref.
675 	 *
676 	 * @param canRewind
677 	 *            {@code true} to permit the client to ask for non-fast-forward
678 	 *            updates of an existing ref.
679 	 */
680 	public void setAllowNonFastForwards(boolean canRewind) {
681 		allowNonFastForwards = canRewind;
682 	}
683 
684 	/**
685 	 * Whether the client's commands should be performed as a single atomic
686 	 * transaction.
687 	 *
688 	 * @return {@code true} if the client's commands should be performed as a
689 	 *         single atomic transaction.
690 	 * @since 4.4
691 	 */
692 	public boolean isAtomic() {
693 		return atomic;
694 	}
695 
696 	/**
697 	 * Configure whether to perform the client's commands as a single atomic
698 	 * transaction.
699 	 *
700 	 * @param atomic
701 	 *            {@code true} to perform the client's commands as a single
702 	 *            atomic transaction.
703 	 * @since 4.4
704 	 */
705 	public void setAtomic(boolean atomic) {
706 		this.atomic = atomic;
707 	}
708 
709 	/**
710 	 * Get identity of the user making the changes in the reflog.
711 	 *
712 	 * @return identity of the user making the changes in the reflog.
713 	 */
714 	public PersonIdent getRefLogIdent() {
715 		return refLogIdent;
716 	}
717 
718 	/**
719 	 * Set the identity of the user appearing in the affected reflogs.
720 	 * <p>
721 	 * The timestamp portion of the identity is ignored. A new identity with the
722 	 * current timestamp will be created automatically when the updates occur
723 	 * and the log records are written.
724 	 *
725 	 * @param pi
726 	 *            identity of the user. If null the identity will be
727 	 *            automatically determined based on the repository
728 	 *            configuration.
729 	 */
730 	public void setRefLogIdent(PersonIdent pi) {
731 		refLogIdent = pi;
732 	}
733 
734 	/**
735 	 * Get the hook used while advertising the refs to the client
736 	 *
737 	 * @return the hook used while advertising the refs to the client
738 	 */
739 	public AdvertiseRefsHook getAdvertiseRefsHook() {
740 		return advertiseRefsHook;
741 	}
742 
743 	/**
744 	 * Get the filter used while advertising the refs to the client
745 	 *
746 	 * @return the filter used while advertising the refs to the client
747 	 */
748 	public RefFilter getRefFilter() {
749 		return refFilter;
750 	}
751 
752 	/**
753 	 * Set the hook used while advertising the refs to the client.
754 	 * <p>
755 	 * If the {@link org.eclipse.jgit.transport.AdvertiseRefsHook} chooses to
756 	 * call {@link #setAdvertisedRefs(Map,Set)}, only refs set by this hook
757 	 * <em>and</em> selected by the {@link org.eclipse.jgit.transport.RefFilter}
758 	 * will be shown to the client. Clients may still attempt to create or
759 	 * update a reference not advertised by the configured
760 	 * {@link org.eclipse.jgit.transport.AdvertiseRefsHook}. These attempts
761 	 * should be rejected by a matching
762 	 * {@link org.eclipse.jgit.transport.PreReceiveHook}.
763 	 *
764 	 * @param advertiseRefsHook
765 	 *            the hook; may be null to show all refs.
766 	 */
767 	public void setAdvertiseRefsHook(AdvertiseRefsHook advertiseRefsHook) {
768 		if (advertiseRefsHook != null)
769 			this.advertiseRefsHook = advertiseRefsHook;
770 		else
771 			this.advertiseRefsHook = AdvertiseRefsHook.DEFAULT;
772 	}
773 
774 	/**
775 	 * Set the filter used while advertising the refs to the client.
776 	 * <p>
777 	 * Only refs allowed by this filter will be shown to the client. The filter
778 	 * is run against the refs specified by the
779 	 * {@link org.eclipse.jgit.transport.AdvertiseRefsHook} (if applicable).
780 	 *
781 	 * @param refFilter
782 	 *            the filter; may be null to show all refs.
783 	 */
784 	public void setRefFilter(RefFilter refFilter) {
785 		this.refFilter = refFilter != null ? refFilter : RefFilter.DEFAULT;
786 	}
787 
788 	/**
789 	 * Get timeout (in seconds) before aborting an IO operation.
790 	 *
791 	 * @return timeout (in seconds) before aborting an IO operation.
792 	 */
793 	public int getTimeout() {
794 		return timeout;
795 	}
796 
797 	/**
798 	 * Set the timeout before willing to abort an IO call.
799 	 *
800 	 * @param seconds
801 	 *            number of seconds to wait (with no data transfer occurring)
802 	 *            before aborting an IO read or write operation with the
803 	 *            connected client.
804 	 */
805 	public void setTimeout(int seconds) {
806 		timeout = seconds;
807 	}
808 
809 	/**
810 	 * Set the maximum number of command bytes to read from the client.
811 	 *
812 	 * @param limit
813 	 *            command limit in bytes; if 0 there is no limit.
814 	 * @since 4.7
815 	 */
816 	public void setMaxCommandBytes(long limit) {
817 		maxCommandBytes = limit;
818 	}
819 
820 	/**
821 	 * Set the maximum number of command bytes to discard from the client.
822 	 * <p>
823 	 * Discarding remaining bytes allows this instance to consume the rest of
824 	 * the command block and send a human readable over-limit error via the
825 	 * side-band channel. If the client sends an excessive number of bytes this
826 	 * limit kicks in and the instance disconnects, resulting in a non-specific
827 	 * 'pipe closed', 'end of stream', or similar generic error at the client.
828 	 * <p>
829 	 * When the limit is set to {@code -1} the implementation will default to
830 	 * the larger of {@code 3 * maxCommandBytes} or {@code 3 MiB}.
831 	 *
832 	 * @param limit
833 	 *            discard limit in bytes; if 0 there is no limit; if -1 the
834 	 *            implementation tries to set a reasonable default.
835 	 * @since 4.7
836 	 */
837 	public void setMaxCommandDiscardBytes(long limit) {
838 		maxDiscardBytes = limit;
839 	}
840 
841 	/**
842 	 * Set the maximum allowed Git object size.
843 	 * <p>
844 	 * If an object is larger than the given size the pack-parsing will throw an
845 	 * exception aborting the receive-pack operation.
846 	 *
847 	 * @param limit
848 	 *            the Git object size limit. If zero then there is not limit.
849 	 */
850 	public void setMaxObjectSizeLimit(long limit) {
851 		maxObjectSizeLimit = limit;
852 	}
853 
854 	/**
855 	 * Set the maximum allowed pack size.
856 	 * <p>
857 	 * A pack exceeding this size will be rejected.
858 	 *
859 	 * @param limit
860 	 *            the pack size limit, in bytes
861 	 * @since 3.3
862 	 */
863 	public void setMaxPackSizeLimit(long limit) {
864 		if (limit < 0)
865 			throw new IllegalArgumentException(
866 					MessageFormat.format(JGitText.get().receivePackInvalidLimit,
867 							Long.valueOf(limit)));
868 		maxPackSizeLimit = limit;
869 	}
870 
871 	/**
872 	 * Check whether the client expects a side-band stream.
873 	 *
874 	 * @return true if the client has advertised a side-band capability, false
875 	 *         otherwise.
876 	 * @throws org.eclipse.jgit.transport.RequestNotYetReadException
877 	 *             if the client's request has not yet been read from the wire,
878 	 *             so we do not know if they expect side-band. Note that the
879 	 *             client may have already written the request, it just has not
880 	 *             been read.
881 	 */
882 	public boolean isSideBand() throws RequestNotYetReadException {
883 		checkRequestWasRead();
884 		return enabledCapabilities.contains(CAPABILITY_SIDE_BAND_64K);
885 	}
886 
887 	/**
888 	 * Whether clients may request avoiding noisy progress messages.
889 	 *
890 	 * @return true if clients may request avoiding noisy progress messages.
891 	 * @since 4.0
892 	 */
893 	public boolean isAllowQuiet() {
894 		return allowQuiet;
895 	}
896 
897 	/**
898 	 * Configure if clients may request the server skip noisy messages.
899 	 *
900 	 * @param allow
901 	 *            true to allow clients to request quiet behavior; false to
902 	 *            refuse quiet behavior and send messages anyway. This may be
903 	 *            necessary if processing is slow and the client-server network
904 	 *            connection can timeout.
905 	 * @since 4.0
906 	 */
907 	public void setAllowQuiet(boolean allow) {
908 		allowQuiet = allow;
909 	}
910 
911 	/**
912 	 * Whether the server supports receiving push options.
913 	 *
914 	 * @return true if the server supports receiving push options.
915 	 * @since 4.5
916 	 */
917 	public boolean isAllowPushOptions() {
918 		return allowPushOptions;
919 	}
920 
921 	/**
922 	 * Configure if the server supports receiving push options.
923 	 *
924 	 * @param allow
925 	 *            true to optionally accept option strings from the client.
926 	 * @since 4.5
927 	 */
928 	public void setAllowPushOptions(boolean allow) {
929 		allowPushOptions = allow;
930 	}
931 
932 	/**
933 	 * True if the client wants less verbose output.
934 	 *
935 	 * @return true if the client has requested the server to be less verbose.
936 	 * @throws org.eclipse.jgit.transport.RequestNotYetReadException
937 	 *             if the client's request has not yet been read from the wire,
938 	 *             so we do not know if they expect side-band. Note that the
939 	 *             client may have already written the request, it just has not
940 	 *             been read.
941 	 * @since 4.0
942 	 */
943 	public boolean isQuiet() throws RequestNotYetReadException {
944 		checkRequestWasRead();
945 		return quiet;
946 	}
947 
948 	/**
949 	 * Set the configuration for push certificate verification.
950 	 *
951 	 * @param cfg
952 	 *            new configuration; if this object is null or its
953 	 *            {@link SignedPushConfig#getCertNonceSeed()} is null, push
954 	 *            certificate verification will be disabled.
955 	 * @since 4.1
956 	 */
957 	public void setSignedPushConfig(SignedPushConfig cfg) {
958 		signedPushConfig = cfg;
959 	}
960 
961 	private PushCertificateParser getPushCertificateParser() {
962 		if (pushCertificateParser == null) {
963 			pushCertificateParser = new PushCertificateParser(db,
964 					signedPushConfig);
965 		}
966 		return pushCertificateParser;
967 	}
968 
969 	/**
970 	 * Get the user agent of the client.
971 	 * <p>
972 	 * If the client is new enough to use {@code agent=} capability that value
973 	 * will be returned. Older HTTP clients may also supply their version using
974 	 * the HTTP {@code User-Agent} header. The capability overrides the HTTP
975 	 * header if both are available.
976 	 * <p>
977 	 * When an HTTP request has been received this method returns the HTTP
978 	 * {@code User-Agent} header value until capabilities have been parsed.
979 	 *
980 	 * @return user agent supplied by the client. Available only if the client
981 	 *         is new enough to advertise its user agent.
982 	 * @since 4.0
983 	 */
984 	public String getPeerUserAgent() {
985 		return UserAgent.getAgent(enabledCapabilities, userAgent);
986 	}
987 
988 	/**
989 	 * Get all of the command received by the current request.
990 	 *
991 	 * @return all of the command received by the current request.
992 	 */
993 	public List<ReceiveCommand> getAllCommands() {
994 		return Collections.unmodifiableList(commands);
995 	}
996 
997 	/**
998 	 * Set an error handler for {@link ReceiveCommand}.
999 	 *
1000 	 * @param receiveCommandErrorHandler
1001 	 * @since 5.7
1002 	 */
1003 	public void setReceiveCommandErrorHandler(
1004 			ReceiveCommandErrorHandler receiveCommandErrorHandler) {
1005 		this.receiveCommandErrorHandler = receiveCommandErrorHandler;
1006 	}
1007 
1008 	/**
1009 	 * Send an error message to the client.
1010 	 * <p>
1011 	 * If any error messages are sent before the references are advertised to
1012 	 * the client, the errors will be sent instead of the advertisement and the
1013 	 * receive operation will be aborted. All clients should receive and display
1014 	 * such early stage errors.
1015 	 * <p>
1016 	 * If the reference advertisements have already been sent, messages are sent
1017 	 * in a side channel. If the client doesn't support receiving messages, the
1018 	 * message will be discarded, with no other indication to the caller or to
1019 	 * the client.
1020 	 * <p>
1021 	 * {@link org.eclipse.jgit.transport.PreReceiveHook}s should always try to
1022 	 * use
1023 	 * {@link org.eclipse.jgit.transport.ReceiveCommand#setResult(Result, String)}
1024 	 * with a result status of
1025 	 * {@link org.eclipse.jgit.transport.ReceiveCommand.Result#REJECTED_OTHER_REASON}
1026 	 * to indicate any reasons for rejecting an update. Messages attached to a
1027 	 * command are much more likely to be returned to the client.
1028 	 *
1029 	 * @param what
1030 	 *            string describing the problem identified by the hook. The
1031 	 *            string must not end with an LF, and must not contain an LF.
1032 	 */
1033 	public void sendError(String what) {
1034 		if (refs == null) {
1035 			if (advertiseError == null)
1036 				advertiseError = new StringBuilder();
1037 			advertiseError.append(what).append('\n');
1038 		} else {
1039 			msgOutWrapper.write(Constants.encode("error: " + what + "\n")); //$NON-NLS-1$ //$NON-NLS-2$
1040 		}
1041 	}
1042 
1043 	private void fatalError(String msg) {
1044 		if (errOut != null) {
1045 			try {
1046 				errOut.write(Constants.encode(msg));
1047 				errOut.flush();
1048 			} catch (IOException e) {
1049 				// Ignore write failures
1050 			}
1051 		} else {
1052 			sendError(msg);
1053 		}
1054 	}
1055 
1056 	/**
1057 	 * Send a message to the client, if it supports receiving them.
1058 	 * <p>
1059 	 * If the client doesn't support receiving messages, the message will be
1060 	 * discarded, with no other indication to the caller or to the client.
1061 	 *
1062 	 * @param what
1063 	 *            string describing the problem identified by the hook. The
1064 	 *            string must not end with an LF, and must not contain an LF.
1065 	 */
1066 	public void sendMessage(String what) {
1067 		msgOutWrapper.write(Constants.encode(what + "\n")); //$NON-NLS-1$
1068 	}
1069 
1070 	/**
1071 	 * Get an underlying stream for sending messages to the client.
1072 	 *
1073 	 * @return an underlying stream for sending messages to the client.
1074 	 */
1075 	public OutputStream getMessageOutputStream() {
1076 		return msgOutWrapper;
1077 	}
1078 
1079 	/**
1080 	 * Get whether or not a pack has been received.
1081 	 *
1082 	 * This can be called before calling {@link #getPackSize()} to avoid causing
1083 	 * {@code IllegalStateException} when the pack size was not set because no
1084 	 * pack was received.
1085 	 *
1086 	 * @return true if a pack has been received.
1087 	 * @since 5.6
1088 	 */
1089 	public boolean hasReceivedPack() {
1090 		return packSize != null;
1091 	}
1092 
1093 	/**
1094 	 * Get the size of the received pack file including the index size.
1095 	 *
1096 	 * This can only be called if the pack is already received.
1097 	 *
1098 	 * @return the size of the received pack including index size
1099 	 * @throws java.lang.IllegalStateException
1100 	 *             if called before the pack has been received
1101 	 * @since 3.3
1102 	 */
1103 	public long getPackSize() {
1104 		if (packSize != null)
1105 			return packSize.longValue();
1106 		throw new IllegalStateException(JGitText.get().packSizeNotSetYet);
1107 	}
1108 
1109 	/**
1110 	 * Get the commits from the client's shallow file.
1111 	 *
1112 	 * @return if the client is a shallow repository, the list of edge commits
1113 	 *         that define the client's shallow boundary. Empty set if the
1114 	 *         client is earlier than Git 1.9, or is a full clone.
1115 	 */
1116 	private Set<ObjectId> getClientShallowCommits() {
1117 		return clientShallowCommits;
1118 	}
1119 
1120 	/**
1121 	 * Whether any commands to be executed have been read.
1122 	 *
1123 	 * @return {@code true} if any commands to be executed have been read.
1124 	 */
1125 	private boolean hasCommands() {
1126 		return !commands.isEmpty();
1127 	}
1128 
1129 	/**
1130 	 * Whether an error occurred that should be advertised.
1131 	 *
1132 	 * @return true if an error occurred that should be advertised.
1133 	 */
1134 	private boolean hasError() {
1135 		return advertiseError != null;
1136 	}
1137 
1138 	/**
1139 	 * Initialize the instance with the given streams.
1140 	 *
1141 	 * Visible for out-of-tree subclasses (e.g. tests that need to set the
1142 	 * streams without going through the {@link #service()} method).
1143 	 *
1144 	 * @param input
1145 	 *            raw input to read client commands and pack data from. Caller
1146 	 *            must ensure the input is buffered, otherwise read performance
1147 	 *            may suffer.
1148 	 * @param output
1149 	 *            response back to the Git network client. Caller must ensure
1150 	 *            the output is buffered, otherwise write performance may
1151 	 *            suffer.
1152 	 * @param messages
1153 	 *            secondary "notice" channel to send additional messages out
1154 	 *            through. When run over SSH this should be tied back to the
1155 	 *            standard error channel of the command execution. For most
1156 	 *            other network connections this should be null.
1157 	 */
1158 	protected void init(final InputStream input, final OutputStream output,
1159 			final OutputStream messages) {
1160 		origOut = output;
1161 		rawIn = input;
1162 		rawOut = output;
1163 		msgOut = messages;
1164 
1165 		if (timeout > 0) {
1166 			final Thread caller = Thread.currentThread();
1167 			timer = new InterruptTimer(caller.getName() + "-Timer"); //$NON-NLS-1$
1168 			timeoutIn = new TimeoutInputStream(rawIn, timer);
1169 			TimeoutOutputStream o = new TimeoutOutputStream(rawOut, timer);
1170 			timeoutIn.setTimeout(timeout * 1000);
1171 			o.setTimeout(timeout * 1000);
1172 			rawIn = timeoutIn;
1173 			rawOut = o;
1174 		}
1175 
1176 		pckIn = new PacketLineIn(rawIn);
1177 		pckOut = new PacketLineOut(rawOut);
1178 		pckOut.setFlushOnEnd(false);
1179 
1180 		enabledCapabilities = new HashSet<>();
1181 		commands = new ArrayList<>();
1182 	}
1183 
1184 	/**
1185 	 * Get advertised refs, or the default if not explicitly advertised.
1186 	 *
1187 	 * @return advertised refs, or the default if not explicitly advertised.
1188 	 */
1189 	private Map<String, Ref> getAdvertisedOrDefaultRefs() {
1190 		if (refs == null)
1191 			setAdvertisedRefs(null, null);
1192 		return refs;
1193 	}
1194 
1195 	/**
1196 	 * Receive a pack from the stream and check connectivity if necessary.
1197 	 *
1198 	 * Visible for out-of-tree subclasses. Subclasses overriding this method
1199 	 * should invoke this implementation, as it alters the instance state (e.g.
1200 	 * it reads the pack from the input and parses it before running the
1201 	 * connectivity checks).
1202 	 *
1203 	 * @throws java.io.IOException
1204 	 *             an error occurred during unpacking or connectivity checking.
1205 	 * @throws LargeObjectException
1206 	 *             an large object needs to be opened for the check.
1207 	 * @throws SubmoduleValidationException
1208 	 *             fails to validate the submodule.
1209 	 */
1210 	protected void receivePackAndCheckConnectivity() throws IOException,
1211 			LargeObjectException, SubmoduleValidationException {
1212 		receivePack();
1213 		if (needCheckConnectivity()) {
1214 			checkSubmodules();
1215 			checkConnectivity();
1216 		}
1217 		parser = null;
1218 	}
1219 
1220 	/**
1221 	 * Unlock the pack written by this object.
1222 	 *
1223 	 * @throws java.io.IOException
1224 	 *             the pack could not be unlocked.
1225 	 */
1226 	private void unlockPack() throws IOException {
1227 		if (packLock != null) {
1228 			packLock.unlock();
1229 			packLock = null;
1230 		}
1231 	}
1232 
1233 	/**
1234 	 * Generate an advertisement of available refs and capabilities.
1235 	 *
1236 	 * @param adv
1237 	 *            the advertisement formatter.
1238 	 * @throws java.io.IOException
1239 	 *             the formatter failed to write an advertisement.
1240 	 * @throws org.eclipse.jgit.transport.ServiceMayNotContinueException
1241 	 *             the hook denied advertisement.
1242 	 */
1243 	public void sendAdvertisedRefs(RefAdvertiser adv)
1244 			throws IOException, ServiceMayNotContinueException {
1245 		if (advertiseError != null) {
1246 			adv.writeOne("ERR " + advertiseError); //$NON-NLS-1$
1247 			return;
1248 		}
1249 
1250 		try {
1251 			advertiseRefsHook.advertiseRefs(this);
1252 		} catch (ServiceMayNotContinueException fail) {
1253 			if (fail.getMessage() != null) {
1254 				adv.writeOne("ERR " + fail.getMessage()); //$NON-NLS-1$
1255 				fail.setOutput();
1256 			}
1257 			throw fail;
1258 		}
1259 
1260 		adv.init(db);
1261 		adv.advertiseCapability(CAPABILITY_SIDE_BAND_64K);
1262 		adv.advertiseCapability(CAPABILITY_DELETE_REFS);
1263 		adv.advertiseCapability(CAPABILITY_REPORT_STATUS);
1264 		if (allowQuiet)
1265 			adv.advertiseCapability(CAPABILITY_QUIET);
1266 		String nonce = getPushCertificateParser().getAdvertiseNonce();
1267 		if (nonce != null) {
1268 			adv.advertiseCapability(nonce);
1269 		}
1270 		if (db.getRefDatabase().performsAtomicTransactions())
1271 			adv.advertiseCapability(CAPABILITY_ATOMIC);
1272 		if (allowOfsDelta)
1273 			adv.advertiseCapability(CAPABILITY_OFS_DELTA);
1274 		if (allowPushOptions) {
1275 			adv.advertiseCapability(CAPABILITY_PUSH_OPTIONS);
1276 		}
1277 		adv.advertiseCapability(OPTION_AGENT, UserAgent.get());
1278 		adv.send(getAdvertisedOrDefaultRefs().values());
1279 		for (ObjectId obj : advertisedHaves)
1280 			adv.advertiseHave(obj);
1281 		if (adv.isEmpty())
1282 			adv.advertiseId(ObjectId.zeroId(), "capabilities^{}"); //$NON-NLS-1$
1283 		adv.end();
1284 	}
1285 
1286 	/**
1287 	 * Returns the statistics on the received pack if available. This should be
1288 	 * called after {@link #receivePack} is called.
1289 	 *
1290 	 * @return ReceivedPackStatistics
1291 	 * @since 4.6
1292 	 */
1293 	@Nullable
1294 	public ReceivedPackStatistics getReceivedPackStatistics() {
1295 		return stats;
1296 	}
1297 
1298 	/**
1299 	 * Receive a list of commands from the input.
1300 	 *
1301 	 * @throws java.io.IOException
1302 	 */
1303 	private void recvCommands() throws IOException {
1304 		PacketLineIn pck = maxCommandBytes > 0
1305 				? new PacketLineIn(rawIn, maxCommandBytes)
1306 				: pckIn;
1307 		PushCertificateParser certParser = getPushCertificateParser();
1308 		boolean firstPkt = true;
1309 		try {
1310 			for (;;) {
1311 				String line;
1312 				try {
1313 					line = pck.readString();
1314 				} catch (EOFException eof) {
1315 					if (commands.isEmpty())
1316 						return;
1317 					throw eof;
1318 				}
1319 				if (PacketLineIn.isEnd(line)) {
1320 					break;
1321 				}
1322 
1323 				if (line.length() >= 48 && line.startsWith("shallow ")) { //$NON-NLS-1$
1324 					parseShallow(line.substring(8, 48));
1325 					continue;
1326 				}
1327 
1328 				if (firstPkt) {
1329 					firstPkt = false;
1330 					FirstCommand firstLine = FirstCommand.fromLine(line);
1331 					enabledCapabilities = firstLine.getCapabilities();
1332 					line = firstLine.getLine();
1333 					enableCapabilities();
1334 
1335 					if (line.equals(GitProtocolConstants.OPTION_PUSH_CERT)) {
1336 						certParser.receiveHeader(pck, !isBiDirectionalPipe());
1337 						continue;
1338 					}
1339 				}
1340 
1341 				if (line.equals(PushCertificateParser.BEGIN_SIGNATURE)) {
1342 					certParser.receiveSignature(pck);
1343 					continue;
1344 				}
1345 
1346 				ReceiveCommand cmd = parseCommand(line);
1347 				if (cmd.getRefName().equals(Constants.HEAD)) {
1348 					cmd.setResult(Result.REJECTED_CURRENT_BRANCH);
1349 				} else {
1350 					cmd.setRef(refs.get(cmd.getRefName()));
1351 				}
1352 				commands.add(cmd);
1353 				if (certParser.enabled()) {
1354 					certParser.addCommand(cmd);
1355 				}
1356 			}
1357 			pushCert = certParser.build();
1358 			if (hasCommands()) {
1359 				readPostCommands(pck);
1360 			}
1361 		} catch (Throwable t) {
1362 			discardCommands();
1363 			throw t;
1364 		}
1365 	}
1366 
1367 	private void discardCommands() {
1368 		if (sideBand) {
1369 			long max = maxDiscardBytes;
1370 			if (max < 0) {
1371 				max = Math.max(3 * maxCommandBytes, 3L << 20);
1372 			}
1373 			try {
1374 				new PacketLineIn(rawIn, max).discardUntilEnd();
1375 			} catch (IOException e) {
1376 				// Ignore read failures attempting to discard.
1377 			}
1378 		}
1379 	}
1380 
1381 	private void parseShallow(String idStr) throws PackProtocolException {
1382 		ObjectId id;
1383 		try {
1384 			id = ObjectId.fromString(idStr);
1385 		} catch (InvalidObjectIdException e) {
1386 			throw new PackProtocolException(e.getMessage(), e);
1387 		}
1388 		clientShallowCommits.add(id);
1389 	}
1390 
1391 	/**
1392 	 * @param in
1393 	 *            request stream.
1394 	 * @throws IOException
1395 	 *             request line cannot be read.
1396 	 */
1397 	void readPostCommands(PacketLineIn in) throws IOException {
1398 		if (usePushOptions) {
1399 			pushOptions = new ArrayList<>(4);
1400 			for (;;) {
1401 				String option = in.readString();
1402 				if (PacketLineIn.isEnd(option)) {
1403 					break;
1404 				}
1405 				pushOptions.add(option);
1406 			}
1407 		}
1408 	}
1409 
1410 	/**
1411 	 * Enable capabilities based on a previously read capabilities line.
1412 	 */
1413 	private void enableCapabilities() {
1414 		reportStatus = isCapabilityEnabled(CAPABILITY_REPORT_STATUS);
1415 		usePushOptions = isCapabilityEnabled(CAPABILITY_PUSH_OPTIONS);
1416 		sideBand = isCapabilityEnabled(CAPABILITY_SIDE_BAND_64K);
1417 		quiet = allowQuiet && isCapabilityEnabled(CAPABILITY_QUIET);
1418 		if (sideBand) {
1419 			OutputStream out = rawOut;
1420 
1421 			rawOut = new SideBandOutputStream(CH_DATA, MAX_BUF, out);
1422 			msgOut = new SideBandOutputStream(CH_PROGRESS, MAX_BUF, out);
1423 			errOut = new SideBandOutputStream(CH_ERROR, MAX_BUF, out);
1424 
1425 			pckOut = new PacketLineOut(rawOut);
1426 			pckOut.setFlushOnEnd(false);
1427 		}
1428 	}
1429 
1430 	/**
1431 	 * Check if the peer requested a capability.
1432 	 *
1433 	 * @param name
1434 	 *            protocol name identifying the capability.
1435 	 * @return true if the peer requested the capability to be enabled.
1436 	 */
1437 	private boolean isCapabilityEnabled(String name) {
1438 		return enabledCapabilities.contains(name);
1439 	}
1440 
1441 	private void checkRequestWasRead() {
1442 		if (enabledCapabilities == null)
1443 			throw new RequestNotYetReadException();
1444 	}
1445 
1446 	/**
1447 	 * Whether a pack is expected based on the list of commands.
1448 	 *
1449 	 * @return {@code true} if a pack is expected based on the list of commands.
1450 	 */
1451 	private boolean needPack() {
1452 		for (ReceiveCommand cmd : commands) {
1453 			if (cmd.getType() != ReceiveCommand.Type.DELETE)
1454 				return true;
1455 		}
1456 		return false;
1457 	}
1458 
1459 	/**
1460 	 * Receive a pack from the input and store it in the repository.
1461 	 *
1462 	 * @throws IOException
1463 	 *             an error occurred reading or indexing the pack.
1464 	 */
1465 	private void receivePack() throws IOException {
1466 		// It might take the client a while to pack the objects it needs
1467 		// to send to us. We should increase our timeout so we don't
1468 		// abort while the client is computing.
1469 		//
1470 		if (timeoutIn != null)
1471 			timeoutIn.setTimeout(10 * timeout * 1000);
1472 
1473 		ProgressMonitor receiving = NullProgressMonitor.INSTANCE;
1474 		ProgressMonitor resolving = NullProgressMonitor.INSTANCE;
1475 		if (sideBand && !quiet)
1476 			resolving = new SideBandProgressMonitor(msgOut);
1477 
1478 		try (ObjectInserter ins = db.newObjectInserter()) {
1479 			String lockMsg = "jgit receive-pack"; //$NON-NLS-1$
1480 			if (getRefLogIdent() != null)
1481 				lockMsg += " from " + getRefLogIdent().toExternalString(); //$NON-NLS-1$
1482 
1483 			parser = ins.newPackParser(packInputStream());
1484 			parser.setAllowThin(true);
1485 			parser.setNeedNewObjectIds(checkReferencedAreReachable);
1486 			parser.setNeedBaseObjectIds(checkReferencedAreReachable);
1487 			parser.setCheckEofAfterPackFooter(!biDirectionalPipe
1488 					&& !isExpectDataAfterPackFooter());
1489 			parser.setExpectDataAfterPackFooter(isExpectDataAfterPackFooter());
1490 			parser.setObjectChecker(objectChecker);
1491 			parser.setLockMessage(lockMsg);
1492 			parser.setMaxObjectSizeLimit(maxObjectSizeLimit);
1493 			packLock = parser.parse(receiving, resolving);
1494 			packSize = Long.valueOf(parser.getPackSize());
1495 			stats = parser.getReceivedPackStatistics();
1496 			ins.flush();
1497 		}
1498 
1499 		if (timeoutIn != null)
1500 			timeoutIn.setTimeout(timeout * 1000);
1501 	}
1502 
1503 	private InputStream packInputStream() {
1504 		InputStream packIn = rawIn;
1505 		if (maxPackSizeLimit >= 0) {
1506 			packIn = new LimitedInputStream(packIn, maxPackSizeLimit) {
1507 				@Override
1508 				protected void limitExceeded() throws TooLargePackException {
1509 					throw new TooLargePackException(limit);
1510 				}
1511 			};
1512 		}
1513 		return packIn;
1514 	}
1515 
1516 	private boolean needCheckConnectivity() {
1517 		return isCheckReceivedObjects()
1518 				|| isCheckReferencedObjectsAreReachable()
1519 				|| !getClientShallowCommits().isEmpty();
1520 	}
1521 
1522 	private void checkSubmodules() throws IOException, LargeObjectException,
1523 			SubmoduleValidationException {
1524 		ObjectDatabase odb = db.getObjectDatabase();
1525 		if (objectChecker == null) {
1526 			return;
1527 		}
1528 		for (GitmoduleEntry entry : objectChecker.getGitsubmodules()) {
1529 			AnyObjectId blobId = entry.getBlobId();
1530 			ObjectLoader blob = odb.open(blobId, Constants.OBJ_BLOB);
1531 
1532 			SubmoduleValidator.assertValidGitModulesFile(
1533 					new String(blob.getBytes(), UTF_8));
1534 		}
1535 	}
1536 
1537 	private void checkConnectivity() throws IOException {
1538 		ProgressMonitor checking = NullProgressMonitor.INSTANCE;
1539 		if (sideBand && !quiet) {
1540 			SideBandProgressMonitor m = new SideBandProgressMonitor(msgOut);
1541 			m.setDelayStart(750, TimeUnit.MILLISECONDS);
1542 			checking = m;
1543 		}
1544 
1545 		connectivityChecker.checkConnectivity(createConnectivityCheckInfo(),
1546 				advertisedHaves, checking);
1547 	}
1548 
1549 	private ConnectivityCheckInfo createConnectivityCheckInfo() {
1550 		ConnectivityCheckInfo info = new ConnectivityCheckInfo();
1551 		info.setCheckObjects(checkReferencedAreReachable);
1552 		info.setCommands(getAllCommands());
1553 		info.setRepository(db);
1554 		info.setParser(parser);
1555 		info.setWalk(walk);
1556 		return info;
1557 	}
1558 
1559 	/**
1560 	 * Validate the command list.
1561 	 */
1562 	private void validateCommands() {
1563 		for (ReceiveCommand cmd : commands) {
1564 			final Ref ref = cmd.getRef();
1565 			if (cmd.getResult() != Result.NOT_ATTEMPTED)
1566 				continue;
1567 
1568 			if (cmd.getType() == ReceiveCommand.Type.DELETE) {
1569 				if (!isAllowDeletes()) {
1570 					// Deletes are not supported on this repository.
1571 					cmd.setResult(Result.REJECTED_NODELETE);
1572 					continue;
1573 				}
1574 				if (!isAllowBranchDeletes()
1575 						&& ref.getName().startsWith(Constants.R_HEADS)) {
1576 					// Branches cannot be deleted, but other refs can.
1577 					cmd.setResult(Result.REJECTED_NODELETE);
1578 					continue;
1579 				}
1580 			}
1581 
1582 			if (cmd.getType() == ReceiveCommand.Type.CREATE) {
1583 				if (!isAllowCreates()) {
1584 					cmd.setResult(Result.REJECTED_NOCREATE);
1585 					continue;
1586 				}
1587 
1588 				if (ref != null && !isAllowNonFastForwards()) {
1589 					// Creation over an existing ref is certainly not going
1590 					// to be a fast-forward update. We can reject it early.
1591 					//
1592 					cmd.setResult(Result.REJECTED_NONFASTFORWARD);
1593 					continue;
1594 				}
1595 
1596 				if (ref != null) {
1597 					// A well behaved client shouldn't have sent us a
1598 					// create command for a ref we advertised to it.
1599 					//
1600 					cmd.setResult(Result.REJECTED_OTHER_REASON,
1601 							JGitText.get().refAlreadyExists);
1602 					continue;
1603 				}
1604 			}
1605 
1606 			if (cmd.getType() == ReceiveCommand.Type.DELETE && ref != null) {
1607 				ObjectId id = ref.getObjectId();
1608 				if (id == null) {
1609 					id = ObjectId.zeroId();
1610 				}
1611 				if (!ObjectId.zeroId().equals(cmd.getOldId())
1612 						&& !id.equals(cmd.getOldId())) {
1613 					// Delete commands can be sent with the old id matching our
1614 					// advertised value, *OR* with the old id being 0{40}. Any
1615 					// other requested old id is invalid.
1616 					//
1617 					cmd.setResult(Result.REJECTED_OTHER_REASON,
1618 							JGitText.get().invalidOldIdSent);
1619 					continue;
1620 				}
1621 			}
1622 
1623 			if (cmd.getType() == ReceiveCommand.Type.UPDATE) {
1624 				if (ref == null) {
1625 					// The ref must have been advertised in order to be updated.
1626 					//
1627 					cmd.setResult(Result.REJECTED_OTHER_REASON,
1628 							JGitText.get().noSuchRef);
1629 					continue;
1630 				}
1631 				ObjectId id = ref.getObjectId();
1632 				if (id == null) {
1633 					// We cannot update unborn branch
1634 					cmd.setResult(Result.REJECTED_OTHER_REASON,
1635 							JGitText.get().cannotUpdateUnbornBranch);
1636 					continue;
1637 				}
1638 
1639 				if (!id.equals(cmd.getOldId())) {
1640 					// A properly functioning client will send the same
1641 					// object id we advertised.
1642 					//
1643 					cmd.setResult(Result.REJECTED_OTHER_REASON,
1644 							JGitText.get().invalidOldIdSent);
1645 					continue;
1646 				}
1647 
1648 				// Is this possibly a non-fast-forward style update?
1649 				//
1650 				RevObject oldObj, newObj;
1651 				try {
1652 					oldObj = walk.parseAny(cmd.getOldId());
1653 				} catch (IOException e) {
1654 					receiveCommandErrorHandler
1655 							.handleOldIdValidationException(cmd, e);
1656 					continue;
1657 				}
1658 
1659 				try {
1660 					newObj = walk.parseAny(cmd.getNewId());
1661 				} catch (IOException e) {
1662 					receiveCommandErrorHandler
1663 							.handleNewIdValidationException(cmd, e);
1664 					continue;
1665 				}
1666 
1667 				if (oldObj instanceof RevCommit
1668 						&& newObj instanceof RevCommit) {
1669 					try {
1670 						if (walk.isMergedInto((RevCommit) oldObj,
1671 								(RevCommit) newObj)) {
1672 							cmd.setTypeFastForwardUpdate();
1673 						} else {
1674 							cmd.setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
1675 						}
1676 					} catch (IOException e) {
1677 						receiveCommandErrorHandler
1678 								.handleFastForwardCheckException(cmd, e);
1679 					}
1680 				} else {
1681 					cmd.setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
1682 				}
1683 
1684 				if (cmd.getType() == ReceiveCommand.Type.UPDATE_NONFASTFORWARD
1685 						&& !isAllowNonFastForwards()) {
1686 					cmd.setResult(Result.REJECTED_NONFASTFORWARD);
1687 					continue;
1688 				}
1689 			}
1690 
1691 			if (!cmd.getRefName().startsWith(Constants.R_REFS)
1692 					|| !Repository.isValidRefName(cmd.getRefName())) {
1693 				cmd.setResult(Result.REJECTED_OTHER_REASON,
1694 						JGitText.get().funnyRefname);
1695 			}
1696 		}
1697 	}
1698 
1699 	/**
1700 	 * Whether any commands have been rejected so far.
1701 	 *
1702 	 * @return if any commands have been rejected so far.
1703 	 */
1704 	private boolean anyRejects() {
1705 		for (ReceiveCommand cmd : commands) {
1706 			if (cmd.getResult() != Result.NOT_ATTEMPTED
1707 					&& cmd.getResult() != Result.OK)
1708 				return true;
1709 		}
1710 		return false;
1711 	}
1712 
1713 	/**
1714 	 * Set the result to fail for any command that was not processed yet.
1715 	 *
1716 	 */
1717 	private void failPendingCommands() {
1718 		ReceiveCommand.abort(commands);
1719 	}
1720 
1721 	/**
1722 	 * Filter the list of commands according to result.
1723 	 *
1724 	 * @param want
1725 	 *            desired status to filter by.
1726 	 * @return a copy of the command list containing only those commands with
1727 	 *         the desired status.
1728 	 * @since 5.7
1729 	 */
1730 	protected List<ReceiveCommand> filterCommands(Result want) {
1731 		return ReceiveCommand.filter(commands, want);
1732 	}
1733 
1734 	/**
1735 	 * Execute commands to update references.
1736 	 * @since 5.7
1737 	 */
1738 	protected void executeCommands() {
1739 		List<ReceiveCommand> toApply = filterCommands(Result.NOT_ATTEMPTED);
1740 		if (toApply.isEmpty())
1741 			return;
1742 
1743 		ProgressMonitor updating = NullProgressMonitor.INSTANCE;
1744 		if (sideBand) {
1745 			SideBandProgressMonitor pm = new SideBandProgressMonitor(msgOut);
1746 			pm.setDelayStart(250, TimeUnit.MILLISECONDS);
1747 			updating = pm;
1748 		}
1749 
1750 		BatchRefUpdate batch = db.getRefDatabase().newBatchUpdate();
1751 		batch.setAllowNonFastForwards(isAllowNonFastForwards());
1752 		batch.setAtomic(isAtomic());
1753 		batch.setRefLogIdent(getRefLogIdent());
1754 		batch.setRefLogMessage("push", true); //$NON-NLS-1$
1755 		batch.addCommand(toApply);
1756 		try {
1757 			batch.setPushCertificate(getPushCertificate());
1758 			batch.execute(walk, updating);
1759 		} catch (IOException e) {
1760 			receiveCommandErrorHandler.handleBatchRefUpdateException(toApply,
1761 					e);
1762 		}
1763 	}
1764 
1765 	/**
1766 	 * Send a status report.
1767 	 *
1768 	 * @param unpackError
1769 	 *            an error that occurred during unpacking, or {@code null}
1770 	 * @throws java.io.IOException
1771 	 *             an error occurred writing the status report.
1772 	 * @since 5.6
1773 	 */
1774 	private void sendStatusReport(Throwable unpackError) throws IOException {
1775 		Reporter out = new Reporter() {
1776 			@Override
1777 			void sendString(String s) throws IOException {
1778 				if (reportStatus) {
1779 					pckOut.writeString(s + "\n"); //$NON-NLS-1$
1780 				} else if (msgOut != null) {
1781 					msgOut.write(Constants.encode(s + "\n")); //$NON-NLS-1$
1782 				}
1783 			}
1784 		};
1785 
1786 		try {
1787 			if (unpackError != null) {
1788 				out.sendString("unpack error " + unpackError.getMessage()); //$NON-NLS-1$
1789 				if (reportStatus) {
1790 					for (ReceiveCommand cmd : commands) {
1791 						out.sendString("ng " + cmd.getRefName() //$NON-NLS-1$
1792 								+ " n/a (unpacker error)"); //$NON-NLS-1$
1793 					}
1794 				}
1795 				return;
1796 			}
1797 
1798 			if (reportStatus) {
1799 				out.sendString("unpack ok"); //$NON-NLS-1$
1800 			}
1801 			for (ReceiveCommand cmd : commands) {
1802 				if (cmd.getResult() == Result.OK) {
1803 					if (reportStatus) {
1804 						out.sendString("ok " + cmd.getRefName()); //$NON-NLS-1$
1805 					}
1806 					continue;
1807 				}
1808 
1809 				final StringBuilder r = new StringBuilder();
1810 				if (reportStatus) {
1811 					r.append("ng ").append(cmd.getRefName()).append(" "); //$NON-NLS-1$ //$NON-NLS-2$
1812 				} else {
1813 					r.append(" ! [rejected] ").append(cmd.getRefName()) //$NON-NLS-1$
1814 							.append(" ("); //$NON-NLS-1$
1815 				}
1816 
1817 				if (cmd.getResult() == Result.REJECTED_MISSING_OBJECT) {
1818 					if (cmd.getMessage() == null)
1819 						r.append("missing object(s)"); //$NON-NLS-1$
1820 					else if (cmd.getMessage()
1821 							.length() == Constants.OBJECT_ID_STRING_LENGTH) {
1822 						// TODO: Using get/setMessage to store an OID is a
1823 						// misuse. The caller should set a full error message.
1824 						r.append("object "); //$NON-NLS-1$
1825 						r.append(cmd.getMessage());
1826 						r.append(" missing"); //$NON-NLS-1$
1827 					} else {
1828 						r.append(cmd.getMessage());
1829 					}
1830 				} else if (cmd.getMessage() != null) {
1831 					r.append(cmd.getMessage());
1832 				} else {
1833 					switch (cmd.getResult()) {
1834 					case NOT_ATTEMPTED:
1835 						r.append("server bug; ref not processed"); //$NON-NLS-1$
1836 						break;
1837 
1838 					case REJECTED_NOCREATE:
1839 						r.append("creation prohibited"); //$NON-NLS-1$
1840 						break;
1841 
1842 					case REJECTED_NODELETE:
1843 						r.append("deletion prohibited"); //$NON-NLS-1$
1844 						break;
1845 
1846 					case REJECTED_NONFASTFORWARD:
1847 						r.append("non-fast forward"); //$NON-NLS-1$
1848 						break;
1849 
1850 					case REJECTED_CURRENT_BRANCH:
1851 						r.append("branch is currently checked out"); //$NON-NLS-1$
1852 						break;
1853 
1854 					case REJECTED_OTHER_REASON:
1855 						r.append("unspecified reason"); //$NON-NLS-1$
1856 						break;
1857 
1858 					case LOCK_FAILURE:
1859 						r.append("failed to lock"); //$NON-NLS-1$
1860 						break;
1861 
1862 					case REJECTED_MISSING_OBJECT:
1863 					case OK:
1864 						// We shouldn't have reached this case (see 'ok' case
1865 						// above and if-statement above).
1866 						throw new AssertionError();
1867 					}
1868 				}
1869 
1870 				if (!reportStatus) {
1871 					r.append(")"); //$NON-NLS-1$
1872 				}
1873 				out.sendString(r.toString());
1874 			}
1875 		} finally {
1876 			if (reportStatus) {
1877 				pckOut.end();
1878 			}
1879 		}
1880 	}
1881 
1882 	/**
1883 	 * Close and flush (if necessary) the underlying streams.
1884 	 *
1885 	 * @throws java.io.IOException
1886 	 */
1887 	private void close() throws IOException {
1888 		if (sideBand) {
1889 			// If we are using side band, we need to send a final
1890 			// flush-pkt to tell the remote peer the side band is
1891 			// complete and it should stop decoding. We need to
1892 			// use the original output stream as rawOut is now the
1893 			// side band data channel.
1894 			//
1895 			((SideBandOutputStream) msgOut).flushBuffer();
1896 			((SideBandOutputStream) rawOut).flushBuffer();
1897 
1898 			PacketLineOut plo = new PacketLineOut(origOut);
1899 			plo.setFlushOnEnd(false);
1900 			plo.end();
1901 		}
1902 
1903 		if (biDirectionalPipe) {
1904 			// If this was a native git connection, flush the pipe for
1905 			// the caller. For smart HTTP we don't do this flush and
1906 			// instead let the higher level HTTP servlet code do it.
1907 			//
1908 			if (!sideBand && msgOut != null)
1909 				msgOut.flush();
1910 			rawOut.flush();
1911 		}
1912 	}
1913 
1914 	/**
1915 	 * Release any resources used by this object.
1916 	 *
1917 	 * @throws java.io.IOException
1918 	 *             the pack could not be unlocked.
1919 	 */
1920 	private void release() throws IOException {
1921 		walk.close();
1922 		unlockPack();
1923 		timeoutIn = null;
1924 		rawIn = null;
1925 		rawOut = null;
1926 		msgOut = null;
1927 		pckIn = null;
1928 		pckOut = null;
1929 		refs = null;
1930 		// Keep the capabilities. If responses are sent after this release
1931 		// we need to remember at least whether sideband communication has to be
1932 		// used
1933 		commands = null;
1934 		if (timer != null) {
1935 			try {
1936 				timer.terminate();
1937 			} finally {
1938 				timer = null;
1939 			}
1940 		}
1941 	}
1942 
1943 	/** Interface for reporting status messages. */
1944 	abstract static class Reporter {
1945 		abstract void sendString(String s) throws IOException;
1946 	}
1947 
1948 	/**
1949 	 * Get the push certificate used to verify the pusher's identity.
1950 	 * <p>
1951 	 * Only valid after commands are read from the wire.
1952 	 *
1953 	 * @return the parsed certificate, or null if push certificates are disabled
1954 	 *         or no cert was presented by the client.
1955 	 * @since 4.1
1956 	 */
1957 	public PushCertificate getPushCertificate() {
1958 		return pushCert;
1959 	}
1960 
1961 	/**
1962 	 * Set the push certificate used to verify the pusher's identity.
1963 	 * <p>
1964 	 * Should only be called if reconstructing an instance without going through
1965 	 * the normal {@link #recvCommands()} flow.
1966 	 *
1967 	 * @param cert
1968 	 *            the push certificate to set.
1969 	 * @since 4.1
1970 	 */
1971 	public void setPushCertificate(PushCertificate cert) {
1972 		pushCert = cert;
1973 	}
1974 
1975 	/**
1976 	 * Gets an unmodifiable view of the option strings associated with the push.
1977 	 *
1978 	 * @return an unmodifiable view of pushOptions, or null (if pushOptions is).
1979 	 * @since 4.5
1980 	 */
1981 	@Nullable
1982 	public List<String> getPushOptions() {
1983 		if (isAllowPushOptions() && usePushOptions) {
1984 			return Collections.unmodifiableList(pushOptions);
1985 		}
1986 
1987 		// The client doesn't support push options. Return null to
1988 		// distinguish this from the case where the client declared support
1989 		// for push options and sent an empty list of them.
1990 		return null;
1991 	}
1992 
1993 	/**
1994 	 * Set the push options supplied by the client.
1995 	 * <p>
1996 	 * Should only be called if reconstructing an instance without going through
1997 	 * the normal {@link #recvCommands()} flow.
1998 	 *
1999 	 * @param options
2000 	 *            the list of options supplied by the client. The
2001 	 *            {@code ReceivePack} instance takes ownership of this list.
2002 	 *            Callers are encouraged to first create a copy if the list may
2003 	 *            be modified later.
2004 	 * @since 4.5
2005 	 */
2006 	public void setPushOptions(@Nullable List<String> options) {
2007 		usePushOptions = options != null;
2008 		pushOptions = options;
2009 	}
2010 
2011 	/**
2012 	 * Get the hook invoked before updates occur.
2013 	 *
2014 	 * @return the hook invoked before updates occur.
2015 	 */
2016 	public PreReceiveHook getPreReceiveHook() {
2017 		return preReceive;
2018 	}
2019 
2020 	/**
2021 	 * Set the hook which is invoked prior to commands being executed.
2022 	 * <p>
2023 	 * Only valid commands (those which have no obvious errors according to the
2024 	 * received input and this instance's configuration) are passed into the
2025 	 * hook. The hook may mark a command with a result of any value other than
2026 	 * {@link org.eclipse.jgit.transport.ReceiveCommand.Result#NOT_ATTEMPTED} to
2027 	 * block its execution.
2028 	 * <p>
2029 	 * The hook may be called with an empty command collection if the current
2030 	 * set is completely invalid.
2031 	 *
2032 	 * @param h
2033 	 *            the hook instance; may be null to disable the hook.
2034 	 */
2035 	public void setPreReceiveHook(PreReceiveHook h) {
2036 		preReceive = h != null ? h : PreReceiveHook.NULL;
2037 	}
2038 
2039 	/**
2040 	 * Get the hook invoked after updates occur.
2041 	 *
2042 	 * @return the hook invoked after updates occur.
2043 	 */
2044 	public PostReceiveHook getPostReceiveHook() {
2045 		return postReceive;
2046 	}
2047 
2048 	/**
2049 	 * Set the hook which is invoked after commands are executed.
2050 	 * <p>
2051 	 * Only successful commands (type is
2052 	 * {@link org.eclipse.jgit.transport.ReceiveCommand.Result#OK}) are passed
2053 	 * into the hook. The hook may be called with an empty command collection if
2054 	 * the current set all resulted in an error.
2055 	 *
2056 	 * @param h
2057 	 *            the hook instance; may be null to disable the hook.
2058 	 */
2059 	public void setPostReceiveHook(PostReceiveHook h) {
2060 		postReceive = h != null ? h : PostReceiveHook.NULL;
2061 	}
2062 
2063 	/**
2064 	 * Get the current unpack error handler.
2065 	 *
2066 	 * @return the current unpack error handler.
2067 	 * @since 5.8
2068 	 */
2069 	public UnpackErrorHandler getUnpackErrorHandler() {
2070 		return unpackErrorHandler;
2071 	}
2072 
2073 	/**
2074 	 * @param unpackErrorHandler
2075 	 *            the unpackErrorHandler to set
2076 	 * @since 5.7
2077 	 */
2078 	public void setUnpackErrorHandler(UnpackErrorHandler unpackErrorHandler) {
2079 		this.unpackErrorHandler = unpackErrorHandler;
2080 	}
2081 
2082 	/**
2083 	 * Set whether this class will report command failures as warning messages
2084 	 * before sending the command results.
2085 	 *
2086 	 * @param echo
2087 	 *            if true this class will report command failures as warning
2088 	 *            messages before sending the command results. This is usually
2089 	 *            not necessary, but may help buggy Git clients that discard the
2090 	 *            errors when all branches fail.
2091 	 * @deprecated no widely used Git versions need this any more
2092 	 */
2093 	@Deprecated
2094 	public void setEchoCommandFailures(boolean echo) {
2095 		// No-op.
2096 	}
2097 
2098 	/**
2099 	 * Execute the receive task on the socket.
2100 	 *
2101 	 * @param input
2102 	 *            raw input to read client commands and pack data from. Caller
2103 	 *            must ensure the input is buffered, otherwise read performance
2104 	 *            may suffer.
2105 	 * @param output
2106 	 *            response back to the Git network client. Caller must ensure
2107 	 *            the output is buffered, otherwise write performance may
2108 	 *            suffer.
2109 	 * @param messages
2110 	 *            secondary "notice" channel to send additional messages out
2111 	 *            through. When run over SSH this should be tied back to the
2112 	 *            standard error channel of the command execution. For most
2113 	 *            other network connections this should be null.
2114 	 * @throws java.io.IOException
2115 	 */
2116 	public void receive(final InputStream input, final OutputStream output,
2117 			final OutputStream messages) throws IOException {
2118 		init(input, output, messages);
2119 		try {
2120 			service();
2121 		} catch (PackProtocolException e) {
2122 			fatalError(e.getMessage());
2123 			throw e;
2124 		} catch (InputOverLimitIOException e) {
2125 			String msg = JGitText.get().tooManyCommands;
2126 			fatalError(msg);
2127 			throw new PackProtocolException(msg, e);
2128 		} finally {
2129 			try {
2130 				close();
2131 			} finally {
2132 				release();
2133 			}
2134 		}
2135 	}
2136 
2137 	/**
2138 	 * Execute the receive task on the socket.
2139 	 *
2140 	 * <p>
2141 	 * Same as {@link #receive}, but the exceptions are not reported to the
2142 	 * client yet.
2143 	 *
2144 	 * @param input
2145 	 *            raw input to read client commands and pack data from. Caller
2146 	 *            must ensure the input is buffered, otherwise read performance
2147 	 *            may suffer.
2148 	 * @param output
2149 	 *            response back to the Git network client. Caller must ensure
2150 	 *            the output is buffered, otherwise write performance may
2151 	 *            suffer.
2152 	 * @param messages
2153 	 *            secondary "notice" channel to send additional messages out
2154 	 *            through. When run over SSH this should be tied back to the
2155 	 *            standard error channel of the command execution. For most
2156 	 *            other network connections this should be null.
2157 	 * @throws java.io.IOException
2158 	 * @since 5.7
2159 	 */
2160 	public void receiveWithExceptionPropagation(InputStream input,
2161 			OutputStream output, OutputStream messages) throws IOException {
2162 		init(input, output, messages);
2163 		try {
2164 			service();
2165 		} finally {
2166 			try {
2167 				close();
2168 			} finally {
2169 				release();
2170 			}
2171 		}
2172 	}
2173 
2174 	private void service() throws IOException {
2175 		if (isBiDirectionalPipe()) {
2176 			sendAdvertisedRefs(new PacketLineOutRefAdvertiser(pckOut));
2177 			pckOut.flush();
2178 		} else
2179 			getAdvertisedOrDefaultRefs();
2180 		if (hasError())
2181 			return;
2182 
2183 		recvCommands();
2184 
2185 		if (hasCommands()) {
2186 			try (PostReceiveExecutor e = new PostReceiveExecutor()) {
2187 				if (needPack()) {
2188 					try {
2189 						receivePackAndCheckConnectivity();
2190 					} catch (IOException | RuntimeException
2191 							| SubmoduleValidationException | Error err) {
2192 						unlockPack();
2193 						unpackErrorHandler.handleUnpackException(err);
2194 						throw new UnpackException(err);
2195 					}
2196 				}
2197 
2198 				try {
2199 					setAtomic(isCapabilityEnabled(CAPABILITY_ATOMIC));
2200 
2201 					validateCommands();
2202 					if (atomic && anyRejects()) {
2203 						failPendingCommands();
2204 					}
2205 
2206 					preReceive.onPreReceive(
2207 							this, filterCommands(Result.NOT_ATTEMPTED));
2208 					if (atomic && anyRejects()) {
2209 						failPendingCommands();
2210 					}
2211 					executeCommands();
2212 				} finally {
2213 					unlockPack();
2214 				}
2215 
2216 				sendStatusReport(null);
2217 			}
2218 			autoGc();
2219 		}
2220 	}
2221 
2222 	private void autoGc() {
2223 		Repository repo = getRepository();
2224 		if (!repo.getConfig().getBoolean(ConfigConstants.CONFIG_RECEIVE_SECTION,
2225 				ConfigConstants.CONFIG_KEY_AUTOGC, true)) {
2226 			return;
2227 		}
2228 		repo.autoGC(NullProgressMonitor.INSTANCE);
2229 	}
2230 
2231 	static ReceiveCommand parseCommand(String line)
2232 			throws PackProtocolException {
2233 		if (line == null || line.length() < 83) {
2234 			throw new PackProtocolException(
2235 					JGitText.get().errorInvalidProtocolWantedOldNewRef);
2236 		}
2237 		String oldStr = line.substring(0, 40);
2238 		String newStr = line.substring(41, 81);
2239 		ObjectId oldId, newId;
2240 		try {
2241 			oldId = ObjectId.fromString(oldStr);
2242 			newId = ObjectId.fromString(newStr);
2243 		} catch (InvalidObjectIdException e) {
2244 			throw new PackProtocolException(
2245 					JGitText.get().errorInvalidProtocolWantedOldNewRef, e);
2246 		}
2247 		String name = line.substring(82);
2248 		if (!Repository.isValidRefName(name)) {
2249 			throw new PackProtocolException(
2250 					JGitText.get().errorInvalidProtocolWantedOldNewRef);
2251 		}
2252 		return new ReceiveCommand(oldId, newId, name);
2253 	}
2254 
2255 	private class PostReceiveExecutor implements AutoCloseable {
2256 		@Override
2257 		public void close() {
2258 			postReceive.onPostReceive(ReceivePack.this,
2259 					filterCommands(Result.OK));
2260 		}
2261 	}
2262 
2263 	private class DefaultUnpackErrorHandler implements UnpackErrorHandler {
2264 		@Override
2265 		public void handleUnpackException(Throwable t) throws IOException {
2266 			sendStatusReport(t);
2267 		}
2268 	}
2269 }