build/compare-mozconfig/compare-mozconfigs.py

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

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

mercurial