os: add a glob() function (#10497)
parent
f029f7e897
commit
d2f19ac494
|
@ -0,0 +1,62 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
fn deep_glob() ? {
|
||||||
|
os.chdir(@VMODROOT)
|
||||||
|
matches := os.glob('vlib/v/*/*.v') or { panic(err) }
|
||||||
|
assert matches.len > 10
|
||||||
|
assert 'vlib/v/ast/ast.v' in matches
|
||||||
|
assert 'vlib/v/ast/table.v' in matches
|
||||||
|
assert 'vlib/v/token/token.v' in matches
|
||||||
|
for f in matches {
|
||||||
|
if !f.starts_with('vlib/v/') {
|
||||||
|
assert false
|
||||||
|
}
|
||||||
|
assert f.ends_with('.v')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_glob_can_find_v_files_3_levels_deep() ? {
|
||||||
|
$if !windows {
|
||||||
|
deep_glob() ?
|
||||||
|
}
|
||||||
|
assert true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_glob_can_find_files_in_current_folder() ? {
|
||||||
|
os.chdir(@VMODROOT)
|
||||||
|
matches := os.glob('*') ?
|
||||||
|
assert 'README.md' in matches
|
||||||
|
assert 'v.mod' in matches
|
||||||
|
assert 'cmd/' in matches
|
||||||
|
assert 'vlib/' in matches
|
||||||
|
for f in matches {
|
||||||
|
assert !f.ends_with('.v')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_glob_can_be_used_with_multiple_patterns() ? {
|
||||||
|
os.chdir(@VMODROOT)
|
||||||
|
matches := os.glob('*', 'cmd/tools/*') ?
|
||||||
|
assert 'README.md' in matches
|
||||||
|
assert 'Makefile' in matches
|
||||||
|
$if !windows {
|
||||||
|
assert 'cmd/tools/test_if_v_test_system_works.v' in matches
|
||||||
|
}
|
||||||
|
$if windows {
|
||||||
|
assert 'test_if_v_test_system_works.v' in matches
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_glob_star() ? {
|
||||||
|
os.chdir(@VMODROOT)
|
||||||
|
matches := os.glob('*ake*') ?
|
||||||
|
assert 'Makefile' in matches
|
||||||
|
assert 'make.bat' in matches
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_glob_not_found() ? {
|
||||||
|
os.glob('an_unknown_folder/*.v') or {
|
||||||
|
assert true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
|
@ -183,7 +183,7 @@ pub fn file_size(path string) u64 {
|
||||||
}
|
}
|
||||||
$if x32 {
|
$if x32 {
|
||||||
$if debug {
|
$if debug {
|
||||||
println('Using os.file_size() on 32bit systems may not work on big files.')
|
eprintln('Using os.file_size() on 32bit systems may not work on big files.')
|
||||||
}
|
}
|
||||||
$if windows {
|
$if windows {
|
||||||
if C._wstat(path.to_wide(), voidptr(&s)) != 0 {
|
if C._wstat(path.to_wide(), voidptr(&s)) != 0 {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import strings
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
|
#include <glob.h>
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
path_separator = '/'
|
path_separator = '/'
|
||||||
|
@ -49,6 +50,14 @@ mut:
|
||||||
machine &char
|
machine &char
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[typedef]
|
||||||
|
struct C.glob_t {
|
||||||
|
mut:
|
||||||
|
gl_pathc size_t // number of matched paths
|
||||||
|
gl_pathv &&char // list of matched pathnames
|
||||||
|
gl_offs size_t // slots to reserve in gl_pathv
|
||||||
|
}
|
||||||
|
|
||||||
fn C.uname(name voidptr) int
|
fn C.uname(name voidptr) int
|
||||||
|
|
||||||
fn C.symlink(&char, &char) int
|
fn C.symlink(&char, &char) int
|
||||||
|
@ -67,6 +76,37 @@ fn C.getgid() int
|
||||||
fn C.getegid() int
|
fn C.getegid() int
|
||||||
|
|
||||||
fn C.ptrace(u32, u32, voidptr, int) u64
|
fn C.ptrace(u32, u32, voidptr, int) u64
|
||||||
|
fn C.glob(&char, int, voidptr, voidptr) int
|
||||||
|
|
||||||
|
fn C.globfree(voidptr)
|
||||||
|
|
||||||
|
pub fn glob(patterns ...string) ?[]string {
|
||||||
|
mut matches := []string{}
|
||||||
|
if patterns.len == 0 {
|
||||||
|
return matches
|
||||||
|
}
|
||||||
|
mut globdata := C.glob_t{
|
||||||
|
gl_pathv: 0
|
||||||
|
}
|
||||||
|
mut flags := int(C.GLOB_DOOFFS | C.GLOB_MARK)
|
||||||
|
for i, pattern in patterns {
|
||||||
|
if i > 0 {
|
||||||
|
flags |= C.GLOB_APPEND
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
if C.glob(&char(pattern.str), flags, C.NULL, &globdata) != 0 {
|
||||||
|
return error_with_code(posix_get_error_msg(C.errno), C.errno)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 0; i < int(globdata.gl_pathc); i++ {
|
||||||
|
unsafe {
|
||||||
|
matches << cstring_to_vstring(globdata.gl_pathv[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
C.globfree(&globdata)
|
||||||
|
return matches
|
||||||
|
}
|
||||||
|
|
||||||
pub fn uname() Uname {
|
pub fn uname() Uname {
|
||||||
mut u := Uname{}
|
mut u := Uname{}
|
||||||
|
|
|
@ -699,3 +699,28 @@ fn test_truncate() {
|
||||||
fn test_hostname() {
|
fn test_hostname() {
|
||||||
assert os.hostname().len > 2
|
assert os.hostname().len > 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_glob() {
|
||||||
|
os.mkdir('test_dir') or { panic(err) }
|
||||||
|
for i in 0 .. 4 {
|
||||||
|
if i == 3 {
|
||||||
|
mut f := os.create('test_dir/test0_another') or { panic(err) }
|
||||||
|
f.close()
|
||||||
|
mut f1 := os.create('test_dir/test') or { panic(err) }
|
||||||
|
f1.close()
|
||||||
|
} else {
|
||||||
|
mut f := os.create('test_dir/test' + i.str()) or { panic(err) }
|
||||||
|
f.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
files := os.glob('test_dir/t*') or { panic(err) }
|
||||||
|
assert files.len == 5
|
||||||
|
assert os.base(files[0]) == 'test'
|
||||||
|
|
||||||
|
for i in 0 .. 3 {
|
||||||
|
os.rm('test_dir/test' + i.str()) or { panic(err) }
|
||||||
|
}
|
||||||
|
os.rm('test_dir/test0_another') or { panic(err) }
|
||||||
|
os.rm('test_dir/test') or { panic(err) }
|
||||||
|
os.rmdir_all('test_dir') or { panic(err) }
|
||||||
|
}
|
||||||
|
|
|
@ -94,6 +94,57 @@ fn init_os_args_wide(argc int, argv &&byte) []string {
|
||||||
return args_
|
return args_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn glob(patterns ...string) ?[]string {
|
||||||
|
mut matches := []string{}
|
||||||
|
for pattern in patterns {
|
||||||
|
windows_glob_pattern(pattern, mut matches) ?
|
||||||
|
}
|
||||||
|
return matches
|
||||||
|
}
|
||||||
|
|
||||||
|
fn windows_glob_pattern(pattern string, mut matches []string) ? {
|
||||||
|
$if debug {
|
||||||
|
// FindFirstFile() and FindNextFile() both have a globbing function.
|
||||||
|
// Unfortunately this is not as pronounced as under Unix, but should provide some functionality
|
||||||
|
eprintln('os.glob() does not have all the features on Windows as it has on Unix operating systems')
|
||||||
|
}
|
||||||
|
mut find_file_data := Win32finddata{}
|
||||||
|
wpattern := pattern.replace('/', '\\').to_wide()
|
||||||
|
h_find_files := C.FindFirstFile(wpattern, voidptr(&find_file_data))
|
||||||
|
|
||||||
|
defer {
|
||||||
|
C.FindClose(h_find_files)
|
||||||
|
}
|
||||||
|
|
||||||
|
if h_find_files == C.INVALID_HANDLE_VALUE {
|
||||||
|
return error('os.glob(): Could not get a file handle: ' +
|
||||||
|
get_error_msg(int(C.GetLastError())))
|
||||||
|
}
|
||||||
|
|
||||||
|
// save first finding
|
||||||
|
fname := unsafe { string_from_wide(&find_file_data.c_file_name[0]) }
|
||||||
|
if fname !in ['.', '..'] {
|
||||||
|
mut fp := fname.replace('\\', '/')
|
||||||
|
if find_file_data.dw_file_attributes & u32(C.FILE_ATTRIBUTE_DIRECTORY) > 0 {
|
||||||
|
fp += '/'
|
||||||
|
}
|
||||||
|
matches << fp
|
||||||
|
}
|
||||||
|
|
||||||
|
// check and save next findings
|
||||||
|
for i := 0; C.FindNextFile(h_find_files, voidptr(&find_file_data)) > 0; i++ {
|
||||||
|
filename := unsafe { string_from_wide(&find_file_data.c_file_name[0]) }
|
||||||
|
if filename in ['.', '..'] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
mut fpath := filename.replace('\\', '/')
|
||||||
|
if find_file_data.dw_file_attributes & u32(C.FILE_ATTRIBUTE_DIRECTORY) > 0 {
|
||||||
|
fpath += '/'
|
||||||
|
}
|
||||||
|
matches << fpath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ls(path string) ?[]string {
|
pub fn ls(path string) ?[]string {
|
||||||
mut find_file_data := Win32finddata{}
|
mut find_file_data := Win32finddata{}
|
||||||
mut dir_files := []string{}
|
mut dir_files := []string{}
|
||||||
|
|
Loading…
Reference in New Issue