/*
 * Copyright (C) 2008-2010, Google Inc.
 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
 * Copyright (C) 2008, 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 java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

import org.eclipse.jgit.errors.NoRemoteRepositoryException;
import org.eclipse.jgit.errors.NotSupportedException;
import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.QuotedString;
import org.eclipse.jgit.util.SystemReader;
import org.eclipse.jgit.util.io.MessageWriter;
import org.eclipse.jgit.util.io.StreamCopyThread;

/**
 * Transport through an SSH tunnel.
 * <p>
 * The SSH transport requires the remote side to have Git installed, as the
 * transport logs into the remote system and executes a Git helper program on
 * the remote side to read (or write) the remote repository's files.
 * <p>
 * This transport does not support direct SCP style of copying files, as it
 * assumes there are Git specific smarts on the remote side to perform object
 * enumeration, save file modification and hook execution.
 */
public class TransportGitSsh extends SshTransport implements PackTransport {
	static final TransportProtocol PROTO_SSH = new TransportProtocol() {
		private final String[] schemeNames = { "ssh", "ssh+git", "git+ssh" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

		private final Set<String> schemeSet = Collections
				.unmodifiableSet(new LinkedHashSet<>(Arrays
						.asList(schemeNames)));

		@Override
		public String getName() {
			return JGitText.get().transportProtoSSH;
		}

		@Override
		public Set<String> getSchemes() {
			return schemeSet;
		}

		@Override
		public Set<URIishField> getRequiredFields() {
			return Collections.unmodifiableSet(EnumSet.of(URIishField.HOST,
					URIishField.PATH));
		}

		@Override
		public Set<URIishField> getOptionalFields() {
			return Collections.unmodifiableSet(EnumSet.of(URIishField.USER,
					URIishField.PASS, URIishField.PORT));
		}

		@Override
		public int getDefaultPort() {
			return 22;
		}

		@Override
		public boolean canHandle(URIish uri, Repository local, String remoteName) {
			if (uri.getScheme() == null) {
				// scp-style URI "host:path" does not have scheme.
				return uri.getHost() != null
					&& uri.getPath() != null
					&& uri.getHost().length() != 0
					&& uri.getPath().length() != 0;
			}
			return super.canHandle(uri, local, remoteName);
		}

		@Override
		public Transport open(URIish uri, Repository local, String remoteName)
				throws NotSupportedException {
			return new TransportGitSsh(local, uri);
		}

		@Override
		public Transport open(URIish uri) throws NotSupportedException, TransportException {
			return new TransportGitSsh(uri);
		}
	};

	TransportGitSsh(Repository local, URIish uri) {
		super(local, uri);
		initSshSessionFactory();
	}

	TransportGitSsh(URIish uri) {
		super(uri);
		initSshSessionFactory();
	}

	private void initSshSessionFactory() {
		if (useExtSession()) {
			setSshSessionFactory(new SshSessionFactory() {
				@Override
				public RemoteSession getSession(URIish uri2,
						CredentialsProvider credentialsProvider, FS fs, int tms)
						throws TransportException {
					return new ExtSession();
				}
			});
		}
	}

	/** {@inheritDoc} */
	@Override
	public FetchConnection openFetch() throws TransportException {
		return new SshFetchConnection();
	}

	/** {@inheritDoc} */
	@Override
	public PushConnection openPush() throws TransportException {
		return new SshPushConnection();
	}

	String commandFor(String exe) {
		String path = uri.getPath();
		if (uri.getScheme() != null && uri.getPath().startsWith("/~")) //$NON-NLS-1$
			path = (uri.getPath().substring(1));

		final StringBuilder cmd = new StringBuilder();
		cmd.append(exe);
		cmd.append(' ');
		cmd.append(QuotedString.BOURNE.quote(path));
		return cmd.toString();
	}

	void checkExecFailure(int status, String exe, String why)
			throws TransportException {
		if (status == 127) {
			IOException cause = null;
			if (why != null && why.length() > 0)
				cause = new IOException(why);
			throw new TransportException(uri, MessageFormat.format(
					JGitText.get().cannotExecute, commandFor(exe)), cause);
		}
	}

	NoRemoteRepositoryException cleanNotFound(NoRemoteRepositoryException nf,
			String why) {
		if (why == null || why.length() == 0)
			return nf;

		String path = uri.getPath();
		if (uri.getScheme() != null && uri.getPath().startsWith("/~")) //$NON-NLS-1$
			path = uri.getPath().substring(1);

		final StringBuilder pfx = new StringBuilder();
		pfx.append("fatal: "); //$NON-NLS-1$
		pfx.append(QuotedString.BOURNE.quote(path));
		pfx.append(": "); //$NON-NLS-1$
		if (why.startsWith(pfx.toString()))
			why = why.substring(pfx.length());

		return new NoRemoteRepositoryException(uri, why);
	}

	private static boolean useExtSession() {
		return SystemReader.getInstance().getenv("GIT_SSH") != null; //$NON-NLS-1$
	}

	private class ExtSession implements RemoteSession {
		@Override
		public Process exec(String command, int timeout)
				throws TransportException {
			String ssh = SystemReader.getInstance().getenv("GIT_SSH"); //$NON-NLS-1$
			boolean putty = ssh.toLowerCase(Locale.ROOT).contains("plink"); //$NON-NLS-1$

			List<String> args = new ArrayList<>();
			args.add(ssh);
			if (putty
					&& !ssh.toLowerCase(Locale.ROOT).contains("tortoiseplink")) //$NON-NLS-1$
				args.add("-batch"); //$NON-NLS-1$
			if (0 < getURI().getPort()) {
				args.add(putty ? "-P" : "-p"); //$NON-NLS-1$ //$NON-NLS-2$
				args.add(String.valueOf(getURI().getPort()));
			}
			if (getURI().getUser() != null)
				args.add(getURI().getUser() + "@" + getURI().getHost()); //$NON-NLS-1$
			else
				args.add(getURI().getHost());
			args.add(command);

			ProcessBuilder pb = createProcess(args);
			try {
				return pb.start();
			} catch (IOException err) {
				throw new TransportException(err.getMessage(), err);
			}
		}

		private ProcessBuilder createProcess(List<String> args) {
			ProcessBuilder pb = new ProcessBuilder();
			pb.command(args);
			File directory = local != null ? local.getDirectory() : null;
			if (directory != null) {
				pb.environment().put(Constants.GIT_DIR_KEY,
						directory.getPath());
			}
			return pb;
		}

		@Override
		public void disconnect() {
			// Nothing to do
		}
	}

	class SshFetchConnection extends BasePackFetchConnection {
		private final Process process;

		private StreamCopyThread errorThread;

		SshFetchConnection() throws TransportException {
			super(TransportGitSsh.this);
			try {
				process = getSession().exec(commandFor(getOptionUploadPack()),
						getTimeout());
				final MessageWriter msg = new MessageWriter();
				setMessageWriter(msg);

				final InputStream upErr = process.getErrorStream();
				errorThread = new StreamCopyThread(upErr, msg.getRawStream());
				errorThread.start();

				init(process.getInputStream(), process.getOutputStream());

			} catch (TransportException err) {
				close();
				throw err;
			} catch (Throwable err) {
				close();
				throw new TransportException(uri,
						JGitText.get().remoteHungUpUnexpectedly, err);
			}

			try {
				readAdvertisedRefs();
			} catch (NoRemoteRepositoryException notFound) {
				final String msgs = getMessages();
				checkExecFailure(process.exitValue(), getOptionUploadPack(),
						msgs);
				throw cleanNotFound(notFound, msgs);
			}
		}

		@Override
		public void close() {
			endOut();

			if (process != null) {
				process.destroy();
			}
			if (errorThread != null) {
				try {
					errorThread.halt();
				} catch (InterruptedException e) {
					// Stop waiting and return anyway.
				} finally {
					errorThread = null;
				}
			}

			super.close();
		}
	}

	class SshPushConnection extends BasePackPushConnection {
		private final Process process;

		private StreamCopyThread errorThread;

		SshPushConnection() throws TransportException {
			super(TransportGitSsh.this);
			try {
				process = getSession().exec(commandFor(getOptionReceivePack()),
						getTimeout());
				final MessageWriter msg = new MessageWriter();
				setMessageWriter(msg);

				final InputStream rpErr = process.getErrorStream();
				errorThread = new StreamCopyThread(rpErr, msg.getRawStream());
				errorThread.start();

				init(process.getInputStream(), process.getOutputStream());

			} catch (TransportException err) {
				try {
					close();
				} catch (Exception e) {
					// ignore
				}
				throw err;
			} catch (Throwable err) {
				try {
					close();
				} catch (Exception e) {
					// ignore
				}
				throw new TransportException(uri,
						JGitText.get().remoteHungUpUnexpectedly, err);
			}

			try {
				readAdvertisedRefs();
			} catch (NoRemoteRepositoryException notFound) {
				final String msgs = getMessages();
				checkExecFailure(process.exitValue(), getOptionReceivePack(),
						msgs);
				throw cleanNotFound(notFound, msgs);
			}
		}

		@Override
		public void close() {
			endOut();

			if (process != null) {
				process.destroy();
			}
			if (errorThread != null) {
				try {
					errorThread.halt();
				} catch (InterruptedException e) {
					// Stop waiting and return anyway.
				} finally {
					errorThread = null;
				}
			}

			super.close();
		}
	}
}
