From 8fa4cc9387b5502c51b93552c91136df711ce5b8 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Wed, 26 Sep 2018 02:34:42 -0400 Subject: [PATCH] Fx60: Update Zotero.File.iterateDirectory() signature StopIteration is no longer supported in Firefox 60, so instead of taking a generator function that might throw StopIteration for the second parameter, take a function that is passed to iterator.forEach() that receives an OS.File.DirectoryIterator.Entry for each directory entry. If the function returns a promise, it's waited for. Also update other direct uses of OS.File.DirectoryIterator to remove StopIteration use. --- chrome/content/zotero/fileInterface.js | 23 +-- .../zotero/import/mendeley/mendeleyImport.js | 23 +-- chrome/content/zotero/xpcom/attachments.js | 14 +- chrome/content/zotero/xpcom/dataDirectory.js | 22 +- chrome/content/zotero/xpcom/file.js | 192 ++++++++---------- chrome/content/zotero/xpcom/profile.js | 19 +- chrome/content/zotero/xpcom/zotero.js | 35 ++-- 7 files changed, 142 insertions(+), 186 deletions(-) diff --git a/chrome/content/zotero/fileInterface.js b/chrome/content/zotero/fileInterface.js index 0509f5374e..bbd05957d6 100644 --- a/chrome/content/zotero/fileInterface.js +++ b/chrome/content/zotero/fileInterface.js @@ -238,19 +238,16 @@ var Zotero_File_Interface = new function() { Zotero.debug(`${dir} does not exist`); return dbs; } - await Zotero.File.iterateDirectory(dir, function* (iterator) { - while (true) { - let entry = yield iterator.next(); - if (entry.isDir) continue; - // online.sqlite, counterintuitively, is the default database before you sign in - if (entry.name == 'online.sqlite' || entry.name.endsWith('@www.mendeley.com.sqlite')) { - dbs.push({ - name: entry.name, - path: entry.path, - lastModified: null, - size: null - }); - } + await Zotero.File.iterateDirectory(dir, function (entry) { + if (entry.isDir) return; + // online.sqlite, counterintuitively, is the default database before you sign in + if (entry.name == 'online.sqlite' || entry.name.endsWith('@www.mendeley.com.sqlite')) { + dbs.push({ + name: entry.name, + path: entry.path, + lastModified: null, + size: null + }); } }); for (let i = 0; i < dbs.length; i++) { diff --git a/chrome/content/zotero/import/mendeley/mendeleyImport.js b/chrome/content/zotero/import/mendeley/mendeleyImport.js index 8d693ee6fe..00fff34df5 100644 --- a/chrome/content/zotero/import/mendeley/mendeleyImport.js +++ b/chrome/content/zotero/import/mendeley/mendeleyImport.js @@ -1208,19 +1208,16 @@ Zotero_Import_Mendeley.prototype.deleteNonPrimaryFiles = async function () { let filename = row.path.substr(8); Zotero.debug(`Checking for extra files in ${dir}`); - await Zotero.File.iterateDirectory(dir, function* (iterator) { - while (true) { - let entry = yield iterator.next(); - if (entry.name.startsWith('.zotero') || entry.name == filename) { - continue; - } - Zotero.debug(`Deleting ${entry.path}`); - try { - yield OS.File.remove(entry.path); - } - catch (e) { - Zotero.logError(e); - } + await Zotero.File.iterateDirectory(dir, async function (entry) { + if (entry.name.startsWith('.zotero') || entry.name == filename) { + return; + } + Zotero.debug(`Deleting ${entry.path}`); + try { + await OS.File.remove(entry.path); + } + catch (e) { + Zotero.logError(e); } }); } diff --git a/chrome/content/zotero/xpcom/attachments.js b/chrome/content/zotero/xpcom/attachments.js index 0db4985781..fffce7c66c 100644 --- a/chrome/content/zotero/xpcom/attachments.js +++ b/chrome/content/zotero/xpcom/attachments.js @@ -2113,21 +2113,15 @@ Zotero.Attachments = new function(){ var parent = OS.Path.dirname(path); var iterator = new OS.File.DirectoryIterator(parent); try { - while (true) { - let entry = yield iterator.next(); + yield iterator.forEach((entry) => { if (entry.name.startsWith('.')) { - continue; + return; } numFiles++; if (numFiles > 1) { - break; + iterator.close(); } - } - } - catch (e) { - if (e != StopIteration) { - throw e; - } + }); } finally { iterator.close(); diff --git a/chrome/content/zotero/xpcom/dataDirectory.js b/chrome/content/zotero/xpcom/dataDirectory.js index a845f4bdb6..c0ca29c5b7 100644 --- a/chrome/content/zotero/xpcom/dataDirectory.js +++ b/chrome/content/zotero/xpcom/dataDirectory.js @@ -1012,21 +1012,13 @@ Zotero.DataDirectory = { // Focus the first file/folder in the old directory else if (index == 2) { try { - let it = new OS.File.DirectoryIterator(oldDir); - let entry; - try { - entry = yield it.next(); - } - catch (e) { - if (e != StopIteration) { - throw e; - } - } - finally { - it.close(); - } - if (entry) { - yield Zotero.File.reveal(entry.path); + let firstEntry; + yield Zotero.File.iterateDirectory(oldDir, function (entry, index, iterator) { + firstEntry = entry; + iterator.close(); + }); + if (firstEntry) { + yield Zotero.File.reveal(firstEntry.path); } // Focus the database file in the new directory yield Zotero.File.reveal(OS.Path.join(newDir, this.getDatabaseFilename())); diff --git a/chrome/content/zotero/xpcom/file.js b/chrome/content/zotero/xpcom/file.js index af7feb4813..ddb4842dd9 100644 --- a/chrome/content/zotero/xpcom/file.js +++ b/chrome/content/zotero/xpcom/file.js @@ -562,51 +562,39 @@ Zotero.File = new function(){ /** * @return {Promise} */ - this.directoryIsEmpty = Zotero.Promise.coroutine(function* (path) { - var it = new OS.File.DirectoryIterator(path); + this.directoryIsEmpty = async function (path) { + var iterator = new OS.File.DirectoryIterator(path); + var empty = true; try { - let entry = yield it.next(); - return false; - } - catch (e) { - if (e != StopIteration) { - throw e; - } + await iterator.forEach(() => { + iterator.close(); + empty = false; + }); } finally { - it.close(); + iterator.close(); } - return true; - }); + return empty; + }; /** - * Run a generator with an OS.File.DirectoryIterator, closing the - * iterator when done. Promises yielded by the generator are awaited. + * Run a function on each entry in a directory * - * The DirectoryIterator is passed as the first parameter to the generator. + * 'entry' is an instance of OS.File.DirectoryIterator.Entry: * - * Zotero.File.iterateDirectory(path, function* (iterator) { - * while (true) { - * let entry = yield iterator.next(); - * let contents = yield Zotero.File.getContentsAsync(entry.path); - * [...] - * } - * }) + * https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/OSFile.jsm/OS.File.DirectoryIterator.Entry * * @return {Promise} */ - this.iterateDirectory = function (path, generator) { + this.iterateDirectory = async function (path, onEntry) { var iterator = new OS.File.DirectoryIterator(path); - return Zotero.Promise.coroutine(generator)(iterator) - .catch(function (e) { - if (e != StopIteration) { - throw e; - } - }) - .finally(function () { + try { + await iterator.forEach(onEntry); + } + finally { iterator.close(); - }); + } } @@ -681,85 +669,82 @@ Zotero.File = new function(){ Zotero.debug("Moving files in " + oldDir); - yield Zotero.File.iterateDirectory(oldDir, function* (iterator) { - while (true) { - let entry = yield iterator.next(); - let dest = newDir + entry.path.substr(rootDir.length); - - // entry.isDir can be false for some reason on Travis, causing spurious test failures - if (Zotero.automatedTest && !entry.isDir && (yield OS.File.stat(entry.path)).isDir) { - Zotero.debug("Overriding isDir for " + entry.path); - entry.isDir = true; + yield Zotero.File.iterateDirectory(oldDir, async function (entry) { + var dest = newDir + entry.path.substr(rootDir.length); + + // entry.isDir can be false for some reason on Travis, causing spurious test failures + if (Zotero.automatedTest && !entry.isDir && (await OS.File.stat(entry.path)).isDir) { + Zotero.debug("Overriding isDir for " + entry.path); + entry.isDir = true; + } + + // Move files in directory + if (!entry.isDir) { + try { + await OS.File.move( + entry.path, + dest, + { + noOverwrite: options + && options.noOverwrite + && options.noOverwrite(entry.path) + } + ); } + catch (e) { + checkError(e); + Zotero.debug("Error moving " + entry.path); + addError(e); + } + } + else { + // Move directory with external command if possible and the directory doesn't + // already exist in target + let moved = false; - // Move files in directory - if (!entry.isDir) { + if (useCmd && !(await OS.File.exists(dest))) { + Zotero.debug(`Moving ${entry.path} with ${cmd}`); + let args = [entry.path, dest]; try { - yield OS.File.move( - entry.path, - dest, - { - noOverwrite: options - && options.noOverwrite - && options.noOverwrite(entry.path) - } - ); + await Zotero.Utilities.Internal.exec(cmd, args); + moved = true; } catch (e) { checkError(e); - Zotero.debug("Error moving " + entry.path); - addError(e); + Zotero.debug(e, 1); } } - else { - // Move directory with external command if possible and the directory doesn't - // already exist in target - let moved = false; - - if (useCmd && !(yield OS.File.exists(dest))) { - Zotero.debug(`Moving ${entry.path} with ${cmd}`); - let args = [entry.path, dest]; - try { - yield Zotero.Utilities.Internal.exec(cmd, args); - moved = true; - } - catch (e) { - checkError(e); - Zotero.debug(e, 1); - } + + + // If can't use command, try moving with OS.File.move(). Technically this is + // unsupported for directories, but it works on all platforms as long as noCopy + // is set (and on some platforms regardless) + if (!moved && useFunction) { + Zotero.debug(`Moving ${entry.path} with OS.File`); + try { + await OS.File.move( + entry.path, + dest, + { + noCopy: true + } + ); + moved = true; } - - - // If can't use command, try moving with OS.File.move(). Technically this is - // unsupported for directories, but it works on all platforms as long as noCopy - // is set (and on some platforms regardless) - if (!moved && useFunction) { - Zotero.debug(`Moving ${entry.path} with OS.File`); - try { - yield OS.File.move( - entry.path, - dest, - { - noCopy: true - } - ); - moved = true; - } - catch (e) { - checkError(e); - Zotero.debug(e, 1); - } + catch (e) { + checkError(e); + Zotero.debug(e, 1); } - - // Otherwise, recurse into subdirectories to copy files individually - if (!moved) { - try { - yield moveSubdirs(entry.path, depth - 1); - } - catch (e) { - checkError(e); - addError(e); - } + } + + // Otherwise, recurse into subdirectories to copy files individually + if (!moved) { + try { + await moveSubdirs(entry.path, depth - 1); + } + catch (e) { + checkError(e); + addError(e); } } } @@ -983,11 +968,8 @@ Zotero.File = new function(){ unixMode: 0o755 }); - return this.iterateDirectory(source, function* (iterator) { - while (true) { - let entry = yield iterator.next(); - yield OS.File.copy(entry.path, OS.Path.join(target, entry.name)); - } + return this.iterateDirectory(source, function (entry) { + return OS.File.copy(entry.path, OS.Path.join(target, entry.name)); }) }); diff --git a/chrome/content/zotero/xpcom/profile.js b/chrome/content/zotero/xpcom/profile.js index 4a06a71f7d..136b2f8ff0 100644 --- a/chrome/content/zotero/xpcom/profile.js +++ b/chrome/content/zotero/xpcom/profile.js @@ -283,17 +283,14 @@ Zotero.Profile = { */ _getProfilesInDir: Zotero.Promise.coroutine(function* (profilesDir) { var dirs = []; - yield Zotero.File.iterateDirectory(profilesDir, function* (iterator) { - while (true) { - let entry = yield iterator.next(); - // entry.isDir can be false for some reason on Travis, causing spurious test failures - if (Zotero.automatedTest && !entry.isDir && (yield OS.File.stat(entry.path)).isDir) { - Zotero.debug("Overriding isDir for " + entry.path); - entry.isDir = true; - } - if (entry.isDir && (yield OS.File.exists(OS.Path.join(entry.path, "prefs.js")))) { - dirs.push(entry.path); - } + yield Zotero.File.iterateDirectory(profilesDir, async function (entry) { + // entry.isDir can be false for some reason on Travis, causing spurious test failures + if (Zotero.automatedTest && !entry.isDir && (await OS.File.stat(entry.path)).isDir) { + Zotero.debug("Overriding isDir for " + entry.path); + entry.isDir = true; + } + if (entry.isDir && (await OS.File.exists(OS.Path.join(entry.path, "prefs.js")))) { + dirs.push(entry.path); } }); return dirs; diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js index c8d2c20b7a..f8d8ccb3d1 100644 --- a/chrome/content/zotero/xpcom/zotero.js +++ b/chrome/content/zotero/xpcom/zotero.js @@ -499,28 +499,25 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js"); let lastError; // Delete all files in directory rather than removing directory, in case it's // a symlink - yield Zotero.File.iterateDirectory(dataDir, function* (iterator) { - while (true) { - let entry = yield iterator.next(); - // Don't delete some files - if (entry.name == 'pipes') { - continue; + yield Zotero.File.iterateDirectory(dataDir, async function (entry) { + // Don't delete some files + if (entry.name == 'pipes') { + return; + } + Zotero.debug("Deleting " + entry.path); + try { + if (entry.isDir) { + await OS.File.removeDir(entry.path); } - Zotero.debug("Deleting " + entry.path); - try { - if (entry.isDir) { - yield OS.File.removeDir(entry.path); - } - else { - yield OS.File.remove(entry.path); - } - } - // Keep trying to delete as much as we can - catch (e) { - lastError = e; - Zotero.logError(e); + else { + await OS.File.remove(entry.path); } } + // Keep trying to delete as much as we can + catch (e) { + lastError = e; + Zotero.logError(e); + } }); if (lastError) { throw lastError;