1 /* See license.txt for terms of usage */
  2 
  3 // ********************************************************************************************* //
  4 // Dependencies
  5 
  6 var path = require("path");
  7 var fs = require("fs");
  8 var shell = require("shelljs");
  9 var copy = require("dryice").copy;
 10 var os = require("os");
 11 var spawn = require("child_process").spawn;
 12 
 13 // ********************************************************************************************* //
 14 
 15 function help()
 16 {
 17     console.log('Usage:');
 18     console.log('');
 19     console.log('1. In order to build Firebug (including tracing) xpi run:');
 20     console.log('       $ node build.js');
 21     console.log('   The final xpi + update.rdf file will be located in the \'release\' sub directory.');
 22     console.log('');
 23     console.log('   If GETFIREBUG is properly specified in content/firebug/branch.properties');
 24     console.log('   (it assumes you have fbug and getfirebug.com directories at the same level)');
 25     console.log('   The xpi + update.rdf will be also deployed for you there and so you can');
 26     console.log('   just commit.');
 27     console.log('');
 28     console.log('   The release directory should contain two files:');
 29     console.log('   - firebug<version>.xpi (including updateURL) for getfirebug.com');
 30     console.log('   - firebug<version>-amo.xpi (disabled update) for AMO');
 31     console.log('');
 32     /*
 33     TODO: There were no targets for release ...
 34     console.log('2. In order to build Firebug final release (no tracing) run:');
 35     console.log('       $ node build.js release');
 36     console.log('   Again xpi files will be located in the \'release\' directory.');
 37     console.log('');
 38     */
 39     console.log('2. To check GETFIREBUG value run:');
 40     console.log('       $ node build.js echo');
 41     console.log('');
 42     console.log('3. To build xpi and generate JS doc (from source comments) run:');
 43     console.log('       $ node build.js jsdoc');
 44     console.log('');
 45     console.log('4. To build xpi for Babelzilla run:');
 46     console.log('       $ node build.js bz');
 47     console.log('   - All BZ locales should be stored in "bz-locale" directory.');
 48 }
 49 
 50 // ********************************************************************************************* //
 51 
 52 function main()
 53 {
 54     var args = process.argv;
 55 
 56     if (args.length < 3)
 57         build();
 58     else if (args.length >= 4 || args[2] === "help")
 59         help();
 60     else if (args[2] === "echo")
 61         echo();
 62     else if (args[2] === "jsdoc")
 63         jsdoc();
 64     else if (args[2] === "bz")
 65         bz();
 66     else if (args[2] === "clean")
 67         clean();
 68     else
 69         help();
 70 }
 71 
 72 // ********************************************************************************************* //
 73 // Globals
 74 
 75 // <property file="content/firebug/branch.properties"/>
 76 var getfirebugDir = "none";
 77 var packageFile = fs.readFileSync(__dirname + "/package.json", "utf8");
 78 var versionString = JSON.parse(packageFile).version;
 79 
 80 // Parse Firebug version string (e.e. "1.10.0a5" -> version: "1.10", release ".0a5")
 81 var result = versionString.match(/^(\d+\.\d+)?(\S*)$/);
 82 if (result.length != 3)
 83     throw new Error("Wrong version string!");
 84 
 85 var version = result[1];
 86 var release = result[2];
 87 
 88 // Compute various target directories.
 89 var buildDir = "./build";
 90 var releaseDir = "./release";
 91 var deployXpiDir = getfirebugDir + "/releases/firebug/" + version + "";
 92 var deployJsdocDir = getfirebugDir + "/developer/api/firebug" + version + "";
 93 var bzLocaleDir = "./bz-locale";
 94 
 95 var deployDirAvailable = path.existsSync(getfirebugDir) && fs.statSync(getfirebugDir).isDirectory;
 96 
 97 // ********************************************************************************************* //
 98 
 99 function prepareBuild()
100 {
101     shell.mkdir(buildDir);
102     shell.mkdir(releaseDir);
103 
104     // Copy non JS resources
105     copy({
106         source: {
107             root: '.',
108             // TODO: Previously we copied everything that matched this set of
109             // extensions: js, xul, properties, css, html, xml, dtd, ong, gif, ico,
110             //      manifest, txt, html
111             // and then deleted. Now we copy everything with exclusions, but
112             // we don't know what extra exclusions were missing
113             exclude: [
114                 /.*\.graphml/, /build\.xml/, /node_modules/, /build\.js/,
115                 /install\.rdf\.tpl\.xml/, /update\.rdf\.tpl\.xml/
116             ]
117         },
118         dest: buildDir
119     });
120 
121     var project = copy.createCommonJsProject({
122         roots: [
123             __dirname + "/content"
124         ],
125         aliases: {
126             "arch": "firebug/bti/inProcess"
127         }
128     });
129 
130     copy({
131         source: [
132             //copy.getMiniRequire(),
133             {
134                 project: project,
135                 require: [
136                     "firebug/chrome/chrome",
137                     "firebug/lib/lib",
138                     "firebug/firebug",
139                     "firebug/bti/inProcess/browser",
140                     "firebug/trace/traceModule",
141                     "firebug/chrome/navigationHistory",
142                     "firebug/chrome/knownIssues",
143                     "firebug/js/sourceFile",
144                     "firebug/chrome/shortcuts",
145                     "firebug/firefox/start-button/startButtonOverlay",
146                     "firebug/firefox/external-editors/externalEditors",
147                     "firebug/firefox/firebugMenu",
148                     "firebug/chrome/panelActivation",
149                     //"firebug/console/memoryProfiler", xxxHonza: removed from 1.10 (issue 5599)
150                     "firebug/chrome/tableRep",
151                     "firebug/html/htmlPanel",
152                     "firebug/console/commandLinePopup",
153                     "firebug/accessible/a11y",
154                     "firebug/js/scriptPanel",
155                     "firebug/js/callstack",
156                     "firebug/console/consoleInjector",
157                     "firebug/net/spy",
158                     "firebug/js/tabCache",
159                     "firebug/chrome/activation",
160                     "firebug/css/stylePanel",
161                     "firebug/css/computedPanel"
162                 ],
163             },
164             __dirname + "/content/firebug/main.js"
165         ],
166         filter: moduleDefines,
167         dest: buildDir + "/content/firebug/main.js"
168     });
169 
170     // Compress main.js file (all extension modules)
171     // xxxHonza: do not use uglify for build, there is missing ';' somewhere
172     /*copy({
173         source: buildDir + "/content/firebug/main.js",
174         filter: copy.filter.uglifyjs,
175         dest: buildDir + "/content/firebug/main.js"
176     });*/
177 
178     /*copy({
179         source: {value:project.getDependencyGraphML()},
180         dest: "netpanel.graphml"
181     });*/
182 
183     // Copy install.rdf template into the build dir
184     copy({
185         source: "install.rdf.tpl.xml",
186         dest: buildDir + "/install.rdf"
187     })
188 }
189 
190 // ********************************************************************************************* //
191 
192 /**
193  * Munge define lines to add module names
194  */
195 function moduleDefines(input, source)
196 {
197     if (!source)
198     {
199         console.log("- Source without filename passed to moduleDefines()." +
200             " Skipping addition of define(...) wrapper.");
201         console.log(input.substr(0, 300));
202         return input;
203     }
204 
205     input = (typeof input !== 'string') ? input.toString() : input;
206     var deps = source.deps ? Object.keys(source.deps) : [];
207     deps = deps.length ? (", '" + deps.join("', '") + "'") : "";
208 
209     var module = source.isLocation ? source.path : source;
210     module = module.replace(/\.js$/, '');
211 
212     return input.replace(/define\(\[/, 'define("' + module + '", [');
213 };
214 
215 moduleDefines.onRead = true;
216 
217 // ********************************************************************************************* //
218 
219 /**
220  * Build Firebug XPI
221  */
222 function build()
223 {
224     clean();
225     prepareBuild();
226 
227     // Update install.rdf with updated release version info
228     copy({
229         source: buildDir + "/install.rdf",
230         filter: function(data) {
231             return data
232                 .replace(/@VERSION@/gm, version)
233                 .replace(/@RELEASE@/gm, release);
234         },
235         dest: buildDir + "/install.rdf"
236     });
237 
238     // Remove template for manifest file that is used for Babelzilla builds
239     shell.rm(buildDir + "/chrome.bz.tpl.manifest");
240 
241     // Create XPI for getfirebug.com (zipping is asynchronous)
242     createFirebugXPI("firebug-" + version + release + ".xpi", function()
243     {
244         // Remove update URL, it's needed only for alpha versions. All the other
245         // versions updates from AMO.
246         copy({
247             source: buildDir + "/install.rdf",
248             filter: function(data)
249             {
250                 var re = new RegExp("(.*)https:\/\/getfirebug.com\/releases\/firebug\/" +
251                     version + "\/update.rdf(.*)");
252                 return data.replace(re, '');
253             },
254             dest: buildDir + "/install.rdf"
255         });
256 
257         // Create XPI for AMO (no update URL)
258         createFirebugXPI("firebug-" + version + release + "-amo.xpi", function()
259         {
260             shell.rm("-rf", buildDir);
261 
262             deploy();
263 
264             console.log("Firebug version: " + version + release + " in " + releaseDir);
265         });
266     });
267 }
268 
269 // ********************************************************************************************* //
270 
271 /**
272  * Create final xpi package
273  */
274 function createFirebugXPI(filename, callback)
275 {
276     zip(releaseDir + "/" + filename, buildDir, callback);
277 
278     copy({
279         source: 'update.rdf.tpl.xml',
280         filter: function(data) {
281             return data
282                 .replace(/@VERSION@/gm, version)
283                 .replace(/@RELEASE@/gm, release)
284                 .replace(/@LEAF@/gm, "firebug-" + version + release + ".xpi");
285         },
286         dest: releaseDir + "/update.rdf"
287     });
288 }
289 
290 // ********************************************************************************************* //
291 
292 function deploy()
293 {
294     if (deployDirAvailable) {
295         /*
296         <copy file="${releaseDir}/update.rdf" todir="${deployXpiDir}" overwrite="true"/>
297         <copy file="${releaseDir}/firebug-" + version + release + ".xpi" todir="${deployXpiDir}" overwrite="true"/>
298         <copy file="${releaseDir}/firebug-" + version + release + "-amo.xpi" todir="${deployXpiDir}" overwrite="true"/>
299         <echo message="XPI deployed to: " + version + release + " to ${deployXpiDir}"/>
300         */
301     }
302 }
303 
304 // ********************************************************************************************* //
305 
306 function echo()
307 {
308     console.log("Build directory: " + buildDir);
309     console.log("Deploy directory: " + getfirebugDir + " available: " + deployDirAvailable);
310 }
311 
312 // ********************************************************************************************* //
313 
314 /**
315  * Support for generating docs from Firebug source code using js-doc-toolkit
316  * See the output in $svn/jsdoc/out directory
317  */
318 function jsdoc()
319 {
320     build();
321     /*
322     <property name="jsdoc.dir" value="../../jsdoc/"/>
323     <property name="jsdoc-toolkit.dir" value="${jsdoc.dir}/jsdoc-toolkit-2.3.0/"/>
324     <property name="jsdoc-output.dir" value="${releaseDir}/jsdoc/"/>
325 
326     <path id="jsdoctoolkit">
327         <!-- Rhino js.jar 1.7.R2 must be used with jsdoctoolkit-ant-task-1.0.1.jar -->
328         <fileset dir="${jsdoc.dir}" includes="*.jar"/>
329     </path>
330 
331     <taskdef name="jsdoctoolkit"
332         classpathref="jsdoctoolkit"
333         classname="uk.co.darrenhurley.ant.tasks.JsDocToolkit"/>
334 
335     <echo message="Generate doc from Firebug source."/>
336 
337     <!-- Clean the output direcotory -->
338     <delete dir="${jsdoc-output.dir}"/>
339 
340     <!-- Parse all source files -->
341     <jsdoctoolkit jsdochome="${jsdoc-toolkit.dir}"
342         template="firebug"
343         outputdir="${jsdoc-output.dir}"
344         inputdir="." />
345     */
346     deployJsdoc();
347 }
348 
349 // ********************************************************************************************* //
350 
351 function deployJsdoc()
352 {
353     if (deployDirAvailable) {
354         /*
355         <copy todir="${deployJsdocDir}">
356             <fileset dir="${releaseDir}/jsdoc"/>
357         </copy>
358   
359         <echo message="JSDoc deployed to: " + version + release + " to ${deployXpiDir}"/>
360          */
361     }
362 }
363 
364 // ********************************************************************************************* //
365 
366 function bz()
367 {
368     clean();
369     prepareBuild();
370     /*
371     <!-- Use Babelzila manifest file (with all locales) -->
372     <copy file="chrome.bz.tpl.manifest" tofile="${buildDir}/chrome.manifest"
373         overwrite="true"/>
374     <delete file="${buildDir}/chrome.bz.tpl.manifest"/>
375 
376     <!-- Use all BZ locales -->
377     <copy todir="${buildDir}/locale" overwrite="true">
378         <fileset dir="${bzLocaleDir}">
379            <include name="**[      ]/*.properties"/>
380            <exclude name="en-US/*.properties"/>
381         </fileset>
382     </copy>
383 
384     <!-- Modify version number (append BZ) -->
385     <replace file="${buildDir}/install.rdf" propertyFile="content/firebug/branch.properties">
386         <replacefilter token="@version@" value="" + version + "" />
387         <replacefilter token="@RELEASE@" value="" + release + "-bz" />
388     </replace>
389 
390     <!-- Delete the helper dir with Babelzilla locales from the build directory -->
391     <delete dir="${buildDir}/${bzLocaleDir}" />
392 
393     <!-- Create XPI for getfirebug.com -->
394     <antcall target="createFirebugXPI">
395         <param name="file-name" value="firebug-" + version + release + "-bz.xpi" />
396     </antcall>
397 
398     <delete dir="${buildDir}" />
399 
400     <echo message="Firebug Release for Babelzilla: " + version + release + "-bz in ${releaseDir}" />
401     */
402 }
403 
404 // ********************************************************************************************* //
405 
406 function clean()
407 {
408     shell.rm("-rf", buildDir);
409     shell.rm("-rf", releaseDir);
410 }
411 
412 // ********************************************************************************************* //
413 
414 function zip(filename, directory, callback)
415 {
416     // Create final XPI package.
417     var zip;
418     if (os.platform() === "win32")
419     {
420         var params = "a -tzip " + filename + " " + directory + "/*";
421         zip = spawn("7z.exe", params.split(" "), { cwd: "." });
422     }
423     else
424     {
425         // not tested
426         //zip = spawn("zip", [ "-r", __dirname + "/" + xpiFileName, release ]);
427     }
428 
429     zip.on("exit", function()
430     {
431         callback();
432     });
433 }
434 
435 // ********************************************************************************************* //
436 // Startup
437 
438 main();
439 
440 // ********************************************************************************************* //
441