mirror of
https://github.com/SkinnyMind/libgit2dart.git
synced 2025-05-05 20:59:08 -04:00
feat(revwalk): add bindings and api
This commit is contained in:
parent
e0e3742457
commit
2e0486c641
7 changed files with 424 additions and 0 deletions
136
lib/src/bindings/revwalk.dart
Normal file
136
lib/src/bindings/revwalk.dart
Normal file
|
@ -0,0 +1,136 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'libgit2_bindings.dart';
|
||||
import 'commit.dart' as commit_bindings;
|
||||
import '../error.dart';
|
||||
import '../util.dart';
|
||||
|
||||
/// Allocate a new revision walker to iterate through a repo.
|
||||
///
|
||||
/// This revision walker uses a custom memory pool and an internal commit cache,
|
||||
/// so it is relatively expensive to allocate.
|
||||
///
|
||||
/// For maximum performance, this revision walker should be reused for different walks.
|
||||
///
|
||||
/// This revision walker is not thread safe: it may only be used to walk a repository
|
||||
/// on a single thread; however, it is possible to have several revision walkers in several
|
||||
/// different threads walking the same repository.
|
||||
///
|
||||
/// Throws a [LibGit2Error] if error occured.
|
||||
Pointer<git_revwalk> create(Pointer<git_repository> repo) {
|
||||
final out = calloc<Pointer<git_revwalk>>();
|
||||
final error = libgit2.git_revwalk_new(out, repo);
|
||||
|
||||
if (error < 0) {
|
||||
throw LibGit2Error(libgit2.git_error_last());
|
||||
} else {
|
||||
return out.value;
|
||||
}
|
||||
}
|
||||
|
||||
/// Change the sorting mode when iterating through the repository's contents.
|
||||
///
|
||||
/// Changing the sorting mode resets the walker.
|
||||
///
|
||||
/// Throws a [LibGit2Error] if error occured.
|
||||
void sorting(Pointer<git_revwalk> walker, int sortMode) {
|
||||
final error = libgit2.git_revwalk_sorting(walker, sortMode);
|
||||
|
||||
if (error < 0) {
|
||||
throw LibGit2Error(libgit2.git_error_last());
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a new root for the traversal.
|
||||
///
|
||||
/// The pushed commit will be marked as one of the roots from which to start the walk.
|
||||
/// This commit may not be walked if it or a child is hidden.
|
||||
///
|
||||
/// At least one commit must be pushed onto the walker before a walk can be started.
|
||||
///
|
||||
/// The given id must belong to a committish on the walked repository.
|
||||
///
|
||||
/// Throws a [LibGit2Error] if error occured.
|
||||
void push(Pointer<git_revwalk> walker, Pointer<git_oid> id) {
|
||||
final error = libgit2.git_revwalk_push(walker, id);
|
||||
|
||||
if (error < 0) {
|
||||
throw LibGit2Error(libgit2.git_error_last());
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the list of commits from the revision walk.
|
||||
///
|
||||
/// The initial call to this method is not blocking when iterating through a repo
|
||||
/// with a time-sorting mode.
|
||||
///
|
||||
/// Iterating with Topological or inverted modes makes the initial call blocking to
|
||||
/// preprocess the commit list, but this block should be mostly unnoticeable on most
|
||||
/// repositories (topological preprocessing times at 0.3s on the git.git repo).
|
||||
///
|
||||
/// The revision walker is reset when the walk is over.
|
||||
List<Pointer<git_commit>> walk(
|
||||
Pointer<git_repository> repo,
|
||||
Pointer<git_revwalk> walker,
|
||||
) {
|
||||
var result = <Pointer<git_commit>>[];
|
||||
var error = 0;
|
||||
|
||||
while (error == 0) {
|
||||
final oid = calloc<git_oid>();
|
||||
error = libgit2.git_revwalk_next(oid, walker);
|
||||
if (error == 0) {
|
||||
final commit = commit_bindings.lookup(repo, oid);
|
||||
result.add(commit);
|
||||
calloc.free(oid);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Mark a commit (and its ancestors) uninteresting for the output.
|
||||
///
|
||||
/// The given id must belong to a committish on the walked repository.
|
||||
///
|
||||
/// The resolved commit and all its parents will be hidden from the output on the revision walk.
|
||||
///
|
||||
/// Throws a [LibGit2Error] if error occured.
|
||||
void hide(Pointer<git_revwalk> walk, Pointer<git_oid> oid) {
|
||||
final error = libgit2.git_revwalk_hide(walk, oid);
|
||||
|
||||
if (error < 0) {
|
||||
throw LibGit2Error(libgit2.git_error_last());
|
||||
}
|
||||
}
|
||||
|
||||
/// Reset the revision walker for reuse.
|
||||
///
|
||||
/// This will clear all the pushed and hidden commits, and leave the walker in a blank state
|
||||
/// (just like at creation) ready to receive new commit pushes and start a new walk.
|
||||
///
|
||||
/// The revision walk is automatically reset when a walk is over.
|
||||
void reset(Pointer<git_revwalk> walker) => libgit2.git_revwalk_reset(walker);
|
||||
|
||||
/// Simplify the history by first-parent.
|
||||
///
|
||||
/// No parents other than the first for each commit will be enqueued.
|
||||
///
|
||||
/// Throws a [LibGit2Error] if error occured.
|
||||
void simplifyFirstParent(Pointer<git_revwalk> walk) {
|
||||
final error = libgit2.git_revwalk_simplify_first_parent(walk);
|
||||
|
||||
if (error < 0) {
|
||||
throw LibGit2Error(libgit2.git_error_last());
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the repository on which this walker is operating.
|
||||
Pointer<git_repository> repository(Pointer<git_revwalk> walker) {
|
||||
return libgit2.git_revwalk_repository(walker);
|
||||
}
|
||||
|
||||
/// Free a revision walker previously allocated.
|
||||
void free(Pointer<git_revwalk> walk) => libgit2.git_revwalk_free(walk);
|
Loading…
Add table
Add a link
Reference in a new issue