Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
风弥漫了夏天
nvm-windows
提交
8e6cecd6
N
nvm-windows
项目概览
风弥漫了夏天
/
nvm-windows
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
N
nvm-windows
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
8e6cecd6
编写于
9月 22, 2014
作者:
C
Corey Butler
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fixed symlink issues and added a settings file
上级
70d972c1
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
201 addition
and
42 deletion
+201
-42
src/nvm.go
src/nvm.go
+201
-42
未找到文件。
src/nvm.go
浏览文件 @
8e6cecd6
...
...
@@ -11,21 +11,31 @@ import (
"io/ioutil"
"regexp"
"bytes"
"encoding/json"
"archive/zip"
"log"
"bufio"
)
var
root
=
""
var
symlink
=
""
func
main
()
{
args
:=
os
.
Args
detail
:=
""
setRootDir
(
filepath
.
Dir
(
args
[
0
])
)
setRootDir
()
// Capture any additional arguments
if
(
len
(
args
)
>
2
)
{
detail
=
strings
.
ToLower
(
args
[
2
])
}
if
(
len
(
args
)
<
2
){
help
()
return
}
// Run the appropriate method
switch
args
[
1
]
{
case
"install"
:
install
(
detail
)
...
...
@@ -58,27 +68,47 @@ func install(version string) {
// Check to see if the version is already installed
if
!
isVersionInstalled
(
version
)
{
// If the version does not exist, download it to the temp directory.
success
:=
download
(
version
);
// Make the output directories
os
.
Mkdir
(
root
+
"
\\
v"
+
version
,
os
.
ModeDir
)
os
.
Mkdir
(
root
+
"
\\
v"
+
version
+
"
\\
node_modules"
,
os
.
ModeDir
)
// Download node
success
:=
downloadNodeJs
(
version
);
// Run the installer
// If successful, add npm
if
success
{
fmt
.
Printf
(
"Installing v"
+
version
+
"... "
)
os
.
Mkdir
(
root
+
"
\\
v"
+
version
,
os
.
ModeDir
)
cmd
:=
exec
.
Command
(
"msiexec.exe"
,
"/i"
,
os
.
TempDir
()
+
"
\\
"
+
"node-v"
+
version
+
".msi"
,
"INSTALLDIR="
+
root
+
"
\\
v"
+
version
,
"/qb"
)
err
:=
cmd
.
Run
()
if
err
!=
nil
{
fmt
.
Println
(
"ERROR"
)
fmt
.
Print
(
err
)
os
.
Exit
(
1
)
npmv
:=
getNpmVersion
(
version
)
success
=
downloadNpm
(
getNpmVersion
(
version
))
if
success
{
fmt
.
Printf
(
"Installing npm v"
+
npmv
+
"..."
)
// Extract npm to the temp directory
unzip
(
os
.
TempDir
()
+
"
\\
npm-v"
+
npmv
+
".zip"
,
os
.
TempDir
()
+
"
\\
nvm-npm"
)
// Copy the npm and npm.cmd files to the installation directory
os
.
Rename
(
os
.
TempDir
()
+
"
\\
nvm-npm
\\
npm-"
+
npmv
+
"
\\
bin
\\
npm"
,
root
+
"
\\
v"
+
version
+
"
\\
npm"
)
os
.
Rename
(
os
.
TempDir
()
+
"
\\
nvm-npm
\\
npm-"
+
npmv
+
"
\\
bin
\\
npm.cmd"
,
root
+
"
\\
v"
+
version
+
"
\\
npm.cmd"
)
os
.
Rename
(
os
.
TempDir
()
+
"
\\
nvm-npm
\\
npm-"
+
npmv
,
root
+
"
\\
v"
+
version
+
"
\\
node_modules
\\
npm"
)
// Remove the source file
os
.
RemoveAll
(
os
.
TempDir
()
+
"
\\
nvm-npm"
)
fmt
.
Printf
(
" done."
)
fmt
.
Println
(
"
\n\n
Installation complete. If you want to use this version, type
\n\n
nvm use "
+
version
)
}
else
{
fmt
.
Println
(
"Could not download npm for node v"
+
version
+
"."
)
fmt
.
Println
(
"Please visit https://github.com/npm/npm/releases/tag/v"
+
npmv
+
" to download npm."
)
fmt
.
Println
(
"It should be extracted to "
+
root
+
"
\\
v"
+
version
)
}
fmt
.
Printf
(
"done."
)
}
else
{
fmt
.
Println
(
"Could not download node.js executable for version "
+
version
+
"."
)
}
return
//
Clean up
fmt
.
Printf
(
"
\n
Cleaning up... "
)
os
.
Remove
(
os
.
TempDir
()
+
"
\\
"
+
"node-v"
+
version
+
".msi"
)
fmt
.
Printf
(
"done.
\n
"
)
//
Move node and npm to their directory, then update the symlink
// Remember to set the symlink path in the PATH during the installation
// If this is ever shipped for Mac, it should use homebrew.
// If this ever ships on Linux, it should be on bintray so it can use yum, apt-get, etc.
return
}
else
{
...
...
@@ -98,7 +128,7 @@ func uninstall(version string) {
// Determine if the version exists and skip if it doesn't
if
isVersionInstalled
(
version
)
{
fmt
.
Printf
(
"
\n
Uninstalling node v"
+
version
+
"..."
)
fmt
.
Printf
(
"Uninstalling node v"
+
version
+
"..."
)
e
:=
os
.
RemoveAll
(
root
+
"
\\
v"
+
version
)
if
e
!=
nil
{
fmt
.
Println
(
"Error removing node v"
+
version
)
...
...
@@ -118,8 +148,23 @@ func use(version string) {
return
}
// Create the symlink
c
:=
exec
.
Command
(
root
+
"
\\
elevate.cmd"
,
"cmd"
,
"/C"
,
"mklink"
,
"/D"
,
root
+
"
\\
action"
,
root
+
"
\\
v"
+
version
)
// Create or update the symlink
sym
,
serr
:=
os
.
Stat
(
symlink
)
sym
=
sym
if
serr
==
nil
{
cmd
:=
exec
.
Command
(
root
+
"
\\
elevate.cmd"
,
"cmd"
,
"/C"
,
"rmdir"
,
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
}
}
c
:=
exec
.
Command
(
root
+
"
\\
elevate.cmd"
,
"cmd"
,
"/C"
,
"mklink"
,
"/D"
,
symlink
,
root
+
"
\\
v"
+
version
)
var
out
bytes
.
Buffer
var
stderr
bytes
.
Buffer
c
.
Stdout
=
&
out
...
...
@@ -137,7 +182,7 @@ func list(listtype string) {
listtype
=
"installed"
}
if
listtype
!=
"installed"
&&
listtype
!=
"available"
{
fmt
.
Println
(
"
\n
Invalid list option.
\n\n
Please use on of the following
\n
-
wnvm list
\n
- wnvm list installed
\n
- w
nvm list available"
)
fmt
.
Println
(
"
\n
Invalid list option.
\n\n
Please use on of the following
\n
-
nvm list
\n
- nvm list installed
\n
-
nvm list available"
)
help
()
return
}
...
...
@@ -154,28 +199,18 @@ func disable() {
fmt
.
Printf
(
"Disable by removing the symlink in PATH var"
)
}
func
setRootDir
(
path
string
)
{
// Prompt user, warning them what they're going to do
rootdir
,
err
:=
filepath
.
Abs
(
filepath
.
Dir
(
path
+
"
\\
"
))
if
err
!=
nil
{
fmt
.
Println
(
"Error setting root directory"
)
os
.
Exit
(
1
)
}
root
=
rootdir
fmt
.
Println
(
"
\n
Set the root path to "
+
root
)
}
func
help
()
{
fmt
.
Println
(
"
\n
Usage:
\n
"
)
fmt
.
Println
(
" nvm install <version> : The version can be a node.js version or
\"
latest
\"
for the latest stable version."
)
fmt
.
Println
(
" nvm uninstall <version> : The version must be a specific version."
)
fmt
.
Println
(
" nvm use <version> : Switch to use the specified version."
)
fmt
.
Println
(
" nvm list [type] : type can be
\"
available
\"
(from nodejs.org),"
)
fmt
.
Println
(
"
\"
installed
\"
(what is currently on the computer),"
)
fmt
.
Println
(
" or left blank (same as
\"
installed
\"
)."
)
fmt
.
Println
(
" nvm enable : Enable node.js version management."
)
fmt
.
Println
(
" nvm disable : Disable node.js version management."
)
fmt
.
Println
(
" nvm root <path> : Set the directory where wnvm should install different node.js versions.
\n
"
)
fmt
.
Println
(
"
\"
installed
\"
(what is currently on the computer),"
)
fmt
.
Println
(
" or left blank (same as
\"
installed
\"
)."
)
fmt
.
Println
(
" nvm on : Enable node.js version management."
)
fmt
.
Println
(
" nvm off : Disable node.js version management."
)
fmt
.
Println
(
" nvm root <path> : Set the directory where wnvm should install different node.js versions."
)
fmt
.
Println
(
" If <path> is not set, the current root will be displayed.
\n
"
)
}
func
getRemoteTextFile
(
url
string
)
string
{
...
...
@@ -197,13 +232,61 @@ func getRemoteTextFile(url string) string {
return
""
}
// Download an MSI to the temp directory
func
download
(
v
string
)
bool
{
// Given a node.js version, returns the associated npm version
func
getNpmVersion
(
nodeversion
string
)
string
{
// Get raw text
text
:=
getRemoteTextFile
(
"https://raw.githubusercontent.com/coreybutler/nodedistro/master/nodeversions.json"
)
// Parse
var
data
interface
{}
json
.
Unmarshal
([]
byte
(
text
),
&
data
);
body
:=
data
.
(
map
[
string
]
interface
{})
all
:=
body
[
"all"
]
npm
:=
all
.
(
map
[
string
]
interface
{})
return
npm
[
nodeversion
]
.
(
string
)
}
func
downloadNodeJs
(
v
string
)
bool
{
url
:=
"http://nodejs.org/dist/v"
+
v
+
"/node
-v"
+
v
+
"-x86.msi
"
fileName
:=
os
.
TempDir
()
+
"
\\
"
+
"node-v"
+
v
+
".msi
"
url
:=
"http://nodejs.org/dist/v"
+
v
+
"/node
.exe
"
fileName
:=
root
+
"
\\
v"
+
v
+
"
\\
node.exe
"
fmt
.
Printf
(
"
\n
Downloading node.js version "
+
v
+
"... "
)
fmt
.
Printf
(
"Downloading node.js version "
+
v
+
"... "
)
output
,
err
:=
os
.
Create
(
fileName
)
if
err
!=
nil
{
fmt
.
Println
(
"Error while creating"
,
fileName
,
"-"
,
err
)
}
defer
output
.
Close
()
response
,
err
:=
http
.
Get
(
url
)
if
err
!=
nil
{
fmt
.
Println
(
"Error while downloading"
,
url
,
"-"
,
err
)
}
defer
response
.
Body
.
Close
()
n
,
err
:=
io
.
Copy
(
output
,
response
.
Body
)
if
err
!=
nil
{
fmt
.
Println
(
"Error while downloading"
,
url
,
"-"
,
err
)
}
if
response
.
Status
[
0
:
3
]
==
"200"
{
fmt
.
Println
(
n
,
"bytes downloaded."
)
}
else
{
fmt
.
Println
(
"ERROR"
)
}
return
response
.
Status
[
0
:
3
]
==
"200"
}
func
downloadNpm
(
v
string
)
bool
{
url
:=
"https://github.com/npm/npm/archive/v"
+
v
+
".zip"
fileName
:=
os
.
TempDir
()
+
"
\\
"
+
"npm-v"
+
v
+
".zip"
fmt
.
Printf
(
"Downloading npm version "
+
v
+
"... "
)
output
,
err
:=
os
.
Create
(
fileName
)
if
err
!=
nil
{
...
...
@@ -236,3 +319,79 @@ func isVersionInstalled(version string) bool {
src
=
src
return
err
==
nil
}
// Function courtesy http://stackoverflow.com/users/1129149/swtdrgn
func
unzip
(
src
,
dest
string
)
error
{
r
,
err
:=
zip
.
OpenReader
(
src
)
if
err
!=
nil
{
return
err
}
defer
r
.
Close
()
for
_
,
f
:=
range
r
.
File
{
rc
,
err
:=
f
.
Open
()
if
err
!=
nil
{
return
err
}
defer
rc
.
Close
()
fpath
:=
filepath
.
Join
(
dest
,
f
.
Name
)
if
f
.
FileInfo
()
.
IsDir
()
{
os
.
MkdirAll
(
fpath
,
f
.
Mode
())
}
else
{
var
fdir
string
if
lastIndex
:=
strings
.
LastIndex
(
fpath
,
string
(
os
.
PathSeparator
));
lastIndex
>
-
1
{
fdir
=
fpath
[
:
lastIndex
]
}
err
=
os
.
MkdirAll
(
fdir
,
f
.
Mode
())
if
err
!=
nil
{
log
.
Fatal
(
err
)
return
err
}
f
,
err
:=
os
.
OpenFile
(
fpath
,
os
.
O_WRONLY
|
os
.
O_CREATE
|
os
.
O_TRUNC
,
f
.
Mode
())
if
err
!=
nil
{
return
err
}
defer
f
.
Close
()
_
,
err
=
io
.
Copy
(
f
,
rc
)
if
err
!=
nil
{
return
err
}
}
}
return
nil
}
func
readLines
(
path
string
)
([]
string
,
error
)
{
file
,
err
:=
os
.
Open
(
path
)
if
err
!=
nil
{
return
nil
,
err
}
defer
file
.
Close
()
var
lines
[]
string
scanner
:=
bufio
.
NewScanner
(
file
)
for
scanner
.
Scan
()
{
lines
=
append
(
lines
,
scanner
.
Text
())
}
return
lines
,
scanner
.
Err
()
}
func
setRootDir
()
{
lines
,
err
:=
readLines
(
os
.
Getenv
(
"APPDATA"
)
+
"
\\
nvm
\\
settings.txt"
)
if
err
!=
nil
{
fmt
.
Println
(
"
\n
ERROR"
,
err
)
os
.
Exit
(
1
)
}
// Process each line and extract the value
for
_
,
line
:=
range
lines
{
if
strings
.
Contains
(
line
,
"root:"
)
{
root
=
strings
.
Trim
(
regexp
.
MustCompile
(
"root:"
)
.
ReplaceAllString
(
line
,
""
),
" "
)
}
else
if
strings
.
Contains
(
line
,
"path:"
)
{
symlink
=
strings
.
Trim
(
regexp
.
MustCompile
(
"path:"
)
.
ReplaceAllString
(
line
,
""
),
" "
)
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录