Skip to content

fix: init validation, build-sbf lockfile, profile server truncation#99

Merged
L0STE merged 4 commits intomasterfrom
fix/issues-91-92-94
Mar 27, 2026
Merged

fix: init validation, build-sbf lockfile, profile server truncation#99
L0STE merged 4 commits intomasterfrom
fix/issues-91-92-94

Conversation

@L0STE
Copy link
Copy Markdown
Contributor

@L0STE L0STE commented Mar 27, 2026

Closes #91, closes #92, closes #94


#91 — Init: validate target directory before prompting

scaffold() checked for conflicting files (existing Quasar.toml, Cargo.toml, non-empty directory) but only after the user had already answered every interactive prompt. Extracted the validation into validate_target_dir() and call it in run() immediately after the project name is resolved — before toolchain, test language, template, and git prompts.

#92 — Build: toml_datetime edition 2024 error with Solana toolchain

cargo build-sbf uses Solana's bundled cargo (1.84), which cannot parse crate manifests that declare edition = "2024". Scaffolded projects had no Cargo.lock, so Solana's cargo performed full dependency resolution and choked on transitive dev-dependencies like toml_datetime >= 1.1.

Two-layer fix:

  1. Init timescaffold() now runs cargo generate-lockfile after writing project files, using the system cargo (which handles edition 2024). Every new project starts with a lockfile. If this fails (no network, etc.) it prints a note rather than aborting, since the project files are already on disk.

  2. Build timeensure_lockfile() runs before cargo build-sbf. It compares Cargo.toml and Cargo.lock mtimes and skips entirely when the lockfile is already current (zero overhead on normal builds). When the lockfile is missing or stale it regenerates with the system cargo. If regeneration fails and no lockfile exists, it exits with a clear diagnostic pointing at rustup update instead of letting build-sbf produce a confusing edition error. If it fails but a stale lockfile exists, it warns and continues since the existing lockfile often still works.

#94 — Profile flamegraph truncated for large JSON

run_server() sets the TcpListener to non-blocking for idle-timeout polling. Accepted TcpStreams inherit this flag. When serve_file() calls write_all() on a non-blocking socket and the kernel send buffer fills (~128–300 KB), write_all returns WouldBlock — silently discarded by the let _ = pattern. Any profile JSON larger than one send buffer was truncated, producing ERR_CONTENT_LENGTH_MISMATCH in the browser.

Fix: set_nonblocking(false) at the top of handle_connection(). The blocking server (--diff mode via serve_blocking()) was never affected because it uses a blocking listener.

L0STE added 4 commits March 27, 2026 16:32
Extract validate_target_dir() from scaffold() and call it in run()
immediately after the project name is resolved. Directory and config
checks (existing Quasar.toml, Cargo.toml, non-empty dir) now run
before the user is prompted for toolchain, test language, template,
and git setup.

Closes #91
The Solana toolchain bundles cargo 1.84, which cannot parse crate
manifests that use edition 2024. When a scaffolded project has no
Cargo.lock, Solana's cargo attempts full dependency resolution and
fails on transitive dependencies like toml_datetime >= 1.1.

Two-layer fix:

1. scaffold: run `cargo generate-lockfile` after writing project
   files so every new project starts with a lockfile generated by
   the system cargo (which handles newer editions).

2. build: ensure_lockfile() runs before cargo build-sbf. It skips
   when Cargo.lock exists and is newer than Cargo.toml (zero
   overhead on normal builds). When the lockfile is missing or
   stale it regenerates with the system cargo. If regeneration
   fails and no lockfile exists at all, it exits with a diagnostic
   instead of letting build-sbf produce a confusing edition error.

Closes #92
run_server() sets the TcpListener to non-blocking for idle timeout
polling. Accepted TcpStreams inherit this flag. When serve_file()
calls write_all() on a non-blocking socket and the kernel send
buffer fills, write_all returns WouldBlock — silently discarded by
the let _ = pattern. This truncates any response larger than one
send buffer (~128-300KB).

Fix: set_nonblocking(false) at the top of handle_connection so
write_all blocks until all bytes are flushed. The blocking server
(--diff mode) was never affected because serve_blocking() uses a
blocking listener.

Closes #94
@github-actions
Copy link
Copy Markdown

⚡ CU Benchmark (Vault)

Instruction Base PR Delta
Deposit 1,577 1,577 0 ⚪
Withdraw 411 411 0 ⚪

Binary size: 6,888 bytes (0 ⚪ bytes)

@L0STE L0STE merged commit 4f1287a into master Mar 27, 2026
8 checks passed
@L0STE L0STE deleted the fix/issues-91-92-94 branch March 27, 2026 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant