os: add existing_path function (#14536)
parent
928dafeb6d
commit
4ffdcf8058
|
@ -123,6 +123,52 @@ pub fn norm_path(path string) string {
|
|||
return res
|
||||
}
|
||||
|
||||
// existing_path returns the existing part of the given `path`.
|
||||
// An error is returned if there is no existing part of the given `path`.
|
||||
pub fn existing_path(path string) ?string {
|
||||
err := error('path does not exist')
|
||||
if path.len == 0 {
|
||||
return err
|
||||
}
|
||||
if exists(path) {
|
||||
return path
|
||||
}
|
||||
mut volume_len := 0
|
||||
$if windows {
|
||||
volume_len = win_volume_len(path)
|
||||
}
|
||||
if volume_len > 0 && is_slash(path[volume_len - 1]) {
|
||||
volume_len++
|
||||
}
|
||||
mut sc := textscanner.new(path[volume_len..])
|
||||
mut recent_path := path[..volume_len]
|
||||
for sc.next() != -1 {
|
||||
curr := u8(sc.current())
|
||||
peek := sc.peek()
|
||||
back := sc.peek_back()
|
||||
if is_curr_dir_ref(back, curr, peek) {
|
||||
continue
|
||||
}
|
||||
range := sc.ilen - sc.remaining() + volume_len
|
||||
if is_slash(curr) && !is_slash(u8(peek)) {
|
||||
recent_path = path[..range]
|
||||
continue
|
||||
}
|
||||
if !is_slash(curr) && (peek == -1 || is_slash(u8(peek))) {
|
||||
curr_path := path[..range]
|
||||
if exists(curr_path) {
|
||||
recent_path = curr_path
|
||||
continue
|
||||
}
|
||||
if recent_path.len == 0 {
|
||||
break
|
||||
}
|
||||
return recent_path
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// clean_path returns the "cleaned" version of the given `path`
|
||||
// by turning forward slashes into back slashes
|
||||
// on a Windows system and eliminating:
|
||||
|
@ -144,8 +190,7 @@ fn clean_path(path string) string {
|
|||
continue
|
||||
}
|
||||
// skip reference to current dir (.)
|
||||
if (back == -1 || is_slash(u8(back))) && curr == os.dot
|
||||
&& (peek == -1 || is_slash(u8(peek))) {
|
||||
if is_curr_dir_ref(back, curr, peek) {
|
||||
// skip if the next byte is a path separator
|
||||
if peek != -1 && is_slash(u8(peek)) {
|
||||
sc.skip_n(1)
|
||||
|
@ -246,3 +291,13 @@ fn is_normal_path(path string) bool {
|
|||
return (plen == 1 && is_slash(path[0])) || (plen >= 2 && is_slash(path[0])
|
||||
&& !is_slash(path[1]))
|
||||
}
|
||||
|
||||
// is_curr_dir_ref returns `true` if the 3 given integer construct
|
||||
// a reference to a current directory (.).
|
||||
// NOTE: a negative integer means that no byte is present
|
||||
fn is_curr_dir_ref(byte_one int, byte_two int, byte_three int) bool {
|
||||
if u8(byte_two) != os.dot {
|
||||
return false
|
||||
}
|
||||
return (byte_one < 0 || is_slash(u8(byte_one))) && (byte_three < 0 || is_slash(u8(byte_three)))
|
||||
}
|
||||
|
|
|
@ -36,11 +36,13 @@ fn test_clean_path() {
|
|||
assert clean_path(r'\./path/dir\\file.exe') == r'\path\dir\file.exe'
|
||||
assert clean_path(r'.') == ''
|
||||
assert clean_path(r'./') == ''
|
||||
assert clean_path('') == ''
|
||||
assert clean_path(r'\./') == '\\'
|
||||
assert clean_path(r'//\/\/////') == '\\'
|
||||
return
|
||||
}
|
||||
assert clean_path('./../.././././//') == '../..'
|
||||
assert clean_path('') == ''
|
||||
assert clean_path('.') == ''
|
||||
assert clean_path('./path/to/file.v//./') == 'path/to/file.v'
|
||||
assert clean_path('./') == ''
|
||||
|
@ -127,3 +129,26 @@ fn test_abs_path() {
|
|||
assert abs_path('path/../file.v/..') == wd
|
||||
assert abs_path('///') == '/'
|
||||
}
|
||||
|
||||
fn test_existing_path() {
|
||||
wd := getwd()
|
||||
$if windows {
|
||||
assert existing_path('') or { '' } == ''
|
||||
assert existing_path('..') or { '' } == '..'
|
||||
assert existing_path('.') or { '' } == '.'
|
||||
assert existing_path(wd) or { '' } == wd
|
||||
assert existing_path('\\') or { '' } == '\\'
|
||||
assert existing_path('$wd\\.\\\\does/not/exist\\.\\') or { '' } == '$wd\\.\\\\'
|
||||
assert existing_path('$wd\\\\/\\.\\.\\/.') or { '' } == '$wd\\\\/\\.\\.\\/.'
|
||||
assert existing_path('$wd\\././/\\/oh') or { '' } == '$wd\\././/\\/'
|
||||
return
|
||||
}
|
||||
assert existing_path('') or { '' } == ''
|
||||
assert existing_path('..') or { '' } == '..'
|
||||
assert existing_path('.') or { '' } == '.'
|
||||
assert existing_path(wd) or { '' } == wd
|
||||
assert existing_path('/') or { '' } == '/'
|
||||
assert existing_path('$wd/does/.///not/exist///.//') or { '' } == '$wd/'
|
||||
assert existing_path('$wd//././/.//') or { '' } == '$wd//././/.//'
|
||||
assert existing_path('$wd//././/.//oh') or { '' } == '$wd//././/.//'
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue