Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
125 changes: 125 additions & 0 deletions lib/commit.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var events = require("events");
var fp = require("lodash/fp");
var NodeGit = require("../");
var Commit = NodeGit.Commit;
var LookupWrapper = NodeGit.Utils.lookupWrapper;
Expand Down Expand Up @@ -50,6 +51,130 @@ Commit.prototype.amend = function (
});
};

/**
* Amend a commit with the given signature
* @async
* @param {String} updateRef
* @param {Signature} author
* @param {Signature} committer
* @param {String} messageEncoding
* @param {String} message
* @param {Tree|Oid} tree
* @param {String} signatureField
* @param {Function} onSignature
* @return {Oid}
*/
Commit.prototype.amendWithSignature = function(
updateRef,
author,
committer,
messageEncoding,
message,
tree,
signatureField,
onSignature
) {
var repo = this.repo;
var parentOids = this.parents();
var _this = this;
var promises = [];

if (tree instanceof NodeGit.Oid) {
promises.push(repo.getTree(tree));
} else {
promises.push(Promise.resolve(tree));
}

parentOids.forEach(function (parentOid) {
promises.push(repo.getCommit(parentOid));
});

var treeObject;
var parents;
var commitContent;
var commitOid;
var commit;

var createCommitPromise = Promise.all(promises)
.then(function(results) {
treeObject = fp.head(results);
parents = fp.tail(results);
return _this.getTree();
})
.then(function(commitTreeResult) {
var commitTree = commitTreeResult;

var truthyArgs = fp.omitBy(
fp.isNil,
{
author,
committer,
messageEncoding,
message,
tree: treeObject
}
);

var commitFields = {
author: _this.author(),
committer: _this.committer(),
messageEncoding: _this.messageEncoding(),
message: _this.message(),
tree: commitTree
};

var {
author: resolvedAuthor,
committer: resolvedCommitter,
messageEncoding: resolvedMessageEncoding,
message: resolvedMessage,
tree: resolvedTree
} = fp.assign(
truthyArgs,
commitFields
);

return Commit.createBuffer(
repo,
resolvedAuthor,
resolvedCommitter,
resolvedMessageEncoding,
resolvedMessage,
resolvedTree,
parents.length,
parents
);
})
.then(function(commitContentResult) {
commitContent = commitContentResult + "\n";
return onSignature(commitContent);
})
.then(function(signature) {
return Commit.createWithSignature(
repo,
commitContent,
signature,
signatureField
);
});

if (!updateRef) {
return createCommitPromise;
}

return createCommitPromise.then(function(commitOidResult) {
commitOid = commitOidResult;
return repo.getCommit(commitOid);
}).then(function(commitResult) {
commit = commitResult;
return repo.getReference(updateRef);
}).then(function(ref) {
return ref.setTarget(commitOid, `commit (amend): ${commit.summary()}`);
}).then(function() {
return commitOid;
});
};

/**
* Retrieve the commit time as a Date object.
* @return {Date}
Expand Down
67 changes: 67 additions & 0 deletions test/tests/commit.js
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,73 @@ describe("Commit", function() {
});
});


it("can amend commit with signature", function() {
const signature = "-----BEGIN PGP SIGNATURE-----\n" +
"\n" +
"iQJHBAEBCAAxFiEEKdxGpJ93wnkLaBKfURjJKedOfEMFAlxPKUYTHHN0ZXZla0Bh\n" +
"eG9zb2Z0LmNvbQAKCRBRGMkp5058Q3vcD/0Uf6P68g98Kbvsgjg/aidM1ujruXaw\n" +
"X5WSsCAw+wWGICOj0n+KBnmQruI4HSFz3zykEshuOpcBv1X/+huwDeB/hBqonCU8\n" +
"QdexCdWR70YbT1bufesUwV9v1qwE4WOmFxWXgwh55K0wDRkc0u2aLcwrJkIEEVfs\n" +
"HqZyFzU4kwbGekY/m7d1DsBhWyKEGW9/25WMYmjWOWOiaFjeBaHLlxiEM8KGnMLH\n" +
"wx37NuFuaABgi23AAcBGdeWy04TEuU4S51+bHM3RotrZ2cryW2lEbkkXodhIJcq0\n" +
"RgrStCbvR0ehnOPdYSiRbxK8JNLZuNjHlK2g7wVi+C83vwMQuhU4H6OlYHGVr664\n" +
"4YzL83FdIo7wiMOFd2OOMLlCfHgTun60FvjCs4WHjrwH1fQl287FRPLa/4olBSQP\n" +
"yUXJaZdxm4cB4L/1pmbb/J/XUiOio3MpaN3GFm2hZloUlag1uPDBtCxTl5odvj4a\n" +
"GOmTBWznXxF/zrKnQVSvv+EccNxYFc0VVjAxGgNqPzIxDAKtw1lE5pbBkFpFpNHz\n" +
"StmwZkP9QIJY4hJYQfM+pzHLe8xjexL+Kh/TrYXgY1m/4vJe0HJSsnRnaR8Yfqhh\n" +
"LReqo94VHRYXR0rZQv4py0D9TrWaI8xHLve6ewhLPNRzyaI9fNrinbcPYZZOWnRi\n" +
"ekgUBx+BX6nJOw==\n" +
"=4Hy5\n" +
"-----END PGP SIGNATURE-----";

function onSignature(dataToSign) {
return new Promise(function (resolve) {
return resolve(signature);
});
}

var repo;
var oid;
var commit;
var message;
var parents;

return NodeGit.Repository.open(reposPath)
.then(function(repoResult) {
repo = repoResult;
return repo.getHeadCommit();
})
.then(function(headCommit) {
message = headCommit.message().trim();
parents = headCommit.parents();

return headCommit.amendWithSignature(
null,
null,
null,
null,
null,
null,
"gpgsig",
onSignature
);
})
.then(function(oidResult) {
oid = oidResult;
return NodeGit.Commit.lookup(repo, oid);
})
.then(function(commitResult) {
commit = commitResult;
return commit.getSignature("gpgsig");
})
.then(function(signatureInfo) {
assert.equal(signatureInfo.signature, signature);
assert.equal(commit.message().trim(), message);
assert.deepEqual(commit.parents(), parents);
});
});

it("has an owner", function() {
var owner = this.commit.owner();
assert.ok(owner instanceof Repository);
Expand Down