feat(detector): implement nvm-windows detection#8
Merged
Conversation
|
✔️ 2d1161e - Conventional commits check succeeded. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes
internal/detector/nvm_windows.go(full implementation,//go:build windows):Detect():platform.LookupManagerBinary("nvm") != ""OR$NVM_HOMEenv OR$NVM_SYMLINKenv (asdf pattern, two-env-var detection)Version():nvm version, parses the bare semver (e.g.,"1.1.12") — upstream's dispatcher callsfmt.Println(NvmVersion)so output has no branding prefix and novprefixListInstalled():nvm list, lines* X.Y.Z (Currently using <arch>-bit executable)(current) /X.Y.Z(others), the trailing(Currently using <arch>-bit executable)suffix is stripped before semver parse;No installations recognized.sentinel filtered outnvmWindowsRoot()helper:$NVM_HOMEonly — no home-dir fallback because the default location varies between Windows releases and nodeup should not pretend to knownvmWindowsSymlink()helper:$NVM_SYMLINKonly (the active-version symlink dir)ErrNVMWindowsNotImplementedsentinel (asdf pattern)internal/detector/nvm_windows_test.go(~30 mocked tests,//go:build windows):parseNVMWindowsVersion: standard output (1.1.12),v-prefixed (v1.1.12), git-describe suffix (1.1.12-4-gabc1234), trailing whitespace (incl.\r\n), empty, whitespace-only, multi-token defensiveparseNVMWindowsInstalled: real output (with(Currently using 64-bit executable)suffix), 32-bit marker variant, filtersNo installations recognized.sentinel, sentinel with leading blank lines, unsorted → sorted ascending, empty stdout, only blank lines, defensivevprefix, skips unparseable lines,\r\nline endingsName,Version(success capturing command,v-prefixed, runShell error, empty-output error),ListInstalled(success, empty stdout, runShell error)Detect: no-PATH-no-env, binary-on-PATH (nvm.exedirectly since file is Windows-only), honors$NVM_HOME, honors$NVM_SYMLINK, empty env falls through, whitespace-only env falls throughMutationMethods_NotImplementedsentinel testnvmWindowsRoothelper: env-precedence, empty-when-unset, whitespace-only-env-falls-throughnvmWindowsSymlinkhelper: env, empty-when-unset, whitespace-onlyinternal/detector/registry_windows.go(refactor):NVMWindowstype/methods (they live innvm_windows.gonow)All()continues to returnNewNVMWindows()as the last entry — behavior unchangedDesign notes
internal/detectorsurface (fnm,nvm,Volta,ASDF,mise,n,Nodenv,NVMWindows).//go:build windowson both the implementation AND the test file) means the file is excluded from linux/macOS builds. The CI matrix exerciseswindows-latestso the tests run there.runtime.GOOSswitch when constructing the stubnvm.exebinary — that's why nodenv'sTestNodenv_Detect_FindsBinaryOnPathruntime.GOOSswitch is absent here.nvm.exeon PATH,$NVM_HOME, and$NVM_SYMLINK. The upstream installer sets$NVM_HOMEand$NVM_SYMLINKtogether at install time, so they typically appear together, but either alone is sufficient — the symlink is the active-version dir, the home is the install root.$NVM_HOMEto a hard-coded%APPDATA%\nvmpath because that varies between Windows releases (the upstream installer lets the user pick any directory).nvm listoutput strips thevprefix via regex upstream (regexp.MustCompile("v").ReplaceAllString) before printing — so the parser sees bareX.Y.Z. We re-strip a leadingvdefensively in case a fork skips that step.32-bit/64-bit) is hard-coded in upstream's format string (arm64 installs still print64-bit). We accept both via substring-on-whitespace — the parser doesn't care which bitness the marker uses.nvm versionaliases (v,-v,--version,-version,--v) all dispatch to the same case in upstream, so we useversionas the canonical subcommand.Verification
GOOS=windows go build ./...✅GOOS=windows go vet ./...✅GOOS=windows go test -c -o /tmp/detector.test ./internal/detector✅ (cross-compiles cleanly)go test ./... -race(native darwin) ✅ (all 7 prior-manager test suites still pass; nvm-windows tests are excluded by build tag and will run onwindows-latestin CI)