Skip to content

Commit 3519d3b

Browse files
committed
add progress bar
1 parent de958e9 commit 3519d3b

File tree

6 files changed

+42
-38
lines changed

6 files changed

+42
-38
lines changed

dsc/src/subcommand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use crate::args::{ConfigSubCommand, DscType, OutputFormat, ResourceSubCommand};
55
use crate::resource_command::{get_resource, self};
66
use crate::tablewriter::Table;
77
use crate::util::{EXIT_DSC_ERROR, EXIT_INVALID_INPUT, EXIT_JSON_ERROR, EXIT_SUCCESS, EXIT_VALIDATION_FAILED, get_schema, write_output, get_input, set_dscconfigroot};
8-
use tracing::error;
98

109
use atty::Stream;
1110
use dsc_lib::{
@@ -17,6 +16,7 @@ use dsc_lib::{
1716
use jsonschema::JSONSchema;
1817
use serde_yaml::Value;
1918
use std::process::exit;
19+
use tracing::error;
2020

2121
pub fn config_get(configurator: &mut Configurator, format: &Option<OutputFormat>)
2222
{

dsc_lib/Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ edition = "2021"
55

66
[dependencies]
77
base64 = "0.21"
8-
derive_builder ="0.12"
8+
derive_builder ="0.20"
9+
indicatif = { version = "0.17" }
910
jsonschema = "0.17"
1011
regex = "1.7"
1112
reqwest = { version = "0.11", features = ["blocking"] }
@@ -16,7 +17,7 @@ serde_yaml = { version = "0.9.3" }
1617
thiserror = "1.0"
1718
chrono = "0.4.26"
1819
tracing = "0.1.37"
19-
tree-sitter = "~0.20.10"
20+
tree-sitter = "0.21"
2021
tree-sitter-dscexpression = { path = "../tree-sitter-dscexpression" }
2122

2223
[dev-dependencies]

dsc_lib/src/configure/mod.rs

+32-33
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ use self::config_doc::{Configuration, DataType};
1212
use self::depends_on::get_resource_invocation_order;
1313
use self::config_result::{ConfigurationGetResult, ConfigurationSetResult, ConfigurationTestResult, ConfigurationExportResult};
1414
use self::contraints::{check_length, check_number_limits, check_allowed_values};
15+
use indicatif::{ProgressBar, ProgressStyle};
1516
use serde_json::{Map, Value};
16-
use std::collections::{HashMap, HashSet};
17+
use std::collections::HashMap;
1718
use tracing::debug;
1819

1920
pub mod context;
@@ -130,6 +131,14 @@ fn escape_property_values(properties: &Map<String, Value>) -> Result<Option<Map<
130131
Ok(Some(result))
131132
}
132133

134+
fn get_progress_bar(len: u64) -> Result<ProgressBar, DscError> {
135+
let pb = ProgressBar::new(len);
136+
pb.set_style(ProgressStyle::with_template(
137+
"{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos:>7}/{len:7} {msg}"
138+
)?);
139+
Ok(pb)
140+
}
141+
133142
impl Configurator {
134143
/// Create a new `Configurator` instance.
135144
///
@@ -163,7 +172,11 @@ impl Configurator {
163172
pub fn invoke_get(&mut self, _error_action: ErrorAction, _progress_callback: impl Fn() + 'static) -> Result<ConfigurationGetResult, DscError> {
164173
let config = self.validate_config()?;
165174
let mut result = ConfigurationGetResult::new();
166-
for resource in get_resource_invocation_order(&config, &mut self.statement_parser, &self.context)? {
175+
let resources = get_resource_invocation_order(&config, &mut self.statement_parser, &self.context)?;
176+
let pb = get_progress_bar(resources.len() as u64)?;
177+
for resource in resources {
178+
pb.inc(1);
179+
pb.set_message(format!("Get {}", resource.name));
167180
let properties = self.invoke_property_expressions(&resource.properties)?;
168181
let Some(dsc_resource) = self.discovery.find_resource(&resource.resource_type.to_lowercase()) else {
169182
return Err(DscError::ResourceNotFound(resource.resource_type));
@@ -179,6 +192,7 @@ impl Configurator {
179192
result.results.push(resource_result);
180193
}
181194

195+
pb.finish_and_clear();
182196
Ok(result)
183197
}
184198

@@ -195,7 +209,11 @@ impl Configurator {
195209
pub fn invoke_set(&mut self, skip_test: bool, _error_action: ErrorAction, _progress_callback: impl Fn() + 'static) -> Result<ConfigurationSetResult, DscError> {
196210
let config = self.validate_config()?;
197211
let mut result = ConfigurationSetResult::new();
198-
for resource in get_resource_invocation_order(&config, &mut self.statement_parser, &self.context)? {
212+
let resources = get_resource_invocation_order(&config, &mut self.statement_parser, &self.context)?;
213+
let pb = get_progress_bar(resources.len() as u64)?;
214+
for resource in resources {
215+
pb.inc(1);
216+
pb.set_message(format!("Set {}", resource.name));
199217
let properties = self.invoke_property_expressions(&resource.properties)?;
200218
let Some(dsc_resource) = self.discovery.find_resource(&resource.resource_type.to_lowercase()) else {
201219
return Err(DscError::ResourceNotFound(resource.resource_type));
@@ -211,6 +229,7 @@ impl Configurator {
211229
result.results.push(resource_result);
212230
}
213231

232+
pb.finish_and_clear();
214233
Ok(result)
215234
}
216235

@@ -227,7 +246,11 @@ impl Configurator {
227246
pub fn invoke_test(&mut self, _error_action: ErrorAction, _progress_callback: impl Fn() + 'static) -> Result<ConfigurationTestResult, DscError> {
228247
let config = self.validate_config()?;
229248
let mut result = ConfigurationTestResult::new();
230-
for resource in get_resource_invocation_order(&config, &mut self.statement_parser, &self.context)? {
249+
let resources = get_resource_invocation_order(&config, &mut self.statement_parser, &self.context)?;
250+
let pb = get_progress_bar(resources.len() as u64)?;
251+
for resource in resources {
252+
pb.inc(1);
253+
pb.set_message(format!("Test {}", resource.name));
231254
let properties = self.invoke_property_expressions(&resource.properties)?;
232255
let Some(dsc_resource) = self.discovery.find_resource(&resource.resource_type.to_lowercase()) else {
233256
return Err(DscError::ResourceNotFound(resource.resource_type));
@@ -243,6 +266,7 @@ impl Configurator {
243266
result.results.push(resource_result);
244267
}
245268

269+
pb.finish_and_clear();
246270
Ok(result)
247271
}
248272

@@ -263,17 +287,13 @@ impl Configurator {
263287
pub fn invoke_export(&mut self, _error_action: ErrorAction, _progress_callback: impl Fn() + 'static) -> Result<ConfigurationExportResult, DscError> {
264288
let config = self.validate_config()?;
265289

266-
let duplicates = Self::find_duplicate_resource_types(&config);
267-
if !duplicates.is_empty()
268-
{
269-
let duplicates_string = &duplicates.join(",");
270-
return Err(DscError::Validation(format!("Resource(s) {duplicates_string} specified multiple times")));
271-
}
272-
273290
let mut result = ConfigurationExportResult::new();
274291
let mut conf = config_doc::Configuration::new();
275292

293+
let pb = get_progress_bar(config.resources.len() as u64)?;
276294
for resource in &config.resources {
295+
pb.inc(1);
296+
pb.set_message(format!("Export {}", resource.name));
277297
let Some(dsc_resource) = self.discovery.find_resource(&resource.resource_type.to_lowercase()) else {
278298
return Err(DscError::ResourceNotFound(resource.resource_type.clone()));
279299
};
@@ -283,7 +303,7 @@ impl Configurator {
283303
}
284304

285305
result.result = Some(conf);
286-
306+
pb.finish_and_clear();
287307
Ok(result)
288308
}
289309

@@ -367,27 +387,6 @@ impl Configurator {
367387
Ok(())
368388
}
369389

370-
fn find_duplicate_resource_types(config: &Configuration) -> Vec<String>
371-
{
372-
let mut map: HashMap<&String, i32> = HashMap::new();
373-
let mut result: HashSet<String> = HashSet::new();
374-
let resource_list = &config.resources;
375-
if resource_list.is_empty() {
376-
return Vec::new();
377-
}
378-
379-
for r in resource_list
380-
{
381-
let v = map.entry(&r.resource_type).or_insert(0);
382-
*v += 1;
383-
if *v > 1 {
384-
result.insert(r.resource_type.clone());
385-
}
386-
}
387-
388-
result.into_iter().collect()
389-
}
390-
391390
fn validate_config(&mut self) -> Result<Configuration, DscError> {
392391
let config: Configuration = serde_json::from_str(self.config.as_str())?;
393392

dsc_lib/src/dscerror.rs

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use std::str::Utf8Error;
55

6+
use indicatif::style::TemplateError;
67
use reqwest::StatusCode;
78
use thiserror::Error;
89
use tracing::error;
@@ -76,6 +77,9 @@ pub enum DscError {
7677
#[error("Parser: {0}")]
7778
Parser(String),
7879

80+
#[error("Progress: {0}")]
81+
Progress(#[from] TemplateError),
82+
7983
#[error("Resource not found: {0}")]
8084
ResourceNotFound(String),
8185

dsc_lib/src/parser/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ impl Statement {
2424
/// This function will return an error if the underlying parser fails to initialize.
2525
pub fn new() -> Result<Self, DscError> {
2626
let mut parser = Parser::new();
27-
parser.set_language(tree_sitter_dscexpression::language())?;
27+
parser.set_language(&tree_sitter_dscexpression::language())?;
2828
let function_dispatcher = FunctionDispatcher::new();
2929
Ok(Self {
3030
parser,

tree-sitter-dscexpression/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ include = [
2020
path = "bindings/rust/lib.rs"
2121

2222
[dependencies]
23-
tree-sitter = "~0.20.10"
23+
tree-sitter = "0.21"
2424

2525
[build-dependencies]
2626
cc = "1.0"

0 commit comments

Comments
 (0)