Skip to content

Commit 2f0ba2b

Browse files
karthiknadigCopilot
andcommitted
fix: preserve explicit Conda executable provenance (PR #555)
Keep omitted configuration distinct from an explicitly configured conda command. Verify actual warning emission for both explicit names and the implicit default. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 94fdc3b commit 2f0ba2b

1 file changed

Lines changed: 45 additions & 15 deletions

File tree

‎crates/pet-conda/src/conda_info.rs‎

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ impl CondaInfo {
5252
executable: Option<PathBuf>,
5353
run: impl FnOnce(&mut Command, Duration) -> Result<Output, ProcessError>,
5454
) -> Option<Self> {
55+
let using_default = executable.is_none();
5556
// Possible we got a symlink to the conda exe, first try to resolve that.
5657
let executable = if cfg!(windows) {
5758
executable.clone().unwrap_or("conda".into())
@@ -107,7 +108,7 @@ impl CondaInfo {
107108
}
108109
}
109110
Err(err) => {
110-
if !is_missing_default_conda(&executable, &err) {
111+
if !is_missing_default_conda(using_default, &err) {
111112
warn!(
112113
"Failed to execute conda info using {:?}: {}",
113114
executable, err
@@ -119,8 +120,8 @@ impl CondaInfo {
119120
}
120121
}
121122

122-
fn is_missing_default_conda(executable: &std::path::Path, error: &ProcessError) -> bool {
123-
executable == std::path::Path::new("conda")
123+
fn is_missing_default_conda(using_default: bool, error: &ProcessError) -> bool {
124+
using_default
124125
&& matches!(error, ProcessError::Spawn(source) if source.kind() == io::ErrorKind::NotFound)
125126
}
126127

@@ -203,24 +204,15 @@ mod tests {
203204
#[test]
204205
fn only_missing_default_conda_is_quiet() {
205206
let missing = ProcessError::Spawn(io::Error::from(io::ErrorKind::NotFound));
206-
assert!(is_missing_default_conda(
207-
std::path::Path::new("conda"),
208-
&missing
209-
));
210-
assert!(!is_missing_default_conda(
211-
std::path::Path::new("custom-conda"),
212-
&missing
213-
));
207+
assert!(is_missing_default_conda(true, &missing));
208+
assert!(!is_missing_default_conda(false, &missing));
214209
for error in [
215210
ProcessError::Spawn(io::Error::from(io::ErrorKind::PermissionDenied)),
216211
ProcessError::Io(io::Error::from(io::ErrorKind::NotFound)),
217212
ProcessError::Timeout(Duration::from_secs(15)),
218213
ProcessError::OutputLimit(1),
219214
] {
220-
assert!(!is_missing_default_conda(
221-
std::path::Path::new("conda"),
222-
&error
223-
));
215+
assert!(!is_missing_default_conda(true, &error));
224216
}
225217
}
226218

@@ -270,4 +262,42 @@ mod tests {
270262
.is_none());
271263
assert!(started.elapsed() < Duration::from_secs(3));
272264
}
265+
266+
#[test]
267+
fn configured_conda_name_logs_not_found_while_implicit_default_is_quiet() {
268+
thread_local! {
269+
static WARNINGS: std::cell::Cell<usize> = const { std::cell::Cell::new(0) };
270+
}
271+
struct ProbeLogger;
272+
impl log::Log for ProbeLogger {
273+
fn enabled(&self, metadata: &log::Metadata<'_>) -> bool {
274+
metadata.level() == log::Level::Warn
275+
}
276+
fn log(&self, record: &log::Record<'_>) {
277+
if record.level() == log::Level::Warn && record.target() == "pet_conda::conda_info"
278+
{
279+
WARNINGS.with(|count| count.set(count.get() + 1));
280+
}
281+
}
282+
fn flush(&self) {}
283+
}
284+
log::set_logger(&ProbeLogger).expect("Conda unit tests must have one logger");
285+
log::set_max_level(log::LevelFilter::Warn);
286+
assert!(log::log_enabled!(target: "pet_conda::conda_info", log::Level::Warn));
287+
for (executable, warnings) in [
288+
(None, 0),
289+
(Some("conda".into()), 1),
290+
(Some("custom-conda".into()), 1),
291+
] {
292+
WARNINGS.with(|count| count.set(0));
293+
assert!(CondaInfo::from_with_runner(executable, |_, _| {
294+
Err(ProcessError::Spawn(io::Error::from(
295+
io::ErrorKind::NotFound,
296+
)))
297+
})
298+
.is_none());
299+
log::logger().flush();
300+
WARNINGS.with(|count| assert_eq!(count.get(), warnings));
301+
}
302+
}
273303
}

0 commit comments

Comments
 (0)