未验证 提交 08fb7000 编写于 作者: C Corey Butler 提交者: GitHub

Merge pull request #355 from s-h-a-d-o-w/master

Fixes #41 - Issue with blank spaces in path
package main
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"strings"
"io/ioutil"
"path/filepath"
"regexp"
"bytes"
"strconv"
"strings"
"syscall"
"time"
"./nvm/web"
"./nvm/arch"
"./nvm/file"
"./nvm/node"
"strconv"
"path/filepath"
"github.com/olekukonko/tablewriter"
)
......@@ -57,7 +58,7 @@ func main() {
detail := ""
procarch := arch.Validate(env.arch)
Setup()
setup()
// Capture any additional arguments
if len(args) > 2 {
......@@ -114,13 +115,17 @@ func main() {
env.proxy = detail
saveSettings()
}
case "update": update()
//case "update": update()
case "node_mirror": setNodeMirror(detail)
case "npm_mirror": setNpmMirror(detail)
default: help()
}
}
// ===============================================================
// BEGIN | CLI functions
// ===============================================================
func setNodeMirror(uri string) {
env.node_mirror = uri
saveSettings()
......@@ -131,40 +136,20 @@ func setNpmMirror(uri string) {
saveSettings()
}
/*
func update() {
// cmd := exec.Command("cmd", "/d", "echo", "testing")
// var output bytes.Buffer
// var _stderr bytes.Buffer
// cmd.Stdout = &output
// cmd.Stderr = &_stderr
// perr := cmd.Run()
// if perr != nil {
// fmt.Println(fmt.Sprint(perr) + ": " + _stderr.String())
// return
// }
}
func CheckVersionExceedsLatest(version string) bool{
//content := web.GetRemoteTextFile("http://nodejs.org/dist/latest/SHASUMS256.txt")
url := web.GetFullNodeUrl("latest/SHASUMS256.txt");
content := web.GetRemoteTextFile(url)
re := regexp.MustCompile("node-v(.+)+msi")
reg := regexp.MustCompile("node-v|-x.+")
latest := reg.ReplaceAllString(re.FindString(content),"")
var vArr = strings.Split(version,".")
var lArr = strings.Split(latest, ".")
for index := range lArr {
lat,_ := strconv.Atoi(lArr[index])
ver,_ := strconv.Atoi(vArr[index])
//Should check for valid input (checking for conversion errors) but this tool is made to trust the user
if ver < lat {
return false
} else if ver > lat {
return true
}
}
return false
cmd := exec.Command("cmd", "/d", "echo", "testing")
var output bytes.Buffer
var _stderr bytes.Buffer
cmd.Stdout = &output
cmd.Stderr = &_stderr
perr := cmd.Run()
if perr != nil {
fmt.Println(fmt.Sprint(perr) + ": " + _stderr.String())
return
}
}
*/
func install(version string, cpuarch string) {
args := os.Args
......@@ -213,7 +198,7 @@ func install(version string, cpuarch string) {
version = cleanVersion(version)
}
if CheckVersionExceedsLatest(version) {
if checkVersionExceedsLatest(version) {
fmt.Println("Node.js v"+version+" is not yet released or available.")
return
}
......@@ -356,8 +341,9 @@ func uninstall(version string) {
fmt.Printf("Uninstalling node v"+version+"...")
v, _ := node.GetCurrentVersion()
if v == version {
cmd := exec.Command(filepath.Join(env.root, "elevate.cmd"), "cmd", "/C", "rmdir", env.symlink)
cmd.Run()
runElevated(fmt.Sprintf(`"%s" cmd /C rmdir "%s"`,
filepath.Join(env.root, "elevate.cmd"),
filepath.Clean(env.symlink)))
}
e := os.RemoveAll(filepath.Join(env.root, "v"+version))
if e != nil {
......@@ -381,24 +367,6 @@ func findLatestSubVersion(version string) string {
return latest
}
func cleanVersion(version string) string {
re := regexp.MustCompile("\\d+.\\d+.\\d+")
matched := re.FindString(version)
if len(matched) == 0 {
re = regexp.MustCompile("\\d+.\\d+")
matched = re.FindString(version)
if len(matched) == 0 {
matched = version + ".0.0"
} else {
matched = matched + ".0"
}
fmt.Println(matched)
}
return matched
}
func use(version string, cpuarch string) {
if version == "32" || version == "64" {
cpuarch = version
......@@ -426,30 +394,22 @@ func use(version string, cpuarch string) {
return
}
// Create or update the symlink
// Remove symlink if it already exists
sym, _ := os.Stat(env.symlink)
if sym != nil {
cmd := exec.Command(filepath.Join(env.root, "elevate.cmd"), "cmd", "/C", "rmdir", filepath.Clean(env.symlink))
var output bytes.Buffer
var _stderr bytes.Buffer
cmd.Stdout = &output
cmd.Stderr = &_stderr
perr := cmd.Run()
if perr != nil {
fmt.Println(fmt.Sprint(perr) + ": " + _stderr.String())
return
if !runElevated(fmt.Sprintf(`"%s" cmd /C rmdir "%s"`,
filepath.Join(env.root, "elevate.cmd"),
filepath.Clean(env.symlink))) {
return
}
}
c := exec.Command(filepath.Join(env.root, "elevate.cmd"), "cmd", "/C", "mklink", "/D", filepath.Clean(env.symlink), filepath.Join(env.root, "v"+version))
var out bytes.Buffer
var stderr bytes.Buffer
c.Stdout = &out
c.Stderr = &stderr
err := c.Run()
if err != nil {
fmt.Println(fmt.Sprint(err) + ": " + stderr.String())
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))) {
return
}
// Use the assigned CPU architecture
......@@ -600,8 +560,12 @@ func enable() {
}
func disable() {
cmd := exec.Command(filepath.Join(env.root, "elevate.cmd"), "cmd", "/C", "rmdir", env.symlink)
cmd.Run()
if !runElevated(fmt.Sprintf(`"%s" cmd /C rmdir "%s"`,
filepath.Join(env.root, "elevate.cmd"),
filepath.Clean(env.symlink))) {
return
}
fmt.Println("nvm disabled")
}
......@@ -614,7 +578,7 @@ func help() {
fmt.Println(" Optionally specify whether to install the 32 or 64 bit version (defaults to system arch).")
fmt.Println(" Set [arch] to \"all\" to install 32 AND 64 bit versions.")
fmt.Println(" Add --insecure to the end of this command to bypass SSL validation of the remote download server.")
fmt.Println(" nvm list [available] : List the node.js installations. Type \"available\" at the end to see what can be installed. Aliased as ls.")
fmt.Println(" nvm list [available] : List the node.js installations. Type \"available\" at the end to see what can be installed. Aliased as ls.")
fmt.Println(" nvm on : Enable node.js version management.")
fmt.Println(" nvm off : Disable node.js version management.")
fmt.Println(" nvm proxy [url] : Set a proxy to use for downloads. Leave [url] blank to see the current proxy.")
......@@ -630,12 +594,56 @@ func help() {
fmt.Println(" nvm version : Displays the current running version of nvm for Windows. Aliased as v.")
fmt.Println(" ")
}
// ===============================================================
// END | CLI functions
// ===============================================================
// ===============================================================
// BEGIN | Utility functions
// ===============================================================
func checkVersionExceedsLatest(version string) bool{
//content := web.GetRemoteTextFile("http://nodejs.org/dist/latest/SHASUMS256.txt")
url := web.GetFullNodeUrl("latest/SHASUMS256.txt");
content := web.GetRemoteTextFile(url)
re := regexp.MustCompile("node-v(.+)+msi")
reg := regexp.MustCompile("node-v|-x.+")
latest := reg.ReplaceAllString(re.FindString(content),"")
var vArr = strings.Split(version,".")
var lArr = strings.Split(latest, ".")
for index := range lArr {
lat,_ := strconv.Atoi(lArr[index])
ver,_ := strconv.Atoi(vArr[index])
//Should check for valid input (checking for conversion errors) but this tool is made to trust the user
if ver < lat {
return false
} else if ver > lat {
return true
}
}
return false
}
func cleanVersion(version string) string {
re := regexp.MustCompile("\\d+.\\d+.\\d+")
matched := re.FindString(version)
if len(matched) == 0 {
re = regexp.MustCompile("\\d+.\\d+")
matched = re.FindString(version)
if len(matched) == 0 {
matched = version + ".0.0"
} else {
matched = matched + ".0"
}
fmt.Println(matched)
}
return matched
}
// Given a node.js version, returns the associated npm version
func getNpmVersion(nodeversion string) string {
_, _, _, _, _, npm := node.GetAvailable()
return npm[nodeversion]
}
......@@ -651,13 +659,54 @@ func updateRootDir(path string) {
fmt.Println("\nRoot has been set to "+path)
}
func runElevated(command string) bool {
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.
// But it does and is vital:
// https://github.com/golang/go/issues/15566#issuecomment-333274825
// https://medium.com/@felixge/killing-a-child-process-and-all-of-its-children-in-go-54079af94773
c.SysProcAttr = &syscall.SysProcAttr{CmdLine: command}
var stderr bytes.Buffer
c.Stderr = &stderr
err := c.Run()
if err != nil {
fmt.Println(fmt.Sprint(err) + ": " + stderr.String())
return false
}
return true
}
func saveSettings() {
content := "root: " + strings.Trim(env.root, " \n\r") + "\r\narch: " + strings.Trim(env.arch, " \n\r") + "\r\nproxy: " + strings.Trim(env.proxy, " \n\r") + "\r\noriginalpath: " + strings.Trim(env.originalpath, " \n\r") + "\r\noriginalversion: " + strings.Trim(env.originalversion, " \n\r")
content = content + "\r\nnode_mirror: " + strings.Trim(env.node_mirror, " \n\r") + "\r\nnpm_mirror: " + strings.Trim(env.npm_mirror, " \n\r")
ioutil.WriteFile(env.settings, []byte(content), 0644)
}
func Setup() {
// NOT USED?
/*
func useArchitecture(a string) {
if strings.ContainsAny("32",os.Getenv("PROCESSOR_ARCHITECTURE")) {
fmt.Println("This computer only supports 32-bit processing.")
return
}
if a == "32" || a == "64" {
env.arch = a
saveSettings()
fmt.Println("Set to "+a+"-bit mode")
} else {
fmt.Println("Cannot set architecture to "+a+". Must be 32 or 64 are acceptable values.")
}
}
*/
// ===============================================================
// END | Utility functions
// ===============================================================
func setup() {
lines, err := file.ReadLines(env.settings)
if err != nil {
fmt.Println("\nERROR",err)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册