www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

commit ccb30351c0b7961fe8ee2ac11378585749e6dc0e
parent 700aa5377b838bed6bf8ed4b1c405a58137d0492
Author: Dan Stillman <dstillman@zotero.org>
Date:   Wed, 14 Jun 2017 03:18:27 -0400

Fix incorrect purging of files on WebDAV

Diffstat:
Mchrome/content/zotero/xpcom/storage/webdav.js | 30++++++++++++++++++++----------
Mtest/tests/webdavTest.js | 55++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 74 insertions(+), 11 deletions(-)

diff --git a/chrome/content/zotero/xpcom/storage/webdav.js b/chrome/content/zotero/xpcom/storage/webdav.js @@ -940,6 +940,7 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { */ purgeOrphanedStorageFiles: Zotero.Promise.coroutine(function* () { const libraryID = Zotero.Libraries.userLibraryID; + const library = Zotero.Libraries.get(libraryID); const daysBeforeSyncTime = 7; // If recently purged, skip @@ -966,7 +967,7 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { + "<getlastmodified/>" + "</prop></propfind>"; - var lastSyncDate = Zotero.Libraries.userLibrary.lastSync; + var lastSyncDate = library.lastSync; if (!lastSyncDate) { Zotero.debug(`No last sync date for library ${libraryID} -- not purging orphaned files`); return false; @@ -990,6 +991,9 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { return Zotero.Utilities.xpath(this, path, { D: 'DAV:' }); }; + var syncQueueKeys = new Set( + yield Zotero.Sync.Data.Local.getObjectsFromSyncQueue('item', libraryID) + ); var deleteFiles = []; var trailingSlash = !!path.match(/\/$/); for (let response of responseNode.xpath("D:response")) { @@ -1045,20 +1049,24 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { continue; } - var isLastSyncFile = file !== 'lastsync.txt' || file != 'lastsync'; - - if (!file.match(/\.zip$/) && !file.match(/\.prop$/) && !isLastSyncFile) { - Zotero.debug("Skipping file " + file); - continue; - } - + var isLastSyncFile = file == 'lastsync.txt' || file == 'lastsync'; if (!isLastSyncFile) { - var key = file.replace(/\.(zip|prop)$/, ''); - var item = yield Zotero.Items.getByLibraryAndKeyAsync(libraryID, key); + if (!file.match(/\.zip$/) && !file.match(/\.prop$/)) { + Zotero.debug("Skipping file " + file); + continue; + } + + let key = file.replace(/\.(zip|prop)$/, ''); + let item = yield Zotero.Items.getByLibraryAndKeyAsync(libraryID, key); if (item) { Zotero.debug("Skipping existing file " + file); continue; } + + if (syncQueueKeys.has(key)) { + Zotero.debug(`Skipping file for item ${key} in sync queue`); + continue; + } } Zotero.debug("Checking orphaned file " + file); @@ -1082,6 +1090,8 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = { var results = yield this._deleteStorageFiles(deleteFiles); Zotero.Prefs.set("lastWebDAVOrphanPurge", Math.round(new Date().getTime() / 1000)); Zotero.debug(results); + + return results; }), diff --git a/test/tests/webdavTest.js b/test/tests/webdavTest.js @@ -697,6 +697,13 @@ describe("Zotero.Sync.Storage.Mode.WebDAV", function () { library.updateLastSyncTime(); yield library.saveTx(); + // Create one item + var item1 = yield createDataObject('item'); + var item1Key = item1.key; + // Add another item to sync queue + var item2Key = Zotero.DataObjectUtilities.generateKey(); + yield Zotero.Sync.Data.Local.addObjectsToSyncQueue('item', library.id, [item2Key]); + const daysBeforeSyncTime = 7; var beforeTime = new Date(Date.now() - (daysBeforeSyncTime * 86400 * 1000 + 1)).toUTCString(); @@ -738,6 +745,7 @@ describe("Zotero.Sync.Storage.Mode.WebDAV", function () { + '<D:status>HTTP/1.1 200 OK</D:status>' + '</D:propstat>' + '</D:response>' + + '<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">' + `<D:href>${davBasePath}zotero/AAAAAAAA.zip</D:href>` + '<D:propstat>' @@ -756,6 +764,7 @@ describe("Zotero.Sync.Storage.Mode.WebDAV", function () { + '<D:status>HTTP/1.1 200 OK</D:status>' + '</D:propstat>' + '</D:response>' + + '<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">' + `<D:href>${davBasePath}zotero/BBBBBBBB.zip</D:href>` + '<D:propstat>' @@ -774,6 +783,46 @@ describe("Zotero.Sync.Storage.Mode.WebDAV", function () { + '<D:status>HTTP/1.1 200 OK</D:status>' + '</D:propstat>' + '</D:response>' + + // Item that exists + + '<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">' + + `<D:href>${davBasePath}zotero/${item1Key}.zip</D:href>` + + '<D:propstat>' + + '<D:prop>' + + `<lp1:getlastmodified>${beforeTime}</lp1:getlastmodified>` + + '</D:prop>' + + '<D:status>HTTP/1.1 200 OK</D:status>' + + '</D:propstat>' + + '</D:response>' + + '<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">' + + `<D:href>${davBasePath}zotero/${item1Key}.prop</D:href>` + + '<D:propstat>' + + '<D:prop>' + + `<lp1:getlastmodified>${beforeTime}</lp1:getlastmodified>` + + '</D:prop>' + + '<D:status>HTTP/1.1 200 OK</D:status>' + + '</D:propstat>' + + '</D:response>' + + // Item in sync queue + + '<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">' + + `<D:href>${davBasePath}zotero/${item2Key}.zip</D:href>` + + '<D:propstat>' + + '<D:prop>' + + `<lp1:getlastmodified>${beforeTime}</lp1:getlastmodified>` + + '</D:prop>' + + '<D:status>HTTP/1.1 200 OK</D:status>' + + '</D:propstat>' + + '</D:response>' + + '<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">' + + `<D:href>${davBasePath}zotero/${item2Key}.prop</D:href>` + + '<D:propstat>' + + '<D:prop>' + + `<lp1:getlastmodified>${beforeTime}</lp1:getlastmodified>` + + '</D:prop>' + + '<D:status>HTTP/1.1 200 OK</D:status>' + + '</D:propstat>' + + '</D:response>' + '</D:multistatus>' }); setResponse({ @@ -797,8 +846,12 @@ describe("Zotero.Sync.Storage.Mode.WebDAV", function () { status: 204 }); - yield controller.purgeOrphanedStorageFiles(); + var results = yield controller.purgeOrphanedStorageFiles(); assertRequestCount(5); + + assert.sameMembers(results.deleted, ['lastsync.txt', 'lastsync', 'AAAAAAAA.prop', 'AAAAAAAA.zip']); + assert.lengthOf(results.missing, 0); + assert.lengthOf(results.error, 0); }) it("shouldn't purge if purged recently", function* () {