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
16 changes: 10 additions & 6 deletions generate/input/descriptor.json
Original file line number Diff line number Diff line change
Expand Up @@ -3597,7 +3597,16 @@
"isAsync": true
},
"git_tag_create_frombuffer": {
"ignore": true
"jsFunctionName": "createFromBuffer",
"args": {
"oid": {
"isReturn": true
}
},
"return": {
"isErrorCode": true
},
"isAsync": true
},
"git_tag_create_lightweight": {
"args": {
Expand Down Expand Up @@ -3698,11 +3707,6 @@
"dependencies": [
"git2/sys/time.h"
],
"fields": {
"sign": {
"ignore": true
}
},
"functions": {
"git_time_sign": {
"ignore": true
Expand Down
3 changes: 3 additions & 0 deletions generate/templates/partials/convert_to_v8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
to = Nan::New<v8::String>({{= parsedName =}}, {{ size }}).ToLocalChecked();
{% elsif cType == 'char **' %}
to = Nan::New<v8::String>(*{{= parsedName =}}).ToLocalChecked();
{% elsif cType == 'char' %}
char convertToNullTerminated[2] = { {{= parsedName =}}, '\0' };
to = Nan::New<v8::String>(convertToNullTerminated).ToLocalChecked();
{% else %}
to = Nan::New<v8::String>({{= parsedName =}}).ToLocalChecked();
{% endif %}
Expand Down
35 changes: 31 additions & 4 deletions lib/signature.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,38 @@
var NodeGit = require("../");
var Signature = NodeGit.Signature;

const toPaddedDoubleDigitString = (number) => {
if (number < 10) {
return `0${number}`;
}

return `${number}`;
};

/**
* Standard string representation of an author.
*
* @return {string} Representation of the author.
* @param {Boolean} withTime Whether or not to include timestamp
* @return {String} Representation of the author.
*/
Signature.prototype.toString = function() {
return this.name().toString() + " <" + this.email().toString() + ">";
Signature.prototype.toString = function(withTime) {
const name = this.name().toString();
const email = this.email().toString();

let stringifiedSignature = `${name} <${email}>`;

if (!withTime) {
return stringifiedSignature;
}

const when = this.when();
const offset = when.offset();
const offsetMagnitude = Math.abs(offset);
const time = when.time();

const sign = (offset < 0 || when.sign() === "-") ? "-" : "+";
const hours = toPaddedDoubleDigitString(Math.floor(offsetMagnitude / 60));
const minutes = toPaddedDoubleDigitString(offsetMagnitude % 60);

stringifiedSignature += ` ${time} ${sign}${hours}${minutes}`;
return stringifiedSignature;
};
115 changes: 109 additions & 6 deletions lib/tag.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,114 @@ var NodeGit = require("../");
var LookupWrapper = NodeGit.Utils.lookupWrapper;
var Tag = NodeGit.Tag;

const signatureRegexesBySignatureType = {
gpgsig: [
/-----BEGIN PGP SIGNATURE-----[\s\S]+?-----END PGP SIGNATURE-----/gm,
/-----BEGIN PGP MESSAGE-----[\s\S]+?-----END PGP MESSAGE-----/gm,
],
x509: [
/-----BEGIN SIGNED MESSAGE-----[\s\S]+?-----END SIGNED MESSAGE-----/gm,
]
};

/**
* Retrieves the tag pointed to by the oid
* @async
* @param {Repository} repo The repo that the tag lives in
* @param {String|Oid|Tag} id The tag to lookup
* @return {Tag}
*/
* Retrieves the tag pointed to by the oid
* @async
* @param {Repository} repo The repo that the tag lives in
* @param {String|Oid|Tag} id The tag to lookup
* @return {Tag}
*/
Tag.lookup = LookupWrapper(Tag);

/**
* @async
* @param {Repository} repo
* @param {String} tagName
* @param {Oid} target
* @param {Signature} tagger
* @return {String}
*/
Tag.createBuffer = function(repo, tagName, target, tagger, message) {
return NodeGit.Object.lookup(repo, target, NodeGit.Object.TYPE.ANY)
.then((object) => {
if (!NodeGit.Object.typeisloose(object.type())) {
throw new Error("Object must be a loose type");
}

const id = object.id().toString();
const objectType = NodeGit.Object.type2String(object.type());
const lines = [
`object ${id}`,
`type ${objectType}`,
`tag ${tagName}`,
`tagger ${tagger.toString(true)}\n`,
`${message}${message.endsWith("\n") ? "" : "\n"}`
];
return lines.join("\n");
});
};

/**
* @async
* @param {Repository} repo
* @param {String} tagName
* @param {Oid} target
* @param {Signature} tagger
* @param {String} message
* @param {Number} force
* @param {Function} signingCallback Takes a string and returns a string
* representing the signed message
* @return {Oid}
*/
Tag.createWithSignature = function(
repo,
tagName,
target,
tagger,
message,
force,
signingCallback
) {
let tagBuffer;
return Tag.createBuffer(repo, tagName, target, tagger, message)
.then((tagBufferResult) => {
tagBuffer = tagBufferResult;
return signingCallback(tagBuffer);
})
.then((tagSignature) => {
const normalizedEnding = tagSignature.endsWith("\n") ? "" : "\n";
const signedTagString = tagBuffer + tagSignature + normalizedEnding;
return Tag.createFromBuffer(repo, signedTagString, force);
});
};

/**
* Retrieves the signature of an annotated tag
* @async
* @param {String} signatureType
* @return {String|null}
*/
Tag.prototype.extractSignature = function(signatureType = "gpgsig") {
const id = this.id();
const repo = this.repo;
const signatureRegexes = signatureRegexesBySignatureType[signatureType];
if (!signatureRegexes) {
throw new Error("Unsupported signature type");
}

return repo.odb().then((odb) => {
return odb.read(id);
}).then((odbObject) => {
const odbData = odbObject.toString();

for (const regex of signatureRegexes) {
const matchResult = regex.exec(odbData);

if (matchResult !== null) {
return matchResult[0];
}
}

return null;
});
};
25 changes: 25 additions & 0 deletions test/tests/signature.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,29 @@ describe("Signature", function() {
// the self-freeing time should get freed
assert.equal(startSelfFreeingCount, endSelfFreeingCount);
});

it("toString does not provide a timestamp by default", function () {
const signature = Signature.create(
"Shaggy Rogers",
"shaggy@mystery.com",
987654321,
90
);

assert.equal(signature.toString(), "Shaggy Rogers <shaggy@mystery.com>");
});

it("toString provides the correct timestamp when requested", function() {
const signature = Signature.create(
"Shaggy Rogers",
"shaggy@mystery.com",
987654321,
90
);

assert.equal(
signature.toString(true),
"Shaggy Rogers <shaggy@mystery.com> 987654321 +0130"
);
});
});
Loading