Transport.java

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

  13. package org.eclipse.jgit.transport;

  14. import static java.nio.charset.StandardCharsets.UTF_8;
  15. import static java.util.Objects.requireNonNull;

  16. import java.io.BufferedReader;
  17. import java.io.IOException;
  18. import java.io.InputStreamReader;
  19. import java.io.OutputStream;
  20. import java.io.PrintStream;
  21. import java.lang.ref.WeakReference;
  22. import java.lang.reflect.Field;
  23. import java.lang.reflect.Modifier;
  24. import java.net.URISyntaxException;
  25. import java.net.URL;
  26. import java.text.MessageFormat;
  27. import java.util.ArrayList;
  28. import java.util.Collection;
  29. import java.util.Collections;
  30. import java.util.Enumeration;
  31. import java.util.LinkedHashSet;
  32. import java.util.LinkedList;
  33. import java.util.List;
  34. import java.util.Map;
  35. import java.util.Vector;
  36. import java.util.concurrent.CopyOnWriteArrayList;

  37. import org.eclipse.jgit.annotations.NonNull;
  38. import org.eclipse.jgit.annotations.Nullable;
  39. import org.eclipse.jgit.api.errors.AbortedByHookException;
  40. import org.eclipse.jgit.errors.NotSupportedException;
  41. import org.eclipse.jgit.errors.TransportException;
  42. import org.eclipse.jgit.hooks.Hooks;
  43. import org.eclipse.jgit.hooks.PrePushHook;
  44. import org.eclipse.jgit.internal.JGitText;
  45. import org.eclipse.jgit.lib.Constants;
  46. import org.eclipse.jgit.lib.ObjectChecker;
  47. import org.eclipse.jgit.lib.ObjectId;
  48. import org.eclipse.jgit.lib.ProgressMonitor;
  49. import org.eclipse.jgit.lib.Ref;
  50. import org.eclipse.jgit.lib.Repository;
  51. import org.eclipse.jgit.storage.pack.PackConfig;

  52. /**
  53.  * Connects two Git repositories together and copies objects between them.
  54.  * <p>
  55.  * A transport can be used for either fetching (copying objects into the
  56.  * caller's repository from the remote repository) or pushing (copying objects
  57.  * into the remote repository from the caller's repository). Each transport
  58.  * implementation is responsible for the details associated with establishing
  59.  * the network connection(s) necessary for the copy, as well as actually
  60.  * shuffling data back and forth.
  61.  * <p>
  62.  * Transport instances and the connections they create are not thread-safe.
  63.  * Callers must ensure a transport is accessed by only one thread at a time.
  64.  */
  65. public abstract class Transport implements AutoCloseable {
  66.     /** Type of operation a Transport is being opened for. */
  67.     public enum Operation {
  68.         /** Transport is to fetch objects locally. */
  69.         FETCH,
  70.         /** Transport is to push objects remotely. */
  71.         PUSH;
  72.     }

  73.     private static final List<WeakReference<TransportProtocol>> protocols =
  74.         new CopyOnWriteArrayList<>();

  75.     static {
  76.         // Registration goes backwards in order of priority.
  77.         register(TransportLocal.PROTO_LOCAL);
  78.         register(TransportBundleFile.PROTO_BUNDLE);
  79.         register(TransportAmazonS3.PROTO_S3);
  80.         register(TransportGitAnon.PROTO_GIT);
  81.         register(TransportSftp.PROTO_SFTP);
  82.         register(TransportHttp.PROTO_FTP);
  83.         register(TransportHttp.PROTO_HTTP);
  84.         register(TransportGitSsh.PROTO_SSH);

  85.         registerByService();
  86.     }

  87.     private static void registerByService() {
  88.         ClassLoader ldr = Thread.currentThread().getContextClassLoader();
  89.         if (ldr == null)
  90.             ldr = Transport.class.getClassLoader();
  91.         Enumeration<URL> catalogs = catalogs(ldr);
  92.         while (catalogs.hasMoreElements())
  93.             scan(ldr, catalogs.nextElement());
  94.     }

  95.     private static Enumeration<URL> catalogs(ClassLoader ldr) {
  96.         try {
  97.             String prefix = "META-INF/services/"; //$NON-NLS-1$
  98.             String name = prefix + Transport.class.getName();
  99.             return ldr.getResources(name);
  100.         } catch (IOException err) {
  101.             return new Vector<URL>().elements();
  102.         }
  103.     }

  104.     private static void scan(ClassLoader ldr, URL url) {
  105.         try (BufferedReader br = new BufferedReader(
  106.                 new InputStreamReader(url.openStream(), UTF_8))) {
  107.             String line;
  108.             while ((line = br.readLine()) != null) {
  109.                 line = line.trim();
  110.                 if (line.length() == 0)
  111.                     continue;
  112.                 int comment = line.indexOf('#');
  113.                 if (comment == 0)
  114.                     continue;
  115.                 if (comment != -1)
  116.                     line = line.substring(0, comment).trim();
  117.                 load(ldr, line);
  118.             }
  119.         } catch (IOException e) {
  120.             // Ignore errors
  121.         }
  122.     }

  123.     private static void load(ClassLoader ldr, String cn) {
  124.         Class<?> clazz;
  125.         try {
  126.             clazz = Class.forName(cn, false, ldr);
  127.         } catch (ClassNotFoundException notBuiltin) {
  128.             // Doesn't exist, even though the service entry is present.
  129.             //
  130.             return;
  131.         }

  132.         for (Field f : clazz.getDeclaredFields()) {
  133.             if ((f.getModifiers() & Modifier.STATIC) == Modifier.STATIC
  134.                     && TransportProtocol.class.isAssignableFrom(f.getType())) {
  135.                 TransportProtocol proto;
  136.                 try {
  137.                     proto = (TransportProtocol) f.get(null);
  138.                 } catch (IllegalArgumentException | IllegalAccessException e) {
  139.                     // If we cannot access the field, don't.
  140.                     continue;
  141.                 }
  142.                 if (proto != null)
  143.                     register(proto);
  144.             }
  145.         }
  146.     }

  147.     /**
  148.      * Register a TransportProtocol instance for use during open.
  149.      * <p>
  150.      * Protocol definitions are held by WeakReference, allowing them to be
  151.      * garbage collected when the calling application drops all strongly held
  152.      * references to the TransportProtocol. Therefore applications should use a
  153.      * singleton pattern as described in
  154.      * {@link org.eclipse.jgit.transport.TransportProtocol}'s class
  155.      * documentation to ensure their protocol does not get disabled by garbage
  156.      * collection earlier than expected.
  157.      * <p>
  158.      * The new protocol is registered in front of all earlier protocols, giving
  159.      * it higher priority than the built-in protocol definitions.
  160.      *
  161.      * @param proto
  162.      *            the protocol definition. Must not be null.
  163.      */
  164.     public static void register(TransportProtocol proto) {
  165.         protocols.add(0, new WeakReference<>(proto));
  166.     }

  167.     /**
  168.      * Unregister a TransportProtocol instance.
  169.      * <p>
  170.      * Unregistering a protocol usually isn't necessary, as protocols are held
  171.      * by weak references and will automatically clear when they are garbage
  172.      * collected by the JVM. Matching is handled by reference equality, so the
  173.      * exact reference given to {@link #register(TransportProtocol)} must be
  174.      * used.
  175.      *
  176.      * @param proto
  177.      *            the exact object previously given to register.
  178.      */
  179.     public static void unregister(TransportProtocol proto) {
  180.         for (WeakReference<TransportProtocol> ref : protocols) {
  181.             TransportProtocol refProto = ref.get();
  182.             if (refProto == null || refProto == proto)
  183.                 protocols.remove(ref);
  184.         }
  185.     }

  186.     /**
  187.      * Obtain a copy of the registered protocols.
  188.      *
  189.      * @return an immutable copy of the currently registered protocols.
  190.      */
  191.     public static List<TransportProtocol> getTransportProtocols() {
  192.         int cnt = protocols.size();
  193.         List<TransportProtocol> res = new ArrayList<>(cnt);
  194.         for (WeakReference<TransportProtocol> ref : protocols) {
  195.             TransportProtocol proto = ref.get();
  196.             if (proto != null)
  197.                 res.add(proto);
  198.             else
  199.                 protocols.remove(ref);
  200.         }
  201.         return Collections.unmodifiableList(res);
  202.     }

  203.     /**
  204.      * Open a new transport instance to connect two repositories.
  205.      * <p>
  206.      * This method assumes
  207.      * {@link org.eclipse.jgit.transport.Transport.Operation#FETCH}.
  208.      *
  209.      * @param local
  210.      *            existing local repository.
  211.      * @param remote
  212.      *            location of the remote repository - may be URI or remote
  213.      *            configuration name.
  214.      * @return the new transport instance. Never null. In case of multiple URIs
  215.      *         in remote configuration, only the first is chosen.
  216.      * @throws java.net.URISyntaxException
  217.      *             the location is not a remote defined in the configuration
  218.      *             file and is not a well-formed URL.
  219.      * @throws org.eclipse.jgit.errors.NotSupportedException
  220.      *             the protocol specified is not supported.
  221.      * @throws org.eclipse.jgit.errors.TransportException
  222.      *             the transport cannot open this URI.
  223.      */
  224.     public static Transport open(Repository local, String remote)
  225.             throws NotSupportedException, URISyntaxException,
  226.             TransportException {
  227.         return open(local, remote, Operation.FETCH);
  228.     }

  229.     /**
  230.      * Open a new transport instance to connect two repositories.
  231.      *
  232.      * @param local
  233.      *            existing local repository.
  234.      * @param remote
  235.      *            location of the remote repository - may be URI or remote
  236.      *            configuration name.
  237.      * @param op
  238.      *            planned use of the returned Transport; the URI may differ
  239.      *            based on the type of connection desired.
  240.      * @return the new transport instance. Never null. In case of multiple URIs
  241.      *         in remote configuration, only the first is chosen.
  242.      * @throws java.net.URISyntaxException
  243.      *             the location is not a remote defined in the configuration
  244.      *             file and is not a well-formed URL.
  245.      * @throws org.eclipse.jgit.errors.NotSupportedException
  246.      *             the protocol specified is not supported.
  247.      * @throws org.eclipse.jgit.errors.TransportException
  248.      *             the transport cannot open this URI.
  249.      */
  250.     public static Transport open(final Repository local, final String remote,
  251.             final Operation op) throws NotSupportedException,
  252.             URISyntaxException, TransportException {
  253.         if (local != null) {
  254.             final RemoteConfig cfg = new RemoteConfig(local.getConfig(), remote);
  255.             if (doesNotExist(cfg)) {
  256.                 return open(local, new URIish(remote), null);
  257.             }
  258.             return open(local, cfg, op);
  259.         }
  260.         return open(new URIish(remote));

  261.     }

  262.     /**
  263.      * Open new transport instances to connect two repositories.
  264.      * <p>
  265.      * This method assumes
  266.      * {@link org.eclipse.jgit.transport.Transport.Operation#FETCH}.
  267.      *
  268.      * @param local
  269.      *            existing local repository.
  270.      * @param remote
  271.      *            location of the remote repository - may be URI or remote
  272.      *            configuration name.
  273.      * @return the list of new transport instances for every URI in remote
  274.      *         configuration.
  275.      * @throws java.net.URISyntaxException
  276.      *             the location is not a remote defined in the configuration
  277.      *             file and is not a well-formed URL.
  278.      * @throws org.eclipse.jgit.errors.NotSupportedException
  279.      *             the protocol specified is not supported.
  280.      * @throws org.eclipse.jgit.errors.TransportException
  281.      *             the transport cannot open this URI.
  282.      */
  283.     public static List<Transport> openAll(final Repository local,
  284.             final String remote) throws NotSupportedException,
  285.             URISyntaxException, TransportException {
  286.         return openAll(local, remote, Operation.FETCH);
  287.     }

  288.     /**
  289.      * Open new transport instances to connect two repositories.
  290.      *
  291.      * @param local
  292.      *            existing local repository.
  293.      * @param remote
  294.      *            location of the remote repository - may be URI or remote
  295.      *            configuration name.
  296.      * @param op
  297.      *            planned use of the returned Transport; the URI may differ
  298.      *            based on the type of connection desired.
  299.      * @return the list of new transport instances for every URI in remote
  300.      *         configuration.
  301.      * @throws java.net.URISyntaxException
  302.      *             the location is not a remote defined in the configuration
  303.      *             file and is not a well-formed URL.
  304.      * @throws org.eclipse.jgit.errors.NotSupportedException
  305.      *             the protocol specified is not supported.
  306.      * @throws org.eclipse.jgit.errors.TransportException
  307.      *             the transport cannot open this URI.
  308.      */
  309.     public static List<Transport> openAll(final Repository local,
  310.             final String remote, final Operation op)
  311.             throws NotSupportedException, URISyntaxException,
  312.             TransportException {
  313.         final RemoteConfig cfg = new RemoteConfig(local.getConfig(), remote);
  314.         if (doesNotExist(cfg)) {
  315.             final ArrayList<Transport> transports = new ArrayList<>(1);
  316.             transports.add(open(local, new URIish(remote), null));
  317.             return transports;
  318.         }
  319.         return openAll(local, cfg, op);
  320.     }

  321.     /**
  322.      * Open a new transport instance to connect two repositories.
  323.      * <p>
  324.      * This method assumes
  325.      * {@link org.eclipse.jgit.transport.Transport.Operation#FETCH}.
  326.      *
  327.      * @param local
  328.      *            existing local repository.
  329.      * @param cfg
  330.      *            configuration describing how to connect to the remote
  331.      *            repository.
  332.      * @return the new transport instance. Never null. In case of multiple URIs
  333.      *         in remote configuration, only the first is chosen.
  334.      * @throws org.eclipse.jgit.errors.NotSupportedException
  335.      *             the protocol specified is not supported.
  336.      * @throws org.eclipse.jgit.errors.TransportException
  337.      *             the transport cannot open this URI.
  338.      * @throws java.lang.IllegalArgumentException
  339.      *             if provided remote configuration doesn't have any URI
  340.      *             associated.
  341.      */
  342.     public static Transport open(Repository local, RemoteConfig cfg)
  343.             throws NotSupportedException, TransportException {
  344.         return open(local, cfg, Operation.FETCH);
  345.     }

  346.     /**
  347.      * Open a new transport instance to connect two repositories.
  348.      *
  349.      * @param local
  350.      *            existing local repository.
  351.      * @param cfg
  352.      *            configuration describing how to connect to the remote
  353.      *            repository.
  354.      * @param op
  355.      *            planned use of the returned Transport; the URI may differ
  356.      *            based on the type of connection desired.
  357.      * @return the new transport instance. Never null. In case of multiple URIs
  358.      *         in remote configuration, only the first is chosen.
  359.      * @throws org.eclipse.jgit.errors.NotSupportedException
  360.      *             the protocol specified is not supported.
  361.      * @throws org.eclipse.jgit.errors.TransportException
  362.      *             the transport cannot open this URI.
  363.      * @throws java.lang.IllegalArgumentException
  364.      *             if provided remote configuration doesn't have any URI
  365.      *             associated.
  366.      */
  367.     public static Transport open(final Repository local,
  368.             final RemoteConfig cfg, final Operation op)
  369.             throws NotSupportedException, TransportException {
  370.         final List<URIish> uris = getURIs(cfg, op);
  371.         if (uris.isEmpty())
  372.             throw new IllegalArgumentException(MessageFormat.format(
  373.                     JGitText.get().remoteConfigHasNoURIAssociated, cfg.getName()));
  374.         final Transport tn = open(local, uris.get(0), cfg.getName());
  375.         tn.applyConfig(cfg);
  376.         return tn;
  377.     }

  378.     /**
  379.      * Open new transport instances to connect two repositories.
  380.      * <p>
  381.      * This method assumes
  382.      * {@link org.eclipse.jgit.transport.Transport.Operation#FETCH}.
  383.      *
  384.      * @param local
  385.      *            existing local repository.
  386.      * @param cfg
  387.      *            configuration describing how to connect to the remote
  388.      *            repository.
  389.      * @return the list of new transport instances for every URI in remote
  390.      *         configuration.
  391.      * @throws org.eclipse.jgit.errors.NotSupportedException
  392.      *             the protocol specified is not supported.
  393.      * @throws org.eclipse.jgit.errors.TransportException
  394.      *             the transport cannot open this URI.
  395.      */
  396.     public static List<Transport> openAll(final Repository local,
  397.             final RemoteConfig cfg) throws NotSupportedException,
  398.             TransportException {
  399.         return openAll(local, cfg, Operation.FETCH);
  400.     }

  401.     /**
  402.      * Open new transport instances to connect two repositories.
  403.      *
  404.      * @param local
  405.      *            existing local repository.
  406.      * @param cfg
  407.      *            configuration describing how to connect to the remote
  408.      *            repository.
  409.      * @param op
  410.      *            planned use of the returned Transport; the URI may differ
  411.      *            based on the type of connection desired.
  412.      * @return the list of new transport instances for every URI in remote
  413.      *         configuration.
  414.      * @throws org.eclipse.jgit.errors.NotSupportedException
  415.      *             the protocol specified is not supported.
  416.      * @throws org.eclipse.jgit.errors.TransportException
  417.      *             the transport cannot open this URI.
  418.      */
  419.     public static List<Transport> openAll(final Repository local,
  420.             final RemoteConfig cfg, final Operation op)
  421.             throws NotSupportedException, TransportException {
  422.         final List<URIish> uris = getURIs(cfg, op);
  423.         final List<Transport> transports = new ArrayList<>(uris.size());
  424.         for (URIish uri : uris) {
  425.             final Transport tn = open(local, uri, cfg.getName());
  426.             tn.applyConfig(cfg);
  427.             transports.add(tn);
  428.         }
  429.         return transports;
  430.     }

  431.     private static List<URIish> getURIs(final RemoteConfig cfg,
  432.             final Operation op) {
  433.         switch (op) {
  434.         case FETCH:
  435.             return cfg.getURIs();
  436.         case PUSH: {
  437.             List<URIish> uris = cfg.getPushURIs();
  438.             if (uris.isEmpty())
  439.                 uris = cfg.getURIs();
  440.             return uris;
  441.         }
  442.         default:
  443.             throw new IllegalArgumentException(op.toString());
  444.         }
  445.     }

  446.     private static boolean doesNotExist(RemoteConfig cfg) {
  447.         return cfg.getURIs().isEmpty() && cfg.getPushURIs().isEmpty();
  448.     }

  449.     /**
  450.      * Open a new transport instance to connect two repositories.
  451.      *
  452.      * @param local
  453.      *            existing local repository.
  454.      * @param uri
  455.      *            location of the remote repository.
  456.      * @return the new transport instance. Never null.
  457.      * @throws org.eclipse.jgit.errors.NotSupportedException
  458.      *             the protocol specified is not supported.
  459.      * @throws org.eclipse.jgit.errors.TransportException
  460.      *             the transport cannot open this URI.
  461.      */
  462.     public static Transport open(Repository local, URIish uri)
  463.             throws NotSupportedException, TransportException {
  464.         return open(local, uri, null);
  465.     }

  466.     /**
  467.      * Open a new transport instance to connect two repositories.
  468.      *
  469.      * @param local
  470.      *            existing local repository.
  471.      * @param uri
  472.      *            location of the remote repository.
  473.      * @param remoteName
  474.      *            name of the remote, if the remote as configured in
  475.      *            {@code local}; otherwise null.
  476.      * @return the new transport instance. Never null.
  477.      * @throws org.eclipse.jgit.errors.NotSupportedException
  478.      *             the protocol specified is not supported.
  479.      * @throws org.eclipse.jgit.errors.TransportException
  480.      *             the transport cannot open this URI.
  481.      */
  482.     public static Transport open(Repository local, URIish uri, String remoteName)
  483.             throws NotSupportedException, TransportException {
  484.         for (WeakReference<TransportProtocol> ref : protocols) {
  485.             TransportProtocol proto = ref.get();
  486.             if (proto == null) {
  487.                 protocols.remove(ref);
  488.                 continue;
  489.             }

  490.             if (proto.canHandle(uri, local, remoteName)) {
  491.                 Transport tn = proto.open(uri, local, remoteName);
  492.                 tn.prePush = Hooks.prePush(local, tn.hookOutRedirect);
  493.                 tn.prePush.setRemoteLocation(uri.toString());
  494.                 tn.prePush.setRemoteName(remoteName);
  495.                 return tn;
  496.             }
  497.         }

  498.         throw new NotSupportedException(MessageFormat.format(JGitText.get().URINotSupported, uri));
  499.     }

  500.     /**
  501.      * Open a new transport with no local repository.
  502.      * <p>
  503.      * Note that the resulting transport instance can not be used for fetching
  504.      * or pushing, but only for reading remote refs.
  505.      *
  506.      * @param uri a {@link org.eclipse.jgit.transport.URIish} object.
  507.      * @return new Transport instance
  508.      * @throws org.eclipse.jgit.errors.NotSupportedException
  509.      * @throws org.eclipse.jgit.errors.TransportException
  510.      */
  511.     public static Transport open(URIish uri) throws NotSupportedException, TransportException {
  512.         for (WeakReference<TransportProtocol> ref : protocols) {
  513.             TransportProtocol proto = ref.get();
  514.             if (proto == null) {
  515.                 protocols.remove(ref);
  516.                 continue;
  517.             }

  518.             if (proto.canHandle(uri, null, null))
  519.                 return proto.open(uri);
  520.         }

  521.         throw new NotSupportedException(MessageFormat.format(JGitText.get().URINotSupported, uri));
  522.     }

  523.     /**
  524.      * Convert push remote refs update specification from
  525.      * {@link org.eclipse.jgit.transport.RefSpec} form to
  526.      * {@link org.eclipse.jgit.transport.RemoteRefUpdate}. Conversion expands
  527.      * wildcards by matching source part to local refs. expectedOldObjectId in
  528.      * RemoteRefUpdate is set when specified in leases. Tracking branch is
  529.      * configured if RefSpec destination matches source of any fetch ref spec
  530.      * for this transport remote configuration.
  531.      *
  532.      * @param db
  533.      *            local database.
  534.      * @param specs
  535.      *            collection of RefSpec to convert.
  536.      * @param leases
  537.      *            map from ref to lease (containing expected old object id)
  538.      * @param fetchSpecs
  539.      *            fetch specifications used for finding localtracking refs. May
  540.      *            be null or empty collection.
  541.      * @return collection of set up
  542.      *         {@link org.eclipse.jgit.transport.RemoteRefUpdate}.
  543.      * @throws java.io.IOException
  544.      *             when problem occurred during conversion or specification set
  545.      *             up: most probably, missing objects or refs.
  546.      * @since 4.7
  547.      */
  548.     public static Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
  549.             final Repository db, final Collection<RefSpec> specs,
  550.             final Map<String, RefLeaseSpec> leases,
  551.             Collection<RefSpec> fetchSpecs) throws IOException {
  552.         if (fetchSpecs == null)
  553.             fetchSpecs = Collections.emptyList();
  554.         final List<RemoteRefUpdate> result = new LinkedList<>();
  555.         final Collection<RefSpec> procRefs = expandPushWildcardsFor(db, specs);

  556.         for (RefSpec spec : procRefs) {
  557.             String srcSpec = spec.getSource();
  558.             final Ref srcRef = db.findRef(srcSpec);
  559.             if (srcRef != null)
  560.                 srcSpec = srcRef.getName();

  561.             String destSpec = spec.getDestination();
  562.             if (destSpec == null) {
  563.                 // No destination (no-colon in ref-spec), DWIMery assumes src
  564.                 //
  565.                 destSpec = srcSpec;
  566.             }

  567.             if (srcRef != null && !destSpec.startsWith(Constants.R_REFS)) {
  568.                 // Assume the same kind of ref at the destination, e.g.
  569.                 // "refs/heads/foo:master", DWIMery assumes master is also
  570.                 // under "refs/heads/".
  571.                 //
  572.                 final String n = srcRef.getName();
  573.                 final int kindEnd = n.indexOf('/', Constants.R_REFS.length());
  574.                 destSpec = n.substring(0, kindEnd + 1) + destSpec;
  575.             }

  576.             final boolean forceUpdate = spec.isForceUpdate();
  577.             final String localName = findTrackingRefName(destSpec, fetchSpecs);
  578.             final RefLeaseSpec leaseSpec = leases.get(destSpec);
  579.             final ObjectId expected = leaseSpec == null ? null :
  580.                 db.resolve(leaseSpec.getExpected());
  581.             final RemoteRefUpdate rru = new RemoteRefUpdate(db, srcSpec,
  582.                     destSpec, forceUpdate, localName, expected);
  583.             result.add(rru);
  584.         }
  585.         return result;
  586.     }

  587.     /**
  588.      * Convert push remote refs update specification from
  589.      * {@link org.eclipse.jgit.transport.RefSpec} form to
  590.      * {@link org.eclipse.jgit.transport.RemoteRefUpdate}. Conversion expands
  591.      * wildcards by matching source part to local refs. expectedOldObjectId in
  592.      * RemoteRefUpdate is always set as null. Tracking branch is configured if
  593.      * RefSpec destination matches source of any fetch ref spec for this
  594.      * transport remote configuration.
  595.      *
  596.      * @param db
  597.      *            local database.
  598.      * @param specs
  599.      *            collection of RefSpec to convert.
  600.      * @param fetchSpecs
  601.      *            fetch specifications used for finding localtracking refs. May
  602.      *            be null or empty collection.
  603.      * @return collection of set up
  604.      *         {@link org.eclipse.jgit.transport.RemoteRefUpdate}.
  605.      * @throws java.io.IOException
  606.      *             when problem occurred during conversion or specification set
  607.      *             up: most probably, missing objects or refs.
  608.      */
  609.     public static Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
  610.             final Repository db, final Collection<RefSpec> specs,
  611.             Collection<RefSpec> fetchSpecs) throws IOException {
  612.         return findRemoteRefUpdatesFor(db, specs, Collections.emptyMap(),
  613.                            fetchSpecs);
  614.     }

  615.     private static Collection<RefSpec> expandPushWildcardsFor(
  616.             final Repository db, final Collection<RefSpec> specs)
  617.             throws IOException {
  618.         final List<Ref> localRefs = db.getRefDatabase().getRefs();
  619.         final Collection<RefSpec> procRefs = new LinkedHashSet<>();

  620.         for (RefSpec spec : specs) {
  621.             if (spec.isWildcard()) {
  622.                 for (Ref localRef : localRefs) {
  623.                     if (spec.matchSource(localRef))
  624.                         procRefs.add(spec.expandFromSource(localRef));
  625.                 }
  626.             } else {
  627.                 procRefs.add(spec);
  628.             }
  629.         }
  630.         return procRefs;
  631.     }

  632.     private static String findTrackingRefName(final String remoteName,
  633.             final Collection<RefSpec> fetchSpecs) {
  634.         // try to find matching tracking refs
  635.         for (RefSpec fetchSpec : fetchSpecs) {
  636.             if (fetchSpec.matchSource(remoteName)) {
  637.                 if (fetchSpec.isWildcard()) {
  638.                     return fetchSpec.expandFromSource(remoteName)
  639.                             .getDestination();
  640.                 }
  641.                 return fetchSpec.getDestination();
  642.             }
  643.         }
  644.         return null;
  645.     }

  646.     /**
  647.      * Default setting for {@link #fetchThin} option.
  648.      */
  649.     public static final boolean DEFAULT_FETCH_THIN = true;

  650.     /**
  651.      * Default setting for {@link #pushThin} option.
  652.      */
  653.     public static final boolean DEFAULT_PUSH_THIN = false;

  654.     /**
  655.      * Specification for fetch or push operations, to fetch or push all tags.
  656.      * Acts as --tags.
  657.      */
  658.     public static final RefSpec REFSPEC_TAGS = new RefSpec(
  659.             "refs/tags/*:refs/tags/*"); //$NON-NLS-1$

  660.     /**
  661.      * Specification for push operation, to push all refs under refs/heads. Acts
  662.      * as --all.
  663.      */
  664.     public static final RefSpec REFSPEC_PUSH_ALL = new RefSpec(
  665.             "refs/heads/*:refs/heads/*"); //$NON-NLS-1$

  666.     /** The repository this transport fetches into, or pushes out of. */
  667.     protected final Repository local;

  668.     /** The URI used to create this transport. */
  669.     protected final URIish uri;

  670.     /** Name of the upload pack program, if it must be executed. */
  671.     private String optionUploadPack = RemoteConfig.DEFAULT_UPLOAD_PACK;

  672.     /** Specifications to apply during fetch. */
  673.     private List<RefSpec> fetch = Collections.emptyList();

  674.     /**
  675.      * How {@link #fetch(ProgressMonitor, Collection)} should handle tags.
  676.      * <p>
  677.      * We default to {@link TagOpt#NO_TAGS} so as to avoid fetching annotated
  678.      * tags during one-shot fetches used for later merges. This prevents
  679.      * dragging down tags from repositories that we do not have established
  680.      * tracking branches for. If we do not track the source repository, we most
  681.      * likely do not care about any tags it publishes.
  682.      */
  683.     private TagOpt tagopt = TagOpt.NO_TAGS;

  684.     /** Should fetch request thin-pack if remote repository can produce it. */
  685.     private boolean fetchThin = DEFAULT_FETCH_THIN;

  686.     /** Name of the receive pack program, if it must be executed. */
  687.     private String optionReceivePack = RemoteConfig.DEFAULT_RECEIVE_PACK;

  688.     /** Specifications to apply during push. */
  689.     private List<RefSpec> push = Collections.emptyList();

  690.     /** Should push produce thin-pack when sending objects to remote repository. */
  691.     private boolean pushThin = DEFAULT_PUSH_THIN;

  692.     /** Should push be all-or-nothing atomic behavior? */
  693.     private boolean pushAtomic;

  694.     /** Should push just check for operation result, not really push. */
  695.     private boolean dryRun;

  696.     /** Should an incoming (fetch) transfer validate objects? */
  697.     private ObjectChecker objectChecker;

  698.     /** Should refs no longer on the source be pruned from the destination? */
  699.     private boolean removeDeletedRefs;

  700.     private FilterSpec filterSpec = FilterSpec.NO_FILTER;

  701.     /** Timeout in seconds to wait before aborting an IO read or write. */
  702.     private int timeout;

  703.     /** Pack configuration used by this transport to make pack file. */
  704.     private PackConfig packConfig;

  705.     /** Assists with authentication the connection. */
  706.     private CredentialsProvider credentialsProvider;

  707.     /** The option strings associated with the push operation. */
  708.     private List<String> pushOptions;

  709.     private PrintStream hookOutRedirect;

  710.     private PrePushHook prePush;

  711.     @Nullable
  712.     TransferConfig.ProtocolVersion protocol;

  713.     /**
  714.      * Create a new transport instance.
  715.      *
  716.      * @param local
  717.      *            the repository this instance will fetch into, or push out of.
  718.      *            This must be the repository passed to
  719.      *            {@link #open(Repository, URIish)}.
  720.      * @param uri
  721.      *            the URI used to access the remote repository. This must be the
  722.      *            URI passed to {@link #open(Repository, URIish)}.
  723.      */
  724.     protected Transport(Repository local, URIish uri) {
  725.         final TransferConfig tc = local.getConfig().get(TransferConfig.KEY);
  726.         this.local = local;
  727.         this.uri = uri;
  728.         this.protocol = tc.protocolVersion;
  729.         this.objectChecker = tc.newObjectChecker();
  730.         this.credentialsProvider = CredentialsProvider.getDefault();
  731.         prePush = Hooks.prePush(local, hookOutRedirect);
  732.     }

  733.     /**
  734.      * Create a minimal transport instance not tied to a single repository.
  735.      *
  736.      * @param uri
  737.      *            a {@link org.eclipse.jgit.transport.URIish} object.
  738.      */
  739.     protected Transport(URIish uri) {
  740.         this.uri = uri;
  741.         this.local = null;
  742.         this.objectChecker = new ObjectChecker();
  743.         this.credentialsProvider = CredentialsProvider.getDefault();
  744.     }

  745.     /**
  746.      * Get the URI this transport connects to.
  747.      * <p>
  748.      * Each transport instance connects to at most one URI at any point in time.
  749.      *
  750.      * @return the URI describing the location of the remote repository.
  751.      */
  752.     public URIish getURI() {
  753.         return uri;
  754.     }

  755.     /**
  756.      * Get the name of the remote executable providing upload-pack service.
  757.      *
  758.      * @return typically "git-upload-pack".
  759.      */
  760.     public String getOptionUploadPack() {
  761.         return optionUploadPack;
  762.     }

  763.     /**
  764.      * Set the name of the remote executable providing upload-pack services.
  765.      *
  766.      * @param where
  767.      *            name of the executable.
  768.      */
  769.     public void setOptionUploadPack(String where) {
  770.         if (where != null && where.length() > 0)
  771.             optionUploadPack = where;
  772.         else
  773.             optionUploadPack = RemoteConfig.DEFAULT_UPLOAD_PACK;
  774.     }

  775.     /**
  776.      * Get the description of how annotated tags should be treated during fetch.
  777.      *
  778.      * @return option indicating the behavior of annotated tags in fetch.
  779.      */
  780.     public TagOpt getTagOpt() {
  781.         return tagopt;
  782.     }

  783.     /**
  784.      * Set the description of how annotated tags should be treated on fetch.
  785.      *
  786.      * @param option
  787.      *            method to use when handling annotated tags.
  788.      */
  789.     public void setTagOpt(TagOpt option) {
  790.         tagopt = option != null ? option : TagOpt.AUTO_FOLLOW;
  791.     }

  792.     /**
  793.      * Default setting is: {@link #DEFAULT_FETCH_THIN}
  794.      *
  795.      * @return true if fetch should request thin-pack when possible; false
  796.      *         otherwise
  797.      * @see PackTransport
  798.      */
  799.     public boolean isFetchThin() {
  800.         return fetchThin;
  801.     }

  802.     /**
  803.      * Set the thin-pack preference for fetch operation. Default setting is:
  804.      * {@link #DEFAULT_FETCH_THIN}
  805.      *
  806.      * @param fetchThin
  807.      *            true when fetch should request thin-pack when possible; false
  808.      *            when it shouldn't
  809.      * @see PackTransport
  810.      */
  811.     public void setFetchThin(boolean fetchThin) {
  812.         this.fetchThin = fetchThin;
  813.     }

  814.     /**
  815.      * Whether fetch will verify if received objects are formatted correctly.
  816.      *
  817.      * @return true if fetch will verify received objects are formatted
  818.      *         correctly. Validating objects requires more CPU time on the
  819.      *         client side of the connection.
  820.      */
  821.     public boolean isCheckFetchedObjects() {
  822.         return getObjectChecker() != null;
  823.     }

  824.     /**
  825.      * Configure if checking received objects is enabled
  826.      *
  827.      * @param check
  828.      *            true to enable checking received objects; false to assume all
  829.      *            received objects are valid.
  830.      * @see #setObjectChecker(ObjectChecker)
  831.      */
  832.     public void setCheckFetchedObjects(boolean check) {
  833.         if (check && objectChecker == null)
  834.             setObjectChecker(new ObjectChecker());
  835.         else if (!check && objectChecker != null)
  836.             setObjectChecker(null);
  837.     }

  838.     /**
  839.      * Get configured object checker for received objects
  840.      *
  841.      * @return configured object checker for received objects, or null.
  842.      * @since 3.6
  843.      */
  844.     public ObjectChecker getObjectChecker() {
  845.         return objectChecker;
  846.     }

  847.     /**
  848.      * Set the object checker to verify each received object with
  849.      *
  850.      * @param impl
  851.      *            if non-null the object checking instance to verify each
  852.      *            received object with; null to disable object checking.
  853.      * @since 3.6
  854.      */
  855.     public void setObjectChecker(ObjectChecker impl) {
  856.         objectChecker = impl;
  857.     }

  858.     /**
  859.      * Default setting is:
  860.      * {@link org.eclipse.jgit.transport.RemoteConfig#DEFAULT_RECEIVE_PACK}
  861.      *
  862.      * @return remote executable providing receive-pack service for pack
  863.      *         transports.
  864.      * @see PackTransport
  865.      */
  866.     public String getOptionReceivePack() {
  867.         return optionReceivePack;
  868.     }

  869.     /**
  870.      * Set remote executable providing receive-pack service for pack transports.
  871.      * Default setting is:
  872.      * {@link org.eclipse.jgit.transport.RemoteConfig#DEFAULT_RECEIVE_PACK}
  873.      *
  874.      * @param optionReceivePack
  875.      *            remote executable, if null or empty default one is set;
  876.      */
  877.     public void setOptionReceivePack(String optionReceivePack) {
  878.         if (optionReceivePack != null && optionReceivePack.length() > 0)
  879.             this.optionReceivePack = optionReceivePack;
  880.         else
  881.             this.optionReceivePack = RemoteConfig.DEFAULT_RECEIVE_PACK;
  882.     }

  883.     /**
  884.      * Default setting is: {@value #DEFAULT_PUSH_THIN}
  885.      *
  886.      * @return true if push should produce thin-pack in pack transports
  887.      * @see PackTransport
  888.      */
  889.     public boolean isPushThin() {
  890.         return pushThin;
  891.     }

  892.     /**
  893.      * Set thin-pack preference for push operation. Default setting is:
  894.      * {@value #DEFAULT_PUSH_THIN}
  895.      *
  896.      * @param pushThin
  897.      *            true when push should produce thin-pack in pack transports;
  898.      *            false when it shouldn't
  899.      * @see PackTransport
  900.      */
  901.     public void setPushThin(boolean pushThin) {
  902.         this.pushThin = pushThin;
  903.     }

  904.     /**
  905.      * Default setting is false.
  906.      *
  907.      * @return true if push requires all-or-nothing atomic behavior.
  908.      * @since 4.2
  909.      */
  910.     public boolean isPushAtomic() {
  911.         return pushAtomic;
  912.     }

  913.     /**
  914.      * Request atomic push (all references succeed, or none do).
  915.      * <p>
  916.      * Server must also support atomic push. If the server does not support the
  917.      * feature the push will abort without making changes.
  918.      *
  919.      * @param atomic
  920.      *            true when push should be an all-or-nothing operation.
  921.      * @see PackTransport
  922.      * @since 4.2
  923.      */
  924.     public void setPushAtomic(boolean atomic) {
  925.         this.pushAtomic = atomic;
  926.     }

  927.     /**
  928.      * Whether destination refs should be removed if they no longer exist at the
  929.      * source repository.
  930.      *
  931.      * @return true if destination refs should be removed if they no longer
  932.      *         exist at the source repository.
  933.      */
  934.     public boolean isRemoveDeletedRefs() {
  935.         return removeDeletedRefs;
  936.     }

  937.     /**
  938.      * Set whether or not to remove refs which no longer exist in the source.
  939.      * <p>
  940.      * If true, refs at the destination repository (local for fetch, remote for
  941.      * push) are deleted if they no longer exist on the source side (remote for
  942.      * fetch, local for push).
  943.      * <p>
  944.      * False by default, as this may cause data to become unreachable, and
  945.      * eventually be deleted on the next GC.
  946.      *
  947.      * @param remove true to remove refs that no longer exist.
  948.      */
  949.     public void setRemoveDeletedRefs(boolean remove) {
  950.         removeDeletedRefs = remove;
  951.     }

  952.     /**
  953.      * @return the blob limit value set with {@link #setFilterBlobLimit} or
  954.      *         {@link #setFilterSpec(FilterSpec)}, or -1 if no blob limit value
  955.      *         was set
  956.      * @since 5.0
  957.      * @deprecated Use {@link #getFilterSpec()} instead
  958.      */
  959.     @Deprecated
  960.     public final long getFilterBlobLimit() {
  961.         return filterSpec.getBlobLimit();
  962.     }

  963.     /**
  964.      * @param bytes exclude blobs of size greater than this
  965.      * @since 5.0
  966.      * @deprecated Use {@link #setFilterSpec(FilterSpec)} instead
  967.      */
  968.     @Deprecated
  969.     public final void setFilterBlobLimit(long bytes) {
  970.         setFilterSpec(FilterSpec.withBlobLimit(bytes));
  971.     }

  972.     /**
  973.      * @return the last filter spec set with {@link #setFilterSpec(FilterSpec)},
  974.      *         or {@link FilterSpec#NO_FILTER} if it was never invoked.
  975.      * @since 5.4
  976.      */
  977.     public final FilterSpec getFilterSpec() {
  978.         return filterSpec;
  979.     }

  980.     /**
  981.      * @param filter a new filter to use for this transport
  982.      * @since 5.4
  983.      */
  984.     public final void setFilterSpec(@NonNull FilterSpec filter) {
  985.         filterSpec = requireNonNull(filter);
  986.     }

  987.     /**
  988.      * Apply provided remote configuration on this transport.
  989.      *
  990.      * @param cfg
  991.      *            configuration to apply on this transport.
  992.      */
  993.     public void applyConfig(RemoteConfig cfg) {
  994.         setOptionUploadPack(cfg.getUploadPack());
  995.         setOptionReceivePack(cfg.getReceivePack());
  996.         setTagOpt(cfg.getTagOpt());
  997.         fetch = cfg.getFetchRefSpecs();
  998.         push = cfg.getPushRefSpecs();
  999.         timeout = cfg.getTimeout();
  1000.     }

  1001.     /**
  1002.      * Whether push operation should just check for possible result and not
  1003.      * really update remote refs
  1004.      *
  1005.      * @return true if push operation should just check for possible result and
  1006.      *         not really update remote refs, false otherwise - when push should
  1007.      *         act normally.
  1008.      */
  1009.     public boolean isDryRun() {
  1010.         return dryRun;
  1011.     }

  1012.     /**
  1013.      * Set dry run option for push operation.
  1014.      *
  1015.      * @param dryRun
  1016.      *            true if push operation should just check for possible result
  1017.      *            and not really update remote refs, false otherwise - when push
  1018.      *            should act normally.
  1019.      */
  1020.     public void setDryRun(boolean dryRun) {
  1021.         this.dryRun = dryRun;
  1022.     }

  1023.     /**
  1024.      * Get timeout (in seconds) before aborting an IO operation.
  1025.      *
  1026.      * @return timeout (in seconds) before aborting an IO operation.
  1027.      */
  1028.     public int getTimeout() {
  1029.         return timeout;
  1030.     }

  1031.     /**
  1032.      * Set the timeout before willing to abort an IO call.
  1033.      *
  1034.      * @param seconds
  1035.      *            number of seconds to wait (with no data transfer occurring)
  1036.      *            before aborting an IO read or write operation with this
  1037.      *            remote.
  1038.      */
  1039.     public void setTimeout(int seconds) {
  1040.         timeout = seconds;
  1041.     }

  1042.     /**
  1043.      * Get the configuration used by the pack generator to make packs.
  1044.      *
  1045.      * If {@link #setPackConfig(PackConfig)} was previously given null a new
  1046.      * PackConfig is created on demand by this method using the source
  1047.      * repository's settings.
  1048.      *
  1049.      * @return the pack configuration. Never null.
  1050.      */
  1051.     public PackConfig getPackConfig() {
  1052.         if (packConfig == null)
  1053.             packConfig = new PackConfig(local);
  1054.         return packConfig;
  1055.     }

  1056.     /**
  1057.      * Set the configuration used by the pack generator.
  1058.      *
  1059.      * @param pc
  1060.      *            configuration controlling packing parameters. If null the
  1061.      *            source repository's settings will be used.
  1062.      */
  1063.     public void setPackConfig(PackConfig pc) {
  1064.         packConfig = pc;
  1065.     }

  1066.     /**
  1067.      * A credentials provider to assist with authentication connections..
  1068.      *
  1069.      * @param credentialsProvider
  1070.      *            the credentials provider, or null if there is none
  1071.      */
  1072.     public void setCredentialsProvider(CredentialsProvider credentialsProvider) {
  1073.         this.credentialsProvider = credentialsProvider;
  1074.     }

  1075.     /**
  1076.      * The configured credentials provider.
  1077.      *
  1078.      * @return the credentials provider, or null if no credentials provider is
  1079.      *         associated with this transport.
  1080.      */
  1081.     public CredentialsProvider getCredentialsProvider() {
  1082.         return credentialsProvider;
  1083.     }

  1084.     /**
  1085.      * Get the option strings associated with the push operation
  1086.      *
  1087.      * @return the option strings associated with the push operation
  1088.      * @since 4.5
  1089.      */
  1090.     public List<String> getPushOptions() {
  1091.         return pushOptions;
  1092.     }

  1093.     /**
  1094.      * Sets the option strings associated with the push operation.
  1095.      *
  1096.      * @param pushOptions
  1097.      *            null if push options are unsupported
  1098.      * @since 4.5
  1099.      */
  1100.     public void setPushOptions(List<String> pushOptions) {
  1101.         this.pushOptions = pushOptions;
  1102.     }

  1103.     /**
  1104.      * Fetch objects and refs from the remote repository to the local one.
  1105.      * <p>
  1106.      * This is a utility function providing standard fetch behavior. Local
  1107.      * tracking refs associated with the remote repository are automatically
  1108.      * updated if this transport was created from a
  1109.      * {@link org.eclipse.jgit.transport.RemoteConfig} with fetch RefSpecs
  1110.      * defined.
  1111.      *
  1112.      * @param monitor
  1113.      *            progress monitor to inform the user about our processing
  1114.      *            activity. Must not be null. Use
  1115.      *            {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
  1116.      *            updates are not interesting or necessary.
  1117.      * @param toFetch
  1118.      *            specification of refs to fetch locally. May be null or the
  1119.      *            empty collection to use the specifications from the
  1120.      *            RemoteConfig. Source for each RefSpec can't be null.
  1121.      * @return information describing the tracking refs updated.
  1122.      * @throws org.eclipse.jgit.errors.NotSupportedException
  1123.      *             this transport implementation does not support fetching
  1124.      *             objects.
  1125.      * @throws org.eclipse.jgit.errors.TransportException
  1126.      *             the remote connection could not be established or object
  1127.      *             copying (if necessary) failed or update specification was
  1128.      *             incorrect.
  1129.      * @since 5.11
  1130.      */
  1131.     public FetchResult fetch(final ProgressMonitor monitor,
  1132.             Collection<RefSpec> toFetch)
  1133.             throws NotSupportedException, TransportException {
  1134.         return fetch(monitor, toFetch, null);
  1135.     }

  1136.     /**
  1137.      * Fetch objects and refs from the remote repository to the local one.
  1138.      * <p>
  1139.      * This is a utility function providing standard fetch behavior. Local
  1140.      * tracking refs associated with the remote repository are automatically
  1141.      * updated if this transport was created from a
  1142.      * {@link org.eclipse.jgit.transport.RemoteConfig} with fetch RefSpecs
  1143.      * defined.
  1144.      *
  1145.      * @param monitor
  1146.      *            progress monitor to inform the user about our processing
  1147.      *            activity. Must not be null. Use
  1148.      *            {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
  1149.      *            updates are not interesting or necessary.
  1150.      * @param toFetch
  1151.      *            specification of refs to fetch locally. May be null or the
  1152.      *            empty collection to use the specifications from the
  1153.      *            RemoteConfig. Source for each RefSpec can't be null.
  1154.      * @param branch
  1155.      *            the initial branch to check out when cloning the repository.
  1156.      *            Can be specified as ref name (<code>refs/heads/master</code>),
  1157.      *            branch name (<code>master</code>) or tag name
  1158.      *            (<code>v1.2.3</code>). The default is to use the branch
  1159.      *            pointed to by the cloned repository's HEAD and can be
  1160.      *            requested by passing {@code null} or <code>HEAD</code>.
  1161.      * @return information describing the tracking refs updated.
  1162.      * @throws org.eclipse.jgit.errors.NotSupportedException
  1163.      *             this transport implementation does not support fetching
  1164.      *             objects.
  1165.      * @throws org.eclipse.jgit.errors.TransportException
  1166.      *             the remote connection could not be established or object
  1167.      *             copying (if necessary) failed or update specification was
  1168.      *             incorrect.
  1169.      * @since 5.11
  1170.      */
  1171.     public FetchResult fetch(final ProgressMonitor monitor,
  1172.             Collection<RefSpec> toFetch, String branch)
  1173.             throws NotSupportedException,
  1174.             TransportException {
  1175.         if (toFetch == null || toFetch.isEmpty()) {
  1176.             // If the caller did not ask for anything use the defaults.
  1177.             //
  1178.             if (fetch.isEmpty())
  1179.                 throw new TransportException(JGitText.get().nothingToFetch);
  1180.             toFetch = fetch;
  1181.         } else if (!fetch.isEmpty()) {
  1182.             // If the caller asked for something specific without giving
  1183.             // us the local tracking branch see if we can update any of
  1184.             // the local tracking branches without incurring additional
  1185.             // object transfer overheads.
  1186.             //
  1187.             final Collection<RefSpec> tmp = new ArrayList<>(toFetch);
  1188.             for (RefSpec requested : toFetch) {
  1189.                 final String reqSrc = requested.getSource();
  1190.                 for (RefSpec configured : fetch) {
  1191.                     final String cfgSrc = configured.getSource();
  1192.                     final String cfgDst = configured.getDestination();
  1193.                     if (cfgSrc.equals(reqSrc) && cfgDst != null) {
  1194.                         tmp.add(configured);
  1195.                         break;
  1196.                     }
  1197.                 }
  1198.             }
  1199.             toFetch = tmp;
  1200.         }

  1201.         final FetchResult result = new FetchResult();
  1202.         new FetchProcess(this, toFetch).execute(monitor, result, branch);

  1203.         local.autoGC(monitor);

  1204.         return result;
  1205.     }

  1206.     /**
  1207.      * Push objects and refs from the local repository to the remote one.
  1208.      * <p>
  1209.      * This is a utility function providing standard push behavior. It updates
  1210.      * remote refs and send there necessary objects according to remote ref
  1211.      * update specification. After successful remote ref update, associated
  1212.      * locally stored tracking branch is updated if set up accordingly. Detailed
  1213.      * operation result is provided after execution.
  1214.      * <p>
  1215.      * For setting up remote ref update specification from ref spec, see helper
  1216.      * method {@link #findRemoteRefUpdatesFor(Collection)}, predefined refspecs
  1217.      * ({@link #REFSPEC_TAGS}, {@link #REFSPEC_PUSH_ALL}) or consider using
  1218.      * directly {@link org.eclipse.jgit.transport.RemoteRefUpdate} for more
  1219.      * possibilities.
  1220.      * <p>
  1221.      * When {@link #isDryRun()} is true, result of this operation is just
  1222.      * estimation of real operation result, no real action is performed.
  1223.      *
  1224.      * @see RemoteRefUpdate
  1225.      * @param monitor
  1226.      *            progress monitor to inform the user about our processing
  1227.      *            activity. Must not be null. Use
  1228.      *            {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
  1229.      *            updates are not interesting or necessary.
  1230.      * @param toPush
  1231.      *            specification of refs to push. May be null or the empty
  1232.      *            collection to use the specifications from the RemoteConfig
  1233.      *            converted by {@link #findRemoteRefUpdatesFor(Collection)}. No
  1234.      *            more than 1 RemoteRefUpdate with the same remoteName is
  1235.      *            allowed. These objects are modified during this call.
  1236.      * @param out
  1237.      *            output stream to write messages to
  1238.      * @return information about results of remote refs updates, tracking refs
  1239.      *         updates and refs advertised by remote repository.
  1240.      * @throws org.eclipse.jgit.errors.NotSupportedException
  1241.      *             this transport implementation does not support pushing
  1242.      *             objects.
  1243.      * @throws org.eclipse.jgit.errors.TransportException
  1244.      *             the remote connection could not be established or object
  1245.      *             copying (if necessary) failed at I/O or protocol level or
  1246.      *             update specification was incorrect.
  1247.      * @since 3.0
  1248.      */
  1249.     public PushResult push(final ProgressMonitor monitor,
  1250.             Collection<RemoteRefUpdate> toPush, OutputStream out)
  1251.             throws NotSupportedException,
  1252.             TransportException {
  1253.         if (toPush == null || toPush.isEmpty()) {
  1254.             // If the caller did not ask for anything use the defaults.
  1255.             try {
  1256.                 toPush = findRemoteRefUpdatesFor(push);
  1257.             } catch (final IOException e) {
  1258.                 throw new TransportException(MessageFormat.format(
  1259.                         JGitText.get().problemWithResolvingPushRefSpecsLocally, e.getMessage()), e);
  1260.             }
  1261.             if (toPush.isEmpty())
  1262.                 throw new TransportException(JGitText.get().nothingToPush);
  1263.         }
  1264.         if (prePush != null) {
  1265.             try {
  1266.                 prePush.setRefs(toPush);
  1267.                 prePush.call();
  1268.             } catch (AbortedByHookException | IOException e) {
  1269.                 throw new TransportException(e.getMessage(), e);
  1270.             }
  1271.         }

  1272.         final PushProcess pushProcess = new PushProcess(this, toPush, out);
  1273.         return pushProcess.execute(monitor);
  1274.     }

  1275.     /**
  1276.      * Push objects and refs from the local repository to the remote one.
  1277.      * <p>
  1278.      * This is a utility function providing standard push behavior. It updates
  1279.      * remote refs and sends necessary objects according to remote ref update
  1280.      * specification. After successful remote ref update, associated locally
  1281.      * stored tracking branch is updated if set up accordingly. Detailed
  1282.      * operation result is provided after execution.
  1283.      * <p>
  1284.      * For setting up remote ref update specification from ref spec, see helper
  1285.      * method {@link #findRemoteRefUpdatesFor(Collection)}, predefined refspecs
  1286.      * ({@link #REFSPEC_TAGS}, {@link #REFSPEC_PUSH_ALL}) or consider using
  1287.      * directly {@link org.eclipse.jgit.transport.RemoteRefUpdate} for more
  1288.      * possibilities.
  1289.      * <p>
  1290.      * When {@link #isDryRun()} is true, result of this operation is just
  1291.      * estimation of real operation result, no real action is performed.
  1292.      *
  1293.      * @see RemoteRefUpdate
  1294.      * @param monitor
  1295.      *            progress monitor to inform the user about our processing
  1296.      *            activity. Must not be null. Use
  1297.      *            {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
  1298.      *            updates are not interesting or necessary.
  1299.      * @param toPush
  1300.      *            specification of refs to push. May be null or the empty
  1301.      *            collection to use the specifications from the RemoteConfig
  1302.      *            converted by {@link #findRemoteRefUpdatesFor(Collection)}. No
  1303.      *            more than 1 RemoteRefUpdate with the same remoteName is
  1304.      *            allowed. These objects are modified during this call.
  1305.      * @return information about results of remote refs updates, tracking refs
  1306.      *         updates and refs advertised by remote repository.
  1307.      * @throws org.eclipse.jgit.errors.NotSupportedException
  1308.      *             this transport implementation does not support pushing
  1309.      *             objects.
  1310.      * @throws org.eclipse.jgit.errors.TransportException
  1311.      *             the remote connection could not be established or object
  1312.      *             copying (if necessary) failed at I/O or protocol level or
  1313.      *             update specification was incorrect.
  1314.      */
  1315.     public PushResult push(final ProgressMonitor monitor,
  1316.             Collection<RemoteRefUpdate> toPush) throws NotSupportedException,
  1317.             TransportException {
  1318.         return push(monitor, toPush, null);
  1319.     }

  1320.     /**
  1321.      * Convert push remote refs update specification from
  1322.      * {@link org.eclipse.jgit.transport.RefSpec} form to
  1323.      * {@link org.eclipse.jgit.transport.RemoteRefUpdate}. Conversion expands
  1324.      * wildcards by matching source part to local refs. expectedOldObjectId in
  1325.      * RemoteRefUpdate is always set as null. Tracking branch is configured if
  1326.      * RefSpec destination matches source of any fetch ref spec for this
  1327.      * transport remote configuration.
  1328.      * <p>
  1329.      * Conversion is performed for context of this transport (database, fetch
  1330.      * specifications).
  1331.      *
  1332.      * @param specs
  1333.      *            collection of RefSpec to convert.
  1334.      * @return collection of set up
  1335.      *         {@link org.eclipse.jgit.transport.RemoteRefUpdate}.
  1336.      * @throws java.io.IOException
  1337.      *             when problem occurred during conversion or specification set
  1338.      *             up: most probably, missing objects or refs.
  1339.      */
  1340.     public Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
  1341.             final Collection<RefSpec> specs) throws IOException {
  1342.         return findRemoteRefUpdatesFor(local, specs, Collections.emptyMap(),
  1343.                            fetch);
  1344.     }

  1345.     /**
  1346.      * Convert push remote refs update specification from
  1347.      * {@link org.eclipse.jgit.transport.RefSpec} form to
  1348.      * {@link org.eclipse.jgit.transport.RemoteRefUpdate}. Conversion expands
  1349.      * wildcards by matching source part to local refs. expectedOldObjectId in
  1350.      * RemoteRefUpdate is set according to leases. Tracking branch is configured
  1351.      * if RefSpec destination matches source of any fetch ref spec for this
  1352.      * transport remote configuration.
  1353.      * <p>
  1354.      * Conversion is performed for context of this transport (database, fetch
  1355.      * specifications).
  1356.      *
  1357.      * @param specs
  1358.      *            collection of RefSpec to convert.
  1359.      * @param leases
  1360.      *            map from ref to lease (containing expected old object id)
  1361.      * @return collection of set up
  1362.      *         {@link org.eclipse.jgit.transport.RemoteRefUpdate}.
  1363.      * @throws java.io.IOException
  1364.      *             when problem occurred during conversion or specification set
  1365.      *             up: most probably, missing objects or refs.
  1366.      * @since 4.7
  1367.      */
  1368.     public Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
  1369.             final Collection<RefSpec> specs,
  1370.             final Map<String, RefLeaseSpec> leases) throws IOException {
  1371.         return findRemoteRefUpdatesFor(local, specs, leases,
  1372.                            fetch);
  1373.     }

  1374.     /**
  1375.      * Begins a new connection for fetching from the remote repository.
  1376.      * <p>
  1377.      * If the transport has no local repository, the fetch connection can only
  1378.      * be used for reading remote refs.
  1379.      *
  1380.      * @return a fresh connection to fetch from the remote repository.
  1381.      * @throws org.eclipse.jgit.errors.NotSupportedException
  1382.      *             the implementation does not support fetching.
  1383.      * @throws org.eclipse.jgit.errors.TransportException
  1384.      *             the remote connection could not be established.
  1385.      */
  1386.     public abstract FetchConnection openFetch() throws NotSupportedException,
  1387.             TransportException;

  1388.     /**
  1389.      * Begins a new connection for fetching from the remote repository.
  1390.      * <p>
  1391.      * If the transport has no local repository, the fetch connection can only
  1392.      * be used for reading remote refs.
  1393.      * </p>
  1394.      * <p>
  1395.      * If the server supports git protocol V2, the {@link RefSpec}s and the
  1396.      * additional patterns, if any, are used to restrict the server's ref
  1397.      * advertisement to matching refs only.
  1398.      * </p>
  1399.      * <p>
  1400.      * Transports that want to support git protocol V2 <em>must</em> override
  1401.      * this; the default implementation ignores its arguments and calls
  1402.      * {@link #openFetch()}.
  1403.      * </p>
  1404.      *
  1405.      * @param refSpecs
  1406.      *            that will be fetched via
  1407.      *            {@link FetchConnection#fetch(ProgressMonitor, Collection, java.util.Set, OutputStream)} later
  1408.      * @param additionalPatterns
  1409.      *            that will be set as ref prefixes if the server supports git
  1410.      *            protocol V2; {@code null} values are ignored
  1411.      *
  1412.      * @return a fresh connection to fetch from the remote repository.
  1413.      * @throws org.eclipse.jgit.errors.NotSupportedException
  1414.      *             the implementation does not support fetching.
  1415.      * @throws org.eclipse.jgit.errors.TransportException
  1416.      *             the remote connection could not be established.
  1417.      * @since 5.11
  1418.      */
  1419.     public FetchConnection openFetch(Collection<RefSpec> refSpecs,
  1420.             String... additionalPatterns)
  1421.             throws NotSupportedException, TransportException {
  1422.         return openFetch();
  1423.     }

  1424.     /**
  1425.      * Begins a new connection for pushing into the remote repository.
  1426.      *
  1427.      * @return a fresh connection to push into the remote repository.
  1428.      * @throws org.eclipse.jgit.errors.NotSupportedException
  1429.      *             the implementation does not support pushing.
  1430.      * @throws org.eclipse.jgit.errors.TransportException
  1431.      *             the remote connection could not be established
  1432.      */
  1433.     public abstract PushConnection openPush() throws NotSupportedException,
  1434.             TransportException;

  1435.     /**
  1436.      * {@inheritDoc}
  1437.      * <p>
  1438.      * Close any resources used by this transport.
  1439.      * <p>
  1440.      * If the remote repository is contacted by a network socket this method
  1441.      * must close that network socket, disconnecting the two peers. If the
  1442.      * remote repository is actually local (same system) this method must close
  1443.      * any open file handles used to read the "remote" repository.
  1444.      * <p>
  1445.      * {@code AutoClosable.close()} declares that it throws {@link Exception}.
  1446.      * Implementers shouldn't throw checked exceptions. This override narrows
  1447.      * the signature to prevent them from doing so.
  1448.      */
  1449.     @Override
  1450.     public abstract void close();
  1451. }