Fix: 修复Python Online板卡下「本地文件系统」连续多次读取目录时报错

This commit is contained in:
王立帮
2024-11-27 14:22:02 +08:00
parent e0534d607d
commit 624012e96f
7 changed files with 542 additions and 90 deletions

View File

@@ -1,5 +1,5 @@
import * as path from 'path';
import { FileTree } from 'mixly';
import { FileTree, Debug } from 'mixly';
import FileSystemFS from './filesystem-fs';
@@ -9,36 +9,36 @@ export default class FileSystemFileTree extends FileTree {
}
async readFolder(inPath) {
const fs = this.getFS();
const [, status] = await fs.isDirectory(inPath);
let output = [];
if (!status) {
return output;
}
const result = await fs.readDirectory(inPath);
let children = [];
if (result.length == 2) {
children = result[1];
}
for (let data of children) {
const dataPath = path.join(inPath, data);
const [, isDirectory] = await fs.isDirectory(dataPath);
if (isDirectory) {
const [, isDirEmpty] = await fs.isDirectoryEmpty(dataPath);
output.push({
type: 'folder',
id: dataPath,
children: !isDirEmpty,
title: `/${this.getRootFolderName()}${dataPath}`
});
} else {
output.push({
type: 'file',
id: dataPath,
children: false,
title: `/${this.getRootFolderName()}${dataPath}`
});
try {
const fs = this.getFS();
const status = await fs.isDirectory(inPath);
if (!status) {
return output;
}
const children = await fs.readDirectory(inPath);
for (let data of children) {
const dataPath = path.join(inPath, data);
const isDirectory = await fs.isDirectory(dataPath);
if (isDirectory) {
const isDirEmpty = await fs.isDirectoryEmpty(dataPath);
output.push({
type: 'folder',
id: dataPath,
children: !isDirEmpty,
title: `/${this.getRootFolderName()}${dataPath}`
});
} else {
output.push({
type: 'file',
id: dataPath,
children: false,
title: `/${this.getRootFolderName()}${dataPath}`
});
}
}
} catch (error) {
Debug.error(error);
}
return output;
}

View File

@@ -1,16 +1,27 @@
import { WebAccessFS } from '@zenfs/dom';
import { FS } from 'mixly';
export default class FileSystemFS extends FS {
static {
this.pool = window.workerpool.pool('../common/modules/mixly-modules/workers/web/file-system-access.js', {
workerOpts: {
name: 'pyodideFileSystemAccess'
},
workerType: 'web'
});
class WebAccessFSExt extends WebAccessFS {
constructor(handle) {
super(handle);
}
async readFile(path) {
const handle = await this.getHandle(path);
if (handle instanceof window.FileSystemFileHandle) {
const file = await handle.getFile();
const text = await file.text();
return text;
}
return '';
}
}
export default class FileSystemFS extends FS {
#fs_ = null;
constructor() {
super();
}
@@ -21,32 +32,32 @@ export default class FileSystemFS extends FS {
if (permissionStatus !== 'granted') {
throw new Error('readwrite access to directory not granted');
}
await FileSystemFS.pool.exec('addFileSystemHandler', [directoryHandle]);
this.#fs_ = new WebAccessFSExt(directoryHandle);
return directoryHandle;
}
async createFile(filePath) {
return this.writeFile(filePath, '');
return this.#fs_.createFile(filePath, '');
}
async readFile(path) {
return FileSystemFS.pool.exec('readFile', [path, 'utf8']);
return this.#fs_.readFile(path);
}
async writeFile(path, data) {
return FileSystemFS.pool.exec('writeFile', [path, data, 'utf8']);
return this.#fs_.writeFile(path, data, 'utf8');
}
async isFile(path) {
const [error, stats] = await FileSystemFS.pool.exec('stat', [path]);
if (stats && stats.mode === 33188) {
return [error, true];
const stats = await this.#fs_.stat(path);
if (stats && stats.mode === 33279) {
return true;
}
return [error, false];
return false;
}
async renameFile(oldFilePath, newFilePath) {
return await FileSystemFS.pool.exec('rename', [oldFilePath, newFilePath]);
return await this.#fs_.rename(oldFilePath, newFilePath);
}
async moveFile(oldFilePath, newFilePath) {
@@ -54,43 +65,40 @@ export default class FileSystemFS extends FS {
}
async deleteFile(filePath) {
return FileSystemFS.pool.exec('unlink', [filePath]);
return this.#fs_.unlink(filePath);
}
async createDirectory(folderPath) {
return FileSystemFS.pool.exec('mkdir', [folderPath, 0o777]);
return this.#fs_.mkdir(folderPath, 0o777);
}
async readDirectory(path) {
const result = await FileSystemFS.pool.exec('readdir', [path]);
if (result[0]) {
return [result[0], null];
}
const result = await this.#fs_.readdir(path);
return result;
}
async isDirectory(path) {
const [error, stats] = await FileSystemFS.pool.exec('stat', [path]);
if (stats && stats.mode === 33188) {
return [error, false];
const stats = await this.#fs_.stat(path);
if (stats && stats.mode === 16895) {
return true;
}
return [error, true];
return false;
}
async isDirectoryEmpty(path) {
const [error, result = []] = await this.readDirectory(path);
return [error, !result?.length];
const result = await this.readDirectory(path);
return !result?.length;
}
async renameDirectory(oldFolderPath, newFolderPath) {
return await FileSystemFS.pool.exec('rename', [oldFolderPath, newFolderPath]);
return this.#fs_.rename(oldFolderPath, newFolderPath);
}
async moveDirectory(oldFolderPath, newFolderPath) {
return FileSystemFS.pool.exec('rename', [oldFolderPath, newFolderPath]);
return this.#fs_.rename(oldFolderPath, newFolderPath);
}
async deleteDirectory(folderPath) {
return FileSystemFS.pool.exec('rmdir', [folderPath]);
return this.#fs_.rmdir(folderPath);
}
}

View File

@@ -108,16 +108,17 @@ export default class StatusBarFileSystem extends PageBase {
const filePath = selected[0].id;
this.#fileTree_.showProgress();
const fs = this.#fileTree_.getFS();
const [error, result] = await fs.readFile(filePath);
if (error) {
this.hideEditor();
this.#fileTree_.deselectAll();
} else {
try {
const result = await fs.readFile(filePath);
this.showEditor();
this.#editor_.setValue(result);
this.#editor_.scrollToTop();
this.#editor_.focus();
this.setStatus(false);
} catch (error) {
Debug.error(error);
this.hideEditor();
this.#fileTree_.deselectAll();
}
this.#fileTree_.hideProgress();
});