From 7e0041833fd57fa2f83921f7fa4410d3606d2d49 Mon Sep 17 00:00:00 2001 From: Edmundo Carmona Antoranz Date: Wed, 25 Jun 2025 22:34:37 +0200 Subject: [PATCH] index: map git_index_conflict_add map libgit2's git_index_conflict_add() as Index.add_conflict(). --- pygit2/decl/index.h | 5 +++++ pygit2/index.py | 35 +++++++++++++++++++++++++++++++++++ test/test_index.py | 24 +++++++++++++++++++++++- 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/pygit2/decl/index.h b/pygit2/decl/index.h index 60eba865..11a498cb 100644 --- a/pygit2/decl/index.h +++ b/pygit2/decl/index.h @@ -60,6 +60,11 @@ void git_index_conflict_iterator_free( int git_index_conflict_iterator_new( git_index_conflict_iterator **iterator_out, git_index *index); +int git_index_conflict_add( + git_index *index, + const git_index_entry *ancestor_entry, + const git_index_entry *our_entry, + const git_index_entry *their_entry); int git_index_conflict_get( const git_index_entry **ancestor_out, const git_index_entry **our_out, diff --git a/pygit2/index.py b/pygit2/index.py index 8f7bb0a9..ea8db1d0 100644 --- a/pygit2/index.py +++ b/pygit2/index.py @@ -223,6 +223,41 @@ def add(self, path_or_entry): check_error(err, io=True) + def add_conflict(self, ancestor, ours, theirs): + """ + Add or update index entries to represent a conflict. Any staged entries that + exist at the given paths will be removed. + + Parameters: + + ancestor + ancestor of the conflict + ours + ours side of the conflict + theirs + their side of the conflict + """ + + if ancestor and not isinstance(ancestor, IndexEntry): + raise TypeError('ancestor has to be an instance of IndexEntry or None') + if ours and not isinstance(ours, IndexEntry): + raise TypeError('ours has to be an instance of IndexEntry or None') + if theirs and not isinstance(theirs, IndexEntry): + raise TypeError('theirs has to be an instance of IndexEntry or None') + + centry_ancestor = centry_ours = centry_theirs = ffi.NULL + if ancestor is not None: + centry_ancestor, _ = ancestor._to_c() + if ours is not None: + centry_ours, _ = ours._to_c() + if theirs is not None: + centry_theirs, _ = theirs._to_c() + err = C.git_index_conflict_add( + self._index, centry_ancestor, centry_ours, centry_theirs + ) + + check_error(err, io=True) + def diff_to_workdir( self, flags: DiffOption = DiffOption.NORMAL, diff --git a/test/test_index.py b/test/test_index.py index 41c91e70..be425037 100644 --- a/test/test_index.py +++ b/test/test_index.py @@ -30,7 +30,7 @@ import pytest import pygit2 -from pygit2 import Repository, Index, Oid +from pygit2 import Repository, Index, Oid, IndexEntry from pygit2.enums import FileMode from . import utils @@ -311,3 +311,25 @@ def test_create_empty_read_tree_as_string(): def test_create_empty_read_tree(testrepo): index = Index() index.read_tree(testrepo['fd937514cb799514d4b81bb24c5fcfeb6472b245']) + + +def test_add_conflict(testrepo): + ancestor_blob_id = testrepo.create_blob('ancestor') + ancestor = IndexEntry('conflict.txt', ancestor_blob_id, FileMode.BLOB_EXECUTABLE) + + ours_blob_id = testrepo.create_blob('ours') + ours = IndexEntry('conflict.txt', ours_blob_id, FileMode.BLOB) + + index = Index() + assert index.conflicts is None + + index.add_conflict(ancestor, ours, None) + + assert index.conflicts is not None + assert 'conflict.txt' in index.conflicts + conflict = index.conflicts['conflict.txt'] + assert conflict[0].id == ancestor_blob_id + assert conflict[0].mode == FileMode.BLOB_EXECUTABLE + assert conflict[1].id == ours_blob_id + assert conflict[1].mode == FileMode.BLOB + assert conflict[2] is None