Bug 616810 Remove extraneous CRs r=khuey a=bsmedberg
authorNeil Rashbrook <neil@parkwaycc.co.uk>
Wed, 05 Jan 2011 23:46:04 +0000
changeset 60053 142d984cce4466a1d5b73babc4acb455067d14cb
parent 60052 f893909afc4a5b8a336bdefc75624a9f8bb6b861
child 60054 6f18c950b3b6388054a810531a447f7746d6f344
push idunknown
push userunknown
push dateunknown
reviewerskhuey, bsmedberg
bugs616810
milestone2.0b9pre
Bug 616810 Remove extraneous CRs r=khuey a=bsmedberg
build/cl.py
build/pymake/pymake/implicit.py
build/upload.py
build/util.py
js/src/build/cl.py
tools/update-packaging/generatesnippet.py
--- a/build/cl.py
+++ b/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:])
--- a/build/pymake/pymake/implicit.py
+++ b/build/pymake/pymake/implicit.py
@@ -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',
+    }
+
--- a/build/upload.py
+++ b/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)
--- a/build/util.py
+++ b/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))
--- a/js/src/build/cl.py
+++ b/js/src/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:])
--- a/tools/update-packaging/generatesnippet.py
+++ b/tools/update-packaging/generatesnippet.py
@@ -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()