use std::env;
use serde::Serialize;
use tracing::instrument;
use uv_pep508::MarkerEnvironment;
use uv_platform_tags::{Os, Platform};
use uv_static::EnvVars;
use uv_version::version;
#[derive(Serialize)]
struct Installer {
name: Option<String>,
version: Option<String>,
subcommand: Option<Vec<String>>,
}
#[derive(Serialize)]
struct Implementation {
name: Option<String>,
version: Option<String>,
}
#[derive(Serialize)]
struct Libc {
lib: Option<String>,
version: Option<String>,
}
#[derive(Serialize)]
struct Distro {
name: Option<String>,
version: Option<String>,
id: Option<String>,
libc: Option<Libc>,
}
#[derive(Serialize)]
struct System {
name: Option<String>,
release: Option<String>,
}
#[derive(Serialize)]
pub(crate) struct LineHaul {
installer: Option<Installer>,
python: Option<String>,
implementation: Option<Implementation>,
distro: Option<Distro>,
system: Option<System>,
cpu: Option<String>,
openssl_version: Option<String>,
setuptools_version: Option<String>,
rustc_version: Option<String>,
ci: Option<bool>,
}
impl LineHaul {
#[instrument(name = "linehaul", skip_all)]
pub(crate) fn new(
markers: Option<&MarkerEnvironment>,
platform: Option<&Platform>,
subcommand: Option<Vec<String>>,
) -> Self {
let looks_like_ci = [
EnvVars::BUILD_BUILDID,
EnvVars::BUILD_ID,
EnvVars::CI,
EnvVars::PIP_IS_CI,
]
.iter()
.find_map(|&var_name| env::var(var_name).ok().map(|_| true));
let libc = match platform.map(Platform::os) {
Some(Os::Manylinux { major, minor }) => Some(Libc {
lib: Some("glibc".to_string()),
version: Some(format!("{major}.{minor}")),
}),
Some(Os::Musllinux { major, minor }) => Some(Libc {
lib: Some("musl".to_string()),
version: Some(format!("{major}.{minor}")),
}),
_ => None,
};
let distro: Option<Distro> = if cfg!(target_os = "linux") {
uv_platform::LinuxOsRelease::from_env().map(|info| Distro {
id: info.version_codename,
name: info.name,
version: info.version_id,
libc,
})
} else if cfg!(target_os = "macos") {
let version = match platform.map(Platform::os) {
Some(Os::Macos { major, minor }) => Some(format!("{major}.{minor}")),
_ => None,
};
Some(Distro {
id: None,
name: Some("macOS".to_string()),
version,
libc: None,
})
} else {
None
};
Self {
installer: Option::from(Installer {
name: Some("uv".to_string()),
version: Some(version().to_string()),
subcommand,
}),
python: markers.map(|markers| markers.python_full_version().version.to_string()),
implementation: Option::from(Implementation {
name: markers.map(|markers| markers.platform_python_implementation().to_string()),
version: markers.map(|markers| markers.python_full_version().version.to_string()),
}),
distro,
system: Option::from(System {
name: markers.map(|markers| markers.platform_system().to_string()),
release: markers.map(|markers| markers.platform_release().to_string()),
}),
cpu: markers.map(|markers| markers.platform_machine().to_string()),
openssl_version: None,
setuptools_version: None,
rustc_version: None,
ci: looks_like_ci,
}
}
}