1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/mercurial/hgsetup/config.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,159 @@ 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 +from __future__ import unicode_literals 1.9 + 1.10 +from configobj import ConfigObj 1.11 +import re 1.12 +import os 1.13 + 1.14 + 1.15 +HOST_FINGERPRINTS = { 1.16 + 'bitbucket.org': '45:ad:ae:1a:cf:0e:73:47:06:07:e0:88:f5:cc:10:e5:fa:1c:f7:99', 1.17 + 'bugzilla.mozilla.org': '47:13:a2:14:0c:46:45:53:12:0d:e5:36:16:a5:60:26:3e:da:3a:60', 1.18 + 'hg.mozilla.org': 'af:27:b9:34:47:4e:e5:98:01:f6:83:2b:51:c9:aa:d8:df:fb:1a:27', 1.19 +} 1.20 + 1.21 + 1.22 +class MercurialConfig(object): 1.23 + """Interface for manipulating a Mercurial config file.""" 1.24 + 1.25 + def __init__(self, infiles=None): 1.26 + """Create a new instance, optionally from an existing hgrc file.""" 1.27 + 1.28 + if infiles: 1.29 + # If multiple files were specified, figure out which file we're using: 1.30 + if len(infiles) > 1: 1.31 + picky_infiles = filter(os.path.isfile, infiles) 1.32 + if picky_infiles: 1.33 + picky_infiles = [(os.path.getsize(path), path) for path in picky_infiles] 1.34 + infiles = [max(picky_infiles)[1]] 1.35 + 1.36 + infile = infiles[0] 1.37 + self.config_path = infile 1.38 + else: 1.39 + infile = None 1.40 + 1.41 + # write_empty_values is necessary to prevent built-in extensions (which 1.42 + # have no value) from being dropped on write. 1.43 + # list_values aren't needed by Mercurial and disabling them prevents 1.44 + # quotes from being added. 1.45 + self._c = ConfigObj(infile=infile, encoding='utf-8', 1.46 + write_empty_values=True, list_values=False) 1.47 + 1.48 + @property 1.49 + def config(self): 1.50 + return self._c 1.51 + 1.52 + @property 1.53 + def extensions(self): 1.54 + """Returns the set of currently enabled extensions (by name).""" 1.55 + return set(self._c.get('extensions', {}).keys()) 1.56 + 1.57 + def write(self, fh): 1.58 + return self._c.write(fh) 1.59 + 1.60 + def have_valid_username(self): 1.61 + if 'ui' not in self._c: 1.62 + return False 1.63 + 1.64 + if 'username' not in self._c['ui']: 1.65 + return False 1.66 + 1.67 + # TODO perform actual validation here. 1.68 + 1.69 + return True 1.70 + 1.71 + def add_mozilla_host_fingerprints(self): 1.72 + """Add host fingerprints so SSL connections don't warn.""" 1.73 + if 'hostfingerprints' not in self._c: 1.74 + self._c['hostfingerprints'] = {} 1.75 + 1.76 + for k, v in HOST_FINGERPRINTS.items(): 1.77 + self._c['hostfingerprints'][k] = v 1.78 + 1.79 + def set_username(self, name, email): 1.80 + """Set the username to use for commits. 1.81 + 1.82 + The username consists of a name (typically <firstname> <lastname>) and 1.83 + a well-formed e-mail address. 1.84 + """ 1.85 + if 'ui' not in self._c: 1.86 + self._c['ui'] = {} 1.87 + 1.88 + username = '%s <%s>' % (name, email) 1.89 + 1.90 + self._c['ui']['username'] = username.strip() 1.91 + 1.92 + def activate_extension(self, name, path=None): 1.93 + """Activate an extension. 1.94 + 1.95 + An extension is defined by its name (in the config) and a filesystem 1.96 + path). For built-in extensions, an empty path is specified. 1.97 + """ 1.98 + if not path: 1.99 + path = '' 1.100 + 1.101 + if 'extensions' not in self._c: 1.102 + self._c['extensions'] = {} 1.103 + 1.104 + self._c['extensions'][name] = path 1.105 + 1.106 + def have_recommended_diff_settings(self): 1.107 + if 'diff' not in self._c: 1.108 + return False 1.109 + 1.110 + old = dict(self._c['diff']) 1.111 + try: 1.112 + self.ensure_recommended_diff_settings() 1.113 + finally: 1.114 + self._c['diff'].update(old) 1.115 + 1.116 + return self._c['diff'] == old 1.117 + 1.118 + def ensure_recommended_diff_settings(self): 1.119 + if 'diff' not in self._c: 1.120 + self._c['diff'] = {} 1.121 + 1.122 + d = self._c['diff'] 1.123 + d['git'] = 1 1.124 + d['showfunc'] = 1 1.125 + d['unified'] = 8 1.126 + 1.127 + def have_mqext_autocommit_mq(self): 1.128 + if 'mqext' not in self._c: 1.129 + return False 1.130 + v = self._c['mqext'].get('mqcommit') 1.131 + return v == 'auto' or v == 'yes' 1.132 + 1.133 + def ensure_mqext_autocommit_mq(self): 1.134 + if self.have_mqext_autocommit_mq(): 1.135 + return 1.136 + if 'mqext' not in self._c: 1.137 + self._c['mqext'] = {} 1.138 + self._c['mqext']['mqcommit'] = 'auto' 1.139 + 1.140 + def have_qnew_currentuser_default(self): 1.141 + if 'defaults' not in self._c: 1.142 + return False 1.143 + d = self._c['defaults'] 1.144 + if 'qnew' not in d: 1.145 + return False 1.146 + argv = d['qnew'].split(' ') 1.147 + for arg in argv: 1.148 + if arg == '--currentuser' or re.match("-[^-]*U.*", arg): 1.149 + return True 1.150 + return False 1.151 + 1.152 + def ensure_qnew_currentuser_default(self): 1.153 + if self.have_qnew_currentuser_default(): 1.154 + return 1.155 + if 'defaults' not in self._c: 1.156 + self._c['defaults'] = {} 1.157 + 1.158 + d = self._c['defaults'] 1.159 + if 'qnew' not in d: 1.160 + d['qnew'] = '-U' 1.161 + else: 1.162 + d['qnew'] = '-U ' + d['qnew']