mirror of
https://github.com/coreybutler/nvm-windows.git
synced 2026-01-15 07:04:31 +08:00
Added code-signing capability. Also updated aliases to elevate command when needed (issue #700)
This commit is contained in:
16
build.bat
16
build.bat
@@ -21,7 +21,8 @@ move nvm.exe %GOBIN%
|
||||
cd ..\
|
||||
|
||||
REM Codesign the executable
|
||||
REM .\buildtools\signtools\x64\signtool.exe sign /debug /tr http://timestamp.digicert.com /td sha256 /fd sha256 /a %GOBIN%\nvm.exe
|
||||
echo Sign the nvm executable...
|
||||
buildtools\signtool.exe sign /debug /tr http://timestamp.sectigo.com /td sha256 /fd sha256 /a %GOBIN%\nvm.exe
|
||||
|
||||
for /f %%i in ('"%GOBIN%\nvm.exe" version') do set AppVersion=%%i
|
||||
echo nvm.exe v%AppVersion% built.
|
||||
@@ -42,13 +43,20 @@ REM Create the "no install" zip version
|
||||
for %%a in ("%GOBIN%") do (buildtools\zip -j -9 -r "%DIST%\nvm-noinstall.zip" "%CD%\LICENSE" %%a\* -x "%GOBIN%\nodejs.ico")
|
||||
|
||||
REM Generate update utility
|
||||
echo Generating update utility...
|
||||
cd .\updater
|
||||
go build nvm-update.go
|
||||
echo Sign the updater...
|
||||
buildtools\signtool.exe sign /debug /tr http://timestamp.sectigo.com /td sha256 /fd sha256 /a nvm-update.exe
|
||||
move nvm-update.exe %DIST%
|
||||
cd ..\
|
||||
|
||||
REM Generate the installer (InnoSetup)
|
||||
echo Generating installer...
|
||||
buildtools\iscc "%INNOSETUP%" "/o%DIST%"
|
||||
echo Sign the installer
|
||||
buildtools\signtool.exe sign /debug /tr http://timestamp.sectigo.com /td sha256 /fd sha256 /a %DIST%\nvm-setup.exe
|
||||
echo Bundle the installer/updater...
|
||||
buildtools\zip -j -9 -r "%DIST%\nvm-setup.zip" "%DIST%\nvm-setup.exe"
|
||||
buildtools\zip -j -9 -r "%DIST%\nvm-update.zip" "%DIST%\nvm-update.exe"
|
||||
|
||||
@@ -56,12 +64,14 @@ del %DIST%\nvm-update.exe
|
||||
del %DIST%\nvm-setup.exe
|
||||
|
||||
REM Generate checksums
|
||||
echo Generating checksums...
|
||||
for %%f in (%DIST%\*.*) do (certutil -hashfile "%%f" MD5 | find /i /v "md5" | find /i /v "certutil" >> "%%f.checksum.txt")
|
||||
|
||||
echo Cleaning up...
|
||||
REM Cleanup
|
||||
del %GOBIN%\nvm.exe
|
||||
del %GOBIN%\nvm-update.exe
|
||||
del %GOBIN%\nvm-setup.exe
|
||||
@REM del %GOBIN%\nvm-update.exe
|
||||
@REM del %GOBIN%\nvm-setup.exe
|
||||
|
||||
echo NVM for Windows v%AppVersion% build completed.
|
||||
@echo on
|
||||
|
||||
100
src/nvm.go
100
src/nvm.go
@@ -181,7 +181,7 @@ func update() {
|
||||
*/
|
||||
|
||||
func getVersion(version string, cpuarch string) (string, string, error) {
|
||||
arch := strings.ToLower(cpuarch)
|
||||
cpuarch = strings.ToLower(cpuarch)
|
||||
|
||||
if cpuarch != "" {
|
||||
if cpuarch != "32" && cpuarch != "64" && cpuarch != "all" {
|
||||
@@ -223,11 +223,12 @@ func getVersion(version string, cpuarch string) (string, string, error) {
|
||||
version = v
|
||||
}
|
||||
|
||||
version = strings.Replace(version, "v", "", 1)
|
||||
|
||||
v, err := semver.Make(version)
|
||||
if err == nil {
|
||||
err = v.Validate()
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
// if the user specifies only the major/minor version, identify the latest
|
||||
// version applicable to what was provided.
|
||||
@@ -237,6 +238,8 @@ func getVersion(version string, cpuarch string) (string, string, error) {
|
||||
} else {
|
||||
version = cleanVersion(version)
|
||||
}
|
||||
|
||||
version = strings.Replace(version, "v", "", 1)
|
||||
}
|
||||
|
||||
return version, cpuarch, err
|
||||
@@ -434,9 +437,11 @@ func uninstall(version string) {
|
||||
fmt.Printf("Uninstalling node v" + version + "...")
|
||||
v, _ := node.GetCurrentVersion()
|
||||
if v == version {
|
||||
runElevated(fmt.Sprintf(`"%s" cmd /C rmdir "%s"`,
|
||||
filepath.Join(env.root, "elevate.cmd"),
|
||||
filepath.Clean(env.symlink)))
|
||||
_, err := runElevated(fmt.Sprintf(`"%s" cmd /C rmdir "%s"`, filepath.Join(env.root, "elevate.cmd"), filepath.Clean(env.symlink)))
|
||||
if err != nil {
|
||||
fmt.Println(fmt.Sprint(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
e := os.RemoveAll(filepath.Join(env.root, "v"+version))
|
||||
if e != nil {
|
||||
@@ -460,13 +465,17 @@ func findLatestSubVersion(version string) string {
|
||||
return latest
|
||||
}
|
||||
|
||||
func use(version string, cpuarch string) {
|
||||
v, a, err := getVersion(cersion, cpuarch)
|
||||
func use(version string, cpuarch string, reload ...bool) {
|
||||
v, a, err := getVersion(version, cpuarch)
|
||||
version = v
|
||||
cpuarch = a
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
if strings.Contains(err.Error(), "No Major.Minor.Patch") {
|
||||
fmt.Printf("Unrecognized version/alias: \"%v %v-bit\"", v, a)
|
||||
} else {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -489,18 +498,39 @@ func use(version string, cpuarch string) {
|
||||
// Remove symlink if it already exists
|
||||
sym, _ := os.Stat(env.symlink)
|
||||
if sym != nil {
|
||||
if !runElevated(fmt.Sprintf(`"%s" cmd /C rmdir "%s"`,
|
||||
filepath.Join(env.root, "elevate.cmd"),
|
||||
filepath.Clean(env.symlink))) {
|
||||
return
|
||||
_, err := runElevated(fmt.Sprintf(`"%s" cmd /C rmdir "%s"`, filepath.Join(env.root, "elevate.cmd"), filepath.Clean(env.symlink)))
|
||||
if err != nil {
|
||||
fmt.Println(fmt.Sprint(err))
|
||||
}
|
||||
|
||||
// // Return if the symlink already exists
|
||||
// if ok {
|
||||
// fmt.Print(err)
|
||||
// return
|
||||
// }
|
||||
}
|
||||
|
||||
// Create new symlink
|
||||
if !runElevated(fmt.Sprintf(`"%s" cmd /C mklink /D "%s" "%s"`,
|
||||
filepath.Join(env.root, "elevate.cmd"),
|
||||
filepath.Clean(env.symlink),
|
||||
filepath.Join(env.root, "v"+version))) {
|
||||
var ok bool
|
||||
ok, err = runElevated(fmt.Sprintf(`"%s" cmd /C mklink /D "%s" "%s"`, filepath.Join(env.root, "elevate.cmd"), filepath.Clean(env.symlink), filepath.Join(env.root, "v"+version)))
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "file already exists") {
|
||||
ok, err = runElevated(fmt.Sprintf(`"%s" cmd /C rmdir "%s"`, filepath.Join(env.root, "elevate.cmd"), filepath.Clean(env.symlink)))
|
||||
reloadable := true
|
||||
if len(reload) > 0 {
|
||||
reloadable = reload[0]
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println(fmt.Sprint(err))
|
||||
} else if reloadable {
|
||||
use(version, cpuarch, false)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
fmt.Print(fmt.Sprint(err))
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -652,11 +682,13 @@ func enable() {
|
||||
}
|
||||
|
||||
func disable() {
|
||||
if !runElevated(fmt.Sprintf(`"%s" cmd /C rmdir "%s"`,
|
||||
filepath.Join(env.root, "elevate.cmd"),
|
||||
filepath.Clean(env.symlink))) {
|
||||
ok, err := runElevated(fmt.Sprintf(`"%s" cmd /C rmdir "%s"`, filepath.Join(env.root, "elevate.cmd"), filepath.Clean(env.symlink)))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Print(fmt.Sprint(err))
|
||||
}
|
||||
|
||||
fmt.Println("nvm disabled")
|
||||
}
|
||||
@@ -777,7 +809,25 @@ func updateRootDir(path string) {
|
||||
}
|
||||
}
|
||||
|
||||
func runElevated(command string) bool {
|
||||
func runElevated(command string, forceUAC ...bool) (bool, error) {
|
||||
uac := false
|
||||
if len(forceUAC) > 0 {
|
||||
uac = forceUAC[0]
|
||||
}
|
||||
|
||||
if uac {
|
||||
log.Print(command)
|
||||
cmd := exec.Command(filepath.Join(env.root, "elevate.cmd"), command)
|
||||
var output bytes.Buffer
|
||||
var _stderr bytes.Buffer
|
||||
cmd.Stdout = &output
|
||||
cmd.Stderr = &_stderr
|
||||
perr := cmd.Run()
|
||||
if perr != nil {
|
||||
return false, errors.New(fmt.Sprint(perr) + ": " + _stderr.String())
|
||||
}
|
||||
}
|
||||
|
||||
c := exec.Command("cmd") // dummy executable that actually needs to exist but we'll overwrite using .SysProcAttr
|
||||
|
||||
// Based on the official docs, syscall.SysProcAttr.CmdLine doesn't exist.
|
||||
@@ -791,11 +841,15 @@ func runElevated(command string) bool {
|
||||
|
||||
err := c.Run()
|
||||
if err != nil {
|
||||
fmt.Println(fmt.Sprint(err) + ": " + stderr.String())
|
||||
return false
|
||||
msg := stderr.String()
|
||||
if strings.Contains(msg, "not have sufficient privilege") && uac {
|
||||
return runElevated(command, false)
|
||||
}
|
||||
// fmt.Println(fmt.Sprint(err) + ": " + stderr.String())
|
||||
return false, errors.New(fmt.Sprint(err) + ": " + msg)
|
||||
}
|
||||
|
||||
return true
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func saveSettings() {
|
||||
|
||||
Reference in New Issue
Block a user