os: fix is_abs_path function for Windows systems (#14397)
							parent
							
								
									7fe3ef9a6e
								
							
						
					
					
						commit
						cbb24d34c9
					
				| 
						 | 
				
			
			@ -0,0 +1,86 @@
 | 
			
		|||
module os
 | 
			
		||||
 | 
			
		||||
// Collection of useful functions for manipulation, validation and analysis of system paths.
 | 
			
		||||
// The following functions handle paths depending on the operating system,
 | 
			
		||||
// therefore results may be different for certain operating systems.
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	fslash = `/`
 | 
			
		||||
	bslash = `\\`
 | 
			
		||||
	dot    = `.`
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// is_abs_path returns `true` if the given `path` is absolute.
 | 
			
		||||
pub fn is_abs_path(path string) bool {
 | 
			
		||||
	if path.len == 0 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	$if windows {
 | 
			
		||||
		return is_device_path(path) || is_drive_rooted(path) || is_normal_path(path)
 | 
			
		||||
	}
 | 
			
		||||
	return path[0] == os.fslash
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// win_volume_len returns the length of the
 | 
			
		||||
// Windows volume/drive from the given `path`.
 | 
			
		||||
fn win_volume_len(path string) int {
 | 
			
		||||
	plen := path.len
 | 
			
		||||
	if plen < 2 {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	if has_drive_letter(path) {
 | 
			
		||||
		return 2
 | 
			
		||||
	}
 | 
			
		||||
	// its UNC path / DOS device path?
 | 
			
		||||
	if path.len >= 5 && starts_w_slash_slash(path) && !is_slash(path[2]) {
 | 
			
		||||
		for i := 3; i < plen; i++ {
 | 
			
		||||
			if is_slash(path[i]) {
 | 
			
		||||
				if i + 1 >= plen || is_slash(path[i + 1]) {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				i++
 | 
			
		||||
				for ; i < plen; i++ {
 | 
			
		||||
					if is_slash(path[i]) {
 | 
			
		||||
						return i
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				return i
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn is_slash(b u8) bool {
 | 
			
		||||
	$if windows {
 | 
			
		||||
		return b == os.bslash || b == os.fslash
 | 
			
		||||
	}
 | 
			
		||||
	return b == os.fslash
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn is_device_path(path string) bool {
 | 
			
		||||
	return win_volume_len(path) >= 5 && starts_w_slash_slash(path)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn has_drive_letter(path string) bool {
 | 
			
		||||
	return path.len >= 2 && path[0].is_letter() && path[1] == `:`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn starts_w_slash_slash(path string) bool {
 | 
			
		||||
	return path.len >= 2 && is_slash(path[0]) && is_slash(path[1])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn is_drive_rooted(path string) bool {
 | 
			
		||||
	return path.len >= 3 && has_drive_letter(path) && is_slash(path[2])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// is_normal_path returns `true` if the given
 | 
			
		||||
// `path` is NOT a network or Windows device path.
 | 
			
		||||
fn is_normal_path(path string) bool {
 | 
			
		||||
	plen := path.len
 | 
			
		||||
	if plen == 0 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return (plen == 1 && is_slash(path[0])) || (plen >= 2 && is_slash(path[0])
 | 
			
		||||
		&& !is_slash(path[1]))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
module os
 | 
			
		||||
 | 
			
		||||
fn test_is_abs_path() {
 | 
			
		||||
	$if windows {
 | 
			
		||||
		assert is_abs_path('/')
 | 
			
		||||
		assert is_abs_path('\\')
 | 
			
		||||
		assert !is_abs_path('\\\\')
 | 
			
		||||
		assert is_abs_path(r'C:\path\to\files\file.v')
 | 
			
		||||
		assert is_abs_path(r'\\Host\share')
 | 
			
		||||
		assert is_abs_path(r'//Host\share\files\file.v')
 | 
			
		||||
		assert is_abs_path(r'\\.\BootPartition\Windows')
 | 
			
		||||
		assert !is_abs_path(r'\\.\')
 | 
			
		||||
		assert !is_abs_path(r'\\?\\')
 | 
			
		||||
		assert !is_abs_path(r'C:path\to\dir')
 | 
			
		||||
		assert !is_abs_path(r'dir')
 | 
			
		||||
		assert !is_abs_path(r'.\')
 | 
			
		||||
		assert !is_abs_path(r'.')
 | 
			
		||||
		assert !is_abs_path(r'\\Host')
 | 
			
		||||
		assert !is_abs_path(r'\\Host\')
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	assert is_abs_path('/')
 | 
			
		||||
	assert is_abs_path('/path/to/files/file.v')
 | 
			
		||||
	assert !is_abs_path('\\')
 | 
			
		||||
	assert !is_abs_path('path/to/files/file.v')
 | 
			
		||||
	assert !is_abs_path('dir')
 | 
			
		||||
	assert !is_abs_path('./')
 | 
			
		||||
	assert !is_abs_path('.')
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								vlib/os/os.v
								
								
								
								
							
							
						
						
									
										12
									
								
								vlib/os/os.v
								
								
								
								
							| 
						 | 
				
			
			@ -454,18 +454,6 @@ pub fn is_file(path string) bool {
 | 
			
		|||
	return exists(path) && !is_dir(path)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// is_abs_path returns `true` if `path` is absolute.
 | 
			
		||||
pub fn is_abs_path(path string) bool {
 | 
			
		||||
	if path.len == 0 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	$if windows {
 | 
			
		||||
		return path[0] == `/` || // incase we're in MingGW bash
 | 
			
		||||
		(path[0].is_letter() && path.len > 1 && path[1] == `:`)
 | 
			
		||||
	}
 | 
			
		||||
	return path[0] == `/`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// join_path returns a path as string from input string parameter(s).
 | 
			
		||||
[manualfree]
 | 
			
		||||
pub fn join_path(base string, dirs ...string) string {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -590,14 +590,6 @@ fn test_ext() {
 | 
			
		|||
	assert os.file_ext('file') == ''
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_is_abs() {
 | 
			
		||||
	assert os.is_abs_path('/home/user')
 | 
			
		||||
	assert os.is_abs_path('v/vlib') == false
 | 
			
		||||
	$if windows {
 | 
			
		||||
		assert os.is_abs_path('C:\\Windows\\')
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_join() {
 | 
			
		||||
	$if windows {
 | 
			
		||||
		assert os.join_path('v', 'vlib', 'os') == 'v\\vlib\\os'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue