1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/update-packaging/generatesnippet.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,166 @@ 1.4 +# This Source Code Form is subject to the terms of the Mozilla Public 1.5 +# License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 +# file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.7 + 1.8 +""" 1.9 +This script generates the complete snippet for a given locale or en-US 1.10 +Most of the parameters received are to generate the MAR's download URL 1.11 +and determine the MAR's filename 1.12 +""" 1.13 +import sys, os, platform, sha 1.14 +from optparse import OptionParser 1.15 +from ConfigParser import ConfigParser 1.16 +from stat import ST_SIZE 1.17 + 1.18 +def main(): 1.19 + error = False 1.20 + parser = OptionParser( 1.21 + usage="%prog [options]") 1.22 + parser.add_option("--mar-path", 1.23 + action="store", 1.24 + dest="marPath", 1.25 + help="[Required] Specify the absolute path where the MAR file is found.") 1.26 + parser.add_option("--application-ini-file", 1.27 + action="store", 1.28 + dest="applicationIniFile", 1.29 + help="[Required] Specify the absolute path to the application.ini file.") 1.30 + parser.add_option("-l", 1.31 + "--locale", 1.32 + action="store", 1.33 + dest="locale", 1.34 + help="[Required] Specify which locale we are generating the snippet for.") 1.35 + parser.add_option("-p", 1.36 + "--product", 1.37 + action="store", 1.38 + dest="product", 1.39 + help="[Required] This option is used to generate the URL to download the MAR file.") 1.40 + parser.add_option("--platform", 1.41 + action="store", 1.42 + dest="platform", 1.43 + help="[Required] This option is used to indicate which target platform.") 1.44 + parser.add_option("--branch", 1.45 + action="store", 1.46 + dest="branch", 1.47 + help="This option is used to indicate which branch name to use for FTP file names.") 1.48 + parser.add_option("--download-base-URL", 1.49 + action="store", 1.50 + dest="downloadBaseURL", 1.51 + help="This option indicates under which.") 1.52 + parser.add_option("-v", 1.53 + "--verbose", 1.54 + action="store_true", 1.55 + dest="verbose", 1.56 + default=False, 1.57 + help="This option increases the output of the script.") 1.58 + (options, args) = parser.parse_args() 1.59 + for req, msg in (('marPath', "the absolute path to the where the MAR file is"), 1.60 + ('applicationIniFile', "the absolute path to the application.ini file."), 1.61 + ('locale', "a locale."), 1.62 + ('product', "specify a product."), 1.63 + ('platform', "specify the platform.")): 1.64 + if not hasattr(options, req): 1.65 + parser.error('You must specify %s' % msg) 1.66 + 1.67 + if not options.downloadBaseURL or options.downloadBaseURL == '': 1.68 + options.downloadBaseURL = 'http://ftp.mozilla.org/pub/mozilla.org/%s/nightly' % options.product 1.69 + 1.70 + if not options.branch or options.branch == '': 1.71 + options.branch = None 1.72 + 1.73 + snippet = generateSnippet(options.marPath, 1.74 + options.applicationIniFile, 1.75 + options.locale, 1.76 + options.downloadBaseURL, 1.77 + options.product, 1.78 + options.platform, 1.79 + options.branch) 1.80 + f = open(os.path.join(options.marPath, 'complete.update.snippet'), 'wb') 1.81 + f.write(snippet) 1.82 + f.close() 1.83 + 1.84 + if options.verbose: 1.85 + # Show in our logs what the contents of the snippet are 1.86 + print snippet 1.87 + 1.88 +def generateSnippet(abstDistDir, applicationIniFile, locale, 1.89 + downloadBaseURL, product, platform, branch): 1.90 + # Let's extract information from application.ini 1.91 + c = ConfigParser() 1.92 + try: 1.93 + c.readfp(open(applicationIniFile)) 1.94 + except IOError, (stderror): 1.95 + sys.exit(stderror) 1.96 + buildid = c.get("App", "BuildID") 1.97 + appVersion = c.get("App", "Version") 1.98 + branchName = branch or c.get("App", "SourceRepository").split('/')[-1] 1.99 + 1.100 + marFileName = '%s-%s.%s.%s.complete.mar' % ( 1.101 + product, 1.102 + appVersion, 1.103 + locale, 1.104 + platform) 1.105 + # Let's determine the hash and the size of the MAR file 1.106 + # This function exits the script if the file does not exist 1.107 + (completeMarHash, completeMarSize) = getFileHashAndSize( 1.108 + os.path.join(abstDistDir, marFileName)) 1.109 + # Construct the URL to where the MAR file will exist 1.110 + interfix = '' 1.111 + if locale == 'en-US': 1.112 + interfix = '' 1.113 + else: 1.114 + interfix = '-l10n' 1.115 + marDownloadURL = "%s/%s%s/%s" % (downloadBaseURL, 1.116 + datedDirPath(buildid, branchName), 1.117 + interfix, 1.118 + marFileName) 1.119 + 1.120 + snippet = """complete 1.121 +%(marDownloadURL)s 1.122 +sha1 1.123 +%(completeMarHash)s 1.124 +%(completeMarSize)s 1.125 +%(buildid)s 1.126 +%(appVersion)s 1.127 +%(appVersion)s 1.128 +""" % dict( marDownloadURL=marDownloadURL, 1.129 + completeMarHash=completeMarHash, 1.130 + completeMarSize=completeMarSize, 1.131 + buildid=buildid, 1.132 + appVersion=appVersion) 1.133 + 1.134 + return snippet 1.135 + 1.136 +def getFileHashAndSize(filepath): 1.137 + sha1Hash = 'UNKNOWN' 1.138 + size = 'UNKNOWN' 1.139 + 1.140 + try: 1.141 + # open in binary mode to make sure we get consistent results 1.142 + # across all platforms 1.143 + f = open(filepath, "rb") 1.144 + shaObj = sha.new(f.read()) 1.145 + sha1Hash = shaObj.hexdigest() 1.146 + size = os.stat(filepath)[ST_SIZE] 1.147 + except IOError, (stderror): 1.148 + sys.exit(stderror) 1.149 + 1.150 + return (sha1Hash, size) 1.151 + 1.152 +def datedDirPath(buildid, milestone): 1.153 + """ 1.154 + Returns a string that will look like: 1.155 + 2009/12/2009-12-31-09-mozilla-central 1.156 + """ 1.157 + year = buildid[0:4] 1.158 + month = buildid[4:6] 1.159 + day = buildid[6:8] 1.160 + hour = buildid[8:10] 1.161 + datedDir = "%s-%s-%s-%s-%s" % (year, 1.162 + month, 1.163 + day, 1.164 + hour, 1.165 + milestone) 1.166 + return "%s/%s/%s" % (year, month, datedDir) 1.167 + 1.168 +if __name__ == '__main__': 1.169 + main()