8000 Add signature-handling methods by carlosmn · Pull Request #1304 · libgit2/libgit2sharp · GitHub
[go: up one dir, main page]

Skip to content

Add signature-handling methods #1304

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 27, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Add methods to create a signed commit
First you need to create a buffer which you can apply the signature
function to. You can then create the commit object the data and its
signature.
  • Loading branch information
carlosmn committed Apr 26, 2016
commit 508807fbe6767e5d005e01df7ae0dbd235a4a48b
57 changes: 50 additions & 7 deletions LibGit2Sharp.Tests/CommitFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1057,10 +1057,7 @@ public void CanPrettifyAMessage()
Assert.Equal(expected, Commit.PrettifyMessage(input.Replace('#', ';'), ';'));
}

[Fact]
public void CanExtractSignatureFromCommit()
{
string commitData = @"tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6
private readonly string signedCommit = @"tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6
parent 34734e478d6cf50c27c9d69026d93974d052c454
author Ben Burkert <ben@benburkert.com> 1358451456 -0800
committer Ben Burkert <ben@benburkert.com> 1358451456 -0800
Expand All @@ -1085,7 +1082,7 @@ committer Ben Burkert <ben@benburkert.com> 1358451456 -0800
a simple commit which works
";

string signatureData = @"-----BEGIN PGP SIGNATURE-----
private readonly string signatureData = @"-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (Darwin)

iQIcBAABAgAGBQJQ+FMIAAoJEH+LfPdZDSs1e3EQAJMjhqjWF+WkGLHju7pTw2al
Expand All @@ -1103,19 +1100,23 @@ a simple commit which works
=ozeK
-----END PGP SIGNATURE-----";

string signedData = @"tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6
private readonly string signedData = @"tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6
parent 34734e478d6cf50c27c9d69026d93974d052c454
author Ben Burkert <ben@benburkert.com> 1358451456 -0800
committer Ben Burkert <ben@benburkert.com> 1358451456 -0800

a simple commit which works
";


[Fact]
public void CanExtractSignatureFromCommit()
{
string repoPath = InitNewRepository();
using (var repo = new Repository(repoPath))
{
var odb = repo.ObjectDatabase;
var signedId = odb.Write<Commit>(Encoding.UTF8.GetBytes(commitData));
var signedId = odb.Write<Commit>(Encoding.UTF8.GetBytes(signedCommit));

// Look up the commit to make sure we wrote something valid
var commit = repo.Lookup<Commit>(signedId);
Expand All @@ -1124,6 +1125,48 @@ a simple commit which works
var signatureInfo = Commit.ExtractSignature(repo, signedId, "gpgsig");
Assert.Equal(signedData, signatureInfo.SignedData);
Assert.Equal(signatureData, signatureInfo.Signature);

signatureInfo = Commit.ExtractSignature(repo, signedId);
Assert.Equal(signedData, signatureInfo.SignedData);
Assert.Equal(signatureData, signatureInfo.Signature);
}
}

[Fact]
public void CanCreateACommitString()
{
string repoPath = SandboxStandardTestRepo();
using (var repo = new Repository(repoPath))
{
var tipCommit = repo.Head.Tip;
var recreatedCommit = Commit.CreateBuffer(
tipCommit.Author,
tipCommit.Committer,
tipCommit.Message,
tipCommit.Tree,
tipCommit.Parents,
false, null);

var recreatedId = repo.ObjectDatabase.Write<Commit>(Encoding.UTF8.GetBytes(recreatedCommit));
Assert.Equal(tipCommit.Id, recreatedId);
}
}

[Fact]
public void CanCreateASignedCommit()
{
string repoPath = InitNewRepository();
using (var repo = new Repository(repoPath))
{
var odb = repo.ObjectDatabase;
var signedId = odb.Write<Commit>(Encoding.UTF8.GetBytes(signedCommit));
var signedId2 = odb.CreateCommitWithSignature(signedData, signatureData);

Assert.Equal(signedId, signedId2);

var signatureInfo = Commit.ExtractSignature(repo, signedId2);
Assert.Equal(signedData, signatureInfo.SignedData);
Assert.Equal(signatureData, signatureInfo.Signature);
}
}
}
Expand Down
36 changes: 36 additions & 0 deletions LibGit2Sharp/Commit.cs
8000
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,42 @@ public static SignatureInfo ExtractSignature(Repository repo, ObjectId id)
return Proxy.git_commit_extract_signature(repo.Handle, id, null);
}

/// <summary>
/// Create a commit in-memory
/// <para>
/// Prettifing the message includes:
/// * Removing empty lines from the beginning and end.
/// * Removing trailing spaces from every line.
/// * Turning multiple consecutive empty lines between paragraphs into just one empty line.
/// * Ensuring the commit message ends with a newline.
/// * Removing every line starting with the <paramref name="commentChar"/>.
/// </para>
/// </summary>
/// <param name="author">The <see cref="Signature"/> of who made the change.</param>
/// <param name="committer">The <see cref="Signature"/> of who added the change to the repository.</param>
/// <param name="message">The description of why a change was made to the repository.</param>
/// <param name="tree">The <see cref="Tree"/> of the <see cref="Commit"/> to be created.</param>
/// <param name="parents">The parents of the <see cref="Commit"/> to be created.</param>
/// <param name="prettifyMessage">True to prettify the message, or false to leave it as is.</param>
/// <param name="commentChar">When non null, lines starting with this character will be stripped if prettifyMessage is true.</param>
/// <returns>The contents of the commit object.</returns>
public static string CreateBuffer(Signature author, Signature committer, string message, Tree tree, IEnumerable<Commit> parents, bool prettifyMessage, char? commentChar)
{
Ensure.ArgumentNotNull(message, "message");
Ensure.ArgumentDoesNotContainZeroByte(message, "message");
Ensure.ArgumentNotNull(author, "author");
Ensure.ArgumentNotNull(committer, "committer");
Ensure.ArgumentNotNull(tree, "tree");
Ensure.ArgumentNotNull(parents, "parents");

if (prettifyMessage)
{
message = Proxy.git_message_prettify(message, commentChar);
}

return Proxy.git_commit_create_buffer(tree.repo.Handle, author, committer, message, tree, parents.ToArray());
}

private class ParentsCollection : ICollection<Commit>
{
private readonly Lazy<ICollection<Commit>> _parents;
Expand Down
21 changes: 21 additions & 0 deletions LibGit2Sharp/Core/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,27 @@ internal static extern unsafe int git_commit_create_from_ids(
UIntPtr parentCount,
[MarshalAs(UnmanagedType.LPArray)] [In] IntPtr[] parents);

[DllImport(libgit2)]
internal static extern unsafe int git_commit_create_buffer(
GitBuf res,
git_repository* repo,
git_signature* author,
git_signature* committer,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string encoding,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string message,
git_object* tree,
UIntPtr parent_count,
IntPtr* parents /* git_commit** originally */);

[DllImport(libgit2)]
internal static extern unsafe int git_commit_create_with_signature(
out GitOid id,
git_repository* repo,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string commit_content,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string signature,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string signature_field);


[DllImport(libgit2)]
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxUtf8NoCleanupMarshaler))]
internal static extern unsafe string git_commit_message(git_object* commit);
Expand Down
55 changes: 55 additions & 0 deletions LibGit2Sharp/Core/Proxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,61 @@ public static unsafe ObjectId git_commit_create(
}
}

public static unsafe string git_commit_create_buffer(
RepositoryHandle repo,
Signature author,
Signature committer,
string message,
Tree tree,
Commit[] parents)
{
using (SignatureHandle authorHandle = author.BuildHandle())
using (SignatureHandle committerHandle = committer.BuildHandle())
using (var treeHandle = Proxy.git_object_lookup(tree.repo.Handle, tree.Id, GitObjectType.Tree))
using (var buf = new GitBuf())
{
ObjectHandle[] handles = new ObjectHandle[0];
try
{
handles = parents.Select(c => Proxy.git_object_lookup(c.repo.Handle, c.Id, GitObjectType.Commit)).ToArray();
var ptrs = handles.Select(p => p.AsIntPtr()).ToArray();
int res;
fixed(IntPtr* objs = ptrs)
{
res = NativeMethods.git_commit_create_buffer(buf,
repo,
authorHandle,
committerHandle,
null,
message,
treeHandle,
new UIntPtr((ulong)parents.LongCount()),
objs);
}
Ensure.ZeroResult(res);
}
finally
{
foreach (var handle in handles)
{
handle.Dispose();
}
}

return LaxUtf8Marshaler.FromNative(buf.ptr);
}
}

public static unsafe ObjectId git_commit_create_with_signature(RepositoryHandle repo, string commitContent,
string signature, string field)
{
GitOid id;
int res = NativeMethods.git_commit_create_with_signature(out id, repo, commitContent, signature, field);
Ensure.ZeroResult(res);

return id;
}

public static unsafe string git_commit_message(ObjectHandle obj)
{
return NativeMethods.git_commit_message(obj);
Expand Down
2 changes: 1 addition & 1 deletion LibGit2Sharp/GitObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public abstract class GitObject : IEquatable<GitObject>, IBelongToARepository
/// <summary>
/// The <see cref="Repository"/> containing the object.
/// </summary>
protected readonly Repository repo;
internal readonly Repository repo;

/// <summary>
/// Needed for mocking purposes.
Expand Down
26 changes: 26 additions & 0 deletions LibGit2Sharp/ObjectDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,32 @@ public virtual Commit CreateCommit(Signature author, Signature committer, string
return commit;
}

/// <summary>
/// Inserts a <see cref="Commit"/> into the object database after attaching the given signature.
/// </summary>
/// <param name="commitContent">The raw unsigned commit</param>
/// <param name="signature">The signature data </param>
/// <param name="field">The header field in the commit in which to store the signature</param>
/// <returns>The created <see cref="Commit"/>.</returns>
public virtual ObjectId CreateCommitWithSignature(string commitContent, string signature, string field)
{
return Proxy.git_commit_create_with_signature(repo.Handle, commitContent, signature, field);
}

/// <summary>
/// Inserts a <see cref="Commit"/> into the object database after attaching the given signature.
/// <para>
/// This overload uses the default header field of "gpgsig"
/// </para>
/// </summary>
/// <param name="commitContent">The raw unsigned commit</param>
/// <param name="signature">The signature data </param>
/// <returns>The created <see cref="Commit"/>.</returns>
public virtual ObjectId CreateCommitWithSignature(string commitContent, string signature)
{
return Proxy.git_commit_create_with_signature(repo.Handle, commitContent, signature, null);
}

/// <summary>
/// Inserts a <see cref="TagAnnotation"/> into the object database, pointing to a specific <see cref="GitObject"/>.
/// </summary>
Expand Down
0