Skip to content

Commit 90b3c7e

Browse files
committed
feat(cli): add --config option
1 parent 798fdbb commit 90b3c7e

3 files changed

Lines changed: 53 additions & 4 deletions

File tree

src/cli.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ pub enum UpdateTarget {
3737
pub struct Cli {
3838
/// Whether to check formatting instead of fixing it
3939
pub check: bool,
40+
/// Path to a specific config file to use
41+
pub config_path: Option<String>,
4042
/// The path to the root of the project
4143
pub cwd: PathBuf,
4244
/// Whether to disable ANSI color codes in terminal output
@@ -81,6 +83,7 @@ impl Cli {
8183
fn from_arg_matches(subcommand: Subcommand, matches: &ArgMatches) -> Cli {
8284
Cli {
8385
check: (matches!(&subcommand, Subcommand::Format | Subcommand::Update)) && matches.get_flag("check"),
86+
config_path: matches.get_one::<String>("config").cloned(),
8487
cwd: env::current_dir().unwrap(),
8588
dependencies: get_patterns(matches, "dependencies"),
8689
dependency_types: get_patterns(matches, "dependency-types"),
@@ -144,6 +147,7 @@ fn create() -> Command {
144147
Command::new("lint")
145148
.about("Lint all versions and ranges and exit with 0 or 1 based on whether all files match your Syncpack configuration file")
146149
.after_long_help(additional_help())
150+
.arg(config_option("lint"))
147151
.arg(dependencies_option("lint"))
148152
.arg(dependency_types_option("lint"))
149153
.arg(log_levels_option("lint"))
@@ -157,6 +161,7 @@ fn create() -> Command {
157161
Command::new("fix")
158162
.about("Ensure that multiple packages requiring the same dependency use the same version")
159163
.after_long_help(additional_help())
164+
.arg(config_option("fix"))
160165
.arg(dependencies_option("fix"))
161166
.arg(dependency_types_option("fix"))
162167
.arg(dry_run_option("fix"))
@@ -177,6 +182,7 @@ fn create() -> Command {
177182
.long_help(cformat!(r#"Lint formatting instead of fixing it"#))
178183
.action(clap::ArgAction::SetTrue),
179184
)
185+
.arg(config_option("format"))
180186
.arg(dry_run_option("format"))
181187
.arg(log_levels_option("format"))
182188
.arg(no_ansi_option("format"))
@@ -192,6 +198,7 @@ fn create() -> Command {
192198
.long_help(cformat!(r#"Check versions are up to date instead of updating them"#))
193199
.action(clap::ArgAction::SetTrue),
194200
)
201+
.arg(config_option("update"))
195202
.arg(dependencies_option("update"))
196203
.arg(dependency_types_option("update"))
197204
.arg(dry_run_option("update"))
@@ -205,6 +212,7 @@ fn create() -> Command {
205212
Command::new("list")
206213
.about("Query and inspect all dependencies in your project, both valid and invalid")
207214
.after_long_help(additional_help())
215+
.arg(config_option("list"))
208216
.arg(dependencies_option("list"))
209217
.arg(dependency_types_option("list"))
210218
.arg(log_levels_option("list"))
@@ -218,6 +226,7 @@ fn create() -> Command {
218226
Command::new("json")
219227
.about("Output all dependencies as flattened JSON objects")
220228
.after_long_help(additional_help())
229+
.arg(config_option("json"))
221230
.arg(dependencies_option("json"))
222231
.arg(dependency_types_option("json"))
223232
.arg(log_levels_option("json"))
@@ -228,6 +237,12 @@ fn create() -> Command {
228237
)
229238
}
230239

240+
fn config_option(_command: &str) -> Arg {
241+
Arg::new("config").long("config").value_name("PATH").long_help(cformat!(
242+
r#"Path to a specific config file to use. When set, config file discovery is skipped."#
243+
))
244+
}
245+
231246
fn dependencies_option(command: &str) -> Arg {
232247
let short_help = "Only include dependencies whose name matches this glob pattern";
233248
Arg::new("dependencies")

src/rcfile/discovery.rs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,23 @@ use {
22
crate::{
33
cli::Cli,
44
rcfile::{
5-
javascript::try_from_js_candidates, json::try_from_json_candidates, package_json::try_from_package_json_config_property,
6-
yaml::try_from_yaml_candidates, Rcfile,
5+
error::RcfileError,
6+
javascript::{from_javascript_path, try_from_js_candidates},
7+
json::{from_json_path, try_from_json_candidates},
8+
package_json::try_from_package_json_config_property,
9+
yaml::{from_yaml_path, try_from_yaml_candidates},
10+
Rcfile,
711
},
812
},
913
log::{debug, error},
10-
std::{process::exit, time::Instant},
14+
std::{path::PathBuf, process::exit, time::Instant},
1115
};
1216

1317
impl Rcfile {
1418
pub fn from_disk(cli: &Cli) -> Rcfile {
1519
let start = Instant::now();
16-
let rcfile = try_from_json_candidates(cli)
20+
let rcfile = Self::try_from_cli_option(cli)
21+
.or_else(|| try_from_json_candidates(cli))
1722
.or_else(|| try_from_yaml_candidates(cli))
1823
.or_else(|| try_from_package_json_config_property(cli))
1924
.or_else(|| try_from_js_candidates(cli))
@@ -31,4 +36,32 @@ impl Rcfile {
3136
debug!("Config discovery completed in {:?}", start.elapsed());
3237
rcfile
3338
}
39+
40+
fn try_from_cli_option(cli: &Cli) -> Option<Result<Rcfile, RcfileError>> {
41+
cli.config_path.as_ref().map(|path| {
42+
let config_path = PathBuf::from(path);
43+
let absolute_path = if config_path.is_absolute() {
44+
config_path
45+
} else {
46+
cli.cwd.join(config_path)
47+
};
48+
49+
debug!("Using config file from CLI option: {absolute_path:?}");
50+
51+
if !absolute_path.exists() {
52+
return Err(RcfileError::FileReadFailed(std::io::Error::new(
53+
std::io::ErrorKind::NotFound,
54+
format!("Config file not found: {}", absolute_path.display()),
55+
)));
56+
}
57+
58+
let extension = absolute_path.extension().and_then(|ext| ext.to_str());
59+
match extension {
60+
Some("json") => from_json_path(&absolute_path),
61+
Some("yaml") | Some("yml") => from_yaml_path(&absolute_path),
62+
Some("js") | Some("cjs") | Some("mjs") | Some("ts") | Some("cts") | Some("mts") => from_javascript_path(&absolute_path),
63+
_ => from_json_path(&absolute_path),
64+
}
65+
})
66+
}
3467
}

src/test/mock.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use {
1717
pub fn cli() -> Cli {
1818
Cli {
1919
check: true,
20+
config_path: None,
2021
cwd: env::current_dir().unwrap(),
2122
dependencies: vec![],
2223
dependency_types: vec![],

0 commit comments

Comments
 (0)