Skip to content

Commit 504ba13

Browse files
author
Kyle Smith
committed
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`.
1 parent 3e06530 commit 504ba13

File tree

5 files changed

+127
-34
lines changed

5 files changed

+127
-34
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
/lib/nodegit.js
77
/node_modules/
88
/src/
9+
/temp/
910
/test/coverage/
1011
/test/home/
1112
/test/repos/

generate/scripts/generateMissingTests.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module.exports = function generateMissingTests() {
1212
var testFilePath = path.join(testFilesPath, idef.filename + ".js");
1313
var result = {};
1414

15-
var file = utils.readFile(testFilePath);
15+
var file = utils.readLocalFile(testFilePath);
1616
if (file) {
1717
var fieldsResult = [];
1818
var functionsResult = [];

generate/scripts/generateNativeCode.js

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,27 @@ module.exports = function generateNativeCode() {
2424
};
2525

2626
var partials = {
27-
asyncFunction: utils.readFile("templates/partials/async_function.cc"),
28-
callbackHelpers: utils.readFile("templates/partials/callback_helpers.cc"),
29-
convertFromV8: utils.readFile("templates/partials/convert_from_v8.cc"),
30-
convertToV8: utils.readFile("templates/partials/convert_to_v8.cc"),
31-
doc: utils.readFile("templates/partials/doc.cc"),
32-
fields: utils.readFile("templates/partials/fields.cc"),
33-
guardArguments: utils.readFile("templates/partials/guard_arguments.cc"),
34-
syncFunction: utils.readFile("templates/partials/sync_function.cc"),
35-
fieldAccessors: utils.readFile("templates/partials/field_accessors.cc"),
36-
traits: utils.readFile("templates/partials/traits.h")
27+
asyncFunction: utils.readLocalFile("templates/partials/async_function.cc"),
28+
callbackHelpers: utils.readLocalFile("templates/partials/callback_helpers.cc"),
29+
convertFromV8: utils.readLocalFile("templates/partials/convert_from_v8.cc"),
30+
convertToV8: utils.readLocalFile("templates/partials/convert_to_v8.cc"),
31+
doc: utils.readLocalFile("templates/partials/doc.cc"),
32+
fields: utils.readLocalFile("templates/partials/fields.cc"),
33+
guardArguments: utils.readLocalFile("templates/partials/guard_arguments.cc"),
34+
syncFunction: utils.readLocalFile("templates/partials/sync_function.cc"),
35+
fieldAccessors: utils.readLocalFile("templates/partials/field_accessors.cc"),
36+
traits: utils.readLocalFile("templates/partials/traits.h")
3737
};
3838

3939
var templates = {
40-
class_content: utils.readFile("templates/templates/class_content.cc"),
41-
struct_content: utils.readFile("templates/templates/struct_content.cc"),
42-
class_header: utils.readFile("templates/templates/class_header.h"),
43-
struct_header: utils.readFile("templates/templates/struct_header.h"),
44-
binding: utils.readFile("templates/templates/binding.gyp"),
45-
nodegitCC: utils.readFile("templates/templates/nodegit.cc"),
46-
nodegitJS: utils.readFile("templates/templates/nodegit.js"),
47-
enums: utils.readFile("templates/templates/enums.js")
40+
class_content: utils.readLocalFile("templates/templates/class_content.cc"),
41+
struct_content: utils.readLocalFile("templates/templates/struct_content.cc"),
42+
class_header: utils.readLocalFile("templates/templates/class_header.h"),
43+
struct_header: utils.readLocalFile("templates/templates/struct_header.h"),
44+
binding: utils.readLocalFile("templates/templates/binding.gyp"),
45+
nodegitCC: utils.readLocalFile("templates/templates/nodegit.cc"),
46+
nodegitJS: utils.readLocalFile("templates/templates/nodegit.js"),
47+
enums: utils.readLocalFile("templates/templates/enums.js")
4848
};
4949

5050
var filters = {
@@ -99,28 +99,32 @@ module.exports = function generateNativeCode() {
9999
return !idef.ignore;
100100
});
101101

102+
const tempDirPath = path.resolve(__dirname, "../../temp");
103+
const tempSrcDirPath = path.join(tempDirPath, "src");
104+
const tempIncludeDirPath = path.join(tempDirPath, "include");
102105

103-
fse.remove(path.resolve(__dirname, "../../src")).then(function() {
104-
return fse.remove(path.resolve(__dirname, "../../include"));
105-
}).then(function() {
106-
return fse.copy(path.resolve(__dirname, "../templates/manual/include"), path.resolve(__dirname, "../../include"));
106+
const finalSrcDirPath = path.join(__dirname, '../../src');
107+
const finalIncludeDirPath = path.join(__dirname, '../../include');
108+
109+
fse.remove(tempDirPath).then(function() {
110+
return fse.copy(path.resolve(__dirname, "../templates/manual/include"), tempIncludeDirPath);
107111
}).then(function() {
108-
return fse.copy(path.resolve(__dirname, "../templates/manual/src"), path.resolve(__dirname, "../../src"));
112+
return fse.copy(path.resolve(__dirname, "../templates/manual/src"), tempSrcDirPath);
109113
}).then(function() {
110114
// Write out single purpose templates.
111115
utils.writeFile("../binding.gyp", beautify(templates.binding.render(enabled)), "binding.gyp");
112-
utils.writeFile("../src/nodegit.cc", templates.nodegitCC.render(enabled), "nodegit.cc");
116+
utils.writeFile("../temp/src/nodegit.cc", templates.nodegitCC.render(enabled), "nodegit.cc");
113117
utils.writeFile("../lib/nodegit.js", beautify(templates.nodegitJS.render(enabled)), "nodegit.js");
114118
// Write out all the classes.
115119
enabled.forEach(function(idef) {
116120
if (idef.type && idef.type != "enum") {
117121
utils.writeFile(
118-
"../src/" + idef.filename + ".cc",
122+
"../temp/src/" + idef.filename + ".cc",
119123
templates[idef.type + "_content"].render(idef),
120124
idef.type + "_content.cc"
121125
);
122126
utils.writeFile(
123-
"../include/" + idef.filename + ".h",
127+
"../temp/include/" + idef.filename + ".h",
124128
templates[idef.type + "_header"].render(idef),
125129
idef.type + "_header.h"
126130
);
@@ -133,17 +137,24 @@ module.exports = function generateNativeCode() {
133137
if (astyle) {
134138
return exec(
135139
"astyle --options=\".astylerc\" "
136-
+ path.resolve(__dirname, "../../src") + "/*.cc "
137-
+ path.resolve(__dirname, "../../include") + "/*.h"
140+
+ tempSrcDirPath + "/*.cc "
141+
+ tempIncludeDirPath + "/*.h"
138142
).then(function() {
139143
return exec(
140144
"rm "
141-
+ path.resolve(__dirname, "../../src") + "/*.cc.orig "
142-
+ path.resolve(__dirname, "../../include") + "/*.h.orig "
145+
+ tempSrcDirPath + "/*.cc.orig "
146+
+ tempIncludeDirPath + "/*.h.orig "
143147
);
144148
});
145149
}
146150
}, function() {})
151+
}).then(function() {
152+
return Promise.all([
153+
utils.syncDirs(tempSrcDirPath, finalSrcDirPath),
154+
utils.syncDirs(tempIncludeDirPath, finalIncludeDirPath),
155+
]);
156+
}).then(function() {
157+
return fse.remove(tempDirPath);
147158
}).catch(console.log);
148159

149160
};

generate/scripts/utils.js

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const fse = require("fs-extra");
2+
const walk = require("walk");
23

34
const fs = require("fs");
45
const path = require("path");
@@ -10,7 +11,7 @@ var util = {
1011
pointerRegex: /\s*\*\s*/,
1112
doublePointerRegex: /\s*\*\*\s*/,
1213

13-
readFile: function(file) {
14+
readLocalFile: function(file) {
1415
try {
1516
return fs.readFileSync(local(file)).toString();
1617
}
@@ -19,6 +20,15 @@ var util = {
1920
}
2021
},
2122

23+
readFile: function(filePath) {
24+
try {
25+
return fs.readFileSync(filePath).toString();
26+
}
27+
catch (unhandledException) {
28+
return "";
29+
}
30+
},
31+
2232
writeFile: function(file, content, header) {
2333
try {
2434
var file = local(file);
@@ -62,14 +72,84 @@ var util = {
6272
}).join("");
6373
},
6474

75+
getFilePathsRelativeToDir: function(dir) {
76+
const files = [];
77+
const walker = walk.walk(dir, { followLinks: false });
78+
if (!util.isDirectory(dir)) {
79+
return Promise.resolve([]);
80+
}
81+
82+
return new Promise(function(resolve, reject) {
83+
walker.on('file', function(root, stat, next) {
84+
files.push(path.relative(dir, path.join(root, stat.name)));
85+
next();
86+
});
87+
88+
walker.on('end', function() {
89+
resolve(files);
90+
});
91+
92+
walker.on('errors', function() {
93+
reject();
94+
});
95+
});
96+
},
97+
98+
isFile: function(path) {
99+
var isFile;
100+
try {
101+
isFile = fse.statSync(path).isFile();
102+
} catch(e) {
103+
isFile = false;
104+
}
105+
106+
return isFile;
107+
},
108+
109+
isDirectory: function(path) {
110+
var isDirectory;
111+
try {
112+
isDirectory = fse.statSync(path).isDirectory();
113+
} catch(e) {
114+
isDirectory = false;
115+
}
116+
117+
return isDirectory;
118+
},
119+
65120
isPointer: function(type) {
66121
return util.pointerRegex.test(type) || util.doublePointerRegex.test(type);
67122
},
68123

69124
isDoublePointer: function(type) {
70125
return util.doublePointerRegex.test(type);
71-
}
126+
},
72127

128+
syncDirs: function(fromDir, toDir) {
129+
return Promise.all([
130+
util.getFilePathsRelativeToDir(toDir),
131+
util.getFilePathsRelativeToDir(fromDir)
132+
]).then(function(filePaths) {
133+
const toFilePaths = filePaths[0];
134+
const fromFilePaths = filePaths[1];
135+
136+
// Delete files that aren't in fromDir
137+
toFilePaths.forEach(function(filePath) {
138+
if (!util.isFile(path.join(fromDir, filePath))) {
139+
fse.remove(path.join(toDir, filePath));
140+
}
141+
});
142+
143+
// Copy files that don't exist in toDir or have different contents
144+
fromFilePaths.forEach(function(filePath) {
145+
const toFilePath = path.join(toDir, filePath);
146+
const fromFilePath = path.join(fromDir, filePath);
147+
if (!util.isFile(toFilePath) || util.readFile(toFilePath) !== util.readFile(fromFilePath)) {
148+
fse.copy(fromFilePath, toFilePath);
149+
}
150+
});
151+
});
152+
}
73153
};
74154

75155
module.exports = util;

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252
"js-beautify": "~1.5.10",
5353
"jshint": "~2.8.0",
5454
"lcov-result-merger": "~1.0.2",
55-
"mocha": "~2.3.4"
55+
"mocha": "~2.3.4",
56+
"walk": "^2.3.9"
5657
},
5758
"vendorDependencies": {
5859
"libssh2": "1.7.0",

0 commit comments

Comments
 (0)