From 05c06a8a183ff76c54fc75948d837f6abf575770 Mon Sep 17 00:00:00 2001 From: Maximiliano Korp Date: Tue, 25 Nov 2014 15:29:31 -0700 Subject: [PATCH] clean up the contents of the generate folder --- .gitignore | 5 +- generate/{ => combyne}/filters/and.js | 0 generate/{ => combyne}/filters/args_info.js | 0 generate/{ => combyne}/filters/cpp_to_v8.js | 0 .../{ => combyne}/filters/default_value.js | 0 generate/{ => combyne}/filters/fields_info.js | 0 .../{ => combyne}/filters/has_return_type.js | 0 generate/{ => combyne}/filters/has_returns.js | 0 .../filters/is_double_pointer.js | 0 generate/{ => combyne}/filters/is_pointer.js | 0 generate/{ => combyne}/filters/is_v8_value.js | 0 .../{ => combyne}/filters/js_args_count.js | 0 generate/{ => combyne}/filters/or.js | 0 generate/{ => combyne}/filters/payload_for.js | 0 generate/{ => combyne}/filters/replace.js | 0 .../{ => combyne}/filters/returns_count.js | 0 .../{ => combyne}/filters/returns_info.js | 0 generate/{ => combyne}/filters/title_case.js | 0 generate/{ => combyne}/filters/un_pointer.js | 0 generate/{ => combyne}/filters/upper.js | 0 .../manual/include/functions/copy.h | 0 .../{ => combyne}/manual/include/macros.h | 0 .../{ => combyne}/manual/include/wrapper.h | 0 .../manual/src/functions/copy.cc | 0 generate/{ => combyne}/manual/src/wrapper.cc | 0 .../{ => combyne}/partials/async_function.cc | 0 .../{ => combyne}/partials/convert_from_v8.cc | 0 .../{ => combyne}/partials/convert_to_v8.cc | 0 generate/{ => combyne}/partials/doc.cc | 0 .../{ => combyne}/partials/field_accessors.cc | 0 generate/{ => combyne}/partials/fields.cc | 0 .../{ => combyne}/partials/guard_arguments.cc | 0 .../{ => combyne}/partials/sync_function.cc | 0 generate/{ => combyne}/templates/binding.gyp | 0 .../{ => combyne}/templates/class_content.cc | 0 .../{ => combyne}/templates/class_header.h | 0 generate/{ => combyne}/templates/enums.js | 0 generate/{ => combyne}/templates/nodegit.cc | 0 .../{ => combyne}/templates/struct_content.cc | 0 .../{ => combyne}/templates/struct_header.h | 0 generate/index.js | 145 +----------- generate/{ => input}/callbacks.json | 0 generate/{ => input}/descriptor.json | 0 .../ignored-missing-tests.json} | 0 generate/{ => input}/libgit2-supplement.json | 0 generate/{ => input}/v0.21.2.json | 0 generate/missing-tests.js | 64 ----- generate/scripts/generateJson.js | 222 ++++++++++++++++++ generate/scripts/generateMissingTests.js | 73 ++++++ generate/scripts/generateNativeCode.js | 146 ++++++++++++ generate/{utils.js => scripts/helpers.js} | 144 +++++------- generate/scripts/utils.js | 67 ++++++ generate/setup.js | 218 ----------------- generate/util/file.js | 24 -- package.json | 9 +- 55 files changed, 580 insertions(+), 537 deletions(-) rename generate/{ => combyne}/filters/and.js (100%) rename generate/{ => combyne}/filters/args_info.js (100%) rename generate/{ => combyne}/filters/cpp_to_v8.js (100%) rename generate/{ => combyne}/filters/default_value.js (100%) rename generate/{ => combyne}/filters/fields_info.js (100%) rename generate/{ => combyne}/filters/has_return_type.js (100%) rename generate/{ => combyne}/filters/has_returns.js (100%) rename generate/{ => combyne}/filters/is_double_pointer.js (100%) rename generate/{ => combyne}/filters/is_pointer.js (100%) rename generate/{ => combyne}/filters/is_v8_value.js (100%) rename generate/{ => combyne}/filters/js_args_count.js (100%) rename generate/{ => combyne}/filters/or.js (100%) rename generate/{ => combyne}/filters/payload_for.js (100%) rename generate/{ => combyne}/filters/replace.js (100%) rename generate/{ => combyne}/filters/returns_count.js (100%) rename generate/{ => combyne}/filters/returns_info.js (100%) rename generate/{ => combyne}/filters/title_case.js (100%) rename generate/{ => combyne}/filters/un_pointer.js (100%) rename generate/{ => combyne}/filters/upper.js (100%) rename generate/{ => combyne}/manual/include/functions/copy.h (100%) rename generate/{ => combyne}/manual/include/macros.h (100%) rename generate/{ => combyne}/manual/include/wrapper.h (100%) rename generate/{ => combyne}/manual/src/functions/copy.cc (100%) rename generate/{ => combyne}/manual/src/wrapper.cc (100%) rename generate/{ => combyne}/partials/async_function.cc (100%) rename generate/{ => combyne}/partials/convert_from_v8.cc (100%) rename generate/{ => combyne}/partials/convert_to_v8.cc (100%) rename generate/{ => combyne}/partials/doc.cc (100%) rename generate/{ => combyne}/partials/field_accessors.cc (100%) rename generate/{ => combyne}/partials/fields.cc (100%) rename generate/{ => combyne}/partials/guard_arguments.cc (100%) rename generate/{ => combyne}/partials/sync_function.cc (100%) rename generate/{ => combyne}/templates/binding.gyp (100%) rename generate/{ => combyne}/templates/class_content.cc (100%) rename generate/{ => combyne}/templates/class_header.h (100%) rename generate/{ => combyne}/templates/enums.js (100%) rename generate/{ => combyne}/templates/nodegit.cc (100%) rename generate/{ => combyne}/templates/struct_content.cc (100%) rename generate/{ => combyne}/templates/struct_header.h (100%) rename generate/{ => input}/callbacks.json (100%) rename generate/{ => input}/descriptor.json (100%) rename generate/{missing-tests-ignore.json => input/ignored-missing-tests.json} (100%) rename generate/{ => input}/libgit2-supplement.json (100%) rename generate/{ => input}/v0.21.2.json (100%) delete mode 100644 generate/missing-tests.js create mode 100644 generate/scripts/generateJson.js create mode 100644 generate/scripts/generateMissingTests.js create mode 100644 generate/scripts/generateNativeCode.js rename generate/{utils.js => scripts/helpers.js} (63%) create mode 100644 generate/scripts/utils.js delete mode 100644 generate/setup.js delete mode 100644 generate/util/file.js diff --git a/.gitignore b/.gitignore index 5188a2e6a..48f8535aa 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,10 @@ /vendor/*.filters /vendor/*.sln -/generate/idefs.json +/generate/output +/generate/**/*.json +!/generate/input/*.json + /generate/missing-tests.json /binding.gyp diff --git a/generate/filters/and.js b/generate/combyne/filters/and.js similarity index 100% rename from generate/filters/and.js rename to generate/combyne/filters/and.js diff --git a/generate/filters/args_info.js b/generate/combyne/filters/args_info.js similarity index 100% rename from generate/filters/args_info.js rename to generate/combyne/filters/args_info.js diff --git a/generate/filters/cpp_to_v8.js b/generate/combyne/filters/cpp_to_v8.js similarity index 100% rename from generate/filters/cpp_to_v8.js rename to generate/combyne/filters/cpp_to_v8.js diff --git a/generate/filters/default_value.js b/generate/combyne/filters/default_value.js similarity index 100% rename from generate/filters/default_value.js rename to generate/combyne/filters/default_value.js diff --git a/generate/filters/fields_info.js b/generate/combyne/filters/fields_info.js similarity index 100% rename from generate/filters/fields_info.js rename to generate/combyne/filters/fields_info.js diff --git a/generate/filters/has_return_type.js b/generate/combyne/filters/has_return_type.js similarity index 100% rename from generate/filters/has_return_type.js rename to generate/combyne/filters/has_return_type.js diff --git a/generate/filters/has_returns.js b/generate/combyne/filters/has_returns.js similarity index 100% rename from generate/filters/has_returns.js rename to generate/combyne/filters/has_returns.js diff --git a/generate/filters/is_double_pointer.js b/generate/combyne/filters/is_double_pointer.js similarity index 100% rename from generate/filters/is_double_pointer.js rename to generate/combyne/filters/is_double_pointer.js diff --git a/generate/filters/is_pointer.js b/generate/combyne/filters/is_pointer.js similarity index 100% rename from generate/filters/is_pointer.js rename to generate/combyne/filters/is_pointer.js diff --git a/generate/filters/is_v8_value.js b/generate/combyne/filters/is_v8_value.js similarity index 100% rename from generate/filters/is_v8_value.js rename to generate/combyne/filters/is_v8_value.js diff --git a/generate/filters/js_args_count.js b/generate/combyne/filters/js_args_count.js similarity index 100% rename from generate/filters/js_args_count.js rename to generate/combyne/filters/js_args_count.js diff --git a/generate/filters/or.js b/generate/combyne/filters/or.js similarity index 100% rename from generate/filters/or.js rename to generate/combyne/filters/or.js diff --git a/generate/filters/payload_for.js b/generate/combyne/filters/payload_for.js similarity index 100% rename from generate/filters/payload_for.js rename to generate/combyne/filters/payload_for.js diff --git a/generate/filters/replace.js b/generate/combyne/filters/replace.js similarity index 100% rename from generate/filters/replace.js rename to generate/combyne/filters/replace.js diff --git a/generate/filters/returns_count.js b/generate/combyne/filters/returns_count.js similarity index 100% rename from generate/filters/returns_count.js rename to generate/combyne/filters/returns_count.js diff --git a/generate/filters/returns_info.js b/generate/combyne/filters/returns_info.js similarity index 100% rename from generate/filters/returns_info.js rename to generate/combyne/filters/returns_info.js diff --git a/generate/filters/title_case.js b/generate/combyne/filters/title_case.js similarity index 100% rename from generate/filters/title_case.js rename to generate/combyne/filters/title_case.js diff --git a/generate/filters/un_pointer.js b/generate/combyne/filters/un_pointer.js similarity index 100% rename from generate/filters/un_pointer.js rename to generate/combyne/filters/un_pointer.js diff --git a/generate/filters/upper.js b/generate/combyne/filters/upper.js similarity index 100% rename from generate/filters/upper.js rename to generate/combyne/filters/upper.js diff --git a/generate/manual/include/functions/copy.h b/generate/combyne/manual/include/functions/copy.h similarity index 100% rename from generate/manual/include/functions/copy.h rename to generate/combyne/manual/include/functions/copy.h diff --git a/generate/manual/include/macros.h b/generate/combyne/manual/include/macros.h similarity index 100% rename from generate/manual/include/macros.h rename to generate/combyne/manual/include/macros.h diff --git a/generate/manual/include/wrapper.h b/generate/combyne/manual/include/wrapper.h similarity index 100% rename from generate/manual/include/wrapper.h rename to generate/combyne/manual/include/wrapper.h diff --git a/generate/manual/src/functions/copy.cc b/generate/combyne/manual/src/functions/copy.cc similarity index 100% rename from generate/manual/src/functions/copy.cc rename to generate/combyne/manual/src/functions/copy.cc diff --git a/generate/manual/src/wrapper.cc b/generate/combyne/manual/src/wrapper.cc similarity index 100% rename from generate/manual/src/wrapper.cc rename to generate/combyne/manual/src/wrapper.cc diff --git a/generate/partials/async_function.cc b/generate/combyne/partials/async_function.cc similarity index 100% rename from generate/partials/async_function.cc rename to generate/combyne/partials/async_function.cc diff --git a/generate/partials/convert_from_v8.cc b/generate/combyne/partials/convert_from_v8.cc similarity index 100% rename from generate/partials/convert_from_v8.cc rename to generate/combyne/partials/convert_from_v8.cc diff --git a/generate/partials/convert_to_v8.cc b/generate/combyne/partials/convert_to_v8.cc similarity index 100% rename from generate/partials/convert_to_v8.cc rename to generate/combyne/partials/convert_to_v8.cc diff --git a/generate/partials/doc.cc b/generate/combyne/partials/doc.cc similarity index 100% rename from generate/partials/doc.cc rename to generate/combyne/partials/doc.cc diff --git a/generate/partials/field_accessors.cc b/generate/combyne/partials/field_accessors.cc similarity index 100% rename from generate/partials/field_accessors.cc rename to generate/combyne/partials/field_accessors.cc diff --git a/generate/partials/fields.cc b/generate/combyne/partials/fields.cc similarity index 100% rename from generate/partials/fields.cc rename to generate/combyne/partials/fields.cc diff --git a/generate/partials/guard_arguments.cc b/generate/combyne/partials/guard_arguments.cc similarity index 100% rename from generate/partials/guard_arguments.cc rename to generate/combyne/partials/guard_arguments.cc diff --git a/generate/partials/sync_function.cc b/generate/combyne/partials/sync_function.cc similarity index 100% rename from generate/partials/sync_function.cc rename to generate/combyne/partials/sync_function.cc diff --git a/generate/templates/binding.gyp b/generate/combyne/templates/binding.gyp similarity index 100% rename from generate/templates/binding.gyp rename to generate/combyne/templates/binding.gyp diff --git a/generate/templates/class_content.cc b/generate/combyne/templates/class_content.cc similarity index 100% rename from generate/templates/class_content.cc rename to generate/combyne/templates/class_content.cc diff --git a/generate/templates/class_header.h b/generate/combyne/templates/class_header.h similarity index 100% rename from generate/templates/class_header.h rename to generate/combyne/templates/class_header.h diff --git a/generate/templates/enums.js b/generate/combyne/templates/enums.js similarity index 100% rename from generate/templates/enums.js rename to generate/combyne/templates/enums.js diff --git a/generate/templates/nodegit.cc b/generate/combyne/templates/nodegit.cc similarity index 100% rename from generate/templates/nodegit.cc rename to generate/combyne/templates/nodegit.cc diff --git a/generate/templates/struct_content.cc b/generate/combyne/templates/struct_content.cc similarity index 100% rename from generate/templates/struct_content.cc rename to generate/combyne/templates/struct_content.cc diff --git a/generate/templates/struct_header.h b/generate/combyne/templates/struct_header.h similarity index 100% rename from generate/templates/struct_header.h rename to generate/combyne/templates/struct_header.h diff --git a/generate/index.js b/generate/index.js index a70bca618..536dce70a 100644 --- a/generate/index.js +++ b/generate/index.js @@ -1,142 +1,3 @@ -const path = require("path"); -const combyne = require("combyne"); -const file = require("./util/file"); -const idefs = require("./idefs"); -const promisify = require("promisify-node"); -const fse = promisify(require("fs-extra")); -const js_beautify = require('js-beautify').js_beautify; -const beautify = function (input) { - return js_beautify(input, { - "brace_style": "end-expand", - "max_preserve_newlines": 2, - "preserve_newlines": true, - "indent_size": 2, - "indent_char": " " - }); -} - - -var exec = promisify(function(command, opts, callback) { - return require("child_process").exec(command, opts, callback); -}); - -// Customize the delimiters so as to not process `{{{` or `}}}`. -combyne.settings.delimiters = { - START_RAW: "{{=", - END_RAW: "=}}" -}; - -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"), - fieldAccessors: file.read("partials/field_accessors.cc") -}; - -var templates = { - class_content: file.read("templates/class_content.cc"), - struct_content: file.read("templates/struct_content.cc"), - class_header: file.read("templates/class_header.h"), - struct_header: file.read("templates/struct_header.h"), - binding: file.read("templates/binding.gyp"), - nodegit: file.read("templates/nodegit.cc"), - enums: file.read("templates/enums.js") -}; - -var filters = { - upper: require("./filters/upper"), - replace: require("./filters/replace"), - titleCase: require("./filters/title_case"), - 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"), - payloadFor: require("./filters/payload_for"), - 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") -}; - -// 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]); - }); -}); - -// Attach all partials to select templates. -Object.keys(partials).forEach(function(partial) { - templates.class_content.registerPartial(partial, combyne(partials[partial])); - templates.struct_content.registerPartial(partial, combyne(partials[partial])); -}); - - -// Determine which definitions to actually include in the source code. -// This might not be needed anymore but to be frank I'm not totally positive -var enabled = idefs.filter(function(idef) { - return !idef.ignore; -}); - -fse.remove(path.resolve(__dirname, "../src")).then(function() { - return fse.remove(path.resolve(__dirname, "../include")); -}).then(function() { - return fse.copy(path.resolve(__dirname, "./manual/"), path.resolve(__dirname, "../")); -}).then(function() { - // Write out single purpose templates. - file.write("../binding.gyp", beautify(templates.binding.render(enabled))); - file.write("../src/nodegit.cc", templates.nodegit.render(enabled)); - - - // Write out all the classes. - enabled.forEach(function(idef) { - try { - if (idef.type == "struct") { - file.write("../src/" + idef.filename + ".cc", templates.struct_content.render(idef)); - file.write("../include/" + idef.filename + ".h", templates.struct_header.render(idef)); - } - else if (idef.type == "class") { - file.write("../src/" + idef.filename + ".cc", templates.class_content.render(idef)); - file.write("../include/" + idef.filename + ".h", templates.class_header.render(idef)); - } - } - catch (e) { - if (process.env.BUILD_ONLY) { - console.log(e); - } - } - }); - - - file.write("../lib/enums.js", beautify(templates.enums.render(enabled))); -}).then(function() { - return exec('command -v astyle').then(function(astyle) { - if (astyle) { - return exec( - 'astyle --options=\".astylerc\" ' - + path.resolve(__dirname, "../src") + "/*.cc " - + path.resolve(__dirname, "../include") + "/*.h" - ).then(function() { - return exec( - 'rm ' - + path.resolve(__dirname, "../src") + "/*.cc.orig " - + path.resolve(__dirname, "../include") + "/*.h.orig " - ); - }); - } - }) -}); +require("./scripts/generateJson")(); +require("./scripts/generateNativeCode")(); +require("./scripts/generateMissingTests")(); diff --git a/generate/callbacks.json b/generate/input/callbacks.json similarity index 100% rename from generate/callbacks.json rename to generate/input/callbacks.json diff --git a/generate/descriptor.json b/generate/input/descriptor.json similarity index 100% rename from generate/descriptor.json rename to generate/input/descriptor.json diff --git a/generate/missing-tests-ignore.json b/generate/input/ignored-missing-tests.json similarity index 100% rename from generate/missing-tests-ignore.json rename to generate/input/ignored-missing-tests.json diff --git a/generate/libgit2-supplement.json b/generate/input/libgit2-supplement.json similarity index 100% rename from generate/libgit2-supplement.json rename to generate/input/libgit2-supplement.json diff --git a/generate/v0.21.2.json b/generate/input/v0.21.2.json similarity index 100% rename from generate/v0.21.2.json rename to generate/input/v0.21.2.json diff --git a/generate/missing-tests.js b/generate/missing-tests.js deleted file mode 100644 index 339f1a217..000000000 --- a/generate/missing-tests.js +++ /dev/null @@ -1,64 +0,0 @@ -const path = require("path"); -const idefs = require("./idefs"); -const Promise = require("nodegit-promise"); -const promisify = require("promisify-node"); -const fse = promisify(require("fs-extra")); -const testFilesPath = path.resolve(__dirname, "../test/tests"); -const missingFileIgnores = require("./missing-tests-ignore"); - -var output = {}; - -function findMissingTest(idef) { - var testFilePath = path.join(testFilesPath, idef.filename + ".js"); - var result = {}; - - return fse.readFile(testFilePath, "utf8") - .then(function(file) { - var fieldsResult = []; - var functionsResult = []; - var fieldIgnores = (missingFileIgnores[idef.filename] || {}).fields; - var functionIgnores = (missingFileIgnores[idef.filename] || {}).functions; - - fieldIgnores = fieldIgnores || []; - functionIgnores = functionIgnores || []; - file = file || ""; - - idef.fields.forEach(function(field) { - if (file.indexOf(field.jsFunctionName) < 0 - && fieldIgnores.indexOf(field.jsFunctionName < 0)) { - fieldsResult.push(field.jsFunctionName); - } - }); - - result.fields = fieldsResult; - - idef.functions.forEach(function(fn) { - if (file.indexOf(fn.jsFunctionName) < 0 - && functionIgnores.indexOf(fn.jsFunctionName) < 0) { - functionsResult.push(fn.jsFunctionName); - } - }); - - result.functions = functionsResult; - }, - function() { - result.testFileMissing = false; - result.testFilePath = testFilePath; - }).then(function() { - output[idef.filename] = result; - }); -}; - -var promises = []; - -idefs.forEach(function(idef) { - promises.push(findMissingTest(idef)); -}); - -Promise.all(promises) -.then(function() { - fse.writeFileSync(path.join(__dirname, "missing-tests.json"), - JSON.stringify(output, null, 2)); -}, function(fail) { - console.log(fail); -}); diff --git a/generate/scripts/generateJson.js b/generate/scripts/generateJson.js new file mode 100644 index 000000000..4bf029587 --- /dev/null +++ b/generate/scripts/generateJson.js @@ -0,0 +1,222 @@ +const fs = require("fs"); +const path = require("path"); +const helpers = require("./helpers"); +const utils = require("./utils"); +const _ = require("lodash"); + +var version = require("../../package.json").libgit2.version; +var libgit2 = require("../input/v" + version + ".json"); +var descriptor = require("../input/descriptor.json"); + var supplement = require("../input/libgit2-supplement.json"); + +module.exports = function() { + libgit2.types.forEach(function(type) { + if (supplement.types[type[0]]){ + _.merge(type[1], supplement.types[type[0]]); + } + }); + + // libgit2's docs aren't complete so we'll add in what they're missing here + Array.prototype.push.apply(libgit2.types, supplement.new.types); + Array.prototype.push.apply(libgit2.groups, supplement.new.groups); + + var output = []; + var dependencyLookup = {}; + var types = []; + var enums = []; + + // reduce all of the groups into a hashmap and a name array for easy lookup + var groups = libgit2.groups.reduce(function(memo, group) { + var groupName = group[0]; + + // Some functions are in the wrong group so we can't just ignore them. + // We have to completely remove them from one group and manually add them + // into the other. + var functionNames = group[1].filter(function(fnName) { + return !supplement.remove[groupName] || + !supplement.remove[groupName].functions || + !~supplement.remove[groupName].functions.indexOf(fnName); + }); + + memo[groupName] = functionNames; + return memo; + }, {}); + + + // Split each type from the array into classes/structs and enums + // each entry is of type ['name', {definingobject}] + libgit2.types.forEach(function(current) { + current[1].typeName = current[0]; + + // just log these out to a file for fun + if (current[1].type === "enum") { + enums.push(current[1]); + } + else { + types.push(current[1]); + } + }); + + var previous = ""; + enums = _(enums).sortBy("name").reduce(function(enumMemo, enumerable) { + if (previous == enumerable.typeName) { + if (process.env.BUILD_ONLY) { + console.warn('Duplicate definition for enum ' + enumerable.typeName + + ". skipped."); + } + } + else if (!enumerable.fields) { + if (process.env.BUILD_ONLY) { + console.warn('Incomplete definition for enum ' + enumerable.typeName + + ". skipped."); + } + } + else { + enumMemo[enumerable.typeName] = { + typeName: enumerable.typeName.replace(/^git_/, "").replace(/_t$/, ""), + type: "enum", + cType: enumerable.typeName, + isMask: (/_t$/).test(enumerable.typeName), + values: enumerable.fields.map(function(field) { + return { + name: field.name, + value: field.value + } + }) + }; + } + + previous = enumerable.typeName; + return enumMemo; + }, {}).valueOf(); + + // decorate the definitions with required data to build the C++ files + types.forEach(function(typeDef) { + var typeName = typeDef.typeName; + typeDef.cType = typeName; + typeName = typeName.replace("git_", ""); + typeDef.typeName = typeName; + dependencyLookup[typeName] = typeName; + + typeDef.functions = groups[typeName] || []; + helpers.decoratePrimaryType(typeDef, enums); + + groups[typeName] = false; + + typeDef.type = typeDef.hasConstructor ? "struct" : "class"; + + output.push(typeDef); + }); + + // Loop over the groups in case we missed anything (eg the types are missing in the docs); + for (var groupName in groups) { + var groupDef = groups[groupName]; + if (groupDef === false) { + continue; + } + + groupDef = { + functions: groupDef + }; + + groupDef.type = "class"; + groupDef.cType = (descriptor.types[groupName] || {}).cType || groupDef.cType; + + groupDef.typeName = groupName; + dependencyLookup[groupName] = groupName; + helpers.decoratePrimaryType(groupDef, enums); + + output.push(groupDef); + } + + // Calculate dependencies + output.forEach(function (def) { + if (def.ignore) { + return; + } + + var dependencies = {}; + var addDependencies = function (prop) { + if (prop.ignore) { + return; + } + + var type = helpers.normalizeCtype(prop.type || prop.cType).replace("git_", ""); + var dependencyFilename = dependencyLookup[type]; + + if (dependencyFilename) { + dependencies[dependencyFilename] = dependencyFilename; + } + + (prop.args || []).forEach(addDependencies); + + if (prop.return) { + addDependencies(prop.return); + } + }; + + def.fields.forEach(addDependencies); + def.functions.forEach(addDependencies); + + Object.keys(dependencies).forEach(function (dependencyFilename) { + def.dependencies.push("../include/" + dependencyFilename + ".h"); + }); + + // Additionally provide a friendly name to the actual filename. + def.name = path.basename(def.filename, ".h"); + + def.functions.forEach(function(fn) { + fn.cppClassName = def.cppClassName; + }); + }); + + // Process enums + _(enums).forEach(function(enumerable) { + output.some(function(obj) { + if (enumerable.typeName.indexOf(obj.typeName) == 0) { + enumerable.owner = obj.jsClassName; + } + else if (enumerable.owner) { + return true; + } + }); + + var override = descriptor.enums[enumerable.typeName] || {}; + + enumerable.owner = override.owner || enumerable.owner || "Enums"; + + enumerable.JsName = enumerable.typeName + .replace(new RegExp("^" + enumerable.owner.toLowerCase()), "") + .replace(/^_/, "") + .toUpperCase(); + + enumerable.values.forEach(function(value) { + value.JsName = value.name + .replace(/^GIT_/, "") + .replace(override.removeString || "", "") + .replace(new RegExp("^" + enumerable.owner.toUpperCase()), "") + .replace(/^_/, "") + .replace(new RegExp("^" + enumerable.JsName), "") + .replace(/^_/, "") + .toUpperCase(); + + if (override.values && override.values[value.name]) { + _.merge(value, override.values[value.name]); + } + }); + + _.merge(enumerable, _.omit(override, ["values"])); + + output.push(enumerable); + }); + + output = _.sortBy(output, "typeName"); + + if (process.argv[2] != "--documentation") { + helpers.filterDocumentation(output); + } + + + utils.writeFile("output/idefs.json", output); + +} diff --git a/generate/scripts/generateMissingTests.js b/generate/scripts/generateMissingTests.js new file mode 100644 index 000000000..6dfc06539 --- /dev/null +++ b/generate/scripts/generateMissingTests.js @@ -0,0 +1,73 @@ +const path = require("path"); +const Promise = require("nodegit-promise"); +const promisify = require("promisify-node"); +const fse = promisify(require("fs-extra")); +const utils = require("./utils"); + +const testFilesPath = "../test/tests"; +const idefs = require("../output/idefs"); +const missingFileIgnores = require("../input/ignored-missing-tests"); + +module.exports = function() { + var output = {}; + + function findMissingTest(idef) { + return new Promise(function(resolve, reject) { + var testFilePath = path.join(testFilesPath, idef.filename + ".js"); + var result = {}; + + var file = utils.readFile(testFilePath); + if (file) { + var fieldsResult = []; + var functionsResult = []; + var fieldIgnores = (missingFileIgnores[idef.filename] || {}).fields; + var functionIgnores = (missingFileIgnores[idef.filename] || {}).functions; + + fieldIgnores = fieldIgnores || []; + functionIgnores = functionIgnores || []; + file = file || ""; + + idef.fields.forEach(function(field) { + if (file.indexOf(field.jsFunctionName) < 0 + && fieldIgnores.indexOf(field.jsFunctionName < 0)) { + fieldsResult.push(field.jsFunctionName); + } + }); + + result.fields = fieldsResult; + + idef.functions.forEach(function(fn) { + if (file.indexOf(fn.jsFunctionName) < 0 + && functionIgnores.indexOf(fn.jsFunctionName) < 0) { + functionsResult.push(fn.jsFunctionName); + } + }); + + result.functions = functionsResult; + } + else { + result.testFileMissing = false; + result.testFilePath = testFilePath; + } + + output[idef.filename] = result; + resolve(); + }); + }; + + var promises = []; + + idefs.forEach(function(idef) { + promises.push(findMissingTest(idef)); + }); + + Promise.all(promises).then( + function() { + utils.writeFile("output/missing-tests.json", output); + }, + function(fail) { + console.log(fail); + } + ); + +} diff --git a/generate/scripts/generateNativeCode.js b/generate/scripts/generateNativeCode.js new file mode 100644 index 000000000..0a476de61 --- /dev/null +++ b/generate/scripts/generateNativeCode.js @@ -0,0 +1,146 @@ +const path = require("path"); +const combyne = require("combyne"); +const promisify = require("promisify-node"); +const fse = promisify(require("fs-extra")); +const js_beautify = require('js-beautify').js_beautify; +const beautify = function (input) { + return js_beautify(input, { + "brace_style": "end-expand", + "max_preserve_newlines": 2, + "preserve_newlines": true, + "indent_size": 2, + "indent_char": " " + }); +} +const exec = promisify(function(command, opts, callback) { + return require("child_process").exec(command, opts, callback); +}); + + +const utils = require("./utils"); +const idefs = require("../output/idefs"); + +module.exports = function() { + // Customize the delimiters so as to not process `{{{` or `}}}`. + combyne.settings.delimiters = { + START_RAW: "{{=", + END_RAW: "=}}" + }; + + var partials = { + asyncFunction: utils.readFile("combyne/partials/async_function.cc"), + convertFromV8: utils.readFile("combyne/partials/convert_from_v8.cc"), + convertToV8: utils.readFile("combyne/partials/convert_to_v8.cc"), + doc: utils.readFile("combyne/partials/doc.cc"), + fields: utils.readFile("combyne/partials/fields.cc"), + guardArguments: utils.readFile("combyne/partials/guard_arguments.cc"), + syncFunction: utils.readFile("combyne/partials/sync_function.cc"), + fieldAccessors: utils.readFile("combyne/partials/field_accessors.cc") + }; + + var templates = { + class_content: utils.readFile("combyne/templates/class_content.cc"), + struct_content: utils.readFile("combyne/templates/struct_content.cc"), + class_header: utils.readFile("combyne/templates/class_header.h"), + struct_header: utils.readFile("combyne/templates/struct_header.h"), + binding: utils.readFile("combyne/templates/binding.gyp"), + nodegit: utils.readFile("combyne/templates/nodegit.cc"), + enums: utils.readFile("combyne/templates/enums.js") + }; + + var filters = { + upper: require("../combyne/filters/upper"), + replace: require("../combyne/filters/replace"), + titleCase: require("../combyne/filters/title_case"), + or: require("../combyne/filters/or"), + and: require("../combyne/filters/and"), + defaultValue: require("../combyne/filters/default_value"), + argsInfo: require("../combyne/filters/args_info"), + cppToV8: require("../combyne/filters/cpp_to_v8"), + jsArgsCount: require("../combyne/filters/js_args_count"), + isV8Value: require("../combyne/filters/is_v8_value"), + isPointer: require("../combyne/filters/is_pointer"), + isDoublePointer: require("../combyne/filters/is_double_pointer"), + unPointer: require("../combyne/filters/un_pointer"), + payloadFor: require("../combyne/filters/payload_for"), + hasReturnType: require("../combyne/filters/has_return_type"), + hasReturns: require("../combyne/filters/has_returns"), + returnsCount: require("../combyne/filters/returns_count"), + returnsInfo: require("../combyne/filters/returns_info"), + fieldsInfo: require("../combyne/filters/fields_info") + }; + + // 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]); + }); + }); + + // Attach all partials to select templates. + Object.keys(partials).forEach(function(partial) { + templates.class_content.registerPartial(partial, combyne(partials[partial])); + templates.struct_content.registerPartial(partial, combyne(partials[partial])); + }); + + + // Determine which definitions to actually include in the source code. + // This might not be needed anymore but to be frank I'm not totally positive + var enabled = idefs.filter(function(idef) { + return !idef.ignore; + }); + + + fse.remove(path.resolve(__dirname, "../../src")).then(function() { + return fse.remove(path.resolve(__dirname, "../../include")); + }).then(function() { + return fse.copy(path.resolve(__dirname, "../combyne/manual/"), path.resolve(__dirname, "../../")); + }).then(function() { + // Write out single purpose templates. + utils.writeFile("../binding.gyp", beautify(templates.binding.render(enabled))); + utils.writeFile("../src/nodegit.cc", templates.nodegit.render(enabled)); + + + // Write out all the classes. + enabled.forEach(function(idef) { + try { + if (idef.type == "struct") { + utils.writeFile("../src/" + idef.filename + ".cc", templates.struct_content.render(idef)); + utils.writeFile("../include/" + idef.filename + ".h", templates.struct_header.render(idef)); + } + else if (idef.type == "class") { + utils.writeFile("../src/" + idef.filename + ".cc", templates.class_content.render(idef)); + utils.writeFile("../include/" + idef.filename + ".h", templates.class_header.render(idef)); + } + } + catch (e) { + if (process.env.BUILD_ONLY) { + console.log(e); + } + } + }); + + + utils.writeFile("../lib/enums.js", beautify(templates.enums.render(enabled))); + }).then(function() { + return exec('command -v astyle').then(function(astyle) { + if (astyle) { + return exec( + 'astyle --options=\".astylerc\" ' + + path.resolve(__dirname, "../../src") + "/*.cc " + + path.resolve(__dirname, "../../include") + "/*.h" + ).then(function() { + return exec( + 'rm ' + + path.resolve(__dirname, "../../src") + "/*.cc.orig " + + path.resolve(__dirname, "../../include") + "/*.h.orig " + ); + }); + } + }) + }); + +} diff --git a/generate/utils.js b/generate/scripts/helpers.js similarity index 63% rename from generate/utils.js rename to generate/scripts/helpers.js index 24f612d8b..2386461bd 100644 --- a/generate/utils.js +++ b/generate/scripts/helpers.js @@ -1,13 +1,15 @@ -var pointerRegex = /\s*\*\s*/; -var doublePointerRegex = /\s*\*\*\s*/; + var callbackTypePattern = /\s*_cb/; + +var utils = require("./utils"); var _ = require("lodash"); // TODO: When libgit2's docs include callbacks we should be able to remove this -var callbackDefs = require("./callbacks.json"); -var descriptor = require("./descriptor.json"); -var version = require("../package.json").libgit2.version; -var libgit2 = require("./v" + version + ".json"); +var version = require("../../package.json").libgit2.version; +var callbackDefs = require("../input/callbacks.json"); +var descriptor = require("../input/descriptor.json"); +var libgit2 = require("../input/v" + version + ".json"); + var cTypes = libgit2.groups.map(function(group) { return group[0];}); var cTypeMappings = { @@ -27,61 +29,35 @@ var collisionMappings = { "new": "create" } -var Utils = { - titleCase: function(str) { - return str.split(/_|\//).map(function(val, index) { - if (val.length) { - return val[0].toUpperCase() + val.slice(1); - } - - return val; - }).join(""); - }, - - camelCase: function(str) { - return str.split(/_|\//).map(function(val, index) { - return (index >= 1 - ? val[0].toUpperCase() + val.slice(1) - : val[0].toLowerCase() + val.slice(1)); - }).join(""); - }, - - isPointer: function(cType) { - return pointerRegex.test(cType) || doublePointerRegex.test(cType); - }, - - isDoublePointer: function(cType) { - return doublePointerRegex.test(cType); - }, - +var Helpers = { normalizeCtype: function(cType) { return (cType || "") .toLowerCase() .replace("const ", "") .replace("unsigned ", "") .replace("struct", "") - .replace(doublePointerRegex, "") - .replace(pointerRegex, "") + .replace(utils.doublePointerRegex, "") + .replace(utils.pointerRegex, "") .trim(); }, cTypeToCppName: function(cType, ownerType) { - var normalizedType = Utils.normalizeCtype(cType); + var normalizedType = Helpers.normalizeCtype(cType); if (ownerType && normalizedType != ownerType) { normalizedType = normalizedType.replace(ownerType, ""); } - return cTypeMappings[normalizedType] || Utils.titleCase(normalizedType); + return cTypeMappings[normalizedType] || utils.titleCase(normalizedType); }, cTypeToJsName: function(cType, ownerType) { - var output = Utils.camelCase(Utils.cTypeToCppName(cType, ownerType).replace(/^Git/, "")); + var output = utils.camelCase(Helpers.cTypeToCppName(cType, ownerType).replace(/^Git/, "")); var mergedPrefixes = ["from", "by"]; mergedPrefixes.forEach(function(prefix) { - var reg = new RegExp("(^" + prefix + "|" + Utils.titleCase(prefix) + ")([a-z]+)$"); + var reg = new RegExp("(^" + prefix + "|" + utils.titleCase(prefix) + ")([a-z]+)$"); output = output.replace(reg, function(all, prefixMatch, otherWord) { - return prefixMatch + Utils.titleCase(otherWord); + return prefixMatch + utils.titleCase(otherWord); }); }); @@ -102,7 +78,7 @@ var Utils = { return type.used && type.used.needs && type.used.needs.some(function (fnName) { - return Utils.isConstructorFunction(normalizedType, fnName); + return Helpers.isConstructorFunction(normalizedType, fnName); }); }, @@ -112,7 +88,7 @@ var Utils = { isPayloadFor: function(cbField, payloadName) { return ~payloadName.indexOf("_payload") - && Utils.isCallbackFunction(cbField.cType) + && Helpers.isCallbackFunction(cbField.cType) && ~cbField.name.indexOf(payloadName.replace("_payload", "")); }, @@ -150,7 +126,7 @@ var Utils = { var cbFieldName; allFields.some(function (cbField) { - if (Utils.isPayloadFor(cbField, field.name)) { + if (Helpers.isPayloadFor(cbField, field.name)) { cbFieldName = cbField.name; return true; } @@ -163,13 +139,13 @@ var Utils = { }, decorateLibgitType: function(type, types, enums) { - var normalizedType = Utils.normalizeCtype(type.cType); - var libgitType = Utils.getLibgitType(normalizedType, types); + var normalizedType = Helpers.normalizeCtype(type.cType); + var libgitType = Helpers.getLibgitType(normalizedType, types); if (libgitType) { type.isLibgitType = true; type.isEnum = libgitType.type === "enum"; - type.hasConstructor = Utils.hasConstructor(type, normalizedType); + type.hasConstructor = Helpers.hasConstructor(type, normalizedType); // there are no enums at the struct level currently, but we still need to override function args if (type.isEnum) { @@ -188,8 +164,8 @@ var Utils = { var partialOverrides = _.omit(typeDefOverrides, ["fields", "functions"]); typeDef.cType = typeDef.cType || null; - typeDef.cppClassName = Utils.cTypeToCppName(typeDef.cType || "git_" + typeDef.typeName); - typeDef.jsClassName = Utils.titleCase(Utils.cTypeToJsName(typeDef.cType || "git_" + typeDef.typeName)); + typeDef.cppClassName = Helpers.cTypeToCppName(typeDef.cType || "git_" + typeDef.typeName); + typeDef.jsClassName = utils.titleCase(Helpers.cTypeToJsName(typeDef.cType || "git_" + typeDef.typeName)); typeDef.filename = typeDef.typeName; typeDef.isLibgitType = true; typeDef.dependencies = []; @@ -197,13 +173,13 @@ var Utils = { typeDef.fields = typeDef.fields || []; typeDef.fields.forEach(function (field, index, allFields) { var fieldOverrides = typeDefOverrides.fields || {}; - Utils.decorateField(field, allFields, fieldOverrides[field.name] || {}, enums); + Helpers.decorateField(field, allFields, fieldOverrides[field.name] || {}, enums); }); typeDef.needsForwardDeclaration = typeDef.decl === typeDef.cType; - var normalizedType = Utils.normalizeCtype(typeDef.cType); - typeDef.hasConstructor = Utils.hasConstructor(typeDef, normalizedType); + var normalizedType = Helpers.normalizeCtype(typeDef.cType); + typeDef.hasConstructor = Helpers.hasConstructor(typeDef, normalizedType); typeDef.functions = (typeDef.functions).map(function(fn) { var fnDef = libgit2.functions[fn]; @@ -214,58 +190,58 @@ var Utils = { var typeDefOverrides = descriptor.types[typeDef.typeName] || {}; var functionOverrides = typeDefOverrides.functions || {}; typeDef.functions.forEach(function(fnDef) { - Utils.decorateFunction(fnDef, typeDef, functionOverrides[fnDef.cFunctionName] || {}, enums); + Helpers.decorateFunction(fnDef, typeDef, functionOverrides[fnDef.cFunctionName] || {}, enums); }); _.merge(typeDef, partialOverrides); }, decorateField: function(field, allFields, fieldOverrides, enums) { - var normalizeType = Utils.normalizeCtype(field.type); + var normalizeType = Helpers.normalizeCtype(field.type); field.cType = field.type; - field.cppFunctionName = Utils.titleCase(field.name); - field.jsFunctionName = Utils.camelCase(field.name); - field.cppClassName = Utils.cTypeToCppName(field.type); - field.jsClassName = Utils.titleCase(Utils.cTypeToJsName(field.type)); + field.cppFunctionName = utils.titleCase(field.name); + field.jsFunctionName = utils.camelCase(field.name); + field.cppClassName = Helpers.cTypeToCppName(field.type); + field.jsClassName = utils.titleCase(Helpers.cTypeToJsName(field.type)); - if (Utils.isCallbackFunction(field.cType)) { - Utils.processCallback(field); + if (Helpers.isCallbackFunction(field.cType)) { + Helpers.processCallback(field); var argOverrides = fieldOverrides.args || {}; field.args = field.args || []; field.args.forEach(function (arg) { - Utils.decorateArg(arg, null, null, argOverrides[arg.name] || {}, enums); + Helpers.decorateArg(arg, null, null, argOverrides[arg.name] || {}, enums); }); } else { field.isCallbackFunction = false; - Utils.processPayload(field, allFields); + Helpers.processPayload(field, allFields); if (field.payloadFor) { return; } } - Utils.decorateLibgitType(field, libgit2.types, enums); + Helpers.decorateLibgitType(field, libgit2.types, enums); _.merge(field, fieldOverrides); }, decorateArg: function(arg, typeDef, fnDef, argOverrides, enums) { var type = arg.cType || arg.type; - var normalizedType = Utils.normalizeCtype(type); + var normalizedType = Helpers.normalizeCtype(type); arg.cType = type; - arg.cppClassName = Utils.cTypeToCppName(arg.cType); - arg.jsClassName = Utils.titleCase(Utils.cTypeToJsName(arg.cType)); + arg.cppClassName = Helpers.cTypeToCppName(arg.cType); + arg.jsClassName = utils.titleCase(Helpers.cTypeToJsName(arg.cType)); - Utils.decorateLibgitType(arg, libgit2.types, enums); + Helpers.decorateLibgitType(arg, libgit2.types, enums); if (typeDef && fnDef) { // Mark all of the args that are either returns or are the object // itself and determine if this function goes on the prototype // or is a constructor method. - arg.isReturn = arg.name === "out" || (Utils.isDoublePointer(arg.type) && normalizedType == typeDef.cType); - arg.isSelf = Utils.isPointer(arg.type) && normalizedType == typeDef.cType; + arg.isReturn = arg.name === "out" || (utils.isDoublePointer(arg.type) && normalizedType == typeDef.cType); + arg.isSelf = utils.isPointer(arg.type) && normalizedType == typeDef.cType; if (arg.isReturn && fnDef.return && fnDef.return.type === "int") { fnDef.return.isErrorCode = true; @@ -296,8 +272,8 @@ var Utils = { return; } - fnDef.cppFunctionName = Utils.cTypeToCppName(key, "git_" + typeDef.typeName); - fnDef.jsFunctionName = Utils.cTypeToJsName(key, "git_" + typeDef.typeName); + fnDef.cppFunctionName = Helpers.cTypeToCppName(key, "git_" + typeDef.typeName); + fnDef.jsFunctionName = Helpers.cTypeToJsName(key, "git_" + typeDef.typeName); //fnDef.isAsync = false; // until proven otherwise if (fnDef.cppFunctionName == typeDef.cppClassName) { @@ -306,20 +282,20 @@ var Utils = { var argOverrides = fnOverrides.args || {}; fnDef.args.forEach(function(arg) { - Utils.decorateArg(arg, typeDef, fnDef, argOverrides[arg.name] || {}, enums); + Helpers.decorateArg(arg, typeDef, fnDef, argOverrides[arg.name] || {}, enums); }); if (fnDef.return) { - Utils.decorateArg(fnDef.return, typeDef, fnDef, fnOverrides.return || {}, enums); + Helpers.decorateArg(fnDef.return, typeDef, fnDef, fnOverrides.return || {}, enums); } _(collisionMappings).forEach(function(newName, collidingName) { - if (fnDef.cppFunctionName == Utils.titleCase(collidingName)) { - fnDef.cppFunctionName = Utils.titleCase(newName); + if (fnDef.cppFunctionName == utils.titleCase(collidingName)) { + fnDef.cppFunctionName = utils.titleCase(newName); } - if (fnDef.jsFunctionName == Utils.camelCase(collidingName)) { - fnDef.jsFunctionName = Utils.camelCase(newName); + if (fnDef.jsFunctionName == utils.camelCase(collidingName)) { + fnDef.jsFunctionName = utils.camelCase(newName); } }); @@ -354,17 +330,17 @@ var Utils = { }, filterDocumentation: function(idefs) { - Utils.filterIgnored(idefs, function (idef) { - Utils.deleteProperties(idef); + Helpers.filterIgnored(idefs, function (idef) { + Helpers.deleteProperties(idef); - Utils.filterIgnored(idef.fields, Utils.deleteProperties); + Helpers.filterIgnored(idef.fields, Helpers.deleteProperties); - Utils.filterIgnored(idef.functions, function (fn) { - Utils.deleteProperties(fn); + Helpers.filterIgnored(idef.functions, function (fn) { + Helpers.deleteProperties(fn); - Utils.filterIgnored(fn.args, function(arg) { - Utils.deleteProperties(arg); + Helpers.filterIgnored(fn.args, function(arg) { + Helpers.deleteProperties(arg); delete arg.functions; }); }); @@ -372,4 +348,4 @@ var Utils = { } }; -module.exports = Utils; +module.exports = Helpers; diff --git a/generate/scripts/utils.js b/generate/scripts/utils.js new file mode 100644 index 000000000..3395fe272 --- /dev/null +++ b/generate/scripts/utils.js @@ -0,0 +1,67 @@ +const promisify = require("promisify-node"); +const fse = require("fs-extra"); + +const fs = require("fs"); +const path = require("path"); + +// Make a locally bound path joiner, (bound to generate). +var local = path.join.bind(null, __dirname, "../"); + +var util = { + pointerRegex: /\s*\*\s*/, + doublePointerRegex: /\s*\*\*\s*/, + + readFile: function(file) { + try { + return fs.readFileSync(local(file)).toString(); + } + catch (unhandledException) { + return ""; + } + }, + + writeFile: function(file, content) { + try { + var file = local(file); + if (typeof content == "object") { + content = JSON.stringify(content, null, 2) + } + + fse.ensureFileSync(file); + fse.writeFileSync(file, content); + return true; + } + catch (exception) { + return false; + } + }, + + titleCase: function(str) { + return str.split(/_|\//).map(function(val, index) { + if (val.length) { + return val[0].toUpperCase() + val.slice(1); + } + + return val; + }).join(""); + }, + + camelCase: function(str) { + return str.split(/_|\//).map(function(val, index) { + return (index >= 1 + ? val[0].toUpperCase() + val.slice(1) + : val[0].toLowerCase() + val.slice(1)); + }).join(""); + }, + + isPointer: function(type) { + return util.pointerRegex.test(type) || util.doublePointerRegex.test(type); + }, + + isDoublePointer: function(type) { + return util.doublePointerRegex.test(type); + } + +}; + +module.exports = util; diff --git a/generate/setup.js b/generate/setup.js deleted file mode 100644 index 98cb3617f..000000000 --- a/generate/setup.js +++ /dev/null @@ -1,218 +0,0 @@ -const fs = require("fs"); -const path = require("path"); -const utils = require("./utils"); -const _ = require("lodash"); - -var version = require("../package.json").libgit2.version; -var descriptor = require("./descriptor.json"); -var libgit2 = require("./v" + version + ".json"); -var supplement = require("./libgit2-supplement.json"); - -libgit2.types.forEach(function(type) { - if (supplement.types[type[0]]){ - _.merge(type[1], supplement.types[type[0]]); - } -}); - -// libgit2's docs aren't complete so we'll add in what they're missing here -Array.prototype.push.apply(libgit2.types, supplement.new.types); -Array.prototype.push.apply(libgit2.groups, supplement.new.groups); - -var output = []; -var dependencyLookup = {}; -var types = []; -var enums = []; - -// reduce all of the groups into a hashmap and a name array for easy lookup -var groups = libgit2.groups.reduce(function(memo, group) { - var groupName = group[0]; - - // Some functions are in the wrong group so we can't just ignore them. - // We have to completely remove them from one group and manually add them - // into the other. - var functionNames = group[1].filter(function(fnName) { - return !supplement.remove[groupName] || - !supplement.remove[groupName].functions || - !~supplement.remove[groupName].functions.indexOf(fnName); - }); - - memo[groupName] = functionNames; - return memo; -}, {}); - - -// Split each type from the array into classes/structs and enums -// each entry is of type ['name', {definingobject}] -libgit2.types.forEach(function(current) { - current[1].typeName = current[0]; - - // just log these out to a file for fun - if (current[1].type === "enum") { - enums.push(current[1]); - } - else { - types.push(current[1]); - } -}); - -var previous = ""; -enums = _(enums).sortBy("name").reduce(function(enumMemo, enumerable) { - if (previous == enumerable.typeName) { - if (process.env.BUILD_ONLY) { - console.warn('Duplicate definition for enum ' + enumerable.typeName + - ". skipped."); - } - } - else if (!enumerable.fields) { - if (process.env.BUILD_ONLY) { - console.warn('Incomplete definition for enum ' + enumerable.typeName + - ". skipped."); - } - } - else { - enumMemo[enumerable.typeName] = { - typeName: enumerable.typeName.replace(/^git_/, "").replace(/_t$/, ""), - type: "enum", - cType: enumerable.typeName, - isMask: (/_t$/).test(enumerable.typeName), - values: enumerable.fields.map(function(field) { - return { - name: field.name, - value: field.value - } - }) - }; - } - - previous = enumerable.typeName; - return enumMemo; -}, {}).valueOf(); - -// decorate the definitions with required data to build the C++ files -types.forEach(function(typeDef) { - var typeName = typeDef.typeName; - typeDef.cType = typeName; - typeName = typeName.replace("git_", ""); - typeDef.typeName = typeName; - dependencyLookup[typeName] = typeName; - - typeDef.functions = groups[typeName] || []; - utils.decoratePrimaryType(typeDef, enums); - - groups[typeName] = false; - - typeDef.type = typeDef.hasConstructor ? "struct" : "class"; - - output.push(typeDef); -}); - -// Loop over the groups in case we missed anything (eg the types are missing in the docs); -for (var groupName in groups) { - var groupDef = groups[groupName]; - if (groupDef === false) { - continue; - } - - groupDef = { - functions: groupDef - }; - - groupDef.type = "class"; - groupDef.cType = (descriptor.types[groupName] || {}).cType || groupDef.cType; - - groupDef.typeName = groupName; - dependencyLookup[groupName] = groupName; - utils.decoratePrimaryType(groupDef, enums); - - output.push(groupDef); -} - -// Calculate dependencies -output.forEach(function (def) { - if (def.ignore) { - return; - } - - var dependencies = {}; - var addDependencies = function (prop) { - if (prop.ignore) { - return; - } - - var type = utils.normalizeCtype(prop.type || prop.cType).replace("git_", ""); - var dependencyFilename = dependencyLookup[type]; - - if (dependencyFilename) { - dependencies[dependencyFilename] = dependencyFilename; - } - - (prop.args || []).forEach(addDependencies); - - if (prop.return) { - addDependencies(prop.return); - } - }; - - def.fields.forEach(addDependencies); - def.functions.forEach(addDependencies); - - Object.keys(dependencies).forEach(function (dependencyFilename) { - def.dependencies.push("../include/" + dependencyFilename + ".h"); - }); - - // Additionally provide a friendly name to the actual filename. - def.name = path.basename(def.filename, ".h"); - - def.functions.forEach(function(fn) { - fn.cppClassName = def.cppClassName; - }); -}); - -// Process enums -_(enums).forEach(function(enumerable) { - output.some(function(obj) { - if (enumerable.typeName.indexOf(obj.typeName) == 0) { - enumerable.owner = obj.jsClassName; - } - else if (enumerable.owner) { - return true; - } - }); - - var override = descriptor.enums[enumerable.typeName] || {}; - - enumerable.owner = override.owner || enumerable.owner || "Enums"; - - enumerable.JsName = enumerable.typeName - .replace(new RegExp("^" + enumerable.owner.toLowerCase()), "") - .replace(/^_/, "") - .toUpperCase(); - - enumerable.values.forEach(function(value) { - value.JsName = value.name - .replace(/^GIT_/, "") - .replace(override.removeString || "", "") - .replace(new RegExp("^" + enumerable.owner.toUpperCase()), "") - .replace(/^_/, "") - .replace(new RegExp("^" + enumerable.JsName), "") - .replace(/^_/, "") - .toUpperCase(); - - if (override.values && override.values[value.name]) { - _.merge(value, override.values[value.name]); - } - }); - - _.merge(enumerable, _.omit(override, ["values"])); - - output.push(enumerable); -}); - -output = _.sortBy(output, "typeName"); - -if (process.argv[2] != "--documentation") { - utils.filterDocumentation(output); -} - -fs.writeFileSync(path.join(__dirname, "idefs.json"), - JSON.stringify(output, null, 2)); diff --git a/generate/util/file.js b/generate/util/file.js deleted file mode 100644 index c595a7687..000000000 --- a/generate/util/file.js +++ /dev/null @@ -1,24 +0,0 @@ -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 465f4a05f..f15260eb2 100644 --- a/package.json +++ b/package.json @@ -85,11 +85,12 @@ "cov": "node test", "mocha": "mocha test/runner test/tests", "test": "npm run lint && npm run cov", - "missing-tests": "node generate/missing-tests", + "generateJson": "node generate/scripts/generateJson", + "generateNativeCode": "node generate/scripts/generateNativeCode", + "generateMissingTests": "node generate/scripts/generateMissingTests", "publish": "node-pre-gyp package && node-pre-gyp publish", - "generate": "node generate/setup && node generate", - "install": "npm run generate && node install", + "install": "node generate && node install", "recompile": "BUILD_ONLY=true npm install", - "rebuild": "BUILD_ONLY=true npm run generate && node-gyp configure build" + "rebuild": "BUILD_ONLY=true node generate && node-gyp configure build" } }