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.
This commit is contained in:
Dan Stillman 2018-09-26 02:34:42 -04:00
parent f26b1592a3
commit 8fa4cc9387
7 changed files with 142 additions and 186 deletions

View file

@ -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++) {

View file

@ -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);
}
});
}

View file

@ -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();

View file

@ -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()));

View file

@ -562,51 +562,39 @@ Zotero.File = new function(){
/**
* @return {Promise<Boolean>}
*/
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));
})
});

View file

@ -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;

View file

@ -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;