Skip to content

fix(uninstall): allow removing the last installed version - #300

Merged
CalvinAllen merged 1 commit into
mainfrom
fix/uninstall/last-global-version
Nov 7, 2026
Merged

CalvinAllen merged 1 commit into
mainfrom
fix/uninstall/last-global-version

Conversation

@CalvinAllen

Copy link
Copy Markdown
Contributor

Problem

dtvem install makes the first installed version of a runtime the global version, and dtvem uninstall refused to remove the global version until a different one was set. With only one version installed there is nothing to switch to, so the last version of a runtime could never be uninstalled.

Changes

  • Uninstalling the global version
    • When it is the only installed version, uninstall now proceeds. It warns before the confirmation prompt, then removes the runtime's entry from the global runtimes.json once the files are deleted. Other runtimes' entries are kept. Canceling at the prompt leaves everything as it was.
    • When other versions are installed, it is still refused, and the error now lists the other installed versions.
  • New config.UnsetGlobalVersion removes one runtime's entry from the global config. It does nothing when the file or the entry is missing, and it returns an error instead of rewriting a config it cannot parse.
  • Local-version warning fix. Uninstall's "active local version" warning used provider.LocalVersion(), which falls back to the global version. So it fired for every global version and named the obsolete dtvem.config.json. Uninstall never reached that warning for the global version before, so this change would have exposed it. The warning now uses config.Resolve, appears only when a project file (.dtvem/runtimes.json, .tool-versions, .ruby-version, …) pins the version, and names that file.

Testing

  • ./rnr check passes (format, lint with 0 issues, all tests).
  • New unit tests:
    • UnsetGlobalVersion: removes only the target runtime, leaves valid JSON when the last entry is removed, handles a missing file and a missing entry, and does not rewrite a corrupt config.
    • otherVersions and localPinSource: a global version alone is not a local pin, a project .ruby-version with a partial version is a pin, and a pin of a different version is ignored.
  • Manual run of a built binary against a temporary DTVEM_ROOT:
    • The global version is refused while another version is installed.
    • With one version left, uninstall removes it and clears only that runtime's global entry.
    • The local warning appears only inside a directory with .ruby-version, and it names that file.

Install makes the first version of a runtime the global version, and
uninstall refused to remove the global version, so the last installed
version of a runtime could never be uninstalled.

Uninstalling the global version is now allowed when it is the only
installed version; the runtime's entry is removed from the global config
after the files are deleted. With other versions installed it is still
refused, and the message lists them.

The "active local version" warning used provider.LocalVersion, which
falls back to the global version, so it fired for every global version
and named the obsolete dtvem.config.json. It now uses config.Resolve,
warns only when a project file pins the version, and names that file.
@CalvinAllen
CalvinAllen merged commit 49eadb4 into main Nov 7, 2026
11 checks passed
@CalvinAllen
CalvinAllen deleted the fix/uninstall/last-global-version branch November 7, 2026 00:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant