Browse / github.com/storytold/lightcraft / patch
MENU-APP-UPDATES: --no-update-check skips the startup update check
MENU-APP-UPDATES: --no-update-check skips the startup update check Off `main`. ## Problem Every start of the desktop app asks GitHub for a newer release (#2933, the startup prompt of craft-libs#319's rollout). A throwaway copy of LightCraft (a test or scripted run started with a scratch library and settings folder) has no use for that: it makes a network request at start, and when a newer release exists the prompt opens and takes the keyboard (`updates_ui::blocks_input`), which can break a control-channel smoke run. There was no way to turn the check off. ## Change - `--no-update-check` on the desktop app skips the startup update check. Without it nothing
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- nledford (imported from pull request #3171, open)
- Base
3a3e49af53aeff55248419234a05d1a262094092- Size
- +101 −21 in 6 files
- Review
- pending
- Shared
- 2026-10-28
- Id
5d2ae90a1ae97b6e3110aa7a
How it went
No other operator has reported using it yet.
Diff
raw · README.md apps/lightcraft/src/launch.rs apps/lightcraft/src/main.rs apps/lightcraft/src/tests.rs docs/control-protocol.md docs/whats-new.md
@@ -402,6 +402,7 @@ cargo run --release -p lightcraft # opens your library (~/ cargo run --release -p lightcraft -- ~/Pictures/trip # import your photos (folders are scanned, duplicates skipped) cargo run --release -p lightcraft -- --memory # a throwaway in-memory demo session (writes nothing) cargo run --release -p lightcraft -- --control 7980 # with the automation channel+cargo run --release -p lightcraft -- --no-update-check # don't look for a newer release at start (Help ▸ Check for Updates… still works) cargo xtask web --serve # the same app in the browser: http://127.0.0.1:8080/ cargo run --release -p lightcraft-cli -- render photo.jpg -o out.jpg --set light.exposure=0.5 cargo xtask ci # fmt, clippy, HEIF, tests, parity, layers, assets, WASM@@ -13,6 +13,8 @@ OPTIONS: --memory throwaway in-memory session (alias --demo); nothing is saved --control PORT serve the JSON-lines control channel on 127.0.0.1:PORT (env LIGHTCRAFT_CONTROL_PORT; see docs/control-protocol.md)+ --no-update-check+ don't look for a newer release at start (Help > Check for Updates… still works) --version, --help ENVIRONMENT:@@ -28,6 +30,50 @@ ENVIRONMENT: <settings folder>/logs/lightcraft.log (previous runs: lightcraft.1.log, lightcraft.2.log) "; +/// What the command line asks for (see [`parse_args`]).+#[derive(Debug, PartialEq)]+pub(crate) struct LaunchArgs {+ pub control_port: Option<u16>,+ /// Files and folders to import, as written (see [`launch_imports`]).+ pub files: Vec<String>,+ pub seed_demo: bool,+ pub in_memory: bool,+ pub library_dir: Option<std::path::PathBuf>,+ /// Whether the window looks for a newer release once it is up; `--no-update-check` turns it off.+ pub startup_update_check: bool,+}++/// How the command line was read.+#[derive(Debug, PartialEq)]+pub(crate) enum Parsed {+ Run(LaunchArgs),+ Version,+ Help,+ /// An option that doesn't exist.+ Unknown(String),+}++/// Reads the command line (without the program name); `control_port` is the one from+/// `LIGHTCRAFT_CONTROL_PORT`, which `--control` replaces.+pub(crate) fn parse_args(args: impl IntoIterator<Item = String>, control_port: Option<u16>) -> Parsed {+ let mut parsed = LaunchArgs { control_port, files: Vec::new(), seed_demo: true, in_memory: false, library_dir: None, startup_update_check: true };+ let mut args = args.into_iter();+ while let Some(a) = args.next() {+ match a.as_str() {+ "--control" => parsed.control_port = control_port_from("--control", Some(args.next().unwrap_or_default())),+ "--library" => parsed.library_dir = args.next().map(std::path::PathBuf::from),+ "--no-demo" => parsed.seed_demo = false,+ "--memory" | "--demo" => parsed.in_memory = true,+ "--no-update-check" => parsed.startup_update_check = false,+ "--version" => return Parsed::Version,+ "-h" | "--help" => return Parsed::Help,+ o if o.starts_with("--") => return Parsed::Unknown(a),+ _ => parsed.files.push(a),+ }+ }+ Parsed::Run(parsed)+}+ /// The launch arguments' files and folders to import (absolute), and a notice for each one that /// is not imported (see [`lightcraft_engine::import::launch_path`]; issue #374). pub(crate) fn launch_imports(args: &[String]) -> (Vec<String>, Vec<String>) {@@ -1,6 +1,6 @@ //! LightCraft desktop app. //!-//! Usage: `lightcraft [--library DIR | --memory] [--no-demo] [--control <port>] [files or folders…]`+//! Usage: `lightcraft [--library DIR | --memory] [--no-demo] [--no-update-check] [--control <port>] [files or folders…]` //! //! The library (catalog, presets, thumbnail cache) lives in `--library DIR`, else //! `$LIGHTCRAFT_LIBRARY`, else — with Settings ▸ General ▸ At launch set to *Ask me*, or Alt/Option@@ -55,7 +55,10 @@ use gpu_crash::{gpu_crash_check, gpu_lost_check_at, gpu_lost_marker_path, gpu_lo use gpu_crash::{gpu_crash_check_at, gpu_crash_notice, window_wgpu_options}; #[cfg(test)] use launch::launch_imports_in;-use launch::{HELP, control_port_from, launch_imports, log_dir, panic_log_path_with, startup_failed, stopped_text, stopped_while_running};+use launch::{+ HELP, LaunchArgs, Parsed, control_port_from, launch_imports, log_dir, panic_log_path_with, parse_args, startup_failed, stopped_text,+ stopped_while_running,+}; #[cfg(test)] use platform::{explorer_select_arg, explorer_select_command, windows_open_url_command}; use prefs::{PrefsWriter, as_remembered, load_prefs, prefs_path};@@ -146,33 +149,23 @@ fn main() -> eframe::Result { logging::record_panics(logger); } alloc_release::install();- let mut control_port = control_port_from("LIGHTCRAFT_CONTROL_PORT", std::env::var("LIGHTCRAFT_CONTROL_PORT").ok().filter(|v| !v.is_empty()));- let mut files = Vec::new();- let mut seed_demo = true;- let mut in_memory = false;- let mut library_dir: Option<std::path::PathBuf> = None;- let mut args = std::env::args().skip(1);- while let Some(a) = args.next() {- match a.as_str() {- "--control" => control_port = control_port_from("--control", Some(args.next().unwrap_or_default())),- "--library" => library_dir = args.next().map(std::path::PathBuf::from),- "--no-demo" => seed_demo = false,- "--memory" | "--demo" => in_memory = true,- "--version" => {+ let env_port = control_port_from("LIGHTCRAFT_CONTROL_PORT", std::env::var("LIGHTCRAFT_CONTROL_PORT").ok().filter(|v| !v.is_empty()));+ let LaunchArgs { control_port, files, seed_demo, in_memory, library_dir, startup_update_check } =+ match parse_args(std::env::args().skip(1), env_port) {+ Parsed::Run(args) => args,+ Parsed::Version => { println!("lightcraft {}", env!("CARGO_PKG_VERSION")); return Ok(()); }- "-h" | "--help" => {+ Parsed::Help => { print!("{HELP}"); return Ok(()); }- o if o.starts_with("--") => {+ Parsed::Unknown(o) => { eprintln!("lightcraft: unknown option `{o}`\n\n{HELP}"); std::process::exit(2); }- _ => files.push(a),- }- }+ }; // The log file: opened after the arguments, so `--version`, `--help` and a usage error leave // no file behind. Records logged until now are written to it first. let mut log_file = None;@@ -267,7 +260,7 @@ fn main() -> eframe::Result { // HDR display: SDR unless the surface, platform and display all allow HDR hdr_display::report(cc.wgpu_render_state.as_ref().map(|r| r.target_format)); let mut app = LightcraftApp::new(session, services(cc, app_log_file.as_deref()));- app.set_startup_update_check(true);+ app.set_startup_update_check(startup_update_check); if let Some(ui) = prefs { app.ui = ui; }@@ -462,3 +462,33 @@ fn on_exit_ends_the_process_on_macos() { assert!(stdout.contains("calling on_exit"), "the child didn't run the test: {stdout}"); assert_eq!(stdout.contains("on_exit returned"), !cfg!(target_os = "macos"), "{stdout}"); }++fn parsed(args: &[&str]) -> LaunchArgs {+ match parse_args(args.iter().map(|a| a.to_string()), None) {+ Parsed::Run(a) => a,+ other => panic!("expected a launch, got {other:?}"),+ }+}++/// `--no-update-check` (throwaway test copies must not call GitHub at start) turns the startup+/// update check off and nothing else; without it the check stays on.+#[test]+fn no_update_check_turns_the_startup_update_check_off() {+ assert!(parsed(&[]).startup_update_check, "the default is to check");+ assert!(parsed(&["--memory", "--control", "7981", "Trip"]).startup_update_check, "other options leave it on");+ let off = parsed(&["--memory", "--no-update-check", "Trip"]);+ assert!(!off.startup_update_check);+ // the flag is only that: the other options and the files still read the same+ assert_eq!(LaunchArgs { startup_update_check: true, ..off }, parsed(&["--memory", "Trip"]));+ // a value of --library is that folder, never the flag+ let lib = parsed(&["--library", "--no-update-check"]);+ assert!(lib.startup_update_check);+ assert_eq!(lib.library_dir, Some(std::path::PathBuf::from("--no-update-check")));+}++/// The flag is a known option (an unknown one exits with a usage error) and `--help` lists it.+#[test]+fn no_update_check_is_a_known_option_and_listed_in_the_help() {+ assert_eq!(parse_args(["--no-update-chek".to_string()], None), Parsed::Unknown("--no-update-chek".into()));+ assert!(HELP.contains("--no-update-check"));+}@@ -51,6 +51,9 @@ empty value disables the settings directory, while the emergency panic log retai Explicit model-directory environment variables still take precedence over their defaults. Also pass `--library DIR` with a separate scratch library: the configuration override does not change the default photo-library location. Do not use `--memory` or `LIGHTCRAFT_NO_PREFS` when testing persistence.+Pass `--no-update-check` as well: the startup check for a newer release (a request to GitHub) is skipped, so a+throwaway run makes no network request at start, and a newer release can't open the update prompt, which takes the+keyboard. Help ▸ Check for Updates… (`app.checkForUpdates`) still checks when asked. A native acceptance run must reject the stderr message `rendering headlessly`: `ui.screenshot` automatically uses the CPU fallback after two seconds without a presented frame. That fallback is useful@@ -1,5 +1,12 @@ # What's new in LightCraft +## 2026-10-27++### `--no-update-check` for throwaway copies+- Starting LightCraft with `--no-update-check` skips the look for a newer release at start, so a throwaway copy (a test+ or scripted run) makes no request to GitHub and never opens the update prompt. Help ▸ Check for Updates… still+ checks when you ask; without the option nothing changes.+ ## 2026-10-24 ### Relative-date filters and smart albums follow the clock