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.submodule.SubmoduleValidator;
52  import org.eclipse.jgit.internal.submodule.SubmoduleValidator.SubmoduleValidationException;
53  import org.eclipse.jgit.internal.transport.connectivity.FullConnectivityChecker;
54  import org.eclipse.jgit.internal.transport.parser.FirstCommand;
55  import org.eclipse.jgit.lib.AnyObjectId;
56  import org.eclipse.jgit.lib.BatchRefUpdate;
57  import org.eclipse.jgit.lib.Config;
58  import org.eclipse.jgit.lib.ConfigConstants;
59  import org.eclipse.jgit.lib.Constants;
60  import org.eclipse.jgit.lib.GitmoduleEntry;
61  import org.eclipse.jgit.lib.NullProgressMonitor;
62  import org.eclipse.jgit.lib.ObjectChecker;
63  import org.eclipse.jgit.lib.ObjectDatabase;
64  import org.eclipse.jgit.lib.ObjectId;
65  import org.eclipse.jgit.lib.ObjectInserter;
66  import org.eclipse.jgit.lib.ObjectLoader;
67  import org.eclipse.jgit.lib.PersonIdent;
68  import org.eclipse.jgit.lib.ProgressMonitor;
69  import org.eclipse.jgit.lib.Ref;
70  import org.eclipse.jgit.lib.Repository;
71  import org.eclipse.jgit.revwalk.RevCommit;
72  import org.eclipse.jgit.revwalk.RevObject;
73  import org.eclipse.jgit.revwalk.RevWalk;
74  import org.eclipse.jgit.transport.ConnectivityChecker.ConnectivityCheckInfo;
75  import org.eclipse.jgit.transport.PacketLineIn.InputOverLimitIOException;
76  import org.eclipse.jgit.transport.ReceiveCommand.Result;
77  import org.eclipse.jgit.transport.RefAdvertiser.PacketLineOutRefAdvertiser;
78  import org.eclipse.jgit.util.io.InterruptTimer;
79  import org.eclipse.jgit.util.io.LimitedInputStream;
80  import org.eclipse.jgit.util.io.TimeoutInputStream;
81  import org.eclipse.jgit.util.io.TimeoutOutputStream;
82  
83  /**
84   * Implements the server side of a push connection, receiving objects.
85   */
86  public class ReceivePack {
87  	/**
88  	 * Data in the first line of a request, the line itself plus capabilities.
89  	 *
90  	 * @deprecated Use {@link FirstCommand} instead.
91  	 * @since 5.6
92  	 */
93  	@Deprecated
94  	public static class FirstLine {
95  		private final FirstCommand command;
96  
97  		/**
98  		 * Parse the first line of a receive-pack request.
99  		 *
100 		 * @param line
101 		 *            line from the client.
102 		 */
103 		public FirstLine(String line) {
104 			command = FirstCommand.fromLine(line);
105 		}
106 
107 		/** @return non-capabilities part of the line. */
108 		public String getLine() {
109 			return command.getLine();
110 		}
111 
112 		/** @return capabilities parsed from the line. */
113 		public Set<String> getCapabilities() {
114 			return command.getCapabilities();
115 		}
116 	}
117 
118 	/** Database we write the stored objects into. */
119 	private final Repository db;
120 
121 	/** Revision traversal support over {@link #db}. */
122 	private final RevWalk walk;
123 
124 	/**
125 	 * Is the client connection a bi-directional socket or pipe?
126 	 * <p>
127 	 * If true, this class assumes it can perform multiple read and write cycles
128 	 * with the client over the input and output streams. This matches the
129 	 * functionality available with a standard TCP/IP connection, or a local
130 	 * operating system or in-memory pipe.
131 	 * <p>
132 	 * If false, this class runs in a read everything then output results mode,
133 	 * making it suitable for single round-trip systems RPCs such as HTTP.
134 	 */
135 	private boolean biDirectionalPipe = true;
136 
137 	/** Expecting data after the pack footer */
138 	private boolean expectDataAfterPackFooter;
139 
140 	/** Should an incoming transfer validate objects? */
141 	private ObjectChecker objectChecker;
142 
143 	/** Should an incoming transfer permit create requests? */
144 	private boolean allowCreates;
145 
146 	/** Should an incoming transfer permit delete requests? */
147 	private boolean allowAnyDeletes;
148 
149 	private boolean allowBranchDeletes;
150 
151 	/** Should an incoming transfer permit non-fast-forward requests? */
152 	private boolean allowNonFastForwards;
153 
154 	/** Should an incoming transfer permit push options? **/
155 	private boolean allowPushOptions;
156 
157 	/**
158 	 * Should the requested ref updates be performed as a single atomic
159 	 * transaction?
160 	 */
161 	private boolean atomic;
162 
163 	private boolean allowOfsDelta;
164 
165 	private boolean allowQuiet = true;
166 
167 	/** Identity to record action as within the reflog. */
168 	private PersonIdent refLogIdent;
169 
170 	/** Hook used while advertising the refs to the client. */
171 	private AdvertiseRefsHook advertiseRefsHook;
172 
173 	/** Filter used while advertising the refs to the client. */
174 	private RefFilter refFilter;
175 
176 	/** Timeout in seconds to wait for client interaction. */
177 	private int timeout;
178 
179 	/** Timer to manage {@link #timeout}. */
180 	private InterruptTimer timer;
181 
182 	private TimeoutInputStream timeoutIn;
183 
184 	// Original stream passed to init(), since rawOut may be wrapped in a
185 	// sideband.
186 	private OutputStream origOut;
187 
188 	/** Raw input stream. */
189 	private InputStream rawIn;
190 
191 	/** Raw output stream. */
192 	private OutputStream rawOut;
193 
194 	/** Optional message output stream. */
195 	private OutputStream msgOut;
196 
197 	private SideBandOutputStream errOut;
198 
199 	/** Packet line input stream around {@link #rawIn}. */
200 	private PacketLineIn pckIn;
201 
202 	/** Packet line output stream around {@link #rawOut}. */
203 	private PacketLineOut pckOut;
204 
205 	private final MessageOutputWrapper msgOutWrapper = new MessageOutputWrapper();
206 
207 	private PackParser parser;
208 
209 	/** The refs we advertised as existing at the start of the connection. */
210 	private Map<String, Ref> refs;
211 
212 	/** All SHA-1s shown to the client, which can be possible edges. */
213 	private Set<ObjectId> advertisedHaves;
214 
215 	/** Capabilities requested by the client. */
216 	private Set<String> enabledCapabilities;
217 
218 	String userAgent;
219 
220 	private Set<ObjectId> clientShallowCommits;
221 
222 	private List<ReceiveCommand> commands;
223 
224 	private long maxCommandBytes;
225 
226 	private long maxDiscardBytes;
227 
228 	private StringBuilder advertiseError;
229 
230 	/**
231 	 * If {@link BasePackPushConnection#CAPABILITY_SIDE_BAND_64K} is enabled.
232 	 */
233 	private boolean sideBand;
234 
235 	private boolean quiet;
236 
237 	/** Lock around the received pack file, while updating refs. */
238 	private PackLock packLock;
239 
240 	private boolean checkReferencedAreReachable;
241 
242 	/** Git object size limit */
243 	private long maxObjectSizeLimit;
244 
245 	/** Total pack size limit */
246 	private long maxPackSizeLimit = -1;
247 
248 	/** The size of the received pack, including index size */
249 	private Long packSize;
250 
251 	private PushCertificateParser pushCertificateParser;
252 
253 	private SignedPushConfig signedPushConfig;
254 
255 	private PushCertificate pushCert;
256 
257 	private ReceivedPackStatistics stats;
258 
259 	/**
260 	 * Connectivity checker to use.
261 	 * @since 5.7
262 	 */
263 	protected ConnectivityChecker connectivityChecker = new FullConnectivityChecker();
264 
265 	/** Hook to validate the update commands before execution. */
266 	private PreReceiveHook preReceive;
267 
268 	private ReceiveCommandErrorHandler receiveCommandErrorHandler = new ReceiveCommandErrorHandler() {
269 		// Use the default implementation.
270 	};
271 
272 	private UnpackErrorHandler unpackErrorHandler = new DefaultUnpackErrorHandler();
273 
274 	/** Hook to report on the commands after execution. */
275 	private PostReceiveHook postReceive;
276 
277 	/** If {@link BasePackPushConnection#CAPABILITY_REPORT_STATUS} is enabled. */
278 	private boolean reportStatus;
279 
280 	/** Whether the client intends to use push options. */
281 	private boolean usePushOptions;
282 	private List<String> pushOptions;
283 
284 	/**
285 	 * Create a new pack receive for an open repository.
286 	 *
287 	 * @param into
288 	 *            the destination repository.
289 	 */
290 	public ReceivePack(Repository into) {
291 		db = into;
292 		walk = new RevWalk(db);
293 		walk.setRetainBody(false);
294 
295 		TransferConfig tc = db.getConfig().get(TransferConfig.KEY);
296 		objectChecker = tc.newReceiveObjectChecker();
297 
298 		ReceiveConfig rc = db.getConfig().get(ReceiveConfig::new);
299 		allowCreates = rc.allowCreates;
300 		allowAnyDeletes = true;
301 		allowBranchDeletes = rc.allowDeletes;
302 		allowNonFastForwards = rc.allowNonFastForwards;
303 		allowOfsDelta = rc.allowOfsDelta;
304 		allowPushOptions = rc.allowPushOptions;
305 		maxCommandBytes = rc.maxCommandBytes;
306 		maxDiscardBytes = rc.maxDiscardBytes;
307 		advertiseRefsHook = AdvertiseRefsHook.DEFAULT;
308 		refFilter = RefFilter.DEFAULT;
309 		advertisedHaves = new HashSet<>();
310 		clientShallowCommits = new HashSet<>();
311 		signedPushConfig = rc.signedPush;
312 		preReceive = PreReceiveHook.NULL;
313 		postReceive = PostReceiveHook.NULL;
314 	}
315 
316 	/** Configuration for receive operations. */
317 	private static class ReceiveConfig {
318 		final boolean allowCreates;
319 
320 		final boolean allowDeletes;
321 
322 		final boolean allowNonFastForwards;
323 
324 		final boolean allowOfsDelta;
325 
326 		final boolean allowPushOptions;
327 
328 		final long maxCommandBytes;
329 
330 		final long maxDiscardBytes;
331 
332 		final SignedPushConfig signedPush;
333 
334 		ReceiveConfig(Config config) {
335 			allowCreates = true;
336 			allowDeletes = !config.getBoolean("receive", "denydeletes", false); //$NON-NLS-1$ //$NON-NLS-2$
337 			allowNonFastForwards = !config.getBoolean("receive", //$NON-NLS-1$
338 					"denynonfastforwards", false); //$NON-NLS-1$
339 			allowOfsDelta = config.getBoolean("repack", "usedeltabaseoffset", //$NON-NLS-1$ //$NON-NLS-2$
340 					true);
341 			allowPushOptions = config.getBoolean("receive", "pushoptions", //$NON-NLS-1$ //$NON-NLS-2$
342 					false);
343 			maxCommandBytes = config.getLong("receive", //$NON-NLS-1$
344 					"maxCommandBytes", //$NON-NLS-1$
345 					3 << 20);
346 			maxDiscardBytes = config.getLong("receive", //$NON-NLS-1$
347 					"maxCommandDiscardBytes", //$NON-NLS-1$
348 					-1);
349 			signedPush = SignedPushConfig.KEY.parse(config);
350 		}
351 	}
352 
353 	/**
354 	 * Output stream that wraps the current {@link #msgOut}.
355 	 * <p>
356 	 * We don't want to expose {@link #msgOut} directly because it can change
357 	 * several times over the course of a session.
358 	 */
359 	class MessageOutputWrapper extends OutputStream {
360 		@Override
361 		public void write(int ch) {
362 			if (msgOut != null) {
363 				try {
364 					msgOut.write(ch);
365 				} catch (IOException e) {
366 					// Ignore write failures.
367 				}
368 			}
369 		}
370 
371 		@Override
372 		public void write(byte[] b, int off, int len) {
373 			if (msgOut != null) {
374 				try {
375 					msgOut.write(b, off, len);
376 				} catch (IOException e) {
377 					// Ignore write failures.
378 				}
379 			}
380 		}
381 
382 		@Override
383 		public void write(byte[] b) {
384 			write(b, 0, b.length);
385 		}
386 
387 		@Override
388 		public void flush() {
389 			if (msgOut != null) {
390 				try {
391 					msgOut.flush();
392 				} catch (IOException e) {
393 					// Ignore write failures.
394 				}
395 			}
396 		}
397 	}
398 
399 	/**
400 	 * Get the repository this receive completes into.
401 	 *
402 	 * @return the repository this receive completes into.
403 	 */
404 	public Repository getRepository() {
405 		return db;
406 	}
407 
408 	/**
409 	 * Get the RevWalk instance used by this connection.
410 	 *
411 	 * @return the RevWalk instance used by this connection.
412 	 */
413 	public RevWalk getRevWalk() {
414 		return walk;
415 	}
416 
417 	/**
418 	 * Get refs which were advertised to the client.
419 	 *
420 	 * @return all refs which were advertised to the client, or null if
421 	 *         {@link #setAdvertisedRefs(Map, Set)} has not been called yet.
422 	 */
423 	public Map<String, Ref> getAdvertisedRefs() {
424 		return refs;
425 	}
426 
427 	/**
428 	 * Set the refs advertised by this ReceivePack.
429 	 * <p>
430 	 * Intended to be called from a
431 	 * {@link org.eclipse.jgit.transport.PreReceiveHook}.
432 	 *
433 	 * @param allRefs
434 	 *            explicit set of references to claim as advertised by this
435 	 *            ReceivePack instance. This overrides any references that may
436 	 *            exist in the source repository. The map is passed to the
437 	 *            configured {@link #getRefFilter()}. If null, assumes all refs
438 	 *            were advertised.
439 	 * @param additionalHaves
440 	 *            explicit set of additional haves to claim as advertised. If
441 	 *            null, assumes the default set of additional haves from the
442 	 *            repository.
443 	 * @throws IOException
444 	 */
445 	public void setAdvertisedRefs(Map<String, Ref> allRefs,
446 			Set<ObjectId> additionalHaves) throws IOException {
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 	 * @throws IOException
1192 	 */
1193 	private Map<String, Ref> getAdvertisedOrDefaultRefs() throws IOException {
1194 		if (refs == null)
1195 			setAdvertisedRefs(null, null);
1196 		return refs;
1197 	}
1198 
1199 	/**
1200 	 * Receive a pack from the stream and check connectivity if necessary.
1201 	 *
1202 	 * Visible for out-of-tree subclasses. Subclasses overriding this method
1203 	 * should invoke this implementation, as it alters the instance state (e.g.
1204 	 * it reads the pack from the input and parses it before running the
1205 	 * connectivity checks).
1206 	 *
1207 	 * @throws java.io.IOException
1208 	 *             an error occurred during unpacking or connectivity checking.
1209 	 * @throws LargeObjectException
1210 	 *             an large object needs to be opened for the check.
1211 	 * @throws SubmoduleValidationException
1212 	 *             fails to validate the submodule.
1213 	 */
1214 	protected void receivePackAndCheckConnectivity() throws IOException,
1215 			LargeObjectException, SubmoduleValidationException {
1216 		receivePack();
1217 		if (needCheckConnectivity()) {
1218 			checkSubmodules();
1219 			checkConnectivity();
1220 		}
1221 		parser = null;
1222 	}
1223 
1224 	/**
1225 	 * Unlock the pack written by this object.
1226 	 *
1227 	 * @throws java.io.IOException
1228 	 *             the pack could not be unlocked.
1229 	 */
1230 	private void unlockPack() throws IOException {
1231 		if (packLock != null) {
1232 			packLock.unlock();
1233 			packLock = null;
1234 		}
1235 	}
1236 
1237 	/**
1238 	 * Generate an advertisement of available refs and capabilities.
1239 	 *
1240 	 * @param adv
1241 	 *            the advertisement formatter.
1242 	 * @throws java.io.IOException
1243 	 *             the formatter failed to write an advertisement.
1244 	 * @throws org.eclipse.jgit.transport.ServiceMayNotContinueException
1245 	 *             the hook denied advertisement.
1246 	 */
1247 	public void sendAdvertisedRefs(RefAdvertiser adv)
1248 			throws IOException, ServiceMayNotContinueException {
1249 		if (advertiseError != null) {
1250 			adv.writeOne("ERR " + advertiseError); //$NON-NLS-1$
1251 			return;
1252 		}
1253 
1254 		try {
1255 			advertiseRefsHook.advertiseRefs(this);
1256 		} catch (ServiceMayNotContinueException fail) {
1257 			if (fail.getMessage() != null) {
1258 				adv.writeOne("ERR " + fail.getMessage()); //$NON-NLS-1$
1259 				fail.setOutput();
1260 			}
1261 			throw fail;
1262 		}
1263 
1264 		adv.init(db);
1265 		adv.advertiseCapability(CAPABILITY_SIDE_BAND_64K);
1266 		adv.advertiseCapability(CAPABILITY_DELETE_REFS);
1267 		adv.advertiseCapability(CAPABILITY_REPORT_STATUS);
1268 		if (allowQuiet)
1269 			adv.advertiseCapability(CAPABILITY_QUIET);
1270 		String nonce = getPushCertificateParser().getAdvertiseNonce();
1271 		if (nonce != null) {
1272 			adv.advertiseCapability(nonce);
1273 		}
1274 		if (db.getRefDatabase().performsAtomicTransactions())
1275 			adv.advertiseCapability(CAPABILITY_ATOMIC);
1276 		if (allowOfsDelta)
1277 			adv.advertiseCapability(CAPABILITY_OFS_DELTA);
1278 		if (allowPushOptions) {
1279 			adv.advertiseCapability(CAPABILITY_PUSH_OPTIONS);
1280 		}
1281 		adv.advertiseCapability(OPTION_AGENT, UserAgent.get());
1282 		adv.send(getAdvertisedOrDefaultRefs().values());
1283 		for (ObjectId obj : advertisedHaves)
1284 			adv.advertiseHave(obj);
1285 		if (adv.isEmpty())
1286 			adv.advertiseId(ObjectId.zeroId(), "capabilities^{}"); //$NON-NLS-1$
1287 		adv.end();
1288 	}
1289 
1290 	/**
1291 	 * Returns the statistics on the received pack if available. This should be
1292 	 * called after {@link #receivePack} is called.
1293 	 *
1294 	 * @return ReceivedPackStatistics
1295 	 * @since 4.6
1296 	 */
1297 	@Nullable
1298 	public ReceivedPackStatistics getReceivedPackStatistics() {
1299 		return stats;
1300 	}
1301 
1302 	/**
1303 	 * Extract the full list of refs from the ref-db.
1304 	 *
1305 	 * @return Map of all refname/ref
1306 	 */
1307 	private Map<String, Ref> getAllRefs() {
1308 		try {
1309 			return db.getRefDatabase().getRefs().stream()
1310 					.collect(Collectors.toMap(Ref::getName,
1311 							Function.identity()));
1312 		} catch (IOException e) {
1313 			throw new UncheckedIOException(e);
1314 		}
1315 	}
1316 
1317 	/**
1318 	 * Receive a list of commands from the input.
1319 	 *
1320 	 * @throws java.io.IOException
1321 	 */
1322 	private void recvCommands() throws IOException {
1323 		PacketLineIn pck = maxCommandBytes > 0
1324 				? new PacketLineIn(rawIn, maxCommandBytes)
1325 				: pckIn;
1326 		PushCertificateParser certParser = getPushCertificateParser();
1327 		boolean firstPkt = true;
1328 		try {
1329 			for (;;) {
1330 				String line;
1331 				try {
1332 					line = pck.readString();
1333 				} catch (EOFException eof) {
1334 					if (commands.isEmpty())
1335 						return;
1336 					throw eof;
1337 				}
1338 				if (PacketLineIn.isEnd(line)) {
1339 					break;
1340 				}
1341 
1342 				if (line.length() >= 48 && line.startsWith("shallow ")) { //$NON-NLS-1$
1343 					parseShallow(line.substring(8, 48));
1344 					continue;
1345 				}
1346 
1347 				if (firstPkt) {
1348 					firstPkt = false;
1349 					FirstCommand firstLine = FirstCommand.fromLine(line);
1350 					enabledCapabilities = firstLine.getCapabilities();
1351 					line = firstLine.getLine();
1352 					enableCapabilities();
1353 
1354 					if (line.equals(GitProtocolConstants.OPTION_PUSH_CERT)) {
1355 						certParser.receiveHeader(pck, !isBiDirectionalPipe());
1356 						continue;
1357 					}
1358 				}
1359 
1360 				if (line.equals(PushCertificateParser.BEGIN_SIGNATURE)) {
1361 					certParser.receiveSignature(pck);
1362 					continue;
1363 				}
1364 
1365 				ReceiveCommand cmd = parseCommand(line);
1366 				if (cmd.getRefName().equals(Constants.HEAD)) {
1367 					cmd.setResult(Result.REJECTED_CURRENT_BRANCH);
1368 				} else {
1369 					cmd.setRef(refs.get(cmd.getRefName()));
1370 				}
1371 				commands.add(cmd);
1372 				if (certParser.enabled()) {
1373 					certParser.addCommand(cmd);
1374 				}
1375 			}
1376 			pushCert = certParser.build();
1377 			if (hasCommands()) {
1378 				readPostCommands(pck);
1379 			}
1380 		} catch (Throwable t) {
1381 			discardCommands();
1382 			throw t;
1383 		}
1384 	}
1385 
1386 	private void discardCommands() {
1387 		if (sideBand) {
1388 			long max = maxDiscardBytes;
1389 			if (max < 0) {
1390 				max = Math.max(3 * maxCommandBytes, 3L << 20);
1391 			}
1392 			try {
1393 				new PacketLineIn(rawIn, max).discardUntilEnd();
1394 			} catch (IOException e) {
1395 				// Ignore read failures attempting to discard.
1396 			}
1397 		}
1398 	}
1399 
1400 	private void parseShallow(String idStr) throws PackProtocolException {
1401 		ObjectId id;
1402 		try {
1403 			id = ObjectId.fromString(idStr);
1404 		} catch (InvalidObjectIdException e) {
1405 			throw new PackProtocolException(e.getMessage(), e);
1406 		}
1407 		clientShallowCommits.add(id);
1408 	}
1409 
1410 	/**
1411 	 * @param in
1412 	 *            request stream.
1413 	 * @throws IOException
1414 	 *             request line cannot be read.
1415 	 */
1416 	void readPostCommands(PacketLineIn in) throws IOException {
1417 		if (usePushOptions) {
1418 			pushOptions = new ArrayList<>(4);
1419 			for (;;) {
1420 				String option = in.readString();
1421 				if (PacketLineIn.isEnd(option)) {
1422 					break;
1423 				}
1424 				pushOptions.add(option);
1425 			}
1426 		}
1427 	}
1428 
1429 	/**
1430 	 * Enable capabilities based on a previously read capabilities line.
1431 	 */
1432 	private void enableCapabilities() {
1433 		reportStatus = isCapabilityEnabled(CAPABILITY_REPORT_STATUS);
1434 		usePushOptions = isCapabilityEnabled(CAPABILITY_PUSH_OPTIONS);
1435 		sideBand = isCapabilityEnabled(CAPABILITY_SIDE_BAND_64K);
1436 		quiet = allowQuiet && isCapabilityEnabled(CAPABILITY_QUIET);
1437 		if (sideBand) {
1438 			OutputStream out = rawOut;
1439 
1440 			rawOut = new SideBandOutputStream(CH_DATA, MAX_BUF, out);
1441 			msgOut = new SideBandOutputStream(CH_PROGRESS, MAX_BUF, out);
1442 			errOut = new SideBandOutputStream(CH_ERROR, MAX_BUF, out);
1443 
1444 			pckOut = new PacketLineOut(rawOut);
1445 			pckOut.setFlushOnEnd(false);
1446 		}
1447 	}
1448 
1449 	/**
1450 	 * Check if the peer requested a capability.
1451 	 *
1452 	 * @param name
1453 	 *            protocol name identifying the capability.
1454 	 * @return true if the peer requested the capability to be enabled.
1455 	 */
1456 	private boolean isCapabilityEnabled(String name) {
1457 		return enabledCapabilities.contains(name);
1458 	}
1459 
1460 	private void checkRequestWasRead() {
1461 		if (enabledCapabilities == null)
1462 			throw new RequestNotYetReadException();
1463 	}
1464 
1465 	/**
1466 	 * Whether a pack is expected based on the list of commands.
1467 	 *
1468 	 * @return {@code true} if a pack is expected based on the list of commands.
1469 	 */
1470 	private boolean needPack() {
1471 		for (ReceiveCommand cmd : commands) {
1472 			if (cmd.getType() != ReceiveCommand.Type.DELETE)
1473 				return true;
1474 		}
1475 		return false;
1476 	}
1477 
1478 	/**
1479 	 * Receive a pack from the input and store it in the repository.
1480 	 *
1481 	 * @throws IOException
1482 	 *             an error occurred reading or indexing the pack.
1483 	 */
1484 	private void receivePack() throws IOException {
1485 		// It might take the client a while to pack the objects it needs
1486 		// to send to us. We should increase our timeout so we don't
1487 		// abort while the client is computing.
1488 		//
1489 		if (timeoutIn != null)
1490 			timeoutIn.setTimeout(10 * timeout * 1000);
1491 
1492 		ProgressMonitor receiving = NullProgressMonitor.INSTANCE;
1493 		ProgressMonitor resolving = NullProgressMonitor.INSTANCE;
1494 		if (sideBand && !quiet)
1495 			resolving = new SideBandProgressMonitor(msgOut);
1496 
1497 		try (ObjectInserter ins = db.newObjectInserter()) {
1498 			String lockMsg = "jgit receive-pack"; //$NON-NLS-1$
1499 			if (getRefLogIdent() != null)
1500 				lockMsg += " from " + getRefLogIdent().toExternalString(); //$NON-NLS-1$
1501 
1502 			parser = ins.newPackParser(packInputStream());
1503 			parser.setAllowThin(true);
1504 			parser.setNeedNewObjectIds(checkReferencedAreReachable);
1505 			parser.setNeedBaseObjectIds(checkReferencedAreReachable);
1506 			parser.setCheckEofAfterPackFooter(!biDirectionalPipe
1507 					&& !isExpectDataAfterPackFooter());
1508 			parser.setExpectDataAfterPackFooter(isExpectDataAfterPackFooter());
1509 			parser.setObjectChecker(objectChecker);
1510 			parser.setLockMessage(lockMsg);
1511 			parser.setMaxObjectSizeLimit(maxObjectSizeLimit);
1512 			packLock = parser.parse(receiving, resolving);
1513 			packSize = Long.valueOf(parser.getPackSize());
1514 			stats = parser.getReceivedPackStatistics();
1515 			ins.flush();
1516 		}
1517 
1518 		if (timeoutIn != null)
1519 			timeoutIn.setTimeout(timeout * 1000);
1520 	}
1521 
1522 	private InputStream packInputStream() {
1523 		InputStream packIn = rawIn;
1524 		if (maxPackSizeLimit >= 0) {
1525 			packIn = new LimitedInputStream(packIn, maxPackSizeLimit) {
1526 				@Override
1527 				protected void limitExceeded() throws TooLargePackException {
1528 					throw new TooLargePackException(limit);
1529 				}
1530 			};
1531 		}
1532 		return packIn;
1533 	}
1534 
1535 	private boolean needCheckConnectivity() {
1536 		return isCheckReceivedObjects()
1537 				|| isCheckReferencedObjectsAreReachable()
1538 				|| !getClientShallowCommits().isEmpty();
1539 	}
1540 
1541 	private void checkSubmodules() throws IOException, LargeObjectException,
1542 			SubmoduleValidationException {
1543 		ObjectDatabase odb = db.getObjectDatabase();
1544 		if (objectChecker == null) {
1545 			return;
1546 		}
1547 		for (GitmoduleEntry entry : objectChecker.getGitsubmodules()) {
1548 			AnyObjectId blobId = entry.getBlobId();
1549 			ObjectLoader blob = odb.open(blobId, Constants.OBJ_BLOB);
1550 
1551 			SubmoduleValidator.assertValidGitModulesFile(
1552 					new String(blob.getBytes(), UTF_8));
1553 		}
1554 	}
1555 
1556 	private void checkConnectivity() throws IOException {
1557 		ProgressMonitor checking = NullProgressMonitor.INSTANCE;
1558 		if (sideBand && !quiet) {
1559 			SideBandProgressMonitor m = new SideBandProgressMonitor(msgOut);
1560 			m.setDelayStart(750, TimeUnit.MILLISECONDS);
1561 			checking = m;
1562 		}
1563 
1564 		connectivityChecker.checkConnectivity(createConnectivityCheckInfo(),
1565 				advertisedHaves, checking);
1566 	}
1567 
1568 	private ConnectivityCheckInfo createConnectivityCheckInfo() {
1569 		ConnectivityCheckInfo info = new ConnectivityCheckInfo();
1570 		info.setCheckObjects(checkReferencedAreReachable);
1571 		info.setCommands(getAllCommands());
1572 		info.setRepository(db);
1573 		info.setParser(parser);
1574 		info.setWalk(walk);
1575 		return info;
1576 	}
1577 
1578 	/**
1579 	 * Validate the command list.
1580 	 */
1581 	private void validateCommands() {
1582 		for (ReceiveCommand cmd : commands) {
1583 			final Ref ref = cmd.getRef();
1584 			if (cmd.getResult() != Result.NOT_ATTEMPTED)
1585 				continue;
1586 
1587 			if (cmd.getType() == ReceiveCommand.Type.DELETE) {
1588 				if (!isAllowDeletes()) {
1589 					// Deletes are not supported on this repository.
1590 					cmd.setResult(Result.REJECTED_NODELETE);
1591 					continue;
1592 				}
1593 				if (!isAllowBranchDeletes()
1594 						&& ref.getName().startsWith(Constants.R_HEADS)) {
1595 					// Branches cannot be deleted, but other refs can.
1596 					cmd.setResult(Result.REJECTED_NODELETE);
1597 					continue;
1598 				}
1599 			}
1600 
1601 			if (cmd.getType() == ReceiveCommand.Type.CREATE) {
1602 				if (!isAllowCreates()) {
1603 					cmd.setResult(Result.REJECTED_NOCREATE);
1604 					continue;
1605 				}
1606 
1607 				if (ref != null && !isAllowNonFastForwards()) {
1608 					// Creation over an existing ref is certainly not going
1609 					// to be a fast-forward update. We can reject it early.
1610 					//
1611 					cmd.setResult(Result.REJECTED_NONFASTFORWARD);
1612 					continue;
1613 				}
1614 
1615 				if (ref != null) {
1616 					// A well behaved client shouldn't have sent us a
1617 					// create command for a ref we advertised to it.
1618 					//
1619 					cmd.setResult(Result.REJECTED_OTHER_REASON,
1620 							JGitText.get().refAlreadyExists);
1621 					continue;
1622 				}
1623 			}
1624 
1625 			if (cmd.getType() == ReceiveCommand.Type.DELETE && ref != null) {
1626 				ObjectId id = ref.getObjectId();
1627 				if (id == null) {
1628 					id = ObjectId.zeroId();
1629 				}
1630 				if (!ObjectId.zeroId().equals(cmd.getOldId())
1631 						&& !id.equals(cmd.getOldId())) {
1632 					// Delete commands can be sent with the old id matching our
1633 					// advertised value, *OR* with the old id being 0{40}. Any
1634 					// other requested old id is invalid.
1635 					//
1636 					cmd.setResult(Result.REJECTED_OTHER_REASON,
1637 							JGitText.get().invalidOldIdSent);
1638 					continue;
1639 				}
1640 			}
1641 
1642 			if (cmd.getType() == ReceiveCommand.Type.UPDATE) {
1643 				if (ref == null) {
1644 					// The ref must have been advertised in order to be updated.
1645 					//
1646 					cmd.setResult(Result.REJECTED_OTHER_REASON,
1647 							JGitText.get().noSuchRef);
1648 					continue;
1649 				}
1650 				ObjectId id = ref.getObjectId();
1651 				if (id == null) {
1652 					// We cannot update unborn branch
1653 					cmd.setResult(Result.REJECTED_OTHER_REASON,
1654 							JGitText.get().cannotUpdateUnbornBranch);
1655 					continue;
1656 				}
1657 
1658 				if (!id.equals(cmd.getOldId())) {
1659 					// A properly functioning client will send the same
1660 					// object id we advertised.
1661 					//
1662 					cmd.setResult(Result.REJECTED_OTHER_REASON,
1663 							JGitText.get().invalidOldIdSent);
1664 					continue;
1665 				}
1666 
1667 				// Is this possibly a non-fast-forward style update?
1668 				//
1669 				RevObject oldObj, newObj;
1670 				try {
1671 					oldObj = walk.parseAny(cmd.getOldId());
1672 				} catch (IOException e) {
1673 					receiveCommandErrorHandler
1674 							.handleOldIdValidationException(cmd, e);
1675 					continue;
1676 				}
1677 
1678 				try {
1679 					newObj = walk.parseAny(cmd.getNewId());
1680 				} catch (IOException e) {
1681 					receiveCommandErrorHandler
1682 							.handleNewIdValidationException(cmd, e);
1683 					continue;
1684 				}
1685 
1686 				if (oldObj instanceof RevCommit
1687 						&& newObj instanceof RevCommit) {
1688 					try {
1689 						if (walk.isMergedInto((RevCommit) oldObj,
1690 								(RevCommit) newObj)) {
1691 							cmd.setTypeFastForwardUpdate();
1692 						} else {
1693 							cmd.setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
1694 						}
1695 					} catch (IOException e) {
1696 						receiveCommandErrorHandler
1697 								.handleFastForwardCheckException(cmd, e);
1698 					}
1699 				} else {
1700 					cmd.setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
1701 				}
1702 
1703 				if (cmd.getType() == ReceiveCommand.Type.UPDATE_NONFASTFORWARD
1704 						&& !isAllowNonFastForwards()) {
1705 					cmd.setResult(Result.REJECTED_NONFASTFORWARD);
1706 					continue;
1707 				}
1708 			}
1709 
1710 			if (!cmd.getRefName().startsWith(Constants.R_REFS)
1711 					|| !Repository.isValidRefName(cmd.getRefName())) {
1712 				cmd.setResult(Result.REJECTED_OTHER_REASON,
1713 						JGitText.get().funnyRefname);
1714 			}
1715 		}
1716 	}
1717 
1718 	/**
1719 	 * Whether any commands have been rejected so far.
1720 	 *
1721 	 * @return if any commands have been rejected so far.
1722 	 */
1723 	private boolean anyRejects() {
1724 		for (ReceiveCommand cmd : commands) {
1725 			if (cmd.getResult() != Result.NOT_ATTEMPTED
1726 					&& cmd.getResult() != Result.OK)
1727 				return true;
1728 		}
1729 		return false;
1730 	}
1731 
1732 	/**
1733 	 * Set the result to fail for any command that was not processed yet.
1734 	 *
1735 	 */
1736 	private void failPendingCommands() {
1737 		ReceiveCommand.abort(commands);
1738 	}
1739 
1740 	/**
1741 	 * Filter the list of commands according to result.
1742 	 *
1743 	 * @param want
1744 	 *            desired status to filter by.
1745 	 * @return a copy of the command list containing only those commands with
1746 	 *         the desired status.
1747 	 * @since 5.7
1748 	 */
1749 	protected List<ReceiveCommand> filterCommands(Result want) {
1750 		return ReceiveCommand.filter(commands, want);
1751 	}
1752 
1753 	/**
1754 	 * Execute commands to update references.
1755 	 * @since 5.7
1756 	 */
1757 	protected void executeCommands() {
1758 		List<ReceiveCommand> toApply = filterCommands(Result.NOT_ATTEMPTED);
1759 		if (toApply.isEmpty())
1760 			return;
1761 
1762 		ProgressMonitor updating = NullProgressMonitor.INSTANCE;
1763 		if (sideBand) {
1764 			SideBandProgressMonitor pm = new SideBandProgressMonitor(msgOut);
1765 			pm.setDelayStart(250, TimeUnit.MILLISECONDS);
1766 			updating = pm;
1767 		}
1768 
1769 		BatchRefUpdate batch = db.getRefDatabase().newBatchUpdate();
1770 		batch.setAllowNonFastForwards(isAllowNonFastForwards());
1771 		batch.setAtomic(isAtomic());
1772 		batch.setRefLogIdent(getRefLogIdent());
1773 		batch.setRefLogMessage("push", true); //$NON-NLS-1$
1774 		batch.addCommand(toApply);
1775 		try {
1776 			batch.setPushCertificate(getPushCertificate());
1777 			batch.execute(walk, updating);
1778 		} catch (IOException e) {
1779 			receiveCommandErrorHandler.handleBatchRefUpdateException(toApply,
1780 					e);
1781 		}
1782 	}
1783 
1784 	/**
1785 	 * Send a status report.
1786 	 *
1787 	 * @param unpackError
1788 	 *            an error that occurred during unpacking, or {@code null}
1789 	 * @throws java.io.IOException
1790 	 *             an error occurred writing the status report.
1791 	 * @since 5.6
1792 	 */
1793 	private void sendStatusReport(Throwable unpackError) throws IOException {
1794 		Reporter out = new Reporter() {
1795 			@Override
1796 			void sendString(String s) throws IOException {
1797 				if (reportStatus) {
1798 					pckOut.writeString(s + "\n"); //$NON-NLS-1$
1799 				} else if (msgOut != null) {
1800 					msgOut.write(Constants.encode(s + "\n")); //$NON-NLS-1$
1801 				}
1802 			}
1803 		};
1804 
1805 		try {
1806 			if (unpackError != null) {
1807 				out.sendString("unpack error " + unpackError.getMessage()); //$NON-NLS-1$
1808 				if (reportStatus) {
1809 					for (ReceiveCommand cmd : commands) {
1810 						out.sendString("ng " + cmd.getRefName() //$NON-NLS-1$
1811 								+ " n/a (unpacker error)"); //$NON-NLS-1$
1812 					}
1813 				}
1814 				return;
1815 			}
1816 
1817 			if (reportStatus) {
1818 				out.sendString("unpack ok"); //$NON-NLS-1$
1819 			}
1820 			for (ReceiveCommand cmd : commands) {
1821 				if (cmd.getResult() == Result.OK) {
1822 					if (reportStatus) {
1823 						out.sendString("ok " + cmd.getRefName()); //$NON-NLS-1$
1824 					}
1825 					continue;
1826 				}
1827 
1828 				final StringBuilder r = new StringBuilder();
1829 				if (reportStatus) {
1830 					r.append("ng ").append(cmd.getRefName()).append(" "); //$NON-NLS-1$ //$NON-NLS-2$
1831 				} else {
1832 					r.append(" ! [rejected] ").append(cmd.getRefName()) //$NON-NLS-1$
1833 							.append(" ("); //$NON-NLS-1$
1834 				}
1835 
1836 				if (cmd.getResult() == Result.REJECTED_MISSING_OBJECT) {
1837 					if (cmd.getMessage() == null)
1838 						r.append("missing object(s)"); //$NON-NLS-1$
1839 					else if (cmd.getMessage()
1840 							.length() == Constants.OBJECT_ID_STRING_LENGTH) {
1841 						// TODO: Using get/setMessage to store an OID is a
1842 						// misuse. The caller should set a full error message.
1843 						r.append("object "); //$NON-NLS-1$
1844 						r.append(cmd.getMessage());
1845 						r.append(" missing"); //$NON-NLS-1$
1846 					} else {
1847 						r.append(cmd.getMessage());
1848 					}
1849 				} else if (cmd.getMessage() != null) {
1850 					r.append(cmd.getMessage());
1851 				} else {
1852 					switch (cmd.getResult()) {
1853 					case NOT_ATTEMPTED:
1854 						r.append("server bug; ref not processed"); //$NON-NLS-1$
1855 						break;
1856 
1857 					case REJECTED_NOCREATE:
1858 						r.append("creation prohibited"); //$NON-NLS-1$
1859 						break;
1860 
1861 					case REJECTED_NODELETE:
1862 						r.append("deletion prohibited"); //$NON-NLS-1$
1863 						break;
1864 
1865 					case REJECTED_NONFASTFORWARD:
1866 						r.append("non-fast forward"); //$NON-NLS-1$
1867 						break;
1868 
1869 					case REJECTED_CURRENT_BRANCH:
1870 						r.append("branch is currently checked out"); //$NON-NLS-1$
1871 						break;
1872 
1873 					case REJECTED_OTHER_REASON:
1874 						r.append("unspecified reason"); //$NON-NLS-1$
1875 						break;
1876 
1877 					case LOCK_FAILURE:
1878 						r.append("failed to lock"); //$NON-NLS-1$
1879 						break;
1880 
1881 					case REJECTED_MISSING_OBJECT:
1882 					case OK:
1883 						// We shouldn't have reached this case (see 'ok' case
1884 						// above and if-statement above).
1885 						throw new AssertionError();
1886 					}
1887 				}
1888 
1889 				if (!reportStatus) {
1890 					r.append(")"); //$NON-NLS-1$
1891 				}
1892 				out.sendString(r.toString());
1893 			}
1894 		} finally {
1895 			if (reportStatus) {
1896 				pckOut.end();
1897 			}
1898 		}
1899 	}
1900 
1901 	/**
1902 	 * Close and flush (if necessary) the underlying streams.
1903 	 *
1904 	 * @throws java.io.IOException
1905 	 */
1906 	private void close() throws IOException {
1907 		if (sideBand) {
1908 			// If we are using side band, we need to send a final
1909 			// flush-pkt to tell the remote peer the side band is
1910 			// complete and it should stop decoding. We need to
1911 			// use the original output stream as rawOut is now the
1912 			// side band data channel.
1913 			//
1914 			((SideBandOutputStream) msgOut).flushBuffer();
1915 			((SideBandOutputStream) rawOut).flushBuffer();
1916 
1917 			PacketLineOut plo = new PacketLineOut(origOut);
1918 			plo.setFlushOnEnd(false);
1919 			plo.end();
1920 		}
1921 
1922 		if (biDirectionalPipe) {
1923 			// If this was a native git connection, flush the pipe for
1924 			// the caller. For smart HTTP we don't do this flush and
1925 			// instead let the higher level HTTP servlet code do it.
1926 			//
1927 			if (!sideBand && msgOut != null)
1928 				msgOut.flush();
1929 			rawOut.flush();
1930 		}
1931 	}
1932 
1933 	/**
1934 	 * Release any resources used by this object.
1935 	 *
1936 	 * @throws java.io.IOException
1937 	 *             the pack could not be unlocked.
1938 	 */
1939 	private void release() throws IOException {
1940 		walk.close();
1941 		unlockPack();
1942 		timeoutIn = null;
1943 		rawIn = null;
1944 		rawOut = null;
1945 		msgOut = null;
1946 		pckIn = null;
1947 		pckOut = null;
1948 		refs = null;
1949 		// Keep the capabilities. If responses are sent after this release
1950 		// we need to remember at least whether sideband communication has to be
1951 		// used
1952 		commands = null;
1953 		if (timer != null) {
1954 			try {
1955 				timer.terminate();
1956 			} finally {
1957 				timer = null;
1958 			}
1959 		}
1960 	}
1961 
1962 	/** Interface for reporting status messages. */
1963 	abstract static class Reporter {
1964 		abstract void sendString(String s) throws IOException;
1965 	}
1966 
1967 	/**
1968 	 * Get the push certificate used to verify the pusher's identity.
1969 	 * <p>
1970 	 * Only valid after commands are read from the wire.
1971 	 *
1972 	 * @return the parsed certificate, or null if push certificates are disabled
1973 	 *         or no cert was presented by the client.
1974 	 * @since 4.1
1975 	 */
1976 	public PushCertificate getPushCertificate() {
1977 		return pushCert;
1978 	}
1979 
1980 	/**
1981 	 * Set the push certificate used to verify the pusher's identity.
1982 	 * <p>
1983 	 * Should only be called if reconstructing an instance without going through
1984 	 * the normal {@link #recvCommands()} flow.
1985 	 *
1986 	 * @param cert
1987 	 *            the push certificate to set.
1988 	 * @since 4.1
1989 	 */
1990 	public void setPushCertificate(PushCertificate cert) {
1991 		pushCert = cert;
1992 	}
1993 
1994 	/**
1995 	 * Gets an unmodifiable view of the option strings associated with the push.
1996 	 *
1997 	 * @return an unmodifiable view of pushOptions, or null (if pushOptions is).
1998 	 * @since 4.5
1999 	 */
2000 	@Nullable
2001 	public List<String> getPushOptions() {
2002 		if (isAllowPushOptions() && usePushOptions) {
2003 			return Collections.unmodifiableList(pushOptions);
2004 		}
2005 
2006 		// The client doesn't support push options. Return null to
2007 		// distinguish this from the case where the client declared support
2008 		// for push options and sent an empty list of them.
2009 		return null;
2010 	}
2011 
2012 	/**
2013 	 * Set the push options supplied by the client.
2014 	 * <p>
2015 	 * Should only be called if reconstructing an instance without going through
2016 	 * the normal {@link #recvCommands()} flow.
2017 	 *
2018 	 * @param options
2019 	 *            the list of options supplied by the client. The
2020 	 *            {@code ReceivePack} instance takes ownership of this list.
2021 	 *            Callers are encouraged to first create a copy if the list may
2022 	 *            be modified later.
2023 	 * @since 4.5
2024 	 */
2025 	public void setPushOptions(@Nullable List<String> options) {
2026 		usePushOptions = options != null;
2027 		pushOptions = options;
2028 	}
2029 
2030 	/**
2031 	 * Get the hook invoked before updates occur.
2032 	 *
2033 	 * @return the hook invoked before updates occur.
2034 	 */
2035 	public PreReceiveHook getPreReceiveHook() {
2036 		return preReceive;
2037 	}
2038 
2039 	/**
2040 	 * Set the hook which is invoked prior to commands being executed.
2041 	 * <p>
2042 	 * Only valid commands (those which have no obvious errors according to the
2043 	 * received input and this instance's configuration) are passed into the
2044 	 * hook. The hook may mark a command with a result of any value other than
2045 	 * {@link org.eclipse.jgit.transport.ReceiveCommand.Result#NOT_ATTEMPTED} to
2046 	 * block its execution.
2047 	 * <p>
2048 	 * The hook may be called with an empty command collection if the current
2049 	 * set is completely invalid.
2050 	 *
2051 	 * @param h
2052 	 *            the hook instance; may be null to disable the hook.
2053 	 */
2054 	public void setPreReceiveHook(PreReceiveHook h) {
2055 		preReceive = h != null ? h : PreReceiveHook.NULL;
2056 	}
2057 
2058 	/**
2059 	 * Get the hook invoked after updates occur.
2060 	 *
2061 	 * @return the hook invoked after updates occur.
2062 	 */
2063 	public PostReceiveHook getPostReceiveHook() {
2064 		return postReceive;
2065 	}
2066 
2067 	/**
2068 	 * Set the hook which is invoked after commands are executed.
2069 	 * <p>
2070 	 * Only successful commands (type is
2071 	 * {@link org.eclipse.jgit.transport.ReceiveCommand.Result#OK}) are passed
2072 	 * into the hook. The hook may be called with an empty command collection if
2073 	 * the current set all resulted in an error.
2074 	 *
2075 	 * @param h
2076 	 *            the hook instance; may be null to disable the hook.
2077 	 */
2078 	public void setPostReceiveHook(PostReceiveHook h) {
2079 		postReceive = h != null ? h : PostReceiveHook.NULL;
2080 	}
2081 
2082 	/**
2083 	 * Get the current unpack error handler.
2084 	 *
2085 	 * @return the current unpack error handler.
2086 	 * @since 5.8
2087 	 */
2088 	public UnpackErrorHandler getUnpackErrorHandler() {
2089 		return unpackErrorHandler;
2090 	}
2091 
2092 	/**
2093 	 * @param unpackErrorHandler
2094 	 *            the unpackErrorHandler to set
2095 	 * @since 5.7
2096 	 */
2097 	public void setUnpackErrorHandler(UnpackErrorHandler unpackErrorHandler) {
2098 		this.unpackErrorHandler = unpackErrorHandler;
2099 	}
2100 
2101 	/**
2102 	 * Set whether this class will report command failures as warning messages
2103 	 * before sending the command results.
2104 	 *
2105 	 * @param echo
2106 	 *            if true this class will report command failures as warning
2107 	 *            messages before sending the command results. This is usually
2108 	 *            not necessary, but may help buggy Git clients that discard the
2109 	 *            errors when all branches fail.
2110 	 * @deprecated no widely used Git versions need this any more
2111 	 */
2112 	@Deprecated
2113 	public void setEchoCommandFailures(boolean echo) {
2114 		// No-op.
2115 	}
2116 
2117 	/**
2118 	 * Execute the receive task on the socket.
2119 	 *
2120 	 * @param input
2121 	 *            raw input to read client commands and pack data from. Caller
2122 	 *            must ensure the input is buffered, otherwise read performance
2123 	 *            may suffer.
2124 	 * @param output
2125 	 *            response back to the Git network client. Caller must ensure
2126 	 *            the output is buffered, otherwise write performance may
2127 	 *            suffer.
2128 	 * @param messages
2129 	 *            secondary "notice" channel to send additional messages out
2130 	 *            through. When run over SSH this should be tied back to the
2131 	 *            standard error channel of the command execution. For most
2132 	 *            other network connections this should be null.
2133 	 * @throws java.io.IOException
2134 	 */
2135 	public void receive(final InputStream input, final OutputStream output,
2136 			final OutputStream messages) throws IOException {
2137 		init(input, output, messages);
2138 		try {
2139 			service();
2140 		} catch (PackProtocolException e) {
2141 			fatalError(e.getMessage());
2142 			throw e;
2143 		} catch (InputOverLimitIOException e) {
2144 			String msg = JGitText.get().tooManyCommands;
2145 			fatalError(msg);
2146 			throw new PackProtocolException(msg, e);
2147 		} finally {
2148 			try {
2149 				close();
2150 			} finally {
2151 				release();
2152 			}
2153 		}
2154 	}
2155 
2156 	/**
2157 	 * Execute the receive task on the socket.
2158 	 *
2159 	 * <p>
2160 	 * Same as {@link #receive}, but the exceptions are not reported to the
2161 	 * client yet.
2162 	 *
2163 	 * @param input
2164 	 *            raw input to read client commands and pack data from. Caller
2165 	 *            must ensure the input is buffered, otherwise read performance
2166 	 *            may suffer.
2167 	 * @param output
2168 	 *            response back to the Git network client. Caller must ensure
2169 	 *            the output is buffered, otherwise write performance may
2170 	 *            suffer.
2171 	 * @param messages
2172 	 *            secondary "notice" channel to send additional messages out
2173 	 *            through. When run over SSH this should be tied back to the
2174 	 *            standard error channel of the command execution. For most
2175 	 *            other network connections this should be null.
2176 	 * @throws java.io.IOException
2177 	 * @since 5.7
2178 	 */
2179 	public void receiveWithExceptionPropagation(InputStream input,
2180 			OutputStream output, OutputStream messages) throws IOException {
2181 		init(input, output, messages);
2182 		try {
2183 			service();
2184 		} finally {
2185 			try {
2186 				close();
2187 			} finally {
2188 				release();
2189 			}
2190 		}
2191 	}
2192 
2193 	private void service() throws IOException {
2194 		if (isBiDirectionalPipe()) {
2195 			sendAdvertisedRefs(new PacketLineOutRefAdvertiser(pckOut));
2196 			pckOut.flush();
2197 		} else
2198 			getAdvertisedOrDefaultRefs();
2199 		if (hasError())
2200 			return;
2201 
2202 		recvCommands();
2203 
2204 		if (hasCommands()) {
2205 			try (PostReceiveExecutor e = new PostReceiveExecutor()) {
2206 				if (needPack()) {
2207 					try {
2208 						receivePackAndCheckConnectivity();
2209 					} catch (IOException | RuntimeException
2210 							| SubmoduleValidationException | Error err) {
2211 						unlockPack();
2212 						unpackErrorHandler.handleUnpackException(err);
2213 						throw new UnpackException(err);
2214 					}
2215 				}
2216 
2217 				try {
2218 					setAtomic(isCapabilityEnabled(CAPABILITY_ATOMIC));
2219 
2220 					validateCommands();
2221 					if (atomic && anyRejects()) {
2222 						failPendingCommands();
2223 					}
2224 
2225 					preReceive.onPreReceive(
2226 							this, filterCommands(Result.NOT_ATTEMPTED));
2227 					if (atomic && anyRejects()) {
2228 						failPendingCommands();
2229 					}
2230 					executeCommands();
2231 				} finally {
2232 					unlockPack();
2233 				}
2234 
2235 				sendStatusReport(null);
2236 			}
2237 			autoGc();
2238 		}
2239 	}
2240 
2241 	private void autoGc() {
2242 		Repository repo = getRepository();
2243 		if (!repo.getConfig().getBoolean(ConfigConstants.CONFIG_RECEIVE_SECTION,
2244 				ConfigConstants.CONFIG_KEY_AUTOGC, true)) {
2245 			return;
2246 		}
2247 		repo.autoGC(NullProgressMonitor.INSTANCE);
2248 	}
2249 
2250 	static ReceiveCommand parseCommand(String line)
2251 			throws PackProtocolException {
2252 		if (line == null || line.length() < 83) {
2253 			throw new PackProtocolException(
2254 					JGitText.get().errorInvalidProtocolWantedOldNewRef);
2255 		}
2256 		String oldStr = line.substring(0, 40);
2257 		String newStr = line.substring(41, 81);
2258 		ObjectId oldId, newId;
2259 		try {
2260 			oldId = ObjectId.fromString(oldStr);
2261 			newId = ObjectId.fromString(newStr);
2262 		} catch (InvalidObjectIdException e) {
2263 			throw new PackProtocolException(
2264 					JGitText.get().errorInvalidProtocolWantedOldNewRef, e);
2265 		}
2266 		String name = line.substring(82);
2267 		if (!Repository.isValidRefName(name)) {
2268 			throw new PackProtocolException(
2269 					JGitText.get().errorInvalidProtocolWantedOldNewRef);
2270 		}
2271 		return new ReceiveCommand(oldId, newId, name);
2272 	}
2273 
2274 	private class PostReceiveExecutor implements AutoCloseable {
2275 		@Override
2276 		public void close() {
2277 			postReceive.onPostReceive(ReceivePack.this,
2278 					filterCommands(Result.OK));
2279 		}
2280 	}
2281 
2282 	private class DefaultUnpackErrorHandler implements UnpackErrorHandler {
2283 		@Override
2284 		public void handleUnpackException(Throwable t) throws IOException {
2285 			sendStatusReport(t);
2286 		}
2287 	}
2288 }