From a48779bc7293f0927cc5b87f93cd569ad17d2484 Mon Sep 17 00:00:00 2001 From: Carson Howard Date: Thu, 13 Jul 2017 12:41:20 -0700 Subject: [PATCH 1/6] Added blob methods and converted to async --- generate/input/descriptor.json | 52 ++++- test/tests/blob.js | 397 +++++++++++++++++++++++++++++++++ test/tests/diff.js | 9 +- 3 files changed, 453 insertions(+), 5 deletions(-) diff --git a/generate/input/descriptor.json b/generate/input/descriptor.json index 1290486d9..7d1953de8 100644 --- a/generate/input/descriptor.json +++ b/generate/input/descriptor.json @@ -130,7 +130,7 @@ "selfFreeing": true, "functions": { "git_blob_create_frombuffer": { - "isAsync": false, + "isAsync": true, "args": { "id": { "isReturn": true @@ -141,11 +141,59 @@ } } }, + "git_blob_create_fromworkdir": { + "isAsync": true, + "args": { + "id": { + "isReturn": true + } + }, + "return": { + "isErrorCode": true + } + }, + "git_blob_create_fromdisk": { + "isAsync": true, + "args": { + "id": { + "isReturn": true + } + }, + "return": { + "isErrorCode": true + } + }, "git_blob_create_fromchunks": { "ignore": true }, "git_blob_filtered_content": { - "ignore": true + "isAsync": true, + "isPrototypeMethod": false, + "args": { + "out": { + "isReturn": true, + "cppClassName": "GitBuf", + "jsClassName": "Buffer" + }, + "blob": { + "cppClassName": "GitBlob", + "jsClassName": "Blob", + "isSelf": false + }, + "as_path": { + "cppClassName": "String", + "jsClassName": "String", + "cType": "const char *" + }, + "check_for_binary_data": { + "cppClassName": "Number", + "jsClassName": "Number", + "cType": "int" + } + }, + "return": { + "isErrorCode": true + } }, "git_blob_id": { "return": { diff --git a/test/tests/blob.js b/test/tests/blob.js index 342cb2578..a6c466995 100644 --- a/test/tests/blob.js +++ b/test/tests/blob.js @@ -1,17 +1,69 @@ var assert = require("assert"); var path = require("path"); var local = path.join.bind(path, __dirname); +var promisify = require("promisify-node"); +var fse = promisify("fs-extra"); describe("Blob", function() { var NodeGit = require("../../"); var Oid = NodeGit.Oid; var Repository = NodeGit.Repository; + var Blob = NodeGit.Blob; var FileMode = NodeGit.TreeEntry.FILEMODE; var reposPath = local("../repos/workdir"); var oid = "111dd657329797f6165f52f5085f61ac976dcf04"; + function commitFile(repo, fileName, fileContent, commitMessage) { + var index; + var treeOid; + var parent; + + return fse.writeFile(path.join(repo.workdir(), fileName), fileContent) + .then(function() { + return repo.refreshIndex(); + }) + .then(function(indexResult) { + index = indexResult; + }) + .then(function() { + return index.addByPath(fileName); + }) + .then(function() { + return index.write(); + }) + .then(function() { + return index.writeTree(); + }) + .then(function(oidResult) { + treeOid = oidResult; + return NodeGit.Reference.nameToId(repo, "HEAD"); + }) + .then(function(head) { + return repo.getCommit(head); + }) + .then(function(parentResult) { + parent = parentResult; + return Promise.all([ + NodeGit.Signature.create("Foo Bar", "foo@bar.com", 123456789, 60), + NodeGit.Signature.create("Foo A Bar", "foo@bar.com", 987654321, 90) + ]); + }) + .then(function(signatures) { + var author = signatures[0]; + var committer = signatures[1]; + + return repo.createCommit( + "HEAD", + author, + committer, + commitMessage, + treeOid, + [parent]); + }); + } + beforeEach(function() { var test = this; @@ -50,4 +102,349 @@ describe("Blob", function() { assert.equal(blob.id().toString(), oid); }); }); + + describe("createFromBuffer", function() { + it("creates a new blob from the buffer", function() { + var content = "This is a new buffer"; + var buf = new Buffer(content, content.length); + var test = this; + + return Blob.createFromBuffer(test.repository, buf, content.length) + .then(function(oid) { + return test.repository.getBlob(oid); + }) + .then(function(newBlob) { + assert.equal(newBlob.toString(), content); + }); + }); + + it("creates blob with content equal to length", function() { + var content = "This is a new buffer"; + var buf = new Buffer(content, content.length); + var test = this; + + return Blob.createFromBuffer(test.repository, buf, 2) + .then(function(oid) { + return test.repository.getBlob(oid); + }) + .then(function(newBlob) { + assert.equal(newBlob.toString(), "Th"); + }); + }); + + it("throws an error when repository is null", function() { + return Blob.createFromBuffer(null, null, 0) + .catch(function(error) { + assert.strictEqual(error.message, "Repository repo is required."); + }); + }); + + it("throws an error when buffer is null", function() { + var test = this; + return Blob.createFromBuffer(test.repository, null) + .catch(function(error) { + assert.strictEqual(error.message, "Buffer buffer is required."); + }); + }); + + it("throws an error when no length is provided", function() { + var test = this; + return Blob.createFromBuffer(test.repository, new Buffer("testing")) + .catch(function(error) { + assert.strictEqual(error.message, "Number len is required."); + }); + }); + }); + + describe("createFromDisk", function() { + var fileName = path.join(reposPath, "testFile.zzz"); + var fileContent = "this is my file content"; + + beforeEach(function() { + return fse.writeFile(fileName, fileContent); + }); + + afterEach(function() { + return fse.unlink(fileName); + }); + + it("creates a new blob from the file", function() { + var test = this; + + return Blob.createFromDisk(test.repository, fileName) + .then(function(oid) { + return test.repository.getBlob(oid); + }) + .then(function(newBlob) { + assert.equal(newBlob.toString(), fileContent); + }); + }); + + it("throws an error when the file cannot be found", function() { + var test = this; + + return Blob.createFromDisk(test.repository, "aaaaaaaaaa") + .catch(function(error) { + assert.equal(error.errno, -3); + }); + }); + + it("throws an error when repository is null", function() { + return Blob.createFromDisk(null, null, 0) + .catch(function(error) { + assert.strictEqual(error.message, "Repository repo is required."); + }); + }); + + it("throws an error when path is null", function() { + var test = this; + return Blob.createFromDisk(test.repository, null) + .catch(function(error) { + assert.strictEqual(error.message, "String path is required."); + }); + }); + }); + + describe("createFromWorkdir", function() { + it("creates a blob from the file", function() { + var fileName = "package.json"; + var filePath = path.join(reposPath, "package.json"); + var test = this; + + return fse.readFile(filePath) + .then(function(content) { + test.content = content.toString(); + return Blob.createFromWorkdir(test.repository, fileName); + }) + .then(function(oid) { + return test.repository.getBlob(oid); + }) + .then(function(newBlob) { + assert.equal(newBlob.toString(), test.content); + }); + }); + + it("throws an error when the file cannot be found", function() { + var test = this; + + return Blob.createFromWorkdir(test.repository, "thisisabadfile.jpg") + .catch(function(error) { + assert.equal(error.errno, -3); + }); + }); + + it("throws an error when repository is null", function() { + return Blob.createFromWorkdir(null, null, 0) + .catch(function(error) { + assert.strictEqual(error.message, "Repository repo is required."); + }); + }); + + it("throws an error when path is null", function() { + var test = this; + return Blob.createFromWorkdir(test.repository, null) + .catch(function(error) { + assert + .strictEqual(error.message, "String relative_path is required."); + }); + }); + }); + + describe("filteredContent", function() { + var attrFileName = ".gitattributes"; + var filter = "* text eol=crlf"; + var lineEndingRegex = /\r\n|\r|\n/; + var newFileName = "testfile.test"; + + it("retrieves the filtered content", function() { + var test = this; + + return commitFile( + test.repository, + attrFileName, + filter, + "added gitattributes") + .then(function() { + return commitFile( + test.repository, + newFileName, + "this\nis\nfun\guys", + "added LF ending file"); + }) + .then(function(oid) { + return test.repository.getCommit(oid); + }) + .then(function(commit) { + test.filteredCommit = commit; + return commit.getEntry(newFileName); + }) + .then(function(entry) { + return entry.getBlob(); + }) + .then(function(lfBlob) { + test.lfBlob = lfBlob; + var ending = test.lfBlob.toString().match(lineEndingRegex); + assert.strictEqual(ending[0], "\n"); + + return Blob.filteredContent( + test.lfBlob, + newFileName, + 0); + }) + .then(function(content) { + var ending = content.match(lineEndingRegex); + assert.strictEqual(ending[0], "\r\n"); + assert.notStrictEqual(content, test.blob.toString()); + }); + }); + + it("returns non-binary filtered content when checking binary", function() { + var test = this; + + return commitFile( + test.repository, + attrFileName, + filter, + "added gitattributes") + .then(function() { + return commitFile( + test.repository, + newFileName, + "this\nis\nfun\guys", + "added LF ending file"); + }) + .then(function(oid) { + return test.repository.getCommit(oid); + }) + .then(function(commit) { + test.filteredCommit = commit; + return commit.getEntry(newFileName); + }) + .then(function(entry) { + return entry.getBlob(); + }) + .then(function(lfBlob) { + test.lfBlob = lfBlob; + var ending = test.lfBlob.toString().match(lineEndingRegex); + assert.strictEqual(ending[0], "\n"); + + return Blob.filteredContent( + test.lfBlob, + newFileName, + 1); + }) + .then(function(content) { + var ending = content.match(lineEndingRegex); + assert.strictEqual(ending[0], "\r\n"); + assert.notStrictEqual(content, test.blob.toString()); + }); + }); + + it("returns nothing when checking binary blob", function() { + var test = this; + var binary = new Buffer(new Uint8Array([1,2,3,4,5,6])); + + return commitFile( + test.repository, + attrFileName, + filter, + "added gitattributes") + .then(function() { + return commitFile( + test.repository, + newFileName, + binary, + "binary content"); + }) + .then(function(oid) { + return test.repository.getCommit(oid); + }) + .then(function(commit) { + test.filteredCommit = commit; + return commit.getEntry(newFileName); + }) + .then(function(entry) { + return entry.getBlob(); + }) + .then(function(bblob) { + test.bblob = bblob; + assert.equal(true, bblob.isBinary()); + + return Blob.filteredContent( + test.bblob, + newFileName, + 1); + }) + .then(function(content) { + assert.strictEqual(content, ""); + }); + }); + + it("returns blob when not checking binary on binary blob", function() { + var test = this; + var binary = new Buffer(new Uint8Array([1,2,3,4,5,6])); + + return commitFile( + test.repository, + attrFileName, + filter, + "added gitattributes") + .then(function() { + return commitFile( + test.repository, + newFileName, + binary, + "binary content"); + }) + .then(function(oid) { + return test.repository.getCommit(oid); + }) + .then(function(commit) { + test.filteredCommit = commit; + return commit.getEntry(newFileName); + }) + .then(function(entry) { + return entry.getBlob(); + }) + .then(function(bblob) { + test.bblob = bblob; + assert.equal(true, bblob.isBinary()); + + return Blob.filteredContent( + test.bblob, + newFileName, + 0); + }) + .then(function(content) { + assert.strictEqual(content, binary.toString()); + }); + }); + + it("throws an error when the blob is null", function() { + return Blob.filteredContent(null, "", 0) + .catch(function(err) { + assert.strictEqual( + err.message, + "Blob blob is required."); + }); + }); + + it("throws an error when the path is null", function() { + var test = this; + return Blob.filteredContent(test.blob, null, 0) + .catch(function(err) { + assert.strictEqual(err.message, "String as_path is required."); + }); + }); + + it("throws an error when the flag is undefined", function() { + var test = this; + return Blob.filteredContent(test.blob, "") + .catch(function(err) { + assert.strictEqual( + err.message, + "Number check_for_binary_data is required."); + }); + }); + }); }); diff --git a/test/tests/diff.js b/test/tests/diff.js index 43d14a3ec..fdad25354 100644 --- a/test/tests/diff.js +++ b/test/tests/diff.js @@ -247,10 +247,13 @@ describe("Diff", function() { function(done) { var evilString = "Unicode’s fun!\nAnd it’s good for you!\n"; var buffer = new Buffer(evilString); - var oid = Blob.createFromBuffer(this.repository, buffer, buffer.length); - Blob.lookup(this.repository, oid) + var test = this; + Blob.createFromBuffer(test.repository, buffer, buffer.length) + .then(function(oid) { + return Blob.lookup(test.repository, oid); + }) .then(function(blob) { - blob.repo = this.repository; + blob.repo = test.repository; return Diff.blobToBuffer( blob, null, From d7eff48e14def704f623ca075515ac4d989400ed Mon Sep 17 00:00:00 2001 From: Carson Howard Date: Tue, 25 Jul 2017 14:52:54 -0700 Subject: [PATCH 2/6] Fixed test and made repo blob method return a promise --- lib/repository.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/repository.js b/lib/repository.js index bcf8591c7..33adcc498 100644 --- a/lib/repository.js +++ b/lib/repository.js @@ -511,8 +511,8 @@ Repository.prototype.createBranch = function(name, commit, force) { * @param {Buffer} buffer * @return {Oid} */ -Repository.prototype.createBlobFromBuffer = function(buffer, callback) { - return Blob.createFromBuffer(this, buffer, buffer.length, callback); +Repository.prototype.createBlobFromBuffer = function(buffer) { + return Blob.createFromBuffer(this, buffer, buffer.length); }; /** @@ -1784,9 +1784,9 @@ Repository.prototype.stageLines = .then(function(newContent) { var newContentBuffer = new Buffer(newContent); - var newOid = repo.createBlobFromBuffer(newContentBuffer); - return repo.getBlob(newOid); + return repo.createBlobFromBuffer(newContentBuffer); }) + .then(newOid => repo.getBlob(newOid)) .then(function(newBlob) { var entry = index.getByPath(filePath, 0); entry.id = newBlob.id(); From be3955eba3718cb6306b61396c39be97f9e70714 Mon Sep 17 00:00:00 2001 From: Carson Howard Date: Tue, 25 Jul 2017 16:26:31 -0700 Subject: [PATCH 3/6] Fixed unit tests --- test/tests/blob.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/tests/blob.js b/test/tests/blob.js index a6c466995..004136147 100644 --- a/test/tests/blob.js +++ b/test/tests/blob.js @@ -3,6 +3,7 @@ var path = require("path"); var local = path.join.bind(path, __dirname); var promisify = require("promisify-node"); var fse = promisify("fs-extra"); +var exec = require("../../utils/execPromise"); describe("Blob", function() { var NodeGit = require("../../"); @@ -14,6 +15,7 @@ describe("Blob", function() { var reposPath = local("../repos/workdir"); var oid = "111dd657329797f6165f52f5085f61ac976dcf04"; + var previousCommitOid = ""; function commitFile(repo, fileName, fileContent, commitMessage) { var index; @@ -64,6 +66,16 @@ describe("Blob", function() { }); } + before(function() { + return Repository.open(reposPath) + .then(function(repository) { + return repository.getHeadCommit(); + }) + .then(function(commit) { + previousCommitOid = commit.id(); + }); + }); + beforeEach(function() { var test = this; @@ -78,6 +90,17 @@ describe("Blob", function() { }); }); + after(function() { + console.log("cleaning"); + return exec("git clean -xdf", {cwd: reposPath}) + .then(function() { + return exec("git checkout master", {cwd: reposPath}); + }) + .then(function() { + return exec("git reset --hard " + previousCommitOid, {cwd: reposPath}); + }); + }); + it("can provide content as a buffer", function() { var contents = this.blob.content(); From c87633eae89bf5c615ee2689dd755e01941f3667 Mon Sep 17 00:00:00 2001 From: Carson Howard Date: Tue, 25 Jul 2017 16:33:55 -0700 Subject: [PATCH 4/6] removed console.log --- test/tests/blob.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/tests/blob.js b/test/tests/blob.js index 004136147..70543323c 100644 --- a/test/tests/blob.js +++ b/test/tests/blob.js @@ -91,7 +91,6 @@ describe("Blob", function() { }); after(function() { - console.log("cleaning"); return exec("git clean -xdf", {cwd: reposPath}) .then(function() { return exec("git checkout master", {cwd: reposPath}); From ff97c4beff1a29b47685e2e838c35f608c545bd4 Mon Sep 17 00:00:00 2001 From: Carson Howard Date: Mon, 31 Jul 2017 07:35:10 -0700 Subject: [PATCH 5/6] style fixes --- test/tests/blob.js | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/test/tests/blob.js b/test/tests/blob.js index 70543323c..a4299cee4 100644 --- a/test/tests/blob.js +++ b/test/tests/blob.js @@ -62,7 +62,8 @@ describe("Blob", function() { committer, commitMessage, treeOid, - [parent]); + [parent] + ); }); } @@ -291,7 +292,8 @@ describe("Blob", function() { test.repository, newFileName, "this\nis\nfun\guys", - "added LF ending file"); + "added LF ending file" + ); }) .then(function(oid) { return test.repository.getCommit(oid); @@ -311,7 +313,8 @@ describe("Blob", function() { return Blob.filteredContent( test.lfBlob, newFileName, - 0); + 0 + ); }) .then(function(content) { var ending = content.match(lineEndingRegex); @@ -333,7 +336,8 @@ describe("Blob", function() { test.repository, newFileName, "this\nis\nfun\guys", - "added LF ending file"); + "added LF ending file" + ); }) .then(function(oid) { return test.repository.getCommit(oid); @@ -353,7 +357,8 @@ describe("Blob", function() { return Blob.filteredContent( test.lfBlob, newFileName, - 1); + 1 + ); }) .then(function(content) { var ending = content.match(lineEndingRegex); @@ -376,7 +381,8 @@ describe("Blob", function() { test.repository, newFileName, binary, - "binary content"); + "binary content" + ); }) .then(function(oid) { return test.repository.getCommit(oid); @@ -395,7 +401,8 @@ describe("Blob", function() { return Blob.filteredContent( test.bblob, newFileName, - 1); + 1 + ); }) .then(function(content) { assert.strictEqual(content, ""); @@ -416,7 +423,8 @@ describe("Blob", function() { test.repository, newFileName, binary, - "binary content"); + "binary content" + ); }) .then(function(oid) { return test.repository.getCommit(oid); @@ -435,7 +443,8 @@ describe("Blob", function() { return Blob.filteredContent( test.bblob, newFileName, - 0); + 0 + ); }) .then(function(content) { assert.strictEqual(content, binary.toString()); @@ -447,7 +456,8 @@ describe("Blob", function() { .catch(function(err) { assert.strictEqual( err.message, - "Blob blob is required."); + "Blob blob is required." + ); }); }); @@ -465,7 +475,8 @@ describe("Blob", function() { .catch(function(err) { assert.strictEqual( err.message, - "Number check_for_binary_data is required."); + "Number check_for_binary_data is required." + ); }); }); }); From cdfad45b16638b68cc6709773dcc784753986933 Mon Sep 17 00:00:00 2001 From: Carson Howard Date: Wed, 16 Aug 2017 07:53:20 -0700 Subject: [PATCH 6/6] renamed bblob to binaryBlob --- test/tests/blob.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/tests/blob.js b/test/tests/blob.js index a4299cee4..dce4ce619 100644 --- a/test/tests/blob.js +++ b/test/tests/blob.js @@ -394,12 +394,12 @@ describe("Blob", function() { .then(function(entry) { return entry.getBlob(); }) - .then(function(bblob) { - test.bblob = bblob; - assert.equal(true, bblob.isBinary()); + .then(function(binaryBlob) { + test.binaryBlob = binaryBlob; + assert.equal(true, binaryBlob.isBinary()); return Blob.filteredContent( - test.bblob, + test.binaryBlob, newFileName, 1 ); @@ -436,12 +436,12 @@ describe("Blob", function() { .then(function(entry) { return entry.getBlob(); }) - .then(function(bblob) { - test.bblob = bblob; - assert.equal(true, bblob.isBinary()); + .then(function(binaryBlob) { + test.binaryBlob = binaryBlob; + assert.equal(true, binaryBlob.isBinary()); return Blob.filteredContent( - test.bblob, + test.binaryBlob, newFileName, 0 );