github.com/whamcloud/lemur@v0.0.0-20190827193804-4655df8a52af/packaging/ci/lambda/GitPullS3/pygit2/config.py (about) 1 # -*- coding: utf-8 -*- 2 # 3 # Copyright 2010-2015 The pygit2 contributors 4 # 5 # This file is free software; you can redistribute it and/or modify 6 # it under the terms of the GNU General Public License, version 2, 7 # as published by the Free Software Foundation. 8 # 9 # In addition to the permissions in the GNU General Public License, 10 # the authors give you unlimited permission to link the compiled 11 # version of this file into combinations with other programs, 12 # and to distribute those combinations without any restriction 13 # coming from the use of this file. (The General Public License 14 # restrictions do apply in other respects; for example, they cover 15 # modification of the file, and distribution when not linked into 16 # a combined executable.) 17 # 18 # This file is distributed in the hope that it will be useful, but 19 # WITHOUT ANY WARRANTY; without even the implied warranty of 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 # General Public License for more details. 22 # 23 # You should have received a copy of the GNU General Public License 24 # along with this program; see the file COPYING. If not, write to 25 # the Free Software Foundation, 51 Franklin Street, Fifth Floor, 26 # Boston, MA 02110-1301, USA. 27 28 # Import from the future 29 from __future__ import absolute_import, unicode_literals 30 31 # Import from pygit2 32 from .errors import check_error 33 from .ffi import ffi, C 34 from .utils import to_bytes, is_string 35 36 37 def assert_string(v, desc): 38 if not is_string(v): 39 raise TypeError("%s must be a string" % desc) 40 41 42 class ConfigIterator(object): 43 44 def __init__(self, config, ptr): 45 self._iter = ptr 46 self._config = config 47 48 def __del__(self): 49 C.git_config_iterator_free(self._iter) 50 51 def __iter__(self): 52 return self 53 54 def _next_entry(self): 55 centry = ffi.new('git_config_entry **') 56 err = C.git_config_next(centry, self._iter) 57 check_error(err) 58 59 return centry[0] 60 61 def next(self): 62 return self.__next__() 63 64 def __next__(self): 65 entry = self._next_entry() 66 return ffi.string(entry.name).decode('utf-8') 67 68 69 class ConfigMultivarIterator(ConfigIterator): 70 def __next__(self): 71 entry = self._next_entry() 72 return ffi.string(entry.value).decode('utf-8') 73 74 75 class Config(object): 76 """Git configuration management""" 77 78 def __init__(self, path=None): 79 cconfig = ffi.new('git_config **') 80 81 if not path: 82 err = C.git_config_new(cconfig) 83 else: 84 assert_string(path, "path") 85 err = C.git_config_open_ondisk(cconfig, to_bytes(path)) 86 87 check_error(err, True) 88 self._config = cconfig[0] 89 90 @classmethod 91 def from_c(cls, repo, ptr): 92 config = cls.__new__(cls) 93 config._repo = repo 94 config._config = ptr 95 96 return config 97 98 def __del__(self): 99 C.git_config_free(self._config) 100 101 def _get(self, key): 102 assert_string(key, "key") 103 104 entry = ffi.new('git_config_entry **') 105 err = C.git_config_get_entry(entry, self._config, to_bytes(key)) 106 107 return err, ConfigEntry._from_c(entry[0]) 108 109 def _get_entry(self, key): 110 err, entry = self._get(key) 111 112 if err == C.GIT_ENOTFOUND: 113 raise KeyError(key) 114 115 check_error(err) 116 return entry 117 118 def __contains__(self, key): 119 err, cstr = self._get(key) 120 121 if err == C.GIT_ENOTFOUND: 122 return False 123 124 check_error(err) 125 126 return True 127 128 def __getitem__(self, key): 129 entry = self._get_entry(key) 130 131 return ffi.string(entry.value).decode('utf-8') 132 133 def __setitem__(self, key, value): 134 assert_string(key, "key") 135 136 err = 0 137 if isinstance(value, bool): 138 err = C.git_config_set_bool(self._config, to_bytes(key), value) 139 elif isinstance(value, int): 140 err = C.git_config_set_int64(self._config, to_bytes(key), value) 141 else: 142 err = C.git_config_set_string(self._config, to_bytes(key), 143 to_bytes(value)) 144 145 check_error(err) 146 147 def __delitem__(self, key): 148 assert_string(key, "key") 149 150 err = C.git_config_delete_entry(self._config, to_bytes(key)) 151 check_error(err) 152 153 def __iter__(self): 154 citer = ffi.new('git_config_iterator **') 155 err = C.git_config_iterator_new(citer, self._config) 156 check_error(err) 157 158 return ConfigIterator(self, citer[0]) 159 160 def get_multivar(self, name, regex=None): 161 """Get each value of a multivar ''name'' as a list of strings. 162 163 The optional ''regex'' parameter is expected to be a regular expression 164 to filter the variables we're interested in. 165 """ 166 assert_string(name, "name") 167 168 citer = ffi.new('git_config_iterator **') 169 err = C.git_config_multivar_iterator_new(citer, self._config, 170 to_bytes(name), 171 to_bytes(regex)) 172 check_error(err) 173 174 return ConfigMultivarIterator(self, citer[0]) 175 176 def set_multivar(self, name, regex, value): 177 """Set a multivar ''name'' to ''value''. ''regexp'' is a regular 178 expression to indicate which values to replace. 179 """ 180 assert_string(name, "name") 181 assert_string(regex, "regex") 182 assert_string(value, "value") 183 184 err = C.git_config_set_multivar(self._config, to_bytes(name), 185 to_bytes(regex), to_bytes(value)) 186 check_error(err) 187 188 def get_bool(self, key): 189 """Look up *key* and parse its value as a boolean as per the git-config 190 rules. Return a boolean value (True or False). 191 192 Truthy values are: 'true', 1, 'on' or 'yes'. Falsy values are: 'false', 193 0, 'off' and 'no' 194 """ 195 196 entry = self._get_entry(key) 197 res = ffi.new('int *') 198 err = C.git_config_parse_bool(res, entry.value) 199 check_error(err) 200 201 return res[0] != 0 202 203 def get_int(self, key): 204 """Look up *key* and parse its value as an integer as per the git-config 205 rules. Return an integer. 206 207 A value can have a suffix 'k', 'm' or 'g' which stand for 'kilo', 208 'mega' and 'giga' respectively. 209 """ 210 211 entry = self._get_entry(key) 212 res = ffi.new('int64_t *') 213 err = C.git_config_parse_int64(res, entry.value) 214 check_error(err) 215 216 return res[0] 217 218 def add_file(self, path, level=0, force=0): 219 """Add a config file instance to an existing config.""" 220 221 err = C.git_config_add_file_ondisk(self._config, to_bytes(path), level, 222 force) 223 check_error(err) 224 225 def snapshot(self): 226 """Create a snapshot from this Config object. 227 228 This means that looking up multiple values will use the same version 229 of the configuration files. 230 """ 231 ccfg = ffi.new('git_config **') 232 err = C.git_config_snapshot(ccfg, self._config) 233 check_error(err) 234 235 return Config.from_c(self._repo, ccfg[0]) 236 237 # 238 # Methods to parse a string according to the git-config rules 239 # 240 241 @staticmethod 242 def parse_bool(text): 243 res = ffi.new('int *') 244 err = C.git_config_parse_bool(res, to_bytes(text)) 245 check_error(err) 246 247 return res[0] != 0 248 249 @staticmethod 250 def parse_int(text): 251 res = ffi.new('int64_t *') 252 err = C.git_config_parse_int64(res, to_bytes(text)) 253 check_error(err) 254 255 return res[0] 256 257 # 258 # Static methods to get specialized version of the config 259 # 260 261 @staticmethod 262 def _from_found_config(fn): 263 buf = ffi.new('git_buf *', (ffi.NULL, 0)) 264 err = fn(buf) 265 check_error(err, True) 266 cpath = ffi.string(buf.ptr).decode() 267 C.git_buf_free(buf) 268 269 return Config(cpath) 270 271 @staticmethod 272 def get_system_config(): 273 """Return a <Config> object representing the system configuration file. 274 """ 275 return Config._from_found_config(C.git_config_find_system) 276 277 @staticmethod 278 def get_global_config(): 279 """Return a <Config> object representing the global configuration file. 280 """ 281 return Config._from_found_config(C.git_config_find_global) 282 283 @staticmethod 284 def get_xdg_config(): 285 """Return a <Config> object representing the global configuration file. 286 """ 287 return Config._from_found_config(C.git_config_find_xdg) 288 289 class ConfigEntry(object): 290 """An entry in a configuation object 291 """ 292 293 @classmethod 294 def _from_c(cls, ptr): 295 entry = cls.__new__(cls) 296 entry._entry = ptr 297 return entry 298 299 def __del__(self): 300 C.git_config_entry_free(self._entry) 301 302 @property 303 def value(self): 304 return self._entry.value