diff --git a/news/changelog-1.6.md b/news/changelog-1.6.md index d6f820934fb..1743764ed19 100644 --- a/news/changelog-1.6.md +++ b/news/changelog-1.6.md @@ -75,6 +75,7 @@ All changes included in 1.6: ### Websites +- ([#2671](https://github.com/quarto-dev/quarto-cli/issues/2671)): Ensure that `--output-dir` works across filesystem boundaries. - ([#8932](https://github.com/quarto-dev/quarto-cli/issues/8932)): Escape render ids in markdown pipeline to allow special characters in sidebars/navbars, etc. - ([#10616](https://github.com/quarto-dev/quarto-cli/issues/10268)): Add a `z-index` setting to the 'back to top' button to ensure it is always visible. diff --git a/src/command/render/project.ts b/src/command/render/project.ts index a808e02cc7a..76fbbeb175d 100644 --- a/src/command/render/project.ts +++ b/src/command/render/project.ts @@ -4,7 +4,7 @@ * Copyright (C) 2020-2022 Posit Software, PBC */ -import { ensureDirSync, existsSync } from "../../deno_ral/fs.ts"; +import { ensureDirSync, existsSync, safeMoveSync } from "../../deno_ral/fs.ts"; import { dirname, isAbsolute, join, relative } from "../../deno_ral/path.ts"; import { info, warning } from "../../deno_ral/log.ts"; import { mergeProjectMetadata } from "../../config/metadata.ts"; @@ -530,7 +530,7 @@ export async function renderProject( if (!renderedFile.isTransient) { const outputFile = join(formatOutputDir, renderedFile.file); ensureDirSync(dirname(outputFile)); - Deno.renameSync(join(projDir, renderedFile.file), outputFile); + safeMoveSync(join(projDir, renderedFile.file), outputFile); } // files dir diff --git a/src/core/path.ts b/src/core/path.ts index 75331568464..a10fa62926e 100644 --- a/src/core/path.ts +++ b/src/core/path.ts @@ -18,7 +18,9 @@ import { import { warning } from "../deno_ral/log.ts"; -import { existsSync, expandGlobSync } from "../deno_ral/fs.ts"; +export { safeRemoveSync } from "../deno_ral/fs.ts"; + +import { existsSync, expandGlobSync, safeRemoveSync } from "../deno_ral/fs.ts"; import * as ld from "./lodash.ts"; @@ -41,19 +43,6 @@ export function safeRemoveIfExists(file: string) { } } -export function safeRemoveSync( - file: string, - options: Deno.RemoveOptions = {}, -) { - try { - Deno.removeSync(file, options); - } catch (e) { - if (existsSync(file)) { - throw e; - } - } -} - export function removeIfEmptyDir(dir: string): boolean { if (existsSync(dir)) { let empty = true; diff --git a/src/deno_ral/fs.ts b/src/deno_ral/fs.ts index ca640075c98..cf229454518 100644 --- a/src/deno_ral/fs.ts +++ b/src/deno_ral/fs.ts @@ -6,6 +6,8 @@ import { fromFileUrl } from "./path.ts"; import { resolve, SEP as SEPARATOR } from "./path.ts"; +import { copySync } from "fs/copy"; +import { existsSync } from "fs/exists"; export { ensureDir, ensureDirSync } from "fs/ensure-dir"; export { existsSync } from "fs/exists"; @@ -74,3 +76,31 @@ export function toPathString( ): string { return pathUrl instanceof URL ? fromFileUrl(pathUrl) : pathUrl; } + +export function safeMoveSync( + src: string, + dest: string, +): void { + try { + Deno.renameSync(src, dest); + } catch (err) { + if (err.code !== "EXDEV") { + throw err; + } + copySync(src, dest, { overwrite: true }); + safeRemoveSync(src, { recursive: true }); + } +} + +export function safeRemoveSync( + file: string, + options: Deno.RemoveOptions = {}, +) { + try { + Deno.removeSync(file, options); + } catch (e) { + if (existsSync(file)) { + throw e; + } + } +}