diff --git a/chrome/content/zotero/xpcom/db.js b/chrome/content/zotero/xpcom/db.js index ec84660fc..e1c45397c 100644 --- a/chrome/content/zotero/xpcom/db.js +++ b/chrome/content/zotero/xpcom/db.js @@ -1025,8 +1025,11 @@ Zotero.DBConnection.prototype.checkException = function (e) { Zotero.DBConnection.prototype.closeDatabase = function () { if(this._connection) { - this._connection.asyncClose(); - return true; + var deferred = Q.defer(); + this._connection.asyncClose(deferred.resolve); + return deferred.promise; + } else { + return Q(); } } diff --git a/chrome/content/zotero/xpcom/storage.js b/chrome/content/zotero/xpcom/storage.js index 97bd845da..8b6bdbbc9 100644 --- a/chrome/content/zotero/xpcom/storage.js +++ b/chrome/content/zotero/xpcom/storage.js @@ -811,8 +811,12 @@ Zotero.Sync.Storage = new function () { var numItems = items.length; var updatedStates = {}; - // OS.File didn't work reliably before Firefox 23, so use the old code - if (Zotero.platformMajorVersion < 23) { + // OS.File didn't work reliably before Firefox 23, and on Windows it returns + // the access time instead of the modification time until Firefox 25 + // (https://bugzilla.mozilla.org/show_bug.cgi?id=899436), + // so use the old code + if (Zotero.platformMajorVersion < 23 + || (Zotero.isWin && Zotero.platformMajorVersion < 25)) { Zotero.debug("Performing synchronous file update check"); for each(var item in items) { @@ -935,10 +939,10 @@ Zotero.Sync.Storage = new function () { throw new Task.Result(changed); } - Components.utils.import("resource://gre/modules/osfile.jsm") + Components.utils.import("resource://gre/modules/osfile.jsm"); let checkItems = function () { - if (!items.length) return; + if (!items.length) return Q(); //Zotero.debug("Memory usage: " + memmgr.resident); @@ -948,6 +952,11 @@ Zotero.Sync.Storage = new function () { //Zotero.debug("Checking attachment file for item " + lk); let nsIFile = item.getFile(row, true); + if (!nsIFile) { + Zotero.debug("Marking pathless attachment " + lk + " as in-sync"); + updatedStates[item.id] = Zotero.Sync.Storage.SYNC_STATE_IN_SYNC; + return checkItems(); + } let file = null; return Q(OS.File.open(nsIFile.path)) .then(function (promisedFile) { @@ -1022,16 +1031,21 @@ Zotero.Sync.Storage = new function () { return Zotero.Utilities.Internal.md5Async(file) .then(function (fileHash) { if (row.hash && row.hash == fileHash) { - Zotero.debug("Mod time didn't match (" + fmtime + "!=" + mtime + ") " - + "but hash did for " + file.leafName + " for item " + lk - + " -- updating file mod time"); - try { - nsIFile.lastModifiedTime = row.mtime; - } - catch (e) { - Zotero.File.checkFileAccessError(e, nsIFile, 'update'); - } - return; + // We have to close the file before modifying it from the main + // thread (at least on Windows, where assigning lastModifiedTime + // throws an NS_ERROR_FILE_IS_LOCKED otherwise) + return Q(file.close()) + .then(function () { + Zotero.debug("Mod time didn't match (" + fmtime + "!=" + mtime + ") " + + "but hash did for " + nsIFile.leafName + " for item " + lk + + " -- updating file mod time"); + try { + nsIFile.lastModifiedTime = row.mtime; + } + catch (e) { + Zotero.File.checkFileAccessError(e, nsIFile, 'update'); + } + }); } // Mark file for upload @@ -1048,20 +1062,27 @@ Zotero.Sync.Storage = new function () { } }) .catch(function (e) { - if (e instanceof OS.File.Error && e.becauseNoSuchFile) { + if (e instanceof OS.File.Error && + (e.becauseNoSuchFile + // This can happen if a path is too long on Windows, + // e.g. a file is being accessed on a VM through a share + // (and probably in other cases). + || (e.winLastError && e.winLastError == 3))) { Zotero.debug("Marking attachment " + lk + " as missing"); updatedStates[item.id] = Zotero.Sync.Storage.SYNC_STATE_TO_DOWNLOAD; return; } - if (e instanceof OS.File.Error && e.becauseClosed) { - Zotero.debug("File was closed", 2); - } - else { + if (e instanceof OS.File.Error) { + if (e.becauseClosed) { + Zotero.debug("File was closed", 2); + } Zotero.debug(e); Zotero.debug(e.toString()); + throw new Error("Error for operation '" + e.operation + "' for " + nsIFile.path); } - throw new Error("Error " + e.operation + " " + nsIFile.path); + + throw e; }) .then(function () { return checkItems(); diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js index d54e255fa..8a977f2df 100644 --- a/chrome/content/zotero/xpcom/zotero.js +++ b/chrome/content/zotero/xpcom/zotero.js @@ -405,7 +405,7 @@ Components.utils.import("resource://gre/modules/Services.jsm"); } // Register shutdown handler to call Zotero.shutdown() - var _shutdownObserver = {observe:Zotero.shutdown}; + var _shutdownObserver = {observe:function() { Zotero.shutdown().done() }}; Services.obs.addObserver(_shutdownObserver, "quit-application", false); try { @@ -758,7 +758,7 @@ Components.utils.import("resource://gre/modules/Services.jsm"); } - this.shutdown = function (subject, topic, data) { + this.shutdown = function() { Zotero.debug("Shutting down Zotero"); try { @@ -786,17 +786,17 @@ Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.forceGC(); // unlock DB - Zotero.DB.closeDatabase(); - - // broadcast that DB lock has been released - Zotero.IPC.broadcast("lockReleased"); + return Zotero.DB.closeDatabase().then(function() { + // broadcast that DB lock has been released + Zotero.IPC.broadcast("lockReleased"); + }); } + + return Q(); } catch(e) { Zotero.debug(e); - throw e; + return Q.reject(e); } - - return true; } diff --git a/components/zotero-service.js b/components/zotero-service.js index e00edaa59..14a59f6a4 100644 --- a/components/zotero-service.js +++ b/components/zotero-service.js @@ -164,11 +164,11 @@ ZoteroContext.prototype = { */ "switchConnectorMode":function(isConnector) { if(isConnector !== this.isConnector) { - zContext.Zotero.shutdown(); - - // create a new zContext - makeZoteroContext(isConnector); - zContext.Zotero.init(); + zContext.Zotero.shutdown().then(function() { + // create a new zContext + makeZoteroContext(isConnector); + zContext.Zotero.init(); + }).done(); } return zContext; @@ -292,16 +292,11 @@ function ZoteroService() { try { zContext.Zotero.init(); } catch(e) { - if(e === "ZOTERO_SHOULD_START_AS_CONNECTOR") { - // if Zotero should start as a connector, reload it - zContext.Zotero.shutdown(); + // if Zotero should start as a connector, reload it + zContext.Zotero.shutdown().then(function() { makeZoteroContext(true); zContext.Zotero.init(); - } else { - dump(e.toSource()); - Components.utils.reportError(e); - throw e; - } + }).done(); } } isFirstLoadThisSession = false; // no longer first load diff --git a/styles b/styles index d7eaec6c1..01e0f42ae 160000 --- a/styles +++ b/styles @@ -1 +1 @@ -Subproject commit d7eaec6c1e691b661facc0b4db491a1052c3bf1a +Subproject commit 01e0f42aee7595b7cccafe731de57f277c2b76df