11use crate :: error:: { Error , Result } ;
22use crate :: paths;
33use crate :: version_manager:: download:: download_version;
4+ use crate :: version_manager:: resolve:: is_tarball_download;
45use std:: os:: unix:: fs:: PermissionsExt ;
56
67/// Installs a ClickHouse version
@@ -17,11 +18,21 @@ pub async fn install_version(version: &str, channel: &str) -> Result<()> {
1718 // Create the version directory
1819 std:: fs:: create_dir_all ( & version_dir) ?;
1920
20- // Download the binary directly to the destination
2121 let binary_path = version_dir. join ( "clickhouse" ) ;
2222
2323 println ! ( "Downloading ClickHouse {}..." , version) ;
24- download_version ( version, channel, & binary_path) . await ?;
24+
25+ if is_tarball_download ( ) ? {
26+ // Linux: download tarball, extract, move binary
27+ let tarball_path = version_dir. join ( "clickhouse.tgz" ) ;
28+ download_version ( version, channel, & tarball_path) . await ?;
29+
30+ println ! ( "Extracting..." ) ;
31+ extract_tarball ( & tarball_path, & version_dir, version) ?;
32+ } else {
33+ // macOS: download binary directly
34+ download_version ( version, channel, & binary_path) . await ?;
35+ }
2536
2637 // Make the binary executable
2738 let mut perms = std:: fs:: metadata ( & binary_path) ?. permissions ( ) ;
@@ -31,3 +42,47 @@ pub async fn install_version(version: &str, channel: &str) -> Result<()> {
3142 println ! ( "ClickHouse {} installed successfully" , version) ;
3243 Ok ( ( ) )
3344}
45+
46+ /// Extracts the ClickHouse binary from a Linux tarball
47+ fn extract_tarball (
48+ tarball_path : & std:: path:: Path ,
49+ version_dir : & std:: path:: Path ,
50+ version : & str ,
51+ ) -> Result < ( ) > {
52+ // Extract the tarball
53+ let status = std:: process:: Command :: new ( "tar" )
54+ . args ( [ "xzf" , & tarball_path. to_string_lossy ( ) ] )
55+ . current_dir ( version_dir)
56+ . status ( )
57+ . map_err ( |e| Error :: Extract ( format ! ( "Failed to run tar: {}" , e) ) ) ?;
58+
59+ if !status. success ( ) {
60+ // Clean up tarball on failure
61+ let _ = std:: fs:: remove_file ( tarball_path) ;
62+ return Err ( Error :: Extract ( "tar extraction failed" . to_string ( ) ) ) ;
63+ }
64+
65+ // Find the clickhouse binary inside the extracted directory
66+ let extracted_dir = version_dir. join ( format ! ( "clickhouse-common-static-{}" , version) ) ;
67+ let extracted_binary = extracted_dir. join ( "usr/bin/clickhouse" ) ;
68+
69+ if !extracted_binary. exists ( ) {
70+ // Clean up on failure
71+ let _ = std:: fs:: remove_file ( tarball_path) ;
72+ let _ = std:: fs:: remove_dir_all ( & extracted_dir) ;
73+ return Err ( Error :: Extract ( format ! (
74+ "Binary not found at expected path: {}" ,
75+ extracted_binary. display( )
76+ ) ) ) ;
77+ }
78+
79+ // Move binary to final location
80+ let final_binary = version_dir. join ( "clickhouse" ) ;
81+ std:: fs:: rename ( & extracted_binary, & final_binary) ?;
82+
83+ // Clean up tarball and extracted directory
84+ let _ = std:: fs:: remove_file ( tarball_path) ;
85+ let _ = std:: fs:: remove_dir_all ( & extracted_dir) ;
86+
87+ Ok ( ( ) )
88+ }
0 commit comments