Commit Graph
4 Commits
Author SHA1 Message Date
soubarnak ea7be5f111 feat(identity): rename user-visible identity to voculinux with one-time legacy import
The fork takes its own name everywhere a user can see it: binaries
(voculinux, voculinux-gui), desktop entry, autostart, tray, D-Bus
namespace (com.voculinux.Voculinux, no alias for the old name),
config/data/cache dirs, single-instance lock, IBus engine identity,
tray icons, resource prefixes, VOCULINUX_* environment names, and the
update-checker user agent. The internal Python module stays vocalinux
and the distribution metadata keeps the upstream URLs as provenance.

On first run a previous Vocalinux install's config.json, custom
dictionary, and portal restore token are copied once into the new
locations (new config always wins, no merge, no write-back); models
re-resolve through the pinned-checksum download path. An offline
naming-sweep test proves no old-name strings remain on user-visible
surfaces outside the allowlist.

Refs #18
2026-11-06 01:29:39 +05:30
be690f0bd8 fix(installer): add upgrade mode that keeps the existing configuration (#1026)
* fix(installer): add upgrade mode that keeps the existing configuration

Re-running install.sh on an existing install replayed first-time setup:
the mode menu offered only interactive or automatic, automatic mode
forced whisper.cpp regardless of the configured engine, and nothing said
config.json would be kept, even though docs/UPDATE.md promised the
installer updates in place and preserves configuration.

Detect an existing install early (venv activate + config.json) and offer
an upgrade path:

- The curl|bash mode menu gains 'Upgrade (keep current settings)' as the
  default when an install is detected; the guided setup offers it first
  too.
- A --upgrade flag runs the same path non-interactively for scripts, and
  falls back to a normal automatic install when nothing is installed.
- Upgrade mode reads speech_recognition.engine from the existing
  config.json instead of forcing whisper.cpp, reuses the venv, updates
  that engine's dependencies, and rebuilds pywhispercpp only when the
  installed version drifts from the pinned release or GPU support is
  missing.
- config.json is never modified: every engine path that may rewrite it
  (parakeet, faster_whisper, the whisper.cpp -> vosk fallback) goes
  through a wrapper that is a logged no-op in upgrade mode, and
  verify_configured_engine reports an unimportable configured engine
  instead of repairing the file.
- The installer prints 'Existing configuration found at
  ~/.config/vocalinux/config.json - it will be kept.' when it detects
  one.

Update docs/UPDATE.md with the upgrade behavior and add
tests/test_installer_upgrade.py covering detection, the mode menu
default, engine resolution from config, config immutability, the guided
offer, --upgrade parsing, and an end-to-end pty run of the piped
installer.

Fixes #1009

* test(installer): isolate the upgrade pty test from host changes

Skip system-dependency and model steps in the end-to-end installer run
so the only host-mutating calls are gated out entirely; the timed
interrupt is no longer the only thing between the marker and sudo.

---------

Co-authored-by: Jatin K Malik <jatinkrmalik@gmail.com>
2026-10-26 20:55:39 -07:00
e9598d64ce fix(installer): keep piped script on stdin and prompt via /dev/tty (#935)
* fix(installer): keep piped script on stdin and prompt via /dev/tty

`curl | bash` left bash reading the installer itself from stdin, and the
detection block's `exec < /dev/tty` (from #315) closed that pipe about 300
lines into a 3000-line script. curl died with error 23 writing to the
closed pipe, and bash read the rest of the installer from the terminal as
commands instead of finishing the script.

stdin now stays on the pipe and a reachable terminal is recorded in
TERMINAL_PROMPTS. Every interactive prompt goes through read_prompt, which
reads /dev/tty explicitly only for that read, so user input still works in
a terminal while the script body keeps flowing through the pipe. The
interactive-mode gate now checks TERMINAL_PROMPTS rather than `-t 0`,
which also lets `--interactive` work under a pipe.

Regression coverage: the remote-install gate's second run now pipes the
bootstrap in under a `script` pty (the literal `cat | bash` shape a
curl user takes), and new tests run install.sh in a pty with the script on
a pipe to assert the mode and engine prompts still answer on the terminal.

Fixes #933

* fix(installer): drain the piped bootstrap before the handoff exec

A curl|bash bootstrap leaves its unread tail on stdin; the tagged installer
reads its commands from a file, so nothing drained the pipe and a still-
streaming curl reported error 23 when the installer exited. Drain stdin to
EOF before exec (Greptile P2 on #935).

Gate: drip-feed the piped run so the producer is mid-write at the handoff
like real curl, and run it under pipefail so a producer killed early fails
the run. Tests: pass --tag so a slow release lookup cannot eat the window,
wait for the engine prompt before Ctrl+C, and quote the installer path.

* test(installer): propagate a killed producer's status in the piped gate

A cat dying mid-drip (SIGPIPE when the consumer abandons the pipe) was
swallowed by the loop and the final rm, so drip returned success and
pipefail could not see the download failure the arm exists to catch.

---------

Co-authored-by: Jatin K Malik <jatinkrmalik@gmail.com>
2026-10-11 17:37:51 -07:00
244b62c8ad refactor(installer): split implementation into sourced modules (#862)
* refactor(installer): split implementation into sourced modules

* test(installer): harden module path coverage

* fix(installer): qualify interactive privacy and engine claims

The guided installer overstated local-only privacy and ranked
whisper.cpp without evidence. Match PRODUCT.md: on-device local
engines, optional Remote API, and the ~33 language catalog plus
Auto-detect.

---------

Co-authored-by: Jatin K Malik <jatinkrmalik@gmail.com>
2026-09-29 01:07:16 -07:00