Skip to content

Commit 72d206e

Browse files
committed
fix(parser): Ensure globals override env vars
This fixes a bug introduced in 4a694f3 when we were trying to move away from presence checks via occurrences. I switched it to the common type of presence check but really what we want is a highest-precedence check. Fixes #3872
1 parent f082eb6 commit 72d206e

File tree

2 files changed

+38
-3
lines changed

2 files changed

+38
-3
lines changed

src/parser/arg_matcher.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,7 @@ impl ArgMatcher {
7474
// a default value of `other` myprog would have an existing MatchedArg for
7575
// `--global-arg` where the value is `other`
7676
let to_update = if let Some(parent_ma) = vals_map.get(global_arg) {
77-
if parent_ma.check_explicit(ArgPredicate::IsPresent)
78-
&& !ma.check_explicit(ArgPredicate::IsPresent)
79-
{
77+
if parent_ma.source() > ma.source() {
8078
parent_ma
8179
} else {
8280
ma

tests/builder/global_args.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,40 @@ fn global_overrides_default() {
163163
.unwrap();
164164
assert_eq!(m.get_one::<String>("name").unwrap().as_str(), "from_arg");
165165
}
166+
167+
#[test]
168+
#[cfg(feature = "env")]
169+
fn global_overrides_env() {
170+
std::env::set_var("GLOBAL_OVERRIDES_ENV", "from_env");
171+
172+
let cmd = Command::new("test")
173+
.arg(
174+
Arg::new("name")
175+
.long("name")
176+
.global(true)
177+
.takes_value(true)
178+
.env("GLOBAL_OVERRIDES_ENV"),
179+
)
180+
.subcommand(Command::new("sub"));
181+
182+
let m = cmd.clone().try_get_matches_from(["test"]).unwrap();
183+
assert_eq!(m.get_one::<String>("name").unwrap().as_str(), "from_env");
184+
185+
let m = cmd
186+
.clone()
187+
.try_get_matches_from(["test", "--name", "from_arg"])
188+
.unwrap();
189+
assert_eq!(m.get_one::<String>("name").unwrap().as_str(), "from_arg");
190+
191+
let m = cmd
192+
.clone()
193+
.try_get_matches_from(["test", "--name", "from_arg", "sub"])
194+
.unwrap();
195+
assert_eq!(m.get_one::<String>("name").unwrap().as_str(), "from_arg");
196+
197+
let m = cmd
198+
.clone()
199+
.try_get_matches_from(["test", "sub", "--name", "from_arg"])
200+
.unwrap();
201+
assert_eq!(m.get_one::<String>("name").unwrap().as_str(), "from_arg");
202+
}

0 commit comments

Comments
 (0)