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, 2022 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.time.Instant;
  28. import java.util.ArrayList;
  29. import java.util.Collection;
  30. import java.util.Collections;
  31. import java.util.Enumeration;
  32. import java.util.LinkedHashSet;
  33. import java.util.LinkedList;
  34. import java.util.List;
  35. import java.util.Map;
  36. import java.util.Vector;
  37. import java.util.concurrent.CopyOnWriteArrayList;

  38. import org.eclipse.jgit.annotations.NonNull;
  39. import org.eclipse.jgit.annotations.Nullable;
  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.remoteName = remoteName;
  493.                 return tn;
  494.             }
  495.         }

  496.         throw new NotSupportedException(MessageFormat.format(JGitText.get().URINotSupported, uri));
  497.     }

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

  516.             if (proto.canHandle(uri, null, null))
  517.                 return proto.open(uri);
  518.         }

  519.         throw new NotSupportedException(MessageFormat.format(JGitText.get().URINotSupported, uri));
  520.     }

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

  554.         for (RefSpec spec : procRefs) {
  555.             if (spec.isMatching()) {
  556.                 result.add(new RemoteRefUpdate(db, spec.isForceUpdate(),
  557.                         fetchSpecs));
  558.                 continue;
  559.             }
  560.             String srcSpec = spec.getSource();
  561.             final Ref srcRef = db.findRef(srcSpec);
  562.             if (srcRef != null)
  563.                 srcSpec = srcRef.getName();

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

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

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

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

  618.     private static Collection<RefSpec> expandPushWildcardsFor(
  619.             final Repository db, final Collection<RefSpec> specs)
  620.             throws IOException {
  621.         final Collection<RefSpec> procRefs = new LinkedHashSet<>();

  622.         List<Ref> localRefs = null;
  623.         for (RefSpec spec : specs) {
  624.             if (!spec.isMatching() && spec.isWildcard()) {
  625.                 if (localRefs == null) {
  626.                     localRefs = db.getRefDatabase().getRefs();
  627.                 }
  628.                 for (Ref localRef : localRefs) {
  629.                     if (spec.matchSource(localRef)) {
  630.                         procRefs.add(spec.expandFromSource(localRef));
  631.                     }
  632.                 }
  633.             } else {
  634.                 procRefs.add(spec);
  635.             }
  636.         }
  637.         return procRefs;
  638.     }

  639.     static String findTrackingRefName(final String remoteName,
  640.             final Collection<RefSpec> fetchSpecs) {
  641.         // try to find matching tracking refs
  642.         for (RefSpec fetchSpec : fetchSpecs) {
  643.             if (fetchSpec.matchSource(remoteName)) {
  644.                 if (fetchSpec.isWildcard()) {
  645.                     return fetchSpec.expandFromSource(remoteName)
  646.                             .getDestination();
  647.                 }
  648.                 return fetchSpec.getDestination();
  649.             }
  650.         }
  651.         return null;
  652.     }

  653.     /**
  654.      * Default setting for {@link #fetchThin} option.
  655.      */
  656.     public static final boolean DEFAULT_FETCH_THIN = true;

  657.     /**
  658.      * Default setting for {@link #pushThin} option.
  659.      */
  660.     public static final boolean DEFAULT_PUSH_THIN = false;

  661.     /**
  662.      * Default setting for {@link #pushUseBitmaps} option.
  663.      *
  664.      * @since 6.4
  665.      */
  666.     public static final boolean DEFAULT_PUSH_USE_BITMAPS = true;

  667.     /**
  668.      * Specification for fetch or push operations, to fetch or push all tags.
  669.      * Acts as --tags.
  670.      */
  671.     public static final RefSpec REFSPEC_TAGS = new RefSpec(
  672.             "refs/tags/*:refs/tags/*"); //$NON-NLS-1$

  673.     /**
  674.      * Specification for push operation, to push all refs under refs/heads. Acts
  675.      * as --all.
  676.      */
  677.     public static final RefSpec REFSPEC_PUSH_ALL = new RefSpec(
  678.             "refs/heads/*:refs/heads/*"); //$NON-NLS-1$

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

  681.     /** The URI used to create this transport. */
  682.     protected final URIish uri;

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

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

  687.     /**
  688.      * How {@link #fetch(ProgressMonitor, Collection)} should handle tags.
  689.      * <p>
  690.      * We default to {@link TagOpt#NO_TAGS} so as to avoid fetching annotated
  691.      * tags during one-shot fetches used for later merges. This prevents
  692.      * dragging down tags from repositories that we do not have established
  693.      * tracking branches for. If we do not track the source repository, we most
  694.      * likely do not care about any tags it publishes.
  695.      */
  696.     private TagOpt tagopt = TagOpt.NO_TAGS;

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

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

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

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

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

  707.     /** Should push use bitmaps? */
  708.     private boolean pushUseBitmaps = DEFAULT_PUSH_USE_BITMAPS;

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

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

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

  715.     private FilterSpec filterSpec = FilterSpec.NO_FILTER;

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

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

  720.     /** Assists with authentication the connection. */
  721.     private CredentialsProvider credentialsProvider;

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

  724.     private PrintStream hookOutRedirect;

  725.     private PrintStream hookErrRedirect;

  726.     private String remoteName;

  727.     private Integer depth;

  728.     private Instant deepenSince;

  729.     private List<String> deepenNots = new ArrayList<>();

  730.     @Nullable
  731.     TransferConfig.ProtocolVersion protocol;

  732.     /**
  733.      * Create a new transport instance.
  734.      *
  735.      * @param local
  736.      *            the repository this instance will fetch into, or push out of.
  737.      *            This must be the repository passed to
  738.      *            {@link #open(Repository, URIish)}.
  739.      * @param uri
  740.      *            the URI used to access the remote repository. This must be the
  741.      *            URI passed to {@link #open(Repository, URIish)}.
  742.      */
  743.     protected Transport(Repository local, URIish uri) {
  744.         final TransferConfig tc = local.getConfig().get(TransferConfig.KEY);
  745.         this.local = local;
  746.         this.uri = uri;
  747.         this.protocol = tc.protocolVersion;
  748.         this.objectChecker = tc.newObjectChecker();
  749.         this.credentialsProvider = CredentialsProvider.getDefault();
  750.     }

  751.     /**
  752.      * Create a minimal transport instance not tied to a single repository.
  753.      *
  754.      * @param uri
  755.      *            a {@link org.eclipse.jgit.transport.URIish} object.
  756.      */
  757.     protected Transport(URIish uri) {
  758.         this.uri = uri;
  759.         this.local = null;
  760.         this.objectChecker = new ObjectChecker();
  761.         this.credentialsProvider = CredentialsProvider.getDefault();
  762.     }

  763.     /**
  764.      * Get the URI this transport connects to.
  765.      * <p>
  766.      * Each transport instance connects to at most one URI at any point in time.
  767.      *
  768.      * @return the URI describing the location of the remote repository.
  769.      */
  770.     public URIish getURI() {
  771.         return uri;
  772.     }

  773.     /**
  774.      * Get the name of the remote executable providing upload-pack service.
  775.      *
  776.      * @return typically "git-upload-pack".
  777.      */
  778.     public String getOptionUploadPack() {
  779.         return optionUploadPack;
  780.     }

  781.     /**
  782.      * Set the name of the remote executable providing upload-pack services.
  783.      *
  784.      * @param where
  785.      *            name of the executable.
  786.      */
  787.     public void setOptionUploadPack(String where) {
  788.         if (where != null && where.length() > 0)
  789.             optionUploadPack = where;
  790.         else
  791.             optionUploadPack = RemoteConfig.DEFAULT_UPLOAD_PACK;
  792.     }

  793.     /**
  794.      * Sets a {@link PrintStream} a {@link PrePushHook} may write its stdout to.
  795.      * If not set, {@link System#out} will be used.
  796.      *
  797.      * @param redirect
  798.      *            {@link PrintStream} to use; if {@code null},
  799.      *            {@link System#out} will be used
  800.      * @since 6.4
  801.      */
  802.     public void setHookOutputStream(PrintStream redirect) {
  803.         hookOutRedirect = redirect;
  804.     }

  805.     /**
  806.      * Sets a {@link PrintStream} a {@link PrePushHook} may write its stderr to.
  807.      * If not set, {@link System#err} will be used.
  808.      *
  809.      * @param redirect
  810.      *            {@link PrintStream} to use; if {@code null},
  811.      *            {@link System#err} will be used
  812.      * @since 6.4
  813.      */
  814.     public void setHookErrorStream(PrintStream redirect) {
  815.         hookErrRedirect = redirect;
  816.     }

  817.     /**
  818.      * Get the description of how annotated tags should be treated during fetch.
  819.      *
  820.      * @return option indicating the behavior of annotated tags in fetch.
  821.      */
  822.     public TagOpt getTagOpt() {
  823.         return tagopt;
  824.     }

  825.     /**
  826.      * Set the description of how annotated tags should be treated on fetch.
  827.      *
  828.      * @param option
  829.      *            method to use when handling annotated tags.
  830.      */
  831.     public void setTagOpt(TagOpt option) {
  832.         tagopt = option != null ? option : TagOpt.AUTO_FOLLOW;
  833.     }

  834.     /**
  835.      * Default setting is: {@link #DEFAULT_FETCH_THIN}
  836.      *
  837.      * @return true if fetch should request thin-pack when possible; false
  838.      *         otherwise
  839.      * @see PackTransport
  840.      */
  841.     public boolean isFetchThin() {
  842.         return fetchThin;
  843.     }

  844.     /**
  845.      * Set the thin-pack preference for fetch operation. Default setting is:
  846.      * {@link #DEFAULT_FETCH_THIN}
  847.      *
  848.      * @param fetchThin
  849.      *            true when fetch should request thin-pack when possible; false
  850.      *            when it shouldn't
  851.      * @see PackTransport
  852.      */
  853.     public void setFetchThin(boolean fetchThin) {
  854.         this.fetchThin = fetchThin;
  855.     }

  856.     /**
  857.      * Whether fetch will verify if received objects are formatted correctly.
  858.      *
  859.      * @return true if fetch will verify received objects are formatted
  860.      *         correctly. Validating objects requires more CPU time on the
  861.      *         client side of the connection.
  862.      */
  863.     public boolean isCheckFetchedObjects() {
  864.         return getObjectChecker() != null;
  865.     }

  866.     /**
  867.      * Configure if checking received objects is enabled
  868.      *
  869.      * @param check
  870.      *            true to enable checking received objects; false to assume all
  871.      *            received objects are valid.
  872.      * @see #setObjectChecker(ObjectChecker)
  873.      */
  874.     public void setCheckFetchedObjects(boolean check) {
  875.         if (check && objectChecker == null)
  876.             setObjectChecker(new ObjectChecker());
  877.         else if (!check && objectChecker != null)
  878.             setObjectChecker(null);
  879.     }

  880.     /**
  881.      * Get configured object checker for received objects
  882.      *
  883.      * @return configured object checker for received objects, or null.
  884.      * @since 3.6
  885.      */
  886.     public ObjectChecker getObjectChecker() {
  887.         return objectChecker;
  888.     }

  889.     /**
  890.      * Set the object checker to verify each received object with
  891.      *
  892.      * @param impl
  893.      *            if non-null the object checking instance to verify each
  894.      *            received object with; null to disable object checking.
  895.      * @since 3.6
  896.      */
  897.     public void setObjectChecker(ObjectChecker impl) {
  898.         objectChecker = impl;
  899.     }

  900.     /**
  901.      * Default setting is:
  902.      * {@link org.eclipse.jgit.transport.RemoteConfig#DEFAULT_RECEIVE_PACK}
  903.      *
  904.      * @return remote executable providing receive-pack service for pack
  905.      *         transports.
  906.      * @see PackTransport
  907.      */
  908.     public String getOptionReceivePack() {
  909.         return optionReceivePack;
  910.     }

  911.     /**
  912.      * Set remote executable providing receive-pack service for pack transports.
  913.      * Default setting is:
  914.      * {@link org.eclipse.jgit.transport.RemoteConfig#DEFAULT_RECEIVE_PACK}
  915.      *
  916.      * @param optionReceivePack
  917.      *            remote executable, if null or empty default one is set;
  918.      */
  919.     public void setOptionReceivePack(String optionReceivePack) {
  920.         if (optionReceivePack != null && optionReceivePack.length() > 0)
  921.             this.optionReceivePack = optionReceivePack;
  922.         else
  923.             this.optionReceivePack = RemoteConfig.DEFAULT_RECEIVE_PACK;
  924.     }

  925.     /**
  926.      * Default setting is: {@value #DEFAULT_PUSH_THIN}
  927.      *
  928.      * @return true if push should produce thin-pack in pack transports
  929.      * @see PackTransport
  930.      */
  931.     public boolean isPushThin() {
  932.         return pushThin;
  933.     }

  934.     /**
  935.      * Set thin-pack preference for push operation. Default setting is:
  936.      * {@value #DEFAULT_PUSH_THIN}
  937.      *
  938.      * @param pushThin
  939.      *            true when push should produce thin-pack in pack transports;
  940.      *            false when it shouldn't
  941.      * @see PackTransport
  942.      */
  943.     public void setPushThin(boolean pushThin) {
  944.         this.pushThin = pushThin;
  945.     }

  946.     /**
  947.      * Default setting is false.
  948.      *
  949.      * @return true if push requires all-or-nothing atomic behavior.
  950.      * @since 4.2
  951.      */
  952.     public boolean isPushAtomic() {
  953.         return pushAtomic;
  954.     }

  955.     /**
  956.      * Request atomic push (all references succeed, or none do).
  957.      * <p>
  958.      * Server must also support atomic push. If the server does not support the
  959.      * feature the push will abort without making changes.
  960.      *
  961.      * @param atomic
  962.      *            true when push should be an all-or-nothing operation.
  963.      * @see PackTransport
  964.      * @since 4.2
  965.      */
  966.     public void setPushAtomic(boolean atomic) {
  967.         this.pushAtomic = atomic;
  968.     }

  969.     /**
  970.      * Default setting is: {@value #DEFAULT_PUSH_USE_BITMAPS}
  971.      *
  972.      * @return true if push use bitmaps.
  973.      * @since 6.4
  974.      */
  975.     public boolean isPushUseBitmaps() {
  976.         return pushUseBitmaps;
  977.     }

  978.     /**
  979.      * Set whether to use bitmaps for push. Default setting is:
  980.      * {@value #DEFAULT_PUSH_USE_BITMAPS}
  981.      *
  982.      * @param useBitmaps
  983.      *            false to disable use of bitmaps for push, true otherwise.
  984.      * @since 6.4
  985.      */
  986.     public void setPushUseBitmaps(boolean useBitmaps) {
  987.         this.pushUseBitmaps = useBitmaps;
  988.     }

  989.     /**
  990.      * Whether destination refs should be removed if they no longer exist at the
  991.      * source repository.
  992.      *
  993.      * @return true if destination refs should be removed if they no longer
  994.      *         exist at the source repository.
  995.      */
  996.     public boolean isRemoveDeletedRefs() {
  997.         return removeDeletedRefs;
  998.     }

  999.     /**
  1000.      * Set whether or not to remove refs which no longer exist in the source.
  1001.      * <p>
  1002.      * If true, refs at the destination repository (local for fetch, remote for
  1003.      * push) are deleted if they no longer exist on the source side (remote for
  1004.      * fetch, local for push).
  1005.      * <p>
  1006.      * False by default, as this may cause data to become unreachable, and
  1007.      * eventually be deleted on the next GC.
  1008.      *
  1009.      * @param remove true to remove refs that no longer exist.
  1010.      */
  1011.     public void setRemoveDeletedRefs(boolean remove) {
  1012.         removeDeletedRefs = remove;
  1013.     }

  1014.     /**
  1015.      * @return the blob limit value set with {@link #setFilterBlobLimit} or
  1016.      *         {@link #setFilterSpec(FilterSpec)}, or -1 if no blob limit value
  1017.      *         was set
  1018.      * @since 5.0
  1019.      * @deprecated Use {@link #getFilterSpec()} instead
  1020.      */
  1021.     @Deprecated
  1022.     public final long getFilterBlobLimit() {
  1023.         return filterSpec.getBlobLimit();
  1024.     }

  1025.     /**
  1026.      * @param bytes exclude blobs of size greater than this
  1027.      * @since 5.0
  1028.      * @deprecated Use {@link #setFilterSpec(FilterSpec)} instead
  1029.      */
  1030.     @Deprecated
  1031.     public final void setFilterBlobLimit(long bytes) {
  1032.         setFilterSpec(FilterSpec.withBlobLimit(bytes));
  1033.     }

  1034.     /**
  1035.      * @return the last filter spec set with {@link #setFilterSpec(FilterSpec)},
  1036.      *         or {@link FilterSpec#NO_FILTER} if it was never invoked.
  1037.      * @since 5.4
  1038.      */
  1039.     public final FilterSpec getFilterSpec() {
  1040.         return filterSpec;
  1041.     }

  1042.     /**
  1043.      * @param filter a new filter to use for this transport
  1044.      * @since 5.4
  1045.      */
  1046.     public final void setFilterSpec(@NonNull FilterSpec filter) {
  1047.         filterSpec = requireNonNull(filter);
  1048.     }


  1049.     /**
  1050.      * Retrieves the depth for a shallow clone.
  1051.      *
  1052.      * @return the depth, or {@code null} if none set
  1053.      * @since 6.3
  1054.      */
  1055.     public final Integer getDepth() {
  1056.         return depth;
  1057.     }

  1058.     /**
  1059.      * Limits fetching to the specified number of commits from the tip of each
  1060.      * remote branch history.
  1061.      *
  1062.      * @param depth
  1063.      *            the depth
  1064.      * @since 6.3
  1065.      */
  1066.     public final void setDepth(int depth) {
  1067.         if (depth < 1) {
  1068.             throw new IllegalArgumentException(JGitText.get().depthMustBeAt1);
  1069.         }
  1070.         this.depth = Integer.valueOf(depth);
  1071.     }

  1072.     /**
  1073.      * Limits fetching to the specified number of commits from the tip of each
  1074.      * remote branch history.
  1075.      *
  1076.      * @param depth
  1077.      *            the depth, or {@code null} to unset the depth
  1078.      * @since 6.3
  1079.      */
  1080.     public final void setDepth(Integer depth) {
  1081.         if (depth != null && depth.intValue() < 1) {
  1082.             throw new IllegalArgumentException(JGitText.get().depthMustBeAt1);
  1083.         }
  1084.         this.depth = depth;
  1085.     }

  1086.     /**
  1087.      * @return the deepen-since for a shallow clone
  1088.      * @since 6.3
  1089.      */
  1090.     public final Instant getDeepenSince() {
  1091.         return deepenSince;
  1092.     }

  1093.     /**
  1094.      * Deepen or shorten the history of a shallow repository to include all reachable commits after a specified time.
  1095.      *
  1096.      * @param deepenSince the deepen-since. Must not be {@code null}
  1097.      * @since 6.3
  1098.      */
  1099.     public final void setDeepenSince(@NonNull Instant deepenSince) {
  1100.         this.deepenSince = deepenSince;
  1101.     }

  1102.     /**
  1103.      * @return the deepen-not for a shallow clone
  1104.      * @since 6.3
  1105.      */
  1106.     public final List<String> getDeepenNots() {
  1107.         return deepenNots;
  1108.     }

  1109.     /**
  1110.      * Deepen or shorten the history of a shallow repository to exclude commits reachable from a specified remote branch or tag.
  1111.      *
  1112.      * @param deepenNots the deepen-not. Must not be {@code null}
  1113.      * @since 6.3
  1114.      */
  1115.     public final void setDeepenNots(@NonNull List<String> deepenNots) {
  1116.         this.deepenNots = deepenNots;
  1117.     }

  1118.     /**
  1119.      * Apply provided remote configuration on this transport.
  1120.      *
  1121.      * @param cfg
  1122.      *            configuration to apply on this transport.
  1123.      */
  1124.     public void applyConfig(RemoteConfig cfg) {
  1125.         setOptionUploadPack(cfg.getUploadPack());
  1126.         setOptionReceivePack(cfg.getReceivePack());
  1127.         setTagOpt(cfg.getTagOpt());
  1128.         fetch = cfg.getFetchRefSpecs();
  1129.         push = cfg.getPushRefSpecs();
  1130.         timeout = cfg.getTimeout();
  1131.     }

  1132.     /**
  1133.      * Whether push operation should just check for possible result and not
  1134.      * really update remote refs
  1135.      *
  1136.      * @return true if push operation should just check for possible result and
  1137.      *         not really update remote refs, false otherwise - when push should
  1138.      *         act normally.
  1139.      */
  1140.     public boolean isDryRun() {
  1141.         return dryRun;
  1142.     }

  1143.     /**
  1144.      * Set dry run option for push operation.
  1145.      *
  1146.      * @param dryRun
  1147.      *            true if push operation should just check for possible result
  1148.      *            and not really update remote refs, false otherwise - when push
  1149.      *            should act normally.
  1150.      */
  1151.     public void setDryRun(boolean dryRun) {
  1152.         this.dryRun = dryRun;
  1153.     }

  1154.     /**
  1155.      * Get timeout (in seconds) before aborting an IO operation.
  1156.      *
  1157.      * @return timeout (in seconds) before aborting an IO operation.
  1158.      */
  1159.     public int getTimeout() {
  1160.         return timeout;
  1161.     }

  1162.     /**
  1163.      * Set the timeout before willing to abort an IO call.
  1164.      *
  1165.      * @param seconds
  1166.      *            number of seconds to wait (with no data transfer occurring)
  1167.      *            before aborting an IO read or write operation with this
  1168.      *            remote.
  1169.      */
  1170.     public void setTimeout(int seconds) {
  1171.         timeout = seconds;
  1172.     }

  1173.     /**
  1174.      * Get the configuration used by the pack generator to make packs.
  1175.      *
  1176.      * If {@link #setPackConfig(PackConfig)} was previously given null a new
  1177.      * PackConfig is created on demand by this method using the source
  1178.      * repository's settings.
  1179.      *
  1180.      * @return the pack configuration. Never null.
  1181.      */
  1182.     public PackConfig getPackConfig() {
  1183.         if (packConfig == null)
  1184.             packConfig = new PackConfig(local);
  1185.         return packConfig;
  1186.     }

  1187.     /**
  1188.      * Set the configuration used by the pack generator.
  1189.      *
  1190.      * @param pc
  1191.      *            configuration controlling packing parameters. If null the
  1192.      *            source repository's settings will be used.
  1193.      */
  1194.     public void setPackConfig(PackConfig pc) {
  1195.         packConfig = pc;
  1196.     }

  1197.     /**
  1198.      * A credentials provider to assist with authentication connections..
  1199.      *
  1200.      * @param credentialsProvider
  1201.      *            the credentials provider, or null if there is none
  1202.      */
  1203.     public void setCredentialsProvider(CredentialsProvider credentialsProvider) {
  1204.         this.credentialsProvider = credentialsProvider;
  1205.     }

  1206.     /**
  1207.      * The configured credentials provider.
  1208.      *
  1209.      * @return the credentials provider, or null if no credentials provider is
  1210.      *         associated with this transport.
  1211.      */
  1212.     public CredentialsProvider getCredentialsProvider() {
  1213.         return credentialsProvider;
  1214.     }

  1215.     /**
  1216.      * Get the option strings associated with the push operation
  1217.      *
  1218.      * @return the option strings associated with the push operation
  1219.      * @since 4.5
  1220.      */
  1221.     public List<String> getPushOptions() {
  1222.         return pushOptions;
  1223.     }

  1224.     /**
  1225.      * Sets the option strings associated with the push operation.
  1226.      *
  1227.      * @param pushOptions
  1228.      *            null if push options are unsupported
  1229.      * @since 4.5
  1230.      */
  1231.     public void setPushOptions(List<String> pushOptions) {
  1232.         this.pushOptions = pushOptions;
  1233.     }

  1234.     /**
  1235.      * Fetch objects and refs from the remote repository to the local one.
  1236.      * <p>
  1237.      * This is a utility function providing standard fetch behavior. Local
  1238.      * tracking refs associated with the remote repository are automatically
  1239.      * updated if this transport was created from a
  1240.      * {@link org.eclipse.jgit.transport.RemoteConfig} with fetch RefSpecs
  1241.      * defined.
  1242.      *
  1243.      * @param monitor
  1244.      *            progress monitor to inform the user about our processing
  1245.      *            activity. Must not be null. Use
  1246.      *            {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
  1247.      *            updates are not interesting or necessary.
  1248.      * @param toFetch
  1249.      *            specification of refs to fetch locally. May be null or the
  1250.      *            empty collection to use the specifications from the
  1251.      *            RemoteConfig. May contains regular and negative
  1252.      *            {@link RefSpec}s. Source for each regular RefSpec can't
  1253.      *            be null.
  1254.      * @return information describing the tracking refs updated.
  1255.      * @throws org.eclipse.jgit.errors.NotSupportedException
  1256.      *             this transport implementation does not support fetching
  1257.      *             objects.
  1258.      * @throws org.eclipse.jgit.errors.TransportException
  1259.      *             the remote connection could not be established or object
  1260.      *             copying (if necessary) failed or update specification was
  1261.      *             incorrect.
  1262.      * @since 5.11
  1263.      */
  1264.     public FetchResult fetch(final ProgressMonitor monitor,
  1265.             Collection<RefSpec> toFetch)
  1266.             throws NotSupportedException, TransportException {
  1267.         return fetch(monitor, toFetch, null);
  1268.     }

  1269.     /**
  1270.      * Fetch objects and refs from the remote repository to the local one.
  1271.      * <p>
  1272.      * This is a utility function providing standard fetch behavior. Local
  1273.      * tracking refs associated with the remote repository are automatically
  1274.      * updated if this transport was created from a
  1275.      * {@link org.eclipse.jgit.transport.RemoteConfig} with fetch RefSpecs
  1276.      * defined.
  1277.      *
  1278.      * @param monitor
  1279.      *            progress monitor to inform the user about our processing
  1280.      *            activity. Must not be null. Use
  1281.      *            {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
  1282.      *            updates are not interesting or necessary.
  1283.      * @param toFetch
  1284.      *            specification of refs to fetch locally. May be null or the
  1285.      *            empty collection to use the specifications from the
  1286.      *            RemoteConfig. May contain regular and negative
  1287.      *            {@link RefSpec}s. Source for each regular RefSpec can't
  1288.      *            be null.
  1289.      * @param branch
  1290.      *            the initial branch to check out when cloning the repository.
  1291.      *            Can be specified as ref name (<code>refs/heads/master</code>),
  1292.      *            branch name (<code>master</code>) or tag name
  1293.      *            (<code>v1.2.3</code>). The default is to use the branch
  1294.      *            pointed to by the cloned repository's HEAD and can be
  1295.      *            requested by passing {@code null} or <code>HEAD</code>.
  1296.      * @return information describing the tracking refs updated.
  1297.      * @throws org.eclipse.jgit.errors.NotSupportedException
  1298.      *             this transport implementation does not support fetching
  1299.      *             objects.
  1300.      * @throws org.eclipse.jgit.errors.TransportException
  1301.      *             the remote connection could not be established or object
  1302.      *             copying (if necessary) failed or update specification was
  1303.      *             incorrect.
  1304.      * @since 5.11
  1305.      */
  1306.     public FetchResult fetch(final ProgressMonitor monitor,
  1307.             Collection<RefSpec> toFetch, String branch)
  1308.             throws NotSupportedException,
  1309.             TransportException {
  1310.         if (toFetch == null || toFetch.isEmpty()) {
  1311.             // If the caller did not ask for anything use the defaults.
  1312.             //
  1313.             if (fetch.isEmpty())
  1314.                 throw new TransportException(JGitText.get().nothingToFetch);
  1315.             toFetch = fetch;
  1316.         } else if (!fetch.isEmpty()) {
  1317.             // If the caller asked for something specific without giving
  1318.             // us the local tracking branch see if we can update any of
  1319.             // the local tracking branches without incurring additional
  1320.             // object transfer overheads.
  1321.             //
  1322.             final Collection<RefSpec> tmp = new ArrayList<>(toFetch);
  1323.             for (RefSpec requested : toFetch) {
  1324.                 final String reqSrc = requested.getSource();
  1325.                 for (RefSpec configured : fetch) {
  1326.                     final String cfgSrc = configured.getSource();
  1327.                     final String cfgDst = configured.getDestination();
  1328.                     if (cfgSrc.equals(reqSrc) && cfgDst != null) {
  1329.                         tmp.add(configured);
  1330.                         break;
  1331.                     }
  1332.                 }
  1333.             }
  1334.             toFetch = tmp;
  1335.         }

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

  1338.         local.autoGC(monitor);

  1339.         return result;
  1340.     }

  1341.     /**
  1342.      * Push objects and refs from the local repository to the remote one.
  1343.      * <p>
  1344.      * This is a utility function providing standard push behavior. It updates
  1345.      * remote refs and send there necessary objects according to remote ref
  1346.      * update specification. After successful remote ref update, associated
  1347.      * locally stored tracking branch is updated if set up accordingly. Detailed
  1348.      * operation result is provided after execution.
  1349.      * <p>
  1350.      * For setting up remote ref update specification from ref spec, see helper
  1351.      * method {@link #findRemoteRefUpdatesFor(Collection)}, predefined refspecs
  1352.      * ({@link #REFSPEC_TAGS}, {@link #REFSPEC_PUSH_ALL}) or consider using
  1353.      * directly {@link org.eclipse.jgit.transport.RemoteRefUpdate} for more
  1354.      * possibilities.
  1355.      * <p>
  1356.      * When {@link #isDryRun()} is true, result of this operation is just
  1357.      * estimation of real operation result, no real action is performed.
  1358.      *
  1359.      * @see RemoteRefUpdate
  1360.      * @param monitor
  1361.      *            progress monitor to inform the user about our processing
  1362.      *            activity. Must not be null. Use
  1363.      *            {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
  1364.      *            updates are not interesting or necessary.
  1365.      * @param toPush
  1366.      *            specification of refs to push. May be null or the empty
  1367.      *            collection to use the specifications from the RemoteConfig
  1368.      *            converted by {@link #findRemoteRefUpdatesFor(Collection)}. No
  1369.      *            more than 1 RemoteRefUpdate with the same remoteName is
  1370.      *            allowed. These objects are modified during this call.
  1371.      * @param out
  1372.      *            output stream to write messages to
  1373.      * @return information about results of remote refs updates, tracking refs
  1374.      *         updates and refs advertised by remote repository.
  1375.      * @throws org.eclipse.jgit.errors.NotSupportedException
  1376.      *             this transport implementation does not support pushing
  1377.      *             objects.
  1378.      * @throws org.eclipse.jgit.errors.TransportException
  1379.      *             the remote connection could not be established or object
  1380.      *             copying (if necessary) failed at I/O or protocol level or
  1381.      *             update specification was incorrect.
  1382.      * @since 3.0
  1383.      */
  1384.     public PushResult push(final ProgressMonitor monitor,
  1385.             Collection<RemoteRefUpdate> toPush, OutputStream out)
  1386.             throws NotSupportedException,
  1387.             TransportException {
  1388.         if (toPush == null || toPush.isEmpty()) {
  1389.             // If the caller did not ask for anything use the defaults.
  1390.             try {
  1391.                 toPush = findRemoteRefUpdatesFor(push);
  1392.             } catch (final IOException e) {
  1393.                 throw new TransportException(MessageFormat.format(
  1394.                         JGitText.get().problemWithResolvingPushRefSpecsLocally, e.getMessage()), e);
  1395.             }
  1396.             if (toPush.isEmpty())
  1397.                 throw new TransportException(JGitText.get().nothingToPush);
  1398.         }

  1399.         PrePushHook prePush = null;
  1400.         if (local != null) {
  1401.             // Pushing will always have a local repository. But better safe than
  1402.             // sorry.
  1403.             prePush = Hooks.prePush(local, hookOutRedirect, hookErrRedirect);
  1404.             prePush.setRemoteLocation(uri.toString());
  1405.             prePush.setRemoteName(remoteName);
  1406.         }
  1407.         PushProcess pushProcess = new PushProcess(this, toPush, prePush, out);
  1408.         return pushProcess.execute(monitor);
  1409.     }

  1410.     /**
  1411.      * Push objects and refs from the local repository to the remote one.
  1412.      * <p>
  1413.      * This is a utility function providing standard push behavior. It updates
  1414.      * remote refs and sends necessary objects according to remote ref update
  1415.      * specification. After successful remote ref update, associated locally
  1416.      * stored tracking branch is updated if set up accordingly. Detailed
  1417.      * operation result is provided after execution.
  1418.      * <p>
  1419.      * For setting up remote ref update specification from ref spec, see helper
  1420.      * method {@link #findRemoteRefUpdatesFor(Collection)}, predefined refspecs
  1421.      * ({@link #REFSPEC_TAGS}, {@link #REFSPEC_PUSH_ALL}) or consider using
  1422.      * directly {@link org.eclipse.jgit.transport.RemoteRefUpdate} for more
  1423.      * possibilities.
  1424.      * <p>
  1425.      * When {@link #isDryRun()} is true, result of this operation is just
  1426.      * estimation of real operation result, no real action is performed.
  1427.      *
  1428.      * @see RemoteRefUpdate
  1429.      * @param monitor
  1430.      *            progress monitor to inform the user about our processing
  1431.      *            activity. Must not be null. Use
  1432.      *            {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
  1433.      *            updates are not interesting or necessary.
  1434.      * @param toPush
  1435.      *            specification of refs to push. May be null or the empty
  1436.      *            collection to use the specifications from the RemoteConfig
  1437.      *            converted by {@link #findRemoteRefUpdatesFor(Collection)}. No
  1438.      *            more than 1 RemoteRefUpdate with the same remoteName is
  1439.      *            allowed. These objects are modified during this call.
  1440.      * @return information about results of remote refs updates, tracking refs
  1441.      *         updates and refs advertised by remote repository.
  1442.      * @throws org.eclipse.jgit.errors.NotSupportedException
  1443.      *             this transport implementation does not support pushing
  1444.      *             objects.
  1445.      * @throws org.eclipse.jgit.errors.TransportException
  1446.      *             the remote connection could not be established or object
  1447.      *             copying (if necessary) failed at I/O or protocol level or
  1448.      *             update specification was incorrect.
  1449.      */
  1450.     public PushResult push(final ProgressMonitor monitor,
  1451.             Collection<RemoteRefUpdate> toPush) throws NotSupportedException,
  1452.             TransportException {
  1453.         return push(monitor, toPush, null);
  1454.     }

  1455.     /**
  1456.      * Convert push remote refs update specification from
  1457.      * {@link org.eclipse.jgit.transport.RefSpec} form to
  1458.      * {@link org.eclipse.jgit.transport.RemoteRefUpdate}. Conversion expands
  1459.      * wildcards by matching source part to local refs. expectedOldObjectId in
  1460.      * RemoteRefUpdate is always set as null. Tracking branch is configured if
  1461.      * RefSpec destination matches source of any fetch ref spec for this
  1462.      * transport remote configuration.
  1463.      * <p>
  1464.      * Conversion is performed for context of this transport (database, fetch
  1465.      * specifications).
  1466.      *
  1467.      * @param specs
  1468.      *            collection of RefSpec to convert.
  1469.      * @return collection of set up
  1470.      *         {@link org.eclipse.jgit.transport.RemoteRefUpdate}.
  1471.      * @throws java.io.IOException
  1472.      *             when problem occurred during conversion or specification set
  1473.      *             up: most probably, missing objects or refs.
  1474.      */
  1475.     public Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
  1476.             final Collection<RefSpec> specs) throws IOException {
  1477.         return findRemoteRefUpdatesFor(local, specs, Collections.emptyMap(),
  1478.                            fetch);
  1479.     }

  1480.     /**
  1481.      * Convert push remote refs update specification from
  1482.      * {@link org.eclipse.jgit.transport.RefSpec} form to
  1483.      * {@link org.eclipse.jgit.transport.RemoteRefUpdate}. Conversion expands
  1484.      * wildcards by matching source part to local refs. expectedOldObjectId in
  1485.      * RemoteRefUpdate is set according to leases. Tracking branch is configured
  1486.      * if RefSpec destination matches source of any fetch ref spec for this
  1487.      * transport remote configuration.
  1488.      * <p>
  1489.      * Conversion is performed for context of this transport (database, fetch
  1490.      * specifications).
  1491.      *
  1492.      * @param specs
  1493.      *            collection of RefSpec to convert.
  1494.      * @param leases
  1495.      *            map from ref to lease (containing expected old object id)
  1496.      * @return collection of set up
  1497.      *         {@link org.eclipse.jgit.transport.RemoteRefUpdate}.
  1498.      * @throws java.io.IOException
  1499.      *             when problem occurred during conversion or specification set
  1500.      *             up: most probably, missing objects or refs.
  1501.      * @since 4.7
  1502.      */
  1503.     public Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
  1504.             final Collection<RefSpec> specs,
  1505.             final Map<String, RefLeaseSpec> leases) throws IOException {
  1506.         return findRemoteRefUpdatesFor(local, specs, leases,
  1507.                            fetch);
  1508.     }

  1509.     /**
  1510.      * Begins a new connection for fetching from the remote repository.
  1511.      * <p>
  1512.      * If the transport has no local repository, the fetch connection can only
  1513.      * be used for reading remote refs.
  1514.      *
  1515.      * @return a fresh connection to fetch from the remote repository.
  1516.      * @throws org.eclipse.jgit.errors.NotSupportedException
  1517.      *             the implementation does not support fetching.
  1518.      * @throws org.eclipse.jgit.errors.TransportException
  1519.      *             the remote connection could not be established.
  1520.      */
  1521.     public abstract FetchConnection openFetch() throws NotSupportedException,
  1522.             TransportException;

  1523.     /**
  1524.      * Begins a new connection for fetching from the remote repository.
  1525.      * <p>
  1526.      * If the transport has no local repository, the fetch connection can only
  1527.      * be used for reading remote refs.
  1528.      * </p>
  1529.      * <p>
  1530.      * If the server supports git protocol V2, the {@link RefSpec}s and the
  1531.      * additional patterns, if any, are used to restrict the server's ref
  1532.      * advertisement to matching refs only.
  1533.      * </p>
  1534.      * <p>
  1535.      * Transports that want to support git protocol V2 <em>must</em> override
  1536.      * this; the default implementation ignores its arguments and calls
  1537.      * {@link #openFetch()}.
  1538.      * </p>
  1539.      *
  1540.      * @param refSpecs
  1541.      *            that will be fetched via
  1542.      *            {@link FetchConnection#fetch(ProgressMonitor, Collection, java.util.Set, OutputStream)} later
  1543.      * @param additionalPatterns
  1544.      *            that will be set as ref prefixes if the server supports git
  1545.      *            protocol V2; {@code null} values are ignored
  1546.      *
  1547.      * @return a fresh connection to fetch from the remote repository.
  1548.      * @throws org.eclipse.jgit.errors.NotSupportedException
  1549.      *             the implementation does not support fetching.
  1550.      * @throws org.eclipse.jgit.errors.TransportException
  1551.      *             the remote connection could not be established.
  1552.      * @since 5.11
  1553.      */
  1554.     public FetchConnection openFetch(Collection<RefSpec> refSpecs,
  1555.             String... additionalPatterns)
  1556.             throws NotSupportedException, TransportException {
  1557.         return openFetch();
  1558.     }

  1559.     /**
  1560.      * Begins a new connection for pushing into the remote repository.
  1561.      *
  1562.      * @return a fresh connection to push into the remote repository.
  1563.      * @throws org.eclipse.jgit.errors.NotSupportedException
  1564.      *             the implementation does not support pushing.
  1565.      * @throws org.eclipse.jgit.errors.TransportException
  1566.      *             the remote connection could not be established
  1567.      */
  1568.     public abstract PushConnection openPush() throws NotSupportedException,
  1569.             TransportException;

  1570.     /**
  1571.      * {@inheritDoc}
  1572.      * <p>
  1573.      * Close any resources used by this transport.
  1574.      * <p>
  1575.      * If the remote repository is contacted by a network socket this method
  1576.      * must close that network socket, disconnecting the two peers. If the
  1577.      * remote repository is actually local (same system) this method must close
  1578.      * any open file handles used to read the "remote" repository.
  1579.      * <p>
  1580.      * {@code AutoClosable.close()} declares that it throws {@link Exception}.
  1581.      * Implementers shouldn't throw checked exceptions. This override narrows
  1582.      * the signature to prevent them from doing so.
  1583.      */
  1584.     @Override
  1585.     public abstract void close();
  1586. }