build/upload.py

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 #!/usr/bin/python
michael@0 2 #
michael@0 3 # This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 # License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 6 #
michael@0 7 # When run directly, this script expects the following environment variables
michael@0 8 # to be set:
michael@0 9 # UPLOAD_HOST : host to upload files to
michael@0 10 # UPLOAD_USER : username on that host
michael@0 11 # UPLOAD_PATH : path on that host to put the files in
michael@0 12 #
michael@0 13 # And will use the following optional environment variables if set:
michael@0 14 # UPLOAD_SSH_KEY : path to a ssh private key to use
michael@0 15 # UPLOAD_PORT : port to use for ssh
michael@0 16 # POST_UPLOAD_CMD: a commandline to run on the remote host after uploading.
michael@0 17 # UPLOAD_PATH and the full paths of all files uploaded will
michael@0 18 # be appended to the commandline.
michael@0 19 #
michael@0 20 # All files to be uploaded should be passed as commandline arguments to this
michael@0 21 # script. The script takes one other parameter, --base-path, which you can use
michael@0 22 # to indicate that files should be uploaded including their paths relative
michael@0 23 # to the base path.
michael@0 24
michael@0 25 import sys, os
michael@0 26 from optparse import OptionParser
michael@0 27 from subprocess import PIPE, Popen, check_call
michael@0 28
michael@0 29 def RequireEnvironmentVariable(v):
michael@0 30 """Return the value of the environment variable named v, or print
michael@0 31 an error and exit if it's unset (or empty)."""
michael@0 32 if not v in os.environ or os.environ[v] == "":
michael@0 33 print "Error: required environment variable %s not set" % v
michael@0 34 sys.exit(1)
michael@0 35 return os.environ[v]
michael@0 36
michael@0 37 def OptionalEnvironmentVariable(v):
michael@0 38 """Return the value of the environment variable named v, or None
michael@0 39 if it's unset (or empty)."""
michael@0 40 if v in os.environ and os.environ[v] != "":
michael@0 41 return os.environ[v]
michael@0 42 return None
michael@0 43
michael@0 44 def FixupMsysPath(path):
michael@0 45 """MSYS helpfully translates absolute pathnames in environment variables
michael@0 46 and commandline arguments into Windows native paths. This sucks if you're
michael@0 47 trying to pass an absolute path on a remote server. This function attempts
michael@0 48 to un-mangle such paths."""
michael@0 49 if 'OSTYPE' in os.environ and os.environ['OSTYPE'] == 'msys':
michael@0 50 # sort of awful, find out where our shell is (should be in msys/bin)
michael@0 51 # and strip the first part of that path out of the other path
michael@0 52 if 'SHELL' in os.environ:
michael@0 53 sh = os.environ['SHELL']
michael@0 54 msys = sh[:sh.find('/bin')]
michael@0 55 if path.startswith(msys):
michael@0 56 path = path[len(msys):]
michael@0 57 return path
michael@0 58
michael@0 59 def WindowsPathToMsysPath(path):
michael@0 60 """Translate a Windows pathname to an MSYS pathname.
michael@0 61 Necessary because we call out to ssh/scp, which are MSYS binaries
michael@0 62 and expect MSYS paths."""
michael@0 63 if sys.platform != 'win32':
michael@0 64 return path
michael@0 65 (drive, path) = os.path.splitdrive(os.path.abspath(path))
michael@0 66 return "/" + drive[0] + path.replace('\\','/')
michael@0 67
michael@0 68 def AppendOptionalArgsToSSHCommandline(cmdline, port, ssh_key):
michael@0 69 """Given optional port and ssh key values, append valid OpenSSH
michael@0 70 commandline arguments to the list cmdline if the values are not None."""
michael@0 71 if port is not None:
michael@0 72 cmdline.append("-P%d" % port)
michael@0 73 if ssh_key is not None:
michael@0 74 # Don't interpret ~ paths - ssh can handle that on its own
michael@0 75 if not ssh_key.startswith('~'):
michael@0 76 ssh_key = WindowsPathToMsysPath(ssh_key)
michael@0 77 cmdline.extend(["-o", "IdentityFile=%s" % ssh_key])
michael@0 78
michael@0 79 def DoSSHCommand(command, user, host, port=None, ssh_key=None):
michael@0 80 """Execute command on user@host using ssh. Optionally use
michael@0 81 port and ssh_key, if provided."""
michael@0 82 cmdline = ["ssh"]
michael@0 83 AppendOptionalArgsToSSHCommandline(cmdline, port, ssh_key)
michael@0 84 cmdline.extend(["%s@%s" % (user, host), command])
michael@0 85 cmd = Popen(cmdline, stdout=PIPE)
michael@0 86 retcode = cmd.wait()
michael@0 87 if retcode != 0:
michael@0 88 raise Exception("Command %s returned non-zero exit code: %i" % \
michael@0 89 (cmdline, retcode))
michael@0 90 return cmd.stdout.read().strip()
michael@0 91
michael@0 92 def DoSCPFile(file, remote_path, user, host, port=None, ssh_key=None):
michael@0 93 """Upload file to user@host:remote_path using scp. Optionally use
michael@0 94 port and ssh_key, if provided."""
michael@0 95 cmdline = ["scp"]
michael@0 96 AppendOptionalArgsToSSHCommandline(cmdline, port, ssh_key)
michael@0 97 cmdline.extend([WindowsPathToMsysPath(file),
michael@0 98 "%s@%s:%s" % (user, host, remote_path)])
michael@0 99 check_call(cmdline)
michael@0 100
michael@0 101 def GetRemotePath(path, local_file, base_path):
michael@0 102 """Given a remote path to upload to, a full path to a local file, and an
michael@0 103 optional full path that is a base path of the local file, construct the
michael@0 104 full remote path to place the file in. If base_path is not None, include
michael@0 105 the relative path from base_path to file."""
michael@0 106 if base_path is None or not local_file.startswith(base_path):
michael@0 107 return path
michael@0 108 dir = os.path.dirname(local_file)
michael@0 109 # strip base_path + extra slash and make it unixy
michael@0 110 dir = dir[len(base_path)+1:].replace('\\','/')
michael@0 111 return path + dir
michael@0 112
michael@0 113 def UploadFiles(user, host, path, files, verbose=False, port=None, ssh_key=None, base_path=None, upload_to_temp_dir=False, post_upload_command=None):
michael@0 114 """Upload each file in the list files to user@host:path. Optionally pass
michael@0 115 port and ssh_key to the ssh commands. If base_path is not None, upload
michael@0 116 files including their path relative to base_path. If upload_to_temp_dir is
michael@0 117 True files will be uploaded to a temporary directory on the remote server.
michael@0 118 Generally, you should have a post upload command specified in these cases
michael@0 119 that can move them around to their correct location(s).
michael@0 120 If post_upload_command is not None, execute that command on the remote host
michael@0 121 after uploading all files, passing it the upload path, and the full paths to
michael@0 122 all files uploaded.
michael@0 123 If verbose is True, print status updates while working."""
michael@0 124 if upload_to_temp_dir:
michael@0 125 path = DoSSHCommand("mktemp -d", user, host, port=port, ssh_key=ssh_key)
michael@0 126 if not path.endswith("/"):
michael@0 127 path += "/"
michael@0 128 if base_path is not None:
michael@0 129 base_path = os.path.abspath(base_path)
michael@0 130 remote_files = []
michael@0 131 try:
michael@0 132 for file in files:
michael@0 133 file = os.path.abspath(file)
michael@0 134 if not os.path.isfile(file):
michael@0 135 raise IOError("File not found: %s" % file)
michael@0 136 # first ensure that path exists remotely
michael@0 137 remote_path = GetRemotePath(path, file, base_path)
michael@0 138 DoSSHCommand("mkdir -p " + remote_path, user, host, port=port, ssh_key=ssh_key)
michael@0 139 if verbose:
michael@0 140 print "Uploading " + file
michael@0 141 DoSCPFile(file, remote_path, user, host, port=port, ssh_key=ssh_key)
michael@0 142 remote_files.append(remote_path + '/' + os.path.basename(file))
michael@0 143 if post_upload_command is not None:
michael@0 144 if verbose:
michael@0 145 print "Running post-upload command: " + post_upload_command
michael@0 146 file_list = '"' + '" "'.join(remote_files) + '"'
michael@0 147 DoSSHCommand('%s "%s" %s' % (post_upload_command, path, file_list), user, host, port=port, ssh_key=ssh_key)
michael@0 148 finally:
michael@0 149 if upload_to_temp_dir:
michael@0 150 DoSSHCommand("rm -rf %s" % path, user, host, port=port,
michael@0 151 ssh_key=ssh_key)
michael@0 152 if verbose:
michael@0 153 print "Upload complete"
michael@0 154
michael@0 155 if __name__ == '__main__':
michael@0 156 host = RequireEnvironmentVariable('UPLOAD_HOST')
michael@0 157 user = RequireEnvironmentVariable('UPLOAD_USER')
michael@0 158 path = OptionalEnvironmentVariable('UPLOAD_PATH')
michael@0 159 upload_to_temp_dir = OptionalEnvironmentVariable('UPLOAD_TO_TEMP')
michael@0 160 port = OptionalEnvironmentVariable('UPLOAD_PORT')
michael@0 161 if port is not None:
michael@0 162 port = int(port)
michael@0 163 key = OptionalEnvironmentVariable('UPLOAD_SSH_KEY')
michael@0 164 post_upload_command = OptionalEnvironmentVariable('POST_UPLOAD_CMD')
michael@0 165 if (not path and not upload_to_temp_dir) or (path and upload_to_temp_dir):
michael@0 166 print "One (and only one of UPLOAD_PATH or UPLOAD_TO_TEMP must be " + \
michael@0 167 "defined."
michael@0 168 sys.exit(1)
michael@0 169 if sys.platform == 'win32':
michael@0 170 if path is not None:
michael@0 171 path = FixupMsysPath(path)
michael@0 172 if post_upload_command is not None:
michael@0 173 post_upload_command = FixupMsysPath(post_upload_command)
michael@0 174
michael@0 175 parser = OptionParser(usage="usage: %prog [options] <files>")
michael@0 176 parser.add_option("-b", "--base-path",
michael@0 177 action="store", dest="base_path",
michael@0 178 help="Preserve file paths relative to this path when uploading. If unset, all files will be uploaded directly to UPLOAD_PATH.")
michael@0 179 (options, args) = parser.parse_args()
michael@0 180 if len(args) < 1:
michael@0 181 print "You must specify at least one file to upload"
michael@0 182 sys.exit(1)
michael@0 183 try:
michael@0 184 UploadFiles(user, host, path, args, base_path=options.base_path,
michael@0 185 port=port, ssh_key=key, upload_to_temp_dir=upload_to_temp_dir,
michael@0 186 post_upload_command=post_upload_command,
michael@0 187 verbose=True)
michael@0 188 except IOError, (strerror):
michael@0 189 print strerror
michael@0 190 sys.exit(1)
michael@0 191 except Exception, (err):
michael@0 192 print err
michael@0 193 sys.exit(2)

mercurial