Description
Hi all,
first of all, I would like to thank you for providing this awesome libgit2 wrapper, including the searchable docs.rs documentation. This already helped me a lot in my project!
I am currently struggling to get an in-memory merge conflict resolution done with the libgit2. But let's first explain why I am seeking for in-memory conflict resolution:
- I am currently building a rust-library for the pass password store. I would like to provide an easy-to-use API backed by git for decentralized synchronization (e.g. without a server) from device-to-device over e.g. the local network, ad-hoc wifi, etc. The original pass implementation (shell-script) just delegates the synchronization to git by mirroring the git cli. I therefore decided to base my synchronization approach on git as well, to make it (at least theoretically) compatible.
- As from a user perspective a synchronization is either successful or not (maybe requiring some manual conflict resolution via e.g. a GUI popup), I would like to do the messing with git stages, etc. in-memory to prevent interfering with other tools handling a
pass
password store (e.g. the original cli, the qt intercace, the Firefox extension, etc.). Therefore, I thought that checking out a conflicted index to the repository is not a good idea. Also, if my lib crashes, is quit by the user, etc. my library would have to somehow continue a conflict resolution of a previous run. Furthermore, if multiple instances of my library or another pass implementation are running on the same repository I might run into race condition problems, etc. Those problems are ofc fixable with e.g. locks but it makes the implementation way more complex. That's why I settled with in-memory conflict resolution of a conflicted index.
So, what exactly is my problem? I have (somewhat) the following code:
let mut index = self.repo.merge_trees(&ancestor, &local_tree, &remote_tree, None)?;
// go over index.conflicts() and resolve them
// in pass passwords are gpg encrypted, not really relevant for this issue
index.add_frombuffer(new_index_entry, &encrypted_resolved_password_content)?;
However, this errors with could not initialize index entry. Index is not backed up by an existing repository.
Which is true, I could not (yet) do e.g. a index.write_tree_to(repo)
as my index still contains conflicts. So I tried another variant:
let mut index = self.repo.merge_trees(&ancestor, &local_tree, &remote_tree, None)?;
// go over index.conflicts() and resolve them
let oid = repo.blob(&encrypted_resolved_password_content)?;
index_entry.file_size = encrypted_resolved_password_content.len() as u32;
index_entry.id = oid;
index.add(&index_entry)?;
let result_tree = repo.find_tree(index.write_tree_to(repo)?)?;
But this fails on write_tree_to
as the conflict has not been marked as resolved. I checked the libgit2 C source code and found out that only index.add_bypath
and index.add_frombuffer
mark a conflict as resolved, but not index.add
(although I might have missed sth in the C source).
There are the git_index_conflict_remove
and git_index_conflict_cleanup
functions present in libgit2 but those are not available in the git2-rs
wrapper. They are indeed available in the libgit2-sys
crate but not usable as I require access to the raw pointers of the index in order to use them which I do not have in git2-rs
. Also, I am not sure whether these functions are actually necessary to solve my problem, I have not checked this as I would like to avoid reimplementing my rust code in C to check whether these two functions would make it work.
I could not find working examples on how to resolve merge conflicts in-memory with git (wondering now if it's even possible...). My question is: are git_index_conflict_remove
and git_index_conflict_cleanup
necessary for this and if so, why are these functions missing from git2-rs
?
Thank you in advance for any help!