feat(merge): add ability to merge file from index

This commit is contained in:
Aleksey Kulikov 2021-10-04 12:23:48 +03:00
parent 5c8d6647eb
commit 52707dcc63
4 changed files with 87 additions and 1 deletions

View file

@ -89,6 +89,36 @@ void merge({
} }
} }
/// Merge two files as they exist in the index, using the given common ancestor
/// as the baseline, producing a string that reflects the merge result containing
/// possible conflicts.
///
/// Throws a [LibGit2Error] if error occured.
String mergeFileFromIndex({
required Pointer<git_repository> repoPointer,
required Pointer<git_index_entry>? ancestorPointer,
required Pointer<git_index_entry>? oursPointer,
required Pointer<git_index_entry>? theirsPointer,
}) {
final out = calloc<git_merge_file_result>();
final error = libgit2.git_merge_file_from_index(
out,
repoPointer,
ancestorPointer ?? nullptr,
oursPointer ?? nullptr,
theirsPointer ?? nullptr,
nullptr,
);
if (error < 0) {
throw LibGit2Error(libgit2.git_error_last());
} else {
final result = out.ref.ptr.cast<Utf8>().toDartString(length: out.ref.len);
calloc.free(out);
return result;
}
}
/// Merge two commits, producing a git_index that reflects the result of the merge. /// Merge two commits, producing a git_index that reflects the result of the merge.
/// The index may be written as-is to the working directory or checked out. If the index /// The index may be written as-is to the working directory or checked out. If the index
/// is to be converted to a tree, the caller should resolve any conflicts that arose as /// is to be converted to a tree, the caller should resolve any conflicts that arose as

View file

@ -256,9 +256,11 @@ class IndexEntry {
/// Initializes a new instance of [IndexEntry] class. /// Initializes a new instance of [IndexEntry] class.
const IndexEntry(this._indexEntryPointer); const IndexEntry(this._indexEntryPointer);
/// Pointer to memory address for allocated index entry object.
final Pointer<git_index_entry> _indexEntryPointer; final Pointer<git_index_entry> _indexEntryPointer;
/// Pointer to memory address for allocated index entry object.
Pointer<git_index_entry> get pointer => _indexEntryPointer;
/// Unique identity of the index entry. /// Unique identity of the index entry.
Oid get id => Oid.fromRaw(_indexEntryPointer.ref.id); Oid get id => Oid.fromRaw(_indexEntryPointer.ref.id);
@ -282,6 +284,11 @@ class IndexEntry {
/// Sets the UNIX file attributes of a index entry. /// Sets the UNIX file attributes of a index entry.
set mode(GitFilemode mode) => _indexEntryPointer.ref.mode = mode.value; set mode(GitFilemode mode) => _indexEntryPointer.ref.mode = mode.value;
@override
String toString() {
return 'IndexEntry{path: $path, sha: $sha}';
}
String _oidToHex(git_oid oid) { String _oidToHex(git_oid oid) {
var hex = StringBuffer(); var hex = StringBuffer();
for (var i = 0; i < 20; i++) { for (var i = 0; i < 20; i++) {

View file

@ -677,6 +677,24 @@ class Repository {
commit_bindings.annotatedFree(theirHead.value); commit_bindings.annotatedFree(theirHead.value);
} }
/// Merges two files as they exist in the index, using the given common ancestor
/// as the baseline, producing a string that reflects the merge result containing
/// possible conflicts.
///
/// Throws a [LibGit2Error] if error occured.
String mergeFileFromIndex({
required IndexEntry? ancestor,
required IndexEntry? ours,
required IndexEntry? theirs,
}) {
return merge_bindings.mergeFileFromIndex(
repoPointer: _repoPointer,
ancestorPointer: ancestor?.pointer,
oursPointer: ours?.pointer,
theirsPointer: theirs?.pointer,
);
}
/// Merges two commits, producing an index that reflects the result of the merge. /// Merges two commits, producing an index that reflects the result of the merge.
/// The index may be written as-is to the working directory or checked out. If the index /// The index may be written as-is to the working directory or checked out. If the index
/// is to be converted to a tree, the caller should resolve any conflicts that arose as /// is to be converted to a tree, the caller should resolve any conflicts that arose as

View file

@ -1,3 +1,5 @@
// ignore_for_file: unnecessary_string_escapes
import 'dart:io'; import 'dart:io';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'package:libgit2dart/libgit2dart.dart'; import 'package:libgit2dart/libgit2dart.dart';
@ -139,6 +141,35 @@ void main() {
conflictBranch.free(); conflictBranch.free();
}); });
group('merge file from index', () {
test('successfully merges', () {
const diffExpected = """
\<<<<<<< conflict_file
master conflict edit
=======
conflict branch edit
>>>>>>> conflict_file
""";
final conflictBranch = repo.branches['conflict-branch'];
final index = repo.index;
repo.merge(conflictBranch.target);
final diff = repo.mergeFileFromIndex(
ancestor: index.conflicts['conflict_file']!.ancestor,
ours: index.conflicts['conflict_file']!.our,
theirs: index.conflicts['conflict_file']!.their,
);
expect(
diff,
diffExpected,
);
index.free();
conflictBranch.free();
});
});
group('merge commits', () { group('merge commits', () {
test('successfully merges with default values', () { test('successfully merges with default values', () {
final theirCommit = final theirCommit =