diff --git a/pygit2/decl.h b/pygit2/decl.h index b1ac828..8e439b7 100644 --- a/pygit2/decl.h +++ b/pygit2/decl.h @@ -7,6 +7,7 @@ typedef ... git_tree; typedef ... git_signature; typedef ... git_index; typedef ... git_diff; +typedef ... git_index_conflict_iterator; #define GIT_OID_RAWSZ ... #define GIT_PATH_MAX ... @@ -492,3 +493,8 @@ const git_index_entry *git_index_get_bypath(git_index *index, const char *path, const git_index_entry *git_index_get_byindex(git_index *index, size_t n); int git_index_add_all(git_index *index, const git_strarray *pathspec, unsigned int flags, git_index_matched_path_cb callback, void *payload); +int git_index_has_conflicts(const git_index *index); +void git_index_conflict_iterator_free(git_index_conflict_iterator *iterator); +int git_index_conflict_iterator_new(git_index_conflict_iterator **iterator_out, git_index *index); +int git_index_conflict_get(const git_index_entry **ancestor_out, const git_index_entry **our_out, const git_index_entry **their_out, git_index *index, const char *path); +int git_index_conflict_next(const git_index_entry **ancestor_out, const git_index_entry **our_out, const git_index_entry **their_out, git_index_conflict_iterator *iterator); diff --git a/pygit2/index.py b/pygit2/index.py index c41b4e0..eb1b5b6 100644 --- a/pygit2/index.py +++ b/pygit2/index.py @@ -195,6 +195,10 @@ class Index(object): check_error(err, True) + @property + def has_conflicts(self): + return C.git_index_has_conflicts(self._index) != 0 + def diff_to_workdir(self, flags=0, context_lines=3, interhunk_lines=0): """Diff the index against the working directory @@ -270,6 +274,13 @@ class Index(object): return Diff.from_c(bytes(ffi.buffer(cdiff)[:]), self._repo) + @property + def conflicts(self): + if not hasattr(self, '_conflicts'): + self._conflicts = ConflictCollection(self) + + return self._conflicts + class IndexEntry(object): __slots__ = ['id', 'path', 'mode', '_index'] @@ -299,6 +310,9 @@ class IndexEntry(object): @classmethod def _from_c(cls, centry): + if centry == ffi.NULL: + return None + entry = cls.__new__(cls) entry.path = ffi.string(centry.path).decode() entry.mode = centry.mode @@ -324,3 +338,57 @@ class IndexIterator(object): self.n += 1 return entry + +class ConflictCollection(object): + + def __init__(self, index): + self._index = index + + def __getitem__(self, path): + cancestor = ffi.new('git_index_entry **') + cours = ffi.new('git_index_entry **') + ctheirs = ffi.new('git_index_entry **') + + err = C.git_index_conflict_get(cancestor, cours, ctheirs, self._index._index, to_str(path)) + check_error(err) + + ancestor = IndexEntry._from_c(cancestor[0]) + ours = IndexEntry._from_c(cours[0]) + theirs = IndexEntry._from_c(ctheirs[0]) + + return ancestor, ours, theirs + + def __iter__(self): + return ConflictIterator(self._index) + +class ConflictIterator(object): + + def __init__(self, index): + citer = ffi.new('git_index_conflict_iterator **') + err = C.git_index_conflict_iterator_new(citer, index._index) + check_error(err) + self._index = index + self._iter = citer[0] + + def __del__(self): + C.git_index_conflict_iterator_free(self._iter) + + def next(self): + return self.__next__() + + def __next__(self): + cancestor = ffi.new('git_index_entry **') + cours = ffi.new('git_index_entry **') + ctheirs = ffi.new('git_index_entry **') + + err = C.git_index_conflict_next(cancestor, cours, ctheirs, self._iter) + if err == C.GIT_ITEROVER: + raise StopIteration + + check_error(err) + + ancestor = IndexEntry._from_c(cancestor[0]) + ours = IndexEntry._from_c(cours[0]) + theirs = IndexEntry._from_c(ctheirs[0]) + + return ancestor, ours, theirs