mirror of
https://github.com/SkinnyMind/libgit2dart.git
synced 2025-05-04 20:29:08 -04:00
feat(commit): add ability to amend commit
This commit is contained in:
parent
4948bba773
commit
199dce111a
4 changed files with 234 additions and 21 deletions
|
@ -113,6 +113,56 @@ Pointer<git_oid> create({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Amend an existing commit by replacing only non-null values.
|
||||||
|
///
|
||||||
|
/// This creates a new commit that is exactly the same as the old commit, except that
|
||||||
|
/// any non-null values will be updated. The new commit has the same parents as the old commit.
|
||||||
|
///
|
||||||
|
/// The [updateRef] value works as in the regular [create], updating the ref to point to
|
||||||
|
/// the newly rewritten commit. If you want to amend a commit that is not currently
|
||||||
|
/// the tip of the branch and then rewrite the following commits to reach a ref, pass
|
||||||
|
/// this as null and update the rest of the commit chain and ref separately.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Pointer<git_oid> amend({
|
||||||
|
required Pointer<git_repository> repoPointer,
|
||||||
|
required Pointer<git_commit> commitPointer,
|
||||||
|
String? updateRef,
|
||||||
|
required Pointer<git_signature>? authorPointer,
|
||||||
|
required Pointer<git_signature>? committerPointer,
|
||||||
|
String? messageEncoding,
|
||||||
|
required String? message,
|
||||||
|
required Pointer<git_tree>? treePointer,
|
||||||
|
}) {
|
||||||
|
final out = calloc<git_oid>();
|
||||||
|
final updateRefC = updateRef?.toNativeUtf8().cast<Int8>() ?? nullptr;
|
||||||
|
final messageEncodingC =
|
||||||
|
messageEncoding?.toNativeUtf8().cast<Int8>() ?? nullptr;
|
||||||
|
final messageC = message?.toNativeUtf8().cast<Int8>() ?? nullptr;
|
||||||
|
|
||||||
|
final error = libgit2.git_commit_amend(
|
||||||
|
out,
|
||||||
|
commitPointer,
|
||||||
|
updateRefC,
|
||||||
|
authorPointer ?? nullptr,
|
||||||
|
committerPointer ?? nullptr,
|
||||||
|
messageEncodingC,
|
||||||
|
messageC,
|
||||||
|
treePointer ?? nullptr,
|
||||||
|
);
|
||||||
|
|
||||||
|
calloc.free(updateRefC);
|
||||||
|
calloc.free(messageEncodingC);
|
||||||
|
calloc.free(messageC);
|
||||||
|
|
||||||
|
if (error < 0) {
|
||||||
|
calloc.free(out);
|
||||||
|
throw LibGit2Error(libgit2.git_error_last());
|
||||||
|
} else {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the encoding for the message of a commit, as a string representing a standard encoding name.
|
/// Get the encoding for the message of a commit, as a string representing a standard encoding name.
|
||||||
///
|
///
|
||||||
/// The encoding may be NULL if the encoding header in the commit is missing;
|
/// The encoding may be NULL if the encoding header in the commit is missing;
|
||||||
|
|
|
@ -58,6 +58,39 @@ class Commit {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Amends an existing commit by replacing only non-null values.
|
||||||
|
///
|
||||||
|
/// This creates a new commit that is exactly the same as the old commit, except that
|
||||||
|
/// any non-null values will be updated. The new commit has the same parents as the old commit.
|
||||||
|
///
|
||||||
|
/// The [updateRef] value works as in the regular [create], updating the ref to point to
|
||||||
|
/// the newly rewritten commit. If you want to amend a commit that is not currently
|
||||||
|
/// the tip of the branch and then rewrite the following commits to reach a ref, pass
|
||||||
|
/// this as null and update the rest of the commit chain and ref separately.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
static Oid amend({
|
||||||
|
required Repository repo,
|
||||||
|
required Commit commit,
|
||||||
|
Signature? author,
|
||||||
|
Signature? committer,
|
||||||
|
Tree? tree,
|
||||||
|
String? updateRef,
|
||||||
|
String? message,
|
||||||
|
String? messageEncoding,
|
||||||
|
}) {
|
||||||
|
return Oid(bindings.amend(
|
||||||
|
repoPointer: repo.pointer,
|
||||||
|
commitPointer: commit.pointer,
|
||||||
|
authorPointer: author?.pointer,
|
||||||
|
committerPointer: committer?.pointer,
|
||||||
|
treePointer: tree?.pointer,
|
||||||
|
updateRef: updateRef,
|
||||||
|
message: message,
|
||||||
|
messageEncoding: messageEncoding,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the encoding for the message of a commit, as a string
|
/// Returns the encoding for the message of a commit, as a string
|
||||||
/// representing a standard encoding name.
|
/// representing a standard encoding name.
|
||||||
String get messageEncoding => bindings.messageEncoding(_commitPointer);
|
String get messageEncoding => bindings.messageEncoding(_commitPointer);
|
||||||
|
|
|
@ -509,6 +509,59 @@ class Repository {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Amends an existing commit by replacing only non-null values.
|
||||||
|
///
|
||||||
|
/// This creates a new commit that is exactly the same as the old commit, except that
|
||||||
|
/// any non-null values will be updated. The new commit has the same parents as the old commit.
|
||||||
|
///
|
||||||
|
/// The [updateRef] value works as in the regular [create], updating the ref to point to
|
||||||
|
/// the newly rewritten commit. If you want to amend a commit that is not currently
|
||||||
|
/// the tip of the branch and then rewrite the following commits to reach a ref, pass
|
||||||
|
/// this as null and update the rest of the commit chain and ref separately.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Oid amendCommit({
|
||||||
|
required Commit commit,
|
||||||
|
Signature? author,
|
||||||
|
Signature? committer,
|
||||||
|
Tree? tree,
|
||||||
|
String? updateRef,
|
||||||
|
String? message,
|
||||||
|
String? messageEncoding,
|
||||||
|
}) {
|
||||||
|
return Commit.amend(
|
||||||
|
repo: this,
|
||||||
|
commit: commit,
|
||||||
|
author: author,
|
||||||
|
committer: committer,
|
||||||
|
tree: tree,
|
||||||
|
updateRef: updateRef,
|
||||||
|
message: message,
|
||||||
|
messageEncoding: messageEncoding,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reverts the given commit against the given "our" commit, producing an index that
|
||||||
|
/// reflects the result of the revert.
|
||||||
|
///
|
||||||
|
/// [mainline] is parent of the [revertCommit] if it is a merge (i.e. 1, 2).
|
||||||
|
///
|
||||||
|
/// The returned index must be freed explicitly with `free()`.
|
||||||
|
///
|
||||||
|
/// Throws a [LibGit2Error] if error occured.
|
||||||
|
Index revertCommit({
|
||||||
|
required Commit revertCommit,
|
||||||
|
required Commit ourCommit,
|
||||||
|
mainline = 0,
|
||||||
|
}) {
|
||||||
|
return Index(commit_bindings.revertCommit(
|
||||||
|
repoPointer: _repoPointer,
|
||||||
|
revertCommitPointer: revertCommit.pointer,
|
||||||
|
ourCommitPointer: ourCommit.pointer,
|
||||||
|
mainline: mainline,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
/// Finds a single object and intermediate reference (if there is one) by a [spec] revision string.
|
/// Finds a single object and intermediate reference (if there is one) by a [spec] revision string.
|
||||||
///
|
///
|
||||||
/// See `man gitrevisions`, or https://git-scm.com/docs/git-rev-parse.html#_specifying_revisions
|
/// See `man gitrevisions`, or https://git-scm.com/docs/git-rev-parse.html#_specifying_revisions
|
||||||
|
@ -875,27 +928,6 @@ class Repository {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reverts the given commit against the given "our" commit, producing an index that
|
|
||||||
/// reflects the result of the revert.
|
|
||||||
///
|
|
||||||
/// [mainline] is parent of the [revertCommit] if it is a merge (i.e. 1, 2).
|
|
||||||
///
|
|
||||||
/// The returned index must be freed explicitly with `free()`.
|
|
||||||
///
|
|
||||||
/// Throws a [LibGit2Error] if error occured.
|
|
||||||
Index revertCommit({
|
|
||||||
required Commit revertCommit,
|
|
||||||
required Commit ourCommit,
|
|
||||||
mainline = 0,
|
|
||||||
}) {
|
|
||||||
return Index(commit_bindings.revertCommit(
|
|
||||||
repoPointer: _repoPointer,
|
|
||||||
revertCommitPointer: revertCommit.pointer,
|
|
||||||
ourCommitPointer: ourCommit.pointer,
|
|
||||||
mainline: mainline,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Merges two trees, producing an index that reflects the result of the merge.
|
/// Merges two trees, producing an index that reflects the result of the merge.
|
||||||
/// The index may be written as-is to the working directory or checked out. If the index
|
/// The index may be written as-is to the working directory or checked out. If the index
|
||||||
/// is to be converted to a tree, the caller should resolve any conflicts that arose as part
|
/// is to be converted to a tree, the caller should resolve any conflicts that arose as part
|
||||||
|
|
|
@ -222,6 +222,104 @@ void main() {
|
||||||
parent.free();
|
parent.free();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('successfully amends commit with default arguments', () {
|
||||||
|
final oldHead = repo.head;
|
||||||
|
final commit = repo.lookupCommit(repo['821ed6e']);
|
||||||
|
expect(commit.oid, oldHead.target);
|
||||||
|
|
||||||
|
final amendedOid = repo.amendCommit(
|
||||||
|
commit: commit,
|
||||||
|
message: 'amended commit\n',
|
||||||
|
updateRef: 'HEAD',
|
||||||
|
);
|
||||||
|
final amendedCommit = repo.lookupCommit(amendedOid);
|
||||||
|
final newHead = repo.head;
|
||||||
|
|
||||||
|
expect(amendedCommit.oid, newHead.target);
|
||||||
|
expect(amendedCommit.message, 'amended commit\n');
|
||||||
|
expect(amendedCommit.author, commit.author);
|
||||||
|
expect(amendedCommit.committer, commit.committer);
|
||||||
|
expect(amendedCommit.tree.oid, commit.tree.oid);
|
||||||
|
expect(amendedCommit.parents, commit.parents);
|
||||||
|
|
||||||
|
amendedCommit.free();
|
||||||
|
commit.free();
|
||||||
|
newHead.free();
|
||||||
|
oldHead.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully amends commit with provided arguments', () {
|
||||||
|
final oldHead = repo.head;
|
||||||
|
final commit = repo.lookupCommit(repo['821ed6e']);
|
||||||
|
expect(commit.oid, oldHead.target);
|
||||||
|
|
||||||
|
final amendedOid = repo.amendCommit(
|
||||||
|
commit: commit,
|
||||||
|
message: 'amended commit\n',
|
||||||
|
updateRef: 'HEAD',
|
||||||
|
author: author,
|
||||||
|
committer: commiter,
|
||||||
|
tree: tree,
|
||||||
|
);
|
||||||
|
final amendedCommit = repo.lookupCommit(amendedOid);
|
||||||
|
final newHead = repo.head;
|
||||||
|
|
||||||
|
expect(amendedCommit.oid, newHead.target);
|
||||||
|
expect(amendedCommit.message, 'amended commit\n');
|
||||||
|
expect(amendedCommit.author, author);
|
||||||
|
expect(amendedCommit.committer, commiter);
|
||||||
|
expect(amendedCommit.tree.oid, tree.oid);
|
||||||
|
expect(amendedCommit.parents, commit.parents);
|
||||||
|
|
||||||
|
amendedCommit.free();
|
||||||
|
commit.free();
|
||||||
|
newHead.free();
|
||||||
|
oldHead.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('successfully amends commit that is not the tip of the branch', () {
|
||||||
|
final head = repo.head;
|
||||||
|
final commit = repo.lookupCommit(repo['78b8bf1']);
|
||||||
|
expect(commit.oid, isNot(head.target));
|
||||||
|
|
||||||
|
expect(
|
||||||
|
() => repo.amendCommit(
|
||||||
|
commit: commit,
|
||||||
|
message: 'amended commit\n',
|
||||||
|
),
|
||||||
|
returnsNormally,
|
||||||
|
);
|
||||||
|
|
||||||
|
commit.free();
|
||||||
|
head.free();
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'throws when trying to amend commit that is not the tip of the branch '
|
||||||
|
'with HEAD provided as update reference', () {
|
||||||
|
final head = repo.head;
|
||||||
|
final commit = repo.lookupCommit(repo['78b8bf1']);
|
||||||
|
expect(commit.oid, isNot(head.target));
|
||||||
|
|
||||||
|
expect(
|
||||||
|
() => repo.amendCommit(
|
||||||
|
commit: commit,
|
||||||
|
message: 'amended commit\n',
|
||||||
|
updateRef: 'HEAD',
|
||||||
|
),
|
||||||
|
throwsA(
|
||||||
|
isA<LibGit2Error>().having(
|
||||||
|
(e) => e.toString(),
|
||||||
|
'error',
|
||||||
|
"commit to amend is not the tip of the given branch",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
commit.free();
|
||||||
|
head.free();
|
||||||
|
});
|
||||||
|
|
||||||
test('returns string representation of Commit object', () {
|
test('returns string representation of Commit object', () {
|
||||||
final commit = repo.lookupCommit(mergeCommit);
|
final commit = repo.lookupCommit(mergeCommit);
|
||||||
expect(commit.toString(), contains('Commit{'));
|
expect(commit.toString(), contains('Commit{'));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue