mirror of
https://github.com/SkinnyMind/libgit2dart.git
synced 2025-05-05 04:39:07 -04:00
refactor!: return sets of git type flags instead of integers
This commit is contained in:
parent
050c0eb57a
commit
7618f944c0
12 changed files with 459 additions and 191 deletions
|
@ -1,121 +1,173 @@
|
||||||
/// Basic type of any Git reference.
|
/// Basic type of any Git reference.
|
||||||
class ReferenceType {
|
class ReferenceType {
|
||||||
const ReferenceType._(this._value);
|
const ReferenceType._(this._value, this._name);
|
||||||
final int _value;
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
/// Invalid reference.
|
/// Invalid reference.
|
||||||
static const invalid = ReferenceType._(0);
|
static const invalid = ReferenceType._(0, 'invalid');
|
||||||
|
|
||||||
/// A reference that points at an object id.
|
/// A reference that points at an object id.
|
||||||
static const direct = ReferenceType._(1);
|
static const direct = ReferenceType._(1, 'direct');
|
||||||
|
|
||||||
/// A reference that points at another reference.
|
/// A reference that points at another reference.
|
||||||
static const symbolic = ReferenceType._(2);
|
static const symbolic = ReferenceType._(2, 'symbolic');
|
||||||
|
|
||||||
static const all = ReferenceType._(3);
|
static const all = ReferenceType._(3, 'all');
|
||||||
|
|
||||||
|
static const List<ReferenceType> values = [invalid, direct, symbolic, all];
|
||||||
|
|
||||||
int get value => _value;
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'ReferenceType.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Valid modes for index and tree entries.
|
/// Valid modes for index and tree entries.
|
||||||
class GitFilemode {
|
class GitFilemode {
|
||||||
const GitFilemode._(this._value);
|
const GitFilemode._(this._value, this._name);
|
||||||
final int _value;
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
static const unreadable = GitFilemode._(0);
|
static const unreadable = GitFilemode._(0, 'unreadable');
|
||||||
static const tree = GitFilemode._(16384);
|
static const tree = GitFilemode._(16384, 'tree');
|
||||||
static const blob = GitFilemode._(33188);
|
static const blob = GitFilemode._(33188, 'blob');
|
||||||
static const blobExecutable = GitFilemode._(33261);
|
static const blobExecutable = GitFilemode._(33261, 'blobExecutable');
|
||||||
static const link = GitFilemode._(40960);
|
static const link = GitFilemode._(40960, 'link');
|
||||||
static const commit = GitFilemode._(57344);
|
static const commit = GitFilemode._(57344, 'commit');
|
||||||
|
|
||||||
|
static const List<GitFilemode> values = [
|
||||||
|
unreadable,
|
||||||
|
tree,
|
||||||
|
blob,
|
||||||
|
blobExecutable,
|
||||||
|
link,
|
||||||
|
commit,
|
||||||
|
];
|
||||||
|
|
||||||
int get value => _value;
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitFilemode.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flags to specify the sorting which a revwalk should perform.
|
/// Flags to specify the sorting which a revwalk should perform.
|
||||||
class GitSort {
|
class GitSort {
|
||||||
const GitSort._(this._value);
|
const GitSort._(this._value, this._name);
|
||||||
final int _value;
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
/// Sort the output with the same default method from `git`: reverse
|
/// Sort the output with the same default method from `git`: reverse
|
||||||
/// chronological order. This is the default sorting for new walkers.
|
/// chronological order. This is the default sorting for new walkers.
|
||||||
static const none = GitSort._(0);
|
static const none = GitSort._(0, 'none');
|
||||||
|
|
||||||
/// Sort the repository contents in topological order (no parents before
|
/// Sort the repository contents in topological order (no parents before
|
||||||
/// all of its children are shown); this sorting mode can be combined
|
/// all of its children are shown); this sorting mode can be combined
|
||||||
/// with time sorting to produce `git`'s `--date-order``.
|
/// with time sorting to produce `git`'s `--date-order``.
|
||||||
static const topological = GitSort._(1);
|
static const topological = GitSort._(1, 'topological');
|
||||||
|
|
||||||
/// Sort the repository contents by commit time;
|
/// Sort the repository contents by commit time;
|
||||||
/// this sorting mode can be combined with topological sorting.
|
/// this sorting mode can be combined with topological sorting.
|
||||||
static const time = GitSort._(2);
|
static const time = GitSort._(2, 'time');
|
||||||
|
|
||||||
/// Iterate through the repository contents in reverse order; this sorting mode
|
/// Iterate through the repository contents in reverse order; this sorting mode
|
||||||
/// can be combined with any of the above.
|
/// can be combined with any of the above.
|
||||||
static const reverse = GitSort._(4);
|
static const reverse = GitSort._(4, 'reverse');
|
||||||
|
|
||||||
|
static const List<GitSort> values = [none, topological, time, reverse];
|
||||||
|
|
||||||
int get value => _value;
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitSort.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Basic type (loose or packed) of any Git object.
|
/// Basic type (loose or packed) of any Git object.
|
||||||
class GitObject {
|
class GitObject {
|
||||||
const GitObject._(this._value);
|
const GitObject._(this._value, this._name);
|
||||||
final int _value;
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
/// Object can be any of the following.
|
/// Object can be any of the following.
|
||||||
static const any = GitObject._(-2);
|
static const any = GitObject._(-2, 'any');
|
||||||
|
|
||||||
/// Object is invalid.
|
/// Object is invalid.
|
||||||
static const invalid = GitObject._(-1);
|
static const invalid = GitObject._(-1, 'invalid');
|
||||||
|
|
||||||
/// A commit object.
|
/// A commit object.
|
||||||
static const commit = GitObject._(1);
|
static const commit = GitObject._(1, 'commit');
|
||||||
|
|
||||||
/// A tree (directory listing) object.
|
/// A tree (directory listing) object.
|
||||||
static const tree = GitObject._(2);
|
static const tree = GitObject._(2, 'tree');
|
||||||
|
|
||||||
/// A file revision object.
|
/// A file revision object.
|
||||||
static const blob = GitObject._(3);
|
static const blob = GitObject._(3, 'blob');
|
||||||
|
|
||||||
/// An annotated tag object.
|
/// An annotated tag object.
|
||||||
static const tag = GitObject._(4);
|
static const tag = GitObject._(4, 'tag');
|
||||||
|
|
||||||
/// A delta, base is given by an offset.
|
/// A delta, base is given by an offset.
|
||||||
static const offsetDelta = GitObject._(6);
|
static const offsetDelta = GitObject._(6, 'offsetDelta');
|
||||||
|
|
||||||
/// A delta, base is given by object id.
|
/// A delta, base is given by object id.
|
||||||
static const refDelta = GitObject._(7);
|
static const refDelta = GitObject._(7, 'refDelta');
|
||||||
|
|
||||||
|
static const List<GitObject> values = [
|
||||||
|
any,
|
||||||
|
invalid,
|
||||||
|
commit,
|
||||||
|
tree,
|
||||||
|
blob,
|
||||||
|
tag,
|
||||||
|
offsetDelta,
|
||||||
|
refDelta,
|
||||||
|
];
|
||||||
|
|
||||||
int get value => _value;
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitObject.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Revparse flags, indicate the intended behavior of the spec.
|
/// Revparse flags, indicate the intended behavior of the spec.
|
||||||
class GitRevParse {
|
class GitRevParse {
|
||||||
const GitRevParse._(this._value);
|
const GitRevParse._(this._value, this._name);
|
||||||
final int _value;
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
/// The spec targeted a single object.
|
/// The spec targeted a single object.
|
||||||
static const single = GitRevParse._(1);
|
static const single = GitRevParse._(1, 'single');
|
||||||
|
|
||||||
/// The spec targeted a range of commits.
|
/// The spec targeted a range of commits.
|
||||||
static const range = GitRevParse._(2);
|
static const range = GitRevParse._(2, 'range');
|
||||||
|
|
||||||
/// The spec used the '...' operator, which invokes special semantics.
|
/// The spec used the '...' operator, which invokes special semantics.
|
||||||
static const mergeBase = GitRevParse._(4);
|
static const mergeBase = GitRevParse._(4, 'mergeBase');
|
||||||
|
|
||||||
|
static const List<GitRevParse> values = [single, range, mergeBase];
|
||||||
|
|
||||||
int get value => _value;
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitRevParse.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Basic type of any Git branch.
|
/// Basic type of any Git branch.
|
||||||
class GitBranch {
|
class GitBranch {
|
||||||
const GitBranch._(this._value);
|
const GitBranch._(this._value, this._name);
|
||||||
final int _value;
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
static const local = GitBranch._(1);
|
static const local = GitBranch._(1, 'local');
|
||||||
static const remote = GitBranch._(2);
|
static const remote = GitBranch._(2, 'remote');
|
||||||
static const all = GitBranch._(3);
|
static const all = GitBranch._(3, 'all');
|
||||||
|
|
||||||
|
static const List<GitBranch> values = [local, remote, all];
|
||||||
|
|
||||||
int get value => _value;
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitBranch.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Status flags for a single file.
|
/// Status flags for a single file.
|
||||||
|
@ -127,73 +179,115 @@ class GitBranch {
|
||||||
/// `GitStatus.wt` set of flags represent the status of the file in the
|
/// `GitStatus.wt` set of flags represent the status of the file in the
|
||||||
/// working directory relative to the index.
|
/// working directory relative to the index.
|
||||||
class GitStatus {
|
class GitStatus {
|
||||||
const GitStatus._(this._value);
|
const GitStatus._(this._value, this._name);
|
||||||
final int _value;
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
static const current = GitStatus._(0);
|
static const current = GitStatus._(0, 'current');
|
||||||
static const indexNew = GitStatus._(1);
|
static const indexNew = GitStatus._(1, 'indexNew');
|
||||||
static const indexModified = GitStatus._(2);
|
static const indexModified = GitStatus._(2, 'indexModified');
|
||||||
static const indexDeleted = GitStatus._(4);
|
static const indexDeleted = GitStatus._(4, 'indexDeleted');
|
||||||
static const indexRenamed = GitStatus._(8);
|
static const indexRenamed = GitStatus._(8, 'indexRenamed');
|
||||||
static const indexTypeChange = GitStatus._(16);
|
static const indexTypeChange = GitStatus._(16, 'indexTypeChange');
|
||||||
static const wtNew = GitStatus._(128);
|
static const wtNew = GitStatus._(128, 'wtNew');
|
||||||
static const wtModified = GitStatus._(256);
|
static const wtModified = GitStatus._(256, 'wtModified');
|
||||||
static const wtDeleted = GitStatus._(512);
|
static const wtDeleted = GitStatus._(512, 'wtDeleted');
|
||||||
static const wtTypeChange = GitStatus._(1024);
|
static const wtTypeChange = GitStatus._(1024, 'wtTypeChange');
|
||||||
static const wtRenamed = GitStatus._(2048);
|
static const wtRenamed = GitStatus._(2048, 'wtRenamed');
|
||||||
static const wtUnreadable = GitStatus._(4096);
|
static const wtUnreadable = GitStatus._(4096, 'wtUnreadable');
|
||||||
static const ignored = GitStatus._(16384);
|
static const ignored = GitStatus._(16384, 'ignored');
|
||||||
static const conflicted = GitStatus._(32768);
|
static const conflicted = GitStatus._(32768, 'conflicted');
|
||||||
|
|
||||||
|
static const List<GitStatus> values = [
|
||||||
|
current,
|
||||||
|
indexNew,
|
||||||
|
indexModified,
|
||||||
|
indexDeleted,
|
||||||
|
indexRenamed,
|
||||||
|
indexTypeChange,
|
||||||
|
wtNew,
|
||||||
|
wtModified,
|
||||||
|
wtDeleted,
|
||||||
|
wtTypeChange,
|
||||||
|
wtRenamed,
|
||||||
|
wtUnreadable,
|
||||||
|
ignored,
|
||||||
|
conflicted,
|
||||||
|
];
|
||||||
|
|
||||||
int get value => _value;
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitStatus.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The results of `mergeAnalysis` indicate the merge opportunities.
|
/// The results of `mergeAnalysis` indicate the merge opportunities.
|
||||||
class GitMergeAnalysis {
|
class GitMergeAnalysis {
|
||||||
const GitMergeAnalysis._(this._value);
|
const GitMergeAnalysis._(this._value, this._name);
|
||||||
final int _value;
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
/// No merge is possible (unused).
|
/// No merge is possible (unused).
|
||||||
static const none = GitMergeAnalysis._(0);
|
static const none = GitMergeAnalysis._(0, 'none');
|
||||||
|
|
||||||
/// A "normal" merge; both HEAD and the given merge input have diverged
|
/// A "normal" merge; both HEAD and the given merge input have diverged
|
||||||
/// from their common ancestor. The divergent commits must be merged.
|
/// from their common ancestor. The divergent commits must be merged.
|
||||||
static const normal = GitMergeAnalysis._(1);
|
static const normal = GitMergeAnalysis._(1, 'normal');
|
||||||
|
|
||||||
/// All given merge inputs are reachable from HEAD, meaning the
|
/// All given merge inputs are reachable from HEAD, meaning the
|
||||||
/// repository is up-to-date and no merge needs to be performed.
|
/// repository is up-to-date and no merge needs to be performed.
|
||||||
static const upToDate = GitMergeAnalysis._(2);
|
static const upToDate = GitMergeAnalysis._(2, 'upToDate');
|
||||||
|
|
||||||
/// The given merge input is a fast-forward from HEAD and no merge
|
/// The given merge input is a fast-forward from HEAD and no merge
|
||||||
/// needs to be performed. Instead, the client can check out the
|
/// needs to be performed. Instead, the client can check out the
|
||||||
/// given merge input.
|
/// given merge input.
|
||||||
static const fastForward = GitMergeAnalysis._(4);
|
static const fastForward = GitMergeAnalysis._(4, 'fastForward');
|
||||||
|
|
||||||
/// The HEAD of the current repository is "unborn" and does not point to
|
/// The HEAD of the current repository is "unborn" and does not point to
|
||||||
/// a valid commit. No merge can be performed, but the caller may wish
|
/// a valid commit. No merge can be performed, but the caller may wish
|
||||||
/// to simply set HEAD to the target commit(s).
|
/// to simply set HEAD to the target commit(s).
|
||||||
static const unborn = GitMergeAnalysis._(8);
|
static const unborn = GitMergeAnalysis._(8, 'unborn');
|
||||||
|
|
||||||
|
static const List<GitMergeAnalysis> values = [
|
||||||
|
normal,
|
||||||
|
upToDate,
|
||||||
|
fastForward,
|
||||||
|
unborn,
|
||||||
|
];
|
||||||
|
|
||||||
int get value => _value;
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitMergeAnalysis.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The user's stated preference for merges.
|
/// The user's stated preference for merges.
|
||||||
class GitMergePreference {
|
class GitMergePreference {
|
||||||
const GitMergePreference._(this._value);
|
const GitMergePreference._(this._value, this._name);
|
||||||
final int _value;
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
/// No configuration was found that suggests a preferred behavior for merge.
|
/// No configuration was found that suggests a preferred behavior for merge.
|
||||||
static const none = GitMergePreference._(0);
|
static const none = GitMergePreference._(0, 'none');
|
||||||
|
|
||||||
/// There is a `merge.ff=false` configuration setting, suggesting that
|
/// There is a `merge.ff=false` configuration setting, suggesting that
|
||||||
/// the user does not want to allow a fast-forward merge.
|
/// the user does not want to allow a fast-forward merge.
|
||||||
static const noFastForward = GitMergePreference._(1);
|
static const noFastForward = GitMergePreference._(1, 'noFastForward');
|
||||||
|
|
||||||
/// There is a `merge.ff=only` configuration setting, suggesting that
|
/// There is a `merge.ff=only` configuration setting, suggesting that
|
||||||
/// the user only wants fast-forward merges.
|
/// the user only wants fast-forward merges.
|
||||||
static const fastForwardOnly = GitMergePreference._(2);
|
static const fastForwardOnly = GitMergePreference._(2, 'fastForwardOnly');
|
||||||
|
|
||||||
|
static const List<GitMergePreference> values = [
|
||||||
|
none,
|
||||||
|
noFastForward,
|
||||||
|
fastForwardOnly,
|
||||||
|
];
|
||||||
|
|
||||||
int get value => _value;
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitMergePreference.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Repository state.
|
/// Repository state.
|
||||||
|
@ -201,113 +295,174 @@ class GitMergePreference {
|
||||||
/// These values represent possible states for the repository to be in,
|
/// These values represent possible states for the repository to be in,
|
||||||
/// based on the current operation which is ongoing.
|
/// based on the current operation which is ongoing.
|
||||||
class GitRepositoryState {
|
class GitRepositoryState {
|
||||||
const GitRepositoryState._(this._value);
|
const GitRepositoryState._(this._value, this._name);
|
||||||
final int _value;
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
static const none = GitRepositoryState._(0);
|
static const none = GitRepositoryState._(0, 'none');
|
||||||
static const merge = GitRepositoryState._(1);
|
static const merge = GitRepositoryState._(1, 'merge');
|
||||||
static const revert = GitRepositoryState._(2);
|
static const revert = GitRepositoryState._(2, 'revert');
|
||||||
static const reverSequence = GitRepositoryState._(3);
|
static const revertSequence = GitRepositoryState._(3, 'revertSequence');
|
||||||
static const cherrypick = GitRepositoryState._(4);
|
static const cherrypick = GitRepositoryState._(4, 'cherrypick');
|
||||||
static const cherrypickSequence = GitRepositoryState._(5);
|
static const cherrypickSequence =
|
||||||
static const bisect = GitRepositoryState._(6);
|
GitRepositoryState._(5, 'cherrypickSequence');
|
||||||
static const rebase = GitRepositoryState._(7);
|
static const bisect = GitRepositoryState._(6, 'bisect');
|
||||||
static const rebaseInteractive = GitRepositoryState._(8);
|
static const rebase = GitRepositoryState._(7, 'rebase');
|
||||||
static const rebaseMerge = GitRepositoryState._(9);
|
static const rebaseInteractive = GitRepositoryState._(8, 'rebaseInteractive');
|
||||||
static const applyMailbox = GitRepositoryState._(10);
|
static const rebaseMerge = GitRepositoryState._(9, 'rebaseMerge');
|
||||||
static const applyMailboxOrRebase = GitRepositoryState._(11);
|
static const applyMailbox = GitRepositoryState._(10, 'applyMailbox');
|
||||||
|
static const applyMailboxOrRebase =
|
||||||
|
GitRepositoryState._(11, 'applyMailboxOrRebase');
|
||||||
|
|
||||||
|
static const List<GitRepositoryState> values = [
|
||||||
|
none,
|
||||||
|
merge,
|
||||||
|
revert,
|
||||||
|
revertSequence,
|
||||||
|
cherrypick,
|
||||||
|
cherrypickSequence,
|
||||||
|
bisect,
|
||||||
|
rebase,
|
||||||
|
rebaseInteractive,
|
||||||
|
rebaseMerge,
|
||||||
|
applyMailbox,
|
||||||
|
applyMailboxOrRebase,
|
||||||
|
];
|
||||||
|
|
||||||
int get value => _value;
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitRepositoryState.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flags for merge options.
|
/// Flags for merge options.
|
||||||
class GitMergeFlag {
|
class GitMergeFlag {
|
||||||
const GitMergeFlag._(this._value);
|
const GitMergeFlag._(this._value, this._name);
|
||||||
final int _value;
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
/// Detect renames that occur between the common ancestor and the "ours"
|
/// Detect renames that occur between the common ancestor and the "ours"
|
||||||
/// side or the common ancestor and the "theirs" side. This will enable
|
/// side or the common ancestor and the "theirs" side. This will enable
|
||||||
/// the ability to merge between a modified and renamed file.
|
/// the ability to merge between a modified and renamed file.
|
||||||
static const findRenames = GitMergeFlag._(1);
|
static const findRenames = GitMergeFlag._(1, 'findRenames');
|
||||||
|
|
||||||
/// If a conflict occurs, exit immediately instead of attempting to
|
/// If a conflict occurs, exit immediately instead of attempting to
|
||||||
/// continue resolving conflicts. The merge operation will fail with
|
/// continue resolving conflicts. The merge operation will fail with
|
||||||
/// and no index will be returned.
|
/// and no index will be returned.
|
||||||
static const failOnConflict = GitMergeFlag._(2);
|
static const failOnConflict = GitMergeFlag._(2, 'failOnConflict');
|
||||||
|
|
||||||
/// Do not write the REUC extension on the generated index.
|
/// Do not write the REUC extension on the generated index.
|
||||||
static const skipREUC = GitMergeFlag._(4);
|
static const skipREUC = GitMergeFlag._(4, 'skipREUC');
|
||||||
|
|
||||||
/// If the commits being merged have multiple merge bases, do not build
|
/// If the commits being merged have multiple merge bases, do not build
|
||||||
/// a recursive merge base (by merging the multiple merge bases),
|
/// a recursive merge base (by merging the multiple merge bases),
|
||||||
/// instead simply use the first base.
|
/// instead simply use the first base.
|
||||||
static const noRecursive = GitMergeFlag._(8);
|
static const noRecursive = GitMergeFlag._(8, 'noRecursive');
|
||||||
|
|
||||||
|
static const List<GitMergeFlag> values = [
|
||||||
|
findRenames,
|
||||||
|
failOnConflict,
|
||||||
|
skipREUC,
|
||||||
|
noRecursive,
|
||||||
|
];
|
||||||
|
|
||||||
int get value => _value;
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitMergeFlag.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Merge file favor options to instruct the file-level merging functionality
|
/// Merge file favor options to instruct the file-level merging functionality
|
||||||
/// on how to deal with conflicting regions of the files.
|
/// on how to deal with conflicting regions of the files.
|
||||||
class GitMergeFileFavor {
|
class GitMergeFileFavor {
|
||||||
const GitMergeFileFavor._(this._value);
|
const GitMergeFileFavor._(this._value, this._name);
|
||||||
final int _value;
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
/// When a region of a file is changed in both branches, a conflict
|
/// When a region of a file is changed in both branches, a conflict
|
||||||
/// will be recorded in the index. This is the default.
|
/// will be recorded in the index. This is the default.
|
||||||
static const normal = GitMergeFileFavor._(0);
|
static const normal = GitMergeFileFavor._(0, 'normal');
|
||||||
|
|
||||||
/// When a region of a file is changed in both branches, the file
|
/// When a region of a file is changed in both branches, the file
|
||||||
/// created in the index will contain the "ours" side of any conflicting
|
/// created in the index will contain the "ours" side of any conflicting
|
||||||
/// region. The index will not record a conflict.
|
/// region. The index will not record a conflict.
|
||||||
static const ours = GitMergeFileFavor._(1);
|
static const ours = GitMergeFileFavor._(1, 'ours');
|
||||||
|
|
||||||
/// When a region of a file is changed in both branches, the file
|
/// When a region of a file is changed in both branches, the file
|
||||||
/// created in the index will contain the "theirs" side of any conflicting
|
/// created in the index will contain the "theirs" side of any conflicting
|
||||||
/// region. The index will not record a conflict.
|
/// region. The index will not record a conflict.
|
||||||
static const theirs = GitMergeFileFavor._(2);
|
static const theirs = GitMergeFileFavor._(2, 'theirs');
|
||||||
|
|
||||||
/// When a region of a file is changed in both branches, the file
|
/// When a region of a file is changed in both branches, the file
|
||||||
/// created in the index will contain each unique line from each side,
|
/// created in the index will contain each unique line from each side,
|
||||||
/// which has the result of combining both files. The index will not
|
/// which has the result of combining both files. The index will not
|
||||||
/// record a conflict.
|
/// record a conflict.
|
||||||
static const union = GitMergeFileFavor._(3);
|
static const union = GitMergeFileFavor._(3, 'union');
|
||||||
|
|
||||||
|
static const List<GitMergeFileFavor> values = [
|
||||||
|
normal,
|
||||||
|
ours,
|
||||||
|
theirs,
|
||||||
|
union,
|
||||||
|
];
|
||||||
|
|
||||||
int get value => _value;
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitMergeFileFavor.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// File merging flags.
|
/// File merging flags.
|
||||||
class GitMergeFileFlag {
|
class GitMergeFileFlag {
|
||||||
const GitMergeFileFlag._(this._value);
|
const GitMergeFileFlag._(this._value, this._name);
|
||||||
final int _value;
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
/// Defaults.
|
/// Defaults.
|
||||||
static const defaults = GitMergeFileFlag._(0);
|
static const defaults = GitMergeFileFlag._(0, 'defaults');
|
||||||
|
|
||||||
/// Create standard conflicted merge files.
|
/// Create standard conflicted merge files.
|
||||||
static const styleMerge = GitMergeFileFlag._(1);
|
static const styleMerge = GitMergeFileFlag._(1, 'styleMerge');
|
||||||
|
|
||||||
/// Create diff3-style files.
|
/// Create diff3-style files.
|
||||||
static const styleDiff3 = GitMergeFileFlag._(2);
|
static const styleDiff3 = GitMergeFileFlag._(2, 'styleDiff3');
|
||||||
|
|
||||||
/// Condense non-alphanumeric regions for simplified diff file.
|
/// Condense non-alphanumeric regions for simplified diff file.
|
||||||
static const simplifyAlnum = GitMergeFileFlag._(4);
|
static const simplifyAlnum = GitMergeFileFlag._(4, 'simplifyAlnum');
|
||||||
|
|
||||||
/// Ignore all whitespace.
|
/// Ignore all whitespace.
|
||||||
static const ignoreWhitespace = GitMergeFileFlag._(8);
|
static const ignoreWhitespace = GitMergeFileFlag._(8, 'ignoreWhitespace');
|
||||||
|
|
||||||
/// Ignore changes in amount of whitespace.
|
/// Ignore changes in amount of whitespace.
|
||||||
static const ignoreWhitespaceChange = GitMergeFileFlag._(16);
|
static const ignoreWhitespaceChange =
|
||||||
|
GitMergeFileFlag._(16, 'ignoreWhitespaceChange');
|
||||||
|
|
||||||
/// Ignore whitespace at end of line.
|
/// Ignore whitespace at end of line.
|
||||||
static const ignoreWhitespaceEOL = GitMergeFileFlag._(32);
|
static const ignoreWhitespaceEOL =
|
||||||
|
GitMergeFileFlag._(32, 'ignoreWhitespaceEOL');
|
||||||
|
|
||||||
/// Use the "patience diff" algorithm.
|
/// Use the "patience diff" algorithm.
|
||||||
static const diffPatience = GitMergeFileFlag._(64);
|
static const diffPatience = GitMergeFileFlag._(64, 'diffPatience');
|
||||||
|
|
||||||
/// Take extra time to find minimal diff.
|
/// Take extra time to find minimal diff.
|
||||||
static const diffMinimal = GitMergeFileFlag._(128);
|
static const diffMinimal = GitMergeFileFlag._(128, 'diffMinimal');
|
||||||
|
|
||||||
|
static const List<GitMergeFileFlag> values = [
|
||||||
|
defaults,
|
||||||
|
styleMerge,
|
||||||
|
styleDiff3,
|
||||||
|
simplifyAlnum,
|
||||||
|
ignoreWhitespace,
|
||||||
|
ignoreWhitespaceChange,
|
||||||
|
ignoreWhitespaceEOL,
|
||||||
|
diffPatience,
|
||||||
|
diffMinimal,
|
||||||
|
];
|
||||||
|
|
||||||
int get value => _value;
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitMergeFileFlag.$_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checkout behavior flags.
|
/// Checkout behavior flags.
|
||||||
|
@ -316,11 +471,12 @@ class GitMergeFileFlag {
|
||||||
/// to match a target tree. Unlike git checkout, it does not move the HEAD
|
/// to match a target tree. Unlike git checkout, it does not move the HEAD
|
||||||
/// commit for you - use `setHead` or the like to do that.
|
/// commit for you - use `setHead` or the like to do that.
|
||||||
class GitCheckout {
|
class GitCheckout {
|
||||||
const GitCheckout._(this._value);
|
const GitCheckout._(this._value, this._name);
|
||||||
final int _value;
|
final int _value;
|
||||||
|
final String _name;
|
||||||
|
|
||||||
/// Default is a dry run, no actual updates.
|
/// Default is a dry run, no actual updates.
|
||||||
static const none = GitCheckout._(0);
|
static const none = GitCheckout._(0, 'none');
|
||||||
|
|
||||||
/// Allow safe updates that cannot overwrite uncommitted data.
|
/// Allow safe updates that cannot overwrite uncommitted data.
|
||||||
/// If the uncommitted changes don't conflict with the checked out files,
|
/// If the uncommitted changes don't conflict with the checked out files,
|
||||||
|
@ -328,65 +484,97 @@ class GitCheckout {
|
||||||
///
|
///
|
||||||
/// Mutually exclusive with [GitCheckout.force].
|
/// Mutually exclusive with [GitCheckout.force].
|
||||||
/// [GitCheckout.force] takes precedence over [GitCheckout.safe].
|
/// [GitCheckout.force] takes precedence over [GitCheckout.safe].
|
||||||
static const safe = GitCheckout._(1);
|
static const safe = GitCheckout._(1, 'safe');
|
||||||
|
|
||||||
/// Allow all updates to force working directory to look like index.
|
/// Allow all updates to force working directory to look like index.
|
||||||
///
|
///
|
||||||
/// Mutually exclusive with [GitCheckout.safe].
|
/// Mutually exclusive with [GitCheckout.safe].
|
||||||
/// [GitCheckout.force] takes precedence over [GitCheckout.safe].
|
/// [GitCheckout.force] takes precedence over [GitCheckout.safe].
|
||||||
static const force = GitCheckout._(2);
|
static const force = GitCheckout._(2, 'force');
|
||||||
|
|
||||||
/// Allow checkout to recreate missing files.
|
/// Allow checkout to recreate missing files.
|
||||||
static const recreateMissing = GitCheckout._(4);
|
static const recreateMissing = GitCheckout._(4, 'recreateMissing');
|
||||||
|
|
||||||
/// Allow checkout to make safe updates even if conflicts are found.
|
/// Allow checkout to make safe updates even if conflicts are found.
|
||||||
static const allowConflicts = GitCheckout._(16);
|
static const allowConflicts = GitCheckout._(16, 'allowConflicts');
|
||||||
|
|
||||||
/// Remove untracked files not in index (that are not ignored).
|
/// Remove untracked files not in index (that are not ignored).
|
||||||
static const removeUntracked = GitCheckout._(32);
|
static const removeUntracked = GitCheckout._(32, 'removeUntracked');
|
||||||
|
|
||||||
/// Remove ignored files not in index.
|
/// Remove ignored files not in index.
|
||||||
static const removeIgnored = GitCheckout._(64);
|
static const removeIgnored = GitCheckout._(64, 'removeIgnored');
|
||||||
|
|
||||||
/// Only update existing files, don't create new ones.
|
/// Only update existing files, don't create new ones.
|
||||||
static const updateOnly = GitCheckout._(128);
|
static const updateOnly = GitCheckout._(128, 'updateOnly');
|
||||||
|
|
||||||
/// Normally checkout updates index entries as it goes; this stops that.
|
/// Normally checkout updates index entries as it goes; this stops that.
|
||||||
/// Implies [GitCheckout.dontWriteIndex].
|
/// Implies [GitCheckout.dontWriteIndex].
|
||||||
static const dontUpdateIndex = GitCheckout._(256);
|
static const dontUpdateIndex = GitCheckout._(256, 'dontUpdateIndex');
|
||||||
|
|
||||||
/// Don't refresh index/config/etc before doing checkout.
|
/// Don't refresh index/config/etc before doing checkout.
|
||||||
static const noRefresh = GitCheckout._(512);
|
static const noRefresh = GitCheckout._(512, 'noRefresh');
|
||||||
|
|
||||||
/// Allow checkout to skip unmerged files.
|
/// Allow checkout to skip unmerged files.
|
||||||
static const skipUnmerged = GitCheckout._(1024);
|
static const skipUnmerged = GitCheckout._(1024, 'skipUnmerged');
|
||||||
|
|
||||||
/// For unmerged files, checkout stage 2 from index.
|
/// For unmerged files, checkout stage 2 from index.
|
||||||
static const useOurs = GitCheckout._(2048);
|
static const useOurs = GitCheckout._(2048, 'useOurs');
|
||||||
|
|
||||||
/// For unmerged files, checkout stage 3 from index.
|
/// For unmerged files, checkout stage 3 from index.
|
||||||
static const useTheirs = GitCheckout._(4096);
|
static const useTheirs = GitCheckout._(4096, 'useTheirs');
|
||||||
|
|
||||||
/// Treat pathspec as simple list of exact match file paths.
|
/// Treat pathspec as simple list of exact match file paths.
|
||||||
static const disablePathspecMatch = GitCheckout._(8192);
|
static const disablePathspecMatch =
|
||||||
|
GitCheckout._(8192, 'disablePathspecMatch');
|
||||||
|
|
||||||
/// Ignore directories in use, they will be left empty.
|
/// Ignore directories in use, they will be left empty.
|
||||||
static const skipLockedDirectories = GitCheckout._(262144);
|
static const skipLockedDirectories =
|
||||||
|
GitCheckout._(262144, 'skipLockedDirectories');
|
||||||
|
|
||||||
/// Don't overwrite ignored files that exist in the checkout target.
|
/// Don't overwrite ignored files that exist in the checkout target.
|
||||||
static const dontOverwriteIgnored = GitCheckout._(524288);
|
static const dontOverwriteIgnored =
|
||||||
|
GitCheckout._(524288, 'dontOverwriteIgnored');
|
||||||
|
|
||||||
/// Write normal merge files for conflicts.
|
/// Write normal merge files for conflicts.
|
||||||
static const conflictStyleMerge = GitCheckout._(1048576);
|
static const conflictStyleMerge =
|
||||||
|
GitCheckout._(1048576, 'conflictStyleMerge');
|
||||||
|
|
||||||
/// Include common ancestor data in diff3 format files for conflicts.
|
/// Include common ancestor data in diff3 format files for conflicts.
|
||||||
static const conflictStyleDiff3 = GitCheckout._(2097152);
|
static const conflictStyleDiff3 =
|
||||||
|
GitCheckout._(2097152, 'conflictStyleDiff3');
|
||||||
|
|
||||||
/// Don't overwrite existing files or folders.
|
/// Don't overwrite existing files or folders.
|
||||||
static const dontRemoveExisting = GitCheckout._(4194304);
|
static const dontRemoveExisting =
|
||||||
|
GitCheckout._(4194304, 'dontRemoveExisting');
|
||||||
|
|
||||||
/// Normally checkout writes the index upon completion; this prevents that.
|
/// Normally checkout writes the index upon completion; this prevents that.
|
||||||
static const dontWriteIndex = GitCheckout._(8388608);
|
static const dontWriteIndex = GitCheckout._(8388608, 'dontWriteIndex');
|
||||||
|
|
||||||
|
static const List<GitCheckout> values = [
|
||||||
|
none,
|
||||||
|
safe,
|
||||||
|
force,
|
||||||
|
recreateMissing,
|
||||||
|
allowConflicts,
|
||||||
|
removeUntracked,
|
||||||
|
removeIgnored,
|
||||||
|
updateOnly,
|
||||||
|
dontUpdateIndex,
|
||||||
|
noRefresh,
|
||||||
|
skipUnmerged,
|
||||||
|
useOurs,
|
||||||
|
useTheirs,
|
||||||
|
disablePathspecMatch,
|
||||||
|
skipLockedDirectories,
|
||||||
|
dontOverwriteIgnored,
|
||||||
|
conflictStyleMerge,
|
||||||
|
conflictStyleDiff3,
|
||||||
|
dontRemoveExisting,
|
||||||
|
dontWriteIndex,
|
||||||
|
];
|
||||||
|
|
||||||
int get value => _value;
|
int get value => _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'GitCheckout.$_name';
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,7 +208,10 @@ class IndexEntry {
|
||||||
String get sha => _oidToHex(_indexEntryPointer.ref.id);
|
String get sha => _oidToHex(_indexEntryPointer.ref.id);
|
||||||
|
|
||||||
/// Returns the UNIX file attributes of a index entry.
|
/// Returns the UNIX file attributes of a index entry.
|
||||||
GitFilemode get mode => intToGitFilemode(_indexEntryPointer.ref.mode);
|
GitFilemode get mode {
|
||||||
|
final modeInt = _indexEntryPointer.ref.mode;
|
||||||
|
return GitFilemode.values.singleWhere((mode) => modeInt == mode.value);
|
||||||
|
}
|
||||||
|
|
||||||
/// 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;
|
||||||
|
|
|
@ -194,7 +194,11 @@ class Repository {
|
||||||
|
|
||||||
/// Returns the status of a git repository - ie, whether an operation
|
/// Returns the status of a git repository - ie, whether an operation
|
||||||
/// (merge, cherry-pick, etc) is in progress.
|
/// (merge, cherry-pick, etc) is in progress.
|
||||||
int get state => bindings.state(_repoPointer);
|
GitRepositoryState get state {
|
||||||
|
final stateInt = bindings.state(_repoPointer);
|
||||||
|
return GitRepositoryState.values
|
||||||
|
.singleWhere((flag) => stateInt == flag.value);
|
||||||
|
}
|
||||||
|
|
||||||
/// Removes all the metadata associated with an ongoing command like
|
/// Removes all the metadata associated with an ongoing command like
|
||||||
/// merge, revert, cherry-pick, etc. For example: MERGE_HEAD, MERGE_MSG, etc.
|
/// merge, revert, cherry-pick, etc. For example: MERGE_HEAD, MERGE_MSG, etc.
|
||||||
|
@ -357,7 +361,7 @@ class Repository {
|
||||||
/// Returns the list of commits starting from provided [sha] hex string.
|
/// Returns the list of commits starting from provided [sha] hex string.
|
||||||
///
|
///
|
||||||
/// If [sorting] isn't provided default will be used (reverse chronological order, like in git).
|
/// If [sorting] isn't provided default will be used (reverse chronological order, like in git).
|
||||||
List<Commit> log(String sha, [List<GitSort> sorting = const [GitSort.none]]) {
|
List<Commit> log(String sha, [Set<GitSort> sorting = const {GitSort.none}]) {
|
||||||
final oid = Oid.fromSHA(this, sha);
|
final oid = Oid.fromSHA(this, sha);
|
||||||
final walker = RevWalk(this);
|
final walker = RevWalk(this);
|
||||||
|
|
||||||
|
@ -454,8 +458,8 @@ class Repository {
|
||||||
/// Checks status of the repository and returns map of file paths and their statuses.
|
/// Checks status of the repository and returns map of file paths and their statuses.
|
||||||
///
|
///
|
||||||
/// Returns empty map if there are no changes in statuses.
|
/// Returns empty map if there are no changes in statuses.
|
||||||
Map<String, int> get status {
|
Map<String, Set<GitStatus>> get status {
|
||||||
var result = <String, int>{};
|
var result = <String, Set<GitStatus>>{};
|
||||||
var list = status_bindings.listNew(_repoPointer);
|
var list = status_bindings.listNew(_repoPointer);
|
||||||
var count = status_bindings.listEntryCount(list);
|
var count = status_bindings.listEntryCount(list);
|
||||||
|
|
||||||
|
@ -471,7 +475,15 @@ class Repository {
|
||||||
.cast<Utf8>()
|
.cast<Utf8>()
|
||||||
.toDartString();
|
.toDartString();
|
||||||
}
|
}
|
||||||
result[path] = entry.ref.status;
|
var statuses = <GitStatus>{};
|
||||||
|
// Skipping GitStatus.current because entry that is in the list can't be without changes
|
||||||
|
// but `&` on `0` value falsly adds it to the set of flags
|
||||||
|
for (var flag in GitStatus.values.skip(1)) {
|
||||||
|
if (entry.ref.status & flag.value == flag.value) {
|
||||||
|
statuses.add(flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result[path] = statuses;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_bindings.listFree(list);
|
status_bindings.listFree(list);
|
||||||
|
@ -487,7 +499,23 @@ class Repository {
|
||||||
/// through looking for the path that you are interested in.
|
/// through looking for the path that you are interested in.
|
||||||
///
|
///
|
||||||
/// Throws a [LibGit2Error] if error occured.
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
int statusFile(String path) => status_bindings.file(_repoPointer, path);
|
Set<GitStatus> statusFile(String path) {
|
||||||
|
final statusInt = status_bindings.file(_repoPointer, path);
|
||||||
|
var statuses = <GitStatus>{};
|
||||||
|
|
||||||
|
if (statusInt == GitStatus.current.value) {
|
||||||
|
statuses.add(GitStatus.current);
|
||||||
|
} else {
|
||||||
|
// Skipping GitStatus.current because `&` on `0` value falsly adds it to the set of flags
|
||||||
|
for (var flag in GitStatus.values.skip(1)) {
|
||||||
|
if (statusInt & flag.value == flag.value) {
|
||||||
|
statuses.add(flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return statuses;
|
||||||
|
}
|
||||||
|
|
||||||
/// Finds a merge base between two commits.
|
/// Finds a merge base between two commits.
|
||||||
///
|
///
|
||||||
|
@ -509,14 +537,30 @@ class Repository {
|
||||||
/// respectively.
|
/// respectively.
|
||||||
///
|
///
|
||||||
/// Throws a [LibGit2Error] if error occured.
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
List<int> mergeAnalysis(Oid theirHead, [String ourRef = 'HEAD']) {
|
List<Set<dynamic>> mergeAnalysis(Oid theirHead, [String ourRef = 'HEAD']) {
|
||||||
final ref = references[ourRef];
|
final ref = references[ourRef];
|
||||||
final head = commit_bindings.annotatedLookup(
|
final head = commit_bindings.annotatedLookup(
|
||||||
_repoPointer,
|
_repoPointer,
|
||||||
theirHead.pointer,
|
theirHead.pointer,
|
||||||
);
|
);
|
||||||
|
|
||||||
final result = merge_bindings.analysis(_repoPointer, ref.pointer, head, 1);
|
var result = <Set<dynamic>>[];
|
||||||
|
var analysisSet = <GitMergeAnalysis>{};
|
||||||
|
final analysisInt = merge_bindings.analysis(
|
||||||
|
_repoPointer,
|
||||||
|
ref.pointer,
|
||||||
|
head,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
for (var analysis in GitMergeAnalysis.values) {
|
||||||
|
if (analysisInt[0] & analysis.value == analysis.value) {
|
||||||
|
analysisSet.add(analysis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.add(analysisSet);
|
||||||
|
result.add(
|
||||||
|
{GitMergePreference.values.singleWhere((e) => analysisInt[1] == e.value)},
|
||||||
|
);
|
||||||
|
|
||||||
commit_bindings.annotatedFree(head.value);
|
commit_bindings.annotatedFree(head.value);
|
||||||
ref.free();
|
ref.free();
|
||||||
|
@ -553,19 +597,15 @@ class Repository {
|
||||||
required Commit ourCommit,
|
required Commit ourCommit,
|
||||||
required Commit theirCommit,
|
required Commit theirCommit,
|
||||||
GitMergeFileFavor favor = GitMergeFileFavor.normal,
|
GitMergeFileFavor favor = GitMergeFileFavor.normal,
|
||||||
List<GitMergeFlag> mergeFlags = const [GitMergeFlag.findRenames],
|
Set<GitMergeFlag> mergeFlags = const {GitMergeFlag.findRenames},
|
||||||
List<GitMergeFileFlag> fileFlags = const [GitMergeFileFlag.defaults],
|
Set<GitMergeFileFlag> fileFlags = const {GitMergeFileFlag.defaults},
|
||||||
}) {
|
}) {
|
||||||
var opts = <String, int>{};
|
var opts = <String, int>{};
|
||||||
opts['favor'] = favor.value;
|
opts['favor'] = favor.value;
|
||||||
opts['mergeFlags'] = mergeFlags.fold(
|
opts['mergeFlags'] =
|
||||||
0,
|
mergeFlags.fold(0, (previousValue, e) => previousValue | e.value);
|
||||||
(previousValue, element) => previousValue + element.value,
|
opts['fileFlags'] =
|
||||||
);
|
fileFlags.fold(0, (previousValue, e) => previousValue | e.value);
|
||||||
opts['fileFlags'] = fileFlags.fold(
|
|
||||||
0,
|
|
||||||
(previousValue, element) => previousValue + element.value,
|
|
||||||
);
|
|
||||||
|
|
||||||
final result = merge_bindings.mergeCommits(
|
final result = merge_bindings.mergeCommits(
|
||||||
_repoPointer,
|
_repoPointer,
|
||||||
|
@ -638,17 +678,15 @@ class Repository {
|
||||||
/// HEAD will not be set to the reference [refName].
|
/// HEAD will not be set to the reference [refName].
|
||||||
void checkout({
|
void checkout({
|
||||||
String refName = '',
|
String refName = '',
|
||||||
List<GitCheckout> strategy = const [
|
Set<GitCheckout> strategy = const {
|
||||||
GitCheckout.safe,
|
GitCheckout.safe,
|
||||||
GitCheckout.recreateMissing
|
GitCheckout.recreateMissing
|
||||||
],
|
},
|
||||||
String? directory,
|
String? directory,
|
||||||
List<String>? paths,
|
List<String>? paths,
|
||||||
}) {
|
}) {
|
||||||
final int strat = strategy.fold(
|
final int strat =
|
||||||
0,
|
strategy.fold(0, (previousValue, e) => previousValue | e.value);
|
||||||
(previousValue, element) => previousValue + element.value,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (refName.isEmpty) {
|
if (refName.isEmpty) {
|
||||||
checkout_bindings.index(_repoPointer, strat, directory, paths);
|
checkout_bindings.index(_repoPointer, strat, directory, paths);
|
||||||
|
|
|
@ -78,14 +78,14 @@ class RevSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The intent of the revspec.
|
/// The intent of the revspec.
|
||||||
GitRevParse get flags {
|
Set<GitRevParse> get flags {
|
||||||
final flag = _revSpecPointer.ref.flags;
|
final flagInt = _revSpecPointer.ref.flags;
|
||||||
if (flag == 1) {
|
var flags = <GitRevParse>{};
|
||||||
return GitRevParse.single;
|
for (var flag in GitRevParse.values) {
|
||||||
} else if (flag == 2) {
|
if (flagInt & flag.value == flag.value) {
|
||||||
return GitRevParse.range;
|
flags.add(flag);
|
||||||
} else {
|
|
||||||
return GitRevParse.mergeBase;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,11 @@ class RevWalk {
|
||||||
/// Changing the sorting mode resets the walker.
|
/// Changing the sorting mode resets the walker.
|
||||||
///
|
///
|
||||||
/// Throws a [LibGit2Error] if error occured.
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
void sorting(List<GitSort> sorting) {
|
void sorting(Set<GitSort> sorting) {
|
||||||
final sort = sorting.fold(0, (previousValue, e) => e.value);
|
final int sort = sorting.fold(
|
||||||
|
0,
|
||||||
|
(previousValue, e) => previousValue | e.value,
|
||||||
|
);
|
||||||
bindings.sorting(_revWalkPointer, sort);
|
bindings.sorting(_revWalkPointer, sort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,8 @@ class TreeEntry {
|
||||||
|
|
||||||
/// Returns the UNIX file attributes of a tree entry.
|
/// Returns the UNIX file attributes of a tree entry.
|
||||||
GitFilemode get filemode {
|
GitFilemode get filemode {
|
||||||
return intToGitFilemode(bindings.entryFilemode(_treeEntryPointer));
|
final modeInt = bindings.entryFilemode(_treeEntryPointer);
|
||||||
|
return GitFilemode.values.singleWhere((mode) => modeInt == mode.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
import 'bindings/libgit2_bindings.dart';
|
import 'bindings/libgit2_bindings.dart';
|
||||||
import 'git_types.dart';
|
|
||||||
|
|
||||||
DynamicLibrary loadLibrary() {
|
DynamicLibrary loadLibrary() {
|
||||||
if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia) {
|
if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia) {
|
||||||
|
@ -26,22 +25,3 @@ bool isValidShaHex(String str) {
|
||||||
return hexRegExp.hasMatch(str) &&
|
return hexRegExp.hasMatch(str) &&
|
||||||
(GIT_OID_MINPREFIXLEN <= str.length && GIT_OID_HEXSZ >= str.length);
|
(GIT_OID_MINPREFIXLEN <= str.length && GIT_OID_HEXSZ >= str.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
GitFilemode intToGitFilemode(int i) {
|
|
||||||
switch (i) {
|
|
||||||
case 0:
|
|
||||||
return GitFilemode.unreadable;
|
|
||||||
case 16384:
|
|
||||||
return GitFilemode.tree;
|
|
||||||
case 33188:
|
|
||||||
return GitFilemode.blob;
|
|
||||||
case 33261:
|
|
||||||
return GitFilemode.blobExecutable;
|
|
||||||
case 40960:
|
|
||||||
return GitFilemode.link;
|
|
||||||
case 57344:
|
|
||||||
return GitFilemode.commit;
|
|
||||||
default:
|
|
||||||
return GitFilemode.unreadable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ void main() {
|
||||||
File('${tmpDir}feature_file').writeAsStringSync('edit');
|
File('${tmpDir}feature_file').writeAsStringSync('edit');
|
||||||
expect(repo.status, contains('feature_file'));
|
expect(repo.status, contains('feature_file'));
|
||||||
|
|
||||||
repo.checkout(refName: 'HEAD', strategy: [GitCheckout.force]);
|
repo.checkout(refName: 'HEAD', strategy: {GitCheckout.force});
|
||||||
expect(repo.status, isEmpty);
|
expect(repo.status, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -37,7 +37,10 @@ void main() {
|
||||||
File('${repo.workdir}feature_file').writeAsStringSync('edit');
|
File('${repo.workdir}feature_file').writeAsStringSync('edit');
|
||||||
expect(repo.status, contains('feature_file'));
|
expect(repo.status, contains('feature_file'));
|
||||||
|
|
||||||
repo.checkout(strategy: [GitCheckout.force]);
|
repo.checkout(strategy: {
|
||||||
|
GitCheckout.force,
|
||||||
|
GitCheckout.conflictStyleMerge,
|
||||||
|
});
|
||||||
expect(repo.status, isEmpty);
|
expect(repo.status, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -90,7 +93,12 @@ void main() {
|
||||||
refName: 'refs/heads/feature',
|
refName: 'refs/heads/feature',
|
||||||
paths: ['another_feature_file'],
|
paths: ['another_feature_file'],
|
||||||
);
|
);
|
||||||
expect(repo.status, {'another_feature_file': GitStatus.indexNew.value});
|
expect(
|
||||||
|
repo.status,
|
||||||
|
{
|
||||||
|
'another_feature_file': {GitStatus.indexNew}
|
||||||
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,8 @@ void main() {
|
||||||
repo['c68ff54aabf660fcdd9a2838d401583fe31249e3'] as Commit;
|
repo['c68ff54aabf660fcdd9a2838d401583fe31249e3'] as Commit;
|
||||||
|
|
||||||
final result = repo.mergeAnalysis(commit.id);
|
final result = repo.mergeAnalysis(commit.id);
|
||||||
expect(result[0], GitMergeAnalysis.upToDate.value);
|
expect(result[0], {GitMergeAnalysis.upToDate});
|
||||||
|
expect(result[1], {GitMergePreference.none});
|
||||||
expect(repo.status, isEmpty);
|
expect(repo.status, isEmpty);
|
||||||
|
|
||||||
commit.free();
|
commit.free();
|
||||||
|
@ -42,7 +43,7 @@ void main() {
|
||||||
repo['c68ff54aabf660fcdd9a2838d401583fe31249e3'] as Commit;
|
repo['c68ff54aabf660fcdd9a2838d401583fe31249e3'] as Commit;
|
||||||
|
|
||||||
final result = repo.mergeAnalysis(commit.id, 'refs/tags/v0.1');
|
final result = repo.mergeAnalysis(commit.id, 'refs/tags/v0.1');
|
||||||
expect(result[0], GitMergeAnalysis.upToDate.value);
|
expect(result[0], {GitMergeAnalysis.upToDate});
|
||||||
expect(repo.status, isEmpty);
|
expect(repo.status, isEmpty);
|
||||||
|
|
||||||
commit.free();
|
commit.free();
|
||||||
|
@ -61,7 +62,7 @@ void main() {
|
||||||
final result = repo.mergeAnalysis(theirHead.id, ffBranch.name);
|
final result = repo.mergeAnalysis(theirHead.id, ffBranch.name);
|
||||||
expect(
|
expect(
|
||||||
result[0],
|
result[0],
|
||||||
GitMergeAnalysis.fastForward.value + GitMergeAnalysis.normal.value,
|
{GitMergeAnalysis.fastForward, GitMergeAnalysis.normal},
|
||||||
);
|
);
|
||||||
expect(repo.status, isEmpty);
|
expect(repo.status, isEmpty);
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ void main() {
|
||||||
repo['5aecfa0fb97eadaac050ccb99f03c3fb65460ad4'] as Commit;
|
repo['5aecfa0fb97eadaac050ccb99f03c3fb65460ad4'] as Commit;
|
||||||
|
|
||||||
final result = repo.mergeAnalysis(commit.id);
|
final result = repo.mergeAnalysis(commit.id);
|
||||||
expect(result[0], GitMergeAnalysis.normal.value);
|
expect(result[0], {GitMergeAnalysis.normal});
|
||||||
expect(repo.status, isEmpty);
|
expect(repo.status, isEmpty);
|
||||||
|
|
||||||
commit.free();
|
commit.free();
|
||||||
|
@ -87,13 +88,18 @@ void main() {
|
||||||
final index = repo.index;
|
final index = repo.index;
|
||||||
|
|
||||||
final result = repo.mergeAnalysis(conflictBranch.target);
|
final result = repo.mergeAnalysis(conflictBranch.target);
|
||||||
expect(result[0], GitMergeAnalysis.normal.value);
|
expect(result[0], {GitMergeAnalysis.normal});
|
||||||
|
|
||||||
repo.merge(conflictBranch.target);
|
repo.merge(conflictBranch.target);
|
||||||
expect(index.hasConflicts, true);
|
expect(index.hasConflicts, true);
|
||||||
expect(index.conflicts.length, 1);
|
expect(index.conflicts.length, 1);
|
||||||
expect(repo.state, GitRepositoryState.merge.value);
|
expect(repo.state, GitRepositoryState.merge);
|
||||||
expect(repo.status, {'conflict_file': GitStatus.conflicted.value});
|
expect(
|
||||||
|
repo.status,
|
||||||
|
{
|
||||||
|
'conflict_file': {GitStatus.conflicted}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
final conflictedFile = index.conflicts['conflict_file']!;
|
final conflictedFile = index.conflicts['conflict_file']!;
|
||||||
expect(conflictedFile.ancestor, null);
|
expect(conflictedFile.ancestor, null);
|
||||||
|
@ -104,7 +110,12 @@ void main() {
|
||||||
index.write();
|
index.write();
|
||||||
expect(index.hasConflicts, false);
|
expect(index.hasConflicts, false);
|
||||||
expect(index.conflicts, isEmpty);
|
expect(index.conflicts, isEmpty);
|
||||||
expect(repo.status, {'conflict_file': GitStatus.indexModified.value});
|
expect(
|
||||||
|
repo.status,
|
||||||
|
{
|
||||||
|
'conflict_file': {GitStatus.indexModified}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
index.free();
|
index.free();
|
||||||
conflictBranch.free();
|
conflictBranch.free();
|
||||||
|
@ -172,6 +183,32 @@ void main() {
|
||||||
ourCommit.free();
|
ourCommit.free();
|
||||||
theirCommit.free();
|
theirCommit.free();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('successfully merges with provided merge and file flags', () {
|
||||||
|
final theirCommit =
|
||||||
|
repo['5aecfa0fb97eadaac050ccb99f03c3fb65460ad4'] as Commit;
|
||||||
|
final ourCommit =
|
||||||
|
repo['14905459d775f3f56a39ebc2ff081163f7da3529'] as Commit;
|
||||||
|
|
||||||
|
final mergeIndex = repo.mergeCommits(
|
||||||
|
ourCommit: ourCommit,
|
||||||
|
theirCommit: theirCommit,
|
||||||
|
mergeFlags: {
|
||||||
|
GitMergeFlag.findRenames,
|
||||||
|
GitMergeFlag.noRecursive,
|
||||||
|
},
|
||||||
|
fileFlags: {
|
||||||
|
GitMergeFileFlag.ignoreWhitespace,
|
||||||
|
GitMergeFileFlag.ignoreWhitespaceEOL,
|
||||||
|
GitMergeFileFlag.styleMerge,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect(mergeIndex.conflicts, isEmpty);
|
||||||
|
|
||||||
|
mergeIndex.free();
|
||||||
|
ourCommit.free();
|
||||||
|
theirCommit.free();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group('merge trees', () {
|
group('merge trees', () {
|
||||||
|
@ -246,7 +283,7 @@ void main() {
|
||||||
test('successfully cherry-picks commit', () {
|
test('successfully cherry-picks commit', () {
|
||||||
final cherry = repo['5aecfa0fb97eadaac050ccb99f03c3fb65460ad4'] as Commit;
|
final cherry = repo['5aecfa0fb97eadaac050ccb99f03c3fb65460ad4'] as Commit;
|
||||||
repo.cherryPick(cherry);
|
repo.cherryPick(cherry);
|
||||||
expect(repo.state, GitRepositoryState.cherrypick.value);
|
expect(repo.state, GitRepositoryState.cherrypick);
|
||||||
expect(repo.message, 'add another feature file\n');
|
expect(repo.message, 'add another feature file\n');
|
||||||
final index = repo.index;
|
final index = repo.index;
|
||||||
expect(index.conflicts, isEmpty);
|
expect(index.conflicts, isEmpty);
|
||||||
|
|
|
@ -343,7 +343,13 @@ void main() {
|
||||||
final index = repo.index;
|
final index = repo.index;
|
||||||
index.remove('file');
|
index.remove('file');
|
||||||
index.add('new_file.txt');
|
index.add('new_file.txt');
|
||||||
expect(repo.status, {'file': 132, 'new_file.txt': 1});
|
expect(
|
||||||
|
repo.status,
|
||||||
|
{
|
||||||
|
'file': {GitStatus.indexDeleted, GitStatus.wtNew},
|
||||||
|
'new_file.txt': {GitStatus.indexNew}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
index.free();
|
index.free();
|
||||||
});
|
});
|
||||||
|
@ -351,7 +357,11 @@ void main() {
|
||||||
test('returns status of a single file for provided path', () {
|
test('returns status of a single file for provided path', () {
|
||||||
final index = repo.index;
|
final index = repo.index;
|
||||||
index.remove('file');
|
index.remove('file');
|
||||||
expect(repo.statusFile('file'), 132);
|
expect(
|
||||||
|
repo.statusFile('file'),
|
||||||
|
{GitStatus.indexDeleted, GitStatus.wtNew},
|
||||||
|
);
|
||||||
|
expect(repo.statusFile('.gitignore'), {GitStatus.current});
|
||||||
|
|
||||||
index.free();
|
index.free();
|
||||||
});
|
});
|
||||||
|
|
|
@ -81,7 +81,7 @@ void main() {
|
||||||
|
|
||||||
expect(revspec.from.id.sha, headSHA);
|
expect(revspec.from.id.sha, headSHA);
|
||||||
expect(revspec.to, isNull);
|
expect(revspec.to, isNull);
|
||||||
expect(revspec.flags, GitRevParse.single);
|
expect(revspec.flags, {GitRevParse.single});
|
||||||
|
|
||||||
revspec.from.free();
|
revspec.from.free();
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ void main() {
|
||||||
|
|
||||||
expect(revspec.from.id.sha, parentSHA);
|
expect(revspec.from.id.sha, parentSHA);
|
||||||
expect(revspec.to?.id.sha, '5aecfa0fb97eadaac050ccb99f03c3fb65460ad4');
|
expect(revspec.to?.id.sha, '5aecfa0fb97eadaac050ccb99f03c3fb65460ad4');
|
||||||
expect(revspec.flags, GitRevParse.range);
|
expect(revspec.flags, {GitRevParse.range});
|
||||||
|
|
||||||
revspec.from.free();
|
revspec.from.free();
|
||||||
revspec.to?.free();
|
revspec.to?.free();
|
||||||
|
@ -98,7 +98,7 @@ void main() {
|
||||||
|
|
||||||
expect(revspec.from.id.sha, headSHA);
|
expect(revspec.from.id.sha, headSHA);
|
||||||
expect(revspec.to?.id.sha, '5aecfa0fb97eadaac050ccb99f03c3fb65460ad4');
|
expect(revspec.to?.id.sha, '5aecfa0fb97eadaac050ccb99f03c3fb65460ad4');
|
||||||
expect(revspec.flags, GitRevParse.mergeBase);
|
expect(revspec.flags, {GitRevParse.range, GitRevParse.mergeBase});
|
||||||
expect(
|
expect(
|
||||||
repo.mergeBase(revspec.from.id.sha, revspec.to!.id.sha),
|
repo.mergeBase(revspec.from.id.sha, revspec.to!.id.sha),
|
||||||
isA<Oid>(),
|
isA<Oid>(),
|
||||||
|
|
|
@ -53,7 +53,7 @@ void main() {
|
||||||
final start = Oid.fromSHA(repo, log.first);
|
final start = Oid.fromSHA(repo, log.first);
|
||||||
|
|
||||||
walker.push(start);
|
walker.push(start);
|
||||||
walker.sorting([GitSort.reverse]);
|
walker.sorting({GitSort.reverse});
|
||||||
final commits = walker.walk();
|
final commits = walker.walk();
|
||||||
|
|
||||||
for (var i = 0; i < commits.length; i++) {
|
for (var i = 0; i < commits.length; i++) {
|
||||||
|
@ -77,7 +77,7 @@ void main() {
|
||||||
expect(timeSortedCommits[i].id.sha, log[i]);
|
expect(timeSortedCommits[i].id.sha, log[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
walker.sorting([GitSort.time, GitSort.reverse]);
|
walker.sorting({GitSort.time, GitSort.reverse});
|
||||||
final reverseSortedCommits = walker.walk();
|
final reverseSortedCommits = walker.walk();
|
||||||
for (var i = 0; i < reverseSortedCommits.length; i++) {
|
for (var i = 0; i < reverseSortedCommits.length; i++) {
|
||||||
expect(reverseSortedCommits[i].id.sha, log.reversed.toList()[i]);
|
expect(reverseSortedCommits[i].id.sha, log.reversed.toList()[i]);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue