refactor(checkout)!: move checkout related methods into Checkout class (#42)

This commit is contained in:
Aleksey Kulikov 2022-01-25 20:16:46 +03:00 committed by GitHub
parent 570c696269
commit 9918ab0905
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 238 additions and 135 deletions

View file

@ -3,6 +3,7 @@ export 'src/blame.dart';
export 'src/blob.dart';
export 'src/branch.dart';
export 'src/callbacks.dart';
export 'src/checkout.dart';
export 'src/commit.dart';
export 'src/config.dart';
export 'src/credentials.dart';

View file

@ -83,8 +83,6 @@ void index({
/// Updates files in the index and working tree to match the content of the tree
/// pointed at by the treeish.
///
/// Throws a [LibGit2Error] if error occured.
void tree({
required Pointer<git_repository> repoPointer,
required Pointer<git_object> treeishPointer,

161
lib/src/checkout.dart Normal file
View file

@ -0,0 +1,161 @@
import 'package:libgit2dart/libgit2dart.dart';
import 'package:libgit2dart/src/bindings/checkout.dart' as bindings;
import 'package:libgit2dart/src/bindings/object.dart' as object_bindings;
class Checkout {
const Checkout._();
/// Updates files in the index and the working tree to match the content of
/// the commit pointed at by HEAD.
///
/// Note that this is **not** the correct mechanism used to switch branches;
/// do not change your HEAD and then call this method, that would leave you
/// with checkout conflicts since your working directory would then appear
/// to be dirty. Instead, checkout the target of the branch and then update
/// HEAD using [Repository]'s `setHead` to point to the branch you checked
/// out.
///
/// [repo] is the repository into which to check out (must be non-bare).
///
/// Default checkout [strategy] is combination of [GitCheckout.safe] and
/// [GitCheckout.recreateMissing].
///
/// [directory] is optional alternative checkout path to workdir.
///
/// [paths] is optional list of files to checkout from index.
///
/// Throws a [LibGit2Error] if error occured.
static void head({
required Repository repo,
Set<GitCheckout> strategy = const {
GitCheckout.safe,
GitCheckout.recreateMissing
},
String? directory,
List<String>? paths,
}) {
bindings.head(
repoPointer: repo.pointer,
strategy: strategy.fold(0, (int acc, e) => acc | e.value),
directory: directory,
paths: paths,
);
}
/// Updates files in the working tree to match the content of the index.
///
/// [repo] is the repository into which to check out (must be non-bare).
///
/// Default checkout [strategy] is combination of [GitCheckout.safe] and
/// [GitCheckout.recreateMissing].
///
/// [directory] is optional alternative checkout path to workdir.
///
/// [paths] is optional list of files to checkout from index.
///
/// Throws a [LibGit2Error] if error occured.
static void index({
required Repository repo,
Set<GitCheckout> strategy = const {
GitCheckout.safe,
GitCheckout.recreateMissing
},
String? directory,
List<String>? paths,
}) {
bindings.index(
repoPointer: repo.pointer,
strategy: strategy.fold(0, (int acc, e) => acc | e.value),
directory: directory,
paths: paths,
);
}
/// Updates files in the working tree to match the content of the tree
/// pointed at by the reference [name] target.
///
/// [repo] is the repository into which to check out (must be non-bare).
///
/// [name] is the fully-qualified reference name (e.g. 'refs/heads/master')
/// which target's content will be used to update the working directory;
///
/// Default checkout [strategy] is combination of [GitCheckout.safe] and
/// [GitCheckout.recreateMissing].
///
/// [directory] is optional alternative checkout path to workdir.
///
/// [paths] is optional list of files to checkout from index.
///
/// Throws a [LibGit2Error] if error occured.
static void reference({
required Repository repo,
required String name,
Set<GitCheckout> strategy = const {
GitCheckout.safe,
GitCheckout.recreateMissing
},
String? directory,
List<String>? paths,
}) {
final ref = Reference.lookup(repo: repo, name: name);
final treeish = object_bindings.lookup(
repoPointer: repo.pointer,
oidPointer: ref.target.pointer,
type: GitObject.any.value,
);
bindings.tree(
repoPointer: repo.pointer,
treeishPointer: treeish,
strategy: strategy.fold(0, (int acc, e) => acc | e.value),
directory: directory,
paths: paths,
);
object_bindings.free(treeish);
ref.free();
}
/// Updates files in the working tree to match the content of the tree
/// pointed at by the [commit].
///
/// [repo] is the repository into which to check out (must be non-bare).
///
/// [commit] is the commit which content will be used to update the working
/// directory.
///
/// Default checkout [strategy] is combination of [GitCheckout.safe] and
/// [GitCheckout.recreateMissing].
///
/// [directory] is optional alternative checkout path to workdir.
///
/// [paths] is optional list of files to checkout from index.
///
/// Throws a [LibGit2Error] if error occured.
static void commit({
required Repository repo,
required Commit commit,
Set<GitCheckout> strategy = const {
GitCheckout.safe,
GitCheckout.recreateMissing
},
String? directory,
List<String>? paths,
}) {
final treeish = object_bindings.lookup(
repoPointer: repo.pointer,
oidPointer: commit.oid.pointer,
type: GitObject.any.value,
);
bindings.tree(
repoPointer: repo.pointer,
treeishPointer: treeish,
strategy: strategy.fold(0, (int acc, e) => acc | e.value),
directory: directory,
paths: paths,
);
object_bindings.free(treeish);
}
}

View file

@ -4,7 +4,6 @@ import 'package:ffi/ffi.dart';
import 'package:libgit2dart/libgit2dart.dart';
import 'package:libgit2dart/src/bindings/attr.dart' as attr_bindings;
import 'package:libgit2dart/src/bindings/checkout.dart' as checkout_bindings;
import 'package:libgit2dart/src/bindings/describe.dart' as describe_bindings;
import 'package:libgit2dart/src/bindings/graph.dart' as graph_bindings;
import 'package:libgit2dart/src/bindings/libgit2_bindings.dart';
@ -552,96 +551,6 @@ class Repository {
}
}
/// Checkouts the provided [target] using the given strategy, and updates the
/// HEAD.
///
/// [target] can be null, 'HEAD', reference name or commit [Oid].
///
/// If no [target] is given, updates files in the working tree to match the
/// content of the index.
///
/// If [target] is 'HEAD' string, updates files in the index and the working
/// tree to match the content of the commit pointed at by HEAD.
///
/// If [target] is reference name, updates files in the index and working
/// tree to match the content of the tree pointed at by the reference.
///
/// If [target] is commit oid, updates files in the index and working
/// tree to match the content of the tree pointed at by the commit.
///
/// Default checkout strategy is combination of [GitCheckout.safe] and
/// [GitCheckout.recreateMissing].
///
/// [directory] is alternative checkout path to workdir.
///
/// [paths] is list of files to checkout from provided [target].
/// If paths are provided, HEAD will not be set to the [target].
///
/// Throws [ArgumentError] if provided [target] is not String or [Oid].
void checkout({
Object? target,
Set<GitCheckout> strategy = const {
GitCheckout.safe,
GitCheckout.recreateMissing
},
String? directory,
List<String>? paths,
}) {
final strat = strategy.fold(0, (int acc, e) => acc | e.value);
if (target == null) {
checkout_bindings.index(
repoPointer: _repoPointer,
strategy: strat,
directory: directory,
paths: paths,
);
} else if (target == 'HEAD') {
checkout_bindings.head(
repoPointer: _repoPointer,
strategy: strat,
directory: directory,
paths: paths,
);
} else if (target is String) {
final ref = Reference.lookup(repo: this, name: target);
final treeish = object_bindings.lookup(
repoPointer: _repoPointer,
oidPointer: ref.target.pointer,
type: GitObject.any.value,
);
checkout_bindings.tree(
repoPointer: _repoPointer,
treeishPointer: treeish,
strategy: strat,
directory: directory,
paths: paths,
);
if (paths == null) {
setHead(target);
}
ref.free();
} else if (target is Oid) {
final treeish = object_bindings.lookup(
repoPointer: _repoPointer,
oidPointer: target.pointer,
type: GitObject.any.value,
);
checkout_bindings.tree(
repoPointer: _repoPointer,
treeishPointer: treeish,
strategy: strat,
directory: directory,
paths: paths,
);
if (paths == null) {
setHead(target);
}
} else {
throw ArgumentError.value('$target must be either String or Oid');
}
}
/// Sets the current head to the specified commit [oid] and optionally resets
/// the index and working tree to match.
///