Make pushsession.js properly update its cached assetManifest
Project: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/commit/a924bb0f Tree: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/tree/a924bb0f Diff: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/diff/a924bb0f Branch: refs/heads/master Commit: a924bb0feee01e13532ceb43410f5e90f702e8f1 Parents: eafb349 Author: Andrew Grieve <[email protected]> Authored: Tue Jun 17 15:30:41 2014 -0400 Committer: Andrew Grieve <[email protected]> Committed: Tue Jun 17 16:40:02 2014 -0400 ---------------------------------------------------------------------- .../cordova-harness-client/pushsession.js | 115 ++++++++++++------- 1 file changed, 71 insertions(+), 44 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/a924bb0f/harness-push/node_modules/cordova-harness-client/pushsession.js ---------------------------------------------------------------------- diff --git a/harness-push/node_modules/cordova-harness-client/pushsession.js b/harness-push/node_modules/cordova-harness-client/pushsession.js index b3f6d9f..95d8a45 100644 --- a/harness-push/node_modules/cordova-harness-client/pushsession.js +++ b/harness-push/node_modules/cordova-harness-client/pushsession.js @@ -94,12 +94,7 @@ function calculateMd5(fileName) { return md5sum.digest('hex'); } -function buildAssetManifest(dir, configXmlPath) { - // If there's a trailing slash, remove it. - if (/\/$/.test(dir)) { - dir = dir.slice(0, dir.length - 1); - } - +function buildAssetMap(dir, configXmlPath) { var fileList = shelljs.find(dir).filter(function(a) { return !IGNORE_PATH_FOR_PUSH_REGEXP.exec(a) && !fs.statSync(a).isDirectory(); }); @@ -109,14 +104,14 @@ function buildAssetManifest(dir, configXmlPath) { // TODO: convert windows slash to unix slash here. var appPath = 'www/' + fileList[i].slice(dir == '.' ? 0 : dir.length + 1); ret[appPath] = { - path: appPath, + dstPath: appPath, realPath: fileList[i], etag: calculateMd5(fileList[i]), }; } if (configXmlPath) { ret['config.xml'] = { - path: 'config.xml', + dstPath: 'config.xml', realPath: configXmlPath, etag: calculateMd5(configXmlPath) }; @@ -124,26 +119,26 @@ function buildAssetManifest(dir, configXmlPath) { return ret; } -function buildDeleteList(existingAssetManifest, newAssetManifest) { +function buildDeleteList(existingAssetManifest, assetMap) { var toDelete = []; for (var k in existingAssetManifest) { // Don't delete top-level files ever. if (k.slice(0, 4) != 'www/') { continue; } - if (!newAssetManifest[k]) { + if (!assetMap[k]) { toDelete.push(k); } } return toDelete; } -function buildPushList(existingAssetManifest, newAssetManifest) { +function buildPushList(existingAssetManifest, assetMap) { var ret = []; - for (var k in newAssetManifest) { - var entry = newAssetManifest[k]; + for (var k in assetMap) { + var entry = assetMap[k]; if (entry.etag != existingAssetManifest[k]) { - if (entry.path == 'config.xml') { + if (entry.dstPath == 'config.xml') { ret.unshift(entry); } else { ret.push(entry); @@ -153,6 +148,15 @@ function buildPushList(existingAssetManifest, newAssetManifest) { return ret; } +function buildZipAssetManifest(pushList) { + var ret = Object.create(null); + // TODO: as of v0.6.2-dev of harness, this can be: {path:etag}. + for (var i = 0; i < pushList.length; ++i) { + ret[pushList[i].dstPath] = pushList[i].etag; + } + return ret; +} + function calculatePushBytes(pushList) { var ret = 0; for (var i = 0; i < pushList.length; ++i) { @@ -184,11 +188,13 @@ function PushSession(harnessClient, dir) { this.wwwDir_ = null; this.appId_ = null; this.platformId_ = null; - this.assetManifest_ = null; + this.assetManifest_ = null; // { "www/foo": "etag" } this.assetManifestEtag_ = null; var self = this; - this.boundUpdateAssetManifestFn_ = function(result) { - self.assetManifestEtag_ = result.body['assetManifestEtag']; + this.boundClearAssetManifestFn_ = function(e) { + self.assetManifest_ = null; + self.assetManifestEtag_ = null; + return Q.reject(e); }; } @@ -202,6 +208,7 @@ PushSession.prototype.initialize = function(opts) { self.assetManifest_ = result.body['assetManifest']; self.assetManifestEtag_ = result.body['assetManifestEtag']; self.wwwDir_ = opts.wwwDir || getDerivedWwwDir(self.rootDir_, self.platformId_); + self.wwwDir_ = self.wwwDir_.replace(/\/$/, ''); self.configXmlPath_ = (typeof opts.configXmlPath == 'undefined') ? getDerivedConfigXmlPath(self.rootDir_, self.platformId_) : opts.configXmlPath; self.cordovaPluginsPath_ = !opts.skipCordovaPlugins && path.join(self.wwwDir_, 'cordova_plugins.js'); self.appType_ = opts.appType || 'cordova'; @@ -218,32 +225,35 @@ PushSession.prototype.push = function() { if (self.cordovaPluginsPath_ && !fs.existsSync(self.cordovaPluginsPath_)) { throw new Error('Could not find: ' + self.cordovaPluginsPath_); } - if (self.assetManifest_) { - return self.doFileSync_(); + + var startTime = new Date(); + var assetMap = buildAssetMap(self.wwwDir_, self.configXmlPath_); + var deleteList = buildDeleteList(self.assetManifest_ || {}, assetMap); + var pushList = buildPushList(self.assetManifest_ || {}, assetMap); + if (deleteList.length === 0 && pushList.length === 0) { + console.log('Application already up-to-date.'); + return; } + var p; // TODO: It might be faster to use Zip even when some files exist. - return self.doZipPush_(); + if (self.assetManifest_) { + p = self.doPerFileSync_(pushList, startTime); + } else { + p = self.doZipPush_(pushList, startTime); + } + return p.then(function() { + return self.deleteFiles_(deleteList); + }); }).then(function() { if (self.launchAfterPush) { return self.harnessClient_.launch(self.appId_); } - }, function(e) { - self.assetManifest_ = null; - throw e; }); }; -PushSession.prototype.doFileSync_ = function() { - var a = new Date(); - var newAssetManifest = buildAssetManifest(this.wwwDir_, this.configXmlPath_); - var deleteList = buildDeleteList(this.assetManifest_, newAssetManifest); - var pushList = buildPushList(this.assetManifest_, newAssetManifest); +PushSession.prototype.doPerFileSync_ = function(pushList, startTime) { var totalPushBytes = calculatePushBytes(pushList); - console.log('Changes calculated (' + (new Date() - a) + ')'); - if (deleteList.length === 0 && pushList.length === 0) { - console.log('Application already up-to-date.'); - return; - } + console.log('Changes calculated (' + (new Date() - startTime) + ')'); var origPushListLen = pushList.length; var self = this; return Q.when().then(function pushNextFile() { @@ -254,28 +264,45 @@ PushSession.prototype.doFileSync_ = function() { var curPushEntry = pushList.shift(); var payload = fs.readFileSync(curPushEntry.realPath); // TODO handle 409 responses. - return self.harnessClient_.pushFile(self.appId_, self.appType_, payload, curPushEntry.etag, curPushEntry.path, firstRequest && totalPushBytes, firstRequest && self.assetManifestEtag_) - .then(self.boundUpdateAssetManifestFn_) + return self.harnessClient_.pushFile(self.appId_, self.appType_, payload, curPushEntry.etag, curPushEntry.dstPath, firstRequest && totalPushBytes, firstRequest && self.assetManifestEtag_) + .then(function(newAssetManifestEtag) { + self.assetManifestEtag_ = newAssetManifestEtag; + self.assetManifest_[curPushEntry.dstPath] = curPushEntry.etag; + }, self.boundClearAssetManifestFn_) .then(pushNextFile); - }).then(function() { - if (deleteList.length > 0) { - return self.harnessClient_.deleteFiles(self.appId_, deleteList, self.assetManifestEtag_) - .then(self.boundUpdateAssetManifestFn_); - } }); }; -PushSession.prototype.doZipPush_ = function() { +PushSession.prototype.deleteFiles_ = function(deleteList) { + if (deleteList.length === 0) { + return Q.when(); + } + var self = this; + return this.harnessClient_.deleteFiles(this.appId_, deleteList, this.assetManifestEtag_) + .then(function(newAssetManifestEtag) { + for (var i = 0; i < deleteList.length; ++i) { + delete self.assetManifest_[deleteList[i]]; + } + self.assetManifestEtag_ = newAssetManifestEtag; + }, this.boundClearAssetManifestFn_); +}; + +PushSession.prototype.doZipPush_ = function(pushList, startTime) { + console.log('Changes calculated (' + (new Date() - startTime) + ')'); var zip = new JSZip(); zipDir(this.wwwDir_, zip.folder('www')); if (this.configXmlPath_) { zip.file('config.xml', fs.readFileSync(this.configXmlPath_, 'binary'), { binary: true }); } - var newAssetManifest = buildAssetManifest(this.wwwDir_, this.configXmlPath_); - zip.file('zipassetmanifest.json', JSON.stringify(newAssetManifest)); + var zipAssetManifest = buildZipAssetManifest(pushList); + zip.file('zipassetmanifest.json', JSON.stringify(zipAssetManifest)); var zipData = new Buffer(zip.generate({ type: 'base64' }), 'base64'); + var self = this; return this.harnessClient_.pushZip(this.appId_, this.appType_, zipData, null, this.assetManifestEtag_) - .then(this.boundUpdateAssetManifestFn_); + .then(function(newAssetManifestEtag) { + self.assetManifestEtag_ = newAssetManifestEtag; + self.assetManifest_ = zipAssetManifest; + }, this.boundClearAssetManifestFn_); }; module.exports = PushSession;
