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