#!/usr/bin/python## This Source Code Form is subject to the terms of the Mozilla Public# License, v. 2.0. If a copy of the MPL was not distributed with this# file, You can obtain one at http://mozilla.org/MPL/2.0/.## When run directly, this script expects the following environment variables# to be set:# UPLOAD_PATH : path on that host to put the files in## Files are simply copied to UPLOAD_PATH.## All files to be uploaded should be passed as commandline arguments to this# script. The script takes one other parameter, --base-path, which you can use# to indicate that files should be uploaded including their paths relative# to the base path.importosimportshutilimportsysfromoptparseimportOptionParserdefOptionalEnvironmentVariable(v):"""Return the value of the environment variable named v, or None if it's unset (or empty)."""ifvinos.environandos.environ[v]!="":returnos.environ[v]returnNonedefFixupMsysPath(path):"""MSYS helpfully translates absolute pathnames in environment variables and commandline arguments into Windows native paths. This sucks if you're trying to pass an absolute path on a remote server. This function attempts to un-mangle such paths."""if"OSTYPE"inos.environandos.environ["OSTYPE"]=="msys":# sort of awful, find out where our shell is (should be in msys2/usr/bin# or msys/bin) and strip the first part of that path out of the other pathif"SHELL"inos.environ:sh=os.environ["SHELL"]msys=sh[:sh.find("/bin")]ifpath.startswith(msys):path=path[len(msys):]returnpathdefGetBaseRelativePath(path,local_file,base_path):"""Given a remote path to upload to, a full path to a local file, and an optional full path that is a base path of the local file, construct the full remote path to place the file in. If base_path is not None, include the relative path from base_path to file."""ifbase_pathisNoneornotlocal_file.startswith(base_path):returnpathdir=os.path.dirname(local_file)# strip base_path + extra slash and make it unixydir=dir[len(base_path)+1:].replace("\\","/")returnpath+dirdefCopyFilesLocally(path,files,verbose=False,base_path=None):"""Copy each file in the list of files to `path`. The `base_path` argument is treated as it is by UploadFiles."""ifnotpath.endswith("/"):path+="/"ifbase_pathisnotNone:base_path=os.path.abspath(base_path)forfileinfiles:file=os.path.abspath(file)ifnotos.path.isfile(file):raiseOSError("File not found: %s"%file)# first ensure that path exists remotelytarget_path=GetBaseRelativePath(path,file,base_path)ifnotos.path.exists(target_path):os.makedirs(target_path)ifverbose:print("Copying "+file+" to "+target_path)shutil.copy(file,target_path)if__name__=="__main__":path=OptionalEnvironmentVariable("UPLOAD_PATH")ifsys.platform=="win32":ifpathisnotNone:path=FixupMsysPath(path)parser=OptionParser(usage="usage: %prog [options] <files>")parser.add_option("-b","--base-path",action="store",help="Preserve file paths relative to this path when uploading. ""If unset, all files will be uploaded directly to UPLOAD_PATH.",)(options,args)=parser.parse_args()iflen(args)<1:print("You must specify at least one file to upload")sys.exit(1)try:CopyFilesLocally(path,args,base_path=options.base_path,verbose=True)exceptOSErrorasstrerror:print(strerror)sys.exit(1)