135 lines
6.6 KiB
JavaScript
135 lines
6.6 KiB
JavaScript
/**
|
|
* grunt-manifester
|
|
* https://github.com/jeffpar/pcjs
|
|
*
|
|
* Copyright (c) 2014-2016 jeffpar
|
|
* Licensed under the MIT license.
|
|
*
|
|
* TODO: Update this header with our standard header and fix all the JSHint warnings
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
var fs = require("fs");
|
|
var path = require("path");
|
|
var mkdirp = require("mkdirp");
|
|
var url = require("url");
|
|
var async = require("async");
|
|
var parseXML = require("xml2js").parseString; // see: https://github.com/Leonidas-from-XIV/node-xml2js
|
|
var unzip = require("unzip");
|
|
var util = require("util");
|
|
var defines = require("../../../shared/lib/defines");
|
|
var net = require("../../../shared/lib/netlib");
|
|
|
|
module.exports = function (grunt) {
|
|
|
|
/*
|
|
* Please see the Grunt documentation for more information regarding task
|
|
* creation: http://gruntjs.com/creating-tasks
|
|
*/
|
|
grunt.registerMultiTask('manifester', 'manifest.xml processor', function() {
|
|
|
|
/*
|
|
* Merge task-specific and/or target-specific options with these defaults
|
|
*
|
|
var options = this.options({
|
|
});
|
|
*/
|
|
|
|
/*
|
|
* Tell grunt this task is asynchronous
|
|
*/
|
|
var asManifests = [];
|
|
var doneGrunt = this.async();
|
|
|
|
/*
|
|
* Iterate over all specified file groups
|
|
*/
|
|
this.files.forEach(function(file) {
|
|
|
|
file.src.filter(function(sFilePath) {
|
|
/*
|
|
* Warn on and remove invalid source files (if nonull was set)
|
|
*/
|
|
if (!grunt.file.exists(sFilePath)) {
|
|
grunt.log.warn('Source file "' + sFilePath + '" not found.');
|
|
return false;
|
|
}
|
|
return true;
|
|
}).map(function(sFilePath) {
|
|
/*
|
|
* TODO: Given the memory constraints I've run into with Grunt in the past, it would
|
|
* probably be better queue up the file paths instead of the file contents, and do async
|
|
* readFile() calls.
|
|
*/
|
|
asManifests.push(sFilePath);
|
|
});
|
|
});
|
|
|
|
async.each(asManifests, function processXML(sManifestFile, doneAsync) {
|
|
var sManifestXML = grunt.file.read(sManifestFile);
|
|
parseXML(sManifestXML, function doneParseXML(err, xml) {
|
|
var cCallbacks = 0;
|
|
if (xml.manifest) {
|
|
// console.log(util.inspect(xml, false, null));
|
|
for (var iRepo in xml.manifest.repo) {
|
|
var repo = xml.manifest.repo[iRepo];
|
|
if (repo.src) {
|
|
var src = repo.src[0];
|
|
var sURL = src.$['href'];
|
|
// var sURL = src._ || src; // the former is set if there are any attributes, otherwise the element is just a string
|
|
console.log('found src URL: "' + sURL + '"');
|
|
if (sURL.slice(0, 5) == "http:" && sURL.slice(-1) == '/') {
|
|
for (var iDownload in repo.download) {
|
|
var download = repo.download[iDownload];
|
|
var sDownloadFile = download.$['href'];
|
|
// var sDownloadFile = download._ || download;
|
|
console.log("processing download " + sDownloadFile);
|
|
var sRemoteFile = sURL + sDownloadFile;
|
|
var sLocalDir = path.join(path.dirname(sManifestFile), repo.$['dir']);
|
|
if (grunt.file.exists(sLocalDir) || mkdirp.sync(sLocalDir)) {
|
|
var sLocalFile = path.join(sLocalDir, sDownloadFile);
|
|
if (grunt.file.exists(sLocalFile)) {
|
|
console.log("file already exists: " + sLocalFile);
|
|
} else {
|
|
console.log('downloadFile("' + sRemoteFile + '", "' + sLocalFile + '")...');
|
|
cCallbacks++;
|
|
net.downloadFile(sRemoteFile, sLocalFile, function doneDownloadFile(err, status) {
|
|
console.log('downloadFile("' + sRemoteFile + '") returned ' + status + ': ' + (err? false : true));
|
|
if (!err && status == 200 && sLocalFile.slice(-4) == ".zip") {
|
|
var sLocalZipDir = path.join(sLocalDir, path.basename(sLocalFile, ".zip"));
|
|
if (grunt.file.exists(sLocalZipDir) || mkdirp.sync(sLocalZipDir)) {
|
|
/*
|
|
* TODO: As explained here (https://github.com/EvanOxfeld/node-unzip/issues/40), determine why this ZIP
|
|
* file (http://beej.us/moria/files/pc/zip-arc/mor55-88.zip) causes an "invalid stored block lengths" error.
|
|
*/
|
|
fs.createReadStream(sLocalFile).pipe(unzip.Extract({path: sLocalZipDir})).on('close', function() {
|
|
console.log("unzip complete: " + sLocalZipDir);
|
|
if (--cCallbacks == 0) doneAsync();
|
|
});
|
|
return;
|
|
} else {
|
|
grunt.log.warn("unzip directory not available: " + sLocalZipDir);
|
|
}
|
|
}
|
|
if (--cCallbacks == 0) doneAsync();
|
|
});
|
|
}
|
|
} else {
|
|
grunt.log.warn("download directory not available: " + sLocalDir);
|
|
}
|
|
}
|
|
} else {
|
|
grunt.log.warn("unsupported repo src: " + sURL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!cCallbacks) doneAsync();
|
|
});
|
|
}, function(err) {
|
|
doneGrunt();
|
|
});
|
|
|
|
});
|
|
};
|