diff --git a/chrome/content/zotero/xpcom/data/library.js b/chrome/content/zotero/xpcom/data/library.js index 79ea829bd6..5646abc738 100644 --- a/chrome/content/zotero/xpcom/data/library.js +++ b/chrome/content/zotero/xpcom/data/library.js @@ -621,11 +621,43 @@ Zotero.Library.prototype._initErase = Zotero.Promise.method(function(env) { return true; }); -Zotero.Library.prototype._eraseData = Zotero.Promise.coroutine(function* (env) { - yield Zotero.DB.queryAsync("DELETE FROM libraries WHERE libraryID=?", this.libraryID); +Zotero.Library.prototype._eraseData = async function (env) { + // Delete attachment files + var attachmentKeys = await Zotero.DB.columnQueryAsync( + "SELECT key FROM items WHERE libraryID=? AND itemID IN " + + "(SELECT itemID FROM itemAttachments WHERE linkMode IN (?, ?))", + [ + this.libraryID, + Zotero.Attachments.LINK_MODE_IMPORTED_FILE, + Zotero.Attachments.LINK_MODE_IMPORTED_URL + ] + ); + if (attachmentKeys.length) { + Zotero.DB.addCurrentCallback('commit', async function () { + for (let key of attachmentKeys) { + try { + let dir = Zotero.Attachments.getStorageDirectoryByLibraryAndKey( + this.libraryID, key + ).path; + await OS.File.removeDir( + dir, + { + ignoreAbsent: true, + ignorePermissions: true + } + ); + } + catch (e) { + Zotero.logError(e); + } + } + }.bind(this)); + } + + await Zotero.DB.queryAsync("DELETE FROM libraries WHERE libraryID=?", this.libraryID); // TODO: Emit event so this doesn't have to be here - yield Zotero.Fulltext.clearLibraryVersion(this.libraryID); -}); + await Zotero.Fulltext.clearLibraryVersion(this.libraryID); +}; Zotero.Library.prototype._finalizeErase = Zotero.Promise.coroutine(function* (env) { Zotero.Libraries.unregister(this.libraryID); diff --git a/test/tests/libraryTest.js b/test/tests/libraryTest.js index a117928edd..98d56f91e6 100644 --- a/test/tests/libraryTest.js +++ b/test/tests/libraryTest.js @@ -262,7 +262,32 @@ describe("Zotero.Library", function() { assert.notOk((yield Zotero.Collections.getAsync(collection.id)), 'collection was unloaded'); assert.notOk((yield Zotero.Items.getAsync(item.id)), 'item was unloaded'); }); + + it("should delete attachment files", async function () { + // My Library + var item1 = await createDataObject('item'); + var attachment1 = await importFileAttachment('test.png', { parentID: item1.id }); + var path1 = attachment1.getFilePath(); + + // Group + var group = await createGroup(); + var libraryID = group.libraryID; + var item2 = await createDataObject('item', { libraryID }); + var attachment2 = await importFileAttachment('test.png', { libraryID, parentID: item2.id }); + var path2 = attachment2.getFilePath(); + + assert.isTrue(await OS.File.exists(path1)); + assert.isTrue(await OS.File.exists(path2)); + + await group.eraseTx(); + + // My Library file should still exist, but group file should be deleted + assert.isTrue(await OS.File.exists(path1)); + assert.isFalse(await OS.File.exists(path2)); + }); }); + + describe("#hasCollections()", function() { it("should throw if called before saving a library", function() { let library = new Zotero.Library();