BasePackFetchConnection.java

  1. /*
  2.  * Copyright (C) 2008, 2010 Google Inc.
  3.  * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
  4.  * Copyright (C) 2008, 2022 Shawn O. Pearce <spearce@spearce.org> and others
  5.  *
  6.  * This program and the accompanying materials are made available under the
  7.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  8.  * https://www.eclipse.org/org/documents/edl-v10.php.
  9.  *
  10.  * SPDX-License-Identifier: BSD-3-Clause
  11.  */

  12. package org.eclipse.jgit.transport;

  13. import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DELIM;
  14. import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DEEPEN;
  15. import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DEEPEN_NOT;
  16. import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DEEPEN_SINCE;
  17. import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_DONE;
  18. import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_END;
  19. import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_ERR;
  20. import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_HAVE;
  21. import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_SHALLOW;
  22. import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_UNSHALLOW;
  23. import static org.eclipse.jgit.transport.GitProtocolConstants.PACKET_WANT;

  24. import java.io.IOException;
  25. import java.io.InputStream;
  26. import java.io.OutputStream;
  27. import java.text.MessageFormat;
  28. import java.time.Instant;
  29. import java.util.Arrays;
  30. import java.util.Collection;
  31. import java.util.Collections;
  32. import java.util.Date;
  33. import java.util.HashSet;
  34. import java.util.LinkedHashSet;
  35. import java.util.List;
  36. import java.util.Set;

  37. import org.eclipse.jgit.errors.PackProtocolException;
  38. import org.eclipse.jgit.errors.RemoteRepositoryException;
  39. import org.eclipse.jgit.errors.TransportException;
  40. import org.eclipse.jgit.internal.JGitText;
  41. import org.eclipse.jgit.lib.AnyObjectId;
  42. import org.eclipse.jgit.lib.Config;
  43. import org.eclipse.jgit.lib.MutableObjectId;
  44. import org.eclipse.jgit.lib.NullProgressMonitor;
  45. import org.eclipse.jgit.lib.ObjectDatabase;
  46. import org.eclipse.jgit.lib.ObjectId;
  47. import org.eclipse.jgit.lib.ObjectInserter;
  48. import org.eclipse.jgit.lib.ProgressMonitor;
  49. import org.eclipse.jgit.lib.Ref;
  50. import org.eclipse.jgit.revwalk.RevCommit;
  51. import org.eclipse.jgit.revwalk.RevCommitList;
  52. import org.eclipse.jgit.revwalk.RevFlag;
  53. import org.eclipse.jgit.revwalk.RevObject;
  54. import org.eclipse.jgit.revwalk.RevSort;
  55. import org.eclipse.jgit.revwalk.RevWalk;
  56. import org.eclipse.jgit.revwalk.filter.CommitTimeRevFilter;
  57. import org.eclipse.jgit.revwalk.filter.RevFilter;
  58. import org.eclipse.jgit.transport.GitProtocolConstants.MultiAck;
  59. import org.eclipse.jgit.transport.PacketLineIn.AckNackResult;
  60. import org.eclipse.jgit.util.StringUtils;
  61. import org.eclipse.jgit.util.TemporaryBuffer;

  62. /**
  63.  * Fetch implementation using the native Git pack transfer service.
  64.  * <p>
  65.  * This is the canonical implementation for transferring objects from the remote
  66.  * repository to the local repository by talking to the 'git-upload-pack'
  67.  * service. Objects are packed on the remote side into a pack file and then sent
  68.  * down the pipe to us.
  69.  * <p>
  70.  * This connection requires only a bi-directional pipe or socket, and thus is
  71.  * easily wrapped up into a local process pipe, anonymous TCP socket, or a
  72.  * command executed through an SSH tunnel.
  73.  * <p>
  74.  * If {@link org.eclipse.jgit.transport.BasePackConnection#statelessRPC} is
  75.  * {@code true}, this connection can be tunneled over a request-response style
  76.  * RPC system like HTTP. The RPC call boundary is determined by this class
  77.  * switching from writing to the OutputStream to reading from the InputStream.
  78.  * <p>
  79.  * Concrete implementations should just call
  80.  * {@link #init(java.io.InputStream, java.io.OutputStream)} and
  81.  * {@link #readAdvertisedRefs()} methods in constructor or before any use. They
  82.  * should also handle resources releasing in {@link #close()} method if needed.
  83.  */
  84. public abstract class BasePackFetchConnection extends BasePackConnection
  85.         implements FetchConnection {
  86.     /**
  87.      * Maximum number of 'have' lines to send before giving up.
  88.      * <p>
  89.      * During {@link #negotiate(ProgressMonitor, boolean, Set)} we send at most this many
  90.      * commits to the remote peer as 'have' lines without an ACK response before
  91.      * we give up.
  92.      */
  93.     private static final int MAX_HAVES = 256;

  94.     /**
  95.      * Amount of data the client sends before starting to read.
  96.      * <p>
  97.      * Any output stream given to the client must be able to buffer this many
  98.      * bytes before the client will stop writing and start reading from the
  99.      * input stream. If the output stream blocks before this many bytes are in
  100.      * the send queue, the system will deadlock.
  101.      */
  102.     protected static final int MIN_CLIENT_BUFFER = 2 * 32 * 46 + 8;

  103.     /**
  104.      * Include tags if we are also including the referenced objects.
  105.      * @since 2.0
  106.      */
  107.     public static final String OPTION_INCLUDE_TAG = GitProtocolConstants.OPTION_INCLUDE_TAG;

  108.     /**
  109.      * Multi-ACK support for improved negotiation.
  110.      * @since 2.0
  111.      */
  112.     public static final String OPTION_MULTI_ACK = GitProtocolConstants.OPTION_MULTI_ACK;

  113.     /**
  114.      * Multi-ACK detailed support for improved negotiation.
  115.      * @since 2.0
  116.      */
  117.     public static final String OPTION_MULTI_ACK_DETAILED = GitProtocolConstants.OPTION_MULTI_ACK_DETAILED;

  118.     /**
  119.      * The client supports packs with deltas but not their bases.
  120.      * @since 2.0
  121.      */
  122.     public static final String OPTION_THIN_PACK = GitProtocolConstants.OPTION_THIN_PACK;

  123.     /**
  124.      * The client supports using the side-band for progress messages.
  125.      * @since 2.0
  126.      */
  127.     public static final String OPTION_SIDE_BAND = GitProtocolConstants.OPTION_SIDE_BAND;

  128.     /**
  129.      * The client supports using the 64K side-band for progress messages.
  130.      * @since 2.0
  131.      */
  132.     public static final String OPTION_SIDE_BAND_64K = GitProtocolConstants.OPTION_SIDE_BAND_64K;

  133.     /**
  134.      * The client supports packs with OFS deltas.
  135.      * @since 2.0
  136.      */
  137.     public static final String OPTION_OFS_DELTA = GitProtocolConstants.OPTION_OFS_DELTA;

  138.     /**
  139.      * The client supports shallow fetches.
  140.      * @since 2.0
  141.      */
  142.     public static final String OPTION_SHALLOW = GitProtocolConstants.OPTION_SHALLOW;

  143.     /**
  144.      * The client does not want progress messages and will ignore them.
  145.      * @since 2.0
  146.      */
  147.     public static final String OPTION_NO_PROGRESS = GitProtocolConstants.OPTION_NO_PROGRESS;

  148.     /**
  149.      * The client supports receiving a pack before it has sent "done".
  150.      * @since 2.0
  151.      */
  152.     public static final String OPTION_NO_DONE = GitProtocolConstants.OPTION_NO_DONE;

  153.     /**
  154.      * The client supports fetching objects at the tip of any ref, even if not
  155.      * advertised.
  156.      * @since 3.1
  157.      */
  158.     public static final String OPTION_ALLOW_TIP_SHA1_IN_WANT = GitProtocolConstants.OPTION_ALLOW_TIP_SHA1_IN_WANT;

  159.     /**
  160.      * The client supports fetching objects that are reachable from a tip of a
  161.      * ref that is allowed to fetch.
  162.      * @since 4.1
  163.      */
  164.     public static final String OPTION_ALLOW_REACHABLE_SHA1_IN_WANT = GitProtocolConstants.OPTION_ALLOW_REACHABLE_SHA1_IN_WANT;

  165.     /**
  166.      * The client specified a filter expression.
  167.      *
  168.      * @since 5.0
  169.      */
  170.     public static final String OPTION_FILTER = GitProtocolConstants.OPTION_FILTER;

  171.     private final RevWalk walk;

  172.     /** All commits that are immediately reachable by a local ref. */
  173.     private RevCommitList<RevCommit> reachableCommits;

  174.     /** Marks an object as having all its dependencies. */
  175.     final RevFlag REACHABLE;

  176.     /** Marks a commit known to both sides of the connection. */
  177.     final RevFlag COMMON;

  178.     /** Like {@link #COMMON} but means its also in {@link #pckState}. */
  179.     private final RevFlag STATE;

  180.     /** Marks a commit listed in the advertised refs. */
  181.     final RevFlag ADVERTISED;

  182.     private MultiAck multiAck = MultiAck.OFF;

  183.     private boolean thinPack;

  184.     private boolean sideband;

  185.     private boolean includeTags;

  186.     private boolean allowOfsDelta;

  187.     private boolean noDone;

  188.     private boolean noProgress;

  189.     private String lockMessage;

  190.     private PackLock packLock;

  191.     private int maxHaves;

  192.     private Integer depth;

  193.     private Instant deepenSince;

  194.     private List<String> deepenNots;

  195.     /**
  196.      * RPC state, if {@link BasePackConnection#statelessRPC} is true or protocol
  197.      * V2 is used.
  198.      */
  199.     private TemporaryBuffer.Heap state;

  200.     private PacketLineOut pckState;

  201.     /**
  202.      * Either FilterSpec.NO_FILTER for a filter that doesn't filter
  203.      * anything, or a filter that indicates what and what not to send to the
  204.      * server.
  205.      */
  206.     private final FilterSpec filterSpec;

  207.     /**
  208.      * Create a new connection to fetch using the native git transport.
  209.      *
  210.      * @param packTransport
  211.      *            the transport.
  212.      */
  213.     public BasePackFetchConnection(PackTransport packTransport) {
  214.         super(packTransport);

  215.         if (local != null) {
  216.             final FetchConfig cfg = getFetchConfig();
  217.             allowOfsDelta = cfg.allowOfsDelta;
  218.             maxHaves = cfg.maxHaves;
  219.         } else {
  220.             allowOfsDelta = true;
  221.             maxHaves = Integer.MAX_VALUE;
  222.         }

  223.         includeTags = transport.getTagOpt() != TagOpt.NO_TAGS;
  224.         thinPack = transport.isFetchThin();
  225.         filterSpec = transport.getFilterSpec();
  226.         depth = transport.getDepth();
  227.         deepenSince = transport.getDeepenSince();
  228.         deepenNots = transport.getDeepenNots();

  229.         if (local != null) {
  230.             walk = new RevWalk(local);
  231.             walk.setRetainBody(false);
  232.             reachableCommits = new RevCommitList<>();
  233.             REACHABLE = walk.newFlag("REACHABLE"); //$NON-NLS-1$
  234.             COMMON = walk.newFlag("COMMON"); //$NON-NLS-1$
  235.             STATE = walk.newFlag("STATE"); //$NON-NLS-1$
  236.             ADVERTISED = walk.newFlag("ADVERTISED"); //$NON-NLS-1$

  237.             walk.carry(COMMON);
  238.             walk.carry(REACHABLE);
  239.             walk.carry(ADVERTISED);
  240.         } else {
  241.             walk = null;
  242.             REACHABLE = null;
  243.             COMMON = null;
  244.             STATE = null;
  245.             ADVERTISED = null;
  246.         }
  247.     }

  248.     static class FetchConfig {
  249.         final boolean allowOfsDelta;

  250.         final int maxHaves;

  251.         FetchConfig(Config c) {
  252.             allowOfsDelta = c.getBoolean("repack", "usedeltabaseoffset", true); //$NON-NLS-1$ //$NON-NLS-2$
  253.             maxHaves = c.getInt("fetch", "maxhaves", Integer.MAX_VALUE); //$NON-NLS-1$ //$NON-NLS-2$
  254.         }

  255.         FetchConfig(boolean allowOfsDelta, int maxHaves) {
  256.             this.allowOfsDelta = allowOfsDelta;
  257.             this.maxHaves = maxHaves;
  258.         }
  259.     }

  260.     /** {@inheritDoc} */
  261.     @Override
  262.     public final void fetch(final ProgressMonitor monitor,
  263.             final Collection<Ref> want, final Set<ObjectId> have)
  264.             throws TransportException {
  265.         fetch(monitor, want, have, null);
  266.     }

  267.     /** {@inheritDoc} */
  268.     @Override
  269.     public final void fetch(final ProgressMonitor monitor,
  270.             final Collection<Ref> want, final Set<ObjectId> have,
  271.             OutputStream outputStream) throws TransportException {
  272.         markStartedOperation();
  273.         doFetch(monitor, want, have, outputStream);
  274.     }

  275.     /** {@inheritDoc} */
  276.     @Override
  277.     public boolean didFetchIncludeTags() {
  278.         return false;
  279.     }

  280.     /** {@inheritDoc} */
  281.     @Override
  282.     public boolean didFetchTestConnectivity() {
  283.         return false;
  284.     }

  285.     /** {@inheritDoc} */
  286.     @Override
  287.     public void setPackLockMessage(String message) {
  288.         lockMessage = message;
  289.     }

  290.     /** {@inheritDoc} */
  291.     @Override
  292.     public Collection<PackLock> getPackLocks() {
  293.         if (packLock != null)
  294.             return Collections.singleton(packLock);
  295.         return Collections.<PackLock> emptyList();
  296.     }

  297.     private void clearState() {
  298.         walk.dispose();
  299.         reachableCommits = null;
  300.         state = null;
  301.         pckState = null;
  302.     }

  303.     /**
  304.      * Execute common ancestor negotiation and fetch the objects.
  305.      *
  306.      * @param monitor
  307.      *            progress monitor to receive status updates. If the monitor is
  308.      *            the {@link org.eclipse.jgit.lib.NullProgressMonitor#INSTANCE}, then the no-progress
  309.      *            option enabled.
  310.      * @param want
  311.      *            the advertised remote references the caller wants to fetch.
  312.      * @param have
  313.      *            additional objects to assume that already exist locally. This
  314.      *            will be added to the set of objects reachable from the
  315.      *            destination repository's references.
  316.      * @param outputStream
  317.      *            ouputStream to write sideband messages to
  318.      * @throws org.eclipse.jgit.errors.TransportException
  319.      *             if any exception occurs.
  320.      * @since 3.0
  321.      */
  322.     protected void doFetch(final ProgressMonitor monitor,
  323.             final Collection<Ref> want, final Set<ObjectId> have,
  324.             OutputStream outputStream) throws TransportException {
  325.         try {
  326.             noProgress = monitor == NullProgressMonitor.INSTANCE;

  327.             markRefsAdvertised();
  328.             markReachable(have, maxTimeWanted(want));

  329.             if (TransferConfig.ProtocolVersion.V2
  330.                     .equals(getProtocolVersion())) {
  331.                 // Protocol V2 always is a "stateless" protocol, even over a
  332.                 // bidirectional pipe: the server serves one "fetch" request and
  333.                 // then forgets anything it has learned, so the next fetch
  334.                 // request has to re-send all wants and previously determined
  335.                 // common objects as "have"s again.
  336.                 state = new TemporaryBuffer.Heap(Integer.MAX_VALUE);
  337.                 pckState = new PacketLineOut(state);
  338.                 try {
  339.                     doFetchV2(monitor, want, outputStream);
  340.                 } finally {
  341.                     clearState();
  342.                 }
  343.                 return;
  344.             }
  345.             // Protocol V0/1
  346.             if (statelessRPC) {
  347.                 state = new TemporaryBuffer.Heap(Integer.MAX_VALUE);
  348.                 pckState = new PacketLineOut(state);
  349.             }
  350.             PacketLineOut output = statelessRPC ? pckState : pckOut;
  351.             if (sendWants(want, output)) {
  352.                 boolean mayHaveShallow = depth != null || deepenSince != null || !deepenNots.isEmpty();
  353.                 Set<ObjectId> shallowCommits = local.getObjectDatabase().getShallowCommits();
  354.                 if (isCapableOf(GitProtocolConstants.CAPABILITY_SHALLOW)) {
  355.                     sendShallow(shallowCommits, output);
  356.                 } else if (mayHaveShallow) {
  357.                     throw new PackProtocolException(JGitText.get().shallowNotSupported);
  358.                 }
  359.                 output.end();
  360.                 outNeedsEnd = false;

  361.                 negotiate(monitor, mayHaveShallow, shallowCommits);

  362.                 clearState();

  363.                 receivePack(monitor, outputStream);
  364.             }
  365.         } catch (CancelledException ce) {
  366.             close();
  367.             return; // Caller should test (or just know) this themselves.
  368.         } catch (IOException | RuntimeException err) {
  369.             close();
  370.             throw new TransportException(err.getMessage(), err);
  371.         }
  372.     }

  373.     private void doFetchV2(ProgressMonitor monitor, Collection<Ref> want,
  374.             OutputStream outputStream) throws IOException, CancelledException {
  375.         sideband = true;
  376.         negotiateBegin();

  377.         pckState.writeString("command=" + GitProtocolConstants.COMMAND_FETCH); //$NON-NLS-1$
  378.         // Capabilities are sent as command arguments in protocol V2
  379.         String agent = UserAgent.get();
  380.         if (agent != null && isCapableOf(GitProtocolConstants.OPTION_AGENT)) {
  381.             pckState.writeString(
  382.                     GitProtocolConstants.OPTION_AGENT + '=' + agent);
  383.         }
  384.         Set<String> capabilities = new HashSet<>();
  385.         String advertised = getCapability(GitProtocolConstants.COMMAND_FETCH);
  386.         if (!StringUtils.isEmptyOrNull(advertised)) {
  387.             capabilities.addAll(Arrays.asList(advertised.split("\\s+"))); //$NON-NLS-1$
  388.         }
  389.         // Arguments
  390.         pckState.writeDelim();
  391.         for (String capability : getCapabilitiesV2(capabilities)) {
  392.             pckState.writeString(capability);
  393.         }

  394.         if (!sendWants(want, pckState)) {
  395.             // We already have everything we wanted.
  396.             return;
  397.         }

  398.         Set<ObjectId> shallowCommits = local.getObjectDatabase().getShallowCommits();
  399.         if (capabilities.contains(GitProtocolConstants.CAPABILITY_SHALLOW)) {
  400.             sendShallow(shallowCommits, pckState);
  401.         } else if (depth != null || deepenSince != null || !deepenNots.isEmpty()) {
  402.             throw new PackProtocolException(JGitText.get().shallowNotSupported);
  403.         }
  404.         // If we send something, we always close it properly ourselves.
  405.         outNeedsEnd = false;

  406.         FetchStateV2 fetchState = new FetchStateV2();
  407.         boolean sentDone = false;
  408.         for (;;) {
  409.             // The "state" buffer contains the full fetch request with all
  410.             // common objects found so far.
  411.             state.writeTo(out, monitor);
  412.             sentDone = sendNextHaveBatch(fetchState, pckOut, monitor);
  413.             if (sentDone) {
  414.                 break;
  415.             }
  416.             if (readAcknowledgments(fetchState, pckIn, monitor)) {
  417.                 // We got a "ready": next should be a patch file.
  418.                 break;
  419.             }
  420.             // Note: C git reads and requires here (and after a packfile) a
  421.             // "0002" packet in stateless RPC transports (https). This "response
  422.             // end" packet is even mentioned in the protocol V2 technical
  423.             // documentation. However, it is not actually part of the public
  424.             // protocol; it occurs only in an internal protocol wrapper in the C
  425.             // git implementation.
  426.         }
  427.         clearState();
  428.         String line = pckIn.readString();
  429.         // If we sent a done, we may have an error reply here.
  430.         if (sentDone && line.startsWith(PACKET_ERR)) {
  431.             throw new RemoteRepositoryException(uri, line.substring(4));
  432.         }

  433.         if (GitProtocolConstants.SECTION_SHALLOW_INFO.equals(line)) {
  434.             line = handleShallowUnshallow(shallowCommits, pckIn);
  435.             if (!PacketLineIn.isDelimiter(line)) {
  436.                 throw new PackProtocolException(MessageFormat
  437.                         .format(JGitText.get().expectedGot, PACKET_DELIM,
  438.                                 line));
  439.             }
  440.             line = pckIn.readString();
  441.         }

  442.         // "wanted-refs" and "packfile-uris" would have to be
  443.         // handled here in that order.
  444.         if (!GitProtocolConstants.SECTION_PACKFILE.equals(line)) {
  445.             throw new PackProtocolException(
  446.                     MessageFormat.format(JGitText.get().expectedGot,
  447.                             GitProtocolConstants.SECTION_PACKFILE, line));
  448.         }
  449.         receivePack(monitor, outputStream);
  450.     }

  451.     /**
  452.      * Sends the next batch of "have"s and terminates the {@code output}.
  453.      *
  454.      * @param fetchState
  455.      *            is updated with information about the number of items written,
  456.      *            and whether to expect a packfile next
  457.      * @param output
  458.      *            to write to
  459.      * @param monitor
  460.      *            for progress reporting and cancellation
  461.      * @return {@code true} if a "done" was written and we should thus expect a
  462.      *         packfile next
  463.      * @throws IOException
  464.      *             on errors
  465.      * @throws CancelledException
  466.      *             on cancellation
  467.      */
  468.     private boolean sendNextHaveBatch(FetchStateV2 fetchState,
  469.             PacketLineOut output, ProgressMonitor monitor)
  470.             throws IOException, CancelledException {
  471.         long n = 0;
  472.         while (n < fetchState.havesToSend) {
  473.             final RevCommit c = walk.next();
  474.             if (c == null) {
  475.                 break;
  476.             }
  477.             output.writeString(PACKET_HAVE + c.getId().name() + '\n');
  478.             n++;
  479.             if (n % 10 == 0 && monitor.isCancelled()) {
  480.                 throw new CancelledException();
  481.             }
  482.         }
  483.         fetchState.havesTotal += n;
  484.         if (n == 0
  485.                 || (fetchState.hadAcks
  486.                         && fetchState.havesWithoutAck > MAX_HAVES)
  487.                 || fetchState.havesTotal > maxHaves) {
  488.             output.writeString(PACKET_DONE + '\n');
  489.             output.end();
  490.             return true;
  491.         }
  492.         // Increment only after the test above. Of course we have no ACKs yet
  493.         // for the newly added "have"s, so it makes no sense to count them
  494.         // against the MAX_HAVES limit.
  495.         fetchState.havesWithoutAck += n;
  496.         output.end();
  497.         fetchState.incHavesToSend(statelessRPC);
  498.         return false;
  499.     }

  500.     /**
  501.      * Reads and processes acknowledgments, adding ACKed objects as "have"s to
  502.      * the global state {@link TemporaryBuffer}.
  503.      *
  504.      * @param fetchState
  505.      *            to update
  506.      * @param input
  507.      *            to read from
  508.      * @param monitor
  509.      *            for progress reporting and cancellation
  510.      * @return {@code true} if a "ready" was received and a packfile is expected
  511.      *         next
  512.      * @throws IOException
  513.      *             on errors
  514.      * @throws CancelledException
  515.      *             on cancellation
  516.      */
  517.     private boolean readAcknowledgments(FetchStateV2 fetchState,
  518.             PacketLineIn input, ProgressMonitor monitor)
  519.             throws IOException, CancelledException {
  520.         String line = input.readString();
  521.         if (!GitProtocolConstants.SECTION_ACKNOWLEDGMENTS.equals(line)) {
  522.             throw new PackProtocolException(MessageFormat.format(
  523.                     JGitText.get().expectedGot,
  524.                     GitProtocolConstants.SECTION_ACKNOWLEDGMENTS, line));
  525.         }
  526.         MutableObjectId returnedId = new MutableObjectId();
  527.         line = input.readString();
  528.         boolean gotReady = false;
  529.         long n = 0;
  530.         while (!PacketLineIn.isEnd(line) && !PacketLineIn.isDelimiter(line)) {
  531.             AckNackResult ack = PacketLineIn.parseACKv2(line, returnedId);
  532.             // If we got a "ready", we just skip the remaining lines after
  533.             // having checked them for being valid. (Normally, the "ready"
  534.             // should be the last line anyway.)
  535.             if (!gotReady) {
  536.                 if (ack == AckNackResult.ACK_COMMON) {
  537.                     // markCommon appends the object to the "state"
  538.                     markCommon(walk.parseAny(returnedId), ack, true);
  539.                     fetchState.havesWithoutAck = 0;
  540.                     fetchState.hadAcks = true;
  541.                 } else if (ack == AckNackResult.ACK_READY) {
  542.                     gotReady = true;
  543.                 }
  544.             }
  545.             n++;
  546.             if (n % 10 == 0 && monitor.isCancelled()) {
  547.                 throw new CancelledException();
  548.             }
  549.             line = input.readString();
  550.         }
  551.         if (gotReady) {
  552.             if (!PacketLineIn.isDelimiter(line)) {
  553.                 throw new PackProtocolException(MessageFormat
  554.                         .format(JGitText.get().expectedGot, PACKET_DELIM,
  555.                                 line));
  556.             }
  557.         } else if (!PacketLineIn.isEnd(line)) {
  558.             throw new PackProtocolException(MessageFormat
  559.                     .format(JGitText.get().expectedGot, PACKET_END, line));
  560.         }
  561.         return gotReady;
  562.     }

  563.     /** {@inheritDoc} */
  564.     @Override
  565.     public void close() {
  566.         if (walk != null)
  567.             walk.close();
  568.         super.close();
  569.     }

  570.     FetchConfig getFetchConfig() {
  571.         return local.getConfig().get(FetchConfig::new);
  572.     }

  573.     private int maxTimeWanted(Collection<Ref> wants) {
  574.         int maxTime = 0;
  575.         for (Ref r : wants) {
  576.             try {
  577.                 final RevObject obj = walk.parseAny(r.getObjectId());
  578.                 if (obj instanceof RevCommit) {
  579.                     final int cTime = ((RevCommit) obj).getCommitTime();
  580.                     if (maxTime < cTime)
  581.                         maxTime = cTime;
  582.                 }
  583.             } catch (IOException error) {
  584.                 // We don't have it, but we want to fetch (thus fixing error).
  585.             }
  586.         }
  587.         return maxTime;
  588.     }

  589.     private void markReachable(Set<ObjectId> have, int maxTime)
  590.             throws IOException {
  591.         for (Ref r : local.getRefDatabase().getRefs()) {
  592.             ObjectId id = r.getPeeledObjectId();
  593.             if (id == null)
  594.                 id = r.getObjectId();
  595.             if (id == null)
  596.                 continue;
  597.             parseReachable(id);
  598.         }

  599.         for (ObjectId id : local.getAdditionalHaves())
  600.             parseReachable(id);

  601.         for (ObjectId id : have)
  602.             parseReachable(id);

  603.         if (maxTime > 0) {
  604.             // Mark reachable commits until we reach maxTime. These may
  605.             // wind up later matching up against things we want and we
  606.             // can avoid asking for something we already happen to have.
  607.             //
  608.             final Date maxWhen = new Date(maxTime * 1000L);
  609.             walk.sort(RevSort.COMMIT_TIME_DESC);
  610.             walk.markStart(reachableCommits);
  611.             walk.setRevFilter(CommitTimeRevFilter.after(maxWhen));
  612.             for (;;) {
  613.                 final RevCommit c = walk.next();
  614.                 if (c == null)
  615.                     break;
  616.                 if (c.has(ADVERTISED) && !c.has(COMMON)) {
  617.                     // This is actually going to be a common commit, but
  618.                     // our peer doesn't know that fact yet.
  619.                     //
  620.                     c.add(COMMON);
  621.                     c.carry(COMMON);
  622.                     reachableCommits.add(c);
  623.                 }
  624.             }
  625.         }
  626.     }

  627.     private void parseReachable(ObjectId id) {
  628.         try {
  629.             RevCommit o = walk.parseCommit(id);
  630.             if (!o.has(REACHABLE)) {
  631.                 o.add(REACHABLE);
  632.                 reachableCommits.add(o);
  633.             }
  634.         } catch (IOException readError) {
  635.             // If we cannot read the value of the ref skip it.
  636.         }
  637.     }

  638.     private boolean sendWants(Collection<Ref> want, PacketLineOut p)
  639.             throws IOException {
  640.         boolean first = true;
  641.         for (Ref r : want) {
  642.             ObjectId objectId = r.getObjectId();
  643.             if (objectId == null) {
  644.                 continue;
  645.             }
  646.             // if depth is set we need to fetch the objects even if they are already available
  647.             if (transport.getDepth() == null) {
  648.                 try {
  649.                     if (walk.parseAny(objectId).has(REACHABLE)) {
  650.                         // We already have this object. Asking for it is
  651.                         // not a very good idea.
  652.                         //
  653.                         continue;
  654.                     }
  655.                 } catch (IOException err) {
  656.                     // Its OK, we don't have it, but we want to fix that
  657.                     // by fetching the object from the other side.
  658.                 }
  659.             }

  660.             final StringBuilder line = new StringBuilder(46);
  661.             line.append(PACKET_WANT).append(objectId.name());
  662.             if (first && TransferConfig.ProtocolVersion.V0
  663.                     .equals(getProtocolVersion())) {
  664.                 line.append(enableCapabilities());
  665.             }
  666.             first = false;
  667.             line.append('\n');
  668.             p.writeString(line.toString());
  669.         }
  670.         if (first) {
  671.             return false;
  672.         }
  673.         if (!filterSpec.isNoOp()) {
  674.             p.writeString(filterSpec.filterLine());
  675.         }
  676.         return true;
  677.     }

  678.     private Set<String> getCapabilitiesV2(Set<String> advertisedCapabilities)
  679.             throws TransportException {
  680.         Set<String> capabilities = new LinkedHashSet<>();
  681.         // Protocol V2 is implicitly capable of all these.
  682.         if (noProgress) {
  683.             capabilities.add(OPTION_NO_PROGRESS);
  684.         }
  685.         if (includeTags) {
  686.             capabilities.add(OPTION_INCLUDE_TAG);
  687.         }
  688.         if (allowOfsDelta) {
  689.             capabilities.add(OPTION_OFS_DELTA);
  690.         }
  691.         if (thinPack) {
  692.             capabilities.add(OPTION_THIN_PACK);
  693.         }
  694.         if (!filterSpec.isNoOp()
  695.                 && !advertisedCapabilities.contains(OPTION_FILTER)) {
  696.             throw new PackProtocolException(uri,
  697.                     JGitText.get().filterRequiresCapability);
  698.         }
  699.         // The FilterSpec will be added later in sendWants().
  700.         return capabilities;
  701.     }

  702.     private String enableCapabilities() throws TransportException {
  703.         final StringBuilder line = new StringBuilder();
  704.         if (noProgress)
  705.             wantCapability(line, OPTION_NO_PROGRESS);
  706.         if (includeTags)
  707.             includeTags = wantCapability(line, OPTION_INCLUDE_TAG);
  708.         if (allowOfsDelta)
  709.             wantCapability(line, OPTION_OFS_DELTA);

  710.         if (wantCapability(line, OPTION_MULTI_ACK_DETAILED)) {
  711.             multiAck = MultiAck.DETAILED;
  712.             if (statelessRPC)
  713.                 noDone = wantCapability(line, OPTION_NO_DONE);
  714.         } else if (wantCapability(line, OPTION_MULTI_ACK))
  715.             multiAck = MultiAck.CONTINUE;
  716.         else
  717.             multiAck = MultiAck.OFF;

  718.         if (thinPack)
  719.             thinPack = wantCapability(line, OPTION_THIN_PACK);
  720.         if (wantCapability(line, OPTION_SIDE_BAND_64K))
  721.             sideband = true;
  722.         else if (wantCapability(line, OPTION_SIDE_BAND))
  723.             sideband = true;

  724.         if (statelessRPC && multiAck != MultiAck.DETAILED) {
  725.             // Our stateless RPC implementation relies upon the detailed
  726.             // ACK status to tell us common objects for reuse in future
  727.             // requests.  If its not enabled, we can't talk to the peer.
  728.             //
  729.             throw new PackProtocolException(uri, MessageFormat.format(
  730.                     JGitText.get().statelessRPCRequiresOptionToBeEnabled,
  731.                     OPTION_MULTI_ACK_DETAILED));
  732.         }

  733.         if (!filterSpec.isNoOp() && !wantCapability(line, OPTION_FILTER)) {
  734.             throw new PackProtocolException(uri,
  735.                     JGitText.get().filterRequiresCapability);
  736.         }

  737.         addUserAgentCapability(line);
  738.         return line.toString();
  739.     }

  740.     private void negotiate(ProgressMonitor monitor, boolean mayHaveShallow, Set<ObjectId> shallowCommits)
  741.             throws IOException, CancelledException {
  742.         final MutableObjectId ackId = new MutableObjectId();
  743.         int resultsPending = 0;
  744.         int havesSent = 0;
  745.         int havesSinceLastContinue = 0;
  746.         boolean receivedContinue = false;
  747.         boolean receivedAck = false;
  748.         boolean receivedReady = false;

  749.         if (statelessRPC) {
  750.             state.writeTo(out, null);
  751.         }

  752.         negotiateBegin();
  753.         SEND_HAVES: for (;;) {
  754.             final RevCommit c = walk.next();
  755.             if (c == null) {
  756.                 break SEND_HAVES;
  757.             }

  758.             ObjectId o = c.getId();
  759.             pckOut.writeString(PACKET_HAVE + o.name() + '\n');
  760.             havesSent++;
  761.             havesSinceLastContinue++;

  762.             if ((31 & havesSent) != 0) {
  763.                 // We group the have lines into blocks of 32, each marked
  764.                 // with a flush (aka end). This one is within a block so
  765.                 // continue with another have line.
  766.                 //
  767.                 continue;
  768.             }

  769.             if (monitor.isCancelled()) {
  770.                 throw new CancelledException();
  771.             }

  772.             pckOut.end();
  773.             resultsPending++; // Each end will cause a result to come back.

  774.             if (havesSent == 32 && !statelessRPC) {
  775.                 // On the first block we race ahead and try to send
  776.                 // more of the second block while waiting for the
  777.                 // remote to respond to our first block request.
  778.                 // This keeps us one block ahead of the peer.
  779.                 //
  780.                 continue;
  781.             }

  782.             READ_RESULT: for (;;) {
  783.                 final AckNackResult anr = pckIn.readACK(ackId);
  784.                 switch (anr) {
  785.                 case NAK:
  786.                     // More have lines are necessary to compute the
  787.                     // pack on the remote side. Keep doing that.
  788.                     //
  789.                     resultsPending--;
  790.                     break READ_RESULT;

  791.                 case ACK:
  792.                     // The remote side is happy and knows exactly what
  793.                     // to send us. There is no further negotiation and
  794.                     // we can break out immediately.
  795.                     //
  796.                     multiAck = MultiAck.OFF;
  797.                     resultsPending = 0;
  798.                     receivedAck = true;
  799.                     if (statelessRPC) {
  800.                         state.writeTo(out, null);
  801.                     }
  802.                     break SEND_HAVES;

  803.                 case ACK_CONTINUE:
  804.                 case ACK_COMMON:
  805.                 case ACK_READY:
  806.                     // The server knows this commit (ackId). We don't
  807.                     // need to send any further along its ancestry, but
  808.                     // we need to continue to talk about other parts of
  809.                     // our local history.
  810.                     //
  811.                     markCommon(walk.parseAny(ackId), anr, statelessRPC);
  812.                     receivedAck = true;
  813.                     receivedContinue = true;
  814.                     havesSinceLastContinue = 0;
  815.                     if (anr == AckNackResult.ACK_READY) {
  816.                         receivedReady = true;
  817.                     }
  818.                     break;
  819.                 }

  820.                 if (monitor.isCancelled()) {
  821.                     throw new CancelledException();
  822.                 }
  823.             }

  824.             if (noDone && receivedReady) {
  825.                 break SEND_HAVES;
  826.             }
  827.             if (statelessRPC) {
  828.                 state.writeTo(out, null);
  829.             }

  830.             if ((receivedContinue && havesSinceLastContinue > MAX_HAVES)
  831.                     || havesSent >= maxHaves) {
  832.                 // Our history must be really different from the remote's.
  833.                 // We just sent a whole slew of have lines, and it did not
  834.                 // recognize any of them. Avoid sending our entire history
  835.                 // to them by giving up early.
  836.                 //
  837.                 break SEND_HAVES;
  838.             }
  839.         }

  840.         // Tell the remote side we have run out of things to talk about.
  841.         //
  842.         if (monitor.isCancelled()) {
  843.             throw new CancelledException();
  844.         }

  845.         if (!receivedReady || !noDone) {
  846.             // When statelessRPC is true we should always leave SEND_HAVES
  847.             // loop above while in the middle of a request. This allows us
  848.             // to just write done immediately.
  849.             //
  850.             pckOut.writeString(PACKET_DONE + '\n');
  851.             pckOut.flush();
  852.         }

  853.         if (!receivedAck) {
  854.             // Apparently if we have never received an ACK earlier
  855.             // there is one more result expected from the done we
  856.             // just sent to the remote.
  857.             //
  858.             multiAck = MultiAck.OFF;
  859.             resultsPending++;
  860.         }

  861.         if (mayHaveShallow) {
  862.             String line = handleShallowUnshallow(shallowCommits, pckIn);
  863.             if (!PacketLineIn.isEnd(line)) {
  864.                 throw new PackProtocolException(MessageFormat
  865.                         .format(JGitText.get().expectedGot, PACKET_END, line));
  866.             }
  867.         }

  868.         READ_RESULT: while (resultsPending > 0 || multiAck != MultiAck.OFF) {
  869.             final AckNackResult anr = pckIn.readACK(ackId);
  870.             resultsPending--;
  871.             switch (anr) {
  872.             case NAK:
  873.                 // A NAK is a response to an end we queued earlier
  874.                 // we eat it and look for another ACK/NAK message.
  875.                 //
  876.                 break;

  877.             case ACK:
  878.                 // A solitary ACK at this point means the remote won't
  879.                 // speak anymore, but is going to send us a pack now.
  880.                 //
  881.                 break READ_RESULT;

  882.             case ACK_CONTINUE:
  883.             case ACK_COMMON:
  884.             case ACK_READY:
  885.                 // We will expect a normal ACK to break out of the loop.
  886.                 //
  887.                 multiAck = MultiAck.CONTINUE;
  888.                 break;
  889.             }

  890.             if (monitor.isCancelled()) {
  891.                 throw new CancelledException();
  892.             }
  893.         }
  894.     }

  895.     private void negotiateBegin() throws IOException {
  896.         walk.resetRetain(REACHABLE, ADVERTISED);
  897.         walk.markStart(reachableCommits);
  898.         walk.sort(RevSort.COMMIT_TIME_DESC);
  899.         walk.setRevFilter(new RevFilter() {
  900.             @Override
  901.             public RevFilter clone() {
  902.                 return this;
  903.             }

  904.             @Override
  905.             public boolean include(RevWalk walker, RevCommit c) {
  906.                 final boolean remoteKnowsIsCommon = c.has(COMMON);
  907.                 if (c.has(ADVERTISED)) {
  908.                     // Remote advertised this, and we have it, hence common.
  909.                     // Whether or not the remote knows that fact is tested
  910.                     // before we added the flag. If the remote doesn't know
  911.                     // we have to still send them this object.
  912.                     //
  913.                     c.add(COMMON);
  914.                 }
  915.                 return !remoteKnowsIsCommon;
  916.             }

  917.             @Override
  918.             public boolean requiresCommitBody() {
  919.                 return false;
  920.             }
  921.         });
  922.     }

  923.     private void markRefsAdvertised() {
  924.         for (Ref r : getRefs()) {
  925.             markAdvertised(r.getObjectId());
  926.             if (r.getPeeledObjectId() != null)
  927.                 markAdvertised(r.getPeeledObjectId());
  928.         }
  929.     }

  930.     private void markAdvertised(AnyObjectId id) {
  931.         try {
  932.             walk.parseAny(id).add(ADVERTISED);
  933.         } catch (IOException readError) {
  934.             // We probably just do not have this object locally.
  935.         }
  936.     }

  937.     private void markCommon(RevObject obj, AckNackResult anr, boolean useState)
  938.             throws IOException {
  939.         if (useState && anr == AckNackResult.ACK_COMMON && !obj.has(STATE)) {
  940.             pckState.writeString(PACKET_HAVE + obj.name() + '\n');
  941.             obj.add(STATE);
  942.         }
  943.         obj.add(COMMON);
  944.         if (obj instanceof RevCommit)
  945.             ((RevCommit) obj).carry(COMMON);
  946.     }

  947.     private void receivePack(final ProgressMonitor monitor,
  948.             OutputStream outputStream) throws IOException {
  949.         onReceivePack();
  950.         InputStream input = in;
  951.         SideBandInputStream sidebandIn = null;
  952.         if (sideband) {
  953.             sidebandIn = new SideBandInputStream(input, monitor,
  954.                     getMessageWriter(), outputStream);
  955.             input = sidebandIn;
  956.         }

  957.         try (ObjectInserter ins = local.newObjectInserter()) {
  958.             PackParser parser = ins.newPackParser(input);
  959.             parser.setAllowThin(thinPack);
  960.             parser.setObjectChecker(transport.getObjectChecker());
  961.             parser.setLockMessage(lockMessage);
  962.             packLock = parser.parse(monitor);
  963.             ins.flush();
  964.         } finally {
  965.             if (sidebandIn != null) {
  966.                 sidebandIn.drainMessages();
  967.             }
  968.         }
  969.     }

  970.     private void sendShallow(Set<ObjectId> shallowCommits, PacketLineOut output)
  971.             throws IOException {
  972.         for (ObjectId shallowCommit : shallowCommits) {
  973.             output.writeString(PACKET_SHALLOW + shallowCommit.name());
  974.         }

  975.         if (depth != null) {
  976.             output.writeString(PACKET_DEEPEN + depth);
  977.         }

  978.         if (deepenSince != null) {
  979.             output.writeString(
  980.                     PACKET_DEEPEN_SINCE + deepenSince.getEpochSecond());
  981.         }

  982.         if (deepenNots != null) {
  983.             for (String deepenNotRef : deepenNots) {
  984.                 output.writeString(PACKET_DEEPEN_NOT + deepenNotRef);
  985.             }
  986.         }
  987.     }

  988.     private String handleShallowUnshallow(
  989.             Set<ObjectId> advertisedShallowCommits, PacketLineIn input)
  990.             throws IOException {
  991.         String line = input.readString();
  992.         ObjectDatabase objectDatabase = local.getObjectDatabase();
  993.         HashSet<ObjectId> newShallowCommits = new HashSet<>(
  994.                 advertisedShallowCommits);
  995.         while (!PacketLineIn.isDelimiter(line) && !PacketLineIn.isEnd(line)) {
  996.             if (line.startsWith(PACKET_SHALLOW)) {
  997.                 newShallowCommits.add(ObjectId
  998.                         .fromString(line.substring(PACKET_SHALLOW.length())));
  999.             } else if (line.startsWith(PACKET_UNSHALLOW)) {
  1000.                 ObjectId unshallow = ObjectId
  1001.                         .fromString(line.substring(PACKET_UNSHALLOW.length()));
  1002.                 if (!advertisedShallowCommits.contains(unshallow)) {
  1003.                     throw new PackProtocolException(MessageFormat.format(
  1004.                             JGitText.get().notShallowedUnshallow,
  1005.                             unshallow.name()));
  1006.                 }
  1007.                 newShallowCommits.remove(unshallow);
  1008.             }
  1009.             line = input.readString();
  1010.         }
  1011.         objectDatabase.setShallowCommits(newShallowCommits);
  1012.         return line;
  1013.     }

  1014.     /**
  1015.      * Notification event delivered just before the pack is received from the
  1016.      * network. This event can be used by RPC such as {@link org.eclipse.jgit.transport.TransportHttp} to
  1017.      * disable its request magic and ensure the pack stream is read correctly.
  1018.      *
  1019.      * @since 2.0
  1020.      */
  1021.     protected void onReceivePack() {
  1022.         // By default do nothing for TCP based protocols.
  1023.     }

  1024.     private static class CancelledException extends Exception {
  1025.         private static final long serialVersionUID = 1L;
  1026.     }

  1027.     private static class FetchStateV2 {

  1028.         long havesToSend = 32;

  1029.         long havesTotal;

  1030.         // Set to true if we got at least one ACK in protocol V2.
  1031.         boolean hadAcks;

  1032.         // Counts haves without ACK. Use as cutoff for negotiation only once
  1033.         // hadAcks == true.
  1034.         long havesWithoutAck;

  1035.         void incHavesToSend(boolean statelessRPC) {
  1036.             if (statelessRPC) {
  1037.                 // Increase this quicker since connection setup costs accumulate
  1038.                 if (havesToSend < 16384) {
  1039.                     havesToSend *= 2;
  1040.                 } else {
  1041.                     havesToSend = havesToSend * 11 / 10;
  1042.                 }
  1043.             } else {
  1044.                 havesToSend += 32;
  1045.             }
  1046.         }
  1047.     }
  1048. }