BasePackFetchConnection.java

  1. /*
  2.  * Copyright (C) 2008-2010, Google Inc.
  3.  * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
  4.  * Copyright (C) 2008, 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 java.io.IOException;
  14. import java.io.InputStream;
  15. import java.io.OutputStream;
  16. import java.text.MessageFormat;
  17. import java.util.Collection;
  18. import java.util.Collections;
  19. import java.util.Date;
  20. import java.util.Set;

  21. import org.eclipse.jgit.errors.PackProtocolException;
  22. import org.eclipse.jgit.errors.TransportException;
  23. import org.eclipse.jgit.internal.JGitText;
  24. import org.eclipse.jgit.internal.storage.file.PackLock;
  25. import org.eclipse.jgit.lib.AnyObjectId;
  26. import org.eclipse.jgit.lib.Config;
  27. import org.eclipse.jgit.lib.Constants;
  28. import org.eclipse.jgit.lib.MutableObjectId;
  29. import org.eclipse.jgit.lib.NullProgressMonitor;
  30. import org.eclipse.jgit.lib.ObjectId;
  31. import org.eclipse.jgit.lib.ObjectInserter;
  32. import org.eclipse.jgit.lib.ProgressMonitor;
  33. import org.eclipse.jgit.lib.Ref;
  34. import org.eclipse.jgit.revwalk.RevCommit;
  35. import org.eclipse.jgit.revwalk.RevCommitList;
  36. import org.eclipse.jgit.revwalk.RevFlag;
  37. import org.eclipse.jgit.revwalk.RevObject;
  38. import org.eclipse.jgit.revwalk.RevSort;
  39. import org.eclipse.jgit.revwalk.RevWalk;
  40. import org.eclipse.jgit.revwalk.filter.CommitTimeRevFilter;
  41. import org.eclipse.jgit.revwalk.filter.RevFilter;
  42. import org.eclipse.jgit.transport.GitProtocolConstants.MultiAck;
  43. import org.eclipse.jgit.transport.PacketLineIn.AckNackResult;
  44. import org.eclipse.jgit.util.TemporaryBuffer;

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

  77.     /**
  78.      * Amount of data the client sends before starting to read.
  79.      * <p>
  80.      * Any output stream given to the client must be able to buffer this many
  81.      * bytes before the client will stop writing and start reading from the
  82.      * input stream. If the output stream blocks before this many bytes are in
  83.      * the send queue, the system will deadlock.
  84.      */
  85.     protected static final int MIN_CLIENT_BUFFER = 2 * 32 * 46 + 8;

  86.     /**
  87.      * Include tags if we are also including the referenced objects.
  88.      * @since 2.0
  89.      */
  90.     public static final String OPTION_INCLUDE_TAG = GitProtocolConstants.OPTION_INCLUDE_TAG;

  91.     /**
  92.      * Multi-ACK support for improved negotiation.
  93.      * @since 2.0
  94.      */
  95.     public static final String OPTION_MULTI_ACK = GitProtocolConstants.OPTION_MULTI_ACK;

  96.     /**
  97.      * Multi-ACK detailed support for improved negotiation.
  98.      * @since 2.0
  99.      */
  100.     public static final String OPTION_MULTI_ACK_DETAILED = GitProtocolConstants.OPTION_MULTI_ACK_DETAILED;

  101.     /**
  102.      * The client supports packs with deltas but not their bases.
  103.      * @since 2.0
  104.      */
  105.     public static final String OPTION_THIN_PACK = GitProtocolConstants.OPTION_THIN_PACK;

  106.     /**
  107.      * The client supports using the side-band for progress messages.
  108.      * @since 2.0
  109.      */
  110.     public static final String OPTION_SIDE_BAND = GitProtocolConstants.OPTION_SIDE_BAND;

  111.     /**
  112.      * The client supports using the 64K side-band for progress messages.
  113.      * @since 2.0
  114.      */
  115.     public static final String OPTION_SIDE_BAND_64K = GitProtocolConstants.OPTION_SIDE_BAND_64K;

  116.     /**
  117.      * The client supports packs with OFS deltas.
  118.      * @since 2.0
  119.      */
  120.     public static final String OPTION_OFS_DELTA = GitProtocolConstants.OPTION_OFS_DELTA;

  121.     /**
  122.      * The client supports shallow fetches.
  123.      * @since 2.0
  124.      */
  125.     public static final String OPTION_SHALLOW = GitProtocolConstants.OPTION_SHALLOW;

  126.     /**
  127.      * The client does not want progress messages and will ignore them.
  128.      * @since 2.0
  129.      */
  130.     public static final String OPTION_NO_PROGRESS = GitProtocolConstants.OPTION_NO_PROGRESS;

  131.     /**
  132.      * The client supports receiving a pack before it has sent "done".
  133.      * @since 2.0
  134.      */
  135.     public static final String OPTION_NO_DONE = GitProtocolConstants.OPTION_NO_DONE;

  136.     /**
  137.      * The client supports fetching objects at the tip of any ref, even if not
  138.      * advertised.
  139.      * @since 3.1
  140.      */
  141.     public static final String OPTION_ALLOW_TIP_SHA1_IN_WANT = GitProtocolConstants.OPTION_ALLOW_TIP_SHA1_IN_WANT;

  142.     /**
  143.      * The client supports fetching objects that are reachable from a tip of a
  144.      * ref that is allowed to fetch.
  145.      * @since 4.1
  146.      */
  147.     public static final String OPTION_ALLOW_REACHABLE_SHA1_IN_WANT = GitProtocolConstants.OPTION_ALLOW_REACHABLE_SHA1_IN_WANT;

  148.     /**
  149.      * The client specified a filter expression.
  150.      *
  151.      * @since 5.0
  152.      */
  153.     public static final String OPTION_FILTER = GitProtocolConstants.OPTION_FILTER;

  154.     private final RevWalk walk;

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

  157.     /** Marks an object as having all its dependencies. */
  158.     final RevFlag REACHABLE;

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

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

  163.     /** Marks a commit listed in the advertised refs. */
  164.     final RevFlag ADVERTISED;

  165.     private MultiAck multiAck = MultiAck.OFF;

  166.     private boolean thinPack;

  167.     private boolean sideband;

  168.     private boolean includeTags;

  169.     private boolean allowOfsDelta;

  170.     private boolean noDone;

  171.     private boolean noProgress;

  172.     private String lockMessage;

  173.     private PackLock packLock;

  174.     private int maxHaves;

  175.     /** RPC state, if {@link BasePackConnection#statelessRPC} is true. */
  176.     private TemporaryBuffer.Heap state;

  177.     private PacketLineOut pckState;

  178.     /**
  179.      * Either FilterSpec.NO_FILTER for a filter that doesn't filter
  180.      * anything, or a filter that indicates what and what not to send to the
  181.      * server.
  182.      */
  183.     private final FilterSpec filterSpec;

  184.     /**
  185.      * Create a new connection to fetch using the native git transport.
  186.      *
  187.      * @param packTransport
  188.      *            the transport.
  189.      */
  190.     public BasePackFetchConnection(PackTransport packTransport) {
  191.         super(packTransport);

  192.         if (local != null) {
  193.             final FetchConfig cfg = getFetchConfig();
  194.             allowOfsDelta = cfg.allowOfsDelta;
  195.             maxHaves = cfg.maxHaves;
  196.         } else {
  197.             allowOfsDelta = true;
  198.             maxHaves = Integer.MAX_VALUE;
  199.         }

  200.         includeTags = transport.getTagOpt() != TagOpt.NO_TAGS;
  201.         thinPack = transport.isFetchThin();
  202.         filterSpec = transport.getFilterSpec();

  203.         if (local != null) {
  204.             walk = new RevWalk(local);
  205.             walk.setRetainBody(false);
  206.             reachableCommits = new RevCommitList<>();
  207.             REACHABLE = walk.newFlag("REACHABLE"); //$NON-NLS-1$
  208.             COMMON = walk.newFlag("COMMON"); //$NON-NLS-1$
  209.             STATE = walk.newFlag("STATE"); //$NON-NLS-1$
  210.             ADVERTISED = walk.newFlag("ADVERTISED"); //$NON-NLS-1$

  211.             walk.carry(COMMON);
  212.             walk.carry(REACHABLE);
  213.             walk.carry(ADVERTISED);
  214.         } else {
  215.             walk = null;
  216.             REACHABLE = null;
  217.             COMMON = null;
  218.             STATE = null;
  219.             ADVERTISED = null;
  220.         }
  221.     }

  222.     static class FetchConfig {
  223.         final boolean allowOfsDelta;

  224.         final int maxHaves;

  225.         FetchConfig(Config c) {
  226.             allowOfsDelta = c.getBoolean("repack", "usedeltabaseoffset", true); //$NON-NLS-1$ //$NON-NLS-2$
  227.             maxHaves = c.getInt("fetch", "maxhaves", Integer.MAX_VALUE); //$NON-NLS-1$ //$NON-NLS-2$
  228.         }

  229.         FetchConfig(boolean allowOfsDelta, int maxHaves) {
  230.             this.allowOfsDelta = allowOfsDelta;
  231.             this.maxHaves = maxHaves;
  232.         }
  233.     }

  234.     /** {@inheritDoc} */
  235.     @Override
  236.     public final void fetch(final ProgressMonitor monitor,
  237.             final Collection<Ref> want, final Set<ObjectId> have)
  238.             throws TransportException {
  239.         fetch(monitor, want, have, null);
  240.     }

  241.     /** {@inheritDoc} */
  242.     @Override
  243.     public final void fetch(final ProgressMonitor monitor,
  244.             final Collection<Ref> want, final Set<ObjectId> have,
  245.             OutputStream outputStream) throws TransportException {
  246.         markStartedOperation();
  247.         doFetch(monitor, want, have, outputStream);
  248.     }

  249.     /** {@inheritDoc} */
  250.     @Override
  251.     public boolean didFetchIncludeTags() {
  252.         return false;
  253.     }

  254.     /** {@inheritDoc} */
  255.     @Override
  256.     public boolean didFetchTestConnectivity() {
  257.         return false;
  258.     }

  259.     /** {@inheritDoc} */
  260.     @Override
  261.     public void setPackLockMessage(String message) {
  262.         lockMessage = message;
  263.     }

  264.     /** {@inheritDoc} */
  265.     @Override
  266.     public Collection<PackLock> getPackLocks() {
  267.         if (packLock != null)
  268.             return Collections.singleton(packLock);
  269.         return Collections.<PackLock> emptyList();
  270.     }

  271.     /**
  272.      * Execute common ancestor negotiation and fetch the objects.
  273.      *
  274.      * @param monitor
  275.      *            progress monitor to receive status updates. If the monitor is
  276.      *            the {@link org.eclipse.jgit.lib.NullProgressMonitor#INSTANCE}, then the no-progress
  277.      *            option enabled.
  278.      * @param want
  279.      *            the advertised remote references the caller wants to fetch.
  280.      * @param have
  281.      *            additional objects to assume that already exist locally. This
  282.      *            will be added to the set of objects reachable from the
  283.      *            destination repository's references.
  284.      * @param outputStream
  285.      *            ouputStream to write sideband messages to
  286.      * @throws org.eclipse.jgit.errors.TransportException
  287.      *             if any exception occurs.
  288.      * @since 3.0
  289.      */
  290.     protected void doFetch(final ProgressMonitor monitor,
  291.             final Collection<Ref> want, final Set<ObjectId> have,
  292.             OutputStream outputStream) throws TransportException {
  293.         try {
  294.             noProgress = monitor == NullProgressMonitor.INSTANCE;

  295.             markRefsAdvertised();
  296.             markReachable(have, maxTimeWanted(want));

  297.             if (statelessRPC) {
  298.                 state = new TemporaryBuffer.Heap(Integer.MAX_VALUE);
  299.                 pckState = new PacketLineOut(state);
  300.             }

  301.             if (sendWants(want)) {
  302.                 negotiate(monitor);

  303.                 walk.dispose();
  304.                 reachableCommits = null;
  305.                 state = null;
  306.                 pckState = null;

  307.                 receivePack(monitor, outputStream);
  308.             }
  309.         } catch (CancelledException ce) {
  310.             close();
  311.             return; // Caller should test (or just know) this themselves.
  312.         } catch (IOException | RuntimeException err) {
  313.             close();
  314.             throw new TransportException(err.getMessage(), err);
  315.         }
  316.     }

  317.     /** {@inheritDoc} */
  318.     @Override
  319.     public void close() {
  320.         if (walk != null)
  321.             walk.close();
  322.         super.close();
  323.     }

  324.     FetchConfig getFetchConfig() {
  325.         return local.getConfig().get(FetchConfig::new);
  326.     }

  327.     private int maxTimeWanted(Collection<Ref> wants) {
  328.         int maxTime = 0;
  329.         for (Ref r : wants) {
  330.             try {
  331.                 final RevObject obj = walk.parseAny(r.getObjectId());
  332.                 if (obj instanceof RevCommit) {
  333.                     final int cTime = ((RevCommit) obj).getCommitTime();
  334.                     if (maxTime < cTime)
  335.                         maxTime = cTime;
  336.                 }
  337.             } catch (IOException error) {
  338.                 // We don't have it, but we want to fetch (thus fixing error).
  339.             }
  340.         }
  341.         return maxTime;
  342.     }

  343.     private void markReachable(Set<ObjectId> have, int maxTime)
  344.             throws IOException {
  345.         for (Ref r : local.getRefDatabase().getRefs()) {
  346.             ObjectId id = r.getPeeledObjectId();
  347.             if (id == null)
  348.                 id = r.getObjectId();
  349.             if (id == null)
  350.                 continue;
  351.             parseReachable(id);
  352.         }

  353.         for (ObjectId id : local.getAdditionalHaves())
  354.             parseReachable(id);

  355.         for (ObjectId id : have)
  356.             parseReachable(id);

  357.         if (maxTime > 0) {
  358.             // Mark reachable commits until we reach maxTime. These may
  359.             // wind up later matching up against things we want and we
  360.             // can avoid asking for something we already happen to have.
  361.             //
  362.             final Date maxWhen = new Date(maxTime * 1000L);
  363.             walk.sort(RevSort.COMMIT_TIME_DESC);
  364.             walk.markStart(reachableCommits);
  365.             walk.setRevFilter(CommitTimeRevFilter.after(maxWhen));
  366.             for (;;) {
  367.                 final RevCommit c = walk.next();
  368.                 if (c == null)
  369.                     break;
  370.                 if (c.has(ADVERTISED) && !c.has(COMMON)) {
  371.                     // This is actually going to be a common commit, but
  372.                     // our peer doesn't know that fact yet.
  373.                     //
  374.                     c.add(COMMON);
  375.                     c.carry(COMMON);
  376.                     reachableCommits.add(c);
  377.                 }
  378.             }
  379.         }
  380.     }

  381.     private void parseReachable(ObjectId id) {
  382.         try {
  383.             RevCommit o = walk.parseCommit(id);
  384.             if (!o.has(REACHABLE)) {
  385.                 o.add(REACHABLE);
  386.                 reachableCommits.add(o);
  387.             }
  388.         } catch (IOException readError) {
  389.             // If we cannot read the value of the ref skip it.
  390.         }
  391.     }

  392.     private boolean sendWants(Collection<Ref> want) throws IOException {
  393.         final PacketLineOut p = statelessRPC ? pckState : pckOut;
  394.         boolean first = true;
  395.         for (Ref r : want) {
  396.             ObjectId objectId = r.getObjectId();
  397.             if (objectId == null) {
  398.                 continue;
  399.             }
  400.             try {
  401.                 if (walk.parseAny(objectId).has(REACHABLE)) {
  402.                     // We already have this object. Asking for it is
  403.                     // not a very good idea.
  404.                     //
  405.                     continue;
  406.                 }
  407.             } catch (IOException err) {
  408.                 // Its OK, we don't have it, but we want to fix that
  409.                 // by fetching the object from the other side.
  410.             }

  411.             final StringBuilder line = new StringBuilder(46);
  412.             line.append("want "); //$NON-NLS-1$
  413.             line.append(objectId.name());
  414.             if (first) {
  415.                 line.append(enableCapabilities());
  416.                 first = false;
  417.             }
  418.             line.append('\n');
  419.             p.writeString(line.toString());
  420.         }
  421.         if (first) {
  422.             return false;
  423.         }
  424.         if (!filterSpec.isNoOp()) {
  425.             p.writeString(filterSpec.filterLine());
  426.         }
  427.         p.end();
  428.         outNeedsEnd = false;
  429.         return true;
  430.     }

  431.     private String enableCapabilities() throws TransportException {
  432.         final StringBuilder line = new StringBuilder();
  433.         if (noProgress)
  434.             wantCapability(line, OPTION_NO_PROGRESS);
  435.         if (includeTags)
  436.             includeTags = wantCapability(line, OPTION_INCLUDE_TAG);
  437.         if (allowOfsDelta)
  438.             wantCapability(line, OPTION_OFS_DELTA);

  439.         if (wantCapability(line, OPTION_MULTI_ACK_DETAILED)) {
  440.             multiAck = MultiAck.DETAILED;
  441.             if (statelessRPC)
  442.                 noDone = wantCapability(line, OPTION_NO_DONE);
  443.         } else if (wantCapability(line, OPTION_MULTI_ACK))
  444.             multiAck = MultiAck.CONTINUE;
  445.         else
  446.             multiAck = MultiAck.OFF;

  447.         if (thinPack)
  448.             thinPack = wantCapability(line, OPTION_THIN_PACK);
  449.         if (wantCapability(line, OPTION_SIDE_BAND_64K))
  450.             sideband = true;
  451.         else if (wantCapability(line, OPTION_SIDE_BAND))
  452.             sideband = true;

  453.         if (statelessRPC && multiAck != MultiAck.DETAILED) {
  454.             // Our stateless RPC implementation relies upon the detailed
  455.             // ACK status to tell us common objects for reuse in future
  456.             // requests.  If its not enabled, we can't talk to the peer.
  457.             //
  458.             throw new PackProtocolException(uri, MessageFormat.format(
  459.                     JGitText.get().statelessRPCRequiresOptionToBeEnabled,
  460.                     OPTION_MULTI_ACK_DETAILED));
  461.         }

  462.         if (!filterSpec.isNoOp() && !wantCapability(line, OPTION_FILTER)) {
  463.             throw new PackProtocolException(uri,
  464.                     JGitText.get().filterRequiresCapability);
  465.         }

  466.         addUserAgentCapability(line);
  467.         return line.toString();
  468.     }

  469.     private void negotiate(ProgressMonitor monitor) throws IOException,
  470.             CancelledException {
  471.         final MutableObjectId ackId = new MutableObjectId();
  472.         int resultsPending = 0;
  473.         int havesSent = 0;
  474.         int havesSinceLastContinue = 0;
  475.         boolean receivedContinue = false;
  476.         boolean receivedAck = false;
  477.         boolean receivedReady = false;

  478.         if (statelessRPC) {
  479.             state.writeTo(out, null);
  480.         }

  481.         negotiateBegin();
  482.         SEND_HAVES: for (;;) {
  483.             final RevCommit c = walk.next();
  484.             if (c == null) {
  485.                 break SEND_HAVES;
  486.             }

  487.             ObjectId o = c.getId();
  488.             pckOut.writeString("have " + o.name() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
  489.             havesSent++;
  490.             havesSinceLastContinue++;

  491.             if ((31 & havesSent) != 0) {
  492.                 // We group the have lines into blocks of 32, each marked
  493.                 // with a flush (aka end). This one is within a block so
  494.                 // continue with another have line.
  495.                 //
  496.                 continue;
  497.             }

  498.             if (monitor.isCancelled()) {
  499.                 throw new CancelledException();
  500.             }

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

  503.             if (havesSent == 32 && !statelessRPC) {
  504.                 // On the first block we race ahead and try to send
  505.                 // more of the second block while waiting for the
  506.                 // remote to respond to our first block request.
  507.                 // This keeps us one block ahead of the peer.
  508.                 //
  509.                 continue;
  510.             }

  511.             READ_RESULT: for (;;) {
  512.                 final AckNackResult anr = pckIn.readACK(ackId);
  513.                 switch (anr) {
  514.                 case NAK:
  515.                     // More have lines are necessary to compute the
  516.                     // pack on the remote side. Keep doing that.
  517.                     //
  518.                     resultsPending--;
  519.                     break READ_RESULT;

  520.                 case ACK:
  521.                     // The remote side is happy and knows exactly what
  522.                     // to send us. There is no further negotiation and
  523.                     // we can break out immediately.
  524.                     //
  525.                     multiAck = MultiAck.OFF;
  526.                     resultsPending = 0;
  527.                     receivedAck = true;
  528.                     if (statelessRPC) {
  529.                         state.writeTo(out, null);
  530.                     }
  531.                     break SEND_HAVES;

  532.                 case ACK_CONTINUE:
  533.                 case ACK_COMMON:
  534.                 case ACK_READY:
  535.                     // The server knows this commit (ackId). We don't
  536.                     // need to send any further along its ancestry, but
  537.                     // we need to continue to talk about other parts of
  538.                     // our local history.
  539.                     //
  540.                     markCommon(walk.parseAny(ackId), anr);
  541.                     receivedAck = true;
  542.                     receivedContinue = true;
  543.                     havesSinceLastContinue = 0;
  544.                     if (anr == AckNackResult.ACK_READY) {
  545.                         receivedReady = true;
  546.                     }
  547.                     break;
  548.                 }

  549.                 if (monitor.isCancelled()) {
  550.                     throw new CancelledException();
  551.                 }
  552.             }

  553.             if (noDone && receivedReady) {
  554.                 break SEND_HAVES;
  555.             }
  556.             if (statelessRPC) {
  557.                 state.writeTo(out, null);
  558.             }

  559.             if ((receivedContinue && havesSinceLastContinue > MAX_HAVES)
  560.                     || havesSent >= maxHaves) {
  561.                 // Our history must be really different from the remote's.
  562.                 // We just sent a whole slew of have lines, and it did not
  563.                 // recognize any of them. Avoid sending our entire history
  564.                 // to them by giving up early.
  565.                 //
  566.                 break SEND_HAVES;
  567.             }
  568.         }

  569.         // Tell the remote side we have run out of things to talk about.
  570.         //
  571.         if (monitor.isCancelled()) {
  572.             throw new CancelledException();
  573.         }

  574.         if (!receivedReady || !noDone) {
  575.             // When statelessRPC is true we should always leave SEND_HAVES
  576.             // loop above while in the middle of a request. This allows us
  577.             // to just write done immediately.
  578.             //
  579.             pckOut.writeString("done\n"); //$NON-NLS-1$
  580.             pckOut.flush();
  581.         }

  582.         if (!receivedAck) {
  583.             // Apparently if we have never received an ACK earlier
  584.             // there is one more result expected from the done we
  585.             // just sent to the remote.
  586.             //
  587.             multiAck = MultiAck.OFF;
  588.             resultsPending++;
  589.         }

  590.         READ_RESULT: while (resultsPending > 0 || multiAck != MultiAck.OFF) {
  591.             final AckNackResult anr = pckIn.readACK(ackId);
  592.             resultsPending--;
  593.             switch (anr) {
  594.             case NAK:
  595.                 // A NAK is a response to an end we queued earlier
  596.                 // we eat it and look for another ACK/NAK message.
  597.                 //
  598.                 break;

  599.             case ACK:
  600.                 // A solitary ACK at this point means the remote won't
  601.                 // speak anymore, but is going to send us a pack now.
  602.                 //
  603.                 break READ_RESULT;

  604.             case ACK_CONTINUE:
  605.             case ACK_COMMON:
  606.             case ACK_READY:
  607.                 // We will expect a normal ACK to break out of the loop.
  608.                 //
  609.                 multiAck = MultiAck.CONTINUE;
  610.                 break;
  611.             }

  612.             if (monitor.isCancelled()) {
  613.                 throw new CancelledException();
  614.             }
  615.         }
  616.     }

  617.     private void negotiateBegin() throws IOException {
  618.         walk.resetRetain(REACHABLE, ADVERTISED);
  619.         walk.markStart(reachableCommits);
  620.         walk.sort(RevSort.COMMIT_TIME_DESC);
  621.         walk.setRevFilter(new RevFilter() {
  622.             @Override
  623.             public RevFilter clone() {
  624.                 return this;
  625.             }

  626.             @Override
  627.             public boolean include(RevWalk walker, RevCommit c) {
  628.                 final boolean remoteKnowsIsCommon = c.has(COMMON);
  629.                 if (c.has(ADVERTISED)) {
  630.                     // Remote advertised this, and we have it, hence common.
  631.                     // Whether or not the remote knows that fact is tested
  632.                     // before we added the flag. If the remote doesn't know
  633.                     // we have to still send them this object.
  634.                     //
  635.                     c.add(COMMON);
  636.                 }
  637.                 return !remoteKnowsIsCommon;
  638.             }

  639.             @Override
  640.             public boolean requiresCommitBody() {
  641.                 return false;
  642.             }
  643.         });
  644.     }

  645.     private void markRefsAdvertised() {
  646.         for (Ref r : getRefs()) {
  647.             markAdvertised(r.getObjectId());
  648.             if (r.getPeeledObjectId() != null)
  649.                 markAdvertised(r.getPeeledObjectId());
  650.         }
  651.     }

  652.     private void markAdvertised(AnyObjectId id) {
  653.         try {
  654.             walk.parseAny(id).add(ADVERTISED);
  655.         } catch (IOException readError) {
  656.             // We probably just do not have this object locally.
  657.         }
  658.     }

  659.     private void markCommon(RevObject obj, AckNackResult anr)
  660.             throws IOException {
  661.         if (statelessRPC && anr == AckNackResult.ACK_COMMON && !obj.has(STATE)) {
  662.             StringBuilder s;

  663.             s = new StringBuilder(6 + Constants.OBJECT_ID_STRING_LENGTH);
  664.             s.append("have "); //$NON-NLS-1$
  665.             s.append(obj.name());
  666.             s.append('\n');
  667.             pckState.writeString(s.toString());
  668.             obj.add(STATE);
  669.         }
  670.         obj.add(COMMON);
  671.         if (obj instanceof RevCommit)
  672.             ((RevCommit) obj).carry(COMMON);
  673.     }

  674.     private void receivePack(final ProgressMonitor monitor,
  675.             OutputStream outputStream) throws IOException {
  676.         onReceivePack();
  677.         InputStream input = in;
  678.         if (sideband)
  679.             input = new SideBandInputStream(input, monitor, getMessageWriter(),
  680.                     outputStream);

  681.         try (ObjectInserter ins = local.newObjectInserter()) {
  682.             PackParser parser = ins.newPackParser(input);
  683.             parser.setAllowThin(thinPack);
  684.             parser.setObjectChecker(transport.getObjectChecker());
  685.             parser.setLockMessage(lockMessage);
  686.             packLock = parser.parse(monitor);
  687.             ins.flush();
  688.         }
  689.     }

  690.     /**
  691.      * Notification event delivered just before the pack is received from the
  692.      * network. This event can be used by RPC such as {@link org.eclipse.jgit.transport.TransportHttp} to
  693.      * disable its request magic and ensure the pack stream is read correctly.
  694.      *
  695.      * @since 2.0
  696.      */
  697.     protected void onReceivePack() {
  698.         // By default do nothing for TCP based protocols.
  699.     }

  700.     private static class CancelledException extends Exception {
  701.         private static final long serialVersionUID = 1L;
  702.     }
  703. }