1use std::io;
4use std::path::PathBuf;
5
6use owo_colors::OwoColorize;
7use thiserror::Error;
8
9use uv_fs::Simplified;
10use uv_normalize::PackageName;
11use uv_pep440::Version;
12use uv_pypi_types::Scheme;
13
14pub use install::install_wheel;
15pub use linker::{LinkMode, Locks};
16pub use uninstall::{Uninstall, uninstall_egg, uninstall_legacy_editable, uninstall_wheel};
17pub use wheel::{LibKind, WheelFile, read_record_file};
18
19mod install;
20mod linker;
21mod record;
22mod script;
23mod uninstall;
24mod wheel;
25
26#[derive(Debug, Clone)]
28pub struct Layout {
29 pub sys_executable: PathBuf,
31 pub python_version: (u8, u8),
33 pub os_name: String,
35 pub scheme: Scheme,
37}
38
39#[derive(Error, Debug)]
41pub enum Error {
42 #[error(transparent)]
43 Io(#[from] io::Error),
44 #[error("Failed to reflink {} to {}", from.user_display(), to.user_display())]
46 Reflink {
47 from: PathBuf,
48 to: PathBuf,
49 #[source]
50 err: io::Error,
51 },
52 #[error("The wheel is invalid: {0}")]
54 InvalidWheel(String),
55 #[error("Failed to move data files")]
57 WalkDir(#[from] walkdir::Error),
58 #[error("RECORD file doesn't match wheel contents: {0}")]
59 RecordFile(String),
60 #[error("RECORD file is invalid")]
61 RecordCsv(#[from] csv::Error),
62 #[error("Broken virtual environment: {0}")]
63 BrokenVenv(String),
64 #[error(
65 "Unable to create Windows launcher for: {0} (only x86_64, x86, and arm64 are supported)"
66 )]
67 UnsupportedWindowsArch(&'static str),
68 #[error("Unable to create Windows launcher on non-Windows platform")]
69 NotWindows,
70 #[error("Invalid `direct_url.json`")]
71 DirectUrlJson(#[from] serde_json::Error),
72 #[error("Cannot uninstall package; `RECORD` file not found at: {}", _0.user_display())]
73 MissingRecord(PathBuf),
74 #[error("Cannot uninstall package; `top_level.txt` file not found at: {}", _0.user_display())]
75 MissingTopLevel(PathBuf),
76 #[error("Invalid package version")]
77 InvalidVersion(#[from] uv_pep440::VersionParseError),
78 #[error("Wheel package name does not match filename ({0} != {1}), which indicates a malformed wheel. If this is intentional, set `{env_var}`.", env_var = "UV_SKIP_WHEEL_FILENAME_CHECK=1".green())]
79 MismatchedName(PackageName, PackageName),
80 #[error("Wheel version does not match filename ({0} != {1}), which indicates a malformed wheel. If this is intentional, set `{env_var}`.", env_var = "UV_SKIP_WHEEL_FILENAME_CHECK=1".green())]
81 MismatchedVersion(Version, Version),
82 #[error("Invalid egg-link")]
83 InvalidEggLink(PathBuf),
84 #[error(transparent)]
85 LauncherError(#[from] uv_trampoline_builder::Error),
86 #[error("Scripts must not use the reserved name {0}")]
87 ReservedScriptName(String),
88}