diff --git a/src/handlers/onDidSaveTextDocument.ts b/src/handlers/onDidSaveTextDocument.ts index 7007768..1ac3329 100644 --- a/src/handlers/onDidSaveTextDocument.ts +++ b/src/handlers/onDidSaveTextDocument.ts @@ -265,7 +265,7 @@ export async function onDidSaveTextDocument(document: vscode.TextDocument) { } } - // Copy files + // Copy files/directories for (const [oldPath, newPath] of copiedLines) { try { // Create directory structure if needed @@ -274,13 +274,15 @@ export async function onDidSaveTextDocument(document: vscode.TextDocument) { if (!fs.existsSync(dirPath)) { fs.mkdirSync(dirPath, { recursive: true }); } - if (!isDir) { - // Copy the file to the new location + + if (isDir) { + fs.cpSync(oldPath, newPath, { recursive: true }); + } else { fs.copyFileSync(oldPath, newPath); } } catch (error) { vscode.window.showErrorMessage( - `Failed to copy file: ${formatPath(oldPath)} to ${newPath.replace( + `Failed to copy: ${formatPath(oldPath)} to ${newPath.replace( currentPath + path.sep, "" )} - ${error}` diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts index 513f4aa..9eabf11 100644 --- a/src/test/extension.test.ts +++ b/src/test/extension.test.ts @@ -918,6 +918,52 @@ suite("oil.code", () => { }); }); + test("Copy non-empty directory and rename preserves nested files", async () => { + const workspaceUri = vscode.workspace.workspaceFolders![0].uri; + const sourceDirUri = vscode.Uri.joinPath(workspaceUri, "test"); + const sourceFileUri = vscode.Uri.joinPath(sourceDirUri, "test.md"); + const testContent = `# Test${newline}Nested file content.`; + + await vscode.workspace.fs.createDirectory(sourceDirUri); + await vscode.workspace.fs.writeFile( + sourceFileUri, + Buffer.from(testContent, "utf-8") + ); + + await vscode.commands.executeCommand("oil-code.open"); + await waitForDocumentText(["/000 ../", "/001 test/"]); + + const editor = vscode.window.activeTextEditor; + assert.ok(editor, "No active editor"); + + // Copy and rename non-empty directory. + await editor.edit((editBuilder) => { + editBuilder.insert(new vscode.Position(2, 0), `${newline}/001 test2/`); + }); + + await saveFile(); + + await waitForDocumentText(["/000 ../", "/001 test/", "/002 test2/"]); + await assertProjectFileStructure([ + "test/", + " test.md", + "test2/", + " test.md", + ]); + + const copiedFileUri = vscode.Uri.joinPath(workspaceUri, "test2", "test.md"); + const copiedFileContent = await vscode.workspace.fs.readFile(copiedFileUri); + assert.strictEqual( + copiedFileContent.toString(), + testContent, + "Copied directory did not preserve nested file content" + ); + + editor.selection = new vscode.Selection(2, 0, 2, 0); + await vscode.commands.executeCommand("oil-code.select"); + await waitForDocumentText(["/000 ../", "/003 test.md"]); + }); + test("Copy and move file in one action", async () => { await vscode.commands.executeCommand("oil-code.open"); await waitForDocumentText("/000 ../");