fix: synchronise case-only file renames safely

This commit is contained in:
metrovoc
2026-07-14 10:39:45 +09:00
committed by vorotamoroz
parent ba7ea27d0c
commit 869a893c19
362 changed files with 722 additions and 380 deletions
@@ -36,8 +36,27 @@ export class NodeFileSystemAdapter implements IFileSystemAdapter<NodeFile, NodeF
return this.path.normalisePath(p as string);
}
private async hasExactPathCase(pathStr: string): Promise<boolean> {
try {
const segments = pathStr.split("/").filter((segment) => segment !== "");
let currentPath = this.basePath;
for (const segment of segments) {
const entries = await fs.readdir(currentPath);
if (!entries.includes(segment)) return false;
currentPath = path.join(currentPath, segment);
}
return segments.length > 0;
} catch {
return false;
}
}
async getAbstractFileByPath(p: FilePath | string): Promise<NodeFile | null> {
const pathStr = this.normalisePath(p);
if (!this.fileCache.has(pathStr) && !(await this.hasExactPathCase(pathStr))) {
this.fileCache.delete(pathStr);
return null;
}
return await this.refreshFile(pathStr);
}
@@ -74,6 +93,15 @@ export class NodeFileSystemAdapter implements IFileSystemAdapter<NodeFile, NodeF
return Array.from(this.fileCache.values());
}
async renameFile(file: NodeFile, newPath: string): Promise<NodeFile> {
const oldPath = file.path;
await this.vault.rename(file, newPath);
this.fileCache.delete(oldPath);
const renamedFile = await this.refreshFile(newPath);
if (!renamedFile) throw new Error(`Could not find renamed file: ${newPath}`);
return renamedFile;
}
async statFromNative(file: NodeFile): Promise<UXStat> {
return file.stat;
}