diff --git a/generate/input/descriptor.json b/generate/input/descriptor.json index bf0efcd0a..af15fb511 100644 --- a/generate/input/descriptor.json +++ b/generate/input/descriptor.json @@ -1448,6 +1448,13 @@ "diff_format_email_options": { "ignore": true }, + "diff_line": { + "dependencies": [ + "../include/functions/free.h" + ], + "selfFreeing": true, + "freeFunctionName": "git_diff_line_free" + }, "diff_perfdata": { "selfFreeing": true, "cDependencies": [ @@ -1874,11 +1881,19 @@ "git_index_free": { "ignore": true }, + "git_index_get_byindex": { + "return": { + "ownedByThis": true + } + }, "git_index_get_bypath": { "args": { "stage": { "isOptional": true } + }, + "return": { + "ownedByThis": true } }, "git_index_new": { @@ -2027,6 +2042,12 @@ } }, "index_entry": { + "dependencies": [ + "../include/functions/copy.h", + "../include/functions/free.h" + ], + "freeFunctionName": "git_index_entry_free", + "dupFunction": "git_index_entry_dup", "isReturnable": true, "hasConstructor": true, "ignoreInit": true diff --git a/generate/templates/manual/commit/extract_signature.cc b/generate/templates/manual/commit/extract_signature.cc index b42e8f188..05029b801 100644 --- a/generate/templates/manual/commit/extract_signature.cc +++ b/generate/templates/manual/commit/extract_signature.cc @@ -28,7 +28,9 @@ NAN_METHOD(GitCommit::ExtractSignature) if (info[1]->IsString()) { Nan::Utf8String oidString(Nan::To(info[1]).ToLocalChecked()); baton->commit_id = (git_oid *)malloc(sizeof(git_oid)); - if (git_oid_fromstr(baton->commit_id, (const char *)strdup(*oidString)) != GIT_OK) { + baton->commit_idNeedsFree = true; + string str = string(*oidString); + if (git_oid_fromstr(baton->commit_id, str.c_str()) != GIT_OK) { free(baton->commit_id); if (git_error_last()) { @@ -39,6 +41,7 @@ NAN_METHOD(GitCommit::ExtractSignature) } } else { baton->commit_id = Nan::ObjectWrap::Unwrap(Nan::To(info[1]).ToLocalChecked())->GetValue(); + baton->commit_idNeedsFree = false; } // baton->field @@ -96,6 +99,10 @@ void GitCommit::ExtractSignatureWorker::HandleErrorCallback() { git_buf_dispose(&baton->signature); git_buf_dispose(&baton->signed_data); + if (baton->commit_idNeedsFree) { + free(baton->commit_id); + } + free(baton->field); delete baton; @@ -154,9 +161,11 @@ void GitCommit::ExtractSignatureWorker::HandleOKCallback() git_buf_dispose(&baton->signature); git_buf_dispose(&baton->signed_data); - if (baton->field != NULL) { - free((void *)baton->field); + if (baton->commit_idNeedsFree) { + free(baton->commit_id); } + free(baton->field); + delete baton; } diff --git a/generate/templates/manual/include/cleanup_handle.h b/generate/templates/manual/include/cleanup_handle.h index 5eca8cf70..0dd00eb88 100644 --- a/generate/templates/manual/include/cleanup_handle.h +++ b/generate/templates/manual/include/cleanup_handle.h @@ -5,6 +5,12 @@ #include #include +extern "C" { + #include + #include +} + + namespace nodegit { class CleanupHandle { public: @@ -14,6 +20,12 @@ namespace nodegit { class FilterRegistryCleanupHandles : public CleanupHandle { public: + ~FilterRegistryCleanupHandles() { + for(std::map>::iterator iter = registeredFilters.begin(); iter != registeredFilters.end(); ++iter) { + std::string filtername = iter->first; + git_filter_unregister(filtername.c_str()); + } + } std::map> registeredFilters; }; } diff --git a/generate/templates/manual/include/functions/copy.h b/generate/templates/manual/include/functions/copy.h index 9983e575a..75818bb00 100644 --- a/generate/templates/manual/include/functions/copy.h +++ b/generate/templates/manual/include/functions/copy.h @@ -9,7 +9,6 @@ const git_error *git_error_dup(const git_error *arg); const git_oid *git_oid_dup(const git_oid *arg); -const git_index_entry *git_index_entry_dup(const git_index_entry *arg); const git_index_time *git_index_time_dup(const git_index_time *arg); const git_time *git_time_dup(const git_time *arg); const git_diff_delta *git_diff_delta_dup(const git_diff_delta *arg); @@ -19,5 +18,6 @@ git_remote_head *git_remote_head_dup(const git_remote_head *src); void git_time_dup(git_time **out, const git_time *arg); void git_transfer_progress_dup(git_transfer_progress **out, const git_transfer_progress *arg); +void git_index_entry_dup(git_index_entry **dest, const git_index_entry *src); #endif diff --git a/generate/templates/manual/include/functions/free.h b/generate/templates/manual/include/functions/free.h index 873417b98..c7db4b7f6 100644 --- a/generate/templates/manual/include/functions/free.h +++ b/generate/templates/manual/include/functions/free.h @@ -8,5 +8,7 @@ #define NODEGIT_FREE_FUNCTIONS void git_remote_head_free(git_remote_head *remote_head); +void git_diff_line_free(const git_diff_line *diff_line); +void git_index_entry_free(const git_index_entry *index_entry); #endif diff --git a/generate/templates/manual/patches/convenient_patches.cc b/generate/templates/manual/patches/convenient_patches.cc index e183afb75..855789b32 100644 --- a/generate/templates/manual/patches/convenient_patches.cc +++ b/generate/templates/manual/patches/convenient_patches.cc @@ -156,6 +156,7 @@ void GitPatch::ConvenientFromDiffWorker::HandleOKCallback() { } delete baton->out; + delete baton; Local argv[2] = { Nan::Null(), @@ -185,8 +186,6 @@ void GitPatch::ConvenientFromDiffWorker::HandleOKCallback() { } free((void *)baton->error); - - return; } if (baton->error_code < 0) { @@ -197,9 +196,15 @@ void GitPatch::ConvenientFromDiffWorker::HandleOKCallback() { err }; callback->Call(1, argv, async_resource); - - return; } + while (!baton->out->empty()) { + PatchDataFree(baton->out->back()); + baton->out->pop_back(); + } + + delete baton->out; + + delete baton; Nan::Call(*callback, 0, NULL); } diff --git a/generate/templates/manual/revwalk/file_history_walk.cc b/generate/templates/manual/revwalk/file_history_walk.cc index 714d6f5db..ac25b8b3f 100644 --- a/generate/templates/manual/revwalk/file_history_walk.cc +++ b/generate/templates/manual/revwalk/file_history_walk.cc @@ -291,6 +291,8 @@ void GitRevwalk::FileHistoryWalkWorker::Execute() if (fileHistoryEvent->type != GIT_DELTA_UNMODIFIED) { baton->out->push_back(fileHistoryEvent); + } else { + delete fileHistoryEvent; } git_commit_free(currentCommit); @@ -470,6 +472,7 @@ void GitRevwalk::FileHistoryWalkWorker::HandleOKCallback() callback->Call(2, argv, async_resource); delete baton->out; + delete baton; return; } @@ -492,6 +495,7 @@ void GitRevwalk::FileHistoryWalkWorker::HandleOKCallback() } free((void *)baton->error); + delete baton; return; } @@ -503,6 +507,7 @@ void GitRevwalk::FileHistoryWalkWorker::HandleOKCallback() err }; callback->Call(1, argv, async_resource); + delete baton; return; } diff --git a/generate/templates/manual/src/convenient_patch.cc b/generate/templates/manual/src/convenient_patch.cc index f60f53257..d31853b9b 100644 --- a/generate/templates/manual/src/convenient_patch.cc +++ b/generate/templates/manual/src/convenient_patch.cc @@ -27,8 +27,10 @@ void PatchDataFree(PatchData *patch) { free((void *)line->content); free((void *)line); } + delete hunk->lines; delete hunk; } + delete patch->hunks; delete patch; } diff --git a/generate/templates/manual/src/functions/copy.cc b/generate/templates/manual/src/functions/copy.cc index 90327650b..820122d34 100644 --- a/generate/templates/manual/src/functions/copy.cc +++ b/generate/templates/manual/src/functions/copy.cc @@ -4,6 +4,8 @@ #include "git2.h" #include "git2/diff.h" +#include + const git_error *git_error_dup(const git_error *arg) { git_error *result = (git_error *)malloc(sizeof(git_error)); result->klass = arg->klass; @@ -35,3 +37,11 @@ git_remote_head *git_remote_head_dup(const git_remote_head *src) { : NULL; return dest; } + +void git_index_entry_dup(git_index_entry **dest, const git_index_entry *src) { + *dest = (git_index_entry *)malloc(sizeof(git_index_entry)); + memcpy(*dest, src, sizeof(git_index_entry)); + (*dest)->path = src->path + ? strdup(src->path) + : NULL; +} diff --git a/generate/templates/manual/src/functions/free.cc b/generate/templates/manual/src/functions/free.cc index a52a7016f..318cd61d6 100644 --- a/generate/templates/manual/src/functions/free.cc +++ b/generate/templates/manual/src/functions/free.cc @@ -1,9 +1,20 @@ #include #include "git2.h" +#include void git_remote_head_free(git_remote_head *remote_head) { free(remote_head->name); free(remote_head->symref_target); free(remote_head); } + +void git_diff_line_free(const git_diff_line *diff_line) { + free((void*)(diff_line->content)); + free((void*) diff_line); +} + +void git_index_entry_free(const git_index_entry *index_entry) { + free((void*)(index_entry->path)); + free((void*) index_entry); +} diff --git a/generate/templates/manual/src/str_array_converter.cc b/generate/templates/manual/src/str_array_converter.cc index 732f16cf2..eab9a9063 100644 --- a/generate/templates/manual/src/str_array_converter.cc +++ b/generate/templates/manual/src/str_array_converter.cc @@ -25,11 +25,9 @@ git_strarray *StrArrayConverter::Convert(v8::Local val) { } git_strarray * StrArrayConverter::AllocStrArray(const size_t count) { - const size_t size = sizeof(git_strarray) + (sizeof(char*) * count); - uint8_t* memory = reinterpret_cast(malloc(size)); - git_strarray *result = reinterpret_cast(memory); + git_strarray *result = (git_strarray *)malloc(sizeof(git_strarray)); + result->strings = (char **)malloc(sizeof(char*) * count); result->count = count; - result->strings = reinterpret_cast(memory + sizeof(git_strarray)); return result; } diff --git a/generate/templates/partials/async_function.cc b/generate/templates/partials/async_function.cc index 6041c16f3..9a03b35d0 100644 --- a/generate/templates/partials/async_function.cc +++ b/generate/templates/partials/async_function.cc @@ -64,7 +64,9 @@ NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) { ); if (!conversionResult.result) { - delete[] baton->{{ arg.name }}; + // TODO free previously allocated memory + free(baton->{{ arg.name }}); + delete baton; return Nan::ThrowError(Nan::New(conversionResult.error).ToLocalChecked()); } @@ -77,6 +79,7 @@ NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) { { auto conversionResult = Configurable{{ arg.cppClassName }}::fromJavascript(nodegitContext, info[{{ arg.jsArg }}]); if (!conversionResult.result) { + delete baton; return Nan::ThrowError(Nan::New(conversionResult.error).ToLocalChecked()); } @@ -178,6 +181,36 @@ void {{ cppClassName }}::{{ cppFunctionName }}Worker::Execute() { baton->result = result; {%endif%} + + {%each args|argsInfo as arg %} + {%if not arg.isSelf %} + {%if not arg.payloadFor %} + {%if not arg.isReturn %} + {%if arg.cppClassName == 'GitStrarray' %} + {{ arg.freeFunctionName }}((git_strarray*)baton->{{ arg.name }}); + free((void*)baton->{{ arg.name }}); + {%elsif arg.cppClassName == 'Array' %} + free((void*)baton->{{ arg.name }}); + {%elsif not arg.isCallbackFunction %} + {%if not arg.isStructType %} + {%if not arg.isStructType %} + {%if not arg.isPayload %} + {%if arg.name %} + {%if arg.cppClassName == 'String'%} + free((void*)baton->{{ arg.name }}); + {%endif%} + {%if arg.cppClassName == 'Wrapper'%} + free((void*)baton->{{ arg.name }}); + {%endif%} + {%endif%} + {%endif%} + {%endif%} + {%endif%} + {%endif%} + {%endif%} + {%endif%} + {%endif%} + {%endeach%} } void {{ cppClassName }}::{{ cppFunctionName }}Worker::HandleErrorCallback() { @@ -201,6 +234,17 @@ void {{ cppClassName }}::{{ cppFunctionName }}Worker::HandleErrorCallback() { {%each args|argsInfo as arg %} {%if arg.shouldAlloc %} {%if not arg.isCppClassStringOrArray %} + {%if arg.cppClassName == "GitBuf" %} + {%else%} + {%if arg | isOid %} + if (baton->{{ arg.name}}NeedsFree) { + baton->{{ arg.name}}NeedsFree = false; + free((void*)baton->{{ arg.name }}); + } + {%else%} + free((void*)baton->{{ arg.name }}); + {%endif%} + {%endif%} {%elsif arg | isOid %} if (baton->{{ arg.name}}NeedsFree) { baton->{{ arg.name}}NeedsFree = false; @@ -273,6 +317,33 @@ void {{ cppClassName }}::{{ cppFunctionName }}Worker::HandleOKCallback() { Nan::Set(result, Nan::New("{{ _return.returnNameOrName }}").ToLocalChecked(), v8ConversionSlot); {%endif%} {%endeach%} + + {%each args|argsInfo as arg %} + {%if arg.shouldAlloc|and arg.isReturn|and arg.cppClassName == 'Array' %} + {%if arg.cType == 'git_strarray *' %} + // We need to free the strarray + {{ arg.freeFunctionName }}(baton->{{ arg.name }}); + free((void *)baton->{{ arg.name }}); + {%endif%} + {%endif%} + {%if not arg.shouldAlloc %} + {%if arg.ownedByThis|and arg.dupFunction|and arg.freeFunctionName|and arg.isReturn|and arg.selfFreeing %} + // We need to free duplicated memory we are responsible for that we obtained from libgit2 because + // nodegit duplicates it again when calling the wrapper + if(baton->{{ arg.name }} != NULL) { + {{ arg.freeFunctionName }}(baton->{{ arg.name }}); + } + {%endif%} + {%elsif arg.isReturn %} + {%if not arg.selfFreeing %} + {%if arg.cppClassName == "GitBuf" %} + {%else%} + free((void *)baton->{{ arg.name }}); + {%endif%} + {%endif%} + {%endif%} + {%endeach%} + {%if .|returnsCount == 1 %} v8::Local result = v8ConversionSlot; {%endif%} @@ -346,6 +417,13 @@ void {{ cppClassName }}::{{ cppFunctionName }}Worker::HandleOKCallback() { {%each args|argsInfo as arg %} {%if arg.shouldAlloc %} {%if not arg.isCppClassStringOrArray %} + {%if arg.cppClassName == "GitBuf" %} + {%else%} + {%if arg | isOid %} + {%else%} + free((void*)baton->{{ arg.name }}); + {%endif%} + {%endif%} {%elsif arg | isOid %} if (baton->{{ arg.name}}NeedsFree) { baton->{{ arg.name}}NeedsFree = false; @@ -368,10 +446,6 @@ void {{ cppClassName }}::{{ cppFunctionName }}Worker::HandleOKCallback() { {%each args|argsInfo as arg %} {%if arg.isCppClassStringOrArray %} - {%if arg.freeFunctionName %} - {%elsif not arg.isConst%} - free((void *)baton->{{ arg.name }}); - {%endif%} {%elsif arg | isOid %} if (baton->{{ arg.name}}NeedsFree) { baton->{{ arg.name}}NeedsFree = false; diff --git a/generate/templates/partials/convert_from_v8.cc b/generate/templates/partials/convert_from_v8.cc index 8b928e7f4..29db4bd07 100644 --- a/generate/templates/partials/convert_from_v8.cc +++ b/generate/templates/partials/convert_from_v8.cc @@ -14,9 +14,9 @@ {% elsif cppClassName == 'GitBuf' %} {%-- Print nothing --%} {%else%} - if ((info.Length() - 1) > {{ jsArg }} && info[{{ jsArg }}]->Is{{ cppClassName|cppToV8 }}()) { - {%endif%} + if ((info.Length() - 1) > {{ jsArg }} && info[{{ jsArg }}]->Is{{ cppClassName|cppToV8 }}()) { {%endif%} + {%endif%} {%if cppClassName == 'String'%} Nan::Utf8String {{ name }}(Nan::To(info[{{ jsArg }}]).ToLocalChecked()); @@ -58,8 +58,8 @@ if (arrayVal->IsString()) { // Try and parse in a string to a git_oid Nan::Utf8String oidString(Nan::To(arrayVal).ToLocalChecked()); - - if (git_oid_fromstr(&from_{{ name }}[i], (const char *) strdup(*oidString)) != GIT_OK) { + string str = string(*oidString); + if (git_oid_fromstr(&from_{{ name }}[i], str.c_str()) != GIT_OK) { if (git_error_last()) { return Nan::ThrowError(git_error_last()->message); } else { @@ -90,8 +90,8 @@ // Try and parse in a string to a git_oid Nan::Utf8String oidString(Nan::To(info[{{ jsArg }}]).ToLocalChecked()); git_oid *oidOut = (git_oid *)malloc(sizeof(git_oid)); - - if (git_oid_fromstr(oidOut, (const char *) strdup(*oidString)) != GIT_OK) { + string str = string(*oidString); + if (git_oid_fromstr(oidOut, str.c_str()) != GIT_OK) { free(oidOut); if (git_error_last()) { diff --git a/generate/templates/partials/field_accessors.cc b/generate/templates/partials/field_accessors.cc index bcd5e5f87..c0f6c5674 100644 --- a/generate/templates/partials/field_accessors.cc +++ b/generate/templates/partials/field_accessors.cc @@ -55,6 +55,7 @@ {% elsif field.cppClassName == 'String' %} if (wrapper->GetValue()->{{ field.name }}) { + free((void*)wrapper->GetValue()->{{ field.name }}); } Nan::Utf8String str(value); diff --git a/generate/templates/partials/sync_function.cc b/generate/templates/partials/sync_function.cc index 8868bb5ca..4429f57c5 100644 --- a/generate/templates/partials/sync_function.cc +++ b/generate/templates/partials/sync_function.cc @@ -92,12 +92,53 @@ NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) { } // lock master scope end {%endif%} + {%each args|argsInfo as arg %} + {%if not arg.isSelf %} + {%if not arg.payloadFor %} + {%if not arg.isReturn %} + {%if arg.cppClassName == 'GitStrarray' %} + {{ arg.freeFunctionName }}((git_strarray*)from_{{ arg.name }}); + free((void*)from_{{ arg.name }}); + {%elsif arg.cppClassName == 'Array' %} + free((void*)from_{{ arg.name }}); + {%endif%} + {%endif%} + {%endif%} + {%endif%} + {%endeach%} + + {%each args|argsInfo as arg %} + {%if arg.shouldAlloc|and arg.isReturn|and arg.cppClassName == 'Array' %} + {%if arg.cType == 'git_strarray *' %} + // We need to free the strarray + {{ arg.freeFunctionName }}(from_{{ arg.name }}); + free((void *)from_{{ arg.name }}); + {%endif%} + {%endif%} + {%if arg.shouldAlloc|and arg.isReturn %} + {%if not arg.selfFreeing %} + {%if arg.cppClassName == "GitBuf" %} + {%else%} + free((void *)from_{{ arg.name }}); + {%endif%} + {%endif%} + {%endif%} + {%endeach%} {%each args|argsInfo as arg %} {%if arg | isOid %} - if (info[{{ arg.jsArg }}]->IsString()) { - free((void *)from_{{ arg.name }}); - } + if (info[{{ arg.jsArg }}]->IsString()) { + free((void *)from_{{ arg.name }}); + } + {%else%} + {%if not arg.isReturn %} + {%if arg.cppClassName == 'String'%} + free((void *)from_{{ arg.name }}); + {%endif%} + {%if arg.cppClassName == 'Wrapper'%} + free((void *)from_{{ arg.name }}); + {%endif%} + {%endif%} {%endif%} {%endeach%}