Config: move to cffi
This halves the amount of code we have to take into account for dealing with the config. There is a slight change in the API. Config.get_multivar() returns an iterator instead of a list, which lets us reuse code from the general iterator and is closer to libgit2's API.
This commit is contained in:
@@ -38,6 +38,7 @@ from .version import __version__
|
|||||||
from .settings import Settings
|
from .settings import Settings
|
||||||
from .credentials import *
|
from .credentials import *
|
||||||
from .remote import Remote, get_credentials
|
from .remote import Remote, get_credentials
|
||||||
|
from .config import Config
|
||||||
from .errors import check_error
|
from .errors import check_error
|
||||||
from .ffi import ffi, C, to_str
|
from .ffi import ffi, C, to_str
|
||||||
|
|
||||||
|
259
pygit2/config.py
Normal file
259
pygit2/config.py
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright 2010-2014 The pygit2 contributors
|
||||||
|
#
|
||||||
|
# This file is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License, version 2,
|
||||||
|
# as published by the Free Software Foundation.
|
||||||
|
#
|
||||||
|
# In addition to the permissions in the GNU General Public License,
|
||||||
|
# the authors give you unlimited permission to link the compiled
|
||||||
|
# version of this file into combinations with other programs,
|
||||||
|
# and to distribute those combinations without any restriction
|
||||||
|
# coming from the use of this file. (The General Public License
|
||||||
|
# restrictions do apply in other respects; for example, they cover
|
||||||
|
# modification of the file, and distribution when not linked into
|
||||||
|
# a combined executable.)
|
||||||
|
#
|
||||||
|
# This file is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; see the file COPYING. If not, write to
|
||||||
|
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||||
|
# Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
# Import from the future
|
||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
from _pygit2 import Oid
|
||||||
|
|
||||||
|
from .ffi import ffi, C, to_str, is_string
|
||||||
|
from .errors import check_error, GitError
|
||||||
|
from .refspec import Refspec
|
||||||
|
|
||||||
|
def assert_string(v, desc):
|
||||||
|
if not is_string(v):
|
||||||
|
raise TypeError("%s must be a string" % desc)
|
||||||
|
|
||||||
|
class ConfigIterator(object):
|
||||||
|
|
||||||
|
def __init__(self, config, ptr):
|
||||||
|
self._iter = ptr
|
||||||
|
self._config = config
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
C.git_config_iterator_free(self._iter)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def _next_entry(self):
|
||||||
|
centry = ffi.new('git_config_entry **')
|
||||||
|
err = C.git_config_next(centry, self._iter)
|
||||||
|
check_error(err)
|
||||||
|
|
||||||
|
return centry[0]
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
return self.__next__()
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
entry = self._next_entry()
|
||||||
|
name = ffi.string(entry.name).decode('utf-8')
|
||||||
|
value = ffi.string(entry.value).decode('utf-8')
|
||||||
|
|
||||||
|
return name, value
|
||||||
|
|
||||||
|
class ConfigMultivarIterator(ConfigIterator):
|
||||||
|
def __next__(self):
|
||||||
|
entry = self._next_entry()
|
||||||
|
|
||||||
|
return ffi.string(entry.value).decode('utf-8')
|
||||||
|
|
||||||
|
class Config(object):
|
||||||
|
"""Git configuration management"""
|
||||||
|
|
||||||
|
def __init__(self, path=None):
|
||||||
|
cconfig = ffi.new('git_config **')
|
||||||
|
|
||||||
|
if not path:
|
||||||
|
err = C.git_config_new(cconfig)
|
||||||
|
else:
|
||||||
|
assert_string(path, "path")
|
||||||
|
err = C.git_config_open_ondisk(cconfig, to_str(path))
|
||||||
|
|
||||||
|
check_error(err, True)
|
||||||
|
self._config = cconfig[0]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_c(cls, repo, ptr):
|
||||||
|
config = cls.__new__(cls)
|
||||||
|
config._repo = repo
|
||||||
|
config._config = ptr
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
C.git_config_free(self._config)
|
||||||
|
|
||||||
|
def _get(self, key):
|
||||||
|
assert_string(key, "key")
|
||||||
|
|
||||||
|
cstr = ffi.new('char **')
|
||||||
|
err = C.git_config_get_string(cstr, self._config, to_str(key))
|
||||||
|
|
||||||
|
return err, cstr
|
||||||
|
|
||||||
|
def _get_string(self, key):
|
||||||
|
err, cstr = self._get(key)
|
||||||
|
|
||||||
|
if err == C.GIT_ENOTFOUND:
|
||||||
|
raise KeyError(key)
|
||||||
|
|
||||||
|
check_error(err)
|
||||||
|
return cstr[0]
|
||||||
|
|
||||||
|
def __contains__(self, key):
|
||||||
|
err, cstr = self._get(key)
|
||||||
|
|
||||||
|
if err == C.GIT_ENOTFOUND:
|
||||||
|
return False
|
||||||
|
|
||||||
|
check_error(err)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
val = self._get_string(key)
|
||||||
|
|
||||||
|
return ffi.string(val).decode()
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
assert_string(key, "key")
|
||||||
|
|
||||||
|
err = 0
|
||||||
|
if isinstance(value, bool):
|
||||||
|
err = C.git_config_set_bool(self._config, to_str(key), value)
|
||||||
|
elif isinstance(value, int):
|
||||||
|
err = C.git_config_set_int64(self._config, to_str(key), value)
|
||||||
|
else:
|
||||||
|
err = C.git_config_set_string(self._config, to_str(key), to_str(value))
|
||||||
|
|
||||||
|
check_error(err)
|
||||||
|
|
||||||
|
def __delitem__(self, key):
|
||||||
|
assert_string(key, "key")
|
||||||
|
|
||||||
|
err = C.git_config_delete_entry(self._config, to_str(key))
|
||||||
|
check_error(err)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
citer = ffi.new('git_config_iterator **')
|
||||||
|
err = C.git_config_iterator_new(citer, self._config)
|
||||||
|
check_error(err)
|
||||||
|
|
||||||
|
return ConfigIterator(self, citer[0])
|
||||||
|
|
||||||
|
def get_multivar(self, name, regex=None):
|
||||||
|
"""get_multivar(name[, regex]) -> [str, ...]
|
||||||
|
|
||||||
|
Get each value of a multivar ''name'' as a list. The optional ''regex''
|
||||||
|
parameter is expected to be a regular expression to filter the variables
|
||||||
|
we're interested in."""
|
||||||
|
|
||||||
|
assert_string(name, "name")
|
||||||
|
|
||||||
|
citer = ffi.new('git_config_iterator **')
|
||||||
|
err = C.git_config_multivar_iterator_new(citer, self._config, to_str(name), to_str(regex))
|
||||||
|
check_error(err)
|
||||||
|
|
||||||
|
return ConfigMultivarIterator(self, citer[0])
|
||||||
|
|
||||||
|
def set_multivar(self, name, regex, value):
|
||||||
|
"""set_multivar(name, regex, value)
|
||||||
|
|
||||||
|
Set a multivar ''name'' to ''value''. ''regexp'' is a regular expression
|
||||||
|
to indicate which values to replace"""
|
||||||
|
|
||||||
|
assert_string(name, "name")
|
||||||
|
assert_string(regex, "regex")
|
||||||
|
assert_string(value, "value")
|
||||||
|
|
||||||
|
err = C.git_config_set_multivar(self._config, to_str(name), to_str(regex), to_str(value))
|
||||||
|
check_error(err)
|
||||||
|
|
||||||
|
def get_bool(self, key):
|
||||||
|
"""get_bool(key) -> Bool
|
||||||
|
|
||||||
|
Look up *key* and parse its value as a boolean as per the git-config rules
|
||||||
|
|
||||||
|
Truthy values are: 'true', 1, 'on' or 'yes'. Falsy values are: 'false',
|
||||||
|
0, 'off' and 'no'"""
|
||||||
|
|
||||||
|
val = self._get_string(key)
|
||||||
|
res = ffi.new('int *')
|
||||||
|
err = C.git_config_parse_bool(res, val)
|
||||||
|
check_error(err)
|
||||||
|
|
||||||
|
return res[0] != 0
|
||||||
|
|
||||||
|
def get_int(self, key):
|
||||||
|
"""get_int(key) -> int
|
||||||
|
|
||||||
|
Look up *key* and parse its value as an integer as per the git-config rules.
|
||||||
|
|
||||||
|
A value can have a suffix 'k', 'm' or 'g' which stand for 'kilo', 'mega' and
|
||||||
|
'giga' respectively"""
|
||||||
|
|
||||||
|
val = self._get_string(key)
|
||||||
|
res = ffi.new('int64_t *')
|
||||||
|
err = C.git_config_parse_int64(res, val)
|
||||||
|
check_error(err)
|
||||||
|
|
||||||
|
return res[0]
|
||||||
|
|
||||||
|
def add_file(self, path, level=0, force=0):
|
||||||
|
"""add_file(path, level=0, force=0)
|
||||||
|
|
||||||
|
Add a config file instance to an existing config."""
|
||||||
|
|
||||||
|
err = C.git_config_add_file_ondisk(self._config, to_str(path), level, force)
|
||||||
|
check_error(err)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Static methods to get specialized version of the config
|
||||||
|
#
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _from_found_config(fn):
|
||||||
|
buf = ffi.new('char []', C.GIT_PATH_MAX)
|
||||||
|
err = fn(buf, C.GIT_PATH_MAX)
|
||||||
|
check_error(err, True)
|
||||||
|
return Config(ffi.string(buf).decode())
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_system_config():
|
||||||
|
"""get_system_config() -> Config
|
||||||
|
|
||||||
|
Return an object representing the system configuration file."""
|
||||||
|
|
||||||
|
return Config._from_found_config(C.git_config_find_system)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_global_config():
|
||||||
|
"""get_global_config() -> Config
|
||||||
|
|
||||||
|
Return an object representing the global configuration file."""
|
||||||
|
|
||||||
|
return Config._from_found_config(C.git_config_find_global)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_xdg_config():
|
||||||
|
"""get_xdg_config() -> Config
|
||||||
|
|
||||||
|
Return an object representing the global configuration file."""
|
||||||
|
|
||||||
|
return Config._from_found_config(C.git_config_find_xdg)
|
@@ -5,8 +5,11 @@ typedef ... git_push;
|
|||||||
typedef ... git_cred;
|
typedef ... git_cred;
|
||||||
typedef ... git_diff_file;
|
typedef ... git_diff_file;
|
||||||
typedef ... git_tree;
|
typedef ... git_tree;
|
||||||
|
typedef ... git_config;
|
||||||
|
typedef ... git_config_iterator;
|
||||||
|
|
||||||
#define GIT_OID_RAWSZ ...
|
#define GIT_OID_RAWSZ ...
|
||||||
|
#define GIT_PATH_MAX ...
|
||||||
|
|
||||||
typedef struct git_oid {
|
typedef struct git_oid {
|
||||||
unsigned char id[20];
|
unsigned char id[20];
|
||||||
@@ -212,3 +215,49 @@ int git_clone(git_repository **out,
|
|||||||
const char *url,
|
const char *url,
|
||||||
const char *local_path,
|
const char *local_path,
|
||||||
const git_clone_options *options);
|
const git_clone_options *options);
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GIT_CONFIG_LEVEL_SYSTEM = 1,
|
||||||
|
GIT_CONFIG_LEVEL_XDG = 2,
|
||||||
|
GIT_CONFIG_LEVEL_GLOBAL = 3,
|
||||||
|
GIT_CONFIG_LEVEL_LOCAL = 4,
|
||||||
|
GIT_CONFIG_LEVEL_APP = 5,
|
||||||
|
GIT_CONFIG_HIGHEST_LEVEL = -1,
|
||||||
|
} git_config_level_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *name;
|
||||||
|
const char *value;
|
||||||
|
git_config_level_t level;
|
||||||
|
} git_config_entry;
|
||||||
|
|
||||||
|
int git_repository_config(git_config **out, git_repository *repo);
|
||||||
|
void git_config_free(git_config *cfg);
|
||||||
|
|
||||||
|
int git_config_get_string(const char **out, const git_config *cfg, const char *name);
|
||||||
|
int git_config_set_string(git_config *cfg, const char *name, const char *value);
|
||||||
|
int git_config_set_bool(git_config *cfg, const char *name, int value);
|
||||||
|
int git_config_set_int64(git_config *cfg, const char *name, int64_t value);
|
||||||
|
|
||||||
|
int git_config_parse_bool(int *out, const char *value);
|
||||||
|
int git_config_parse_int64(int64_t *out, const char *value);
|
||||||
|
|
||||||
|
int git_config_delete_entry(git_config *cfg, const char *name);
|
||||||
|
int git_config_add_file_ondisk(git_config *cfg,
|
||||||
|
const char *path,
|
||||||
|
git_config_level_t level,
|
||||||
|
int force);
|
||||||
|
|
||||||
|
int git_config_iterator_new(git_config_iterator **out, const git_config *cfg);
|
||||||
|
int git_config_next(git_config_entry **entry, git_config_iterator *iter);
|
||||||
|
void git_config_iterator_free(git_config_iterator *iter);
|
||||||
|
|
||||||
|
int git_config_multivar_iterator_new(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp);
|
||||||
|
int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value);
|
||||||
|
|
||||||
|
int git_config_new(git_config **out);
|
||||||
|
int git_config_open_ondisk(git_config **out, const char *path);
|
||||||
|
int git_config_find_system(char *out, size_t length);
|
||||||
|
int git_config_find_global(char *out, size_t length);
|
||||||
|
int git_config_find_xdg(char *out, size_t length);
|
||||||
|
@@ -33,7 +33,7 @@ from .ffi import ffi, C
|
|||||||
|
|
||||||
from _pygit2 import GitError
|
from _pygit2 import GitError
|
||||||
|
|
||||||
def check_error(err):
|
def check_error(err, io=False):
|
||||||
if err >= 0:
|
if err >= 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -45,7 +45,10 @@ def check_error(err):
|
|||||||
if err in [C.GIT_EEXISTS, C.GIT_EINVALIDSPEC, C.GIT_EEXISTS, C.GIT_EAMBIGUOUS]:
|
if err in [C.GIT_EEXISTS, C.GIT_EINVALIDSPEC, C.GIT_EEXISTS, C.GIT_EAMBIGUOUS]:
|
||||||
raise ValueError(message)
|
raise ValueError(message)
|
||||||
elif err == C.GIT_ENOTFOUND:
|
elif err == C.GIT_ENOTFOUND:
|
||||||
raise KeyError(message)
|
if io:
|
||||||
|
raise IOError(message)
|
||||||
|
else:
|
||||||
|
raise KeyError(message)
|
||||||
elif err == C.GIT_EINVALIDSPEC:
|
elif err == C.GIT_EINVALIDSPEC:
|
||||||
raise ValueError(message)
|
raise ValueError(message)
|
||||||
elif err == C.GIT_ITEROVER:
|
elif err == C.GIT_ITEROVER:
|
||||||
|
@@ -38,6 +38,7 @@ from _pygit2 import Reference, Tree, Commit, Blob
|
|||||||
from .ffi import ffi, C, to_str
|
from .ffi import ffi, C, to_str
|
||||||
from .errors import check_error
|
from .errors import check_error
|
||||||
from .remote import Remote
|
from .remote import Remote
|
||||||
|
from .config import Config
|
||||||
|
|
||||||
class Repository(_Repository):
|
class Repository(_Repository):
|
||||||
|
|
||||||
@@ -110,6 +111,23 @@ class Repository(_Repository):
|
|||||||
C.git_strarray_free(names)
|
C.git_strarray_free(names)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Configuration
|
||||||
|
#
|
||||||
|
@property
|
||||||
|
def config(self):
|
||||||
|
"""The configuration file for this repository
|
||||||
|
|
||||||
|
If a the configuration hasn't been set yet, the default config for
|
||||||
|
repository will be returned, including global and system configurations
|
||||||
|
(if they are available)."""
|
||||||
|
|
||||||
|
cconfig = ffi.new('git_config **')
|
||||||
|
err = C.git_repository_config(cconfig, self._repo)
|
||||||
|
check_error(err)
|
||||||
|
|
||||||
|
return Config.from_c(self, cconfig[0])
|
||||||
|
|
||||||
#
|
#
|
||||||
# References
|
# References
|
||||||
#
|
#
|
||||||
|
540
src/config.c
540
src/config.c
@@ -1,540 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2014 The pygit2 contributors
|
|
||||||
*
|
|
||||||
* This file is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License, version 2,
|
|
||||||
* as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* In addition to the permissions in the GNU General Public License,
|
|
||||||
* the authors give you unlimited permission to link the compiled
|
|
||||||
* version of this file into combinations with other programs,
|
|
||||||
* and to distribute those combinations without any restriction
|
|
||||||
* coming from the use of this file. (The General Public License
|
|
||||||
* restrictions do apply in other respects; for example, they cover
|
|
||||||
* modification of the file, and distribution when not linked into
|
|
||||||
* a combined executable.)
|
|
||||||
*
|
|
||||||
* This file is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
||||||
* Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define PY_SSIZE_T_CLEAN
|
|
||||||
#include <Python.h>
|
|
||||||
#include "error.h"
|
|
||||||
#include "types.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
extern PyTypeObject ConfigType;
|
|
||||||
extern PyTypeObject ConfigIterType;
|
|
||||||
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
wrap_config(char *c_path) {
|
|
||||||
int err;
|
|
||||||
PyObject *py_path;
|
|
||||||
Config *py_config;
|
|
||||||
|
|
||||||
py_path = Py_BuildValue("(s)", c_path);
|
|
||||||
py_config = PyObject_New(Config, &ConfigType);
|
|
||||||
|
|
||||||
err = Config_init(py_config, py_path, NULL);
|
|
||||||
if (err < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return (PyObject*) py_config;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
Config_init(Config *self, PyObject *args, PyObject *kwds)
|
|
||||||
{
|
|
||||||
char *path = NULL;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (kwds && PyDict_Size(kwds) > 0) {
|
|
||||||
PyErr_SetString(PyExc_TypeError,
|
|
||||||
"Config takes no keyword arguments");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "|s", &path))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (path == NULL)
|
|
||||||
err = git_config_new(&self->config);
|
|
||||||
else
|
|
||||||
err = git_config_open_ondisk(&self->config, path);
|
|
||||||
|
|
||||||
if (err < 0) {
|
|
||||||
git_config_free(self->config);
|
|
||||||
|
|
||||||
if (err == GIT_ENOTFOUND)
|
|
||||||
Error_set_exc(PyExc_IOError);
|
|
||||||
else
|
|
||||||
Error_set(err);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Config_dealloc(Config *self)
|
|
||||||
{
|
|
||||||
git_config_free(self->config);
|
|
||||||
Py_TYPE(self)->tp_free(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(Config_get_global_config__doc__,
|
|
||||||
"get_global_config() -> Config\n"
|
|
||||||
"\n"
|
|
||||||
"Return an object representing the global configuration file.");
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
Config_get_global_config(void)
|
|
||||||
{
|
|
||||||
char path[GIT_PATH_MAX];
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = git_config_find_global(path, GIT_PATH_MAX);
|
|
||||||
if (err < 0) {
|
|
||||||
if (err == GIT_ENOTFOUND) {
|
|
||||||
PyErr_SetString(PyExc_IOError, "Global config file not found.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Error_set(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
return wrap_config(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(Config_get_system_config__doc__,
|
|
||||||
"get_system_config() -> Config\n"
|
|
||||||
"\n"
|
|
||||||
"Return an object representing the system configuration file.");
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
Config_get_system_config(void)
|
|
||||||
{
|
|
||||||
char path[GIT_PATH_MAX];
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = git_config_find_system(path, GIT_PATH_MAX);
|
|
||||||
if (err < 0) {
|
|
||||||
if (err == GIT_ENOTFOUND) {
|
|
||||||
PyErr_SetString(PyExc_IOError, "System config file not found.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return Error_set(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
return wrap_config(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
Config_contains(Config *self, PyObject *py_key) {
|
|
||||||
int err;
|
|
||||||
const char *c_value, *c_key;
|
|
||||||
PyObject *tkey;
|
|
||||||
|
|
||||||
c_key = py_str_borrow_c_str(&tkey, py_key, NULL);
|
|
||||||
if (c_key == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
err = git_config_get_string(&c_value, self->config, c_key);
|
|
||||||
Py_DECREF(tkey);
|
|
||||||
|
|
||||||
if (err < 0) {
|
|
||||||
if (err == GIT_ENOTFOUND)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
Error_set(err);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the C string value given a python string as key */
|
|
||||||
static int
|
|
||||||
get_string(const char **key_out, Config *self, PyObject *py_key)
|
|
||||||
{
|
|
||||||
PyObject *tkey;
|
|
||||||
const char *key;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
key = py_str_borrow_c_str(&tkey, py_key, NULL);
|
|
||||||
if (key == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
err = git_config_get_string(key_out, self->config, key);
|
|
||||||
Py_CLEAR(tkey);
|
|
||||||
|
|
||||||
if (err == GIT_ENOTFOUND) {
|
|
||||||
PyErr_SetObject(PyExc_KeyError, py_key);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err < 0) {
|
|
||||||
Error_set(err);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
Config_getitem(Config *self, PyObject *py_key)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
const char *value_str;
|
|
||||||
|
|
||||||
err = get_string(&value_str, self, py_key);
|
|
||||||
if (err < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return to_unicode(value_str, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(Config_get_bool__doc__,
|
|
||||||
"get_bool(key) -> Bool\n"
|
|
||||||
"\n"
|
|
||||||
"Look up *key* and parse its value as a boolean as per the git-config rules\n"
|
|
||||||
"\n"
|
|
||||||
"Truthy values are: 'true', 1, 'on' or 'yes'. Falsy values are: 'false',\n"
|
|
||||||
"0, 'off' and 'no'");
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
Config_get_bool(Config *self, PyObject *key)
|
|
||||||
{
|
|
||||||
int err, value;
|
|
||||||
const char *value_str;
|
|
||||||
|
|
||||||
err = get_string(&value_str, self, key);
|
|
||||||
if (err < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if ((err = git_config_parse_bool(&value, value_str)) < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return PyBool_FromLong(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(Config_get_int__doc__,
|
|
||||||
"get_int(key) -> int\n"
|
|
||||||
"\n"
|
|
||||||
"Look up *key* and parse its value as an integer as per the git-config rules\n"
|
|
||||||
"\n"
|
|
||||||
"A value can have a suffix 'k', 'm' or 'g' which stand for 'kilo', 'mega' and\n"
|
|
||||||
"'giga' respectively");
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
Config_get_int(Config *self, PyObject *key)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
int64_t value;
|
|
||||||
const char *value_str;
|
|
||||||
|
|
||||||
err = get_string(&value_str, self, key);
|
|
||||||
if (err < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if ((err = git_config_parse_int64(&value, value_str)) < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return PyLong_FromLongLong(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
Config_setitem(Config *self, PyObject *py_key, PyObject *py_value)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
const char *key, *value;
|
|
||||||
PyObject *tkey, *tvalue;
|
|
||||||
|
|
||||||
key = py_str_borrow_c_str(&tkey, py_key, NULL);
|
|
||||||
if (key == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (py_value == NULL)
|
|
||||||
err = git_config_delete_entry(self->config, key);
|
|
||||||
else if (PyBool_Check(py_value)) {
|
|
||||||
err = git_config_set_bool(self->config, key,
|
|
||||||
(int)PyObject_IsTrue(py_value));
|
|
||||||
} else if (PyLong_Check(py_value)) {
|
|
||||||
err = git_config_set_int64(self->config, key,
|
|
||||||
(int64_t)PyLong_AsLong(py_value));
|
|
||||||
} else {
|
|
||||||
value = py_str_borrow_c_str(&tvalue, py_value, NULL);
|
|
||||||
err = git_config_set_string(self->config, key, value);
|
|
||||||
Py_DECREF(tvalue);
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_DECREF(tkey);
|
|
||||||
if (err < 0) {
|
|
||||||
Error_set(err);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(Config_add_file__doc__,
|
|
||||||
"add_file(path, level=0, force=0)\n"
|
|
||||||
"\n"
|
|
||||||
"Add a config file instance to an existing config.");
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
Config_add_file(Config *self, PyObject *args, PyObject *kwds)
|
|
||||||
{
|
|
||||||
char *keywords[] = {"path", "level", "force", NULL};
|
|
||||||
int err;
|
|
||||||
char *path;
|
|
||||||
unsigned int level = 0;
|
|
||||||
int force = 0;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|Ii", keywords,
|
|
||||||
&path, &level, &force))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
err = git_config_add_file_ondisk(self->config, path, level, force);
|
|
||||||
if (err < 0)
|
|
||||||
return Error_set_str(err, path);
|
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(Config_get_multivar__doc__,
|
|
||||||
"get_multivar(name[, regex]) -> [str, ...]\n"
|
|
||||||
"\n"
|
|
||||||
"Get each value of a multivar ''name'' as a list. The optional ''regex''\n"
|
|
||||||
"parameter is expected to be a regular expression to filter the variables\n"
|
|
||||||
"we're interested in.");
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
Config_get_multivar(Config *self, PyObject *args)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
PyObject *list;
|
|
||||||
const char *name = NULL;
|
|
||||||
const char *regex = NULL;
|
|
||||||
git_config_iterator *iter;
|
|
||||||
git_config_entry *entry;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s|s", &name, ®ex))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
list = PyList_New(0);
|
|
||||||
err = git_config_multivar_iterator_new(&iter, self->config, name, regex);
|
|
||||||
if (err < 0)
|
|
||||||
return Error_set(err);
|
|
||||||
|
|
||||||
while ((err = git_config_next(&entry, iter)) == 0) {
|
|
||||||
PyObject *item;
|
|
||||||
|
|
||||||
item = to_unicode(entry->value, NULL, NULL);
|
|
||||||
if (item == NULL) {
|
|
||||||
git_config_iterator_free(iter);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyList_Append(list, item);
|
|
||||||
Py_CLEAR(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
git_config_iterator_free(iter);
|
|
||||||
if (err == GIT_ITEROVER)
|
|
||||||
err = 0;
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
return Error_set(err);
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(Config_set_multivar__doc__,
|
|
||||||
"set_multivar(name, regex, value)\n"
|
|
||||||
"\n"
|
|
||||||
"Set a multivar ''name'' to ''value''. ''regexp'' is a regular expression\n"
|
|
||||||
"to indicate which values to replace");
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
Config_set_multivar(Config *self, PyObject *args)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
const char *name = NULL;
|
|
||||||
const char *regex = NULL;
|
|
||||||
const char *value = NULL;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "sss", &name, ®ex, &value))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
err = git_config_set_multivar(self->config, name, regex, value);
|
|
||||||
if (err < 0) {
|
|
||||||
if (err == GIT_ENOTFOUND)
|
|
||||||
Error_set(err);
|
|
||||||
else
|
|
||||||
PyErr_SetNone(PyExc_TypeError);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
Config_iter(Config *self)
|
|
||||||
{
|
|
||||||
ConfigIter *iter;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
iter = PyObject_New(ConfigIter, &ConfigIterType);
|
|
||||||
if (!iter)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if ((err = git_config_iterator_new(&iter->iter, self->config)) < 0)
|
|
||||||
return Error_set(err);
|
|
||||||
|
|
||||||
Py_INCREF(self);
|
|
||||||
iter->owner = self;
|
|
||||||
|
|
||||||
return (PyObject*)iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyMethodDef Config_methods[] = {
|
|
||||||
METHOD(Config, get_system_config, METH_NOARGS | METH_STATIC),
|
|
||||||
METHOD(Config, get_global_config, METH_NOARGS | METH_STATIC),
|
|
||||||
METHOD(Config, add_file, METH_VARARGS | METH_KEYWORDS),
|
|
||||||
METHOD(Config, get_multivar, METH_VARARGS),
|
|
||||||
METHOD(Config, set_multivar, METH_VARARGS),
|
|
||||||
METHOD(Config, get_bool, METH_O),
|
|
||||||
METHOD(Config, get_int, METH_O),
|
|
||||||
{NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
PySequenceMethods Config_as_sequence = {
|
|
||||||
0, /* sq_length */
|
|
||||||
0, /* sq_concat */
|
|
||||||
0, /* sq_repeat */
|
|
||||||
0, /* sq_item */
|
|
||||||
0, /* sq_slice */
|
|
||||||
0, /* sq_ass_item */
|
|
||||||
0, /* sq_ass_slice */
|
|
||||||
(objobjproc)Config_contains, /* sq_contains */
|
|
||||||
};
|
|
||||||
|
|
||||||
PyMappingMethods Config_as_mapping = {
|
|
||||||
0, /* mp_length */
|
|
||||||
(binaryfunc)Config_getitem, /* mp_subscript */
|
|
||||||
(objobjargproc)Config_setitem, /* mp_ass_subscript */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(Config__doc__, "Configuration management.");
|
|
||||||
|
|
||||||
PyTypeObject ConfigType = {
|
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
|
||||||
"_pygit2.Config", /* tp_name */
|
|
||||||
sizeof(Config), /* tp_basicsize */
|
|
||||||
0, /* tp_itemsize */
|
|
||||||
(destructor)Config_dealloc, /* tp_dealloc */
|
|
||||||
0, /* tp_print */
|
|
||||||
0, /* tp_getattr */
|
|
||||||
0, /* tp_setattr */
|
|
||||||
0, /* tp_compare */
|
|
||||||
0, /* tp_repr */
|
|
||||||
0, /* tp_as_number */
|
|
||||||
&Config_as_sequence, /* tp_as_sequence */
|
|
||||||
&Config_as_mapping, /* tp_as_mapping */
|
|
||||||
0, /* tp_hash */
|
|
||||||
0, /* tp_call */
|
|
||||||
0, /* tp_str */
|
|
||||||
0, /* tp_getattro */
|
|
||||||
0, /* tp_setattro */
|
|
||||||
0, /* tp_as_buffer */
|
|
||||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
|
||||||
Config__doc__, /* tp_doc */
|
|
||||||
0, /* tp_traverse */
|
|
||||||
0, /* tp_clear */
|
|
||||||
0, /* tp_richcompare */
|
|
||||||
0, /* tp_weaklistoffset */
|
|
||||||
(getiterfunc)Config_iter, /* tp_iter */
|
|
||||||
0, /* tp_iternext */
|
|
||||||
Config_methods, /* tp_methods */
|
|
||||||
0, /* tp_members */
|
|
||||||
0, /* tp_getset */
|
|
||||||
0, /* tp_base */
|
|
||||||
0, /* tp_dict */
|
|
||||||
0, /* tp_descr_get */
|
|
||||||
0, /* tp_descr_set */
|
|
||||||
0, /* tp_dictoffset */
|
|
||||||
(initproc)Config_init, /* tp_init */
|
|
||||||
0, /* tp_alloc */
|
|
||||||
0, /* tp_new */
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
ConfigIter_dealloc(ConfigIter *self)
|
|
||||||
{
|
|
||||||
Py_CLEAR(self->owner);
|
|
||||||
git_config_iterator_free(self->iter);
|
|
||||||
PyObject_Del(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
ConfigIter_iternext(ConfigIter *self)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
git_config_entry *entry;
|
|
||||||
|
|
||||||
if ((err = git_config_next(&entry, self->iter)) < 0)
|
|
||||||
return Error_set(err);
|
|
||||||
|
|
||||||
return Py_BuildValue("ss", entry->name, entry->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(ConfigIter__doc__, "Configuration iterator.");
|
|
||||||
|
|
||||||
PyTypeObject ConfigIterType = {
|
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
|
||||||
"_pygit2.ConfigIter", /* tp_name */
|
|
||||||
sizeof(ConfigIter), /* tp_basicsize */
|
|
||||||
0, /* tp_itemsize */
|
|
||||||
(destructor)ConfigIter_dealloc , /* tp_dealloc */
|
|
||||||
0, /* tp_print */
|
|
||||||
0, /* tp_getattr */
|
|
||||||
0, /* tp_setattr */
|
|
||||||
0, /* tp_compare */
|
|
||||||
0, /* tp_repr */
|
|
||||||
0, /* tp_as_number */
|
|
||||||
0, /* tp_as_sequence */
|
|
||||||
0, /* tp_as_mapping */
|
|
||||||
0, /* tp_hash */
|
|
||||||
0, /* tp_call */
|
|
||||||
0, /* tp_str */
|
|
||||||
0, /* tp_getattro */
|
|
||||||
0, /* tp_setattro */
|
|
||||||
0, /* tp_as_buffer */
|
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
||||||
ConfigIter__doc__, /* tp_doc */
|
|
||||||
0, /* tp_traverse */
|
|
||||||
0, /* tp_clear */
|
|
||||||
0, /* tp_richcompare */
|
|
||||||
0, /* tp_weaklistoffset */
|
|
||||||
PyObject_SelfIter, /* tp_iter */
|
|
||||||
(iternextfunc)ConfigIter_iternext, /* tp_iternext */
|
|
||||||
|
|
||||||
};
|
|
45
src/config.h
45
src/config.h
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2014 The pygit2 contributors
|
|
||||||
*
|
|
||||||
* This file is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License, version 2,
|
|
||||||
* as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* In addition to the permissions in the GNU General Public License,
|
|
||||||
* the authors give you unlimited permission to link the compiled
|
|
||||||
* version of this file into combinations with other programs,
|
|
||||||
* and to distribute those combinations without any restriction
|
|
||||||
* coming from the use of this file. (The General Public License
|
|
||||||
* restrictions do apply in other respects; for example, they cover
|
|
||||||
* modification of the file, and distribution when not linked into
|
|
||||||
* a combined executable.)
|
|
||||||
*
|
|
||||||
* This file is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
||||||
* Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef INCLUDE_pygit2_config_h
|
|
||||||
#define INCLUDE_pygit2_config_h
|
|
||||||
|
|
||||||
#define PY_SSIZE_T_CLEAN
|
|
||||||
#include <Python.h>
|
|
||||||
#include <git2.h>
|
|
||||||
|
|
||||||
PyObject* wrap_config(char *c_path);
|
|
||||||
PyObject* Config_get_global_config(void);
|
|
||||||
PyObject* Config_get_system_config(void);
|
|
||||||
PyObject* Config_add_file(Config *self, PyObject *args, PyObject *kwds);
|
|
||||||
PyObject* Config_getitem(Config *self, PyObject *key);
|
|
||||||
PyObject* Config_foreach(Config *self, PyObject *args);
|
|
||||||
PyObject* Config_get_multivar(Config *self, PyObject *args);
|
|
||||||
PyObject* Config_set_multivar(Config *self, PyObject *args);
|
|
||||||
int Config_init(Config *self, PyObject *args, PyObject *kwds);
|
|
||||||
int Config_setitem(Config *self, PyObject *key, PyObject *value);
|
|
||||||
#endif
|
|
@@ -66,8 +66,6 @@ extern PyTypeObject IndexType;
|
|||||||
extern PyTypeObject IndexEntryType;
|
extern PyTypeObject IndexEntryType;
|
||||||
extern PyTypeObject IndexIterType;
|
extern PyTypeObject IndexIterType;
|
||||||
extern PyTypeObject WalkerType;
|
extern PyTypeObject WalkerType;
|
||||||
extern PyTypeObject ConfigType;
|
|
||||||
extern PyTypeObject ConfigIterType;
|
|
||||||
extern PyTypeObject ReferenceType;
|
extern PyTypeObject ReferenceType;
|
||||||
extern PyTypeObject RefLogIterType;
|
extern PyTypeObject RefLogIterType;
|
||||||
extern PyTypeObject RefLogEntryType;
|
extern PyTypeObject RefLogEntryType;
|
||||||
@@ -385,11 +383,6 @@ moduleinit(PyObject* m)
|
|||||||
ADD_CONSTANT_INT(m, GIT_CONFIG_LEVEL_XDG);
|
ADD_CONSTANT_INT(m, GIT_CONFIG_LEVEL_XDG);
|
||||||
ADD_CONSTANT_INT(m, GIT_CONFIG_LEVEL_SYSTEM);
|
ADD_CONSTANT_INT(m, GIT_CONFIG_LEVEL_SYSTEM);
|
||||||
|
|
||||||
INIT_TYPE(ConfigType, NULL, PyType_GenericNew)
|
|
||||||
INIT_TYPE(ConfigIterType, NULL, NULL)
|
|
||||||
ADD_TYPE(m, Config)
|
|
||||||
ADD_TYPE(m, ConfigIter)
|
|
||||||
|
|
||||||
/* Blame */
|
/* Blame */
|
||||||
INIT_TYPE(BlameType, NULL, NULL)
|
INIT_TYPE(BlameType, NULL, NULL)
|
||||||
INIT_TYPE(BlameIterType, NULL, NULL)
|
INIT_TYPE(BlameIterType, NULL, NULL)
|
||||||
|
@@ -513,45 +513,6 @@ Repository_workdir__get__(Repository *self, void *closure)
|
|||||||
return to_path(c_path);
|
return to_path(c_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(Repository_config__doc__,
|
|
||||||
"Get the configuration file for this repository.\n"
|
|
||||||
"\n"
|
|
||||||
"If a configuration file has not been set, the default config set for the\n"
|
|
||||||
"repository will be returned, including global and system configurations\n"
|
|
||||||
"(if they are available).");
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
Repository_config__get__(Repository *self)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
git_config *config;
|
|
||||||
Config *py_config;
|
|
||||||
|
|
||||||
assert(self->repo);
|
|
||||||
|
|
||||||
if (self->config == NULL) {
|
|
||||||
err = git_repository_config(&config, self->repo);
|
|
||||||
if (err < 0)
|
|
||||||
return Error_set(err);
|
|
||||||
|
|
||||||
py_config = PyObject_New(Config, &ConfigType);
|
|
||||||
if (py_config == NULL) {
|
|
||||||
git_config_free(config);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
py_config->config = config;
|
|
||||||
self->config = (PyObject*)py_config;
|
|
||||||
/* We need 2 refs here. One is returned, one is kept internally. */
|
|
||||||
Py_INCREF(self->config);
|
|
||||||
} else {
|
|
||||||
Py_INCREF(self->config);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self->config;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(Repository_merge_base__doc__,
|
PyDoc_STRVAR(Repository_merge_base__doc__,
|
||||||
"merge_base(oid, oid) -> Oid\n"
|
"merge_base(oid, oid) -> Oid\n"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -1601,7 +1562,6 @@ PyGetSetDef Repository_getseters[] = {
|
|||||||
GETTER(Repository, head_is_unborn),
|
GETTER(Repository, head_is_unborn),
|
||||||
GETTER(Repository, is_empty),
|
GETTER(Repository, is_empty),
|
||||||
GETTER(Repository, is_bare),
|
GETTER(Repository, is_bare),
|
||||||
GETTER(Repository, config),
|
|
||||||
GETTER(Repository, workdir),
|
GETTER(Repository, workdir),
|
||||||
GETTER(Repository, default_signature),
|
GETTER(Repository, default_signature),
|
||||||
GETTER(Repository, _pointer),
|
GETTER(Repository, _pointer),
|
||||||
|
13
src/types.h
13
src/types.h
@@ -70,19 +70,6 @@ SIMPLE_TYPE(Tree, git_tree, tree)
|
|||||||
SIMPLE_TYPE(Blob, git_blob, blob)
|
SIMPLE_TYPE(Blob, git_blob, blob)
|
||||||
SIMPLE_TYPE(Tag, git_tag, tag)
|
SIMPLE_TYPE(Tag, git_tag, tag)
|
||||||
|
|
||||||
|
|
||||||
/* git_config */
|
|
||||||
typedef struct {
|
|
||||||
PyObject_HEAD
|
|
||||||
git_config* config;
|
|
||||||
} Config;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PyObject_HEAD
|
|
||||||
Config *owner;
|
|
||||||
git_config_iterator *iter;
|
|
||||||
} ConfigIter;
|
|
||||||
|
|
||||||
/* git_note */
|
/* git_note */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
|
@@ -115,9 +115,10 @@ class ConfigTest(utils.RepoTestCase):
|
|||||||
|
|
||||||
config.add_file(CONFIG_FILENAME, 0)
|
config.add_file(CONFIG_FILENAME, 0)
|
||||||
self.assertTrue('this.that' in config)
|
self.assertTrue('this.that' in config)
|
||||||
self.assertEqual(len(config.get_multivar('this.that')), 2)
|
|
||||||
l = config.get_multivar('this.that', 'bar')
|
self.assertEqual(2, len(list(config.get_multivar('this.that'))))
|
||||||
self.assertEqual(len(l), 1)
|
l = list(config.get_multivar('this.that', 'bar'))
|
||||||
|
self.assertEqual(1, len(l))
|
||||||
self.assertEqual(l[0], 'foobar')
|
self.assertEqual(l[0], 'foobar')
|
||||||
|
|
||||||
def test_write(self):
|
def test_write(self):
|
||||||
@@ -155,16 +156,16 @@ class ConfigTest(utils.RepoTestCase):
|
|||||||
config.add_file(CONFIG_FILENAME, 5)
|
config.add_file(CONFIG_FILENAME, 5)
|
||||||
self.assertTrue('this.that' in config)
|
self.assertTrue('this.that' in config)
|
||||||
l = config.get_multivar('this.that', 'foo.*')
|
l = config.get_multivar('this.that', 'foo.*')
|
||||||
self.assertEqual(len(l), 2)
|
self.assertEqual(2, len(list(l)))
|
||||||
|
|
||||||
config.set_multivar('this.that', '^.*beer', 'fool')
|
config.set_multivar('this.that', '^.*beer', 'fool')
|
||||||
l = config.get_multivar('this.that', 'fool')
|
l = list(config.get_multivar('this.that', 'fool'))
|
||||||
self.assertEqual(len(l), 1)
|
self.assertEqual(len(l), 1)
|
||||||
self.assertEqual(l[0], 'fool')
|
self.assertEqual(l[0], 'fool')
|
||||||
|
|
||||||
config.set_multivar('this.that', 'foo.*', 'foo-123456')
|
config.set_multivar('this.that', 'foo.*', 'foo-123456')
|
||||||
l = config.get_multivar('this.that', 'foo.*')
|
l = config.get_multivar('this.that', 'foo.*')
|
||||||
self.assertEqual(len(l), 2)
|
self.assertEqual(2, len(list(l)))
|
||||||
for i in l:
|
for i in l:
|
||||||
self.assertEqual(i, 'foo-123456')
|
self.assertEqual(i, 'foo-123456')
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user