@@ -21,22 +21,28 @@ use crate::config::Config;
2121use crate :: utils:: args:: ArgExt as _;
2222use crate :: utils:: chunks:: { upload_chunks, Chunk , ASSEMBLE_POLL_INTERVAL } ;
2323use crate :: utils:: fs:: get_sha1_checksums;
24+ #[ cfg( target_os = "macos" ) ]
25+ use crate :: utils:: fs:: TempDir ;
2426use crate :: utils:: fs:: TempFile ;
2527#[ cfg( target_os = "macos" ) ]
26- use crate :: utils:: mobile_app:: handle_asset_catalogs;
28+ use crate :: utils:: mobile_app:: { handle_asset_catalogs, ipa_to_xcarchive , is_ipa_file } ;
2729use crate :: utils:: mobile_app:: { is_aab_file, is_apk_file, is_apple_app, is_zip_file} ;
2830use crate :: utils:: progress:: ProgressBar ;
2931use crate :: utils:: vcs;
3032
3133pub fn make_command ( command : Command ) -> Command {
34+ #[ cfg( target_os = "macos" ) ]
35+ const HELP_TEXT : & str = "The path to the mobile app files to upload. Supported files include Apk, Aab, XCArchive, and IPA." ;
36+ #[ cfg( not( target_os = "macos" ) ) ]
37+ const HELP_TEXT : & str = "The path to the mobile app files to upload. Supported files include Apk, Aab, and XCArchive." ;
3238 command
3339 . about ( "[EXPERIMENTAL] Upload mobile app files to a project." )
3440 . org_arg ( )
3541 . project_arg ( false )
3642 . arg (
3743 Arg :: new ( "paths" )
3844 . value_name ( "PATH" )
39- . help ( "The path to the mobile app files to upload. Supported files include Apk, Aab or XCArchive." )
45+ . help ( HELP_TEXT )
4046 . num_args ( 1 ..)
4147 . action ( ArgAction :: Append )
4248 . required ( true ) ,
@@ -95,12 +101,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
95101
96102 let normalized_zip = if path. is_file ( ) {
97103 debug ! ( "Normalizing file: {}" , path. display( ) ) ;
98- normalize_file ( path, & byteview) . with_context ( || {
99- format ! (
100- "Failed to generate uploadable bundle for file {}" ,
101- path. display( )
102- )
103- } ) ?
104+ handle_file ( path, & byteview) ?
104105 } else if path. is_dir ( ) {
105106 debug ! ( "Normalizing directory: {}" , path. display( ) ) ;
106107 normalize_directory ( path) . with_context ( || {
@@ -178,6 +179,25 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
178179 Ok ( ( ) )
179180}
180181
182+ fn handle_file ( path : & Path , byteview : & ByteView ) -> Result < TempFile > {
183+ // Handle IPA files by converting them to XCArchive
184+ #[ cfg( target_os = "macos" ) ]
185+ if is_zip_file ( byteview) && is_ipa_file ( byteview) ? {
186+ debug ! ( "Converting IPA file to XCArchive structure" ) ;
187+ let temp_dir = TempDir :: create ( ) ?;
188+ return ipa_to_xcarchive ( path, byteview, & temp_dir)
189+ . and_then ( |path| normalize_directory ( & path) )
190+ . with_context ( || format ! ( "Failed to process IPA file {}" , path. display( ) ) ) ;
191+ }
192+
193+ normalize_file ( path, byteview) . with_context ( || {
194+ format ! (
195+ "Failed to generate uploadable bundle for file {}" ,
196+ path. display( )
197+ )
198+ } )
199+ }
200+
181201fn validate_is_mobile_app ( path : & Path , bytes : & [ u8 ] ) -> Result < ( ) > {
182202 debug ! ( "Validating mobile app format for: {}" , path. display( ) ) ;
183203
@@ -186,9 +206,13 @@ fn validate_is_mobile_app(path: &Path, bytes: &[u8]) -> Result<()> {
186206 return Ok ( ( ) ) ;
187207 }
188208
189- // Check if the file is a zip file (then AAB or APK )
209+ // Check if the file is a zip file (then AAB, APK, or IPA )
190210 if is_zip_file ( bytes) {
211+ #[ cfg( target_os = "macos" ) ]
212+ debug ! ( "File is a zip, checking for AAB/APK/IPA format" ) ;
213+ #[ cfg( not( target_os = "macos" ) ) ]
191214 debug ! ( "File is a zip, checking for AAB/APK format" ) ;
215+
192216 if is_aab_file ( bytes) ? {
193217 debug ! ( "Detected AAB file" ) ;
194218 return Ok ( ( ) ) ;
@@ -198,11 +222,22 @@ fn validate_is_mobile_app(path: &Path, bytes: &[u8]) -> Result<()> {
198222 debug ! ( "Detected APK file" ) ;
199223 return Ok ( ( ) ) ;
200224 }
225+
226+ #[ cfg( target_os = "macos" ) ]
227+ if is_ipa_file ( bytes) ? {
228+ debug ! ( "Detected IPA file" ) ;
229+ return Ok ( ( ) ) ;
230+ }
201231 }
202232
203233 debug ! ( "File format validation failed" ) ;
234+ #[ cfg( target_os = "macos" ) ]
235+ let format_list = "APK, AAB, XCArchive, or IPA" ;
236+ #[ cfg( not( target_os = "macos" ) ) ]
237+ let format_list = "APK, AAB, or XCArchive" ;
238+
204239 Err ( anyhow ! (
205- "File is not a recognized mobile app format (APK, AAB, or XCArchive ): {}" ,
240+ "File is not a recognized mobile app format ({format_list} ): {}" ,
206241 path. display( )
207242 ) )
208243}
0 commit comments