User-global config.yml and output-dir to collection-dir arg rename #30

Merged
maleszka merged 8 commits from feature/global-config into main 2026-07-13 13:05:17 +02:00
Owner
No description provided.
Behavior-preserving: credentials.json's default path is unchanged, just
computed via a shared helper instead of an inline $HOME read in main.rs.
Lays the groundwork for config.yml, which needs the same directory.
Not yet wired into main.rs — config.yml isn't read anywhere yet, only
loadable in isolation. Mirrors CollectionConfig's deny_unknown_fields /
hard-error-on-malformed-file style. Absence of the file is not an error:
unlike collection.yml, config.yml is never auto-created.
resolve_collection_dir() wires config.yml in as the fallback: CLI flag wins
if present, otherwise config.yml's collection_dir, otherwise a UserError
(exit code 1) rather than clap's own usage-error exit code 2.

resolve_collection_dir takes Option<PathBuf> rather than &Cli — Cli lives in
the cli module, which is bin-only (declared in main.rs, not lib.rs), while
config.rs is part of the librespot_dl library crate.
Interactive mode prints "Collection: <path>" (plain println!, cooked mode)
before the restore prompt; script mode emits the equivalent
"[librespot-dl] collection: <path>" to stderr as its first output. Both
append "(default from config.yml)" when CollectionDirSource::GlobalConfig
supplied the path, so config.yml's silent influence on where a session
writes is never invisible to the user.

Manually verified via the built binary: -c bypasses config.yml entirely
(even a malformed one), and a config.yml collection_dir with a ~ prefix
resolves and creates the collection under the real $HOME. Could not
exercise the banner print itself end-to-end in this sandbox, since it
prints only after Spotify credential auth succeeds and this environment
has no network access to Spotify — covered instead by
interactive_collection_banner/script_collection_banner unit tests.
Rendering has no business in config.rs, which should stay scoped to
resolving configuration. New src/ui/collection_banner.rs holds both lines,
matching the precedent of ui::summary::SessionSummary already formatting
one-shot output for both interactive and script mode.

Interactive mode's line now reuses two colors already meaningful in the
queue view instead of printing fully plain text: the path in
Color::AnsiValue(248) (the light-grey the queue view's rows use for
position/duration values) and the "(default from config.yml)" annotation
in Color::DarkGrey (the queue view's row-aside tone). Script mode's stderr
line stays plain text, unchanged — its audience is cron/automation logs.

specs/features/global-config.md (Decision 13, Test Specifications #8-9, and
the T4 implementation plan) updated to match: the printed wording, the
module location, and the fact that this line is no longer un-styled.
maleszka deleted branch feature/global-config 2026-07-13 13:05:18 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
maleszka/librespot-dl!30
No description provided.