diff --git a/chrome/content/zotero/xpcom/storage.js b/chrome/content/zotero/xpcom/storage.js
index 94b32bf04..f05039e3a 100644
--- a/chrome/content/zotero/xpcom/storage.js
+++ b/chrome/content/zotero/xpcom/storage.js
@@ -289,6 +289,7 @@ Zotero.Sync.Storage = new function () {
]));
}
else {
+ result = result.exception;
Zotero.debug("File " + result.type + " sync failed "
+ "for library " + libraryID);
finalPromises.push([libraryID, queuePromise]);
@@ -378,7 +379,7 @@ Zotero.Sync.Storage = new function () {
var request = new Zotero.Sync.Storage.Request(
(item.libraryID ? item.libraryID : 0) + '/' + item.key, callbacks
);
- if (queue == 'upload') {
+ if (queue.type == 'upload') {
request.setMaxSize(Zotero.Attachments.getTotalFileSize(item));
}
queue.addRequest(request, highPriority);
diff --git a/chrome/content/zotero/xpcom/storage/queue.js b/chrome/content/zotero/xpcom/storage/queue.js
index e2ab45190..2a12b23c4 100644
--- a/chrome/content/zotero/xpcom/storage/queue.js
+++ b/chrome/content/zotero/xpcom/storage/queue.js
@@ -49,6 +49,8 @@ Zotero.Sync.Storage.Queue = function (type, libraryID) {
this._localChanges = false;
this._remoteChanges = false;
this._conflicts = [];
+ this._cachedPercentage;
+ this._cachedPercentageTime;
}
Zotero.Sync.Storage.Queue.prototype.__defineGetter__('name', function () {
@@ -158,11 +160,18 @@ Zotero.Sync.Storage.Queue.prototype.__defineGetter__('percentage', function () {
return 100;
}
+ // Cache percentage for a second
+ if (this._cachedPercentage && (new Date() - this._cachedPercentageTime) < 1000) {
+ return this._cachedPercentage;
+ }
+
var completedRequests = 0;
for each(var request in this._requests) {
completedRequests += request.percentage / 100;
}
- return Math.round((completedRequests / this.totalRequests) * 100);
+ this._cachedPercentage = Math.round((completedRequests / this.totalRequests) * 100);
+ this._cachedPercentageTime = new Date();
+ return this._cachedPercentage;
});
@@ -288,7 +297,7 @@ Zotero.Sync.Storage.Queue.prototype.advance = function () {
);
}
})
- .fail(function (e) {
+ .catch(function (e) {
self.error(e);
});
@@ -330,7 +339,7 @@ Zotero.Sync.Storage.Queue.prototype.advance = function () {
);
}
})
- .fail(function (e) {
+ .catch(function (e) {
self.error(e);
});
@@ -362,7 +371,6 @@ Zotero.Sync.Storage.Queue.prototype.error = function (e) {
this._error = e;
}
Zotero.debug(e, 1);
- Components.utils.reportError(e.message ? e.message : e);
this.stop();
}
diff --git a/chrome/content/zotero/xpcom/storage/request.js b/chrome/content/zotero/xpcom/storage/request.js
index 961c21535..080bd87e5 100644
--- a/chrome/content/zotero/xpcom/storage/request.js
+++ b/chrome/content/zotero/xpcom/storage/request.js
@@ -208,7 +208,6 @@ Zotero.Sync.Storage.Request.prototype.start = function () {
};
})
.then(function (results) {
- Zotero.debug('!!!!');
Zotero.debug(results);
if (results.localChanges) {
@@ -263,7 +262,7 @@ Zotero.Sync.Storage.Request.prototype.isFinished = function () {
* (usually total bytes)
*/
Zotero.Sync.Storage.Request.prototype.onProgress = function (channel, progress, progressMax) {
- Zotero.debug(progress + "/" + progressMax + " for request " + this.name);
+ //Zotero.debug(progress + "/" + progressMax + " for request " + this.name);
if (!this._running) {
Zotero.debug("Trying to update finished request " + this.name + " in "
diff --git a/chrome/content/zotero/xpcom/storage/webdav.js b/chrome/content/zotero/xpcom/storage/webdav.js
index 37901d328..4e56f330a 100644
--- a/chrome/content/zotero/xpcom/storage/webdav.js
+++ b/chrome/content/zotero/xpcom/storage/webdav.js
@@ -68,20 +68,22 @@ Zotero.Sync.Storage.WebDAV = (function () {
return false;
}
- if (req.responseXML) {
- // TODO: other stuff, but this makes us forward-compatible
- try {
- var mtime = req.responseXML.getElementsByTagName('mtime')[0]
- }
- catch (e) {
- Zotero.debug(e);
- var mtime = "";
- }
- var seconds = false;
+ var seconds = false;
+ var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
+ .createInstance(Components.interfaces.nsIDOMParser);
+ try {
+ var xml = parser.parseFromString(req.responseText, "text/xml");
+ var mtime = xml.getElementsByTagName('mtime')[0].textContent;
}
- else {
+ catch (e) {
+ Zotero.debug(e);
+ var mtime = false;
+ }
+
+ // TEMP
+ if (!mtime) {
mtime = req.responseText;
- var seconds = true;
+ seconds = true;
}
var invalid = false;
@@ -106,13 +108,15 @@ Zotero.Sync.Storage.WebDAV = (function () {
+ "' for item " + Zotero.Items.getLibraryKeyHash(item);
Zotero.debug(msg, 1);
Components.utils.reportError(msg);
- deleteStorageFiles([item.key + ".prop"]);
- throw _defaultError;
+ return deleteStorageFiles([item.key + ".prop"])
+ .then(function (results) {
+ throw new Error(_defaultError);
+ });
}
return new Date(parseInt(mtime));
})
- .fail(function (e) {
+ .catch(function (e) {
if (e instanceof Zotero.HTTP.UnexpectedStatusException) {
Zotero.debug(req.responseText);
throw new Error("Unexpected status code " + e.status + " in " + funcName);
@@ -138,8 +142,8 @@ Zotero.Sync.Storage.WebDAV = (function () {
+ '' + hash + ''
+ '';
- return Zotero.HTTP.promise("PUT", uri, prop,
- { debug: true, successCodes: [200, 201, 204] })
+ return Zotero.HTTP.promise("PUT", uri,
+ { body: prop, debug: true, successCodes: [200, 201, 204] })
.then(function (req) {
return { mtime: mtime, hash: hash };
})
@@ -459,7 +463,7 @@ Zotero.Sync.Storage.WebDAV = (function () {
* 'deleted', 'missing', and 'error',
* each containing filenames
*/
- function deleteStorageFiles(files, callback) {
+ function deleteStorageFiles(files) {
var results = {
deleted: [],
missing: [],
@@ -467,114 +471,90 @@ Zotero.Sync.Storage.WebDAV = (function () {
};
if (files.length == 0) {
- if (callback) {
- callback(results);
- }
- return;
+ return Q.resolve(results);
}
- for (var i=0; i i) {
- delete files[propIndex];
- i--;
- last = (i == files.length - 1);
- }
-
- // Delete property file
- Zotero.HTTP.WebDAV.doDelete(deletePropURI, function (req) {
+ let deleteURI = _rootURI.clone();
+ // This should never happen, but let's be safe
+ if (!deleteURI.spec.match(/\/$/)) {
+ throw new Error(
+ "Root URI does not end in slash in "
+ + "Zotero.Sync.Storage.WebDAV.deleteStorageFiles()"
+ );
+ }
+
+ results = Q.resolve(results);
+ files.forEach(function (fileName) {
+ results = results.then(function (results) {
+ let deleteURI = _rootURI.clone();
+ deleteURI.QueryInterface(Components.interfaces.nsIURL);
+ deleteURI.fileName = fileName;
+ deleteURI.QueryInterface(Components.interfaces.nsIURI);
+ return Zotero.HTTP.promise("DELETE", deleteURI, { successCodes: [200, 204, 404] })
+ .then(function (req) {
switch (req.status) {
case 204:
// IIS 5.1 and Sakai return 200
case 200:
- results.deleted.push(fileName);
+ var fileDeleted = true;
break;
case 404:
- if (fileDeleted) {
- results.deleted.push(fileName);
- }
- else {
- results.missing.push(fileName);
- }
+ var fileDeleted = false;
break;
-
- default:
- var error = true;
}
- if (last && callback) {
- callback(results);
+ // If an item file URI, get the property URI
+ var deletePropURI = getPropertyURIFromItemURI(deleteURI);
+ if (!deletePropURI) {
+ if (fileDeleted) {
+ results.deleted.push(fileName);
+ }
+ else {
+ results.missing.push(fileName);
+ }
+ return results;
}
- if (error) {
- results.error.push(fileName);
- var msg = "An error occurred attempting to delete "
- + "'" + fileName
- + "' (" + req.status + " " + req.statusText + ").";
- Zotero.Sync.Storage.EventManager.error(msg);
+ // If property file appears separately in delete queue,
+ // remove it, since we're taking care of it here
+ var propIndex = files.indexOf(deletePropURI.fileName);
+ if (propIndex > i) {
+ delete files[propIndex];
+ i--;
+ last = (i == files.length - 1);
}
+
+ // Delete property file
+ return Zotero.HTTP.promise("DELETE", deletePropURI, { successCodes: [200, 204, 404] })
+ .then(function (req) {
+ switch (req.status) {
+ case 204:
+ // IIS 5.1 and Sakai return 200
+ case 200:
+ results.deleted.push(fileName);
+ break;
+
+ case 404:
+ if (fileDeleted) {
+ results.deleted.push(fileName);
+ }
+ else {
+ results.missing.push(fileName);
+ }
+ break;
+ }
+ });
+ })
+ .catch(function (e) {
+ results.error.push(fileName);
+ var msg = "An error occurred attempting to delete "
+ + "'" + fileName
+ + "' (" + e.status + " " + e.xmlhttp.statusText + ").";
});
});
- }
+ });
+ return results;
}
@@ -888,9 +868,10 @@ Zotero.Sync.Storage.WebDAV = (function () {
Components.utils.reportError(msg);
// Delete the orphaned prop file
- deleteStorageFiles([item.key + ".prop"]);
-
- deferred.resolve(false);
+ deleteStorageFiles([item.key + ".prop"])
+ .finally(function (results) {
+ deferred.resolve(false);
+ });
return;
}
else if (status != 200) {
@@ -1474,27 +1455,23 @@ Zotero.Sync.Storage.WebDAV = (function () {
*
* @param {Function} callback Passed number of files deleted
*/
- obj._purgeDeletedStorageFiles = function (callback) {
+ obj._purgeDeletedStorageFiles = function () {
if (!this._active) {
- return false;
+ return Q(false);
}
Zotero.debug("Purging deleted storage files");
var files = Zotero.Sync.Storage.getDeletedFiles();
if (!files) {
Zotero.debug("No files to delete remotely");
- if (callback) {
- callback();
- }
- return false;
+ return Q(false);
}
- // TODO: promisify
-
// Add .zip extension
var files = files.map(function (file) file + ".zip");
- deleteStorageFiles(files, function (results) {
+ return deleteStorageFiles(files)
+ .then(function (results) {
// Remove deleted and nonexistent files from storage delete log
var toPurge = results.deleted.concat(results.missing);
if (toPurge.length > 0) {
@@ -1516,11 +1493,7 @@ Zotero.Sync.Storage.WebDAV = (function () {
Zotero.DB.commitTransaction();
}
- if (callback) {
- callback(results.deleted.length);
- }
-
- Zotero.Sync.Storage.EventManager.success();
+ return results.deleted.length;
});
};
@@ -1647,12 +1620,10 @@ Zotero.Sync.Storage.WebDAV = (function () {
}
}
- deleteStorageFiles(deleteFiles, function (results) {
+ deleteStorageFiles(deleteFiles)
+ .then(function (results) {
Zotero.Prefs.set("lastWebDAVOrphanPurge", Math.round(new Date().getTime() / 1000))
- if (callback) {
- callback(results);
- }
- Zotero.Sync.Storage.EventManager.success();
+ Zotero.debug(results);
});
}, { Depth: 1 });
};
diff --git a/chrome/content/zotero/xpcom/sync.js b/chrome/content/zotero/xpcom/sync.js
index 90a2c9955..7ca6553ba 100644
--- a/chrome/content/zotero/xpcom/sync.js
+++ b/chrome/content/zotero/xpcom/sync.js
@@ -553,8 +553,11 @@ Zotero.Sync.Runner = new function () {
Zotero.debug("File sync is finished");
if (results.errors.length) {
+ Zotero.debug(results.errors, 1);
+ for each(var e in results.errors) {
+ Components.utils.reportError(e);
+ }
Zotero.Sync.Runner.setErrors(results.errors);
-
return;
}
@@ -716,9 +719,7 @@ Zotero.Sync.Runner = new function () {
* library-specific sync error icons across all windows
*/
this.setErrors = function (errors) {
- Zotero.debug(errors);
errors = [this.parseSyncError(e) for each(e in errors)];
- Zotero.debug(errors);
_errorsByLibrary = {};
var primaryError = this.getPrimaryError(errors);