Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure systemRoot() always has trailing separator character #616

Merged
merged 9 commits into from
Dec 18, 2024
Merged
7 changes: 6 additions & 1 deletion dsc/src/subcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,12 @@ pub fn config(subcommand: &ConfigSubCommand, parameters: &Option<String>, mounte
exit(EXIT_INVALID_ARGS);
}

configurator.set_system_root(path);
// make sure path has a trailing separator if it's a drive letter
if path.len() == 2 && path.chars().nth(1).unwrap_or(' ') == ':' {
configurator.set_system_root(&format!("{path}\\"));
} else {
configurator.set_system_root(path);
}
}

if let Err(err) = configurator.set_context(parameters.as_ref()) {
Expand Down
2 changes: 1 addition & 1 deletion dsc/tests/dsc_functions.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Describe 'tests for function expressions' {
'@

$expected = if ($IsWindows) {
$env:SYSTEMDRIVE
$env:SYSTEMDRIVE + '\'
} else {
'/'
}
Expand Down
4 changes: 2 additions & 2 deletions dsc_lib/src/configure/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ impl Default for Context {

#[cfg(target_os = "windows")]
fn get_default_os_system_root() -> PathBuf {
// use SYSTEMDRIVE env var to get the default target path
// use SYSTEMDRIVE env var to get the default target path, append trailing separator
let system_drive = std::env::var("SYSTEMDRIVE").unwrap_or_else(|_| "C:".to_string());
PathBuf::from(system_drive)
PathBuf::from(system_drive + "\\")
}

#[cfg(not(target_os = "windows"))]
Expand Down
69 changes: 65 additions & 4 deletions dsc_lib/src/functions/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,80 @@ mod tests {
use crate::configure::context::Context;
use crate::parser::Statement;

const SEPARATOR: char = std::path::MAIN_SEPARATOR;

#[test]
fn start_with_drive_letter() {
let mut parser = Statement::new().unwrap();
let result = parser.parse_and_execute("[path('C:\\','test')]", &Context::new()).unwrap();

#[cfg(target_os = "windows")]
assert_eq!(result, format!("C:{SEPARATOR}test"));

#[cfg(not(target_os = "windows"))]
assert_eq!(result, format!("C:\\{SEPARATOR}test"));
}

#[test]
fn drive_letter_in_middle() {
let mut parser = Statement::new().unwrap();
let result = parser.parse_and_execute("[path('a','C:\\','test')]", &Context::new()).unwrap();

// if any part of the path is absolute, it replaces it instead of appending on Windows
#[cfg(target_os = "windows")]
assert_eq!(result, format!("C:{SEPARATOR}test"));

// non-Windows, the colon is a valid character in a path
#[cfg(not(target_os = "windows"))]
assert_eq!(result, format!("a{SEPARATOR}C:\\{SEPARATOR}test"));
}

#[test]
fn multiple_drive_letters() {
let mut parser = Statement::new().unwrap();
let result = parser.parse_and_execute("[path('C:\\','D:\\','test')]", &Context::new()).unwrap();

// if any part of the path is absolute, it replaces it instead of appending on Windows
#[cfg(target_os = "windows")]
assert_eq!(result, format!("D:\\test"));

// non-Windows, the colon is a valid character in a path
#[cfg(not(target_os = "windows"))]
assert_eq!(result, format!("C:\\{SEPARATOR}D:\\{SEPARATOR}test"));
}

#[test]
fn relative_path() {
let mut parser = Statement::new().unwrap();
let result = parser.parse_and_execute("[path('a','..','b')]", &Context::new()).unwrap();
assert_eq!(result, format!("a{SEPARATOR}..{SEPARATOR}b"));
}

#[test]
fn path_segement_with_separator() {
let mut parser = Statement::new().unwrap();
let result = parser.parse_and_execute(format!("[path('a','b{SEPARATOR}c')]").as_str(), &Context::new()).unwrap();
assert_eq!(result, format!("a{SEPARATOR}b{SEPARATOR}c"));
}

#[test]
fn unix_absolute_path() {
let mut parser = Statement::new().unwrap();
let result = parser.parse_and_execute("[path('/','a','b')]", &Context::new()).unwrap();
assert_eq!(result, format!("/a{SEPARATOR}b"));
}

#[test]
fn two_args() {
let mut parser = Statement::new().unwrap();
let separator = std::path::MAIN_SEPARATOR;
let result = parser.parse_and_execute("[path('a','b')]", &Context::new()).unwrap();
assert_eq!(result, format!("a{separator}b"));
assert_eq!(result, format!("a{SEPARATOR}b"));
}

#[test]
fn three_args() {
let mut parser = Statement::new().unwrap();
let separator = std::path::MAIN_SEPARATOR;
let result = parser.parse_and_execute("[path('a','b','c')]", &Context::new()).unwrap();
assert_eq!(result, format!("a{separator}b{separator}c"));
assert_eq!(result, format!("a{SEPARATOR}b{SEPARATOR}c"));
}
}
2 changes: 1 addition & 1 deletion dsc_lib/src/functions/system_root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ mod tests {
let result = parser.parse_and_execute("[systemRoot()]", &Context::new()).unwrap();
// on windows, the default is SYSTEMDRIVE env var
#[cfg(target_os = "windows")]
assert_eq!(result, std::env::var("SYSTEMDRIVE").unwrap());
assert_eq!(result, format!("{}\\", std::env::var("SYSTEMDRIVE").unwrap()));
// on linux/macOS, the default is /
#[cfg(not(target_os = "windows"))]
assert_eq!(result, "/");
Expand Down
Loading