v symlink: fix windows PATH setting (cmd.exe needs C: not c:)
parent
66b8462d7a
commit
f7698ea160
|
@ -8,7 +8,7 @@ $if windows {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn main() {
|
fn main() {
|
||||||
vexe := pref.vexe_path()
|
vexe := os.real_path(pref.vexe_path())
|
||||||
$if windows {
|
$if windows {
|
||||||
setup_symlink_windows(vexe)
|
setup_symlink_windows(vexe)
|
||||||
} $else {
|
} $else {
|
||||||
|
@ -36,10 +36,10 @@ fn setup_symlink(vexe string) {
|
||||||
if ret.exit_code == 0 {
|
if ret.exit_code == 0 {
|
||||||
println('Symlink "$link_path" has been created')
|
println('Symlink "$link_path" has been created')
|
||||||
} else {
|
} else {
|
||||||
println('Failed to create symlink "$link_path". Try again with sudo.')
|
eprintln('Failed to create symlink "$link_path". Try again with sudo.')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
println('Failed to create symlink "$link_path". Try again with sudo.')
|
eprintln('Failed to create symlink "$link_path". Try again with sudo.')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,22 +56,24 @@ fn setup_symlink_windows(vexe string) {
|
||||||
} else {
|
} else {
|
||||||
os.rm(vsymlink)
|
os.rm(vsymlink)
|
||||||
}
|
}
|
||||||
// try to create a native symlink at .\.bin\v.exe
|
// First, try to create a native symlink at .\.bin\v.exe
|
||||||
os.symlink(vsymlink, vexe) or {
|
os.symlink(vsymlink, vexe) or {
|
||||||
// typically only fails if you're on a network drive (VirtualBox)
|
// typically only fails if you're on a network drive (VirtualBox)
|
||||||
// do batch file creation instead
|
// do batch file creation instead
|
||||||
eprint('NOTE: Could not create a native symlink: $err')
|
eprintln('Could not create a native symlink: $err')
|
||||||
eprintln('Creating a batch file instead...')
|
eprintln('Creating a batch file instead...')
|
||||||
vsymlink = os.join_path(vsymlinkdir, 'v.bat')
|
vsymlink = os.join_path(vsymlinkdir, 'v.bat')
|
||||||
if os.exists(vsymlink) {
|
if os.exists(vsymlink) {
|
||||||
os.rm(vsymlink)
|
os.rm(vsymlink)
|
||||||
}
|
}
|
||||||
os.write_file(vsymlink, '@echo off\n$vexe %*')
|
os.write_file(vsymlink, '@echo off\n$vexe %*')
|
||||||
|
eprintln('$vsymlink file written.')
|
||||||
}
|
}
|
||||||
if !os.exists(vsymlink) {
|
if !os.exists(vsymlink) {
|
||||||
warn_and_exit('Could not create $vsymlink')
|
warn_and_exit('Could not create $vsymlink')
|
||||||
}
|
}
|
||||||
print('Symlink $vsymlink to $vexe created.\n\nChecking system %PATH%...')
|
println('Symlink $vsymlink to $vexe created.')
|
||||||
|
println('Checking system %PATH%...')
|
||||||
reg_sys_env_handle := get_reg_sys_env_handle() or {
|
reg_sys_env_handle := get_reg_sys_env_handle() or {
|
||||||
warn_and_exit(err)
|
warn_and_exit(err)
|
||||||
return
|
return
|
||||||
|
@ -87,15 +89,19 @@ fn setup_symlink_windows(vexe string) {
|
||||||
current_sys_paths := sys_env_path.split(os.path_delimiter).map(it.trim('/$os.path_separator'))
|
current_sys_paths := sys_env_path.split(os.path_delimiter).map(it.trim('/$os.path_separator'))
|
||||||
mut new_paths := [vsymlinkdir]
|
mut new_paths := [vsymlinkdir]
|
||||||
for p in current_sys_paths {
|
for p in current_sys_paths {
|
||||||
|
if p == '' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if p !in new_paths {
|
if p !in new_paths {
|
||||||
new_paths << p
|
new_paths << p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new_sys_env_path := new_paths.join(';')
|
new_sys_env_path := new_paths.join(';')
|
||||||
if new_sys_env_path == sys_env_path {
|
if new_sys_env_path == sys_env_path {
|
||||||
println('configured.')
|
println('System %PATH% was already configured.')
|
||||||
} else {
|
} else {
|
||||||
print('not configured.\nAdding symlink directory to system %PATH%...')
|
println('System %PATH% was not configured.')
|
||||||
|
println('Adding symlink directory to system %PATH%...')
|
||||||
set_reg_value(reg_sys_env_handle, 'Path', new_sys_env_path) or {
|
set_reg_value(reg_sys_env_handle, 'Path', new_sys_env_path) or {
|
||||||
warn_and_exit(err)
|
warn_and_exit(err)
|
||||||
C.RegCloseKey(reg_sys_env_handle)
|
C.RegCloseKey(reg_sys_env_handle)
|
||||||
|
@ -103,15 +109,16 @@ fn setup_symlink_windows(vexe string) {
|
||||||
}
|
}
|
||||||
println('done.')
|
println('done.')
|
||||||
}
|
}
|
||||||
print('Letting running process know to update their Environment...')
|
println('Notifying running processes to update their Environment...')
|
||||||
send_setting_change_msg('Environment') or {
|
send_setting_change_msg('Environment') or {
|
||||||
eprintln('\n' + err)
|
eprintln(err)
|
||||||
warn_and_exit('You might need to run this again to have the `v` command in your %PATH%')
|
warn_and_exit('You might need to run this again to have the `v` command in your %PATH%')
|
||||||
C.RegCloseKey(reg_sys_env_handle)
|
C.RegCloseKey(reg_sys_env_handle)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
C.RegCloseKey(reg_sys_env_handle)
|
C.RegCloseKey(reg_sys_env_handle)
|
||||||
println('finished.\n\nNote: restart your shell/IDE to load the new %PATH%.')
|
println('')
|
||||||
|
println('Note: restart your shell/IDE to load the new %PATH%.')
|
||||||
println('After restarting your shell/IDE, give `v version` a try in another dir!')
|
println('After restarting your shell/IDE, give `v version` a try in another dir!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
20
vlib/os/os.v
20
vlib/os/os.v
|
@ -1141,9 +1141,27 @@ pub fn real_path(fpath string) string {
|
||||||
return fpath
|
return fpath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return unsafe { fullpath.vstring() }
|
res := unsafe { fullpath.vstring() }
|
||||||
|
return normalize_drive_letter(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn normalize_drive_letter(path string) string {
|
||||||
|
// normalize_drive_letter is needed, because a path like c:\nv\.bin (note the small `c`)
|
||||||
|
// in %PATH is NOT recognized by cmd.exe (and probably other programs too)...
|
||||||
|
// Capital drive letters do work fine.
|
||||||
|
$if !windows {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
if path.len > 2 && path[0] >= `a` && path[0] <= `z` && path[1] == `:` && path[2] == os.path_separator[0] {
|
||||||
|
unsafe {
|
||||||
|
x := &path.str[0]
|
||||||
|
(*x) = *x - 32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// is_abs_path returns `true` if `path` is absolute.
|
// is_abs_path returns `true` if `path` is absolute.
|
||||||
pub fn is_abs_path(path string) bool {
|
pub fn is_abs_path(path string) bool {
|
||||||
$if windows {
|
$if windows {
|
||||||
|
|
|
@ -294,14 +294,23 @@ pub fn exec(cmd string) ?Result {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw
|
||||||
fn C.CreateSymbolicLinkW(&u16, &u16, u32) int
|
fn C.CreateSymbolicLinkW(&u16, &u16, u32) int
|
||||||
|
|
||||||
pub fn symlink(origin string, target string) ?bool {
|
pub fn symlink(symlink_path string, target_path string) ?bool {
|
||||||
flags := if is_dir(origin) { 1 } else { 0 }
|
mut flags := 0
|
||||||
if C.CreateSymbolicLinkW(origin.to_wide(), target.to_wide(), u32(flags)) != 0 {
|
if is_dir(symlink_path) {
|
||||||
return true
|
flags |= 1
|
||||||
}
|
}
|
||||||
|
flags |= 2 // SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
|
||||||
|
res := C.CreateSymbolicLinkW(symlink_path.to_wide(), target_path.to_wide(), flags)
|
||||||
|
if res == 0 {
|
||||||
return error(get_error_msg(int(C.GetLastError())))
|
return error(get_error_msg(int(C.GetLastError())))
|
||||||
|
}
|
||||||
|
if !exists(symlink_path) {
|
||||||
|
return error('C.CreateSymbolicLinkW reported success, but symlink still does not exist')
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut f File) close() {
|
pub fn (mut f File) close() {
|
||||||
|
|
Loading…
Reference in New Issue