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