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