diff --git a/.gitignore b/.gitignore index 099191756..621086ef2 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,5 @@ /include/* !/include/functions/copy.h !/include/wrapper.h + +*.log diff --git a/README.md b/README.md index c2e03d931..6daa45d42 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,8 @@ git clone git://github.com/tbranyen/nodegit.git # Enter the repository. cd nodegit -# Install the template engine, run the code generation script, and install. -npm install ejs && npm run codegen && npm install +# Installs the template engine, run the code generation script, and build. +npm install ``` If you encounter errors, you most likely have not configured the dependencies @@ -93,35 +93,19 @@ npm install nodegit --msvs_version=2013 ### Cloning a repository and reading a file: ### ``` javascript -var clone = require("nodegit").Repo.clone; +var clone = require("nodegit").Repository.clone; // Clone a given repository into a specific folder. -clone("https://github.com/nodegit/nodegit", "tmp", null, function(err, repo) { - if (err) { - throw err; - } - +clone("https://github.com/nodegit/nodegit", "tmp", null).then(function(repo) { // Use a known commit sha from this repository. var sha = "59b20b8d5c6ff8d09518454d4dd8b7b30f095ab5"; // Look up this known commit. - repo.getCommit(sha, function(err, commit) { - if (err) { - throw err; - } - + repo.getCommit(sha).then(function(commit) { // Look up a specific file within that commit. - commit.getEntry("README.md", function(err, entry) { - if (err) { - throw err; - } - + commit.getEntry("README.md").then(function(entry) { // Get the blob contents from the file. - entry.getBlob(function(err, blob) { - if (err) { - throw err; - } - + entry.getBlob().then(function(blob) { // Show the name, sha, and filesize in byes. console.log(entry.name() + entry.sha() + blob.size() + "b"); @@ -139,20 +123,12 @@ clone("https://github.com/nodegit/nodegit", "tmp", null, function(err, repo) { ### Emulating git log: ### ``` javascript -var open = require("nodegit").Repo.open; +var open = require("nodegit").Repository.open; // Open the repository directory. -open("tmp", function(err, repo) { - if (err) { - throw err; - } - +open("tmp").then(function(repo) { // Open the master branch. - repo.getMaster(function(err, branch) { - if (err) { - throw err; - } - + repo.getMaster().then(function(branch) { // Create a new history event emitter. var history = branch.history(); diff --git a/generate/filters/and.js b/generate/filters/and.js new file mode 100644 index 000000000..042631623 --- /dev/null +++ b/generate/filters/and.js @@ -0,0 +1,3 @@ +module.exports = function(value, other) { + return value && other; +}; diff --git a/generate/filters/args_info.js b/generate/filters/args_info.js new file mode 100644 index 000000000..b2fb1aa5b --- /dev/null +++ b/generate/filters/args_info.js @@ -0,0 +1,30 @@ +module.exports = function(args) { + var result = [], + cArg, + jsArg; + + for(cArg = 0, jsArg = 0; cArg < args.length; cArg++) { + var arg = args[cArg]; + + if (!arg.isReturn && !arg.isSelf && !arg.isPayload) { + arg.isJsArg = true; + arg.jsArg = jsArg; + + jsArg++; + } + + if (cArg === args.length -1) { + arg.lastArg = true; + } + else { + arg.lastArg = false; + } + + arg.cArg = cArg; + arg.isCppClassStringOrArray = ~["String", "Array"].indexOf(arg.cppClassName); + + result.push(arg); + } + + return result; +}; diff --git a/generate/filters/cpp_to_v8.js b/generate/filters/cpp_to_v8.js new file mode 100644 index 000000000..dcf017a4f --- /dev/null +++ b/generate/filters/cpp_to_v8.js @@ -0,0 +1,5 @@ +var isV8Value = require("./is_v8_value"); + +module.exports = function(cppClassName) { + return isV8Value(cppClassName) ? cppClassName : "Object"; +}; diff --git a/generate/filters/default_value.js b/generate/filters/default_value.js new file mode 100644 index 000000000..42682549e --- /dev/null +++ b/generate/filters/default_value.js @@ -0,0 +1,3 @@ +module.exports = function(cType) { + return cType === "git_otype" ? "GIT_OBJ_ANY" : "0"; +}; diff --git a/generate/filters/fields_info.js b/generate/filters/fields_info.js new file mode 100644 index 000000000..8ec8a930b --- /dev/null +++ b/generate/filters/fields_info.js @@ -0,0 +1,17 @@ +module.exports = function(fields) { + var result = []; + + fields.forEach(function (field){ + var fieldInfo = {}; + + fieldInfo.__proto__ = field; + + fieldInfo.parsedName = field.name || "result"; + fieldInfo.isCppClassIntType = ~["Uint32", "Int32"].indexOf(field.cppClassName); + fieldInfo.parsedClassName = (field.cppClassName || '').toLowerCase() + "_t"; + + result.push(fieldInfo); + }); + + return result; +}; diff --git a/generate/filters/has_return_type.js b/generate/filters/has_return_type.js new file mode 100644 index 000000000..2d21a0e66 --- /dev/null +++ b/generate/filters/has_return_type.js @@ -0,0 +1,7 @@ +module.exports = function(functionInfo) { + if (functionInfo.return) { + return functionInfo.return.cType != "void" || functionInfo.return.isErrorCode; + } + + return false; +}; diff --git a/generate/filters/has_returns.js b/generate/filters/has_returns.js new file mode 100644 index 000000000..733bfe6a3 --- /dev/null +++ b/generate/filters/has_returns.js @@ -0,0 +1,15 @@ +module.exports = function(fn) { + var args = fn.args || []; + var result = args.some(function (arg) { + return arg.isReturn; + }); + + if (!result + && fn.return + && !fn.return.isErrorCode + && fn.return.cType != "void") { + result = true; + } + + return result || (fn.return && fn.return.isErrorCode); +}; diff --git a/generate/filters/is_double_pointer.js b/generate/filters/is_double_pointer.js new file mode 100644 index 000000000..9d1246ab4 --- /dev/null +++ b/generate/filters/is_double_pointer.js @@ -0,0 +1,3 @@ +module.exports = function(cType) { + return /\s*\*\*\s*/.test(cType); +}; diff --git a/generate/filters/is_pointer.js b/generate/filters/is_pointer.js new file mode 100644 index 000000000..a5dbb053e --- /dev/null +++ b/generate/filters/is_pointer.js @@ -0,0 +1,3 @@ +module.exports = function(cType) { + return /\s*\*\s*/.test(cType); +}; diff --git a/generate/filters/is_v8_value.js b/generate/filters/is_v8_value.js new file mode 100644 index 000000000..f773ff6a2 --- /dev/null +++ b/generate/filters/is_v8_value.js @@ -0,0 +1,14 @@ +var v8 = [ + "Boolean", + "Number", + "String", + "Integer", + "Int32", + "Uint32", + "Date", + "Function" +]; + +module.exports = function(cppClassName) { + return v8.indexOf(cppClassName) > -1; +}; diff --git a/generate/filters/js_args_count.js b/generate/filters/js_args_count.js new file mode 100644 index 000000000..5be437f41 --- /dev/null +++ b/generate/filters/js_args_count.js @@ -0,0 +1,18 @@ +module.exports = function(args) { + var cArg, + jsArg; + + if (!args) { + return 0; + } + + for(cArg = 0, jsArg = 0; cArg < args.length; cArg++) { + var arg = args[cArg]; + + if (!arg.isReturn && !arg.isSelf && !arg.isPayload) { + jsArg++; + } + } + + return jsArg; +}; diff --git a/generate/filters/or.js b/generate/filters/or.js new file mode 100644 index 000000000..fe02c2a87 --- /dev/null +++ b/generate/filters/or.js @@ -0,0 +1,3 @@ +module.exports = function(value, other) { + return value || other; +}; diff --git a/generate/filters/replace.js b/generate/filters/replace.js new file mode 100644 index 000000000..15ed9c71f --- /dev/null +++ b/generate/filters/replace.js @@ -0,0 +1,3 @@ +module.exports = function(value, find, replace) { + return value.replace(find, replace); +}; diff --git a/generate/filters/returns_count.js b/generate/filters/returns_count.js new file mode 100644 index 000000000..9ba92aec4 --- /dev/null +++ b/generate/filters/returns_count.js @@ -0,0 +1,15 @@ +module.exports = function(fn) { + var args = fn.args || []; + var result = args.reduce(function (currentValue, arg) { + return currentValue + (arg.isReturn ? 1 : 0); + }, 0); + + if (!result + && fn.return + && !fn.return.isErrorCode + && fn.return.cType != "void") { + result = 1; + } + + return result; +}; diff --git a/generate/filters/returns_info.js b/generate/filters/returns_info.js new file mode 100644 index 000000000..7279d5ff1 --- /dev/null +++ b/generate/filters/returns_info.js @@ -0,0 +1,40 @@ +module.exports = function(fn, argReturnsOnly, isAsync) { + var result = []; + var args = fn.args || []; + + args.forEach(function (arg) { + if (!arg.isReturn) return; + + var return_info = {}; + + return_info.__proto__ = arg; + + return_info.parsedName = isAsync ? "baton->" + return_info.name : return_info.name; + return_info.isCppClassIntType = ~['Uint32', 'Int32'].indexOf(return_info.cppClassName); + return_info.parsedClassName = (return_info.cppClassName || '').toLowerCase() + "_t"; + return_info.jsNameOrName = return_info.jsName | return_info.name; + return_info.jsOrCppClassName = return_info.jsClassName || return_info.cppClassName; + + result.push(return_info); + }); + + if (!result.length + && !argReturnsOnly + && fn.return + && !fn.return.isErrorCode + && fn.return.cType != "void") { + var return_info = {}; + + return_info.__proto__ = fn.return; + return_info.parsedName = return_info.name && isAsync ? "baton->" + return_info.name : "result"; + return_info.isCppClassIntType = ~['Uint32', 'Int32'].indexOf(return_info.cppClassName); + return_info.parsedClassName = (return_info.cppClassName || '').toLowerCase() + "_t"; + return_info.jsNameOrName = return_info.jsName | return_info.name; + return_info.jsOrCppClassName = return_info.jsClassName || return_info.cppClassName; + + result.push(return_info); + } + + + return result; +}; diff --git a/generate/filters/un_pointer.js b/generate/filters/un_pointer.js new file mode 100644 index 000000000..99382f36f --- /dev/null +++ b/generate/filters/un_pointer.js @@ -0,0 +1,3 @@ +module.exports = function(cType) { + return cType.replace(/\s*\*\s*$/, ""); +}; diff --git a/generate/filters/upper.js b/generate/filters/upper.js new file mode 100644 index 000000000..bf0aa534b --- /dev/null +++ b/generate/filters/upper.js @@ -0,0 +1,3 @@ +module.exports = function(value) { + return value.toUpperCase(); +}; diff --git a/generate/index.js b/generate/index.js index 977078bda..3ab3b136f 100644 --- a/generate/index.js +++ b/generate/index.js @@ -1,44 +1,88 @@ -// https://github.com/nodegit/nodegit/issues/94 -const fs = require("fs"); -const ejs = require("ejs"); const path = require("path"); +const combyne = require("combyne"); +const file = require("./util/file"); const idefs = require("./idefs"); -var local = path.join.bind(null, __dirname); +// Customize the delimiters so as to not process `{{{` or `}}}`. +combyne.settings.delimiters = { + START_RAW: "{{=", + END_RAW: "=}}" +}; -var classTemplate = ejs.compile( - "" + fs.readFileSync(local("templates/class.cc.ejs")), { - filename: "class.cc" - }); +var partials = { + asyncFunction: file.read("partials/async_function.cc"), + convertFromV8: file.read("partials/convert_from_v8.cc"), + convertToV8: file.read("partials/convert_to_v8.cc"), + doc: file.read("partials/doc.cc"), + fields: file.read("partials/fields.cc"), + guardArguments: file.read("partials/guard_arguments.cc"), + syncFunction: file.read("partials/sync_function.cc") +}; + +var templates = { + class: file.read("templates/class.cc"), + header: file.read("templates/header.h"), + binding: file.read("templates/binding.gyp"), + nodegit: file.read("templates/nodegit.cc") +}; + +var filters = { + upper: require("./filters/upper"), + replace: require("./filters/replace"), + or: require("./filters/or"), + and: require("./filters/and"), + defaultValue: require("./filters/default_value"), + argsInfo: require("./filters/args_info"), + cppToV8: require("./filters/cpp_to_v8"), + jsArgsCount: require("./filters/js_args_count"), + isV8Value: require("./filters/is_v8_value"), + isPointer: require("./filters/is_pointer"), + isDoublePointer: require("./filters/is_double_pointer"), + unPointer: require("./filters/un_pointer"), + hasReturnType: require("./filters/has_return_type"), + hasReturns: require("./filters/has_returns"), + returnsCount: require("./filters/returns_count"), + returnsInfo: require("./filters/returns_info"), + fieldsInfo: require("./filters/fields_info") +}; -var headerTemplate = ejs.compile( - "" + fs.readFileSync(local("templates/header.h.ejs")), { - filename: "header.h" +// Convert Buffers to Combyne templates. +Object.keys(templates).forEach(function(template) { + templates[template] = combyne(templates[template]); + + // Attach all filters to all templates. + Object.keys(filters).forEach(function(filter) { + templates[template].registerFilter(filter, filters[filter]); }); +}); -var bindingTemplate = ejs.compile( - "" + fs.readFileSync(local("templates/binding.gyp.ejs")), {}); +// Attach all partials to select templates. +Object.keys(partials).forEach(function(partial) { + templates.class.registerPartial(partial, combyne(partials[partial])); +}); -var nodegitSourceTemplate = ejs.compile( - "" + fs.readFileSync(local("templates/nodegit.cc.ejs")), {}); +// Determine which definitions to actually include in the source code. var enabled = idefs.filter(function(idef) { + // Additionally provide a friendly name to the actual filename. idef.name = path.basename(idef.filename, ".h"); + + // We need some custom data on each of the functions + idef.functions.forEach(function(fn) { + fn.cppClassName = idef.cppClassName; + }); + return !idef.ignore; }); -enabled.forEach(function(idef) { - fs.writeFileSync(local("../include/", idef.filename), headerTemplate(idef)); - - fs.writeFileSync( - local("../src/", path.basename(idef.filename, ".h")) + ".cc", - classTemplate(idef)); +// TODO Wipe out all existing source files. - fs.writeFileSync(local("../binding.gyp"), bindingTemplate({ - idefs: idefs - })); +// Write out single purpose templates. +file.write("../binding.gyp", templates.binding.render(enabled)); +file.write("../src/nodegit.cc", templates.nodegit.render(enabled)); - fs.writeFileSync(local("../src/nodegit.cc"), nodegitSourceTemplate({ - idefs: idefs - })); +// Write out all the classes. +enabled.forEach(function(idef) { + file.write("../src/" + idef.name + ".cc", templates.class.render(idef)); + file.write("../include/" + idef.name + ".h", templates.header.render(idef)); }); diff --git a/generate/partials/async_function.cc b/generate/partials/async_function.cc new file mode 100644 index 000000000..7b201a44b --- /dev/null +++ b/generate/partials/async_function.cc @@ -0,0 +1,133 @@ +{%partial doc .%} +NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) { + NanScope(); + {%partial guardArguments .%} + + if (args.Length() == {{args|jsArgsCount}} || !args[{{args|jsArgsCount}}]->IsFunction()) { + return NanThrowError("Callback is required and must be a Function."); + } + + {{ cppFunctionName }}Baton* baton = new {{ cppFunctionName }}Baton; + baton->error_code = GIT_OK; + baton->error = NULL; + {%each args|argsInfo as arg %} + {%if not arg.isReturn %} + {%if arg.isSelf %} + baton->{{ arg.name }} = ObjectWrap::Unwrap<{{ arg.cppClassName }}>(args.This())->GetValue(); + {%elsif arg.name %} + {%partial convertFromV8 arg%} + {%if not arg.isPayload %} + baton->{{ arg.name }} = from_{{ arg.name }}; + {%endif%} + {%endif%} + {%elsif arg.shouldAlloc %} + baton->{{ arg.name }} = ({{ arg.cType }})malloc(sizeof({{ arg.cType|replace '*' '' }})); + {%endif%} + {%endeach%} + + NanCallback *callback = new NanCallback(Local::Cast(args[{{args|jsArgsCount}}])); + {{ cppFunctionName }}Worker *worker = new {{ cppFunctionName }}Worker(baton, callback); + {%each args|argsInfo as arg %} + {%if not arg.isReturn %} + {%if arg.isSelf %} + worker->SaveToPersistent("{{ arg.name }}", args.This()); + {%else%} + if (!args[{{ arg.jsArg }}]->IsUndefined() && !args[{{ arg.jsArg }}]->IsNull()) + worker->SaveToPersistent("{{ arg.name }}", args[{{ arg.jsArg }}]->ToObject()); + {%endif%} + {%endif%} + {%endeach%} + + NanAsyncQueueWorker(worker); + NanReturnUndefined(); +} + +void {{ cppClassName }}::{{ cppFunctionName }}Worker::Execute() { + {%if .|hasReturnType %} + {{ return.cType }} result = {{ cFunctionName }}( + {%else%} + {{ cFunctionName }}( + {%endif%} + {%-- Insert Function Arguments --%} + {%each args|argsInfo as arg %} + {%-- turn the pointer into a ref --%} + {%if arg.isReturn|and arg.cType|isDoublePointer %}&{%endif%}baton->{{ arg.name }}{%if not arg.lastArg %},{%endif%} + + {%endeach%} + ); + + {%if return.isErrorCode %} + baton->error_code = result; + + if (result != GIT_OK && giterr_last() != NULL) { + baton->error = git_error_dup(giterr_last()); + } + + {%elsif not return.cType == 'void' %} + + baton->result = result; + + {%endif%} +} + +void {{ cppClassName }}::{{ cppFunctionName }}Worker::HandleOKCallback() { + TryCatch try_catch; + if (baton->error_code == GIT_OK) { + {%if not .|returnsCount %} + Handle result = NanUndefined(); + {%else%} + Handle to; + {%if .|returnsCount > 1 %} + Handle result = NanNew(); + {%endif%} + {%each .|returnsInfo 0 1 as _return %} + {%partial convertToV8 _return %} + {%if .|returnsCount > 1 %} + result->Set(NanNew("{{ _return.jsNameOrName }}"), to); + {%endif%} + {%endeach%} + {%if .|returnsCount == 1 %} + Handle result = to; + {%endif%} + {%endif%} + Handle argv[2] = { + NanNull(), + result + }; + callback->Call(2, argv); + } else { + if (baton->error) { + Handle argv[1] = { + NanError(baton->error->message) + }; + callback->Call(1, argv); + if (baton->error->message) + free((void *)baton->error->message); + free((void *)baton->error); + } else { + callback->Call(0, NULL); + } + + {%each args as arg %} + {%if arg.shouldAlloc %} + free(baton->{{ arg.name }}); + {%endif%} + {%endeach%} + } + + if (try_catch.HasCaught()) { + node::FatalException(try_catch); + } + + {%each args|argsInfo as arg %} + {%if arg.isCppClassStringOrArray %} + {%if arg.freeFunctionName %} + {{ arg.freeFunctionName }}(baton->{{ arg.name }}); + {%else%} + free((void *)baton->{{ arg.name }}); + {%endif%} + {%endif%} + {%endeach%} + + delete baton; +} diff --git a/generate/partials/convert_from_v8.cc b/generate/partials/convert_from_v8.cc new file mode 100644 index 000000000..6a19fe5ab --- /dev/null +++ b/generate/partials/convert_from_v8.cc @@ -0,0 +1,32 @@ +{%if not isPayload %} + {{ cType }} from_{{ name }}; + {%if isOptional %} + if (args[{{ jsArg }}]->Is{{ cppClassName|cppToV8 }}()) { + {%endif%} + {%if cppClassName == 'String' %} + String::Utf8Value {{ name }}(args[{{ jsArg }}]->ToString()); + from_{{ name }} = ({{ cType }}) strdup(*{{ name }}); + {%elsif cppClassName == 'Array' %} + Array *tmp_{{ name }} = Array::Cast(*args[{{ jsArg }}]); + from_{{ name }} = ({{ cType }})malloc(tmp_{{ name }}->Length() * sizeof({{ cType|replace '**' '*' }})); + for (unsigned int i = 0; i < tmp_{{ name }}->Length(); i++) { + {%-- + // FIXME: should recursively call convertFromv8. + --%} + from_{{ name }}[i] = ObjectWrap::Unwrap<{{ arrayElementCppClassName }}>(tmp_{{ name }}->Get(NanNew(static_cast(i)))->ToObject())->GetValue(); + } + {%elsif cppClassName == 'Function' %} + {%elsif cppClassName == 'Buffer' %} + from_{{ name }} = Buffer::Data(args[{{ jsArg }}]->ToObject()); + {%elsif cppClassName|isV8Value %} + from_{{ name }} = ({{ cType }}) {{ additionalCast }} {{ cast }} args[{{ jsArg }}]->To{{ cppClassName }}()->Value(); + {%else%} + from_{{ name }} = ObjectWrap::Unwrap<{{ cppClassName }}>(args[{{ jsArg }}]->ToObject())->GetValue(); + {%endif%} + + {%if isOptional %} + } else { + from_{{ name }} = 0; + } + {%endif%} +{%endif%} diff --git a/generate/partials/convert_to_v8.cc b/generate/partials/convert_to_v8.cc new file mode 100644 index 000000000..ebe2b9dea --- /dev/null +++ b/generate/partials/convert_to_v8.cc @@ -0,0 +1,41 @@ +{%if cppClassName == 'String' %} + {%if size %} +to = NanNew({{= parsedName =}}, {{ size }}); + {%elsif cType == 'char **' %} +to = NanNew(*{{= parsedName =}}); + {%else%} +to = NanNew({{= parsedName =}}); + {%endif%} + + {%if freeFunctionName %} + {{ freeFunctionName }}({{= parsedName =}}); + {%endif%} +{%elsif cppClassName|isV8Value %} + {%if isCppClassIntType %} +to = NanNew<{{ cppClassName }}>(({{ parsedClassName }}){{= parsedName =}}); + {%else%} +to = NanNew<{{ cppClassName }}>({{= parsedName =}}); + {%endif%} +{%elsif cppClassName == 'External' %} +to = NanNew((void *){{= parsedName =}}); +{%elsif cppClassName == 'Array' %} +{%-- + // FIXME this is not general purpose enough. +--%} +Local tmpArray = NanNew({{= parsedName =}}->{{ size }}); +for (unsigned int i = 0; i < {{= parsedName =}}->{{ size }}; i++) { + tmpArray->Set(NanNew(i), NanNew({{= parsedName =}}->{{ key }}[i])); +} +to = tmpArray; +{%else%} + {%if copy %} +if ({{= parsedName =}} != NULL) { + {{= parsedName =}} = ({{ cType|replace '**' '*' }} {%if not cType|isPointer %}*{%endif%}){{ copy }}({{= parsedName =}}); +} + {%endif%} +if ({{= parsedName =}} != NULL) { + to = {{ cppClassName }}::New((void *){{= parsedName =}}); +} else { + to = NanNull(); +} +{%endif%} diff --git a/generate/partials/doc.cc b/generate/partials/doc.cc new file mode 100644 index 000000000..b3bbb5d46 --- /dev/null +++ b/generate/partials/doc.cc @@ -0,0 +1,15 @@ +/** +{%each args as arg %} + {%if not arg.isReturn %} + {%if not arg.isSelf %} +* @param {{ arg.jsClassName }} {{ arg.name }} + {%endif%} + {%endif%} +{%endeach%}{%each .|returnsInfo as returnInfo %} + {%if isAsync %} + * @param {{ returnInfo.jsOrCppClassName }} callback + {%else%} + * @return {{ returnInfo.jsOrCppClassName }} {%if returnInfo.name %}{{ returnInfo.name }}{%else%}result{%endif%} + {%endif%} +{%endeach%} +*/ diff --git a/generate/partials/fields.cc b/generate/partials/fields.cc new file mode 100644 index 000000000..45e17503c --- /dev/null +++ b/generate/partials/fields.cc @@ -0,0 +1,15 @@ +{%each fields|fieldsInfo as field %} + {%if not field.ignore %} + +NAN_METHOD({{ cppClassName }}::{{ field.cppFunctionName }}) { + NanScope(); + Handle to; + + {{ field.cType }} {%if not field.cppClassName|isV8Value %}*{%endif%}{{ field.name }} = + {%if not field.cppClassName|isV8Value %}&{%endif%}ObjectWrap::Unwrap<{{ cppClassName }}>(args.This())->GetValue()->{{ field.name }}; + + {%partial convertToV8 field %} + NanReturnValue(to); +} + {%endif%} +{%endeach%} diff --git a/generate/partials/guard_arguments.cc b/generate/partials/guard_arguments.cc new file mode 100644 index 000000000..b48e561fb --- /dev/null +++ b/generate/partials/guard_arguments.cc @@ -0,0 +1,9 @@ +{%each args|argsInfo as arg%} + {%if arg.isJsArg%} + {%if not arg.isOptional%} + if (args.Length() == {{arg.jsArg}} || !args[{{arg.jsArg}}]->Is{{arg.cppClassName|cppToV8}}()) { + return NanThrowError("{{arg.jsClassName}} {{arg.name}} is required."); + } + {%endif%} + {%endif%} +{%endeach%} diff --git a/generate/partials/sync_function.cc b/generate/partials/sync_function.cc new file mode 100644 index 000000000..a22b45d45 --- /dev/null +++ b/generate/partials/sync_function.cc @@ -0,0 +1,84 @@ +{%partial doc .%} +NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) { + NanScope(); + {%partial guardArguments .%} + + {%each .|returnsInfo 'true' as _return %} + {%if _return.shouldAlloc %} + {{ _return.cType }}{{ _return.name }} = ({{ _return.cType }})malloc(sizeof({{ _return.cType|unPointer }})); + {%else%} + {{ _return.cType|unPointer }} {{ _return.name }} = {{ _return.cType|unPointer|defaultValue }}; + {%endif%} + {%endeach%} + + {%each args|argsInfo as arg %} + {%if not arg.isSelf %} + {%if not arg.isReturn %} + {%partial convertFromV8 arg %} + {%endif%} + {%endif%} + {%endeach%} + +{%if .|hasReturns %} + {{ return.cType }} result = {%endif%}{{ cFunctionName }}( + {%each args|argsInfo as arg %} + {%if arg.isReturn %} + {%if not arg.shouldAlloc %}&{%endif%} + {%endif%} + {%if arg.isSelf %} +ObjectWrap::Unwrap<{{ arg.cppClassName }}>(args.This())->GetValue() + {%elsif arg.isReturn %} +{{ arg.name }} + {%else%} +from_{{ arg.name }} + {%endif%} + {%if not arg.lastArg %},{%endif%} + {%endeach%} + ); + +{%each args|argsInfo as arg %} + {%if arg.isCppClassStringOrArray %} + {%if arg.freeFunctionName %} + {{ arg.freeFunctionName }}(from_{{ arg.name }}); + {%else%} + free((void *)from_{{ arg.name }}); + {%endif%} + {%endif%} +{%endeach%} + +{%if return.isErrorCode %} + if (result != GIT_OK) { + {%each args|argsInfo as arg %} + {%if arg.shouldAlloc %} + free({{ arg.name }}); + {%endif%} + {%endeach%} + + if (giterr_last()) { + return NanThrowError(giterr_last()->message); + } else { + return NanThrowError("Unknown Error"); + } + } +{%endif%} + +{%if not .|returnsCount %} + NanReturnUndefined(); +{%else%} + Handle to; + {%if .|returnsCount > 1 %} + Handle toReturn = NanNew(); + {%endif%} + {%each .|returnsInfo as _return %} + {%partial convertToV8 _return %} + {%if .|returnsCount > 1 %} + toReturn->Set(NanNew("{{ _return.jsNameOrName }}"), to); + {%endif%} + {%endeach%} + {%if .|returnsCount == 1 %} + NanReturnValue(to); + {%else%} + NanReturnValue(toReturn); + {%endif%} +{%endif%} +} diff --git a/generate/templates/asyncFunction.cc.ejs b/generate/templates/asyncFunction.cc.ejs deleted file mode 100644 index 48489a388..000000000 --- a/generate/templates/asyncFunction.cc.ejs +++ /dev/null @@ -1,140 +0,0 @@ -/** -<% include doc.cc.ejs -%> - */ -NAN_METHOD(<%- cppClassName %>::<%- functionInfo.cppFunctionName %>) { - NanScope(); - <% var jsArg; -%> - <% include guardArguments.cc.ejs -%> - - if (args.Length() == <%- jsArg %> || !args[<%- jsArg %>]->IsFunction()) { - return NanThrowError("Callback is required and must be a Function."); - } - - <%- functionInfo.cppFunctionName %>Baton* baton = new <%- functionInfo.cppFunctionName %>Baton; - baton->error_code = GIT_OK; - baton->error = NULL; -<% - for (var cArg = 0, jsArg = 0; cArg < functionInfo.args.length; cArg++) { - var arg = functionInfo.args[cArg]; --%> -<% if (!arg.isReturn) { -%> -<% if (arg.isSelf) { -%> - baton-><%- arg.name %> = ObjectWrap::Unwrap<<%- arg.cppClassName %>>(args.This())->GetValue(); -<% } else if (arg.name) { -%> - <% include convertFromV8.cc.ejs -%> - <% if (!arg.isPayload) { -%> - baton-><%- arg.name %> = from_<%- arg.name %>; - <% } -%> -<% } -%> -<% if (!(arg.isReturn || arg.isSelf || arg.isPayload)) jsArg++; -%> -<% } else { -%> -<% if (arg.shouldAlloc) { -%> - baton-><%- arg.name %> = (<%- arg.cType %>)malloc(sizeof(<%- arg.cType.replace('*', '') %>)); -<% } -%> -<% } -%> -<% } -%> - - NanCallback *callback = new NanCallback(Local::Cast(args[<%- jsArg %>])); - <%- functionInfo.cppFunctionName %>Worker *worker = new <%- functionInfo.cppFunctionName %>Worker(baton, callback); -<% - for (var cArg = 0, jsArg = 0; cArg < functionInfo.args.length; cArg++) { - var arg = functionInfo.args[cArg]; --%> -<% if (!arg.isReturn) { -%> -<% if (arg.isSelf) { -%> - worker->SaveToPersistent("<%- arg.name %>", args.This()); -<% } else { -%> - if (!args[<%- jsArg %>]->IsUndefined() && !args[<%- jsArg %>]->IsNull()) - worker->SaveToPersistent("<%- arg.name %>", args[<%- jsArg %>]->ToObject()); -<% } -%> -<% if (!(arg.isReturn || arg.isSelf || arg.isPayload)) jsArg++; -%> -<% } -%> -<% } -%> - - NanAsyncQueueWorker(worker); - NanReturnUndefined(); -} - -void <%- cppClassName %>::<%- functionInfo.cppFunctionName %>Worker::Execute() { - <% if (functionInfo.return.cType != "void" || functionInfo.return.isErrorCode) { %><%- functionInfo.return.cType %> result = <% } %><%- functionInfo.cFunctionName %>( -<% - for (var i = 0; i < functionInfo.args.length; i++) { - var arg = functionInfo.args[i]; --%> - <% if (arg.isReturn && /\*\*/.test(arg.cType)) { %>&<% } %>baton-><%- arg.name %><% if (i < functionInfo.args.length - 1) { %>, <% } %> -<% } -%> - ); -<% if (functionInfo.return.isErrorCode) { -%> - baton->error_code = result; - if (result != GIT_OK && giterr_last() != NULL) { - baton->error = git_error_dup(giterr_last()); - } -<% } else if (functionInfo.return.cType != "void") { -%> - baton->result = result; -<% } -%> -} - -void <%- cppClassName %>::<%- functionInfo.cppFunctionName %>Worker::HandleOKCallback() { - TryCatch try_catch; - if (baton->error_code == GIT_OK) { -<% if (!returns.length) { -%> - Handle result = NanUndefined(); -<% } else if (returns.length == 1) { -%> -<% var to = {}; to.__proto__ = returns[0]; to.name = "baton->" + to.name; -%> - Handle to; - <% include convertToV8.cc.ejs -%> - Handle result = to; -<% } else { -%> - Handle result = NanNew(); - Handle to; -<% - for (r in returns) { - var to = returns[r]; --%> - <% include convertToV8.cc.ejs -%> - result->Set(NanNew("<%- to.jsName || to.name %>"), to); -<% } -%> -<% } -%> - Handle argv[2] = { - NanNull(), - result - }; - callback->Call(2, argv); - } else { - if (baton->error) { - Handle argv[1] = { - NanError(baton->error->message) - }; - callback->Call(1, argv); - if (baton->error->message) - free((void *)baton->error->message); - free((void *)baton->error); - } else { - callback->Call(0, NULL); - } - <% - for (var i = 0; i < functionInfo.args.length; i++) { - var arg = functionInfo.args[i]; - if (!arg.shouldAlloc) continue; - -%> - free(baton-><%= arg.name %>); - <% } -%> - } - - if (try_catch.HasCaught()) { - node::FatalException(try_catch); - } -<% - for (var i = 0; i < functionInfo.args.length; i++) { - var arg = functionInfo.args[i]; --%> -<% if (['String', 'Array'].indexOf(arg.cppClassName) > -1) { -%> -<% if (arg.freeFunctionName) { %> - <%- arg.freeFunctionName %>(baton-><%- arg.name %>); -<% } else { -%> - free((void *)baton-><%- arg.name %>); -<% } -%> -<% } -%> -<% } -%> - delete baton; -} diff --git a/generate/templates/binding.gyp.ejs b/generate/templates/binding.gyp similarity index 89% rename from generate/templates/binding.gyp.ejs rename to generate/templates/binding.gyp index b5dd98cba..588d66054 100644 --- a/generate/templates/binding.gyp.ejs +++ b/generate/templates/binding.gyp @@ -12,10 +12,10 @@ "src/nodegit.cc", "src/wrapper.cc", "src/functions/copy.cc", - <% idefs.forEach(function(idef) { -%> - "src/<%- idef.name %>.cc", - <% }); -%> - ], + {%each%} + "src/{{ name }}.cc", + {%endeach%} + ], "include_dirs": [ "vendor/libv8-convert", diff --git a/generate/templates/class.cc b/generate/templates/class.cc new file mode 100644 index 000000000..cf46d25b0 --- /dev/null +++ b/generate/templates/class.cc @@ -0,0 +1,110 @@ +// This is a generated file, modify: generate/templates/class.cc. +#include +#include + +extern "C" { +#include +} + +#include "../include/functions/copy.h" +#include "../include/{{ filename }}" + +{%each dependencies as dependency%} +#include "{{ dependency }}" +{%endeach%} + +using namespace v8; +using namespace node; + +{%if cType%} +{{ cppClassName }}::{{ cppClassName }}({{ cType }} *raw) { + this->raw = raw; +} + +{{ cppClassName }}::~{{ cppClassName }}() { + {%if freeFunctionName%} + {{ freeFunctionName }}(this->raw); + {%endif%} +} + +void {{ cppClassName }}::Initialize(Handle target) { + NanScope(); + + Local tpl = NanNew(New); + + tpl->InstanceTemplate()->SetInternalFieldCount(1); + tpl->SetClassName(NanNew("{{ jsClassName }}")); + + {%each functions as function%} + {%if not function.ignore%} + {%if function.isPrototypeMethod%} + NODE_SET_PROTOTYPE_METHOD(tpl, "{{ function.jsFunctionName }}", {{ function.cppFunctionName }}); + {%else%} + NODE_SET_METHOD(tpl, "{{ function.jsFunctionName }}", {{ function.cppFunctionName }}); + {%endif%} + {%endif%} + {%endeach%} + + {%each fields as field%} + {%if not field.ignore%} + NODE_SET_PROTOTYPE_METHOD(tpl, "{{ field.jsFunctionName }}", {{ field.cppFunctionName }}); + {%endif%} + {%endeach%} + + Local _constructor_template = tpl->GetFunction(); + NanAssignPersistent(constructor_template, _constructor_template); + target->Set(NanNew("{{ jsClassName }}"), _constructor_template); +} + +NAN_METHOD({{ cppClassName }}::New) { + NanScope(); + + if (args.Length() == 0 || !args[0]->IsExternal()) { + return NanThrowError("{{ cType }} is required."); + } + {{ cppClassName }}* object = new {{ cppClassName }}(static_cast<{{ cType }} *>(Handle::Cast(args[0])->Value())); + object->Wrap(args.This()); + + NanReturnValue(args.This()); +} + +Handle {{ cppClassName }}::New(void *raw) { + NanEscapableScope(); + Handle argv[1] = { NanNew((void *)raw) }; + return NanEscapeScope(NanNew({{ cppClassName }}::constructor_template)->NewInstance(1, argv)); +} + +{{ cType }} *{{ cppClassName }}::GetValue() { + return this->raw; +} +{%else%} +void {{ cppClassName }}::Initialize(Handle target) { + NanScope(); + + Local object = NanNew(); + + {%each functions as function%} + {%if not function.ignore%} + NODE_SET_METHOD(object, "{{ function.jsFunctionName }}", {{ function.cppFunctionName }}); + {%endif%} + {%endeach%} + + target->Set(NanNew("{{ jsClassName }}"), object); +} +{%endif%} + +{%each functions as function %} + {%if not function.ignore%} + {%if function.isAsync%} + {%partial asyncFunction function %} + {%else%} + {%partial syncFunction function %} + {%endif%} + {%endif%} +{%endeach%} + +{%partial fields .%} + +{%if not cTypeIsUndefined %} +Persistent {{ cppClassName }}::constructor_template; +{%endif%} diff --git a/generate/templates/class.cc.ejs b/generate/templates/class.cc.ejs deleted file mode 100644 index 83c8b5f03..000000000 --- a/generate/templates/class.cc.ejs +++ /dev/null @@ -1,160 +0,0 @@ -<% - function isV8Value(cppClassName) { - return ["Boolean", "Number", "String", "Integer", "Int32", "Uint32", "Date", "Function"].indexOf(cppClassName) > -1; - } - - function cppClassName2v8ValueClassName(cppClassName) { - if (isV8Value(cppClassName)) - return cppClassName; - else - return 'Object'; - } - - function isPointer(cType) { - return /\s*\*\s*$/.test(cType); - } - - function unPointer(cType) { - return cType.replace(/\s*\*\s*$/,''); - } - - function defaultValue(cType) { - if (cType === 'git_otype') { return 'GIT_OBJ_ANY'; } - else { return '0'; } - } --%> -// This is a generated file, modify: generate/templates/class.cc.ejs. -#include -#include - -extern "C" { -#include -} - -#include "../include/functions/copy.h" -#include "../include/<%= filename %>" -<% if (typeof dependencies != 'undefined') { -%> -<% for (d in dependencies) { -%> -#include "<%- dependencies[d] %>" -<% } -%> -<% } -%> - -using namespace v8; -using namespace node; - -<% if (cType != undefined) { -%> -<%- cppClassName %>::<%- cppClassName %>(<%- cType %> *raw) { - this->raw = raw; -} - -<%- cppClassName %>::~<%- cppClassName %>() { -<% if (typeof freeFunctionName != 'undefined') { -%> - <%- freeFunctionName %>(this->raw); -<% } -%> -} - -void <%- cppClassName %>::Initialize(Handle target) { - NanScope(); - - Local tpl = NanNew(New); - - tpl->InstanceTemplate()->SetInternalFieldCount(1); - tpl->SetClassName(NanNew("<%- jsClassName %>")); - -<% if (typeof functions != 'undefined') { -%> -<% - for (var i in functions) { - var functionInfo = functions[i]; - if (functionInfo.ignore) continue; --%> -<% if (functionInfo.isPrototypeMethod) { -%> - NODE_SET_PROTOTYPE_METHOD(tpl, "<%- functionInfo.jsFunctionName %>", <%- functionInfo.cppFunctionName %>); -<% } else { -%> - NODE_SET_METHOD(tpl, "<%- functionInfo.jsFunctionName %>", <%- functionInfo.cppFunctionName %>); -<% } -%> -<% } -%> -<% } -%> - -<% if (typeof fields != 'undefined') { -%> -<% - for (var i in fields) { - var fieldInfo = fields[i]; - if (fieldInfo.ignore) continue; --%> - NODE_SET_PROTOTYPE_METHOD(tpl, "<%- fieldInfo.jsFunctionName %>", <%- fieldInfo.cppFunctionName %>); -<% } -%> -<% } -%> - - Local _constructor_template = tpl->GetFunction(); - NanAssignPersistent(constructor_template, _constructor_template); - target->Set(NanNew("<%- jsClassName %>"), _constructor_template); -} - -NAN_METHOD(<%- cppClassName %>::New) { - NanScope(); - - if (args.Length() == 0 || !args[0]->IsExternal()) { - return NanThrowError("<%= cType %> is required."); - } - <%- cppClassName %>* object = new <%- cppClassName %>(static_cast<<%= cType%> *>(Handle::Cast(args[0])->Value())); - object->Wrap(args.This()); - - NanReturnValue(args.This()); -} - -Handle <%- cppClassName %>::New(void *raw) { - NanEscapableScope(); - Handle argv[1] = { NanNew((void *)raw) }; - return NanEscapeScope(NanNew(<%- cppClassName %>::constructor_template)->NewInstance(1, argv)); -} - -<%- cType %> *<%- cppClassName %>::GetValue() { - return this->raw; -} -<% } else { -%> -void <%- cppClassName %>::Initialize(Handle target) { - NanScope(); - - Local object = NanNew(); - -<% if (typeof functions != 'undefined') { -%> -<% - for (var i in functions) { - var functionInfo = functions[i]; - if (functionInfo.ignore) continue; --%> - NODE_SET_METHOD(object, "<%- functionInfo.jsFunctionName %>", <%- functionInfo.cppFunctionName %>); -<% } -%> -<% } -%> - - target->Set(NanNew("<%- jsClassName %>"), object); -} -<% } -%> - -<% if (typeof functions != 'undefined') { -%> -<% - for (var i in functions) { - var functionInfo = functions[i]; - if (functionInfo.ignore) continue; - - var returns = []; - for (var i = 0; i < functionInfo.args.length; i++) { - var arg = functionInfo.args[i]; - if (arg.isReturn) returns.push(arg); - } - functionInfo.return = functionInfo.return || {}; - if (!returns.length && !functionInfo.return.isErrorCode && functionInfo.return.cType != "void") returns.push(functionInfo.return); --%> - -<% if (functionInfo.isAsync) { -%> -<% include generate/templates/asyncFunction.cc.ejs -%> -<% } else { -%> -<% include generate/templates/syncFunction.cc.ejs -%> -<% } -%> -<% } -%> -<% } -%> -<% include generate/templates/fields.cc.ejs -%> - -<% if (typeof cType != 'undefined') { -%> -Persistent <%- cppClassName %>::constructor_template; -<% } -%> diff --git a/generate/templates/convertFromV8.cc.ejs b/generate/templates/convertFromV8.cc.ejs deleted file mode 100644 index d442377f9..000000000 --- a/generate/templates/convertFromV8.cc.ejs +++ /dev/null @@ -1,31 +0,0 @@ -<% if (!arg.isPayload) { -%> - <%- arg.cType %> from_<%- arg.name %>; - <% if (arg.isOptional) { -%> - if (args[<%- jsArg %>]->Is<%- cppClassName2v8ValueClassName(arg.cppClassName) %>()) { - <% } -%> - <% if (arg.cppClassName == 'String') { -%> - String::Utf8Value <%- arg.name %>(args[<%- jsArg %>]->ToString()); - from_<%- arg.name %> = (<%- arg.cType %>) strdup(*<%- arg.name %>); - <% } else if (arg.cppClassName == 'Array') { -%> - Array *tmp_<%- arg.name %> = Array::Cast(*args[<%- jsArg %>]); - from_<%- arg.name %> = (<%- arg.cType %>)malloc(tmp_<%- arg.name %>->Length() * sizeof(<%- arg.cType.replace('**', '*') %>)); - for (unsigned int i = 0; i < tmp_<%- arg.name %>->Length(); i++) { - <% - // FIXME: should recursively call convertFromv8. - %> - from_<%- arg.name %>[i] = ObjectWrap::Unwrap<<%- arg.arrayElementCppClassName %>>(tmp_<%- arg.name %>->Get(NanNew(static_cast(i)))->ToObject())->GetValue(); - } - <% } else if (arg.cppClassName == "Function") { -%> - <% } else if (arg.cppClassName == 'Buffer') { -%> - from_<%- arg.name %> = Buffer::Data(args[<%- jsArg %>]->ToObject()); - <% } else if (isV8Value(arg.cppClassName)) { -%> - from_<%- arg.name %> = (<%- arg.cType %>) <%- arg.additionalCast %> <%- arg.cast %> args[<%- jsArg %>]->To<%- arg.cppClassName %>()->Value(); - <% } else { -%> - from_<%- arg.name %> = ObjectWrap::Unwrap<<%- arg.cppClassName %>>(args[<%- jsArg %>]->ToObject())->GetValue(); - <% } -%> - <% if (arg.isOptional) { -%> - } else { - from_<%- arg.name %> = 0; - } - <% } -%> -<% } -%> diff --git a/generate/templates/convertToV8.cc.ejs b/generate/templates/convertToV8.cc.ejs deleted file mode 100644 index 7047d1db7..000000000 --- a/generate/templates/convertToV8.cc.ejs +++ /dev/null @@ -1,43 +0,0 @@ -<% toName = to.name || 'result' -%> -<% if (to.cppClassName == "String") { -%> - <% if (typeof to.size != 'undefined') { -%> -to = NanNew(<%- toName %>, <%- to.size %>); - <% } else if (to.cType === "char **") { -%> -to = NanNew(*<%- toName %>); - <% } else { -%> -to = NanNew(<%- toName %>); - <% } -%> - - <% if (to.freeFunctionName) { -%> - <%- to.freeFunctionName %>(<%- toName %>); - <% } -%> -<% } else if (isV8Value(to.cppClassName)) { -%> -<% if (~['Uint32', 'Int32'].indexOf(to.cppClassName)) { -%> -<% var className = to.cppClassName.toLowerCase()+'_t' -%> - to = NanNew<<%- to.cppClassName %>>((<%- className %>)<%- toName %>); -<% } else { -%> - to = NanNew<<%- to.cppClassName %>>(<%- toName %>); -<% } -%> -<% } else if (to.cppClassName == "External") { -%> - to = NanNew((void *)<%- toName %>); -<% } else if (to.cppClassName == 'Array') { -%> -<% - // FIXME this is not general purpose enough. -%> - Local tmpArray = NanNew(<%- toName %>-><%- to.size %>); - for (unsigned int i = 0; i < <%- toName %>-><%- to.size %>; i++) { - tmpArray->Set(NanNew(i), NanNew(<%- toName %>-><%- to.key %>[i])); - } - to = tmpArray; -<% } else { -%> -<% if (to.copy) { -%> - if (<%- toName %> != NULL) { - <%- toName %> = (<%- to.cType.replace('**', '*') %> <% if (!/\*/.test(to.cType)) {%>*<% } %>)<%- to.copy %>(<%- toName %>); - } -<% } -%> - if (<%- toName %> != NULL) { - to = <%- to.cppClassName %>::New((void *)<%- toName %>); - } else { - to = NanNull(); - } -<% } -%> diff --git a/generate/templates/doc.cc.ejs b/generate/templates/doc.cc.ejs deleted file mode 100644 index 44ca0979a..000000000 --- a/generate/templates/doc.cc.ejs +++ /dev/null @@ -1,14 +0,0 @@ -<% - for (var i = 0; i < functionInfo.args.length; i++) { - var arg = functionInfo.args[i]; - if (arg.isReturn || arg.isSelf) continue; --%> - * @param {<%- arg.jsClassName %>} <%- arg.name %> -<% } -%> -<% for (var r = 0; r < returns.length; r++) { -%> -<% if (functionInfo.isAsync) { -%> - * @param {<%- returns[r].jsClassName || returns[r].cppClassName %>} callback -<% } else { -%> - * @return {<%- returns[r].jsClassName || returns[r].cppClassName %>} <%- returns[r].name || 'result' %> -<% } -%> -<% } -%> diff --git a/generate/templates/fields.cc.ejs b/generate/templates/fields.cc.ejs deleted file mode 100644 index f7f684a99..000000000 --- a/generate/templates/fields.cc.ejs +++ /dev/null @@ -1,20 +0,0 @@ -<% if (typeof fields != 'undefined') { -%> -<% - for (var i in fields) { - var fieldInfo = fields[i]; - if (fieldInfo.ignore) continue; --%> - -NAN_METHOD(<%- cppClassName %>::<%- fieldInfo.cppFunctionName %>) { - NanScope(); - <% var to = fieldInfo; -%> - Handle to; - - <%- fieldInfo.cType %> <% if (!isV8Value(fieldInfo.cppClassName)) { %>*<% } %><%- fieldInfo.name %> = - <% if (!isV8Value(fieldInfo.cppClassName)) { %>&<% } %>ObjectWrap::Unwrap<<%- cppClassName %>>(args.This())->GetValue()-><%- fieldInfo.name %>; - - <% include convertToV8.cc.ejs -%> - NanReturnValue(to); -} -<% } -%> -<% } -%> diff --git a/generate/templates/guardArguments.cc.ejs b/generate/templates/guardArguments.cc.ejs deleted file mode 100644 index 99a99fb0f..000000000 --- a/generate/templates/guardArguments.cc.ejs +++ /dev/null @@ -1,13 +0,0 @@ -<% - var cArg = 0; - for (cArg = 0, jsArg = 0; cArg < functionInfo.args.length; cArg++) { - var arg = functionInfo.args[cArg]; - if (arg.isReturn || arg.isSelf || arg.isPayload) continue; --%> -<% if (!arg.isOptional) { -%> - if (args.Length() == <%- jsArg %> || !args[<%- jsArg %>]->Is<%- cppClassName2v8ValueClassName(arg.cppClassName) %>()) { - return NanThrowError("<%- arg.jsClassName %> <%- arg.name %> is required."); - } -<% } -%> -<% jsArg++; -%> -<% } -%> diff --git a/generate/templates/header.h b/generate/templates/header.h new file mode 100644 index 000000000..2f6a58e5b --- /dev/null +++ b/generate/templates/header.h @@ -0,0 +1,95 @@ +#ifndef {{ cppClassName|upper }}_H +#define {{ cppClassName|upper }}_H + +#include +#include + +extern "C" { +#include +} + +{%each dependencies as dependency%} +#include "{{ dependency }}" +{%endeach%} + +{%if forwardDeclare%} +// Forward declaration. +struct {{ cType }} { + {%each fields as field%} + {%if not field.ignore%} + {{ field.structType|or field.cType }} {{ field.structName|or field.name }}; + {%endif%} + {%endeach%} +}; +{%endif%} + +using namespace node; +using namespace v8; + +class {{ cppClassName }} : public ObjectWrap { + public: + + static Persistent constructor_template; + static void Initialize (Handle target); + + {%if cType%} + {{ cType }} *GetValue(); + + static Handle New(void *raw); + {%endif%} + + private: + {%if cType%} + {{ cppClassName }}({{ cType }} *raw); + ~{{ cppClassName }}(); + {%endif%} + + static NAN_METHOD(New); + + {%each fields as field%} + {%if not field.ignore%} + static NAN_METHOD({{ field.cppFunctionName }}); + {%endif%} + {%endeach%} + + {%each functions as function%} + {%if not function.ignore%} + {%if function.isAsync%} + + struct {{ function.cppFunctionName }}Baton { + int error_code; + const git_error* error; + {%each function.args as arg%} + {%if arg.isReturn%} + {{ arg.cType|replace "**" "*" }} {{ arg.name }}; + {%else%} + {{ arg.cType }} {{ arg.name }}; + {%endif%} + {%endeach%} + }; + class {{ function.cppFunctionName }}Worker : public NanAsyncWorker { + public: + {{ function.cppFunctionName }}Worker( + {{ function.cppFunctionName }}Baton *_baton, + NanCallback *callback + ) : NanAsyncWorker(callback) + , baton(_baton) {}; + ~{{ function.cppFunctionName }}Worker() {}; + void Execute(); + void HandleOKCallback(); + + private: + {{ function.cppFunctionName }}Baton *baton; + }; + {%endif%} + + static NAN_METHOD({{ function.cppFunctionName }}); + {%endif%} + {%endeach%} + + {%if cType%} + {{ cType }} *raw; + {%endif%} +}; + +#endif diff --git a/generate/templates/header.h.ejs b/generate/templates/header.h.ejs deleted file mode 100644 index 8280ab1ff..000000000 --- a/generate/templates/header.h.ejs +++ /dev/null @@ -1,112 +0,0 @@ -// This is a generated file, modify: generate/templates/header.h.ejs. -#ifndef <%- cppClassName.toUpperCase() %>_H -#define <%- cppClassName.toUpperCase() %>_H - -#include -#include - -extern "C" { -#include -} - -<% if (typeof dependencies != 'undefined') { -%> -<% for (d in dependencies) { -%> -#include "<%- dependencies[d] %>" -<% } -%> -<% } -%> - -<% if (typeof forwardDeclare !== "undefined") { %> -// Forward declaration. -struct <%- cType %> { - <% if (typeof fields != 'undefined') { %> - <% - for (var i in fields) { - var fieldInfo = fields[i]; - if (fieldInfo.ignore || !fieldInfo.cppFunctionName) continue; - -%> - - <%- fieldInfo.structType || fieldInfo.cType -%> <%- fieldInfo.structName || fieldInfo.name %>; - <% } -%> - <% } -%> - -}; -<% } -%> - -using namespace node; -using namespace v8; - -class <%- cppClassName %> : public ObjectWrap { - public: - - static Persistent constructor_template; - static void Initialize (Handle target); - -<% if (cType != undefined) { -%> - <%- cType %> *GetValue(); - - static Handle New(void *raw); -<% } -%> - - private: -<% if (cType != undefined) { -%> - <%- cppClassName %>(<%- cType %> *raw); - ~<%- cppClassName %>(); -<% } -%> - - static NAN_METHOD(New); - -<% if (typeof fields != 'undefined') { -%> -<% - for (var i in fields) { - var fieldInfo = fields[i]; - if (fieldInfo.ignore || !fieldInfo.cppFunctionName) continue; --%> - static NAN_METHOD(<%- fieldInfo.cppFunctionName %>); -<% } -%> -<% } -%> -<% if (typeof functions != 'undefined') { -%> -<% - for (var i in functions) { - var functionInfo = functions[i]; - if (functionInfo.ignore || !functionInfo.cppFunctionName) continue; --%> -<% if (functionInfo.isAsync) { -%> - - struct <%- functionInfo.cppFunctionName %>Baton { - int error_code; - const git_error* error; -<% - for (var i = 0; i < functionInfo.args.length; i++) { - var arg = functionInfo.args[i]; --%> -<% if (arg.isReturn) { -%> - <%- arg.cType.replace('**', '*') %> <%- arg.name %>; -<% } else { -%> - <%- arg.cType %> <%- arg.name %>; -<% } -%> -<% } -%> - }; - class <%- functionInfo.cppFunctionName %>Worker : public NanAsyncWorker { - public: - <%- functionInfo.cppFunctionName %>Worker( - <%- functionInfo.cppFunctionName %>Baton *_baton, - NanCallback *callback - ) : NanAsyncWorker(callback) - , baton(_baton) {}; - ~<%- functionInfo.cppFunctionName %>Worker() {}; - void Execute(); - void HandleOKCallback(); - - private: - <%- functionInfo.cppFunctionName %>Baton *baton; - }; -<% } -%> - static NAN_METHOD(<%- functionInfo.cppFunctionName %>); -<% } -%> -<% } -%> -<% if (cType != undefined) { -%> - <%- cType %> *raw; -<% } -%> -}; - -#endif diff --git a/generate/templates/nodegit.cc.ejs b/generate/templates/nodegit.cc similarity index 59% rename from generate/templates/nodegit.cc.ejs rename to generate/templates/nodegit.cc index 3036ff7b8..5a1deefd7 100644 --- a/generate/templates/nodegit.cc.ejs +++ b/generate/templates/nodegit.cc @@ -1,24 +1,22 @@ // This is a generated file, modify: generate/templates/nodegit.cc.ejs. #include #include - -#include "git2.h" +#include #include "../include/wrapper.h" #include "../include/functions/copy.h" - -<% idefs.forEach(function(idef) { -%> -#include "../include/<%- idef.filename %>" -<% }); -%> +{%each%} +#include "../include/{{ filename }}" +{%endeach%} extern "C" void init(Handle target) { NanScope(); Wrapper::Initialize(target); -<% idefs.forEach(function(idef) { -%> - <%- idef.cppClassName %>::Initialize(target); -<% }); -%> + {%each%} + {{ cppClassName }}::Initialize(target); + {%endeach%} } NODE_MODULE(nodegit, init) diff --git a/generate/templates/syncFunction.cc.ejs b/generate/templates/syncFunction.cc.ejs deleted file mode 100644 index 5f37e1094..000000000 --- a/generate/templates/syncFunction.cc.ejs +++ /dev/null @@ -1,95 +0,0 @@ -/** -<% include doc.cc.ejs -%> - */ -NAN_METHOD(<%- cppClassName %>::<%- functionInfo.cppFunctionName %>) { - NanScope(); - <% include guardArguments.cc.ejs -%> - -<% - for (var i = 0; i < functionInfo.args.length; i++) { - var arg = functionInfo.args[i]; - if (!arg.isReturn) continue; --%> -<% if (arg.shouldAlloc) { -%> - <%- arg.cType %><%- arg.name %> = (<%- arg.cType %>)malloc(sizeof(<%- unPointer(arg.cType) %>)); -<% } else { -%> - <%- unPointer(arg.cType) %> <%- arg.name %> = <%- defaultValue(unPointer(arg.cType)) %>; -<% } -%> -<% } -%> -<% - for (var cArg = 0, jsArg = 0; cArg < functionInfo.args.length; cArg++) { - var arg = functionInfo.args[cArg]; - if (arg.isSelf || arg.isReturn || arg.isPayload) continue; --%> -<% include convertFromV8.cc.ejs -%> -<% jsArg++; -%> -<% } %> - <% if (returns.length || functionInfo.return.isErrorCode) { %><%- functionInfo.return.cType %> result = <% } %><%- functionInfo.cFunctionName %>( -<% - for (var cArg = 0, jsArg = 0; cArg < functionInfo.args.length; cArg++) { - var arg = functionInfo.args[cArg]; --%> - <% if (cArg > 0) { %>, <% } -%><% if (arg.isReturn && !arg.shouldAlloc) { %>&<% } -%> -<% if (arg.isSelf) { -%> -ObjectWrap::Unwrap<<%- arg.cppClassName %>>(args.This())->GetValue() -<% } else if (arg.isReturn) { -%> -<%- arg.name %> -<% } else { -%> -from_<%- arg.name %> -<% } -%> -<% - if (!(arg.isReturn || arg.isSelf)) jsArg++; - } --%> - ); -<% - for (var i = 0; i < functionInfo.args.length; i++) { - var arg = functionInfo.args[i]; - if (arg.isSelf || arg.isReturn) continue; --%> -<% if (['String', 'Array'].indexOf(arg.cppClassName) > -1) { -%> -<% if (arg.freeFunctionName) { %> - <%- arg.freeFunctionName %>(from_<%- arg.name %>); -<% } else { -%> - free((void *)from_<%- arg.name %>); -<% } -%> -<% } -%> -<% } -%> -<% if (functionInfo.return.isErrorCode) { -%> - if (result != GIT_OK) { -<% - for (var i = 0; i < functionInfo.args.length; i++) { - var arg = functionInfo.args[i]; - if (!arg.shouldAlloc) continue; --%> - free(<%= arg.name %>); -<% } -%> - if (giterr_last()) { - return NanThrowError(giterr_last()->message); - } else { - return NanThrowError("Unknown Error"); - } - } -<% } -%> - -<% if (!returns.length) { -%> - NanReturnUndefined(); -<% } else if (returns.length == 1) { -%> -<% var to = returns[0]; -%> - Handle to; - <% include convertToV8.cc.ejs -%> - NanReturnValue(to); -<% } else { -%> - Handle toReturn = NanNew(); - Handle to; -<% - for (r in returns) { - var to = returns[r]; --%> - <% include convertToV8.cc.ejs -%> - toReturn->Set(NanNew("<%- to.jsName || to.name %>"), to); - -<% } -%> - NanReturnValue(toReturn); -<% } -%> -} diff --git a/generate/types.json b/generate/types.json index a664a78d4..9199f6e24 100644 --- a/generate/types.json +++ b/generate/types.json @@ -3365,6 +3365,7 @@ "js": "Config" }, "const git_config **": { + "cpp": "GitConfig", "js": "Config" }, "git_config_find_global *": { @@ -9147,4 +9148,4 @@ "cpp": "InitInitOptions", "js": "initInitOptions" } -} +} \ No newline at end of file diff --git a/generate/util/file.js b/generate/util/file.js new file mode 100644 index 000000000..c595a7687 --- /dev/null +++ b/generate/util/file.js @@ -0,0 +1,24 @@ +const fs = require("fs"); +const path = require("path"); + +// Make a locally bound path joiner. +var local = path.join.bind(null, __dirname, "../"); + +exports.read = function(file) { + try { + return fs.readFileSync(local(file)).toString(); + } + catch (unhandledException) { + return ""; + } +}; + +exports.write = function(file, contents) { + try { + fs.writeFileSync(local(file), contents); + return true; + } + catch (unhandledException) { + return false; + } +}; diff --git a/package.json b/package.json index 0fa56e90e..c751c2cc2 100644 --- a/package.json +++ b/package.json @@ -40,25 +40,26 @@ "node-pre-gyp" ], "dependencies": { - "fs-extra": "~0.9.1", - "nan": "~1.2.0", - "node-gyp": "~0.13.1", - "node-pre-gyp": "~0.5.16", + "fs-extra": "~0.12.0", + "nan": "~1.3.0", + "node-gyp": "~1.0.2", + "node-pre-gyp": "~0.5.27", "q": "~1.0.1", "ejs": "~1.0.0", - "request": "~2.36.0", + "combyne": "~0.6.0", + "request": "~2.45.0", "rimraf": "~2.2.8", - "tar": "~0.1.19", + "tar": "~1.0.1", "which": "~1.0.5", - "promise": "~4.0.0", + "promise": "~6.0.0", "promisify-node": "~0.1.2" }, "devDependencies": { "async": "~0.9.0", - "aws-sdk": "~2.0.0-rc.20", - "istanbul": "~0.2.14", - "jshint": "~2.5.1", - "mocha": "~1.20.1", + "aws-sdk": "~2.0.18", + "istanbul": "~0.3.2", + "jshint": "~2.5.6", + "mocha": "~1.21.4", "nodeunit": "~0.9.0" }, "binary": { @@ -75,4 +76,4 @@ "install": "npm run generate && node install", "rebuild": "npm run generate && node-gyp configure build" } -} +} \ No newline at end of file