Wed, 31 Dec 2014 07:16:47 +0100
Revert simplistic fix pending revisit of Mozilla integration attempt.
michael@0 | 1 | # This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | # License, v. 2.0. If a copy of the MPL was not distributed with this, |
michael@0 | 3 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
michael@0 | 4 | |
michael@0 | 5 | from __future__ import unicode_literals |
michael@0 | 6 | |
michael@0 | 7 | from configobj import ConfigObj |
michael@0 | 8 | import re |
michael@0 | 9 | import os |
michael@0 | 10 | |
michael@0 | 11 | |
michael@0 | 12 | HOST_FINGERPRINTS = { |
michael@0 | 13 | 'bitbucket.org': '45:ad:ae:1a:cf:0e:73:47:06:07:e0:88:f5:cc:10:e5:fa:1c:f7:99', |
michael@0 | 14 | 'bugzilla.mozilla.org': '47:13:a2:14:0c:46:45:53:12:0d:e5:36:16:a5:60:26:3e:da:3a:60', |
michael@0 | 15 | 'hg.mozilla.org': 'af:27:b9:34:47:4e:e5:98:01:f6:83:2b:51:c9:aa:d8:df:fb:1a:27', |
michael@0 | 16 | } |
michael@0 | 17 | |
michael@0 | 18 | |
michael@0 | 19 | class MercurialConfig(object): |
michael@0 | 20 | """Interface for manipulating a Mercurial config file.""" |
michael@0 | 21 | |
michael@0 | 22 | def __init__(self, infiles=None): |
michael@0 | 23 | """Create a new instance, optionally from an existing hgrc file.""" |
michael@0 | 24 | |
michael@0 | 25 | if infiles: |
michael@0 | 26 | # If multiple files were specified, figure out which file we're using: |
michael@0 | 27 | if len(infiles) > 1: |
michael@0 | 28 | picky_infiles = filter(os.path.isfile, infiles) |
michael@0 | 29 | if picky_infiles: |
michael@0 | 30 | picky_infiles = [(os.path.getsize(path), path) for path in picky_infiles] |
michael@0 | 31 | infiles = [max(picky_infiles)[1]] |
michael@0 | 32 | |
michael@0 | 33 | infile = infiles[0] |
michael@0 | 34 | self.config_path = infile |
michael@0 | 35 | else: |
michael@0 | 36 | infile = None |
michael@0 | 37 | |
michael@0 | 38 | # write_empty_values is necessary to prevent built-in extensions (which |
michael@0 | 39 | # have no value) from being dropped on write. |
michael@0 | 40 | # list_values aren't needed by Mercurial and disabling them prevents |
michael@0 | 41 | # quotes from being added. |
michael@0 | 42 | self._c = ConfigObj(infile=infile, encoding='utf-8', |
michael@0 | 43 | write_empty_values=True, list_values=False) |
michael@0 | 44 | |
michael@0 | 45 | @property |
michael@0 | 46 | def config(self): |
michael@0 | 47 | return self._c |
michael@0 | 48 | |
michael@0 | 49 | @property |
michael@0 | 50 | def extensions(self): |
michael@0 | 51 | """Returns the set of currently enabled extensions (by name).""" |
michael@0 | 52 | return set(self._c.get('extensions', {}).keys()) |
michael@0 | 53 | |
michael@0 | 54 | def write(self, fh): |
michael@0 | 55 | return self._c.write(fh) |
michael@0 | 56 | |
michael@0 | 57 | def have_valid_username(self): |
michael@0 | 58 | if 'ui' not in self._c: |
michael@0 | 59 | return False |
michael@0 | 60 | |
michael@0 | 61 | if 'username' not in self._c['ui']: |
michael@0 | 62 | return False |
michael@0 | 63 | |
michael@0 | 64 | # TODO perform actual validation here. |
michael@0 | 65 | |
michael@0 | 66 | return True |
michael@0 | 67 | |
michael@0 | 68 | def add_mozilla_host_fingerprints(self): |
michael@0 | 69 | """Add host fingerprints so SSL connections don't warn.""" |
michael@0 | 70 | if 'hostfingerprints' not in self._c: |
michael@0 | 71 | self._c['hostfingerprints'] = {} |
michael@0 | 72 | |
michael@0 | 73 | for k, v in HOST_FINGERPRINTS.items(): |
michael@0 | 74 | self._c['hostfingerprints'][k] = v |
michael@0 | 75 | |
michael@0 | 76 | def set_username(self, name, email): |
michael@0 | 77 | """Set the username to use for commits. |
michael@0 | 78 | |
michael@0 | 79 | The username consists of a name (typically <firstname> <lastname>) and |
michael@0 | 80 | a well-formed e-mail address. |
michael@0 | 81 | """ |
michael@0 | 82 | if 'ui' not in self._c: |
michael@0 | 83 | self._c['ui'] = {} |
michael@0 | 84 | |
michael@0 | 85 | username = '%s <%s>' % (name, email) |
michael@0 | 86 | |
michael@0 | 87 | self._c['ui']['username'] = username.strip() |
michael@0 | 88 | |
michael@0 | 89 | def activate_extension(self, name, path=None): |
michael@0 | 90 | """Activate an extension. |
michael@0 | 91 | |
michael@0 | 92 | An extension is defined by its name (in the config) and a filesystem |
michael@0 | 93 | path). For built-in extensions, an empty path is specified. |
michael@0 | 94 | """ |
michael@0 | 95 | if not path: |
michael@0 | 96 | path = '' |
michael@0 | 97 | |
michael@0 | 98 | if 'extensions' not in self._c: |
michael@0 | 99 | self._c['extensions'] = {} |
michael@0 | 100 | |
michael@0 | 101 | self._c['extensions'][name] = path |
michael@0 | 102 | |
michael@0 | 103 | def have_recommended_diff_settings(self): |
michael@0 | 104 | if 'diff' not in self._c: |
michael@0 | 105 | return False |
michael@0 | 106 | |
michael@0 | 107 | old = dict(self._c['diff']) |
michael@0 | 108 | try: |
michael@0 | 109 | self.ensure_recommended_diff_settings() |
michael@0 | 110 | finally: |
michael@0 | 111 | self._c['diff'].update(old) |
michael@0 | 112 | |
michael@0 | 113 | return self._c['diff'] == old |
michael@0 | 114 | |
michael@0 | 115 | def ensure_recommended_diff_settings(self): |
michael@0 | 116 | if 'diff' not in self._c: |
michael@0 | 117 | self._c['diff'] = {} |
michael@0 | 118 | |
michael@0 | 119 | d = self._c['diff'] |
michael@0 | 120 | d['git'] = 1 |
michael@0 | 121 | d['showfunc'] = 1 |
michael@0 | 122 | d['unified'] = 8 |
michael@0 | 123 | |
michael@0 | 124 | def have_mqext_autocommit_mq(self): |
michael@0 | 125 | if 'mqext' not in self._c: |
michael@0 | 126 | return False |
michael@0 | 127 | v = self._c['mqext'].get('mqcommit') |
michael@0 | 128 | return v == 'auto' or v == 'yes' |
michael@0 | 129 | |
michael@0 | 130 | def ensure_mqext_autocommit_mq(self): |
michael@0 | 131 | if self.have_mqext_autocommit_mq(): |
michael@0 | 132 | return |
michael@0 | 133 | if 'mqext' not in self._c: |
michael@0 | 134 | self._c['mqext'] = {} |
michael@0 | 135 | self._c['mqext']['mqcommit'] = 'auto' |
michael@0 | 136 | |
michael@0 | 137 | def have_qnew_currentuser_default(self): |
michael@0 | 138 | if 'defaults' not in self._c: |
michael@0 | 139 | return False |
michael@0 | 140 | d = self._c['defaults'] |
michael@0 | 141 | if 'qnew' not in d: |
michael@0 | 142 | return False |
michael@0 | 143 | argv = d['qnew'].split(' ') |
michael@0 | 144 | for arg in argv: |
michael@0 | 145 | if arg == '--currentuser' or re.match("-[^-]*U.*", arg): |
michael@0 | 146 | return True |
michael@0 | 147 | return False |
michael@0 | 148 | |
michael@0 | 149 | def ensure_qnew_currentuser_default(self): |
michael@0 | 150 | if self.have_qnew_currentuser_default(): |
michael@0 | 151 | return |
michael@0 | 152 | if 'defaults' not in self._c: |
michael@0 | 153 | self._c['defaults'] = {} |
michael@0 | 154 | |
michael@0 | 155 | d = self._c['defaults'] |
michael@0 | 156 | if 'qnew' not in d: |
michael@0 | 157 | d['qnew'] = '-U' |
michael@0 | 158 | else: |
michael@0 | 159 | d['qnew'] = '-U ' + d['qnew'] |