Skip to content

Commit

Permalink
vlib.os: fix join-path
Browse files Browse the repository at this point in the history
Closes #20231
  • Loading branch information
hholst80 committed May 4, 2024
1 parent 387af74 commit 10002cc
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 31 deletions.
55 changes: 25 additions & 30 deletions vlib/os/os.v
Original file line number Diff line number Diff line change
Expand Up @@ -570,54 +570,49 @@ pub fn is_file(path string) bool {
// them with a platform-specific path_separator. Empty elements are ignored.
@[manualfree]
pub fn join_path(base string, dirs ...string) string {
// TODO: fix freeing of `dirs` when the passed arguments are variadic,
// but do not free the arr, when `os.join_path(base, ...arr)` is called.
mut sb := strings.new_builder(base.len + dirs.len * 50)
mut sb := strings.new_builder(256)
defer {
unsafe { sb.free() }
}
sbase := base.trim_right('\\/')
defer {
unsafe { sbase.free() }
mut i := 0
if base != '' {
sb.write_string(base)
} else {
for i < dirs.len {
d := dirs[i]
if d != '' {
sb.write_string(d)
break
}
i++
}
}
sb.write_string(sbase)
for d in dirs {
for i < dirs.len {
d := dirs[i]
if d != '' {
sb.write_string(path_separator)
sb.write_string(d)
}
i++
}
mut res := sb.str()
if sbase == '' {
res = res.trim_left(path_separator)
}
if res.contains('/./') {
// Fix `join_path("/foo/bar", "./file.txt")` => `/foo/bar/./file.txt`
res = res.replace('/./', '/')
}
res := sb.str()
return res
}

// join_path_single appends the `elem` after `base`, separated with a
// platform-specific path_separator. Empty elements are ignored.
@[manualfree]
pub fn join_path_single(base string, elem string) string {
// TODO: deprecate this and make it `return os.join_path(base, elem)`,
// when freeing variadic args vs ...arr is solved in the compiler
mut sb := strings.new_builder(base.len + elem.len + 1)
defer {
unsafe { sb.free() }
}
sbase := base.trim_right('\\/')
defer {
unsafe { sbase.free() }
}
if base != '' {
sb.write_string(sbase)
sb.write_string(path_separator)
if base != '' && elem != '' {
return '${base}${path_separator}${elem}'
} else if base != '' {
return base
} else if elem != '' {
return elem
} else {
return ''
}
sb.write_string(elem)
return sb.str()
}

// walk_ext returns a recursive list of all files in `path` ending with `ext`.
Expand Down
3 changes: 2 additions & 1 deletion vlib/os/os_test.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -621,9 +621,10 @@ fn test_join() {
assert os.join_path('v', '', 'dir') == 'v\\dir'
} $else {
assert os.join_path('v', 'vlib', 'os') == 'v/vlib/os'
assert os.join_path('/foo/bar', './file.txt') == '/foo/bar/file.txt'
assert os.join_path('/foo/bar', './file.txt') == '/foo/bar/./file.txt'
assert os.join_path('', 'f1', 'f2') == 'f1/f2'
assert os.join_path('v', '', 'dir') == 'v/dir'
assert os.join_path('/', 'test') == '/test'
}
}

Expand Down

0 comments on commit 10002cc

Please sign in to comment.