use std::fs::File;
pub use install_location::{normalize_name, InstallLocation, LockedDir};
use platform_info::PlatformInfoError;
use std::io;
use std::path::Path;
use std::str::FromStr;
use thiserror::Error;
pub use wheel::{
get_script_launcher, install_wheel, parse_key_value_file, read_record_file, relative_to,
Script, MONOTRAIL_SCRIPT_SHEBANG,
};
pub use wheel_tags::{Arch, CompatibleTags, Os, WheelFilename};
use zip::result::ZipError;
mod install_location;
#[cfg(feature = "python_bindings")]
mod python_bindings;
mod wheel;
mod wheel_tags;
#[derive(Error, Debug)]
pub enum Error {
#[error(transparent)]
IO(#[from] io::Error),
#[error("Failed to serialize direct_url.json ಠ_ಠ")]
DirectUrlSerdeJson(#[source] serde_json::Error),
#[error("The wheel is incompatible with the current platform {os} {arch}")]
IncompatibleWheel { os: Os, arch: Arch },
#[error("The wheel is invalid: {0}")]
InvalidWheel(String),
#[error("The poetry dependency specification (pyproject.toml or poetry.lock) is broken (try `poetry update`?): {0}")]
InvalidPoetry(String),
#[error("The wheel filename \"{0}\" is invalid: {1}")]
InvalidWheelFileName(String, String),
#[error("Failed to read the wheel file {0}")]
Zip(String, #[source] ZipError),
#[error("Failed to run python subcommand")]
PythonSubcommand(#[source] io::Error),
#[error("Failed to move data files")]
WalkDir(#[from] walkdir::Error),
#[error("RECORD file doesn't match wheel contents: {0}")]
RecordFile(String),
#[error("RECORD file is invalid")]
RecordCsv(#[from] csv::Error),
#[error("Broken virtualenv: {0}")]
BrokenVenv(String),
#[error("Failed to detect the operating system version: {0}")]
OsVersionDetection(String),
#[error("Failed to detect the current platform")]
PlatformInfo(#[source] PlatformInfoError),
#[error("Invalid version specification, only none or == is supported")]
Pep440,
}
pub fn install_wheel_in_venv(
wheel: &Path,
venv: &Path,
interpreter: &Path,
major: u8,
minor: u8,
) -> Result<String, Error> {
let venv_base = venv.canonicalize()?;
let location = InstallLocation::Venv {
venv_base,
python_version: (major, minor),
};
let locked_dir = location.acquire_lock()?;
let filename = wheel
.file_name()
.ok_or_else(|| Error::InvalidWheel("Expected a file".to_string()))?
.to_string_lossy();
let filename = WheelFilename::from_str(&filename)?;
let compatible_tags = CompatibleTags::current(location.get_python_version())?;
filename.compatibility(&compatible_tags)?;
install_wheel(
&locked_dir,
File::open(wheel)?,
filename,
false,
&[],
"",
interpreter,
)
}