Skip to content

Commit f1f6c21

Browse files
committed
WIP
1 parent be4427e commit f1f6c21

4 files changed

Lines changed: 67 additions & 23 deletions

File tree

src/env.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::csmrc::Config;
2-
use crate::util::micromamba;
2+
use crate::micromamba::micromamba;
33

44
use log::{debug, error, info};
55
use serde::Deserialize;

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
mod csmrc;
22
mod env;
3+
mod micromamba;
34
mod robot;
4-
mod util;
55

66
use crate::csmrc::Config;
77
use clap::{Parser, Subcommand};

src/micromamba.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//! This module deals with `micromamba` - obtaining it, calling it, etc.
2+
3+
use crate::csmrc::Config;
4+
use log::debug;
5+
use std::collections::HashMap;
6+
use std::io::{Error, ErrorKind};
7+
use std::path::PathBuf;
8+
use std::process::Command;
9+
10+
pub enum MicromambaLocation {
11+
/// A working `micromamba` was found in `$PATH` already.
12+
InPath,
13+
14+
/// A working `micromamba` exists at the given path.
15+
Path(PathBuf),
16+
}
17+
18+
/// Return a [`Command`] ready to shell out to `micromamba` with the appropriate
19+
/// environment variables set based on configuration.
20+
pub fn micromamba_at(location: MicromambaLocation, config: &Config, args: Vec<&str>) -> Command {
21+
let mut env_vars: HashMap<&str, String> = HashMap::new();
22+
23+
if let Some(mamba_root_prefix) = &config.mamba_root_prefix {
24+
env_vars.insert("MAMBA_ROOT_PREFIX", mamba_root_prefix.to_string());
25+
}
26+
27+
let mut cmd = Command::new("micromamba");
28+
cmd.args(args);
29+
cmd.envs(env_vars);
30+
debug!("About to run: {:?}", cmd);
31+
cmd
32+
}
33+
34+
pub fn micromamba(config: &Config, args: Vec<&str>) -> Result<Command, Error> {
35+
match micromamba_path(config) {
36+
None => Err(Error::from(ErrorKind::NotFound)),
37+
Some(location) => Ok(micromamba_at(location, config, args))
38+
}
39+
}
40+
41+
/// We need a `micromamba` binary to work with. If one is not present, attempt
42+
/// to download and install `micromamba` into the user's cache directory. Return
43+
/// a [`MicromambaLocation`] with the result if we found a working `micromamba`.
44+
///
45+
/// 1. If there is already a `micromamba` command in $PATH, we use it.
46+
/// 2. Otherwise, download micromamba and install it somewhere in the user
47+
/// cache directory. (We cannot rely on this - it could be that the user's
48+
/// cache directory is mounted noexec or similar).
49+
///
50+
/// Alternative approaches that we do not take here currently:
51+
/// - On Linux, we *could* in theory use memfd_create + fexecve to embed the app
52+
/// and run it from memory. This won't work on Windows.
53+
///
54+
/// - We *could* embed the micromamba binary in our binary (Windows or Linux
55+
/// based on compile target) and write it to the user cache directory rather
56+
/// than downloading it. But this inflates our binary size.
57+
pub fn micromamba_path(config: &Config) -> Option<MicromambaLocation> {
58+
// Assume it's in $PATH already and see what happens.
59+
if let Ok(output) = micromamba_at(MicromambaLocation::InPath, config, vec!["--version"]).output() {
60+
// The full path doesn't matter, it's in $PATH
61+
debug!("micromamba reported version {}", String::from_utf8_lossy(&output.stdout));
62+
return Some(MicromambaLocation::InPath);
63+
}
64+
None
65+
}

src/util.rs

Lines changed: 0 additions & 21 deletions
This file was deleted.

0 commit comments

Comments
 (0)