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

package org.eclipse.jgit.transport;

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

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.MessageFormat;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;

import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.errors.NotSupportedException;
import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.hooks.Hooks;
import org.eclipse.jgit.hooks.PrePushHook;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectChecker;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.pack.PackConfig;

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

	// Use weak references to enable unloading dynamically loaded protocols
	private static final List<WeakReference<TransportProtocol>> protocols =
		new CopyOnWriteArrayList<>();

	static {
		// Registration goes backwards in order of priority.
		register(TransportLocal.PROTO_LOCAL);
		register(TransportBundleFile.PROTO_BUNDLE);
		register(TransportAmazonS3.PROTO_S3);
		register(TransportGitAnon.PROTO_GIT);
		register(TransportSftp.PROTO_SFTP);
		register(TransportHttp.PROTO_FTP);
		register(TransportHttp.PROTO_HTTP);
		register(TransportGitSsh.PROTO_SSH);

		registerByService();
	}

	private static void registerByService() {
		ClassLoader ldr = Thread.currentThread().getContextClassLoader();
		if (ldr == null)
			ldr = Transport.class.getClassLoader();
		Enumeration<URL> catalogs = catalogs(ldr);
		while (catalogs.hasMoreElements())
			scan(ldr, catalogs.nextElement());
	}

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

	private static void scan(ClassLoader ldr, URL url) {
		try (BufferedReader br = new BufferedReader(
				new InputStreamReader(url.openStream(), UTF_8))) {
			String line;
			while ((line = br.readLine()) != null) {
				line = line.trim();
				if (line.length() == 0)
					continue;
				int comment = line.indexOf('#');
				if (comment == 0)
					continue;
				if (comment != -1)
					line = line.substring(0, comment).trim();
				load(ldr, line);
			}
		} catch (IOException e) {
			// Ignore errors
		}
	}

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

		for (Field f : clazz.getDeclaredFields()) {
			if ((f.getModifiers() & Modifier.STATIC) == Modifier.STATIC
					&& TransportProtocol.class.isAssignableFrom(f.getType())) {
				TransportProtocol proto;
				try {
					proto = (TransportProtocol) f.get(null);
				} catch (IllegalArgumentException | IllegalAccessException e) {
					// If we cannot access the field, don't.
					continue;
				}
				if (proto != null)
					register(proto);
			}
		}
	}

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

	/**
	 * Unregister a TransportProtocol instance.
	 * <p>
	 * Unregistering a protocol usually isn't necessary, as protocols are held
	 * by weak references and will automatically clear when they are garbage
	 * collected by the JVM. Matching is handled by reference equality, so the
	 * exact reference given to {@link #register(TransportProtocol)} must be
	 * used.
	 *
	 * @param proto
	 *            the exact object previously given to register.
	 */
	@SuppressWarnings("ModifyCollectionInEnhancedForLoop")
	public static void unregister(TransportProtocol proto) {
		for (WeakReference<TransportProtocol> ref : protocols) {
			TransportProtocol refProto = ref.get();
			if (refProto == null || refProto == proto) {
				protocols.remove(ref);
			}
		}
	}

	/**
	 * Obtain a copy of the registered protocols.
	 *
	 * @return an immutable copy of the currently registered protocols.
	 */
	@SuppressWarnings("ModifyCollectionInEnhancedForLoop")
	public static List<TransportProtocol> getTransportProtocols() {
		int cnt = protocols.size();
		List<TransportProtocol> res = new ArrayList<>(cnt);
		for (WeakReference<TransportProtocol> ref : protocols) {
			TransportProtocol proto = ref.get();
			if (proto != null) {
				res.add(proto);
			} else {
				protocols.remove(ref);
			}
		}
		return Collections.unmodifiableList(res);
	}

	/**
	 * Open a new transport instance to connect two repositories.
	 * <p>
	 * This method assumes
	 * {@link org.eclipse.jgit.transport.Transport.Operation#FETCH}.
	 *
	 * @param local
	 *            existing local repository.
	 * @param remote
	 *            location of the remote repository - may be URI or remote
	 *            configuration name.
	 * @return the new transport instance. Never null. In case of multiple URIs
	 *         in remote configuration, only the first is chosen.
	 * @throws java.net.URISyntaxException
	 *             the location is not a remote defined in the configuration
	 *             file and is not a well-formed URL.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             the protocol specified is not supported.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the transport cannot open this URI.
	 */
	public static Transport open(Repository local, String remote)
			throws NotSupportedException, URISyntaxException,
			TransportException {
		return open(local, remote, Operation.FETCH);
	}

	/**
	 * Open a new transport instance to connect two repositories.
	 *
	 * @param local
	 *            existing local repository.
	 * @param remote
	 *            location of the remote repository - may be URI or remote
	 *            configuration name.
	 * @param op
	 *            planned use of the returned Transport; the URI may differ
	 *            based on the type of connection desired.
	 * @return the new transport instance. Never null. In case of multiple URIs
	 *         in remote configuration, only the first is chosen.
	 * @throws java.net.URISyntaxException
	 *             the location is not a remote defined in the configuration
	 *             file and is not a well-formed URL.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             the protocol specified is not supported.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the transport cannot open this URI.
	 */
	public static Transport open(final Repository local, final String remote,
			final Operation op) throws NotSupportedException,
			URISyntaxException, TransportException {
		if (local != null) {
			final RemoteConfig cfg = new RemoteConfig(local.getConfig(), remote);
			if (doesNotExist(cfg)) {
				return open(local, new URIish(remote), null);
			}
			return open(local, cfg, op);
		}
		return open(new URIish(remote));

	}

	/**
	 * Open new transport instances to connect two repositories.
	 * <p>
	 * This method assumes
	 * {@link org.eclipse.jgit.transport.Transport.Operation#FETCH}.
	 *
	 * @param local
	 *            existing local repository.
	 * @param remote
	 *            location of the remote repository - may be URI or remote
	 *            configuration name.
	 * @return the list of new transport instances for every URI in remote
	 *         configuration.
	 * @throws java.net.URISyntaxException
	 *             the location is not a remote defined in the configuration
	 *             file and is not a well-formed URL.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             the protocol specified is not supported.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the transport cannot open this URI.
	 */
	public static List<Transport> openAll(final Repository local,
			final String remote) throws NotSupportedException,
			URISyntaxException, TransportException {
		return openAll(local, remote, Operation.FETCH);
	}

	/**
	 * Open new transport instances to connect two repositories.
	 *
	 * @param local
	 *            existing local repository.
	 * @param remote
	 *            location of the remote repository - may be URI or remote
	 *            configuration name.
	 * @param op
	 *            planned use of the returned Transport; the URI may differ
	 *            based on the type of connection desired.
	 * @return the list of new transport instances for every URI in remote
	 *         configuration.
	 * @throws java.net.URISyntaxException
	 *             the location is not a remote defined in the configuration
	 *             file and is not a well-formed URL.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             the protocol specified is not supported.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the transport cannot open this URI.
	 */
	public static List<Transport> openAll(final Repository local,
			final String remote, final Operation op)
			throws NotSupportedException, URISyntaxException,
			TransportException {
		final RemoteConfig cfg = new RemoteConfig(local.getConfig(), remote);
		if (doesNotExist(cfg)) {
			final ArrayList<Transport> transports = new ArrayList<>(1);
			transports.add(open(local, new URIish(remote), null));
			return transports;
		}
		return openAll(local, cfg, op);
	}

	/**
	 * Open a new transport instance to connect two repositories.
	 * <p>
	 * This method assumes
	 * {@link org.eclipse.jgit.transport.Transport.Operation#FETCH}.
	 *
	 * @param local
	 *            existing local repository.
	 * @param cfg
	 *            configuration describing how to connect to the remote
	 *            repository.
	 * @return the new transport instance. Never null. In case of multiple URIs
	 *         in remote configuration, only the first is chosen.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             the protocol specified is not supported.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the transport cannot open this URI.
	 * @throws java.lang.IllegalArgumentException
	 *             if provided remote configuration doesn't have any URI
	 *             associated.
	 */
	public static Transport open(Repository local, RemoteConfig cfg)
			throws NotSupportedException, TransportException {
		return open(local, cfg, Operation.FETCH);
	}

	/**
	 * Open a new transport instance to connect two repositories.
	 *
	 * @param local
	 *            existing local repository.
	 * @param cfg
	 *            configuration describing how to connect to the remote
	 *            repository.
	 * @param op
	 *            planned use of the returned Transport; the URI may differ
	 *            based on the type of connection desired.
	 * @return the new transport instance. Never null. In case of multiple URIs
	 *         in remote configuration, only the first is chosen.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             the protocol specified is not supported.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the transport cannot open this URI.
	 * @throws java.lang.IllegalArgumentException
	 *             if provided remote configuration doesn't have any URI
	 *             associated.
	 */
	public static Transport open(final Repository local,
			final RemoteConfig cfg, final Operation op)
			throws NotSupportedException, TransportException {
		final List<URIish> uris = getURIs(cfg, op);
		if (uris.isEmpty())
			throw new IllegalArgumentException(MessageFormat.format(
					JGitText.get().remoteConfigHasNoURIAssociated, cfg.getName()));
		final Transport tn = open(local, uris.get(0), cfg.getName());
		tn.applyConfig(cfg);
		return tn;
	}

	/**
	 * Open new transport instances to connect two repositories.
	 * <p>
	 * This method assumes
	 * {@link org.eclipse.jgit.transport.Transport.Operation#FETCH}.
	 *
	 * @param local
	 *            existing local repository.
	 * @param cfg
	 *            configuration describing how to connect to the remote
	 *            repository.
	 * @return the list of new transport instances for every URI in remote
	 *         configuration.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             the protocol specified is not supported.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the transport cannot open this URI.
	 */
	public static List<Transport> openAll(final Repository local,
			final RemoteConfig cfg) throws NotSupportedException,
			TransportException {
		return openAll(local, cfg, Operation.FETCH);
	}

	/**
	 * Open new transport instances to connect two repositories.
	 *
	 * @param local
	 *            existing local repository.
	 * @param cfg
	 *            configuration describing how to connect to the remote
	 *            repository.
	 * @param op
	 *            planned use of the returned Transport; the URI may differ
	 *            based on the type of connection desired.
	 * @return the list of new transport instances for every URI in remote
	 *         configuration.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             the protocol specified is not supported.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the transport cannot open this URI.
	 */
	public static List<Transport> openAll(final Repository local,
			final RemoteConfig cfg, final Operation op)
			throws NotSupportedException, TransportException {
		final List<URIish> uris = getURIs(cfg, op);
		final List<Transport> transports = new ArrayList<>(uris.size());
		for (URIish uri : uris) {
			final Transport tn = open(local, uri, cfg.getName());
			tn.applyConfig(cfg);
			transports.add(tn);
		}
		return transports;
	}

	private static List<URIish> getURIs(final RemoteConfig cfg,
			final Operation op) {
		switch (op) {
		case FETCH:
			return cfg.getURIs();
		case PUSH: {
			List<URIish> uris = cfg.getPushURIs();
			if (uris.isEmpty())
				uris = cfg.getURIs();
			return uris;
		}
		default:
			throw new IllegalArgumentException(op.toString());
		}
	}

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

	/**
	 * Open a new transport instance to connect two repositories.
	 *
	 * @param local
	 *            existing local repository.
	 * @param uri
	 *            location of the remote repository.
	 * @return the new transport instance. Never null.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             the protocol specified is not supported.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the transport cannot open this URI.
	 */
	public static Transport open(Repository local, URIish uri)
			throws NotSupportedException, TransportException {
		return open(local, uri, null);
	}

	/**
	 * Open a new transport instance to connect two repositories.
	 *
	 * @param local
	 *            existing local repository.
	 * @param uri
	 *            location of the remote repository.
	 * @param remoteName
	 *            name of the remote, if the remote as configured in
	 *            {@code local}; otherwise null.
	 * @return the new transport instance. Never null.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             the protocol specified is not supported.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the transport cannot open this URI.
	 */
	@SuppressWarnings("ModifyCollectionInEnhancedForLoop")
	public static Transport open(Repository local, URIish uri, String remoteName)
			throws NotSupportedException, TransportException {
		for (WeakReference<TransportProtocol> ref : protocols) {
			TransportProtocol proto = ref.get();
			if (proto == null) {
				protocols.remove(ref);
				continue;
			}

			if (proto.canHandle(uri, local, remoteName)) {
				Transport tn = proto.open(uri, local, remoteName);
				tn.remoteName = remoteName;
				return tn;
			}
		}

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

	/**
	 * Open a new transport with no local repository.
	 * <p>
	 * Note that the resulting transport instance can not be used for fetching
	 * or pushing, but only for reading remote refs.
	 *
	 * @param uri
	 *            a {@link org.eclipse.jgit.transport.URIish} object.
	 * @return new Transport instance
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             case that is not supported by JGit
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             if transport failed
	 */
	@SuppressWarnings("ModifyCollectionInEnhancedForLoop")
	public static Transport open(URIish uri) throws NotSupportedException, TransportException {
		for (WeakReference<TransportProtocol> ref : protocols) {
			TransportProtocol proto = ref.get();
			if (proto == null) {
				protocols.remove(ref);
				continue;
			}

			if (proto.canHandle(uri, null, null)) {
				return proto.open(uri);
			}
		}

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

	/**
	 * Convert push remote refs update specification from
	 * {@link org.eclipse.jgit.transport.RefSpec} form to
	 * {@link org.eclipse.jgit.transport.RemoteRefUpdate}. Conversion expands
	 * wildcards by matching source part to local refs. expectedOldObjectId in
	 * RemoteRefUpdate is set when specified in leases. Tracking branch is
	 * configured if RefSpec destination matches source of any fetch ref spec
	 * for this transport remote configuration.
	 *
	 * @param db
	 *            local database.
	 * @param specs
	 *            collection of RefSpec to convert.
	 * @param leases
	 *            map from ref to lease (containing expected old object id)
	 * @param fetchSpecs
	 *            fetch specifications used for finding localtracking refs. May
	 *            be null or empty collection.
	 * @return collection of set up
	 *         {@link org.eclipse.jgit.transport.RemoteRefUpdate}.
	 * @throws java.io.IOException
	 *             when problem occurred during conversion or specification set
	 *             up: most probably, missing objects or refs.
	 * @since 4.7
	 */
	public static Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
			final Repository db, final Collection<RefSpec> specs,
			final Map<String, RefLeaseSpec> leases,
			Collection<RefSpec> fetchSpecs) throws IOException {
		if (fetchSpecs == null)
			fetchSpecs = Collections.emptyList();
		final List<RemoteRefUpdate> result = new LinkedList<>();
		final Collection<RefSpec> procRefs = expandPushWildcardsFor(db, specs);

		for (RefSpec spec : procRefs) {
			if (spec.isMatching()) {
				result.add(new RemoteRefUpdate(db, spec.isForceUpdate(),
						fetchSpecs));
				continue;
			}
			String srcSpec = spec.getSource();
			final Ref srcRef = db.findRef(srcSpec);
			if (srcRef != null)
				srcSpec = srcRef.getName();

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

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

			final boolean forceUpdate = spec.isForceUpdate();
			final String localName = findTrackingRefName(destSpec, fetchSpecs);
			final RefLeaseSpec leaseSpec = leases.get(destSpec);
			final ObjectId expected = leaseSpec == null ? null :
				db.resolve(leaseSpec.getExpected());
			final RemoteRefUpdate rru = new RemoteRefUpdate(db, srcSpec,
					destSpec, forceUpdate, localName, expected);
			result.add(rru);
		}
		return result;
	}

	/**
	 * Convert push remote refs update specification from
	 * {@link org.eclipse.jgit.transport.RefSpec} form to
	 * {@link org.eclipse.jgit.transport.RemoteRefUpdate}. Conversion expands
	 * wildcards by matching source part to local refs. expectedOldObjectId in
	 * RemoteRefUpdate is always set as null. Tracking branch is configured if
	 * RefSpec destination matches source of any fetch ref spec for this
	 * transport remote configuration.
	 *
	 * @param db
	 *            local database.
	 * @param specs
	 *            collection of RefSpec to convert.
	 * @param fetchSpecs
	 *            fetch specifications used for finding localtracking refs. May
	 *            be null or empty collection.
	 * @return collection of set up
	 *         {@link org.eclipse.jgit.transport.RemoteRefUpdate}.
	 * @throws java.io.IOException
	 *             when problem occurred during conversion or specification set
	 *             up: most probably, missing objects or refs.
	 */
	public static Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
			final Repository db, final Collection<RefSpec> specs,
			Collection<RefSpec> fetchSpecs) throws IOException {
		return findRemoteRefUpdatesFor(db, specs, Collections.emptyMap(),
					       fetchSpecs);
	}

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

		List<Ref> localRefs = null;
		for (RefSpec spec : specs) {
			if (!spec.isMatching() && spec.isWildcard()) {
				if (localRefs == null) {
					localRefs = db.getRefDatabase().getRefs();
				}
				for (Ref localRef : localRefs) {
					if (spec.matchSource(localRef)) {
						procRefs.add(spec.expandFromSource(localRef));
					}
				}
			} else {
				procRefs.add(spec);
			}
		}
		return procRefs;
	}

	static String findTrackingRefName(final String remoteName,
			final Collection<RefSpec> fetchSpecs) {
		// try to find matching tracking refs
		for (RefSpec fetchSpec : fetchSpecs) {
			if (fetchSpec.matchSource(remoteName)) {
				if (fetchSpec.isWildcard()) {
					return fetchSpec.expandFromSource(remoteName)
							.getDestination();
				}
				return fetchSpec.getDestination();
			}
		}
		return null;
	}

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

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

	/**
	 * Default setting for {@link #pushUseBitmaps} option.
	 *
	 * @since 6.4
	 */
	public static final boolean DEFAULT_PUSH_USE_BITMAPS = true;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	private FilterSpec filterSpec = FilterSpec.NO_FILTER;

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

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

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

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

	private PrintStream hookOutRedirect;

	private PrintStream hookErrRedirect;

	private String remoteName;

	private Integer depth;

	private Instant deepenSince;

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

	@Nullable
	TransferConfig.ProtocolVersion protocol;

	/**
	 * Create a new transport instance.
	 *
	 * @param local
	 *            the repository this instance will fetch into, or push out of.
	 *            This must be the repository passed to
	 *            {@link #open(Repository, URIish)}.
	 * @param uri
	 *            the URI used to access the remote repository. This must be the
	 *            URI passed to {@link #open(Repository, URIish)}.
	 */
	protected Transport(Repository local, URIish uri) {
		final TransferConfig tc = local.getConfig().get(TransferConfig.KEY);
		this.local = local;
		this.uri = uri;
		this.protocol = tc.protocolVersion;
		this.objectChecker = tc.newObjectChecker();
		this.credentialsProvider = CredentialsProvider.getDefault();
	}

	/**
	 * Create a minimal transport instance not tied to a single repository.
	 *
	 * @param uri
	 *            a {@link org.eclipse.jgit.transport.URIish} object.
	 */
	protected Transport(URIish uri) {
		this.uri = uri;
		this.local = null;
		this.objectChecker = new ObjectChecker();
		this.credentialsProvider = CredentialsProvider.getDefault();
	}

	/**
	 * Get the URI this transport connects to.
	 * <p>
	 * Each transport instance connects to at most one URI at any point in time.
	 *
	 * @return the URI describing the location of the remote repository.
	 */
	public URIish getURI() {
		return uri;
	}

	/**
	 * Get the name of the remote executable providing upload-pack service.
	 *
	 * @return typically "git-upload-pack".
	 */
	public String getOptionUploadPack() {
		return optionUploadPack;
	}

	/**
	 * Set the name of the remote executable providing upload-pack services.
	 *
	 * @param where
	 *            name of the executable.
	 */
	public void setOptionUploadPack(String where) {
		if (where != null && where.length() > 0)
			optionUploadPack = where;
		else
			optionUploadPack = RemoteConfig.DEFAULT_UPLOAD_PACK;
	}

	/**
	 * Sets a {@link PrintStream} a {@link PrePushHook} may write its stdout to.
	 * If not set, {@link System#out} will be used.
	 *
	 * @param redirect
	 *            {@link PrintStream} to use; if {@code null},
	 *            {@link System#out} will be used
	 * @since 6.4
	 */
	public void setHookOutputStream(PrintStream redirect) {
		hookOutRedirect = redirect;
	}

	/**
	 * Sets a {@link PrintStream} a {@link PrePushHook} may write its stderr to.
	 * If not set, {@link System#err} will be used.
	 *
	 * @param redirect
	 *            {@link PrintStream} to use; if {@code null},
	 *            {@link System#err} will be used
	 * @since 6.4
	 */
	public void setHookErrorStream(PrintStream redirect) {
		hookErrRedirect = redirect;
	}

	/**
	 * Get the description of how annotated tags should be treated during fetch.
	 *
	 * @return option indicating the behavior of annotated tags in fetch.
	 */
	public TagOpt getTagOpt() {
		return tagopt;
	}

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

	/**
	 * Default setting is: {@link #DEFAULT_FETCH_THIN}
	 *
	 * @return true if fetch should request thin-pack when possible; false
	 *         otherwise
	 * @see PackTransport
	 */
	public boolean isFetchThin() {
		return fetchThin;
	}

	/**
	 * Set the thin-pack preference for fetch operation. Default setting is:
	 * {@link #DEFAULT_FETCH_THIN}
	 *
	 * @param fetchThin
	 *            true when fetch should request thin-pack when possible; false
	 *            when it shouldn't
	 * @see PackTransport
	 */
	public void setFetchThin(boolean fetchThin) {
		this.fetchThin = fetchThin;
	}

	/**
	 * Whether fetch will verify if received objects are formatted correctly.
	 *
	 * @return true if fetch will verify received objects are formatted
	 *         correctly. Validating objects requires more CPU time on the
	 *         client side of the connection.
	 */
	public boolean isCheckFetchedObjects() {
		return getObjectChecker() != null;
	}

	/**
	 * Configure if checking received objects is enabled
	 *
	 * @param check
	 *            true to enable checking received objects; false to assume all
	 *            received objects are valid.
	 * @see #setObjectChecker(ObjectChecker)
	 */
	public void setCheckFetchedObjects(boolean check) {
		if (check && objectChecker == null)
			setObjectChecker(new ObjectChecker());
		else if (!check && objectChecker != null)
			setObjectChecker(null);
	}

	/**
	 * Get configured object checker for received objects
	 *
	 * @return configured object checker for received objects, or null.
	 * @since 3.6
	 */
	public ObjectChecker getObjectChecker() {
		return objectChecker;
	}

	/**
	 * Set the object checker to verify each received object with
	 *
	 * @param impl
	 *            if non-null the object checking instance to verify each
	 *            received object with; null to disable object checking.
	 * @since 3.6
	 */
	public void setObjectChecker(ObjectChecker impl) {
		objectChecker = impl;
	}

	/**
	 * Default setting is:
	 * {@link org.eclipse.jgit.transport.RemoteConfig#DEFAULT_RECEIVE_PACK}
	 *
	 * @return remote executable providing receive-pack service for pack
	 *         transports.
	 * @see PackTransport
	 */
	public String getOptionReceivePack() {
		return optionReceivePack;
	}

	/**
	 * Set remote executable providing receive-pack service for pack transports.
	 * Default setting is:
	 * {@link org.eclipse.jgit.transport.RemoteConfig#DEFAULT_RECEIVE_PACK}
	 *
	 * @param optionReceivePack
	 *            remote executable, if null or empty default one is set;
	 */
	public void setOptionReceivePack(String optionReceivePack) {
		if (optionReceivePack != null && optionReceivePack.length() > 0)
			this.optionReceivePack = optionReceivePack;
		else
			this.optionReceivePack = RemoteConfig.DEFAULT_RECEIVE_PACK;
	}

	/**
	 * Default setting is: {@value #DEFAULT_PUSH_THIN}
	 *
	 * @return true if push should produce thin-pack in pack transports
	 * @see PackTransport
	 */
	public boolean isPushThin() {
		return pushThin;
	}

	/**
	 * Set thin-pack preference for push operation. Default setting is:
	 * {@value #DEFAULT_PUSH_THIN}
	 *
	 * @param pushThin
	 *            true when push should produce thin-pack in pack transports;
	 *            false when it shouldn't
	 * @see PackTransport
	 */
	public void setPushThin(boolean pushThin) {
		this.pushThin = pushThin;
	}

	/**
	 * Default setting is false.
	 *
	 * @return true if push requires all-or-nothing atomic behavior.
	 * @since 4.2
	 */
	public boolean isPushAtomic() {
		return pushAtomic;
	}

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

	/**
	 * Default setting is: {@value #DEFAULT_PUSH_USE_BITMAPS}
	 *
	 * @return true if push use bitmaps.
	 * @since 6.4
	 */
	public boolean isPushUseBitmaps() {
		return pushUseBitmaps;
	}

	/**
	 * Set whether to use bitmaps for push. Default setting is:
	 * {@value #DEFAULT_PUSH_USE_BITMAPS}
	 *
	 * @param useBitmaps
	 *            false to disable use of bitmaps for push, true otherwise.
	 * @since 6.4
	 */
	public void setPushUseBitmaps(boolean useBitmaps) {
		this.pushUseBitmaps = useBitmaps;
	}

	/**
	 * Whether destination refs should be removed if they no longer exist at the
	 * source repository.
	 *
	 * @return true if destination refs should be removed if they no longer
	 *         exist at the source repository.
	 */
	public boolean isRemoveDeletedRefs() {
		return removeDeletedRefs;
	}

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

	/**
	 * @return the blob limit value set with {@link #setFilterBlobLimit} or
	 *         {@link #setFilterSpec(FilterSpec)}, or -1 if no blob limit value
	 *         was set
	 * @since 5.0
	 * @deprecated Use {@link #getFilterSpec()} instead
	 */
	@Deprecated
	public final long getFilterBlobLimit() {
		return filterSpec.getBlobLimit();
	}

	/**
	 * @param bytes exclude blobs of size greater than this
	 * @since 5.0
	 * @deprecated Use {@link #setFilterSpec(FilterSpec)} instead
	 */
	@Deprecated
	public final void setFilterBlobLimit(long bytes) {
		setFilterSpec(FilterSpec.withBlobLimit(bytes));
	}

	/**
	 * Get filter spec
	 *
	 * @return the last filter spec set with {@link #setFilterSpec(FilterSpec)},
	 *         or {@link FilterSpec#NO_FILTER} if it was never invoked.
	 * @since 5.4
	 */
	public final FilterSpec getFilterSpec() {
		return filterSpec;
	}

	/**
	 * Set filter spec
	 *
	 * @param filter
	 *            a new filter to use for this transport
	 * @since 5.4
	 */
	public final void setFilterSpec(@NonNull FilterSpec filter) {
		filterSpec = requireNonNull(filter);
	}


	/**
	 * Retrieves the depth for a shallow clone.
	 *
	 * @return the depth, or {@code null} if none set
	 * @since 6.3
	 */
	public final Integer getDepth() {
		return depth;
	}

	/**
	 * Limits fetching to the specified number of commits from the tip of each
	 * remote branch history.
	 *
	 * @param depth
	 *            the depth
	 * @since 6.3
	 */
	public final void setDepth(int depth) {
		if (depth < 1) {
			throw new IllegalArgumentException(JGitText.get().depthMustBeAt1);
		}
		this.depth = Integer.valueOf(depth);
	}

	/**
	 * Limits fetching to the specified number of commits from the tip of each
	 * remote branch history.
	 *
	 * @param depth
	 *            the depth, or {@code null} to unset the depth
	 * @since 6.3
	 */
	public final void setDepth(Integer depth) {
		if (depth != null && depth.intValue() < 1) {
			throw new IllegalArgumentException(JGitText.get().depthMustBeAt1);
		}
		this.depth = depth;
	}

	/**
	 * Get deepen-since
	 *
	 * @return the deepen-since for a shallow clone
	 * @since 6.3
	 */
	public final Instant getDeepenSince() {
		return deepenSince;
	}

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

	/**
	 * Get list of deepen-not
	 *
	 * @return the list of deepen-not for a shallow clone
	 * @since 6.3
	 */
	public final List<String> getDeepenNots() {
		return deepenNots;
	}

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

	/**
	 * Apply provided remote configuration on this transport.
	 *
	 * @param cfg
	 *            configuration to apply on this transport.
	 */
	public void applyConfig(RemoteConfig cfg) {
		setOptionUploadPack(cfg.getUploadPack());
		setOptionReceivePack(cfg.getReceivePack());
		setTagOpt(cfg.getTagOpt());
		fetch = cfg.getFetchRefSpecs();
		push = cfg.getPushRefSpecs();
		timeout = cfg.getTimeout();
	}

	/**
	 * Whether push operation should just check for possible result and not
	 * really update remote refs
	 *
	 * @return true if push operation should just check for possible result and
	 *         not really update remote refs, false otherwise - when push should
	 *         act normally.
	 */
	public boolean isDryRun() {
		return dryRun;
	}

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

	/**
	 * Get timeout (in seconds) before aborting an IO operation.
	 *
	 * @return timeout (in seconds) before aborting an IO operation.
	 */
	public int getTimeout() {
		return timeout;
	}

	/**
	 * Set the timeout before willing to abort an IO call.
	 *
	 * @param seconds
	 *            number of seconds to wait (with no data transfer occurring)
	 *            before aborting an IO read or write operation with this
	 *            remote.
	 */
	public void setTimeout(int seconds) {
		timeout = seconds;
	}

	/**
	 * Get the configuration used by the pack generator to make packs.
	 *
	 * If {@link #setPackConfig(PackConfig)} was previously given null a new
	 * PackConfig is created on demand by this method using the source
	 * repository's settings.
	 *
	 * @return the pack configuration. Never null.
	 */
	public PackConfig getPackConfig() {
		if (packConfig == null)
			packConfig = new PackConfig(local);
		return packConfig;
	}

	/**
	 * Set the configuration used by the pack generator.
	 *
	 * @param pc
	 *            configuration controlling packing parameters. If null the
	 *            source repository's settings will be used.
	 */
	public void setPackConfig(PackConfig pc) {
		packConfig = pc;
	}

	/**
	 * A credentials provider to assist with authentication connections..
	 *
	 * @param credentialsProvider
	 *            the credentials provider, or null if there is none
	 */
	public void setCredentialsProvider(CredentialsProvider credentialsProvider) {
		this.credentialsProvider = credentialsProvider;
	}

	/**
	 * The configured credentials provider.
	 *
	 * @return the credentials provider, or null if no credentials provider is
	 *         associated with this transport.
	 */
	public CredentialsProvider getCredentialsProvider() {
		return credentialsProvider;
	}

	/**
	 * Get the option strings associated with the push operation
	 *
	 * @return the option strings associated with the push operation
	 * @since 4.5
	 */
	public List<String> getPushOptions() {
		return pushOptions;
	}

	/**
	 * Sets the option strings associated with the push operation.
	 *
	 * @param pushOptions
	 *            null if push options are unsupported
	 * @since 4.5
	 */
	public void setPushOptions(List<String> pushOptions) {
		this.pushOptions = pushOptions;
	}

	/**
	 * Fetch objects and refs from the remote repository to the local one.
	 * <p>
	 * This is a utility function providing standard fetch behavior. Local
	 * tracking refs associated with the remote repository are automatically
	 * updated if this transport was created from a
	 * {@link org.eclipse.jgit.transport.RemoteConfig} with fetch RefSpecs
	 * defined.
	 *
	 * @param monitor
	 *            progress monitor to inform the user about our processing
	 *            activity. Must not be null. Use
	 *            {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
	 *            updates are not interesting or necessary.
	 * @param toFetch
	 *            specification of refs to fetch locally. May be null or the
	 *            empty collection to use the specifications from the
	 *            RemoteConfig. May contains regular and negative
	 *            {@link RefSpec}s. Source for each regular RefSpec can't
	 *            be null.
	 * @return information describing the tracking refs updated.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             this transport implementation does not support fetching
	 *             objects.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the remote connection could not be established or object
	 *             copying (if necessary) failed or update specification was
	 *             incorrect.
	 * @since 5.11
	 */
	public FetchResult fetch(final ProgressMonitor monitor,
			Collection<RefSpec> toFetch)
			throws NotSupportedException, TransportException {
		return fetch(monitor, toFetch, null);
	}

	/**
	 * Fetch objects and refs from the remote repository to the local one.
	 * <p>
	 * This is a utility function providing standard fetch behavior. Local
	 * tracking refs associated with the remote repository are automatically
	 * updated if this transport was created from a
	 * {@link org.eclipse.jgit.transport.RemoteConfig} with fetch RefSpecs
	 * defined.
	 *
	 * @param monitor
	 *            progress monitor to inform the user about our processing
	 *            activity. Must not be null. Use
	 *            {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
	 *            updates are not interesting or necessary.
	 * @param toFetch
	 *            specification of refs to fetch locally. May be null or the
	 *            empty collection to use the specifications from the
	 *            RemoteConfig. May contain regular and negative
	 *            {@link RefSpec}s. Source for each regular RefSpec can't
	 *            be null.
	 * @param branch
	 *            the initial branch to check out when cloning the repository.
	 *            Can be specified as ref name (<code>refs/heads/master</code>),
	 *            branch name (<code>master</code>) or tag name
	 *            (<code>v1.2.3</code>). The default is to use the branch
	 *            pointed to by the cloned repository's HEAD and can be
	 *            requested by passing {@code null} or <code>HEAD</code>.
	 * @return information describing the tracking refs updated.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             this transport implementation does not support fetching
	 *             objects.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the remote connection could not be established or object
	 *             copying (if necessary) failed or update specification was
	 *             incorrect.
	 * @since 5.11
	 */
	public FetchResult fetch(final ProgressMonitor monitor,
			Collection<RefSpec> toFetch, String branch)
			throws NotSupportedException,
			TransportException {
		if (toFetch == null || toFetch.isEmpty()) {
			// If the caller did not ask for anything use the defaults.
			//
			if (fetch.isEmpty())
				throw new TransportException(JGitText.get().nothingToFetch);
			toFetch = fetch;
		} else if (!fetch.isEmpty()) {
			// If the caller asked for something specific without giving
			// us the local tracking branch see if we can update any of
			// the local tracking branches without incurring additional
			// object transfer overheads.
			//
			final Collection<RefSpec> tmp = new ArrayList<>(toFetch);
			for (RefSpec requested : toFetch) {
				final String reqSrc = requested.getSource();
				for (RefSpec configured : fetch) {
					final String cfgSrc = configured.getSource();
					final String cfgDst = configured.getDestination();
					if (cfgSrc.equals(reqSrc) && cfgDst != null) {
						tmp.add(configured);
						break;
					}
				}
			}
			toFetch = tmp;
		}

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

		local.autoGC(monitor);

		return result;
	}

	/**
	 * Push objects and refs from the local repository to the remote one.
	 * <p>
	 * This is a utility function providing standard push behavior. It updates
	 * remote refs and send there necessary objects according to remote ref
	 * update specification. After successful remote ref update, associated
	 * locally stored tracking branch is updated if set up accordingly. Detailed
	 * operation result is provided after execution.
	 * <p>
	 * For setting up remote ref update specification from ref spec, see helper
	 * method {@link #findRemoteRefUpdatesFor(Collection)}, predefined refspecs
	 * ({@link #REFSPEC_TAGS}, {@link #REFSPEC_PUSH_ALL}) or consider using
	 * directly {@link org.eclipse.jgit.transport.RemoteRefUpdate} for more
	 * possibilities.
	 * <p>
	 * When {@link #isDryRun()} is true, result of this operation is just
	 * estimation of real operation result, no real action is performed.
	 *
	 * @see RemoteRefUpdate
	 * @param monitor
	 *            progress monitor to inform the user about our processing
	 *            activity. Must not be null. Use
	 *            {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
	 *            updates are not interesting or necessary.
	 * @param toPush
	 *            specification of refs to push. May be null or the empty
	 *            collection to use the specifications from the RemoteConfig
	 *            converted by {@link #findRemoteRefUpdatesFor(Collection)}. No
	 *            more than 1 RemoteRefUpdate with the same remoteName is
	 *            allowed. These objects are modified during this call.
	 * @param out
	 *            output stream to write messages to
	 * @return information about results of remote refs updates, tracking refs
	 *         updates and refs advertised by remote repository.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             this transport implementation does not support pushing
	 *             objects.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the remote connection could not be established or object
	 *             copying (if necessary) failed at I/O or protocol level or
	 *             update specification was incorrect.
	 * @since 3.0
	 */
	public PushResult push(final ProgressMonitor monitor,
			Collection<RemoteRefUpdate> toPush, OutputStream out)
			throws NotSupportedException,
			TransportException {
		if (toPush == null || toPush.isEmpty()) {
			// If the caller did not ask for anything use the defaults.
			try {
				toPush = findRemoteRefUpdatesFor(push);
			} catch (final IOException e) {
				throw new TransportException(MessageFormat.format(
						JGitText.get().problemWithResolvingPushRefSpecsLocally, e.getMessage()), e);
			}
			if (toPush.isEmpty())
				throw new TransportException(JGitText.get().nothingToPush);
		}

		PrePushHook prePush = null;
		if (local != null) {
			// Pushing will always have a local repository. But better safe than
			// sorry.
			prePush = Hooks.prePush(local, hookOutRedirect, hookErrRedirect);
			prePush.setRemoteLocation(uri.toString());
			prePush.setRemoteName(remoteName);
		}
		PushProcess pushProcess = new PushProcess(this, toPush, prePush, out);
		return pushProcess.execute(monitor);
	}

	/**
	 * Push objects and refs from the local repository to the remote one.
	 * <p>
	 * This is a utility function providing standard push behavior. It updates
	 * remote refs and sends necessary objects according to remote ref update
	 * specification. After successful remote ref update, associated locally
	 * stored tracking branch is updated if set up accordingly. Detailed
	 * operation result is provided after execution.
	 * <p>
	 * For setting up remote ref update specification from ref spec, see helper
	 * method {@link #findRemoteRefUpdatesFor(Collection)}, predefined refspecs
	 * ({@link #REFSPEC_TAGS}, {@link #REFSPEC_PUSH_ALL}) or consider using
	 * directly {@link org.eclipse.jgit.transport.RemoteRefUpdate} for more
	 * possibilities.
	 * <p>
	 * When {@link #isDryRun()} is true, result of this operation is just
	 * estimation of real operation result, no real action is performed.
	 *
	 * @see RemoteRefUpdate
	 * @param monitor
	 *            progress monitor to inform the user about our processing
	 *            activity. Must not be null. Use
	 *            {@link org.eclipse.jgit.lib.NullProgressMonitor} if progress
	 *            updates are not interesting or necessary.
	 * @param toPush
	 *            specification of refs to push. May be null or the empty
	 *            collection to use the specifications from the RemoteConfig
	 *            converted by {@link #findRemoteRefUpdatesFor(Collection)}. No
	 *            more than 1 RemoteRefUpdate with the same remoteName is
	 *            allowed. These objects are modified during this call.
	 * @return information about results of remote refs updates, tracking refs
	 *         updates and refs advertised by remote repository.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             this transport implementation does not support pushing
	 *             objects.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the remote connection could not be established or object
	 *             copying (if necessary) failed at I/O or protocol level or
	 *             update specification was incorrect.
	 */
	public PushResult push(final ProgressMonitor monitor,
			Collection<RemoteRefUpdate> toPush) throws NotSupportedException,
			TransportException {
		return push(monitor, toPush, null);
	}

	/**
	 * Convert push remote refs update specification from
	 * {@link org.eclipse.jgit.transport.RefSpec} form to
	 * {@link org.eclipse.jgit.transport.RemoteRefUpdate}. Conversion expands
	 * wildcards by matching source part to local refs. expectedOldObjectId in
	 * RemoteRefUpdate is always set as null. Tracking branch is configured if
	 * RefSpec destination matches source of any fetch ref spec for this
	 * transport remote configuration.
	 * <p>
	 * Conversion is performed for context of this transport (database, fetch
	 * specifications).
	 *
	 * @param specs
	 *            collection of RefSpec to convert.
	 * @return collection of set up
	 *         {@link org.eclipse.jgit.transport.RemoteRefUpdate}.
	 * @throws java.io.IOException
	 *             when problem occurred during conversion or specification set
	 *             up: most probably, missing objects or refs.
	 */
	public Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
			final Collection<RefSpec> specs) throws IOException {
		return findRemoteRefUpdatesFor(local, specs, Collections.emptyMap(),
					       fetch);
	}

	/**
	 * Convert push remote refs update specification from
	 * {@link org.eclipse.jgit.transport.RefSpec} form to
	 * {@link org.eclipse.jgit.transport.RemoteRefUpdate}. Conversion expands
	 * wildcards by matching source part to local refs. expectedOldObjectId in
	 * RemoteRefUpdate is set according to leases. Tracking branch is configured
	 * if RefSpec destination matches source of any fetch ref spec for this
	 * transport remote configuration.
	 * <p>
	 * Conversion is performed for context of this transport (database, fetch
	 * specifications).
	 *
	 * @param specs
	 *            collection of RefSpec to convert.
	 * @param leases
	 *            map from ref to lease (containing expected old object id)
	 * @return collection of set up
	 *         {@link org.eclipse.jgit.transport.RemoteRefUpdate}.
	 * @throws java.io.IOException
	 *             when problem occurred during conversion or specification set
	 *             up: most probably, missing objects or refs.
	 * @since 4.7
	 */
	public Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
			final Collection<RefSpec> specs,
			final Map<String, RefLeaseSpec> leases) throws IOException {
		return findRemoteRefUpdatesFor(local, specs, leases,
					       fetch);
	}

	/**
	 * Begins a new connection for fetching from the remote repository.
	 * <p>
	 * If the transport has no local repository, the fetch connection can only
	 * be used for reading remote refs.
	 *
	 * @return a fresh connection to fetch from the remote repository.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             the implementation does not support fetching.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the remote connection could not be established.
	 */
	public abstract FetchConnection openFetch() throws NotSupportedException,
			TransportException;

	/**
	 * Begins a new connection for fetching from the remote repository.
	 * <p>
	 * If the transport has no local repository, the fetch connection can only
	 * be used for reading remote refs.
	 * </p>
	 * <p>
	 * If the server supports git protocol V2, the {@link RefSpec}s and the
	 * additional patterns, if any, are used to restrict the server's ref
	 * advertisement to matching refs only.
	 * </p>
	 * <p>
	 * Transports that want to support git protocol V2 <em>must</em> override
	 * this; the default implementation ignores its arguments and calls
	 * {@link #openFetch()}.
	 * </p>
	 *
	 * @param refSpecs
	 *            that will be fetched via
	 *            {@link FetchConnection#fetch(ProgressMonitor, Collection, java.util.Set, OutputStream)} later
	 * @param additionalPatterns
	 *            that will be set as ref prefixes if the server supports git
	 *            protocol V2; {@code null} values are ignored
	 *
	 * @return a fresh connection to fetch from the remote repository.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             the implementation does not support fetching.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the remote connection could not be established.
	 * @since 5.11
	 */
	public FetchConnection openFetch(Collection<RefSpec> refSpecs,
			String... additionalPatterns)
			throws NotSupportedException, TransportException {
		return openFetch();
	}

	/**
	 * Begins a new connection for pushing into the remote repository.
	 *
	 * @return a fresh connection to push into the remote repository.
	 * @throws org.eclipse.jgit.errors.NotSupportedException
	 *             the implementation does not support pushing.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             the remote connection could not be established
	 */
	public abstract PushConnection openPush() throws NotSupportedException,
			TransportException;

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