Skip to content

Commit e3a24a6

Browse files
committed
Fix quarto create producing read-only files from system packages
When Quarto is installed via system packages (e.g. .deb, Nix), resource files may be read-only. Files copied from these resources by `quarto create` inherit the read-only permissions, preventing users from editing them. Add ensureUserWritable() to src/deno_ral/fs.ts (alongside the safeModeFromFile/safeChmodSync it depends on) and call it after every file copy in artifact-shared.ts and project-create.ts.
1 parent 6883f30 commit e3a24a6

4 files changed

Lines changed: 29 additions & 2 deletions

File tree

news/changelog-1.10.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
All changes included in 1.10:
22

3+
## Commands
34

5+
### `quarto create`
6+
7+
- ([#14250](https://github.com/quarto-dev/quarto-cli/issues/14250)): Fix `quarto create` producing read-only files when Quarto is installed via system packages (e.g., `.deb`). Files copied from installed resources now have user-write permission ensured.

src/command/create/artifacts/artifact-shared.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ import { gfmAutoIdentifier } from "../../../core/pandoc/pandoc-id.ts";
1212
import { coerce } from "semver/mod.ts";
1313
import { info } from "../../../deno_ral/log.ts";
1414
import { basename, dirname, join, relative } from "../../../deno_ral/path.ts";
15-
import { ensureDirSync, walkSync } from "../../../deno_ral/fs.ts";
15+
import {
16+
ensureDirSync,
17+
ensureUserWritable,
18+
walkSync,
19+
} from "../../../deno_ral/fs.ts";
1620
import { renderEjs } from "../../../core/ejs.ts";
1721
import { safeExistsSync } from "../../../core/path.ts";
1822
import { CreateDirective, CreateDirectiveData } from "../cmd-types.ts";
@@ -116,6 +120,7 @@ const renderArtifact = (
116120
}
117121
ensureDirSync(dirname(target));
118122
Deno.copyFileSync(src, target);
123+
ensureUserWritable(target);
119124
return target;
120125
}
121126
};

src/deno_ral/fs.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,15 @@ export function safeChmodSync(path: string, mode: number): void {
191191
}
192192
}
193193
}
194+
195+
/**
196+
* Ensure a file has user write permission. Files copied from installed
197+
* resources (e.g. system packages) may be read-only, but users expect
198+
* to edit files created by `quarto create`. No-op on Windows.
199+
*/
200+
export function ensureUserWritable(path: string): void {
201+
const mode = safeModeFromFile(path);
202+
if (mode !== undefined && !(mode & 0o200)) {
203+
safeChmodSync(path, mode | 0o200);
204+
}
205+
}

src/project/project-create.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55
*/
66

77
import * as ld from "../core/lodash.ts";
8-
import { ensureDirSync, existsSync } from "../deno_ral/fs.ts";
8+
import {
9+
ensureDirSync,
10+
ensureUserWritable,
11+
existsSync,
12+
} from "../deno_ral/fs.ts";
913
import { basename, dirname, join } from "../deno_ral/path.ts";
1014
import { info } from "../deno_ral/log.ts";
1115

@@ -139,6 +143,7 @@ export async function projectCreate(options: ProjectCreateOptions) {
139143
if (!existsSync(dest)) {
140144
ensureDirSync(dirname(dest));
141145
copyTo(src, dest);
146+
ensureUserWritable(dest);
142147
if (!options.quiet) {
143148
info("- Created " + displayName, { indent: 2 });
144149
}
@@ -256,6 +261,7 @@ function projectMarkdownFile(
256261
const name = basename(from);
257262
const target = join(dirname(path), name);
258263
copyTo(from, target);
264+
ensureUserWritable(target);
259265
});
260266

261267
return subdirectory ? join(subdirectory, name) : name;

0 commit comments

Comments
 (0)