Skip to content

Commit

Permalink
Add manual template for git_commit_extract_signature
Browse files Browse the repository at this point in the history
This is to date the only known (by the nodegit team) use case of a double return type from libgit2. If we spot other use cases for this, we will need to revisit this decision and build in the correct templating mechanism.
  • Loading branch information
implausible committed Mar 16, 2018
1 parent 60ffb34 commit 716ea86
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 1 deletion.
2 changes: 1 addition & 1 deletion generate/input/descriptor.json
Expand Up @@ -523,7 +523,7 @@
"ignore": true
},
"git_commit_extract_signature": {
"ignore": true
"isAsync": true
},
"git_commit_id": {
"return": {
Expand Down
34 changes: 34 additions & 0 deletions generate/input/libgit2-supplement.json
Expand Up @@ -86,6 +86,40 @@
},
"new" : {
"functions": {
"git_commit_extract_signature": {
"args": [
{
"name": "signature",
"type": "git_buf"
},
{
"name": "signed_data",
"type": "git_buf"
},
{
"name": "repo",
"type": "git_repository *"
},
{
"name": "commit_id",
"type": "git_oid *"
},
{
"name": "field",
"type": "char *"
}
],
"type": "function",
"isManual": true,
"cFile": "generate/templates/manual/commit/extract_signature.cc",
"isAsync": true,
"isPrototypeMethod": false,
"group": "commit",
"return": {
"type": "int",
"isErrorCode": true
}
},
"git_patch_convenient_from_diff": {
"args": [
{
Expand Down
156 changes: 156 additions & 0 deletions generate/templates/manual/commit/extract_signature.cc
@@ -0,0 +1,156 @@
NAN_METHOD(GitCommit::ExtractSignature)
{
if (info.Length() == 0 || !info[0]->IsObject()) {
return Nan::ThrowError("Repository repo is required.");
}

if (info.Length() == 1 || (!info[1]->IsObject() && !info[1]->IsString())) {
return Nan::ThrowError("Oid commit_id is required.");
}

if (info.Length() == 2 || (info.Length() == 3 && !info[2]->IsFunction())) {
return Nan::ThrowError("Callback is required and must be a Function.");
}

if (info.Length() >= 4) {
if (!info[2]->IsString() && !info[2]->IsUndefined() && !info[2]->IsNull()) {
return Nan::ThrowError("String signature_field must be a string or undefined/null.");
}

if (!info[3]->IsFunction()) {
return Nan::ThrowError("Callback is required and must be a Function.");
}
}

ExtractSignatureBaton* baton = new ExtractSignatureBaton;

baton->error_code = GIT_OK;
baton->error = NULL;
baton->signature = GIT_BUF_INIT_CONST(NULL, 0);
baton->signed_data = GIT_BUF_INIT_CONST(NULL, 0);
baton->repo = Nan::ObjectWrap::Unwrap<GitRepository>(info[0]->ToObject())->GetValue();

// baton->commit_id
if (info[1]->IsString()) {
String::Utf8Value oidString(info[1]->ToString());
baton->commit_id = (git_oid *)malloc(sizeof(git_oid));
if (git_oid_fromstr(baton->commit_id, (const char *)strdup(*oidString)) != GIT_OK) {
free(baton->commit_id);

if (giterr_last()) {
return Nan::ThrowError(giterr_last()->message);
} else {
return Nan::ThrowError("Unknown Error");
}
}
} else {
baton->commit_id = Nan::ObjectWrap::Unwrap<GitOid>(info[1]->ToObject())->GetValue();
}

// baton->field
if (info[2]->IsString()) {
String::Utf8Value field(info[2]->ToString());
baton->field = (char *)malloc(field.length() + 1);
memcpy((void *)baton->field, *field, field.length());
baton->field[field.length()] = 0;
} else {
baton->field = NULL;
}

Nan::Callback *callback;
if (info[2]->IsFunction()) {
callback = new Nan::Callback(Local<Function>::Cast(info[2]));
} else {
callback = new Nan::Callback(Local<Function>::Cast(info[3]));
}

ExtractSignatureWorker *worker = new ExtractSignatureWorker(baton, callback);
worker->SaveToPersistent("repo", info[0]->ToObject());
worker->SaveToPersistent("commit_id", info[1]->ToObject());
Nan::AsyncQueueWorker(worker);
return;
}

void GitCommit::ExtractSignatureWorker::Execute()
{
giterr_clear();

{
LockMaster lockMaster(
/*asyncAction: */true,
baton->repo
);

baton->error_code = git_commit_extract_signature(
&baton->signature,
&baton->signed_data,
baton->repo,
baton->commit_id,
(const char *)baton->field
);

if (baton->error_code != GIT_OK && giterr_last() != NULL) {
baton->error = git_error_dup(giterr_last());
}
}
}

void GitCommit::ExtractSignatureWorker::HandleOKCallback()
{
if (baton->error_code == GIT_OK)
{
Local<v8::Object> result = Nan::New<Object>();
Nan::Set(
result,
Nan::New("signature").ToLocalChecked(),
Nan::New<String>(baton->signature.ptr, baton->signature.size).ToLocalChecked()
);
Nan::Set(
result,
Nan::New("signedData").ToLocalChecked(),
Nan::New<String>(baton->signed_data.ptr, baton->signed_data.size).ToLocalChecked()
);

Local<v8::Value> argv[2] = {
Nan::Null(),
result
};
callback->Call(2, argv);
}
else if (baton->error)
{
Local<v8::Value> argv[1] = {
Nan::Error(baton->error->message)
};
callback->Call(1, argv);
if (baton->error->message)
{
free((void *)baton->error->message);
}

free((void *)baton->error);
}
else if (baton->error_code < 0)
{
Local<v8::Object> err = Nan::Error("Extract Signature has thrown an error.")->ToObject();
err->Set(Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
err->Set(Nan::New("errorFunction").ToLocalChecked(), Nan::New("Commit.extractSignature").ToLocalChecked());
Local<v8::Value> argv[1] = {
err
};
callback->Call(1, argv);
}
else
{
callback->Call(0, NULL);
}

git_buf_free(&baton->signature);
git_buf_free(&baton->signed_data);

if (baton->field != NULL) {
free((void *)baton->field);
}

delete baton;
}

0 comments on commit 716ea86

Please sign in to comment.