Commit 504ba139 authored by Kyle Smith's avatar Kyle Smith

Generate script: Don't write .cc or .h files if unchanged

The generation script now checks whether the file has changed before writing it to `/src` or `/include`. This is to improve compilation time when testing changes to generated code.

It works by creating a `/temp` directory, writing the generated code to `/temp/src` and `/temp/include`, then syncing those folders with `/src` and `/include` by deleting files  that no longer exist and copying files that have changed or been added since the last code generation. Finally the `/temp` directory is deleted

If `/src` and `/include` don't exist (i.e. it's the first time the generation script has been run), `/temp/src` will be copied to `/src` and `/temp/include` will be copied to `/include`.
parent 3e065305
......@@ -6,6 +6,7 @@
/lib/nodegit.js
/node_modules/
/src/
/temp/
/test/coverage/
/test/home/
/test/repos/
......
......@@ -12,7 +12,7 @@ module.exports = function generateMissingTests() {
var testFilePath = path.join(testFilesPath, idef.filename + ".js");
var result = {};
var file = utils.readFile(testFilePath);
var file = utils.readLocalFile(testFilePath);
if (file) {
var fieldsResult = [];
var functionsResult = [];
......
......@@ -24,27 +24,27 @@ module.exports = function generateNativeCode() {
};
var partials = {
asyncFunction: utils.readFile("templates/partials/async_function.cc"),
callbackHelpers: utils.readFile("templates/partials/callback_helpers.cc"),
convertFromV8: utils.readFile("templates/partials/convert_from_v8.cc"),
convertToV8: utils.readFile("templates/partials/convert_to_v8.cc"),
doc: utils.readFile("templates/partials/doc.cc"),
fields: utils.readFile("templates/partials/fields.cc"),
guardArguments: utils.readFile("templates/partials/guard_arguments.cc"),
syncFunction: utils.readFile("templates/partials/sync_function.cc"),
fieldAccessors: utils.readFile("templates/partials/field_accessors.cc"),
traits: utils.readFile("templates/partials/traits.h")
asyncFunction: utils.readLocalFile("templates/partials/async_function.cc"),
callbackHelpers: utils.readLocalFile("templates/partials/callback_helpers.cc"),
convertFromV8: utils.readLocalFile("templates/partials/convert_from_v8.cc"),
convertToV8: utils.readLocalFile("templates/partials/convert_to_v8.cc"),
doc: utils.readLocalFile("templates/partials/doc.cc"),
fields: utils.readLocalFile("templates/partials/fields.cc"),
guardArguments: utils.readLocalFile("templates/partials/guard_arguments.cc"),
syncFunction: utils.readLocalFile("templates/partials/sync_function.cc"),
fieldAccessors: utils.readLocalFile("templates/partials/field_accessors.cc"),
traits: utils.readLocalFile("templates/partials/traits.h")
};
var templates = {
class_content: utils.readFile("templates/templates/class_content.cc"),
struct_content: utils.readFile("templates/templates/struct_content.cc"),
class_header: utils.readFile("templates/templates/class_header.h"),
struct_header: utils.readFile("templates/templates/struct_header.h"),
binding: utils.readFile("templates/templates/binding.gyp"),
nodegitCC: utils.readFile("templates/templates/nodegit.cc"),
nodegitJS: utils.readFile("templates/templates/nodegit.js"),
enums: utils.readFile("templates/templates/enums.js")
class_content: utils.readLocalFile("templates/templates/class_content.cc"),
struct_content: utils.readLocalFile("templates/templates/struct_content.cc"),
class_header: utils.readLocalFile("templates/templates/class_header.h"),
struct_header: utils.readLocalFile("templates/templates/struct_header.h"),
binding: utils.readLocalFile("templates/templates/binding.gyp"),
nodegitCC: utils.readLocalFile("templates/templates/nodegit.cc"),
nodegitJS: utils.readLocalFile("templates/templates/nodegit.js"),
enums: utils.readLocalFile("templates/templates/enums.js")
};
var filters = {
......@@ -99,28 +99,32 @@ module.exports = function generateNativeCode() {
return !idef.ignore;
});
const tempDirPath = path.resolve(__dirname, "../../temp");
const tempSrcDirPath = path.join(tempDirPath, "src");
const tempIncludeDirPath = path.join(tempDirPath, "include");
fse.remove(path.resolve(__dirname, "../../src")).then(function() {
return fse.remove(path.resolve(__dirname, "../../include"));
}).then(function() {
return fse.copy(path.resolve(__dirname, "../templates/manual/include"), path.resolve(__dirname, "../../include"));
const finalSrcDirPath = path.join(__dirname, '../../src');
const finalIncludeDirPath = path.join(__dirname, '../../include');
fse.remove(tempDirPath).then(function() {
return fse.copy(path.resolve(__dirname, "../templates/manual/include"), tempIncludeDirPath);
}).then(function() {
return fse.copy(path.resolve(__dirname, "../templates/manual/src"), path.resolve(__dirname, "../../src"));
return fse.copy(path.resolve(__dirname, "../templates/manual/src"), tempSrcDirPath);
}).then(function() {
// Write out single purpose templates.
utils.writeFile("../binding.gyp", beautify(templates.binding.render(enabled)), "binding.gyp");
utils.writeFile("../src/nodegit.cc", templates.nodegitCC.render(enabled), "nodegit.cc");
utils.writeFile("../temp/src/nodegit.cc", templates.nodegitCC.render(enabled), "nodegit.cc");
utils.writeFile("../lib/nodegit.js", beautify(templates.nodegitJS.render(enabled)), "nodegit.js");
// Write out all the classes.
enabled.forEach(function(idef) {
if (idef.type && idef.type != "enum") {
utils.writeFile(
"../src/" + idef.filename + ".cc",
"../temp/src/" + idef.filename + ".cc",
templates[idef.type + "_content"].render(idef),
idef.type + "_content.cc"
);
utils.writeFile(
"../include/" + idef.filename + ".h",
"../temp/include/" + idef.filename + ".h",
templates[idef.type + "_header"].render(idef),
idef.type + "_header.h"
);
......@@ -133,17 +137,24 @@ module.exports = function generateNativeCode() {
if (astyle) {
return exec(
"astyle --options=\".astylerc\" "
+ path.resolve(__dirname, "../../src") + "/*.cc "
+ path.resolve(__dirname, "../../include") + "/*.h"
+ tempSrcDirPath + "/*.cc "
+ tempIncludeDirPath + "/*.h"
).then(function() {
return exec(
"rm "
+ path.resolve(__dirname, "../../src") + "/*.cc.orig "
+ path.resolve(__dirname, "../../include") + "/*.h.orig "
+ tempSrcDirPath + "/*.cc.orig "
+ tempIncludeDirPath + "/*.h.orig "
);
});
}
}, function() {})
}).then(function() {
return Promise.all([
utils.syncDirs(tempSrcDirPath, finalSrcDirPath),
utils.syncDirs(tempIncludeDirPath, finalIncludeDirPath),
]);
}).then(function() {
return fse.remove(tempDirPath);
}).catch(console.log);
};
......
const fse = require("fs-extra");
const walk = require("walk");
const fs = require("fs");
const path = require("path");
......@@ -10,7 +11,7 @@ var util = {
pointerRegex: /\s*\*\s*/,
doublePointerRegex: /\s*\*\*\s*/,
readFile: function(file) {
readLocalFile: function(file) {
try {
return fs.readFileSync(local(file)).toString();
}
......@@ -19,6 +20,15 @@ var util = {
}
},
readFile: function(filePath) {
try {
return fs.readFileSync(filePath).toString();
}
catch (unhandledException) {
return "";
}
},
writeFile: function(file, content, header) {
try {
var file = local(file);
......@@ -62,14 +72,84 @@ var util = {
}).join("");
},
getFilePathsRelativeToDir: function(dir) {
const files = [];
const walker = walk.walk(dir, { followLinks: false });
if (!util.isDirectory(dir)) {
return Promise.resolve([]);
}
return new Promise(function(resolve, reject) {
walker.on('file', function(root, stat, next) {
files.push(path.relative(dir, path.join(root, stat.name)));
next();
});
walker.on('end', function() {
resolve(files);
});
walker.on('errors', function() {
reject();
});
});
},
isFile: function(path) {
var isFile;
try {
isFile = fse.statSync(path).isFile();
} catch(e) {
isFile = false;
}
return isFile;
},
isDirectory: function(path) {
var isDirectory;
try {
isDirectory = fse.statSync(path).isDirectory();
} catch(e) {
isDirectory = false;
}
return isDirectory;
},
isPointer: function(type) {
return util.pointerRegex.test(type) || util.doublePointerRegex.test(type);
},
isDoublePointer: function(type) {
return util.doublePointerRegex.test(type);
}
},
syncDirs: function(fromDir, toDir) {
return Promise.all([
util.getFilePathsRelativeToDir(toDir),
util.getFilePathsRelativeToDir(fromDir)
]).then(function(filePaths) {
const toFilePaths = filePaths[0];
const fromFilePaths = filePaths[1];
// Delete files that aren't in fromDir
toFilePaths.forEach(function(filePath) {
if (!util.isFile(path.join(fromDir, filePath))) {
fse.remove(path.join(toDir, filePath));
}
});
// Copy files that don't exist in toDir or have different contents
fromFilePaths.forEach(function(filePath) {
const toFilePath = path.join(toDir, filePath);
const fromFilePath = path.join(fromDir, filePath);
if (!util.isFile(toFilePath) || util.readFile(toFilePath) !== util.readFile(fromFilePath)) {
fse.copy(fromFilePath, toFilePath);
}
});
});
}
};
module.exports = util;
......@@ -52,7 +52,8 @@
"js-beautify": "~1.5.10",
"jshint": "~2.8.0",
"lcov-result-merger": "~1.0.2",
"mocha": "~2.3.4"
"mocha": "~2.3.4",
"walk": "^2.3.9"
},
"vendorDependencies": {
"libssh2": "1.7.0",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment