Skip to content

Commit f25fa5d

Browse files
authored
🐛(sync) Google Drive ensureDirExists() 接口语义不一致 (#1391)
1 parent 61dd5f4 commit f25fa5d

2 files changed

Lines changed: 44 additions & 20 deletions

File tree

packages/filesystem/googledrive/googledrive.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,38 @@ describe("GoogleDriveFileSystem", () => {
2525

2626
await expect(fs.delete("missing.txt")).resolves.toBeUndefined();
2727
});
28+
29+
it("ensureDirExists should create missing nested directories and return final id", async () => {
30+
const fs = new GoogleDriveFileSystem("/", "token");
31+
const findSpy = vi.spyOn(fs, "findFolderByName").mockResolvedValue(null);
32+
const createSpy = vi
33+
.spyOn(fs, "createFolder")
34+
.mockResolvedValueOnce({ id: "id-A", name: "A" })
35+
.mockResolvedValueOnce({ id: "id-B", name: "B" });
36+
37+
await expect(fs.ensureDirExists("/A/B")).resolves.toBe("id-B");
38+
39+
expect(findSpy.mock.calls).toEqual([
40+
["A", "appDataFolder"],
41+
["B", "id-A"],
42+
]);
43+
expect(createSpy.mock.calls).toEqual([
44+
["A", "appDataFolder"],
45+
["B", "id-A"],
46+
]);
47+
});
48+
49+
it("writer should ensure directory from root when filesystem is opened in subdir", async () => {
50+
const fs = new GoogleDriveFileSystem("/Base", "token");
51+
const writer = await fs.create("file.txt");
52+
const ensureSpy = vi.spyOn(fs, "ensureDirExists").mockResolvedValue("base-id");
53+
const findSpy = vi.spyOn(fs, "findFileInDirectory").mockResolvedValue(null);
54+
const requestSpy = vi.spyOn(fs, "request").mockResolvedValue({});
55+
56+
await expect(writer.write("content")).resolves.toBeUndefined();
57+
58+
expect(ensureSpy).toHaveBeenCalledWith("/Base");
59+
expect(findSpy).toHaveBeenCalledWith("file.txt", "base-id");
60+
expect(requestSpy).toHaveBeenCalledTimes(1);
61+
});
2862
});

packages/filesystem/googledrive/googledrive.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ export default class GoogleDriveFileSystem implements FileSystem {
4040
}
4141

4242
const fullPath = joinPath(this.path, dir);
43+
await this.ensureDirPath(fullPath);
44+
}
45+
46+
private async ensureDirPath(fullPath: string): Promise<string> {
47+
if (fullPath === "/" || fullPath === "") {
48+
return "appDataFolder";
49+
}
50+
4351
const dirs = fullPath.split("/").filter(Boolean);
4452

4553
// 从根目录开始逐级创建目录
@@ -69,7 +77,7 @@ export default class GoogleDriveFileSystem implements FileSystem {
6977
parentId = folderId;
7078
}
7179

72-
return Promise.resolve();
80+
return parentId;
7381
}
7482
async findFolderByName(name: string, parentId: string): Promise<{ id: string; name: string } | null> {
7583
const query = `name='${name}' and mimeType='application/vnd.google-apps.folder' and '${parentId}' in parents and trashed=false`;
@@ -315,24 +323,6 @@ export default class GoogleDriveFileSystem implements FileSystem {
315323

316324
// 确保目录存在并返回目录ID,优化Writer避免重复获取
317325
async ensureDirExists(dirPath: string): Promise<string> {
318-
if (dirPath === "/" || dirPath === "") {
319-
return "appDataFolder";
320-
}
321-
322-
// 先检查缓存
323-
const cachedId = this.pathToIdCache.get(dirPath);
324-
if (cachedId) {
325-
return cachedId;
326-
}
327-
328-
// 如果没有缓存,使用getFileId方法
329-
const foundId = await this.getFileId(dirPath);
330-
if (!foundId) {
331-
throw new Error(`Failed to create or find directory: ${dirPath}`);
332-
}
333-
334-
// 缓存结果
335-
this.pathToIdCache.set(dirPath, foundId);
336-
return foundId;
326+
return this.ensureDirPath(dirPath);
337327
}
338328
}

0 commit comments

Comments
 (0)