Skip to content

Commit 95a5923

Browse files
committed
Script to flatten message directories
Adds a new script that will copy all of your message dependencies into a specified location, flattening the directory structure. It will also parse through your files and update their require paths to take advantage of this new directory structure.
1 parent 09080cb commit 95a5923

3 files changed

Lines changed: 137 additions & 2 deletions

File tree

flatten.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
'use strict'
2+
3+
// a utility script that will flatten the directory structure for the message
4+
// files generated by genjs.
5+
6+
let message_utils = require('./utils/message_utils.js');
7+
8+
let args = process.argv;
9+
console.log(args);
10+
11+
if (args.length < 3) {
12+
throw new Error('Must include desired output directory in calls to flatten!');
13+
}
14+
15+
message_utils.findMessageFiles();
16+
message_utils.flatten(args[2]);

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"js"
1010
],
1111
"scripts": {
12-
"test": "mocha --recursive"
12+
"test": "mocha --recursive",
13+
"flatten": "node flatten.js"
1314
},
1415
"author": "chris smith",
1516
"license": "Apache-2.0",

utils/message_utils.js

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@
1919

2020
let fs = require('fs');
2121
let path = require('path');
22+
let utils = require('util');
2223
let log = require('./logger.js').createLogger();
2324

2425
// When sourcing your workspace, CMAKE_PREFIX_PATH is AUTOMATICALLY
2526
// prepended with the devel directory of your workspace. Workspace
2627
// chaining works by continuing this path prepending.
2728
let cmakePath = process.env.CMAKE_PREFIX_PATH;
2829
let cmakePaths = cmakePath.split(':');
29-
let jsMsgPath = 'share/node_js/ros';
30+
let jsMsgPath = path.join('share', 'node_js', 'ros');
3031

3132
let messagePackageMap = {};
3233
let messagePackagePathMap = {};
@@ -41,6 +42,51 @@ let messagePackagePathMap = {};
4142
// in the cache and require it if found.
4243
//-----------------------------------------------------------------------
4344

45+
function createDirectory(directory) {
46+
let curPath = '/';
47+
const paths = directory.split(path.sep);
48+
paths.forEach((part, index) => {
49+
if (!part) {
50+
return;
51+
}
52+
curPath = path.join(curPath, part);
53+
const thisPath = curPath;
54+
55+
try {
56+
fs.mkdirSync(thisPath);
57+
}
58+
catch (err) {
59+
if (err.code !== 'EEXIST') {
60+
throw err;
61+
}
62+
}
63+
});
64+
}
65+
66+
function copyFile(from, to, replaceCallback) {
67+
return new Promise((resolve, reject) => {
68+
const readStream = fs.createReadStream(from);
69+
let fileData = '';
70+
readStream.on('data', (data) => {
71+
fileData += data;
72+
});
73+
74+
readStream.on('end', () => {
75+
if (typeof replaceCallback === 'function') {
76+
fileData = replaceCallback(fileData);
77+
}
78+
79+
// open the output file for writing
80+
const writeStream = fs.createWriteStream(to);
81+
writeStream.on('open', () => {
82+
writeStream.write(fileData);
83+
writeStream.end();
84+
resolve();
85+
});
86+
});
87+
});
88+
}
89+
4490
let MessageUtils = {
4591
findMessageFiles() {
4692
if (Object.keys(messagePackagePathMap).length > 0) {
@@ -62,6 +108,78 @@ let MessageUtils = {
62108
});
63109
},
64110

111+
flatten(outputDir) {
112+
const finderDeclRegex = /^let _finder = require\('\.\.\/\.\.\/\.\.\/find\.js'\);/m;
113+
const finderCallRegex = /^let (\w+) = _finder\(\'\1\'\);/gm;
114+
115+
const flatten_local = (packageName, startPath, localPath, outputDir) => {
116+
const flattenPath = path.join(startPath, localPath);
117+
fs.readdir(flattenPath, (err, files) => {
118+
if (err) {
119+
// if the path doesn't exist, it just means the package currently
120+
// being flattened doesn't have either msgs or srvs
121+
if (err.code !== 'ENOENT') {
122+
throw new Error('Error while flattening generated messages ' + err);
123+
}
124+
return;
125+
}
126+
// else
127+
const outputPath = path.join(outputDir, packageName, localPath);
128+
createDirectory(outputPath)
129+
130+
files.forEach((file) => {
131+
const filePath = path.join(flattenPath, file);
132+
const outputFilePath = path.join(outputDir, packageName, localPath, file);
133+
let callback;
134+
if (file !== '_index.js') {
135+
callback = (fileData) => {
136+
fileData = fileData.replace(finderDeclRegex, '');
137+
let matchData;
138+
while ((matchData = finderCallRegex.exec(fileData)) !== null) {
139+
const matchStr = matchData[0];
140+
const msgPackage = matchData[1];
141+
const replaceStr = utils.format('let %s = require(\'../../%s/_index.js\');', msgPackage, msgPackage);
142+
fileData = fileData.replace(matchStr, replaceStr);
143+
}
144+
return fileData;
145+
};
146+
}
147+
copyFile(filePath, outputFilePath, callback);
148+
});
149+
});
150+
};
151+
152+
outputDir = path.resolve(outputDir);
153+
const messageDirectory = path.join(outputDir, 'ros');
154+
createDirectory(messageDirectory);
155+
156+
// find relevant genjs base files and copy to output directory
157+
const filesToCopy = ['base_deserialize.js', 'base_serialize.js'];
158+
cmakePaths.some((cmakePath) => {
159+
const checkPath = path.join(cmakePath, 'share', 'node_js');
160+
let files = fs.readdirSync(checkPath);
161+
if (!files) {
162+
return false;
163+
}
164+
files.forEach((fileName) => {
165+
if (filesToCopy.indexOf(fileName) !== -1) {
166+
copyFile(path.join(checkPath, fileName), path.join(outputDir, fileName));
167+
}
168+
});
169+
return true;
170+
});
171+
172+
Object.keys(messagePackagePathMap).forEach((packageName) => {
173+
const messagePackagePath = messagePackagePathMap[packageName];
174+
const dir = path.dirname(messagePackagePath)
175+
176+
flatten_local(packageName, dir, 'msg', messageDirectory);
177+
flatten_local(packageName, dir, 'srv', messageDirectory);
178+
// copy the index
179+
copyFile(messagePackagePath, path.join(messageDirectory, packageName, '_index.js'));
180+
});
181+
},
182+
65183
loadMessagePackage(msgPackage) {
66184
const indexPath = messagePackagePathMap[msgPackage];
67185
if (indexPath === undefined) {

0 commit comments

Comments
 (0)