diff --git a/pygit2/repository.py b/pygit2/repository.py index 038691436..3643e448a 100644 --- a/pygit2/repository.py +++ b/pygit2/repository.py @@ -40,7 +40,7 @@ import six # Import from pygit2 -from _pygit2 import Repository as _Repository +from _pygit2 import Repository as _Repository, init_file_backend from _pygit2 import Oid, GIT_OID_HEXSZ, GIT_OID_MINPREFIXLEN from _pygit2 import GIT_CHECKOUT_SAFE, GIT_CHECKOUT_RECREATE_MISSING, GIT_DIFF_NORMAL from _pygit2 import GIT_FILEMODE_LINK @@ -56,23 +56,12 @@ from .submodule import Submodule -class Repository(_Repository): +class BaseRepository(_Repository): - def __init__(self, path, *args, **kwargs): - if not isinstance(path, six.string_types): - path = path.decode('utf-8') - super(Repository, self).__init__(path, *args, **kwargs) + def __init__(self, backend, *args, **kwargs): + super(BaseRepository, self).__init__(backend, *args, **kwargs) self._common_init() - @classmethod - def _from_c(cls, ptr, owned): - cptr = ffi.new('git_repository **') - cptr[0] = ptr - repo = cls.__new__(cls) - super(cls, repo)._from_c(bytes(ffi.buffer(cptr)[:]), owned) - repo._common_init() - return repo - def _common_init(self): self.remotes = RemoteCollection(self) @@ -318,19 +307,19 @@ def diff(self, a=None, b=None, cached=False, flags=GIT_DIFF_NORMAL, Keyword arguments: a - None, a str (that refers to an Object, see revparse_single()) or a + None, a str (that refers to an Object, see revparse_single()) or a Reference object. If None, b must be None, too. In this case the working directory is compared with the index. Otherwise the referred object is compared to 'b'. - + b None, a str (that refers to an Object, see revparse_single()) or a Reference object. If None, the working directory is compared to 'a'. (except 'cached' is True, in which case the index is compared to 'a'). Otherwise the referred object is compared to 'a' - + cached if 'b' is None, by default the working directory is compared to 'a'. If 'cached' is set to True, the index/staging area is used for comparing. @@ -915,3 +904,21 @@ def set_ident(self, name, email): err = C.git_repository_set_ident(self._repo, to_bytes(name), to_bytes(email)) check_error(err) + + +class Repository(BaseRepository): + def __init__(self, path, *args, **kwargs): + if not isinstance(path, six.string_types): + path = path.decode('utf-8') + + path_backend = init_file_backend(path) + super(Repository, self).__init__(backend=path_backend, *args, **kwargs) + + @classmethod + def _from_c(cls, ptr, owned): + cptr = ffi.new('git_repository **') + cptr[0] = ptr + repo = cls.__new__(cls) + super(cls, repo)._from_c(bytes(ffi.buffer(cptr)[:]), owned) + repo._common_init() + return repo diff --git a/src/pygit2.c b/src/pygit2.c index 6eaafafe8..74ed953cc 100644 --- a/src/pygit2.c +++ b/src/pygit2.c @@ -144,7 +144,43 @@ hash(PyObject *self, PyObject *args) } +PyDoc_STRVAR(init_file_backend__doc__, + "init_file_backend(path) -> object\n" + "\n" + "open repo backend given path."); +PyObject * +init_file_backend(PyObject *self, PyObject *args) +{ + const char* path; + int err = GIT_OK; + git_repository *repository = NULL; + if (!PyArg_ParseTuple(args, "s", &path)) { + return NULL; + }; + + err = git_repository_open(&repository, path); + + if (err < 0) { + Error_set_str(err, path); + err = -1; + goto cleanup; + } + + return PyCapsule_New(repository, "backend", NULL); + +cleanup: + if (repository) + git_repository_free(repository); + + PyErr_Format(PyExc_Exception, + "Git error %d during construction of git repo", err); + return NULL; +} + + PyMethodDef module_methods[] = { + {"init_file_backend", init_file_backend, METH_VARARGS, + init_file_backend__doc__}, {"discover_repository", discover_repository, METH_VARARGS, discover_repository__doc__}, {"hashfile", hashfile, METH_VARARGS, hashfile__doc__}, diff --git a/src/repository.c b/src/repository.c index 355070e20..a5d67f70c 100644 --- a/src/repository.c +++ b/src/repository.c @@ -88,7 +88,7 @@ wrap_repository(git_repository *c_repo) int Repository_init(Repository *self, PyObject *args, PyObject *kwds) { - char *path; + PyObject *backend; int err; if (kwds && PyDict_Size(kwds) > 0) { @@ -97,15 +97,16 @@ Repository_init(Repository *self, PyObject *args, PyObject *kwds) return -1; } - if (!PyArg_ParseTuple(args, "s", &path)) - return -1; - - err = git_repository_open(&self->repo, path); - if (err < 0) { - Error_set_str(err, path); - return -1; + if (!PyArg_ParseTuple(args, "O", &backend)) { + return -1; } + self->repo = PyCapsule_GetPointer(backend, "backend"); + if (self->repo == NULL) { + PyErr_SetString(PyExc_TypeError, + "Repository unable to unpack backend."); + return -1; + } self->owned = 1; self->config = NULL; self->index = NULL; @@ -1747,7 +1748,7 @@ PyGetSetDef Repository_getseters[] = { PyDoc_STRVAR(Repository__doc__, - "Repository(path) -> Repository\n" + "Repository(backend) -> Repository\n" "\n" "Git repository."); @@ -1793,3 +1794,4 @@ PyTypeObject RepositoryType = { 0, /* tp_alloc */ 0, /* tp_new */ }; +