mirror of
https://github.com/SkinnyMind/libgit2dart.git
synced 2025-05-05 04:39:07 -04:00
feat(index): add more bindings and api methods (#17)
This commit is contained in:
parent
7dd433dc08
commit
5264153749
5 changed files with 447 additions and 2 deletions
|
@ -5,6 +5,32 @@ import 'package:libgit2dart/src/bindings/libgit2_bindings.dart';
|
||||||
import 'package:libgit2dart/src/error.dart';
|
import 'package:libgit2dart/src/error.dart';
|
||||||
import 'package:libgit2dart/src/util.dart';
|
import 'package:libgit2dart/src/util.dart';
|
||||||
|
|
||||||
|
/// Read index capabilities flags.
|
||||||
|
int capabilities(Pointer<git_index> index) => libgit2.git_index_caps(index);
|
||||||
|
|
||||||
|
/// Set index capabilities flags.
|
||||||
|
///
|
||||||
|
/// If you pass [GitIndexCapability.fromOwner] for the caps, then capabilities
|
||||||
|
/// will be read from the config of the owner object, looking at
|
||||||
|
/// core.ignorecase, core.filemode, core.symlinks.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void setCapabilities({
|
||||||
|
required Pointer<git_index> indexPointer,
|
||||||
|
required int caps,
|
||||||
|
}) {
|
||||||
|
final error = libgit2.git_index_set_caps(indexPointer, caps);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the full path to the index file on disk.
|
||||||
|
String path(Pointer<git_index> index) {
|
||||||
|
return libgit2.git_index_path(index).cast<Utf8>().toDartString();
|
||||||
|
}
|
||||||
|
|
||||||
/// Update the contents of an existing index object in memory by reading from
|
/// Update the contents of an existing index object in memory by reading from
|
||||||
/// the hard disk.
|
/// the hard disk.
|
||||||
///
|
///
|
||||||
|
@ -133,6 +159,10 @@ Pointer<git_index_entry> getByPath({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the stage number from a git index entry.
|
||||||
|
int entryStage(Pointer<git_index_entry> entry) =>
|
||||||
|
libgit2.git_index_entry_stage(entry);
|
||||||
|
|
||||||
/// Clear the contents (all the entries) of an index object.
|
/// Clear the contents (all the entries) of an index object.
|
||||||
///
|
///
|
||||||
/// This clears the index object in memory; changes must be explicitly written
|
/// This clears the index object in memory; changes must be explicitly written
|
||||||
|
@ -194,6 +224,41 @@ void addByPath({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add or update an index entry from a buffer in memory.
|
||||||
|
///
|
||||||
|
/// This method will create a blob in the repository that owns the index and
|
||||||
|
/// then add the index entry to the index. The path of the entry represents the
|
||||||
|
/// position of the blob relative to the repository's root folder.
|
||||||
|
///
|
||||||
|
/// If a previous index entry exists that has the same path as the given
|
||||||
|
/// 'entry', it will be replaced. Otherwise, the 'entry' will be added.
|
||||||
|
///
|
||||||
|
/// This forces the file to be added to the index, not looking at gitignore
|
||||||
|
/// rules.
|
||||||
|
///
|
||||||
|
/// If this file currently is the result of a merge conflict, this file will no
|
||||||
|
/// longer be marked as conflicting. The data about the conflict will be moved
|
||||||
|
/// to the "resolve undo" (REUC) section.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void addFromBuffer({
|
||||||
|
required Pointer<git_index> indexPointer,
|
||||||
|
required Pointer<git_index_entry> entryPointer,
|
||||||
|
required String buffer,
|
||||||
|
}) {
|
||||||
|
final bufferC = buffer.toNativeUtf8().cast<Int8>();
|
||||||
|
final error = libgit2.git_index_add_from_buffer(
|
||||||
|
indexPointer,
|
||||||
|
entryPointer,
|
||||||
|
bufferC.cast(),
|
||||||
|
buffer.length,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Add or update index entries matching files in the working directory.
|
/// Add or update index entries matching files in the working directory.
|
||||||
///
|
///
|
||||||
/// This method will fail in bare index instances.
|
/// This method will fail in bare index instances.
|
||||||
|
@ -239,6 +304,50 @@ void addAll({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update all index entries to match the working directory.
|
||||||
|
///
|
||||||
|
/// This method will fail in bare index instances.
|
||||||
|
///
|
||||||
|
/// This scans the existing index entries and synchronizes them with the
|
||||||
|
/// working directory, deleting them if the corresponding working directory
|
||||||
|
/// file no longer exists otherwise updating the information (including adding
|
||||||
|
/// the latest version of file to the ODB if needed).
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void updateAll({
|
||||||
|
required Pointer<git_index> indexPointer,
|
||||||
|
required List<String> pathspec,
|
||||||
|
}) {
|
||||||
|
final pathspecC = calloc<git_strarray>();
|
||||||
|
final pathPointers =
|
||||||
|
pathspec.map((e) => e.toNativeUtf8().cast<Int8>()).toList();
|
||||||
|
final strArray = calloc<Pointer<Int8>>(pathspec.length);
|
||||||
|
|
||||||
|
for (var i = 0; i < pathspec.length; i++) {
|
||||||
|
strArray[i] = pathPointers[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
pathspecC.ref.strings = strArray;
|
||||||
|
pathspecC.ref.count = pathspec.length;
|
||||||
|
|
||||||
|
final error = libgit2.git_index_update_all(
|
||||||
|
indexPointer,
|
||||||
|
pathspecC,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
);
|
||||||
|
|
||||||
|
calloc.free(pathspecC);
|
||||||
|
for (final p in pathPointers) {
|
||||||
|
calloc.free(p);
|
||||||
|
}
|
||||||
|
calloc.free(strArray);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Write an existing index object from memory back to disk using an atomic
|
/// Write an existing index object from memory back to disk using an atomic
|
||||||
/// file lock.
|
/// file lock.
|
||||||
void write(Pointer<git_index> index) => libgit2.git_index_write(index);
|
void write(Pointer<git_index> index) => libgit2.git_index_write(index);
|
||||||
|
@ -261,6 +370,17 @@ void remove({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove all entries from the index under a given directory.
|
||||||
|
void removeDirectory({
|
||||||
|
required Pointer<git_index> indexPointer,
|
||||||
|
required String dir,
|
||||||
|
required int stage,
|
||||||
|
}) {
|
||||||
|
final dirC = dir.toNativeUtf8().cast<Int8>();
|
||||||
|
libgit2.git_index_remove_directory(indexPointer, dirC, stage);
|
||||||
|
calloc.free(dirC);
|
||||||
|
}
|
||||||
|
|
||||||
/// Remove all matching index entries.
|
/// Remove all matching index entries.
|
||||||
void removeAll({
|
void removeAll({
|
||||||
required Pointer<git_index> indexPointer,
|
required Pointer<git_index> indexPointer,
|
||||||
|
@ -332,6 +452,39 @@ List<Map<String, Pointer<git_index_entry>>> conflictList(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return whether the given index entry is a conflict (has a high stage entry).
|
||||||
|
/// This is simply shorthand for [entryStage] > 0.
|
||||||
|
bool entryIsConflict(Pointer<git_index_entry> entry) {
|
||||||
|
return libgit2.git_index_entry_is_conflict(entry) == 1 || false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add or update index entries to represent a conflict. Any staged entries
|
||||||
|
/// that exist at the given paths will be removed.
|
||||||
|
///
|
||||||
|
/// The entries are the entries from the tree included in the merge. Any entry
|
||||||
|
/// may be null to indicate that that file was not present in the trees during
|
||||||
|
/// the merge. For example, [ancestorEntryPointer] may be null to indicate that
|
||||||
|
/// a file was added in both branches and must be resolved.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void conflictAdd({
|
||||||
|
required Pointer<git_index> indexPointer,
|
||||||
|
Pointer<git_index_entry>? ancestorEntryPointer,
|
||||||
|
Pointer<git_index_entry>? ourEntryPointer,
|
||||||
|
Pointer<git_index_entry>? theirEntryPointer,
|
||||||
|
}) {
|
||||||
|
final error = libgit2.git_index_conflict_add(
|
||||||
|
indexPointer,
|
||||||
|
ancestorEntryPointer ?? nullptr,
|
||||||
|
ourEntryPointer ?? nullptr,
|
||||||
|
theirEntryPointer ?? nullptr,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Removes the index entries that represent a conflict of a single file.
|
/// Removes the index entries that represent a conflict of a single file.
|
||||||
///
|
///
|
||||||
/// Throws a [LibGit2Error] if error occured.
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
@ -349,6 +502,17 @@ void conflictRemove({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove all conflicts in the index (entries with a stage greater than 0).
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void conflictCleanup(Pointer<git_index> index) {
|
||||||
|
final error = libgit2.git_index_conflict_cleanup(index);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the repository this index relates to.
|
/// Get the repository this index relates to.
|
||||||
Pointer<git_repository> owner(Pointer<git_index> index) =>
|
Pointer<git_repository> owner(Pointer<git_index> index) =>
|
||||||
libgit2.git_index_owner(index);
|
libgit2.git_index_owner(index);
|
||||||
|
|
|
@ -1704,3 +1704,27 @@ class GitSubmoduleStatus {
|
||||||
@override
|
@override
|
||||||
String toString() => 'GitSubmoduleStatus.$_name';
|
String toString() => 'GitSubmoduleStatus.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Capabilities of system that affect index actions.
|
||||||
|
class GitIndexCapability {
|
||||||
|
const GitIndexCapability._(this._value, this._name);
|
||||||
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
|
static const ignoreCase = GitIndexCapability._(1, 'ignoreCase');
|
||||||
|
static const noFileMode = GitIndexCapability._(2, 'noFileMode');
|
||||||
|
static const noSymlinks = GitIndexCapability._(4, 'noSymlinks');
|
||||||
|
static const fromOwner = GitIndexCapability._(-1, 'fromOwner');
|
||||||
|
|
||||||
|
static const List<GitIndexCapability> values = [
|
||||||
|
ignoreCase,
|
||||||
|
noFileMode,
|
||||||
|
noSymlinks,
|
||||||
|
fromOwner,
|
||||||
|
];
|
||||||
|
|
||||||
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitIndexCapability.$_name';
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,24 @@ class Index with IterableMixin<IndexEntry> {
|
||||||
/// Pointer to memory address for allocated index object.
|
/// Pointer to memory address for allocated index object.
|
||||||
Pointer<git_index> get pointer => _indexPointer;
|
Pointer<git_index> get pointer => _indexPointer;
|
||||||
|
|
||||||
|
/// Full path to the index file on disk.
|
||||||
|
String get path => bindings.path(_indexPointer);
|
||||||
|
|
||||||
|
/// Index capabilities flags.
|
||||||
|
Set<GitIndexCapability> get capabilities {
|
||||||
|
final capInt = bindings.capabilities(_indexPointer);
|
||||||
|
return GitIndexCapability.values
|
||||||
|
.where((e) => capInt & e.value == e.value)
|
||||||
|
.toSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
set capabilities(Set<GitIndexCapability> flags) {
|
||||||
|
bindings.setCapabilities(
|
||||||
|
indexPointer: _indexPointer,
|
||||||
|
caps: flags.fold(0, (acc, e) => acc | e.value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns index entry located at provided 0-based position or string path.
|
/// Returns index entry located at provided 0-based position or string path.
|
||||||
///
|
///
|
||||||
/// Throws [RangeError] when provided [value] is outside of valid range or
|
/// Throws [RangeError] when provided [value] is outside of valid range or
|
||||||
|
@ -85,6 +103,39 @@ class Index with IterableMixin<IndexEntry> {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds or updates index entries to represent a conflict. Any staged entries
|
||||||
|
/// that exist at the given paths will be removed.
|
||||||
|
///
|
||||||
|
/// The entries are the entries from the tree included in the merge. Any entry
|
||||||
|
/// may be null to indicate that that file was not present in the trees during
|
||||||
|
/// the merge. For example, [ancestorEntry] may be null to indicate
|
||||||
|
/// that a file was added in both branches and must be resolved.
|
||||||
|
///
|
||||||
|
/// [ancestorEntry] is the entry data for the ancestor of the conflict.
|
||||||
|
///
|
||||||
|
/// [ourEntry] is the entry data for our side of the merge conflict.
|
||||||
|
///
|
||||||
|
/// [theirEntry] is the entry data for their side of the merge conflict.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void addConflict({
|
||||||
|
IndexEntry? ancestorEntry,
|
||||||
|
IndexEntry? ourEntry,
|
||||||
|
IndexEntry? theirEntry,
|
||||||
|
}) {
|
||||||
|
bindings.conflictAdd(
|
||||||
|
indexPointer: _indexPointer,
|
||||||
|
ancestorEntryPointer: ancestorEntry?.pointer,
|
||||||
|
ourEntryPointer: ourEntry?.pointer,
|
||||||
|
theirEntryPointer: theirEntry?.pointer,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes all conflicts in the index (entries with a stage greater than 0).
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void cleanupConflict() => bindings.conflictCleanup(_indexPointer);
|
||||||
|
|
||||||
/// Clears the contents (all the entries) of an index object.
|
/// Clears the contents (all the entries) of an index object.
|
||||||
///
|
///
|
||||||
/// This clears the index object in memory; changes must be explicitly
|
/// This clears the index object in memory; changes must be explicitly
|
||||||
|
@ -116,6 +167,31 @@ class Index with IterableMixin<IndexEntry> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds or updates an index [entry] from a [buffer] in memory.
|
||||||
|
///
|
||||||
|
/// This method will create a blob in the repository that owns the index and
|
||||||
|
/// then add the index entry to the index. The path of the entry represents
|
||||||
|
/// the position of the blob relative to the repository's root folder.
|
||||||
|
///
|
||||||
|
/// If a previous index entry exists that has the same path as the given
|
||||||
|
/// 'entry', it will be replaced. Otherwise, the 'entry' will be added.
|
||||||
|
///
|
||||||
|
/// This forces the file to be added to the index, not looking at gitignore
|
||||||
|
/// rules.
|
||||||
|
///
|
||||||
|
/// If this file currently is the result of a merge conflict, this file will
|
||||||
|
/// no longer be marked as conflicting. The data about the conflict will be
|
||||||
|
/// moved to the "resolve undo" (REUC) section.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void addFromBuffer({required IndexEntry entry, required String buffer}) {
|
||||||
|
bindings.addFromBuffer(
|
||||||
|
indexPointer: _indexPointer,
|
||||||
|
entryPointer: entry.pointer,
|
||||||
|
buffer: buffer,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds or updates index entries matching files in the working directory.
|
/// Adds or updates index entries matching files in the working directory.
|
||||||
///
|
///
|
||||||
/// This method will fail in bare index instances.
|
/// This method will fail in bare index instances.
|
||||||
|
@ -130,6 +206,20 @@ class Index with IterableMixin<IndexEntry> {
|
||||||
bindings.addAll(indexPointer: _indexPointer, pathspec: pathspec);
|
bindings.addAll(indexPointer: _indexPointer, pathspec: pathspec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates all index entries to match the working directory.
|
||||||
|
///
|
||||||
|
/// This method will fail in bare index instances.
|
||||||
|
///
|
||||||
|
/// This scans the existing index entries and synchronizes them with the
|
||||||
|
/// working directory, deleting them if the corresponding working directory
|
||||||
|
/// file no longer exists otherwise updating the information (including adding
|
||||||
|
/// the latest version of file to the ODB if needed).
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
void updateAll(List<String> pathspec) {
|
||||||
|
bindings.updateAll(indexPointer: _indexPointer, pathspec: pathspec);
|
||||||
|
}
|
||||||
|
|
||||||
/// Updates the contents of an existing index object in memory by reading
|
/// Updates the contents of an existing index object in memory by reading
|
||||||
/// from the hard disk.
|
/// from the hard disk.
|
||||||
///
|
///
|
||||||
|
@ -185,6 +275,16 @@ class Index with IterableMixin<IndexEntry> {
|
||||||
void remove(String path, [int stage = 0]) =>
|
void remove(String path, [int stage = 0]) =>
|
||||||
bindings.remove(indexPointer: _indexPointer, path: path, stage: stage);
|
bindings.remove(indexPointer: _indexPointer, path: path, stage: stage);
|
||||||
|
|
||||||
|
/// Removes all entries from the index under a given [directory] with
|
||||||
|
/// optional [stage].
|
||||||
|
void removeDirectory(String directory, [int stage = 0]) {
|
||||||
|
bindings.removeDirectory(
|
||||||
|
indexPointer: _indexPointer,
|
||||||
|
dir: directory,
|
||||||
|
stage: stage,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Removes all matching index entries at provided list of [path]s relative
|
/// Removes all matching index entries at provided list of [path]s relative
|
||||||
/// to repository working directory.
|
/// to repository working directory.
|
||||||
///
|
///
|
||||||
|
@ -286,9 +386,15 @@ 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;
|
||||||
|
|
||||||
|
/// Stage number.
|
||||||
|
int get stage => bindings.entryStage(_indexEntryPointer);
|
||||||
|
|
||||||
|
/// Whether the given index entry is a conflict (has a high stage entry).
|
||||||
|
bool get isConflict => bindings.entryIsConflict(_indexEntryPointer);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'IndexEntry{oid: $oid, path: $path, mode: $mode}';
|
return 'IndexEntry{oid: $oid, path: $path, mode: $mode, stage: $stage}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -561,5 +561,20 @@ void main() {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('GitIndexCapability', () {
|
||||||
|
test('returns correct values', () {
|
||||||
|
const expected = [1, 2, 4, -1];
|
||||||
|
final actual = GitIndexCapability.values.map((e) => e.value).toList();
|
||||||
|
expect(actual, expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns string representation of object', () {
|
||||||
|
expect(
|
||||||
|
GitIndexCapability.ignoreCase.toString(),
|
||||||
|
'GitIndexCapability.ignoreCase',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,37 @@ void main() {
|
||||||
const fileSha = 'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391';
|
const fileSha = 'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391';
|
||||||
const featureFileSha = '9c78c21d6680a7ffebc76f7ac68cacc11d8f48bc';
|
const featureFileSha = '9c78c21d6680a7ffebc76f7ac68cacc11d8f48bc';
|
||||||
|
|
||||||
|
test('returns full path to the index file on disk', () {
|
||||||
|
expect(index.path, '${repo.path}index');
|
||||||
|
});
|
||||||
|
|
||||||
|
group('capabilities', () {
|
||||||
|
test('returns index capabilities', () {
|
||||||
|
expect(index.capabilities, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully sets index capabilities', () {
|
||||||
|
expect(index.capabilities, isEmpty);
|
||||||
|
|
||||||
|
index.capabilities = {
|
||||||
|
GitIndexCapability.ignoreCase,
|
||||||
|
GitIndexCapability.noSymlinks,
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(index.capabilities, {
|
||||||
|
GitIndexCapability.ignoreCase,
|
||||||
|
GitIndexCapability.noSymlinks,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws when trying to set index capabilities and error occurs', () {
|
||||||
|
expect(
|
||||||
|
() => Index(nullptr).capabilities = {},
|
||||||
|
throwsA(isA<LibGit2Error>()),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('returns number of entries', () {
|
test('returns number of entries', () {
|
||||||
expect(index.length, 4);
|
expect(index.length, 4);
|
||||||
});
|
});
|
||||||
|
@ -37,6 +68,10 @@ void main() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('returns stage of entry', () {
|
||||||
|
expect(index['file'].stage, 0);
|
||||||
|
});
|
||||||
|
|
||||||
test('returns index entry at provided position', () {
|
test('returns index entry at provided position', () {
|
||||||
expect(index[3].path, 'file');
|
expect(index[3].path, 'file');
|
||||||
expect(index[3].oid.sha, fileSha);
|
expect(index[3].oid.sha, fileSha);
|
||||||
|
@ -118,6 +153,26 @@ void main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('addFromBuffer()', () {
|
||||||
|
test('successfully updates index entry from a buffer', () {
|
||||||
|
final entry = index['file'];
|
||||||
|
expect(repo.status, isEmpty);
|
||||||
|
|
||||||
|
index.addFromBuffer(entry: entry, buffer: 'updated');
|
||||||
|
expect(repo.status, {
|
||||||
|
'file': {GitStatus.indexModified, GitStatus.wtModified}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws when trying to update entry and error occurs', () {
|
||||||
|
final nullEntry = IndexEntry(nullptr);
|
||||||
|
expect(
|
||||||
|
() => index.addFromBuffer(entry: nullEntry, buffer: ''),
|
||||||
|
throwsA(isA<LibGit2Error>()),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
group('addAll()', () {
|
group('addAll()', () {
|
||||||
test('successfully adds with provided pathspec', () {
|
test('successfully adds with provided pathspec', () {
|
||||||
index.clear();
|
index.clear();
|
||||||
|
@ -152,6 +207,33 @@ void main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('updateAll()', () {
|
||||||
|
test('successfully updates all entries to match working directory', () {
|
||||||
|
expect(repo.status, isEmpty);
|
||||||
|
File('${repo.workdir}file').deleteSync();
|
||||||
|
File('${repo.workdir}feature_file').deleteSync();
|
||||||
|
|
||||||
|
index.updateAll(['file', 'feature_file']);
|
||||||
|
expect(repo.status, {
|
||||||
|
'file': {GitStatus.indexDeleted},
|
||||||
|
'feature_file': {GitStatus.indexDeleted},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws when trying to update all entries in bare repository', () {
|
||||||
|
final bare = Repository.open('test/assets/empty_bare.git');
|
||||||
|
final bareIndex = bare.index;
|
||||||
|
|
||||||
|
expect(
|
||||||
|
() => bareIndex.updateAll(['not_there']),
|
||||||
|
throwsA(isA<LibGit2Error>()),
|
||||||
|
);
|
||||||
|
|
||||||
|
bareIndex.free();
|
||||||
|
bare.free();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('writes to disk', () {
|
test('writes to disk', () {
|
||||||
expect(index.length, 4);
|
expect(index.length, 4);
|
||||||
|
|
||||||
|
@ -186,6 +268,17 @@ void main() {
|
||||||
expect(index.find('feature_file'), false);
|
expect(index.find('feature_file'), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('removes all entries from a directory', () {
|
||||||
|
Directory('${repo.workdir}subdir/').createSync();
|
||||||
|
File('${repo.workdir}subdir/subfile').createSync();
|
||||||
|
|
||||||
|
index.add('subdir/subfile');
|
||||||
|
expect(index.length, 5);
|
||||||
|
|
||||||
|
index.removeDirectory('subdir');
|
||||||
|
expect(index.length, 4);
|
||||||
|
});
|
||||||
|
|
||||||
test('successfully reads tree with provided SHA hex', () {
|
test('successfully reads tree with provided SHA hex', () {
|
||||||
final tree = repo.lookupTree(
|
final tree = repo.lookupTree(
|
||||||
repo['df2b8fc99e1c1d4dbc0a854d9f72157f1d6ea078'],
|
repo['df2b8fc99e1c1d4dbc0a854d9f72157f1d6ea078'],
|
||||||
|
@ -228,6 +321,19 @@ void main() {
|
||||||
tmpDir.deleteSync(recursive: true);
|
tmpDir.deleteSync(recursive: true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('successfully adds conflict entry', () {
|
||||||
|
expect(index.conflicts, isEmpty);
|
||||||
|
index.addConflict(
|
||||||
|
ourEntry: index['file'],
|
||||||
|
theirEntry: index['feature_file'],
|
||||||
|
);
|
||||||
|
expect(index.conflicts.length, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws when trying to add conflict entry and error occurs', () {
|
||||||
|
expect(() => Index(nullptr).addConflict(), throwsA(isA<LibGit2Error>()));
|
||||||
|
});
|
||||||
|
|
||||||
test('returns conflicts with ancestor, our and their present', () {
|
test('returns conflicts with ancestor, our and their present', () {
|
||||||
final repoDir = setupRepo(Directory('test/assets/mergerepo/'));
|
final repoDir = setupRepo(Directory('test/assets/mergerepo/'));
|
||||||
final conflictRepo = Repository.open(repoDir.path);
|
final conflictRepo = Repository.open(repoDir.path);
|
||||||
|
@ -322,7 +428,7 @@ void main() {
|
||||||
repoDir.deleteSync(recursive: true);
|
repoDir.deleteSync(recursive: true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('successfully removes conflicts', () {
|
test('successfully removes conflict', () {
|
||||||
final repoDir = setupRepo(Directory('test/assets/mergerepo/'));
|
final repoDir = setupRepo(Directory('test/assets/mergerepo/'));
|
||||||
final conflictRepo = Repository.open(repoDir.path);
|
final conflictRepo = Repository.open(repoDir.path);
|
||||||
|
|
||||||
|
@ -331,6 +437,8 @@ void main() {
|
||||||
|
|
||||||
conflictRepo.merge(conflictBranch.target);
|
conflictRepo.merge(conflictBranch.target);
|
||||||
expect(index.hasConflicts, true);
|
expect(index.hasConflicts, true);
|
||||||
|
expect(index['.gitignore'].isConflict, false);
|
||||||
|
expect(index.conflicts['conflict_file']!.our!.isConflict, true);
|
||||||
expect(index.conflicts.length, 1);
|
expect(index.conflicts.length, 1);
|
||||||
|
|
||||||
final conflictedFile = index.conflicts['conflict_file']!;
|
final conflictedFile = index.conflicts['conflict_file']!;
|
||||||
|
@ -353,6 +461,34 @@ void main() {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('successfully removes all conflicts', () {
|
||||||
|
final repoDir = setupRepo(Directory('test/assets/mergerepo/'));
|
||||||
|
final conflictRepo = Repository.open(repoDir.path);
|
||||||
|
|
||||||
|
final conflictBranch = conflictRepo.lookupBranch(name: 'conflict-branch');
|
||||||
|
final index = conflictRepo.index;
|
||||||
|
|
||||||
|
conflictRepo.merge(conflictBranch.target);
|
||||||
|
expect(index.hasConflicts, true);
|
||||||
|
expect(index.conflicts.length, 1);
|
||||||
|
|
||||||
|
index.cleanupConflict();
|
||||||
|
expect(index.hasConflicts, false);
|
||||||
|
expect(index.conflicts, isEmpty);
|
||||||
|
|
||||||
|
index.free();
|
||||||
|
conflictBranch.free();
|
||||||
|
conflictRepo.free();
|
||||||
|
repoDir.deleteSync(recursive: true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws when trying to remove all conflicts and error occurs', () {
|
||||||
|
expect(
|
||||||
|
() => Index(nullptr).cleanupConflict(),
|
||||||
|
throwsA(isA<LibGit2Error>()),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('returns string representation of Index and IndexEntry objects', () {
|
test('returns string representation of Index and IndexEntry objects', () {
|
||||||
final index = repo.index;
|
final index = repo.index;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue