Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | #!/usr/bin/python |
michael@0 | 2 | # This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | # License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
michael@0 | 5 | |
michael@0 | 6 | # originally from http://hg.mozilla.org/build/tools/file/4ab9c1a4e05b/scripts/release/compare-mozconfigs.py |
michael@0 | 7 | |
michael@0 | 8 | from __future__ import unicode_literals |
michael@0 | 9 | |
michael@0 | 10 | import logging |
michael@0 | 11 | import os |
michael@0 | 12 | import site |
michael@0 | 13 | import sys |
michael@0 | 14 | import urllib2 |
michael@0 | 15 | import difflib |
michael@0 | 16 | |
michael@0 | 17 | FAILURE_CODE = 1 |
michael@0 | 18 | SUCCESS_CODE = 0 |
michael@0 | 19 | |
michael@0 | 20 | log = logging.getLogger(__name__) |
michael@0 | 21 | |
michael@0 | 22 | class ConfigError(Exception): |
michael@0 | 23 | pass |
michael@0 | 24 | |
michael@0 | 25 | def make_hg_url(hgHost, repoPath, protocol='https', revision=None, |
michael@0 | 26 | filename=None): |
michael@0 | 27 | """construct a valid hg url from a base hg url (hg.mozilla.org), |
michael@0 | 28 | repoPath, revision and possible filename""" |
michael@0 | 29 | base = '%s://%s' % (protocol, hgHost) |
michael@0 | 30 | repo = '/'.join(p.strip('/') for p in [base, repoPath]) |
michael@0 | 31 | if not filename: |
michael@0 | 32 | if not revision: |
michael@0 | 33 | return repo |
michael@0 | 34 | else: |
michael@0 | 35 | return '/'.join([p.strip('/') for p in [repo, 'rev', revision]]) |
michael@0 | 36 | else: |
michael@0 | 37 | assert revision |
michael@0 | 38 | return '/'.join([p.strip('/') for p in [repo, 'raw-file', revision, |
michael@0 | 39 | filename]]) |
michael@0 | 40 | |
michael@0 | 41 | def readConfig(configfile, keys=[], required=[]): |
michael@0 | 42 | c = {} |
michael@0 | 43 | execfile(configfile, c) |
michael@0 | 44 | for k in keys: |
michael@0 | 45 | c = c[k] |
michael@0 | 46 | items = c.keys() |
michael@0 | 47 | err = False |
michael@0 | 48 | for key in required: |
michael@0 | 49 | if key not in items: |
michael@0 | 50 | err = True |
michael@0 | 51 | log.error("Required item `%s' missing from %s" % (key, c)) |
michael@0 | 52 | if err: |
michael@0 | 53 | raise ConfigError("Missing at least one item in config, see above") |
michael@0 | 54 | return c |
michael@0 | 55 | |
michael@0 | 56 | def verify_mozconfigs(mozconfig_pair, nightly_mozconfig_pair, platform, |
michael@0 | 57 | mozconfigWhitelist={}): |
michael@0 | 58 | """Compares mozconfig to nightly_mozconfig and compare to an optional |
michael@0 | 59 | whitelist of known differences. mozconfig_pair and nightly_mozconfig_pair |
michael@0 | 60 | are pairs containing the mozconfig's identifier and the list of lines in |
michael@0 | 61 | the mozconfig.""" |
michael@0 | 62 | |
michael@0 | 63 | # unpack the pairs to get the names, the names are just for |
michael@0 | 64 | # identifying the mozconfigs when logging the error messages |
michael@0 | 65 | mozconfig_name, mozconfig_lines = mozconfig_pair |
michael@0 | 66 | nightly_mozconfig_name, nightly_mozconfig_lines = nightly_mozconfig_pair |
michael@0 | 67 | |
michael@0 | 68 | missing_args = mozconfig_lines == [] or nightly_mozconfig_lines == [] |
michael@0 | 69 | if missing_args: |
michael@0 | 70 | log.info("Missing mozconfigs to compare for %s" % platform) |
michael@0 | 71 | return False |
michael@0 | 72 | |
michael@0 | 73 | success = True |
michael@0 | 74 | |
michael@0 | 75 | diff_instance = difflib.Differ() |
michael@0 | 76 | diff_result = diff_instance.compare(mozconfig_lines, nightly_mozconfig_lines) |
michael@0 | 77 | diff_list = list(diff_result) |
michael@0 | 78 | |
michael@0 | 79 | for line in diff_list: |
michael@0 | 80 | clean_line = line[1:].strip() |
michael@0 | 81 | if (line[0] == '-' or line[0] == '+') and len(clean_line) > 1: |
michael@0 | 82 | # skip comment lines |
michael@0 | 83 | if clean_line.startswith('#'): |
michael@0 | 84 | continue |
michael@0 | 85 | # compare to whitelist |
michael@0 | 86 | message = "" |
michael@0 | 87 | if line[0] == '-': |
michael@0 | 88 | if platform in mozconfigWhitelist.get('release', {}): |
michael@0 | 89 | if clean_line in \ |
michael@0 | 90 | mozconfigWhitelist['release'][platform]: |
michael@0 | 91 | continue |
michael@0 | 92 | elif line[0] == '+': |
michael@0 | 93 | if platform in mozconfigWhitelist.get('nightly', {}): |
michael@0 | 94 | if clean_line in \ |
michael@0 | 95 | mozconfigWhitelist['nightly'][platform]: |
michael@0 | 96 | continue |
michael@0 | 97 | else: |
michael@0 | 98 | log.warning("%s not in %s %s!" % ( |
michael@0 | 99 | clean_line, platform, |
michael@0 | 100 | mozconfigWhitelist['nightly'][platform])) |
michael@0 | 101 | else: |
michael@0 | 102 | log.error("Skipping line %s!" % line) |
michael@0 | 103 | continue |
michael@0 | 104 | message = "found in %s but not in %s: %s" |
michael@0 | 105 | if line[0] == '-': |
michael@0 | 106 | log.error(message % (mozconfig_name, |
michael@0 | 107 | nightly_mozconfig_name, clean_line)) |
michael@0 | 108 | else: |
michael@0 | 109 | log.error(message % (nightly_mozconfig_name, |
michael@0 | 110 | mozconfig_name, clean_line)) |
michael@0 | 111 | success = False |
michael@0 | 112 | return success |
michael@0 | 113 | |
michael@0 | 114 | def get_mozconfig(path, options): |
michael@0 | 115 | """Consumes a path and returns a list of lines from |
michael@0 | 116 | the mozconfig file. If download is required, the path |
michael@0 | 117 | specified should be relative to the root of the hg |
michael@0 | 118 | repository e.g browser/config/mozconfigs/linux32/nightly""" |
michael@0 | 119 | if options.no_download: |
michael@0 | 120 | return open(path, 'r').readlines() |
michael@0 | 121 | else: |
michael@0 | 122 | url = make_hg_url(options.hghost, options.branch, 'http', |
michael@0 | 123 | options.revision, path) |
michael@0 | 124 | return urllib2.urlopen(url).readlines() |
michael@0 | 125 | |
michael@0 | 126 | if __name__ == '__main__': |
michael@0 | 127 | from optparse import OptionParser |
michael@0 | 128 | parser = OptionParser() |
michael@0 | 129 | |
michael@0 | 130 | parser.add_option('--branch', dest='branch') |
michael@0 | 131 | parser.add_option('--revision', dest='revision') |
michael@0 | 132 | parser.add_option('--hghost', dest='hghost', default='hg.mozilla.org') |
michael@0 | 133 | parser.add_option('--whitelist', dest='whitelist') |
michael@0 | 134 | parser.add_option('--no-download', action='store_true', dest='no_download', |
michael@0 | 135 | default=False) |
michael@0 | 136 | options, args = parser.parse_args() |
michael@0 | 137 | |
michael@0 | 138 | logging.basicConfig(level=logging.INFO) |
michael@0 | 139 | |
michael@0 | 140 | missing_args = options.branch is None or options.revision is None |
michael@0 | 141 | if not options.no_download and missing_args: |
michael@0 | 142 | logging.error('Not enough arguments to download mozconfigs') |
michael@0 | 143 | sys.exit(FAILURE_CODE) |
michael@0 | 144 | |
michael@0 | 145 | mozconfig_whitelist = readConfig(options.whitelist, ['whitelist']) |
michael@0 | 146 | |
michael@0 | 147 | for arg in args: |
michael@0 | 148 | platform, mozconfig_path, nightly_mozconfig_path = arg.split(',') |
michael@0 | 149 | |
michael@0 | 150 | mozconfig_lines = get_mozconfig(mozconfig_path, options) |
michael@0 | 151 | nightly_mozconfig_lines = get_mozconfig(nightly_mozconfig_path, options) |
michael@0 | 152 | |
michael@0 | 153 | mozconfig_pair = (mozconfig_path, mozconfig_lines) |
michael@0 | 154 | nightly_mozconfig_pair = (nightly_mozconfig_path, |
michael@0 | 155 | nightly_mozconfig_lines) |
michael@0 | 156 | |
michael@0 | 157 | passed = verify_mozconfigs(mozconfig_pair, nightly_mozconfig_pair, |
michael@0 | 158 | platform, mozconfig_whitelist) |
michael@0 | 159 | |
michael@0 | 160 | if passed: |
michael@0 | 161 | logging.info('Mozconfig check passed!') |
michael@0 | 162 | else: |
michael@0 | 163 | logging.error('Mozconfig check failed!') |
michael@0 | 164 | sys.exit(FAILURE_CODE) |
michael@0 | 165 | sys.exit(SUCCESS_CODE) |