Skip to content

Commit f8b3429

Browse files
authored
Merge pull request #1255 from PowerShell/copilot/replace-file-paths-with-pathbuf
Replace String/&str with PathBuf/&Path for file path handling
2 parents 34be0ae + 0fb51b2 commit f8b3429

File tree

12 files changed

+60
-59
lines changed

12 files changed

+60
-59
lines changed

dsc/src/subcommand.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ fn initialize_config_root(path: Option<&String>) -> Option<String> {
263263
} else {
264264
let current_directory = std::env::current_dir().unwrap_or_default();
265265
debug!("DSC_CONFIG_ROOT = {} '{current_directory:?}'", t!("subcommand.currentDirectory"));
266-
set_dscconfigroot(&current_directory.to_string_lossy());
266+
set_dscconfigroot(current_directory.to_str().unwrap_or_default());
267267
}
268268

269269
// if the path is "-", we need to return it so later processing can handle it correctly

dsc/src/util.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,8 +469,9 @@ pub fn get_input(input: Option<&String>, file: Option<&String>) -> String {
469469
} else {
470470
// see if an extension should handle this file
471471
let mut discovery = Discovery::new();
472+
let path_buf = Path::new(path);
472473
for extension in discovery.get_extensions(&Capability::Import) {
473-
if let Ok(content) = extension.import(path) {
474+
if let Ok(content) = extension.import(path_buf) {
474475
return content;
475476
}
476477
}

lib/dsc-lib/src/discovery/command_discovery.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -751,8 +751,8 @@ fn load_resource_manifest(path: &Path, manifest: &ResourceManifest) -> Result<Ds
751751
description: manifest.description.clone(),
752752
version: manifest.version.clone(),
753753
capabilities,
754-
path: path.to_str().unwrap().to_string(),
755-
directory: path.parent().unwrap().to_str().unwrap().to_string(),
754+
path: path.to_path_buf(),
755+
directory: path.parent().unwrap().to_path_buf(),
756756
manifest: Some(serde_json::to_value(manifest)?),
757757
..Default::default()
758758
};
@@ -793,8 +793,8 @@ fn load_extension_manifest(path: &Path, manifest: &ExtensionManifest) -> Result<
793793
version: manifest.version.clone(),
794794
capabilities,
795795
import_file_extensions: import_extensions,
796-
path: path.to_str().unwrap().to_string(),
797-
directory: path.parent().unwrap().to_str().unwrap().to_string(),
796+
path: path.to_path_buf(),
797+
directory: path.parent().unwrap().to_path_buf(),
798798
manifest: serde_json::to_value(manifest)?,
799799
..Default::default()
800800
};
@@ -803,7 +803,7 @@ fn load_extension_manifest(path: &Path, manifest: &ExtensionManifest) -> Result<
803803
}
804804

805805
fn verify_executable(resource: &str, operation: &str, executable: &str, directory: &Path) {
806-
if canonicalize_which(executable, Some(directory.to_string_lossy().as_ref())).is_err() {
806+
if canonicalize_which(executable, Some(directory)).is_err() {
807807
info!("{}", t!("discovery.commandDiscovery.executableNotFound", resource = resource, operation = operation, executable = executable));
808808
}
809809
}

lib/dsc-lib/src/dscresources/command_resource.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use jsonschema::Validator;
66
use rust_i18n::t;
77
use serde::Deserialize;
88
use serde_json::{Map, Value};
9-
use std::{collections::HashMap, env, process::Stdio};
9+
use std::{collections::HashMap, env, path::Path, process::Stdio};
1010
use crate::{configure::{config_doc::ExecutionKind, config_result::{ResourceGetResult, ResourceTestResult}}, util::canonicalize_which};
1111
use crate::dscerror::DscError;
1212
use super::{dscresource::{get_diff, redact}, invoke_result::{ExportResult, GetResult, ResolveResult, SetResult, TestResult, ValidateResult, ResourceGetResponse, ResourceSetResponse, ResourceTestResponse, get_in_desired_state}, resource_manifest::{ArgKind, InputKind, Kind, ResourceManifest, ReturnKind, SchemaKind}};
@@ -25,7 +25,7 @@ pub const EXIT_PROCESS_TERMINATED: i32 = 0x102;
2525
/// # Errors
2626
///
2727
/// Error returned if the resource does not successfully get the current state
28-
pub fn invoke_get(resource: &ResourceManifest, cwd: &str, filter: &str, target_resource: Option<&str>) -> Result<GetResult, DscError> {
28+
pub fn invoke_get(resource: &ResourceManifest, cwd: &Path, filter: &str, target_resource: Option<&str>) -> Result<GetResult, DscError> {
2929
debug!("{}", t!("dscresources.commandResource.invokeGet", resource = &resource.resource_type));
3030
let mut command_input = CommandInput { env: None, stdin: None };
3131
let Some(get) = &resource.get else {
@@ -78,7 +78,7 @@ pub fn invoke_get(resource: &ResourceManifest, cwd: &str, filter: &str, target_r
7878
///
7979
/// Error returned if the resource does not successfully set the desired state
8080
#[allow(clippy::too_many_lines)]
81-
pub fn invoke_set(resource: &ResourceManifest, cwd: &str, desired: &str, skip_test: bool, execution_type: &ExecutionKind, target_resource: Option<&str>) -> Result<SetResult, DscError> {
81+
pub fn invoke_set(resource: &ResourceManifest, cwd: &Path, desired: &str, skip_test: bool, execution_type: &ExecutionKind, target_resource: Option<&str>) -> Result<SetResult, DscError> {
8282
debug!("{}", t!("dscresources.commandResource.invokeSet", resource = &resource.resource_type));
8383
let operation_type: String;
8484
let mut is_synthetic_what_if = false;
@@ -271,7 +271,7 @@ pub fn invoke_set(resource: &ResourceManifest, cwd: &str, desired: &str, skip_te
271271
/// # Errors
272272
///
273273
/// Error is returned if the underlying command returns a non-zero exit code.
274-
pub fn invoke_test(resource: &ResourceManifest, cwd: &str, expected: &str, target_resource: Option<&str>) -> Result<TestResult, DscError> {
274+
pub fn invoke_test(resource: &ResourceManifest, cwd: &Path, expected: &str, target_resource: Option<&str>) -> Result<TestResult, DscError> {
275275
debug!("{}", t!("dscresources.commandResource.invokeTest", resource = &resource.resource_type));
276276
let Some(test) = &resource.test else {
277277
info!("{}", t!("dscresources.commandResource.testSyntheticTest", resource = &resource.resource_type));
@@ -380,7 +380,7 @@ fn get_desired_state(actual: &Value) -> Result<Option<bool>, DscError> {
380380
Ok(in_desired_state)
381381
}
382382

383-
fn invoke_synthetic_test(resource: &ResourceManifest, cwd: &str, expected: &str, target_resource: Option<&str>) -> Result<TestResult, DscError> {
383+
fn invoke_synthetic_test(resource: &ResourceManifest, cwd: &Path, expected: &str, target_resource: Option<&str>) -> Result<TestResult, DscError> {
384384
let get_result = invoke_get(resource, cwd, expected, target_resource)?;
385385
let actual_state = match get_result {
386386
GetResult::Group(results) => {
@@ -415,7 +415,7 @@ fn invoke_synthetic_test(resource: &ResourceManifest, cwd: &str, expected: &str,
415415
/// # Errors
416416
///
417417
/// Error is returned if the underlying command returns a non-zero exit code.
418-
pub fn invoke_delete(resource: &ResourceManifest, cwd: &str, filter: &str, target_resource: Option<&str>) -> Result<(), DscError> {
418+
pub fn invoke_delete(resource: &ResourceManifest, cwd: &Path, filter: &str, target_resource: Option<&str>) -> Result<(), DscError> {
419419
let Some(delete) = &resource.delete else {
420420
return Err(DscError::NotImplemented("delete".to_string()));
421421
};
@@ -450,7 +450,7 @@ pub fn invoke_delete(resource: &ResourceManifest, cwd: &str, filter: &str, targe
450450
/// # Errors
451451
///
452452
/// Error is returned if the underlying command returns a non-zero exit code.
453-
pub fn invoke_validate(resource: &ResourceManifest, cwd: &str, config: &str, target_resource: Option<&str>) -> Result<ValidateResult, DscError> {
453+
pub fn invoke_validate(resource: &ResourceManifest, cwd: &Path, config: &str, target_resource: Option<&str>) -> Result<ValidateResult, DscError> {
454454
trace!("{}", t!("dscresources.commandResource.invokeValidateConfig", resource = &resource.resource_type, config = &config));
455455
// TODO: use schema to validate config if validate is not implemented
456456
let Some(validate) = resource.validate.as_ref() else {
@@ -479,7 +479,7 @@ pub fn invoke_validate(resource: &ResourceManifest, cwd: &str, config: &str, tar
479479
/// # Errors
480480
///
481481
/// Error if schema is not available or if there is an error getting the schema
482-
pub fn get_schema(resource: &ResourceManifest, cwd: &str) -> Result<String, DscError> {
482+
pub fn get_schema(resource: &ResourceManifest, cwd: &Path) -> Result<String, DscError> {
483483
let Some(schema_kind) = resource.schema.as_ref() else {
484484
return Err(DscError::SchemaNotAvailable(resource.resource_type.clone()));
485485
};
@@ -511,7 +511,7 @@ pub fn get_schema(resource: &ResourceManifest, cwd: &str) -> Result<String, DscE
511511
/// # Errors
512512
///
513513
/// Error returned if the resource does not successfully export the current state
514-
pub fn invoke_export(resource: &ResourceManifest, cwd: &str, input: Option<&str>, target_resource: Option<&str>) -> Result<ExportResult, DscError> {
514+
pub fn invoke_export(resource: &ResourceManifest, cwd: &Path, input: Option<&str>, target_resource: Option<&str>) -> Result<ExportResult, DscError> {
515515
let Some(export) = resource.export.as_ref() else {
516516
// see if get is supported and use that instead
517517
if resource.get.is_some() {
@@ -591,7 +591,7 @@ pub fn invoke_export(resource: &ResourceManifest, cwd: &str, input: Option<&str>
591591
/// # Errors
592592
///
593593
/// Error returned if the resource does not successfully resolve the input
594-
pub fn invoke_resolve(resource: &ResourceManifest, cwd: &str, input: &str) -> Result<ResolveResult, DscError> {
594+
pub fn invoke_resolve(resource: &ResourceManifest, cwd: &Path, input: &str) -> Result<ResolveResult, DscError> {
595595
let Some(resolve) = &resource.resolve else {
596596
return Err(DscError::Operation(t!("dscresources.commandResource.resolveNotSupported", resource = &resource.resource_type).to_string()));
597597
};
@@ -620,7 +620,7 @@ pub fn invoke_resolve(resource: &ResourceManifest, cwd: &str, input: &str) -> Re
620620
///
621621
/// Error is returned if the command fails to execute or stdin/stdout/stderr cannot be opened.
622622
///
623-
async fn run_process_async(executable: &str, args: Option<Vec<String>>, input: Option<&str>, cwd: Option<&str>, env: Option<HashMap<String, String>>, exit_codes: Option<&HashMap<i32, String>>) -> Result<(i32, String, String), DscError> {
623+
async fn run_process_async(executable: &str, args: Option<Vec<String>>, input: Option<&str>, cwd: Option<&Path>, env: Option<HashMap<String, String>>, exit_codes: Option<&HashMap<i32, String>>) -> Result<(i32, String, String), DscError> {
624624

625625
// use somewhat large initial buffer to avoid early string reallocations;
626626
// the value is based on list result of largest of built-in adapters - WMI adapter ~500KB
@@ -761,15 +761,15 @@ fn convert_hashmap_string_keys_to_i32(input: Option<&HashMap<String, String>>) -
761761
/// Will panic if tokio runtime can't be created.
762762
///
763763
#[allow(clippy::implicit_hasher)]
764-
pub fn invoke_command(executable: &str, args: Option<Vec<String>>, input: Option<&str>, cwd: Option<&str>, env: Option<HashMap<String, String>>, exit_codes: Option<&HashMap<String, String>>) -> Result<(i32, String, String), DscError> {
764+
pub fn invoke_command(executable: &str, args: Option<Vec<String>>, input: Option<&str>, cwd: Option<&Path>, env: Option<HashMap<String, String>>, exit_codes: Option<&HashMap<String, String>>) -> Result<(i32, String, String), DscError> {
765765
let exit_codes = convert_hashmap_string_keys_to_i32(exit_codes)?;
766766
let executable = canonicalize_which(executable, cwd)?;
767767

768768
tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap().block_on(
769769
async {
770770
trace!("{}", t!("dscresources.commandResource.commandInvoke", executable = executable, args = args : {:?}));
771771
if let Some(cwd) = cwd {
772-
trace!("{}", t!("dscresources.commandResource.commandCwd", cwd = cwd));
772+
trace!("{}", t!("dscresources.commandResource.commandCwd", cwd = cwd.display()));
773773
}
774774

775775
match run_process_async(&executable, args, input, cwd, env, exit_codes.as_ref()).await {
@@ -854,7 +854,7 @@ fn get_command_input(input_kind: Option<&InputKind>, input: &str) -> Result<Comm
854854
})
855855
}
856856

857-
fn verify_json(resource: &ResourceManifest, cwd: &str, json: &str) -> Result<(), DscError> {
857+
fn verify_json(resource: &ResourceManifest, cwd: &Path, json: &str) -> Result<(), DscError> {
858858

859859
debug!("{}", t!("dscresources.commandResource.verifyJson", resource = resource.resource_type));
860860

lib/dsc-lib/src/dscresources/dscresource.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use schemars::JsonSchema;
1111
use serde::{Deserialize, Serialize};
1212
use serde_json::{Map, Value};
1313
use std::collections::HashMap;
14+
use std::path::PathBuf;
1415
use tracing::{debug, info, trace};
1516

1617
use super::{
@@ -37,11 +38,11 @@ pub struct DscResource {
3738
/// The capabilities of the resource.
3839
pub capabilities: Vec<Capability>,
3940
/// The file path to the resource.
40-
pub path: String,
41+
pub path: PathBuf,
4142
/// The description of the resource.
4243
pub description: Option<String>,
4344
// The directory path to the resource.
44-
pub directory: String,
45+
pub directory: PathBuf,
4546
/// The implementation of the resource.
4647
#[serde(rename="implementedAs")]
4748
pub implemented_as: ImplementedAs,
@@ -98,8 +99,8 @@ impl DscResource {
9899
version: String::new(),
99100
capabilities: Vec::new(),
100101
description: None,
101-
path: String::new(),
102-
directory: String::new(),
102+
path: PathBuf::new(),
103+
directory: PathBuf::new(),
103104
implemented_as: ImplementedAs::Command,
104105
author: None,
105106
properties: Vec::new(),

lib/dsc-lib/src/dscresources/include.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33

44
use schemars::JsonSchema;
55
use serde::{Deserialize, Serialize};
6+
use std::path::PathBuf;
67

78
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
89
pub struct Include {
910
/// The path to the file to include. Relative paths are relative to the file containing the include
1011
/// and not allowed to reference parent directories.
1112
#[serde(rename = "configurationFile")]
12-
pub configuration_file: String,
13+
pub configuration_file: PathBuf,
1314
}

lib/dsc-lib/src/extensions/discover.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::{
2424
use rust_i18n::t;
2525
use schemars::JsonSchema;
2626
use serde::{Deserialize, Serialize};
27-
use std::path::Path;
27+
use std::path::PathBuf;
2828
use tracing::{info, trace};
2929

3030
#[derive(Debug, Default, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
@@ -39,7 +39,7 @@ pub struct DiscoverMethod {
3939
pub struct DiscoverResult {
4040
/// The path to the resource manifest, must be absolute.
4141
#[serde(rename = "manifestPath")]
42-
pub manifest_path: String,
42+
pub manifest_path: PathBuf,
4343
}
4444

4545
impl DscExtension {
@@ -70,7 +70,7 @@ impl DscExtension {
7070
&discover.executable,
7171
args,
7272
None,
73-
Some(self.directory.as_str()),
73+
Some(&self.directory),
7474
None,
7575
extension.exit_codes.as_ref(),
7676
)?;
@@ -85,12 +85,11 @@ impl DscExtension {
8585
return Err(DscError::Json(err));
8686
}
8787
};
88-
if !Path::new(&discover_result.manifest_path).is_absolute() {
89-
return Err(DscError::Extension(t!("extensions.dscextension.discoverNotAbsolutePath", extension = self.type_name.clone(), path = discover_result.manifest_path.clone()).to_string()));
88+
if !discover_result.manifest_path.is_absolute() {
89+
return Err(DscError::Extension(t!("extensions.dscextension.discoverNotAbsolutePath", extension = self.type_name.clone(), path = discover_result.manifest_path.display()).to_string()));
9090
}
91-
let manifest_path = Path::new(&discover_result.manifest_path);
9291
// Currently we don't support extensions discovering other extensions
93-
for imported_manifest in load_manifest(manifest_path)? {
92+
for imported_manifest in load_manifest(&discover_result.manifest_path)? {
9493
if let ImportedManifest::Resource(resource) = imported_manifest {
9594
resources.push(resource);
9695
}

lib/dsc-lib/src/extensions/dscextension.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize};
66
use serde_json::Value;
77
use schemars::JsonSchema;
88
use std::fmt::Display;
9+
use std::path::PathBuf;
910

1011
#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
1112
#[serde(deny_unknown_fields)]
@@ -21,11 +22,11 @@ pub struct DscExtension {
2122
#[serde(rename = "importFileExtensions")]
2223
pub import_file_extensions: Option<Vec<String>>,
2324
/// The file path to the resource.
24-
pub path: String,
25+
pub path: PathBuf,
2526
/// The description of the resource.
2627
pub description: Option<String>,
2728
// The directory path to the resource.
28-
pub directory: String,
29+
pub directory: PathBuf,
2930
/// The author of the resource.
3031
pub author: Option<String>,
3132
/// The manifest of the resource.
@@ -63,8 +64,8 @@ impl DscExtension {
6364
capabilities: Vec::new(),
6465
import_file_extensions: None,
6566
description: None,
66-
path: String::new(),
67-
directory: String::new(),
67+
path: PathBuf::new(),
68+
directory: PathBuf::new(),
6869
author: None,
6970
manifest: Value::Null,
7071
}

lib/dsc-lib/src/extensions/import.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,15 @@ impl DscExtension {
6161
/// # Errors
6262
///
6363
/// This function will return an error if the import fails or if the extension does not support the import capability.
64-
pub fn import(&self, file: &str) -> Result<String, DscError> {
64+
pub fn import(&self, file: &Path) -> Result<String, DscError> {
6565
if self.capabilities.contains(&Capability::Import) {
66-
let file_path = Path::new(file);
67-
let file_extension = file_path.extension().and_then(|s| s.to_str()).unwrap_or_default().to_string();
66+
let file_extension = file.extension().and_then(|s| s.to_str()).unwrap_or_default().to_string();
6867
if self.import_file_extensions.as_ref().is_some_and(|exts| exts.contains(&file_extension)) {
69-
debug!("{}", t!("extensions.dscextension.importingFile", file = file, extension = self.type_name));
68+
debug!("{}", t!("extensions.dscextension.importingFile", file = file.display(), extension = self.type_name));
7069
} else {
71-
debug!("{}", t!("extensions.dscextension.importNotSupported", file = file, extension = self.type_name));
70+
debug!("{}", t!("extensions.dscextension.importNotSupported", file = file.display(), extension = self.type_name));
7271
return Err(DscError::NotSupported(
73-
t!("extensions.dscextension.importNotSupported", file = file, extension = self.type_name).to_string(),
72+
t!("extensions.dscextension.importNotSupported", file = file.display(), extension = self.type_name).to_string(),
7473
));
7574
}
7675

@@ -88,7 +87,7 @@ impl DscExtension {
8887
&import.executable,
8988
args,
9089
None,
91-
Some(self.directory.as_str()),
90+
Some(&self.directory),
9291
None,
9392
extension.exit_codes.as_ref(),
9493
)?;
@@ -105,16 +104,15 @@ impl DscExtension {
105104
}
106105
}
107106

108-
fn process_import_args(args: Option<&Vec<ImportArgKind>>, file: &str) -> Result<Option<Vec<String>>, DscError> {
107+
fn process_import_args(args: Option<&Vec<ImportArgKind>>, file: &Path) -> Result<Option<Vec<String>>, DscError> {
109108
let Some(arg_values) = args else {
110109
debug!("{}", t!("dscresources.commandResource.noArgs"));
111110
return Ok(None);
112111
};
113112

114113
// make path absolute
115-
let path = Path::new(file);
116-
let Ok(full_path) = path.absolutize() else {
117-
return Err(DscError::Extension(t!("util.failedToAbsolutizePath", path = path : {:?}).to_string()));
114+
let Ok(full_path) = file.absolutize() else {
115+
return Err(DscError::Extension(t!("util.failedToAbsolutizePath", path = file.display()).to_string()));
118116
};
119117

120118
let mut processed_args = Vec::<String>::new();

lib/dsc-lib/src/extensions/secret.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ impl DscExtension {
7878
&secret.executable,
7979
args,
8080
vault,
81-
Some(self.directory.as_str()),
81+
Some(&self.directory),
8282
None,
8383
extension.exit_codes.as_ref(),
8484
)?;

0 commit comments

Comments
 (0)