Skip to content
Open
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
30 changes: 30 additions & 0 deletions examples/gpg-keys/secret-key-489B1963.asc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBF3GGN0BCAC5S10y3xUYccBF/ElgVYPM61CAmf5vKbGvsEuDIAqBIvHddCw1
myaHqrK67/mkavlbLp3HD9jTgkd5sRrzVVSFGxeGRf2ysFamsGH+rLwvqzpyb4ru
49ThwMUVsuVExdoQB6Il7cdZLnnEZejr+ud9ZsDP24v5nleqOjAkU8GUiLdOaVgx
e6ObEiSQbmzW9mz+DzLrKgbyar4ID+cC4+5y7D2w+eB9Az6EOCJGVxLxUSo9DyFX
3x0e67MrwrdFTPeKjS+HirzGdyJI7oTJsdWJD3rUDWwxSw7v52I8xGWxBOu67dUT
Ruuhe/JNrAtjnDxZC2qfiFgTB98jGov/FENHABEBAAG0JU5vZGVnaXQgRXhhbXBs
ZSA8bm9kZWdpdEBub2RlZ2l0Lm9yZz6JAU4EEwEKADgWIQRQmkqTSsOlqpBdFEs/
lSx6SJsZYwUCXcYY3QIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRA/lSx6
SJsZY9cCB/9uU/Q4GOHAKP5jnD6ZRdV2GM7DIKQKsUHmq/Zmxr6xGnUQoCw8iNcN
5bwJusJbl0/BbVI0MO4oHWTNZYc6KHz6E7NnM/c8yOZHpvl8PcvprNwUTOTUERGE
noDXr4HEwOUvpkzSnkmy8O0mmmX3gtRs5KZCXJFUsVNII2N04w4wNCITNZvMY8ov
A/xRtUuDsljtyrsUq7ZgVLCwC1AvnLqreTOEbu9KaEykgQ8SkfjFmcl9DXtXkKdw
uKonTKpOo7aeXETDHzQictsGAW6BPm2Dac+c1SbsAx0oa6eF9tqrjkkSEAC7SEFy
Qe5EcuMZfqK8LPzFAWR2ICBnDiuZc71TuQENBF3GGN0BCADYlgAEmX2G2Cdkgh/n
4Q8xyqqOw31JClVtMIIV/c7/VY3Od8f3/OTKb3WrKGOsPWs+nVopeJ5fFlIOyDz6
qsujJvP/EltWit6l0SSXufsM7C9HyHS3vEkBW2ltJ/urZXW1bZ/z7ocwn417OnHK
3k90HcncYca1HvctbZ8VPlyhVkyLllaBFDRvfi/asjZEY1hL5j0HvAGi9jvq/UXg
H+/mskc95SQD5CbrSMkkAogfFkX+g/y7gxSAgY09NWco6+6Uiiq2WAp1MOsPa+Y6
rbfYltIU5UCmcfJ2996y4zgCkDlmITY+T7CvkVs6JeKfYiRMZiNMarFoexjGDzEm
EAiLABEBAAGJATYEGAEKACAWIQRQmkqTSsOlqpBdFEs/lSx6SJsZYwUCXcYY3QIb
DAAKCRA/lSx6SJsZYy/8B/sFT1snW1ldY7zICkUNi4aHdqXWNdPsdSRzGn0C2/Vh
lyPQXWUhcI8a0J9DPOZ9LylMB+MD7Bgt2SNjym711Wce77kPURyNby5/j1kc4LU8
3ArKv9ULiJO2C5NBTgK4uevdOALlMy1AJdt3vi5zO9MQW9QnxnHxBNUxAc/BUPqB
en+XpAmxpr0UqU/q7VY8m8Ep8VA5gp2zuib5R1kUl26lctF8Zae1iFVA+KWhK07l
HJsp5zG8TVlGdHSRhhb/Z5f3AbJzRmSrIeJoWUdSaSbJk5kq7jPaYXtPw3EDyv2F
U/m6Om3LBBsBsIzBadNHTtNdt4PTJByA9dGgqTL46Bjp
=7n4W
-----END PGP PUBLIC KEY BLOCK-----
127 changes: 127 additions & 0 deletions examples/signing-commits.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
const nodegit = require('../');
const path = require('path');
const fs = require('fs-extra');
const openpgp = require('openpgp');

const fileName = 'newfile.txt';
const fileContent = 'hello world';
const directoryName = 'salad/toast/strangerinastrangeland/theresnowaythisexists';
/**
* This example creates a certain file `newfile.txt`, adds it to the git
* index and commits with GOG signaature it to head. Similar to a `git add newfile.txt`
* followed by a `git commit -s`
*
* This example uses `openpgp` library (https://github.com/openpgpjs/openpgpjs)
* to read the key and encrypt the commit message. This involves two functions:
* - the `decryptGpg` function which is responsible for decrypting the GPG key
* - the `onSignature` function which is called during commit operation
*
* The `onSignature` function is the callback function passed to the
* `createCommitWithSignature()` function of Repository instance.
*
* This example uses dummy GPG key. Learn how to generate a GPG key on HitHub
* help pages: https://help.github.com/en/github/authenticating-to-github/generating-a-new-gpg-key
**/

/**
* Decrypts GPG key to be used to sign commits.
* @return {Promise}
*/
async function decryptGpg() {
const key = path.join(__dirname, 'gpg-keys', 'secret-key-489B1963.asc');
const pass = 'nodegit';
const buff = await fs.readFile(key);
const armored = await openpgp.key.readArmored(buff);
const keyObj = armored.keys[0];
const decrypted = keyObj.decrypt(pass);
if (decrypted) {
return keyObj;
}
}

/**
* Callback for GPG signature when signing the commit.
* @param {String} tosign A string to sign.
* @return {Promise}
*/
async function onSignature(tosign) {
const privateKeyResult = await decryptGpg();
if (!privateKeyResult) {
throw new Error('GPG key decoding error.');
}
const buf = new Uint8Array(tosign.length);
for (let i = 0; i < tosign.length; i++) {
buf[i] = tosign.charCodeAt(i);
}
const options = {
message: openpgp.message.fromBinary(buf),
privateKeys: [privateKeyResult],
detached: true
};
const signed = await openpgp.sign(options);
return {
code: nodegit.Git.Error.CODE.OK,
field: 'gpgsig',
signedData: signed.signature
};
}

/**
* Creates files in the local filesystem. This files will be added to the
* repository.
* @param {Repository} repo
* @return {Promise} A promise resolved when files are created
*/
async function addFiles(repo) {
await fs.ensureDir(path.join(repo.workdir(), directoryName));
await fs.writeFile(path.join(repo.workdir(), fileName), fileContent);
await fs.writeFile(
path.join(repo.workdir(), directoryName, fileName),
fileContent
);
}
/**
* Adds files by path and writes the state to the index.
* @param {Repository} repo
* @return {Promise} A promise resolved to an Oid
*/
async function addAndWrite(repo) {
const index = await repo.refreshIndex();
await index.addByPath(fileName);
await index.addByPath(path.posix.join(directoryName, fileName));
await index.write();
return await index.writeTree();
}
/**
* Commits changes using GPG key.
* @param {Repository} repo
* @param {Oid} oid Write Oid
* @return {Promise} Resolved when the commit is ready.
*/
async function commitSigned(repo, oid) {
const head = await nodegit.Reference.nameToId(repo, 'HEAD');
const parent = await repo.getCommit(head);
const author = nodegit.Signature.now('Pawel Psztyc', 'jarrodek@gmail.com');
const committer = nodegit.Signature.now('Pawel Psztyc', 'jarrodek@gmail.com');
return await repo.createCommitWithSignature(
'HEAD',
author,
committer,
'message',
oid,
[parent],
onSignature
);
}

let repo;
nodegit.Repository.open(path.resolve(__dirname, '../.git'))
.then((result) => {
repo = result;
return addFiles(repo);
})
.then(() => addAndWrite(repo))
.then((oid) => commitSigned(repo, oid))
.then((commitId) => {
console.log(`New commit: ${commitId}`);
});