1use std::path::PathBuf;
7use vx_installer::{ArchiveFormat, InstallConfig, InstallMethod};
8use vx_tool_standard::{StandardToolConfig, StandardUrlBuilder, ToolDependency};
9
10pub struct Config;
12
13#[derive(Debug, Clone)]
15pub struct UvUrlBuilder;
16
17impl Default for UvUrlBuilder {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23impl UvUrlBuilder {
24 pub fn new() -> Self {
25 Self
26 }
27}
28
29impl StandardUrlBuilder for UvUrlBuilder {
30 fn download_url(version: &str) -> Option<String> {
32 let filename = Self::get_filename(version);
33
34 Some(format!(
35 "https://github.com/astral-sh/uv/releases/download/{}/{}",
36 version, filename
37 ))
38 }
39
40 fn get_filename(version: &str) -> String {
42 let platform = Self::get_platform_string();
43 if cfg!(windows) {
44 format!("uv-{}-{}.zip", platform, version)
45 } else {
46 format!("uv-{}-{}.tar.gz", platform, version)
47 }
48 }
49
50 fn get_platform_string() -> String {
52 if cfg!(target_os = "windows") {
53 if cfg!(target_arch = "x86_64") {
54 "x86_64-pc-windows-msvc".to_string()
55 } else if cfg!(target_arch = "x86") {
56 "i686-pc-windows-msvc".to_string()
57 } else {
58 "unknown-pc-windows-msvc".to_string()
59 }
60 } else if cfg!(target_os = "macos") {
61 if cfg!(target_arch = "x86_64") {
62 "x86_64-apple-darwin".to_string()
63 } else if cfg!(target_arch = "aarch64") {
64 "aarch64-apple-darwin".to_string()
65 } else {
66 "unknown-apple-darwin".to_string()
67 }
68 } else if cfg!(target_os = "linux") {
69 if cfg!(target_arch = "x86_64") {
70 "x86_64-unknown-linux-gnu".to_string()
71 } else if cfg!(target_arch = "aarch64") {
72 "aarch64-unknown-linux-gnu".to_string()
73 } else {
74 "unknown-unknown-linux-gnu".to_string()
75 }
76 } else {
77 "unknown".to_string()
78 }
79 }
80}
81
82impl StandardToolConfig for Config {
83 fn tool_name() -> &'static str {
84 "uv"
85 }
86
87 fn create_install_config(version: &str, install_dir: PathBuf) -> InstallConfig {
88 create_install_config(version, install_dir)
89 }
90
91 fn get_install_methods() -> Vec<String> {
92 vec!["archive".to_string(), "binary".to_string()]
93 }
94
95 fn supports_auto_install() -> bool {
96 true
97 }
98
99 fn get_manual_instructions() -> String {
100 "Visit https://docs.astral.sh/uv/getting-started/installation/ to install UV manually"
101 .to_string()
102 }
103
104 fn get_dependencies() -> Vec<ToolDependency> {
105 vec![]
106 }
107
108 fn get_default_version() -> &'static str {
109 "latest"
110 }
111}
112
113pub fn create_install_config(version: &str, install_dir: PathBuf) -> InstallConfig {
115 let download_url = UvUrlBuilder::download_url(version);
116
117 InstallConfig::builder()
118 .tool_name(Config::tool_name())
119 .version(version)
120 .download_url(download_url.unwrap_or_default())
121 .install_method(InstallMethod::Archive {
122 format: if cfg!(windows) {
123 ArchiveFormat::Zip
124 } else {
125 ArchiveFormat::TarGz
126 },
127 })
128 .install_dir(install_dir)
129 .build()
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135
136 #[test]
137 fn test_uv_url_builder() {
138 let url = UvUrlBuilder::download_url("0.1.0");
139 assert!(url.is_some());
140 assert!(url.unwrap().contains("github.com"));
141 }
142
143 #[test]
144 fn test_platform_string() {
145 let platform = UvUrlBuilder::get_platform_string();
146 assert!(!platform.is_empty());
147 }
148
149 #[test]
150 fn test_create_install_config() {
151 let config = create_install_config("0.1.0", PathBuf::from("/tmp/uv"));
152 assert_eq!(config.tool_name, "uv");
153 assert_eq!(config.version, "0.1.0");
154 assert!(config.download_url.is_some());
155 }
156}