You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Implement the tfenv uninstall command for the Go edition with full parity to the Bash edition, including multi-version uninstall, version resolution, and version-file fallback.
Parent Epic
Part of #488 — Go Edition: Full Feature Parity Implementation
Motivation
Users need to remove installed Terraform versions to reclaim disk space or clean up old versions. The Bash edition supports multiple versions in a single call, version resolution keywords (latest, latest:<regex>), reading from version files when no argument is given, and TFENV_TERRAFORM_VERSION override. The Go edition must match all of this.
Clean-Room Constraint
This is a clean-room implementation. Contributors MUST NOT read, reference, copy, or adapt source code from tofuutils/tenv, hashicorp/hc-install, or any other third-party tfenv-like tool. The sole reference is tfenv's own Bash source code, documentation, and test suite.
Proposed Design
Command Interface
tfenv uninstall <version> [<version2> ...]
tfenv uninstall latest
tfenv uninstall latest:<regex>
tfenv uninstall # reads from version file or TFENV_TERRAFORM_VERSION
Version Collection
The versions to uninstall are collected from (in priority order):
Command-line arguments — one or more version specifiers
TFENV_TERRAFORM_VERSION — if no args given and env var is set
Version file chain — if no args and no env var, read from .terraform-version walk or ${TFENV_CONFIG_DIR}/version
Error — if none of the above produce a version
Reference: libexec/tfenv-uninstall lines 105-134.
Single Version Uninstall Flow (uninstall_single_version)
For each version specifier:
Reject min-required — not a valid uninstall target
Reject latest-allowed — not a valid uninstall target
Remove the version directory recursively (os.RemoveAll())
Print confirmation: Terraform v${version} is successfully uninstalled
Reference: libexec/tfenv-uninstall lines 65-100.
Multi-Version Uninstall
When multiple arguments are given, each is uninstalled independently. If one fails, the others still proceed. The command tracks failures and returns non-zero exit code if ANY uninstall failed.
The Bash edition runs each uninstall in a subshell so that log 'error' (which calls exit 1) doesn't kill the loop. The Go edition should catch errors per-version and continue.
Post-Uninstall Cleanup
After all uninstalls complete, if the ${TFENV_CONFIG_DIR}/versions/ directory is empty, remove it with os.Remove() (not RemoveAll — only succeeds if actually empty). This is a courtesy cleanup, not an error if it fails.
Reference: libexec/tfenv-uninstall lines 141-143.
Path Traversal Protection
The version string MUST be validated before constructing filesystem paths. Reject any version containing /, \, .., or null bytes. This prevents path traversal attacks where a malicious .terraform-version file could cause deletion of arbitrary directories.
Acceptance Criteria
tfenv uninstall 1.5.0 removes the 1.5.0 version directory
tfenv uninstall 1.5.0 1.4.0 uninstalls both versions
tfenv uninstall latest uninstalls the newest locally installed version
tfenv uninstall latest:^1.5 uninstalls the newest installed 1.5.x version
tfenv uninstall (no args) reads version from .terraform-version or default version file
TFENV_TERRAFORM_VERSION is respected when no args given
tfenv uninstall min-required produces clear error ("unsupported option for uninstall")
tfenv uninstall latest-allowed produces clear error ("unsupported option for uninstall")
Error if version is not installed (clear message, non-zero exit)
Multi-version: continues past individual failures, returns non-zero if any failed
Empty versions/ directory is cleaned up after last version removed
Exit code 0 on full success, non-zero if any version failed
The Go edition uses os.RemoveAll() instead of rm -r
Version matching against installed versions must strip the * prefix and (arch) suffix from tfenv list output — or better, query the versions directory directly
Summary
Implement the
tfenv uninstallcommand for the Go edition with full parity to the Bash edition, including multi-version uninstall, version resolution, and version-file fallback.Parent Epic
Part of #488 — Go Edition: Full Feature Parity Implementation
Motivation
Users need to remove installed Terraform versions to reclaim disk space or clean up old versions. The Bash edition supports multiple versions in a single call, version resolution keywords (
latest,latest:<regex>), reading from version files when no argument is given, andTFENV_TERRAFORM_VERSIONoverride. The Go edition must match all of this.Clean-Room Constraint
This is a clean-room implementation. Contributors MUST NOT read, reference, copy, or adapt source code from
tofuutils/tenv,hashicorp/hc-install, or any other third-party tfenv-like tool. The sole reference is tfenv's own Bash source code, documentation, and test suite.Proposed Design
Command Interface
Version Collection
The versions to uninstall are collected from (in priority order):
TFENV_TERRAFORM_VERSION— if no args given and env var is set.terraform-versionwalk or${TFENV_CONFIG_DIR}/versionReference:
libexec/tfenv-uninstalllines 105-134.Single Version Uninstall Flow (
uninstall_single_version)For each version specifier:
min-required— not a valid uninstall targetlatest-allowed— not a valid uninstall targetlatestkeywords:latest:<regex>→ search locally installed versions matching regex, pick newestlatest(no regex) → search locally installed versions, pick newest^version$regextfenv listoutput, stripped of markers and arch info)${TFENV_CONFIG_DIR}/versions/${version}/terraformexistsos.RemoveAll())Terraform v${version} is successfully uninstalledReference:
libexec/tfenv-uninstalllines 65-100.Multi-Version Uninstall
When multiple arguments are given, each is uninstalled independently. If one fails, the others still proceed. The command tracks failures and returns non-zero exit code if ANY uninstall failed.
The Bash edition runs each uninstall in a subshell so that
log 'error'(which callsexit 1) doesn't kill the loop. The Go edition should catch errors per-version and continue.Post-Uninstall Cleanup
After all uninstalls complete, if the
${TFENV_CONFIG_DIR}/versions/directory is empty, remove it withos.Remove()(notRemoveAll— only succeeds if actually empty). This is a courtesy cleanup, not an error if it fails.Reference:
libexec/tfenv-uninstalllines 141-143.Path Traversal Protection
The version string MUST be validated before constructing filesystem paths. Reject any version containing
/,\,.., or null bytes. This prevents path traversal attacks where a malicious.terraform-versionfile could cause deletion of arbitrary directories.Acceptance Criteria
tfenv uninstall 1.5.0removes the1.5.0version directorytfenv uninstall 1.5.0 1.4.0uninstalls both versionstfenv uninstall latestuninstalls the newest locally installed versiontfenv uninstall latest:^1.5uninstalls the newest installed 1.5.x versiontfenv uninstall(no args) reads version from.terraform-versionor default version fileTFENV_TERRAFORM_VERSIONis respected when no args giventfenv uninstall min-requiredproduces clear error ("unsupported option for uninstall")tfenv uninstall latest-allowedproduces clear error ("unsupported option for uninstall")versions/directory is cleaned up after last version removed..,/,\, or null bytesDependencies
Implementation Notes
libexec/tfenv-uninstall— 145 lines including standalone boilerplate. The actual logic is lines 65-145.min-requiredandlatest-allowedrejected as unsupportedlatest:regex,latest, and exact version handlingtfenv-listoutput (stripped of*, whitespace, arch info)os.RemoveAll()instead ofrm -r*prefix and(arch)suffix fromtfenv listoutput — or better, query the versions directory directlyLabels
type:feature,priority:high,complexity:small,category:uninstall