зеркало из https://github.com/mozilla/gecko-dev.git
Bug 616810 Remove extraneous CRs r=khuey a=bsmedberg
This commit is contained in:
Родитель
39ce14fb83
Коммит
59075a58ed
190
build/cl.py
190
build/cl.py
|
@ -1,96 +1,96 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is cl.py: a python wrapper for cl to automatically generate
|
||||
# dependency information.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Kyle Huey <me@kylehuey.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
import os, os.path
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
CL_INCLUDES_PREFIX = os.environ.get("CL_INCLUDES_PREFIX", "Note: including file:")
|
||||
|
||||
def InvokeClWithDependencyGeneration(cmdline):
|
||||
target = ""
|
||||
# Figure out what the target is
|
||||
for arg in cmdline:
|
||||
if arg.startswith("-Fo"):
|
||||
target = arg[3:]
|
||||
break
|
||||
|
||||
if target == None:
|
||||
print >>sys.stderr, "No target set" and sys.exit(1)
|
||||
|
||||
# The deps target lives here
|
||||
depstarget = os.path.basename(target) + ".pp"
|
||||
|
||||
cmdline += ['-showIncludes']
|
||||
cl = subprocess.Popen(cmdline, stdout=subprocess.PIPE)
|
||||
|
||||
deps = set()
|
||||
for line in cl.stdout:
|
||||
# cl -showIncludes prefixes every header with "Note: including file:"
|
||||
# and an indentation corresponding to the depth (which we don't need)
|
||||
if line.startswith(CL_INCLUDES_PREFIX):
|
||||
dep = line[len(CL_INCLUDES_PREFIX):].strip()
|
||||
# We can't handle pathes with spaces properly in mddepend.pl, but
|
||||
# we can assume that anything in a path with spaces is a system
|
||||
# header and throw it away.
|
||||
if dep.find(' ') == -1:
|
||||
deps.add(dep)
|
||||
else:
|
||||
sys.stdout.write(line) # Make sure we preserve the relevant output
|
||||
# from cl
|
||||
|
||||
ret = cl.wait()
|
||||
if ret != 0 or target == "":
|
||||
sys.exit(ret)
|
||||
|
||||
depsdir = os.path.normpath(os.path.join(os.path.dirname(target), ".deps"))
|
||||
depstarget = os.path.join(depsdir, depstarget)
|
||||
if not os.path.isdir(depsdir):
|
||||
try:
|
||||
os.makedirs(depsdir)
|
||||
except OSError:
|
||||
pass # This suppresses the error we get when the dir exists, at the
|
||||
# cost of masking failure to create the directory. We'll just
|
||||
# die on the next line though, so it's not that much of a loss.
|
||||
|
||||
f = open(depstarget, "w")
|
||||
for dep in sorted(deps):
|
||||
print >>f, "%s: %s" % (target, dep)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is cl.py: a python wrapper for cl to automatically generate
|
||||
# dependency information.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Kyle Huey <me@kylehuey.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
import os, os.path
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
CL_INCLUDES_PREFIX = os.environ.get("CL_INCLUDES_PREFIX", "Note: including file:")
|
||||
|
||||
def InvokeClWithDependencyGeneration(cmdline):
|
||||
target = ""
|
||||
# Figure out what the target is
|
||||
for arg in cmdline:
|
||||
if arg.startswith("-Fo"):
|
||||
target = arg[3:]
|
||||
break
|
||||
|
||||
if target == None:
|
||||
print >>sys.stderr, "No target set" and sys.exit(1)
|
||||
|
||||
# The deps target lives here
|
||||
depstarget = os.path.basename(target) + ".pp"
|
||||
|
||||
cmdline += ['-showIncludes']
|
||||
cl = subprocess.Popen(cmdline, stdout=subprocess.PIPE)
|
||||
|
||||
deps = set()
|
||||
for line in cl.stdout:
|
||||
# cl -showIncludes prefixes every header with "Note: including file:"
|
||||
# and an indentation corresponding to the depth (which we don't need)
|
||||
if line.startswith(CL_INCLUDES_PREFIX):
|
||||
dep = line[len(CL_INCLUDES_PREFIX):].strip()
|
||||
# We can't handle pathes with spaces properly in mddepend.pl, but
|
||||
# we can assume that anything in a path with spaces is a system
|
||||
# header and throw it away.
|
||||
if dep.find(' ') == -1:
|
||||
deps.add(dep)
|
||||
else:
|
||||
sys.stdout.write(line) # Make sure we preserve the relevant output
|
||||
# from cl
|
||||
|
||||
ret = cl.wait()
|
||||
if ret != 0 or target == "":
|
||||
sys.exit(ret)
|
||||
|
||||
depsdir = os.path.normpath(os.path.join(os.path.dirname(target), ".deps"))
|
||||
depstarget = os.path.join(depsdir, depstarget)
|
||||
if not os.path.isdir(depsdir):
|
||||
try:
|
||||
os.makedirs(depsdir)
|
||||
except OSError:
|
||||
pass # This suppresses the error we get when the dir exists, at the
|
||||
# cost of masking failure to create the directory. We'll just
|
||||
# die on the next line though, so it's not that much of a loss.
|
||||
|
||||
f = open(depstarget, "w")
|
||||
for dep in sorted(deps):
|
||||
print >>f, "%s: %s" % (target, dep)
|
||||
|
||||
if __name__ == "__main__":
|
||||
InvokeClWithDependencyGeneration(sys.argv[1:])
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
"""
|
||||
Implicit variables; perhaps in the future this will also include some implicit
|
||||
rules, at least match-anything cancellation rules.
|
||||
"""
|
||||
|
||||
variables = {
|
||||
'RM': '%pymake.builtins rm -f',
|
||||
'SLEEP': '%pymake.builtins sleep',
|
||||
'TOUCH': '%pymake.builtins touch',
|
||||
'.LIBPATTERNS': 'lib%.so lib%.a',
|
||||
'.PYMAKE': '1',
|
||||
}
|
||||
|
||||
"""
|
||||
Implicit variables; perhaps in the future this will also include some implicit
|
||||
rules, at least match-anything cancellation rules.
|
||||
"""
|
||||
|
||||
variables = {
|
||||
'RM': '%pymake.builtins rm -f',
|
||||
'SLEEP': '%pymake.builtins sleep',
|
||||
'TOUCH': '%pymake.builtins touch',
|
||||
'.LIBPATTERNS': 'lib%.so lib%.a',
|
||||
'.PYMAKE': '1',
|
||||
}
|
||||
|
||||
|
|
454
build/upload.py
454
build/upload.py
|
@ -1,227 +1,227 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# The Mozilla Foundation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2008
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Ted Mielczarek <ted.mielczarek@gmail.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
#
|
||||
# When run directly, this script expects the following environment variables
|
||||
# to be set:
|
||||
# UPLOAD_HOST : host to upload files to
|
||||
# UPLOAD_USER : username on that host
|
||||
# UPLOAD_PATH : path on that host to put the files in
|
||||
#
|
||||
# And will use the following optional environment variables if set:
|
||||
# UPLOAD_SSH_KEY : path to a ssh private key to use
|
||||
# UPLOAD_PORT : port to use for ssh
|
||||
# POST_UPLOAD_CMD: a commandline to run on the remote host after uploading.
|
||||
# UPLOAD_PATH and the full paths of all files uploaded will
|
||||
# be appended to the commandline.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import sys, os
|
||||
from optparse import OptionParser
|
||||
from subprocess import Popen, PIPE
|
||||
from util import check_call
|
||||
|
||||
def RequireEnvironmentVariable(v):
|
||||
"""Return the value of the environment variable named v, or print
|
||||
an error and exit if it's unset (or empty)."""
|
||||
if not v in os.environ or os.environ[v] == "":
|
||||
print "Error: required environment variable %s not set" % v
|
||||
sys.exit(1)
|
||||
return os.environ[v]
|
||||
|
||||
def OptionalEnvironmentVariable(v):
|
||||
"""Return the value of the environment variable named v, or None
|
||||
if it's unset (or empty)."""
|
||||
if v in os.environ and os.environ[v] != "":
|
||||
return os.environ[v]
|
||||
return None
|
||||
|
||||
def FixupMsysPath(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' in os.environ and os.environ['OSTYPE'] == 'msys':
|
||||
# sort of awful, find out where our shell is (should be in msys/bin)
|
||||
# and strip the first part of that path out of the other path
|
||||
if 'SHELL' in os.environ:
|
||||
sh = os.environ['SHELL']
|
||||
msys = sh[:sh.find('/bin')]
|
||||
if path.startswith(msys):
|
||||
path = path[len(msys):]
|
||||
return path
|
||||
|
||||
def WindowsPathToMsysPath(path):
|
||||
"""Translate a Windows pathname to an MSYS pathname.
|
||||
Necessary because we call out to ssh/scp, which are MSYS binaries
|
||||
and expect MSYS paths."""
|
||||
if sys.platform != 'win32':
|
||||
return path
|
||||
(drive, path) = os.path.splitdrive(os.path.abspath(path))
|
||||
return "/" + drive[0] + path.replace('\\','/')
|
||||
|
||||
def AppendOptionalArgsToSSHCommandline(cmdline, port, ssh_key):
|
||||
"""Given optional port and ssh key values, append valid OpenSSH
|
||||
commandline arguments to the list cmdline if the values are not None."""
|
||||
if port is not None:
|
||||
cmdline.append("-P%d" % port)
|
||||
if ssh_key is not None:
|
||||
# Don't interpret ~ paths - ssh can handle that on its own
|
||||
if not ssh_key.startswith('~'):
|
||||
ssh_key = WindowsPathToMsysPath(ssh_key)
|
||||
cmdline.extend(["-o", "IdentityFile=%s" % ssh_key])
|
||||
|
||||
def DoSSHCommand(command, user, host, port=None, ssh_key=None):
|
||||
"""Execute command on user@host using ssh. Optionally use
|
||||
port and ssh_key, if provided."""
|
||||
cmdline = ["ssh"]
|
||||
AppendOptionalArgsToSSHCommandline(cmdline, port, ssh_key)
|
||||
cmdline.extend(["%s@%s" % (user, host), command])
|
||||
cmd = Popen(cmdline, stdout=PIPE)
|
||||
retcode = cmd.wait()
|
||||
if retcode != 0:
|
||||
raise Exception("Command %s returned non-zero exit code: %i" % \
|
||||
(cmdline, retcode))
|
||||
return cmd.stdout.read().strip()
|
||||
|
||||
def DoSCPFile(file, remote_path, user, host, port=None, ssh_key=None):
|
||||
"""Upload file to user@host:remote_path using scp. Optionally use
|
||||
port and ssh_key, if provided."""
|
||||
cmdline = ["scp"]
|
||||
AppendOptionalArgsToSSHCommandline(cmdline, port, ssh_key)
|
||||
cmdline.extend([WindowsPathToMsysPath(file),
|
||||
"%s@%s:%s" % (user, host, remote_path)])
|
||||
check_call(cmdline)
|
||||
|
||||
def GetRemotePath(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."""
|
||||
if base_path is None or not local_file.startswith(base_path):
|
||||
return path
|
||||
dir = os.path.dirname(local_file)
|
||||
# strip base_path + extra slash and make it unixy
|
||||
dir = dir[len(base_path)+1:].replace('\\','/')
|
||||
return path + dir
|
||||
|
||||
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):
|
||||
"""Upload each file in the list files to user@host:path. Optionally pass
|
||||
port and ssh_key to the ssh commands. If base_path is not None, upload
|
||||
files including their path relative to base_path. If upload_to_temp_dir is
|
||||
True files will be uploaded to a temporary directory on the remote server.
|
||||
Generally, you should have a post upload command specified in these cases
|
||||
that can move them around to their correct location(s).
|
||||
If post_upload_command is not None, execute that command on the remote host
|
||||
after uploading all files, passing it the upload path, and the full paths to
|
||||
all files uploaded.
|
||||
If verbose is True, print status updates while working."""
|
||||
if upload_to_temp_dir:
|
||||
path = DoSSHCommand("mktemp -d", user, host, port=port, ssh_key=ssh_key)
|
||||
if not path.endswith("/"):
|
||||
path += "/"
|
||||
if base_path is not None:
|
||||
base_path = os.path.abspath(base_path)
|
||||
remote_files = []
|
||||
try:
|
||||
for file in files:
|
||||
file = os.path.abspath(file)
|
||||
if not os.path.isfile(file):
|
||||
raise IOError("File not found: %s" % file)
|
||||
# first ensure that path exists remotely
|
||||
remote_path = GetRemotePath(path, file, base_path)
|
||||
DoSSHCommand("mkdir -p " + remote_path, user, host, port=port, ssh_key=ssh_key)
|
||||
if verbose:
|
||||
print "Uploading " + file
|
||||
DoSCPFile(file, remote_path, user, host, port=port, ssh_key=ssh_key)
|
||||
remote_files.append(remote_path + '/' + os.path.basename(file))
|
||||
if post_upload_command is not None:
|
||||
if verbose:
|
||||
print "Running post-upload command: " + post_upload_command
|
||||
file_list = '"' + '" "'.join(remote_files) + '"'
|
||||
DoSSHCommand('%s "%s" %s' % (post_upload_command, path, file_list), user, host, port=port, ssh_key=ssh_key)
|
||||
finally:
|
||||
if upload_to_temp_dir:
|
||||
DoSSHCommand("rm -rf %s" % path, user, host, port=port,
|
||||
ssh_key=ssh_key)
|
||||
if verbose:
|
||||
print "Upload complete"
|
||||
|
||||
if __name__ == '__main__':
|
||||
host = RequireEnvironmentVariable('UPLOAD_HOST')
|
||||
user = RequireEnvironmentVariable('UPLOAD_USER')
|
||||
path = OptionalEnvironmentVariable('UPLOAD_PATH')
|
||||
upload_to_temp_dir = OptionalEnvironmentVariable('UPLOAD_TO_TEMP')
|
||||
port = OptionalEnvironmentVariable('UPLOAD_PORT')
|
||||
if port is not None:
|
||||
port = int(port)
|
||||
key = OptionalEnvironmentVariable('UPLOAD_SSH_KEY')
|
||||
post_upload_command = OptionalEnvironmentVariable('POST_UPLOAD_CMD')
|
||||
if (not path and not upload_to_temp_dir) or (path and upload_to_temp_dir):
|
||||
print "One (and only one of UPLOAD_PATH or UPLOAD_TO_TEMP must be " + \
|
||||
"defined."
|
||||
sys.exit(1)
|
||||
if sys.platform == 'win32':
|
||||
if path is not None:
|
||||
path = FixupMsysPath(path)
|
||||
if post_upload_command is not None:
|
||||
post_upload_command = FixupMsysPath(post_upload_command)
|
||||
|
||||
parser = OptionParser(usage="usage: %prog [options] <files>")
|
||||
parser.add_option("-b", "--base-path",
|
||||
action="store", dest="base_path",
|
||||
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()
|
||||
if len(args) < 1:
|
||||
print "You must specify at least one file to upload"
|
||||
sys.exit(1)
|
||||
try:
|
||||
UploadFiles(user, host, path, args, base_path=options.base_path,
|
||||
port=port, ssh_key=key, upload_to_temp_dir=upload_to_temp_dir,
|
||||
post_upload_command=post_upload_command,
|
||||
verbose=True)
|
||||
except IOError, (strerror):
|
||||
print strerror
|
||||
sys.exit(1)
|
||||
except Exception, (err):
|
||||
print err
|
||||
sys.exit(2)
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# The Mozilla Foundation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2008
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Ted Mielczarek <ted.mielczarek@gmail.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
#
|
||||
# When run directly, this script expects the following environment variables
|
||||
# to be set:
|
||||
# UPLOAD_HOST : host to upload files to
|
||||
# UPLOAD_USER : username on that host
|
||||
# UPLOAD_PATH : path on that host to put the files in
|
||||
#
|
||||
# And will use the following optional environment variables if set:
|
||||
# UPLOAD_SSH_KEY : path to a ssh private key to use
|
||||
# UPLOAD_PORT : port to use for ssh
|
||||
# POST_UPLOAD_CMD: a commandline to run on the remote host after uploading.
|
||||
# UPLOAD_PATH and the full paths of all files uploaded will
|
||||
# be appended to the commandline.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import sys, os
|
||||
from optparse import OptionParser
|
||||
from subprocess import Popen, PIPE
|
||||
from util import check_call
|
||||
|
||||
def RequireEnvironmentVariable(v):
|
||||
"""Return the value of the environment variable named v, or print
|
||||
an error and exit if it's unset (or empty)."""
|
||||
if not v in os.environ or os.environ[v] == "":
|
||||
print "Error: required environment variable %s not set" % v
|
||||
sys.exit(1)
|
||||
return os.environ[v]
|
||||
|
||||
def OptionalEnvironmentVariable(v):
|
||||
"""Return the value of the environment variable named v, or None
|
||||
if it's unset (or empty)."""
|
||||
if v in os.environ and os.environ[v] != "":
|
||||
return os.environ[v]
|
||||
return None
|
||||
|
||||
def FixupMsysPath(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' in os.environ and os.environ['OSTYPE'] == 'msys':
|
||||
# sort of awful, find out where our shell is (should be in msys/bin)
|
||||
# and strip the first part of that path out of the other path
|
||||
if 'SHELL' in os.environ:
|
||||
sh = os.environ['SHELL']
|
||||
msys = sh[:sh.find('/bin')]
|
||||
if path.startswith(msys):
|
||||
path = path[len(msys):]
|
||||
return path
|
||||
|
||||
def WindowsPathToMsysPath(path):
|
||||
"""Translate a Windows pathname to an MSYS pathname.
|
||||
Necessary because we call out to ssh/scp, which are MSYS binaries
|
||||
and expect MSYS paths."""
|
||||
if sys.platform != 'win32':
|
||||
return path
|
||||
(drive, path) = os.path.splitdrive(os.path.abspath(path))
|
||||
return "/" + drive[0] + path.replace('\\','/')
|
||||
|
||||
def AppendOptionalArgsToSSHCommandline(cmdline, port, ssh_key):
|
||||
"""Given optional port and ssh key values, append valid OpenSSH
|
||||
commandline arguments to the list cmdline if the values are not None."""
|
||||
if port is not None:
|
||||
cmdline.append("-P%d" % port)
|
||||
if ssh_key is not None:
|
||||
# Don't interpret ~ paths - ssh can handle that on its own
|
||||
if not ssh_key.startswith('~'):
|
||||
ssh_key = WindowsPathToMsysPath(ssh_key)
|
||||
cmdline.extend(["-o", "IdentityFile=%s" % ssh_key])
|
||||
|
||||
def DoSSHCommand(command, user, host, port=None, ssh_key=None):
|
||||
"""Execute command on user@host using ssh. Optionally use
|
||||
port and ssh_key, if provided."""
|
||||
cmdline = ["ssh"]
|
||||
AppendOptionalArgsToSSHCommandline(cmdline, port, ssh_key)
|
||||
cmdline.extend(["%s@%s" % (user, host), command])
|
||||
cmd = Popen(cmdline, stdout=PIPE)
|
||||
retcode = cmd.wait()
|
||||
if retcode != 0:
|
||||
raise Exception("Command %s returned non-zero exit code: %i" % \
|
||||
(cmdline, retcode))
|
||||
return cmd.stdout.read().strip()
|
||||
|
||||
def DoSCPFile(file, remote_path, user, host, port=None, ssh_key=None):
|
||||
"""Upload file to user@host:remote_path using scp. Optionally use
|
||||
port and ssh_key, if provided."""
|
||||
cmdline = ["scp"]
|
||||
AppendOptionalArgsToSSHCommandline(cmdline, port, ssh_key)
|
||||
cmdline.extend([WindowsPathToMsysPath(file),
|
||||
"%s@%s:%s" % (user, host, remote_path)])
|
||||
check_call(cmdline)
|
||||
|
||||
def GetRemotePath(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."""
|
||||
if base_path is None or not local_file.startswith(base_path):
|
||||
return path
|
||||
dir = os.path.dirname(local_file)
|
||||
# strip base_path + extra slash and make it unixy
|
||||
dir = dir[len(base_path)+1:].replace('\\','/')
|
||||
return path + dir
|
||||
|
||||
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):
|
||||
"""Upload each file in the list files to user@host:path. Optionally pass
|
||||
port and ssh_key to the ssh commands. If base_path is not None, upload
|
||||
files including their path relative to base_path. If upload_to_temp_dir is
|
||||
True files will be uploaded to a temporary directory on the remote server.
|
||||
Generally, you should have a post upload command specified in these cases
|
||||
that can move them around to their correct location(s).
|
||||
If post_upload_command is not None, execute that command on the remote host
|
||||
after uploading all files, passing it the upload path, and the full paths to
|
||||
all files uploaded.
|
||||
If verbose is True, print status updates while working."""
|
||||
if upload_to_temp_dir:
|
||||
path = DoSSHCommand("mktemp -d", user, host, port=port, ssh_key=ssh_key)
|
||||
if not path.endswith("/"):
|
||||
path += "/"
|
||||
if base_path is not None:
|
||||
base_path = os.path.abspath(base_path)
|
||||
remote_files = []
|
||||
try:
|
||||
for file in files:
|
||||
file = os.path.abspath(file)
|
||||
if not os.path.isfile(file):
|
||||
raise IOError("File not found: %s" % file)
|
||||
# first ensure that path exists remotely
|
||||
remote_path = GetRemotePath(path, file, base_path)
|
||||
DoSSHCommand("mkdir -p " + remote_path, user, host, port=port, ssh_key=ssh_key)
|
||||
if verbose:
|
||||
print "Uploading " + file
|
||||
DoSCPFile(file, remote_path, user, host, port=port, ssh_key=ssh_key)
|
||||
remote_files.append(remote_path + '/' + os.path.basename(file))
|
||||
if post_upload_command is not None:
|
||||
if verbose:
|
||||
print "Running post-upload command: " + post_upload_command
|
||||
file_list = '"' + '" "'.join(remote_files) + '"'
|
||||
DoSSHCommand('%s "%s" %s' % (post_upload_command, path, file_list), user, host, port=port, ssh_key=ssh_key)
|
||||
finally:
|
||||
if upload_to_temp_dir:
|
||||
DoSSHCommand("rm -rf %s" % path, user, host, port=port,
|
||||
ssh_key=ssh_key)
|
||||
if verbose:
|
||||
print "Upload complete"
|
||||
|
||||
if __name__ == '__main__':
|
||||
host = RequireEnvironmentVariable('UPLOAD_HOST')
|
||||
user = RequireEnvironmentVariable('UPLOAD_USER')
|
||||
path = OptionalEnvironmentVariable('UPLOAD_PATH')
|
||||
upload_to_temp_dir = OptionalEnvironmentVariable('UPLOAD_TO_TEMP')
|
||||
port = OptionalEnvironmentVariable('UPLOAD_PORT')
|
||||
if port is not None:
|
||||
port = int(port)
|
||||
key = OptionalEnvironmentVariable('UPLOAD_SSH_KEY')
|
||||
post_upload_command = OptionalEnvironmentVariable('POST_UPLOAD_CMD')
|
||||
if (not path and not upload_to_temp_dir) or (path and upload_to_temp_dir):
|
||||
print "One (and only one of UPLOAD_PATH or UPLOAD_TO_TEMP must be " + \
|
||||
"defined."
|
||||
sys.exit(1)
|
||||
if sys.platform == 'win32':
|
||||
if path is not None:
|
||||
path = FixupMsysPath(path)
|
||||
if post_upload_command is not None:
|
||||
post_upload_command = FixupMsysPath(post_upload_command)
|
||||
|
||||
parser = OptionParser(usage="usage: %prog [options] <files>")
|
||||
parser.add_option("-b", "--base-path",
|
||||
action="store", dest="base_path",
|
||||
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()
|
||||
if len(args) < 1:
|
||||
print "You must specify at least one file to upload"
|
||||
sys.exit(1)
|
||||
try:
|
||||
UploadFiles(user, host, path, args, base_path=options.base_path,
|
||||
port=port, ssh_key=key, upload_to_temp_dir=upload_to_temp_dir,
|
||||
post_upload_command=post_upload_command,
|
||||
verbose=True)
|
||||
except IOError, (strerror):
|
||||
print strerror
|
||||
sys.exit(1)
|
||||
except Exception, (err):
|
||||
print err
|
||||
sys.exit(2)
|
||||
|
|
100
build/util.py
100
build/util.py
|
@ -1,50 +1,50 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# The Mozilla Foundation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2008
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Ted Mielczarek <ted.mielczarek@gmail.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
try:
|
||||
from subprocess import check_call
|
||||
except ImportError:
|
||||
import subprocess
|
||||
def check_call(*popenargs, **kwargs):
|
||||
retcode = subprocess.call(*popenargs, **kwargs)
|
||||
if retcode:
|
||||
cmd = kwargs.get("args")
|
||||
if cmd is None:
|
||||
cmd = popenargs[0]
|
||||
raise Exception("Command '%s' returned non-zero exit status %i" % (cmd, retcode))
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# The Mozilla Foundation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2008
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Ted Mielczarek <ted.mielczarek@gmail.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
try:
|
||||
from subprocess import check_call
|
||||
except ImportError:
|
||||
import subprocess
|
||||
def check_call(*popenargs, **kwargs):
|
||||
retcode = subprocess.call(*popenargs, **kwargs)
|
||||
if retcode:
|
||||
cmd = kwargs.get("args")
|
||||
if cmd is None:
|
||||
cmd = popenargs[0]
|
||||
raise Exception("Command '%s' returned non-zero exit status %i" % (cmd, retcode))
|
||||
|
|
|
@ -1,96 +1,96 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is cl.py: a python wrapper for cl to automatically generate
|
||||
# dependency information.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Kyle Huey <me@kylehuey.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
import os, os.path
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
CL_INCLUDES_PREFIX = os.environ.get("CL_INCLUDES_PREFIX", "Note: including file:")
|
||||
|
||||
def InvokeClWithDependencyGeneration(cmdline):
|
||||
target = ""
|
||||
# Figure out what the target is
|
||||
for arg in cmdline:
|
||||
if arg.startswith("-Fo"):
|
||||
target = arg[3:]
|
||||
break
|
||||
|
||||
if target == None:
|
||||
print >>sys.stderr, "No target set" and sys.exit(1)
|
||||
|
||||
# The deps target lives here
|
||||
depstarget = os.path.basename(target) + ".pp"
|
||||
|
||||
cmdline += ['-showIncludes']
|
||||
cl = subprocess.Popen(cmdline, stdout=subprocess.PIPE)
|
||||
|
||||
deps = set()
|
||||
for line in cl.stdout:
|
||||
# cl -showIncludes prefixes every header with "Note: including file:"
|
||||
# and an indentation corresponding to the depth (which we don't need)
|
||||
if line.startswith(CL_INCLUDES_PREFIX):
|
||||
dep = line[len(CL_INCLUDES_PREFIX):].strip()
|
||||
# We can't handle pathes with spaces properly in mddepend.pl, but
|
||||
# we can assume that anything in a path with spaces is a system
|
||||
# header and throw it away.
|
||||
if dep.find(' ') == -1:
|
||||
deps.add(dep)
|
||||
else:
|
||||
sys.stdout.write(line) # Make sure we preserve the relevant output
|
||||
# from cl
|
||||
|
||||
ret = cl.wait()
|
||||
if ret != 0 or target == "":
|
||||
sys.exit(ret)
|
||||
|
||||
depsdir = os.path.normpath(os.path.join(os.path.dirname(target), ".deps"))
|
||||
depstarget = os.path.join(depsdir, depstarget)
|
||||
if not os.path.isdir(depsdir):
|
||||
try:
|
||||
os.makedirs(depsdir)
|
||||
except OSError:
|
||||
pass # This suppresses the error we get when the dir exists, at the
|
||||
# cost of masking failure to create the directory. We'll just
|
||||
# die on the next line though, so it's not that much of a loss.
|
||||
|
||||
f = open(depstarget, "w")
|
||||
for dep in sorted(deps):
|
||||
print >>f, "%s: %s" % (target, dep)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is cl.py: a python wrapper for cl to automatically generate
|
||||
# dependency information.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Kyle Huey <me@kylehuey.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
import os, os.path
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
CL_INCLUDES_PREFIX = os.environ.get("CL_INCLUDES_PREFIX", "Note: including file:")
|
||||
|
||||
def InvokeClWithDependencyGeneration(cmdline):
|
||||
target = ""
|
||||
# Figure out what the target is
|
||||
for arg in cmdline:
|
||||
if arg.startswith("-Fo"):
|
||||
target = arg[3:]
|
||||
break
|
||||
|
||||
if target == None:
|
||||
print >>sys.stderr, "No target set" and sys.exit(1)
|
||||
|
||||
# The deps target lives here
|
||||
depstarget = os.path.basename(target) + ".pp"
|
||||
|
||||
cmdline += ['-showIncludes']
|
||||
cl = subprocess.Popen(cmdline, stdout=subprocess.PIPE)
|
||||
|
||||
deps = set()
|
||||
for line in cl.stdout:
|
||||
# cl -showIncludes prefixes every header with "Note: including file:"
|
||||
# and an indentation corresponding to the depth (which we don't need)
|
||||
if line.startswith(CL_INCLUDES_PREFIX):
|
||||
dep = line[len(CL_INCLUDES_PREFIX):].strip()
|
||||
# We can't handle pathes with spaces properly in mddepend.pl, but
|
||||
# we can assume that anything in a path with spaces is a system
|
||||
# header and throw it away.
|
||||
if dep.find(' ') == -1:
|
||||
deps.add(dep)
|
||||
else:
|
||||
sys.stdout.write(line) # Make sure we preserve the relevant output
|
||||
# from cl
|
||||
|
||||
ret = cl.wait()
|
||||
if ret != 0 or target == "":
|
||||
sys.exit(ret)
|
||||
|
||||
depsdir = os.path.normpath(os.path.join(os.path.dirname(target), ".deps"))
|
||||
depstarget = os.path.join(depsdir, depstarget)
|
||||
if not os.path.isdir(depsdir):
|
||||
try:
|
||||
os.makedirs(depsdir)
|
||||
except OSError:
|
||||
pass # This suppresses the error we get when the dir exists, at the
|
||||
# cost of masking failure to create the directory. We'll just
|
||||
# die on the next line though, so it's not that much of a loss.
|
||||
|
||||
f = open(depstarget, "w")
|
||||
for dep in sorted(deps):
|
||||
print >>f, "%s: %s" % (target, dep)
|
||||
|
||||
if __name__ == "__main__":
|
||||
InvokeClWithDependencyGeneration(sys.argv[1:])
|
||||
|
|
|
@ -1,198 +1,198 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Mozilla build system
|
||||
#
|
||||
# The Initial Developer of the Original Code is Mozilla.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2009
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Armen Zambrano Gasparnian <armenzg@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
"""
|
||||
This script generates the complete snippet for a given locale or en-US
|
||||
Most of the parameters received are to generate the MAR's download URL
|
||||
and determine the MAR's filename
|
||||
"""
|
||||
import sys, os, platform, sha
|
||||
from optparse import OptionParser
|
||||
from ConfigParser import ConfigParser
|
||||
from stat import ST_SIZE
|
||||
|
||||
def main():
|
||||
error = False
|
||||
parser = OptionParser(
|
||||
usage="%prog [options]")
|
||||
parser.add_option("--mar-path",
|
||||
action="store",
|
||||
dest="marPath",
|
||||
help="[Required] Specify the absolute path where the MAR file is found.")
|
||||
parser.add_option("--application-ini-file",
|
||||
action="store",
|
||||
dest="applicationIniFile",
|
||||
help="[Required] Specify the absolute path to the application.ini file.")
|
||||
parser.add_option("-l",
|
||||
"--locale",
|
||||
action="store",
|
||||
dest="locale",
|
||||
help="[Required] Specify which locale we are generating the snippet for.")
|
||||
parser.add_option("-p",
|
||||
"--product",
|
||||
action="store",
|
||||
dest="product",
|
||||
help="[Required] This option is used to generate the URL to download the MAR file.")
|
||||
parser.add_option("--platform",
|
||||
action="store",
|
||||
dest="platform",
|
||||
help="[Required] This option is used to indicate which target platform.")
|
||||
parser.add_option("--branch",
|
||||
action="store",
|
||||
dest="branch",
|
||||
help="This option is used to indicate which branch name to use for FTP file names.")
|
||||
parser.add_option("--download-base-URL",
|
||||
action="store",
|
||||
dest="downloadBaseURL",
|
||||
help="This option indicates under which.")
|
||||
parser.add_option("-v",
|
||||
"--verbose",
|
||||
action="store_true",
|
||||
dest="verbose",
|
||||
default=False,
|
||||
help="This option increases the output of the script.")
|
||||
(options, args) = parser.parse_args()
|
||||
for req, msg in (('marPath', "the absolute path to the where the MAR file is"),
|
||||
('applicationIniFile', "the absolute path to the application.ini file."),
|
||||
('locale', "a locale."),
|
||||
('product', "specify a product."),
|
||||
('platform', "specify the platform.")):
|
||||
if not hasattr(options, req):
|
||||
parser.error('You must specify %s' % msg)
|
||||
|
||||
if not options.downloadBaseURL or options.downloadBaseURL == '':
|
||||
options.downloadBaseURL = 'http://ftp.mozilla.org/pub/mozilla.org/%s/nightly' % options.product
|
||||
|
||||
if not options.branch or options.branch == '':
|
||||
options.branch = None
|
||||
|
||||
snippet = generateSnippet(options.marPath,
|
||||
options.applicationIniFile,
|
||||
options.locale,
|
||||
options.downloadBaseURL,
|
||||
options.product,
|
||||
options.platform,
|
||||
options.branch)
|
||||
f = open(os.path.join(options.marPath, 'complete.update.snippet'), 'wb')
|
||||
f.write(snippet)
|
||||
f.close()
|
||||
|
||||
if options.verbose:
|
||||
# Show in our logs what the contents of the snippet are
|
||||
print snippet
|
||||
|
||||
def generateSnippet(abstDistDir, applicationIniFile, locale,
|
||||
downloadBaseURL, product, platform, branch):
|
||||
# Let's extract information from application.ini
|
||||
c = ConfigParser()
|
||||
try:
|
||||
c.readfp(open(applicationIniFile))
|
||||
except IOError, (stderror):
|
||||
sys.exit(stderror)
|
||||
buildid = c.get("App", "BuildID")
|
||||
appVersion = c.get("App", "Version")
|
||||
branchName = branch or c.get("App", "SourceRepository").split('/')[-1]
|
||||
|
||||
marFileName = '%s-%s.%s.%s.complete.mar' % (
|
||||
product,
|
||||
appVersion,
|
||||
locale,
|
||||
platform)
|
||||
# Let's determine the hash and the size of the MAR file
|
||||
# This function exits the script if the file does not exist
|
||||
(completeMarHash, completeMarSize) = getFileHashAndSize(
|
||||
os.path.join(abstDistDir, marFileName))
|
||||
# Construct the URL to where the MAR file will exist
|
||||
interfix = ''
|
||||
if locale == 'en-US':
|
||||
interfix = ''
|
||||
else:
|
||||
interfix = '-l10n'
|
||||
marDownloadURL = "%s/%s%s/%s" % (downloadBaseURL,
|
||||
datedDirPath(buildid, branchName),
|
||||
interfix,
|
||||
marFileName)
|
||||
|
||||
snippet = """complete
|
||||
%(marDownloadURL)s
|
||||
sha1
|
||||
%(completeMarHash)s
|
||||
%(completeMarSize)s
|
||||
%(buildid)s
|
||||
%(appVersion)s
|
||||
%(appVersion)s
|
||||
""" % dict( marDownloadURL=marDownloadURL,
|
||||
completeMarHash=completeMarHash,
|
||||
completeMarSize=completeMarSize,
|
||||
buildid=buildid,
|
||||
appVersion=appVersion)
|
||||
|
||||
return snippet
|
||||
|
||||
def getFileHashAndSize(filepath):
|
||||
sha1Hash = 'UNKNOWN'
|
||||
size = 'UNKNOWN'
|
||||
|
||||
try:
|
||||
# open in binary mode to make sure we get consistent results
|
||||
# across all platforms
|
||||
f = open(filepath, "rb")
|
||||
shaObj = sha.new(f.read())
|
||||
sha1Hash = shaObj.hexdigest()
|
||||
size = os.stat(filepath)[ST_SIZE]
|
||||
except IOError, (stderror):
|
||||
sys.exit(stderror)
|
||||
|
||||
return (sha1Hash, size)
|
||||
|
||||
def datedDirPath(buildid, milestone):
|
||||
"""
|
||||
Returns a string that will look like:
|
||||
2009/12/2009-12-31-09-mozilla-central
|
||||
"""
|
||||
year = buildid[0:4]
|
||||
month = buildid[4:6]
|
||||
day = buildid[6:8]
|
||||
hour = buildid[8:10]
|
||||
datedDir = "%s-%s-%s-%s-%s" % (year,
|
||||
month,
|
||||
day,
|
||||
hour,
|
||||
milestone)
|
||||
return "%s/%s/%s" % (year, month, datedDir)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Mozilla build system
|
||||
#
|
||||
# The Initial Developer of the Original Code is Mozilla.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2009
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Armen Zambrano Gasparnian <armenzg@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
"""
|
||||
This script generates the complete snippet for a given locale or en-US
|
||||
Most of the parameters received are to generate the MAR's download URL
|
||||
and determine the MAR's filename
|
||||
"""
|
||||
import sys, os, platform, sha
|
||||
from optparse import OptionParser
|
||||
from ConfigParser import ConfigParser
|
||||
from stat import ST_SIZE
|
||||
|
||||
def main():
|
||||
error = False
|
||||
parser = OptionParser(
|
||||
usage="%prog [options]")
|
||||
parser.add_option("--mar-path",
|
||||
action="store",
|
||||
dest="marPath",
|
||||
help="[Required] Specify the absolute path where the MAR file is found.")
|
||||
parser.add_option("--application-ini-file",
|
||||
action="store",
|
||||
dest="applicationIniFile",
|
||||
help="[Required] Specify the absolute path to the application.ini file.")
|
||||
parser.add_option("-l",
|
||||
"--locale",
|
||||
action="store",
|
||||
dest="locale",
|
||||
help="[Required] Specify which locale we are generating the snippet for.")
|
||||
parser.add_option("-p",
|
||||
"--product",
|
||||
action="store",
|
||||
dest="product",
|
||||
help="[Required] This option is used to generate the URL to download the MAR file.")
|
||||
parser.add_option("--platform",
|
||||
action="store",
|
||||
dest="platform",
|
||||
help="[Required] This option is used to indicate which target platform.")
|
||||
parser.add_option("--branch",
|
||||
action="store",
|
||||
dest="branch",
|
||||
help="This option is used to indicate which branch name to use for FTP file names.")
|
||||
parser.add_option("--download-base-URL",
|
||||
action="store",
|
||||
dest="downloadBaseURL",
|
||||
help="This option indicates under which.")
|
||||
parser.add_option("-v",
|
||||
"--verbose",
|
||||
action="store_true",
|
||||
dest="verbose",
|
||||
default=False,
|
||||
help="This option increases the output of the script.")
|
||||
(options, args) = parser.parse_args()
|
||||
for req, msg in (('marPath', "the absolute path to the where the MAR file is"),
|
||||
('applicationIniFile', "the absolute path to the application.ini file."),
|
||||
('locale', "a locale."),
|
||||
('product', "specify a product."),
|
||||
('platform', "specify the platform.")):
|
||||
if not hasattr(options, req):
|
||||
parser.error('You must specify %s' % msg)
|
||||
|
||||
if not options.downloadBaseURL or options.downloadBaseURL == '':
|
||||
options.downloadBaseURL = 'http://ftp.mozilla.org/pub/mozilla.org/%s/nightly' % options.product
|
||||
|
||||
if not options.branch or options.branch == '':
|
||||
options.branch = None
|
||||
|
||||
snippet = generateSnippet(options.marPath,
|
||||
options.applicationIniFile,
|
||||
options.locale,
|
||||
options.downloadBaseURL,
|
||||
options.product,
|
||||
options.platform,
|
||||
options.branch)
|
||||
f = open(os.path.join(options.marPath, 'complete.update.snippet'), 'wb')
|
||||
f.write(snippet)
|
||||
f.close()
|
||||
|
||||
if options.verbose:
|
||||
# Show in our logs what the contents of the snippet are
|
||||
print snippet
|
||||
|
||||
def generateSnippet(abstDistDir, applicationIniFile, locale,
|
||||
downloadBaseURL, product, platform, branch):
|
||||
# Let's extract information from application.ini
|
||||
c = ConfigParser()
|
||||
try:
|
||||
c.readfp(open(applicationIniFile))
|
||||
except IOError, (stderror):
|
||||
sys.exit(stderror)
|
||||
buildid = c.get("App", "BuildID")
|
||||
appVersion = c.get("App", "Version")
|
||||
branchName = branch or c.get("App", "SourceRepository").split('/')[-1]
|
||||
|
||||
marFileName = '%s-%s.%s.%s.complete.mar' % (
|
||||
product,
|
||||
appVersion,
|
||||
locale,
|
||||
platform)
|
||||
# Let's determine the hash and the size of the MAR file
|
||||
# This function exits the script if the file does not exist
|
||||
(completeMarHash, completeMarSize) = getFileHashAndSize(
|
||||
os.path.join(abstDistDir, marFileName))
|
||||
# Construct the URL to where the MAR file will exist
|
||||
interfix = ''
|
||||
if locale == 'en-US':
|
||||
interfix = ''
|
||||
else:
|
||||
interfix = '-l10n'
|
||||
marDownloadURL = "%s/%s%s/%s" % (downloadBaseURL,
|
||||
datedDirPath(buildid, branchName),
|
||||
interfix,
|
||||
marFileName)
|
||||
|
||||
snippet = """complete
|
||||
%(marDownloadURL)s
|
||||
sha1
|
||||
%(completeMarHash)s
|
||||
%(completeMarSize)s
|
||||
%(buildid)s
|
||||
%(appVersion)s
|
||||
%(appVersion)s
|
||||
""" % dict( marDownloadURL=marDownloadURL,
|
||||
completeMarHash=completeMarHash,
|
||||
completeMarSize=completeMarSize,
|
||||
buildid=buildid,
|
||||
appVersion=appVersion)
|
||||
|
||||
return snippet
|
||||
|
||||
def getFileHashAndSize(filepath):
|
||||
sha1Hash = 'UNKNOWN'
|
||||
size = 'UNKNOWN'
|
||||
|
||||
try:
|
||||
# open in binary mode to make sure we get consistent results
|
||||
# across all platforms
|
||||
f = open(filepath, "rb")
|
||||
shaObj = sha.new(f.read())
|
||||
sha1Hash = shaObj.hexdigest()
|
||||
size = os.stat(filepath)[ST_SIZE]
|
||||
except IOError, (stderror):
|
||||
sys.exit(stderror)
|
||||
|
||||
return (sha1Hash, size)
|
||||
|
||||
def datedDirPath(buildid, milestone):
|
||||
"""
|
||||
Returns a string that will look like:
|
||||
2009/12/2009-12-31-09-mozilla-central
|
||||
"""
|
||||
year = buildid[0:4]
|
||||
month = buildid[4:6]
|
||||
day = buildid[6:8]
|
||||
hour = buildid[8:10]
|
||||
datedDir = "%s-%s-%s-%s-%s" % (year,
|
||||
month,
|
||||
day,
|
||||
hour,
|
||||
milestone)
|
||||
return "%s/%s/%s" % (year, month, datedDir)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
Загрузка…
Ссылка в новой задаче