#!/usr/bin/env python
#===----------------------------------------------------------------------===##
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#===----------------------------------------------------------------------===##

"""
Runs an executable on a remote host.

This is meant to be used as an executor when running the LLVM and the Libraries
tests on a target.
"""

import argparse
import os
import posixpath
import shlex
import subprocess
import sys
import tarfile
import tempfile
import re

def ssh(args, command):
    cmd = ['ssh', '-oBatchMode=yes']
    if args.extra_ssh_args is not None:
        cmd.extend(shlex.split(args.extra_ssh_args))
    return cmd + [args.host, command]


def scp(args, src, dst):
    cmd = ['scp', '-q', '-oBatchMode=yes']
    if args.extra_scp_args is not None:
        cmd.extend(shlex.split(args.extra_scp_args))
    return cmd + [src, '{}:{}'.format(args.host, dst)]


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--host', type=str, required=True)
    parser.add_argument('--execdir', type=str, required=False)
    parser.add_argument('--extra-ssh-args', type=str, required=False)
    parser.add_argument('--extra-scp-args', type=str, required=False)
    parser.add_argument('--codesign_identity', type=str, required=False, default=None)
    parser.add_argument('--env', type=str, nargs='*', required=False, default=dict())

    # Note: The default value is for the backward compatibility with a hack in
    # libcxx test suite.
    # If an argument is a file that ends in `.tmp.exe`, assume it is the name
    # of an executable generated by a test file. We call these test-executables
    # below. This allows us to do custom processing like codesigning test-executables
    # and changing their path when running on the remote host. It's also possible
    # for there to be no such executable, for example in the case of a .sh.cpp
    # test.
    parser.add_argument('--exec-pattern', type=str, required=False, default='.*',
                        help='The name regex pattern of the executables generated by \
                              a test file. Specifying it allows us to do custom \
                              processing like codesigning test-executables \
                              and changing their path when running on \
                              the remote host. It\'s also possible for there \
                              to be no such executable, for example in \
                              the case of a .sh.cpp test.')

    parser.add_argument("command", nargs=argparse.ONE_OR_MORE)
    args = parser.parse_args()
    commandLine = args.command

    execdir = args.execdir
    if execdir == '.':
        # Retrieve the exec directory from the command line.
        execdir, _ = os.path.split(commandLine[0])
        if execdir == '':
            # Get the current directory in that case.
            execdir = os.getcwd()
    arcname = os.path.basename(execdir) if execdir else None

    # Create a temporary directory where the test will be run.
    # That is effectively the value of %T on the remote host.
    tmp = subprocess.check_output(
                  ssh(args, 'mktemp -d /tmp/llvm.XXXXXXXXXX'),
                  universal_newlines=True
              ).strip()

    isExecutable = lambda exe: re.match(args.exec_pattern, exe) and os.path.exists(exe)
    pathOnRemote = lambda file: posixpath.join(tmp, os.path.basename(file))

    remoteCommands = []

    try:
        # Do any necessary codesigning of test-executables found in the command line.
        if args.codesign_identity:
            for exe in filter(isExecutable, commandLine):
                subprocess.check_call(
                    ['xcrun', 'codesign', '-f', '-s', args.codesign_identity, exe],
                    env={})

        # tar up the execution directory (which contains everything that's needed
        # to run the test), and copy the tarball over to the remote host.
        if execdir:
            try:
                tmpTar = tempfile.NamedTemporaryFile(suffix='.tar', delete=False)
                with tarfile.open(fileobj=tmpTar, mode='w') as tarball:
                    tarball.add(execdir, arcname=arcname)

                # Make sure we close the file before we scp it, because accessing
                # the temporary file while still open doesn't work on Windows.
                tmpTar.close()
                remoteTarball = pathOnRemote(tmpTar.name)
                subprocess.check_call(scp(args, tmpTar.name, remoteTarball))
            finally:
                # Make sure we close the file in case an exception happens before
                # we've closed it above -- otherwise close() is idempotent.
                tmpTar.close()
                os.remove(tmpTar.name)

            # Untar the dependencies in the temporary directory and remove the tarball.
            remoteCommands.extend([
                'tar -xf {} -C {} --strip-components 1'.format(remoteTarball, tmp),
                'rm {}'.format(remoteTarball)
            ])
        else:
            # Copy only the files, which are specified in the command line.
            # Copy them to remote host one by one.
            for x in commandLine:
                _, f = os.path.split(x)
                subprocess.check_call(scp(args, x, pathOnRemote(f)))

        # Make sure all executables in the remote command line have 'execute'
        # permissions on the remote host. The host that compiled the test-executable
        # might not have a notion of 'executable' permissions.
        for exe in filter(isExecutable, commandLine):
            remoteCommands.append('chmod +x {}'.format(pathOnRemote(exe)))

        # Execute the command through SSH in the temporary directory, with the
        # correct environment. We tweak the command line to run it on the remote
        # host by transforming the path of test-executables to their path in the
        # temporary directory on the remote host.
        for i, x in enumerate(commandLine):
            if isExecutable(x):
                commandLine[i] = pathOnRemote(x)
        remoteCommands.append('cd {}'.format(tmp))
        if args.env:
            remoteCommands.append('export {}'.format(' '.join(args.env)))
        remoteCommands.append(subprocess.list2cmdline(commandLine))

        # Finally, SSH to the remote host and execute all the commands.
        rc = subprocess.call(ssh(args, ' && '.join(remoteCommands)))
        return rc

    finally:
        # Make sure the temporary directory is removed when we're done.
        subprocess.check_call(ssh(args, 'rm -r {}'.format(tmp)))


if __name__ == '__main__':
    exit(main())
