Manage projectcontext objects correctly on preview - #13804
Conversation
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
|
This last failing test is interesting. If I'm reading the messages correctly, we previously had:
Now that things are properly connected, the test fails. But it seems that this test shouldn't really even be there? |
f89c530 to
6db3515
Compare
There was a problem hiding this comment.
The test failure in render-output-dir.test.ts (and the other playwright docs/playwright/embed-resources/issue-11860/main.qmd) is caused by a logic ordering issue at:
quarto-cli/src/command/render/render-shared.ts
Lines 51 to 63 in e48007d
The change on lines 51-52 now always creates a singleFileProjectContext as fallback:
let context = pContext || (await projectContext(path, nbContext, options)) ||
(await singleFileProjectContext(path, nbContext, options));This means context is never null when the --output-dir check runs on line 57:
if (!context && options.flags?.outputDir) {
The synthetic project creation for --output-dir is now unreachable. The fix could be to check for --output-dir before falling back to singleFileProjectContext, if we really need this fallback. I am unsure about that and its relation to preview fix which is the topic of this PR.
For example
diff --git a/src/command/render/render-shared.ts b/src/command/render/render-shared.ts
--- a/src/command/render/render-shared.ts
+++ b/src/command/render/render-shared.ts
@@ -48,9 +48,7 @@ export async function render(
const nbContext = pContext?.notebookContext || notebookContext();
// determine target context/files
- // let context = await projectContext(path, nbContext, options);
- let context = pContext || (await projectContext(path, nbContext, options)) ||
- (await singleFileProjectContext(path, nbContext, options));
+ let context = pContext || (await projectContext(path, nbContext, options));
// Create a synthetic project when --output-dir is used without a project file
// This creates a temporary .quarto directory to manage the render, which must
@@ -62,6 +60,11 @@ export async function render(
options.forceClean = options.flags.clean !== false;
}
+ // Only fall back to singleFileProjectContext if we don't have a context yet
+ if (!context) {
+ context = await singleFileProjectContext(path, nbContext, options);
+ }
+
// set env var if requested
if (context && options.setProjectDir) {
// FIXME we can't set environment variables like this with asyncs flying around6db3515 to
451f7dc
Compare
Move singleFileProjectContext fallback after the --output-dir check so the synthetic project creation path remains reachable. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
451f7dc to
c3384a5
Compare
Documents the project context lifecycle fix from #13804 that resolves intermittent preview crashes when editing notebooks and qmd files.
Documents the project context lifecycle fix from #13804 that resolves intermittent preview crashes when editing notebooks and qmd files.
Fix preview issue after #13804 changing how project context is handled now by being reused across project preview render.
During Jupyter-based preview, each re-render created a new numbered .quarto_ipynb variant (test.quarto_ipynb_1, _2, etc.) that persisted on disk even with keep-ipynb: false. Regression from v1.8.27 to v1.9 caused by the collision-avoidance loop from #13804 interacting with cache invalidation that deleted the cache entry but not the file. - Add invalidateForFile() to FileInformationCacheMap that deletes the transient notebook file from disk before removing the cache entry - Pass ProjectContext from cmd.ts to preview() via pProject parameter, eliminating redundant context creation that orphaned a .quarto_ipynb at startup - Add unit tests for cache invalidation and manual preview test fixtures Fixes #14281
PR #13804 made project always non-null via singleFileProjectContext(), causing the initialPath computation to always take the project branch. This produced URLs like http://localhost:PORT/hello.html instead of http://localhost:PORT/ for standalone files, breaking Posit Workbench proxy access. Guard with project.isSingleFile so single-file previews use root path. Extract computation into previewInitialPath() for testability. Fixes #14298
PR #13804 made project always non-null via singleFileProjectContext(), causing the initialPath computation to always take the project branch. This produced URLs like http://localhost:PORT/hello.html instead of http://localhost:PORT/ for standalone files, breaking Posit Workbench proxy access. Guard with project.isSingleFile so single-file previews use root path. Extract computation into previewInitialPath() for testability. Fixes #14298
PR #13804 made project always non-null via singleFileProjectContext(), causing the initialPath computation to always take the project branch. This produced URLs like http://localhost:PORT/hello.html instead of http://localhost:PORT/ for standalone files, breaking Posit Workbench proxy access. Guard with project.isSingleFile so single-file previews use root path. Extract computation into previewInitialPath() for testability. Fixes #14298 [backport] Fix preview browse URL for single-file documents (#14298)
Fix preview browse URL for single-file documents After #13804 made the project variable always non-null via singleFileProjectContext(), two code paths in preview() broke for single-file documents: the browse URL included the output filename (e.g. /hello.html instead of /), and GET / returned 404 because the project handler expected index.html as the default file. Guard both the URL path computation and the handler selection with !project.isSingleFile so single-file previews use the correct handler and root URL. Extract URL path logic into a testable previewInitialPath() function. - Fix initialPath using relative path instead of empty string - Fix handler selection using projectHtmlFileRequestHandler with wrong default file instead of htmlFileRequestHandler - Add unit tests for previewInitialPath() (single-file, project, project-subdir, undefined-project cases) - Add manual preview test entries T17-T19 Fixes #14298
[backport] Fix preview browse URL for single-file documents Backport of #14300. After #13804 made the project variable always non-null via singleFileProjectContext(), single-file preview broke: the browse URL included the output filename and GET / returned 404. Guard both the URL path computation and handler selection with !project.isSingleFile. - Fix initialPath using relative path instead of empty string - Fix handler selection using wrong default file for single files - Add unit tests for previewInitialPath() - Add manual preview test entries and plain.qmd fixture Fixes #14298
…14699) Previewing a knitr document in a project subdirectory — running `quarto preview` from that subdirectory with a bare filename, the shape RStudio's Render button uses — failed with `rmarkdown:::abs_path(input): The file 'doc.qmd' does not exist.` This is a regression from #13804, live in stable 1.9.38 and main. #13804 shared one ProjectContext (and its fileInformationCache) between preview's format-resolution and render steps, with cache keys normalized to absolute paths, but the cached ExecutionTarget.input/source kept whatever form the caller passed. Format-resolution seeds the cache with a cwd-relative bare filename; renderProject later looks the same file up by its absolute path, collides on the same cache key, and inherits the stale relative input. The knitr subprocess runs with cwd set to the project directory, where the subdirectory-relative filename doesn't resolve. Normalize the path to absolute once, at the single convergence point (fileExecutionEngineAndTarget in src/execute/engine.ts), so target.source/target.input are always absolute regardless of how the caller spelled the path — consistent with project renders, which were already absolute. This also fixes #12401: QUARTO_DOCUMENT_PATH was relative for single-file renders but absolute for project renders, since both derive from target.source. Adds a regression test exercising the real knitr subprocess and a manual preview-matrix entry (T33) with an on-disk fixture, since `quarto preview` itself can't run under the automated test harness. Fixes #14683, fixes #12401, fixes #14151
This should close a few of our
quarto previewintermittent issues whose symptom is a missingquarto_ipynbfile.See, eg, #12992.