From bc0f89b09a4f1456f652068701b87a73d8e8b316 Mon Sep 17 00:00:00 2001 From: Mengwei Ding Date: Mon, 29 Apr 2019 11:17:07 +0800 Subject: [PATCH 1/3] Override the options for Worktree.add --- generate/input/libgit2-supplement.json | 7 + .../templates/manual/worktree/worktree_add.cc | 211 ++++++++++++++++++ package-lock.json | 2 +- test/tests/worktree.js | 49 ++++ 4 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 generate/templates/manual/worktree/worktree_add.cc create mode 100644 test/tests/worktree.js diff --git a/generate/input/libgit2-supplement.json b/generate/input/libgit2-supplement.json index f0a3bf327..c78082956 100644 --- a/generate/input/libgit2-supplement.json +++ b/generate/input/libgit2-supplement.json @@ -107,6 +107,13 @@ "isPrototypeMethod": false, "group": "clone" }, + "git_worktree_add": { + "isManual": true, + "cFile": "generate/templates/manual/worktree/worktree_add.cc", + "isAsync": true, + "isPrototypeMethod": false, + "group": "worktree" + }, "git_commit_extract_signature": { "args": [ { diff --git a/generate/templates/manual/worktree/worktree_add.cc b/generate/templates/manual/worktree/worktree_add.cc new file mode 100644 index 000000000..8277b06f5 --- /dev/null +++ b/generate/templates/manual/worktree/worktree_add.cc @@ -0,0 +1,211 @@ +NAN_METHOD(GitWorktree::Add) { + + if (info.Length() == 0 || !info[0]->IsObject()) { + return Nan::ThrowError("Repository repo is required."); + } + + if (info.Length() == 1 || !info[1]->IsString()) { + return Nan::ThrowError("String name is required."); + } + + if (info.Length() == 2 || !info[2]->IsString()) { + return Nan::ThrowError("String path is required."); + } + + if (info.Length() == 3 || !info[3]->IsObject()) { + return Nan::ThrowError("WorktreeAddOptions opts is required."); + } + + if (info.Length() == 4 || !info[4]->IsFunction()) { + return Nan::ThrowError("Callback is required and must be a Function."); + } + + AddBaton* baton = new AddBaton; + + baton->error_code = GIT_OK; + baton->error = NULL; + +// start convert_from_v8 block + git_repository * from_repo = NULL; +from_repo = Nan::ObjectWrap::Unwrap(info[0]->ToObject())->GetValue(); +// end convert_from_v8 block + baton->repo = from_repo; +// start convert_from_v8 block + const char * from_name = NULL; + + String::Utf8Value name(info[1]->ToString()); + // malloc with one extra byte so we can add the terminating null character C-strings expect: + from_name = (const char *) malloc(name.length() + 1); + // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in + // the middle of strings are valid coming from nodejs): + memcpy((void *)from_name, *name, name.length()); + // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types + // used in the nodejs binding generation: + memset((void *)(((char *)from_name) + name.length()), 0, 1); +// end convert_from_v8 block + baton->name = from_name; +// start convert_from_v8 block + const char * from_path = NULL; + + String::Utf8Value path(info[2]->ToString()); + // malloc with one extra byte so we can add the terminating null character C-strings expect: + from_path = (const char *) malloc(path.length() + 1); + // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in + // the middle of strings are valid coming from nodejs): + memcpy((void *)from_path, *path, path.length()); + // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types + // used in the nodejs binding generation: + memset((void *)(((char *)from_path) + path.length()), 0, 1); +// end convert_from_v8 block + baton->path = from_path; +// start convert_from_v8 block + // Create a git_worktree_add_options with the default value + const git_worktree_add_options from_opts = {1, 0, NULL}; +// end convert_from_v8 block + baton->opts = &from_opts; + + Nan::Callback *callback = new Nan::Callback(v8::Local::Cast(info[4])); + AddWorker *worker = new AddWorker(baton, callback); + + if (!info[0]->IsUndefined() && !info[0]->IsNull()) + worker->SaveToPersistent("repo", info[0]->ToObject()); + if (!info[1]->IsUndefined() && !info[1]->IsNull()) + worker->SaveToPersistent("name", info[1]->ToObject()); + if (!info[2]->IsUndefined() && !info[2]->IsNull()) + worker->SaveToPersistent("path", info[2]->ToObject()); + if (!info[3]->IsUndefined() && !info[3]->IsNull()) + worker->SaveToPersistent("opts", info[3]->ToObject()); + + AsyncLibgit2QueueWorker(worker); + return; +} + +void GitWorktree::AddWorker::Execute() { + git_error_clear(); + + { + LockMaster lockMaster( + /*asyncAction: */true + ,baton->repo + ,baton->name + ,baton->path + ,baton->opts + ); + + int result = git_worktree_add( +&baton->out,baton->repo,baton->name,baton->path,baton->opts ); + + baton->error_code = result; + + if (result != GIT_OK && git_error_last() != NULL) { + baton->error = git_error_dup(git_error_last()); + } + + } +} + +void GitWorktree::AddWorker::HandleOKCallback() { + if (baton->error_code == GIT_OK) { + v8::Local to; +// start convert_to_v8 block + if (baton->out != NULL) { + v8::Local owners = Nan::New(0); + Nan::Set(owners, Nan::New(owners->Length()), this->GetFromPersistent("repo")->ToObject()); + to = GitWorktree::New( + baton->out, + true + , owners + ); + } + else { + to = Nan::Null(); + } + // end convert_to_v8 block + v8::Local result = to; + + v8::Local argv[2] = { + Nan::Null(), + result + }; + callback->Call(2, argv, async_resource); + } else { + if (baton->error) { + v8::Local err; + if (baton->error->message) { + err = Nan::Error(baton->error->message)->ToObject(); + } else { + err = Nan::Error("Method add has thrown an error.")->ToObject(); + } + err->Set(Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code)); + err->Set(Nan::New("errorFunction").ToLocalChecked(), Nan::New("Worktree.add").ToLocalChecked()); + v8::Local argv[1] = { + err + }; + callback->Call(1, argv, async_resource); + if (baton->error->message) + free((void *)baton->error->message); + free((void *)baton->error); + } else if (baton->error_code < 0) { + std::queue< v8::Local > workerArguments; + workerArguments.push(GetFromPersistent("repo")); + workerArguments.push(GetFromPersistent("name")); + workerArguments.push(GetFromPersistent("path")); + workerArguments.push(GetFromPersistent("opts")); + bool callbackFired = false; + while(!workerArguments.empty()) { + v8::Local node = workerArguments.front(); + workerArguments.pop(); + + if ( + !node->IsObject() + || node->IsArray() + || node->IsBooleanObject() + || node->IsDate() + || node->IsFunction() + || node->IsNumberObject() + || node->IsRegExp() + || node->IsStringObject() + ) { + continue; + } + + v8::Local nodeObj = node->ToObject(); + v8::Local checkValue = GetPrivate(nodeObj, Nan::New("NodeGitPromiseError").ToLocalChecked()); + + if (!checkValue.IsEmpty() && !checkValue->IsNull() && !checkValue->IsUndefined()) { + v8::Local argv[1] = { + checkValue->ToObject() + }; + callback->Call(1, argv, async_resource); + callbackFired = true; + break; + } + + v8::Local properties = nodeObj->GetPropertyNames(); + for (unsigned int propIndex = 0; propIndex < properties->Length(); ++propIndex) { + v8::Local propName = properties->Get(propIndex)->ToString(); + v8::Local nodeToQueue = nodeObj->Get(propName); + if (!nodeToQueue->IsUndefined()) { + workerArguments.push(nodeToQueue); + } + } + } + + if (!callbackFired) { + v8::Local err = Nan::Error("Method add has thrown an error.")->ToObject(); + err->Set(Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code)); + err->Set(Nan::New("errorFunction").ToLocalChecked(), Nan::New("Worktree.add").ToLocalChecked()); + v8::Local argv[1] = { + err + }; + callback->Call(1, argv, async_resource); + } + } else { + callback->Call(0, NULL, async_resource); + } + + } + + + delete baton; +} diff --git a/package-lock.json b/package-lock.json index c1d70a402..f3a607495 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@elastic/nodegit", - "version": "0.25.0-alpha.9", + "version": "0.25.0-alpha.13", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/test/tests/worktree.js b/test/tests/worktree.js new file mode 100644 index 000000000..86dc12b88 --- /dev/null +++ b/test/tests/worktree.js @@ -0,0 +1,49 @@ +var path = require("path"); +var assert = require("assert"); +var fse = require("fs-extra"); +var local = path.join.bind(path, __dirname); + +describe("Worktree", function() { + var NodeGit = require("../../"); + var Repository = NodeGit.Repository; + var Worktree = NodeGit.Worktree; + var Clone = NodeGit.Clone; + + var clonePath = local("../repos/clone"); + var worktreePath = local("../repos/worktree"); + + // Set a reasonable timeout here now that our repository has grown. + this.timeout(30000); + + before(function() { + var test = this; + var url = "https://github.com/nodegit/test.git"; + var opts = { + fetchOpts: { + callbacks: { + certificateCheck: () => 0 + } + } + }; + + return Clone(url, clonePath, opts).then(function(repo) { + assert.ok(repo instanceof Repository); + test.repository = repo; + }); + }); + + after(function() { + return fse.remove(clonePath).catch(function(err) { + console.log(err); + + throw err; + }); + }); + + it("can create worktree", function() { + return Worktree.add(this.repository, "workspace", worktreePath, {}) + .then(function(wt) { + assert.ok(wt instanceof Worktree); + }); + }); +}); From 9de1a3e74924b0f041752dcc8bf9ff4655dca2e0 Mon Sep 17 00:00:00 2001 From: Mengwei Ding Date: Mon, 29 Apr 2019 12:33:00 +0800 Subject: [PATCH 2/3] Revert "Fix binary info's platform passing" This reverts commit 918a517ab6ee2ffe3b84bf97b7cf6b036b0b43a9. --- lib/utils/binary_info.js | 1 - package.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/utils/binary_info.js b/lib/utils/binary_info.js index 4f20c4616..c0ccf60b0 100644 --- a/lib/utils/binary_info.js +++ b/lib/utils/binary_info.js @@ -7,7 +7,6 @@ function binary_info(platform, arch) { var package_json = JSON.parse( fs.readFileSync(path.resolve(__dirname,"../../package.json"), "utf8")); var options = { - platform, target_platform: platform, target_arch: arch }; diff --git a/package.json b/package.json index f9051f9e5..9d925cc32 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@elastic/nodegit", "description": "Node.js libgit2 asynchronous native bindings", - "version": "0.25.0-alpha.13", + "version": "0.25.0-alpha.12", "homepage": "http://github.com/elastic/nodegit", "keywords": [ "libgit2", From e2c3042a9df1d02999fa679331b3d04d4f1fc4ea Mon Sep 17 00:00:00 2001 From: Mengwei Ding Date: Mon, 29 Apr 2019 13:34:51 +0800 Subject: [PATCH 3/3] add open worktree test --- .../templates/manual/worktree/worktree_add.cc | 12 +++++++----- package-lock.json | 2 +- package.json | 2 +- test/tests/worktree.js | 16 +++++++--------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/generate/templates/manual/worktree/worktree_add.cc b/generate/templates/manual/worktree/worktree_add.cc index 8277b06f5..203fa73ec 100644 --- a/generate/templates/manual/worktree/worktree_add.cc +++ b/generate/templates/manual/worktree/worktree_add.cc @@ -59,10 +59,11 @@ from_repo = Nan::ObjectWrap::Unwrap(info[0]->ToObject())->GetValu // end convert_from_v8 block baton->path = from_path; // start convert_from_v8 block - // Create a git_worktree_add_options with the default value - const git_worktree_add_options from_opts = {1, 0, NULL}; + // Create a NULL git_worktree_add_options so that libgit2 will + // use a default options. + const git_worktree_add_options* from_opts = NULL; // end convert_from_v8 block - baton->opts = &from_opts; + baton->opts = from_opts; Nan::Callback *callback = new Nan::Callback(v8::Local::Cast(info[4])); AddWorker *worker = new AddWorker(baton, callback); @@ -73,8 +74,9 @@ from_repo = Nan::ObjectWrap::Unwrap(info[0]->ToObject())->GetValu worker->SaveToPersistent("name", info[1]->ToObject()); if (!info[2]->IsUndefined() && !info[2]->IsNull()) worker->SaveToPersistent("path", info[2]->ToObject()); - if (!info[3]->IsUndefined() && !info[3]->IsNull()) - worker->SaveToPersistent("opts", info[3]->ToObject()); + // Completely ignore info[3]. + // if (!info[3]->IsUndefined() && !info[3]->IsNull()) + // worker->SaveToPersistent("opts", info[3]->ToObject()); AsyncLibgit2QueueWorker(worker); return; diff --git a/package-lock.json b/package-lock.json index f3a607495..dad55a67a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@elastic/nodegit", - "version": "0.25.0-alpha.13", + "version": "0.25.0-alpha.14", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 9d925cc32..d92f1477a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@elastic/nodegit", "description": "Node.js libgit2 asynchronous native bindings", - "version": "0.25.0-alpha.12", + "version": "0.25.0-alpha.14", "homepage": "http://github.com/elastic/nodegit", "keywords": [ "libgit2", diff --git a/test/tests/worktree.js b/test/tests/worktree.js index 86dc12b88..ecf4c4fb2 100644 --- a/test/tests/worktree.js +++ b/test/tests/worktree.js @@ -1,6 +1,5 @@ var path = require("path"); var assert = require("assert"); -var fse = require("fs-extra"); var local = path.join.bind(path, __dirname); describe("Worktree", function() { @@ -32,18 +31,17 @@ describe("Worktree", function() { }); }); - after(function() { - return fse.remove(clonePath).catch(function(err) { - console.log(err); - - throw err; - }); - }); - it("can create worktree", function() { return Worktree.add(this.repository, "workspace", worktreePath, {}) .then(function(wt) { assert.ok(wt instanceof Worktree); }); }); + + it("can open a worktree repository", function() { + return Repository.open(worktreePath).then(function(repo) { + assert.ok(repo instanceof Repository); + assert.ok(repo.isWorktree()); + }); + }); });