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