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;

Reply via email to