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