@@ -125,7 +125,7 @@ int AMDeviceSecureInstallApplication(int zero, AMDeviceRef device, CFURLRef url,
125
125
int AMDeviceMountImage (AMDeviceRef device , CFStringRef image , CFDictionaryRef options , void * callback , int cbarg );
126
126
mach_error_t AMDeviceLookupApplications (AMDeviceRef device , CFDictionaryRef options , CFDictionaryRef * result );
127
127
128
- bool found_device = false, debug = false, verbose = false, unbuffered = false, nostart = false, detect_only = false, install = true;
128
+ bool found_device = false, debug = false, verbose = false, unbuffered = false, nostart = false, detect_only = false, install = true, uninstall = false ;
129
129
bool interactive = true;
130
130
char * app_path = NULL ;
131
131
char * device_id = NULL ;
@@ -813,6 +813,42 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) {
813
813
}
814
814
}
815
815
816
+ CFStringRef get_bundle_id (CFURLRef app_url )
817
+ {
818
+ if (app_url == NULL )
819
+ return NULL ;
820
+
821
+ CFURLRef url = CFURLCreateCopyAppendingPathComponent (NULL , app_url , CFSTR ("Info.plist" ), false);
822
+
823
+ if (url == NULL )
824
+ return NULL ;
825
+
826
+ CFReadStreamRef stream = CFReadStreamCreateWithFile (NULL , url );
827
+ CFRelease (url );
828
+
829
+ if (stream == NULL )
830
+ return NULL ;
831
+
832
+ CFPropertyListRef plist = NULL ;
833
+ if (CFReadStreamOpen (stream ) == TRUE) {
834
+ plist = CFPropertyListCreateWithStream (NULL , stream , 0 ,
835
+ kCFPropertyListImmutable , NULL , NULL );
836
+ }
837
+ CFReadStreamClose (stream );
838
+ CFRelease (stream );
839
+
840
+ if (plist == NULL )
841
+ return NULL ;
842
+
843
+ const void * value = CFDictionaryGetValue (plist , CFSTR ("CFBundleIdentifier" ));
844
+ CFStringRef bundle_id = NULL ;
845
+ if (value != NULL )
846
+ bundle_id = CFRetain (value );
847
+
848
+ CFRelease (plist );
849
+ return bundle_id ;
850
+ }
851
+
816
852
void handle_device (AMDeviceRef device ) {
817
853
if (found_device ) return ; // handle one device only
818
854
CFStringRef found_device_id = AMDeviceCopyDeviceIdentifier (device );
@@ -841,7 +877,29 @@ void handle_device(AMDeviceRef device) {
841
877
842
878
CFRelease (relative_url );
843
879
880
+ if (uninstall ) {
881
+ printf ("------ Uninstall phase ------\n" );
882
+
883
+ CFStringRef bundle_id = get_bundle_id (url );
884
+ if (bundle_id == NULL ) {
885
+ printf ("Error: Unable to get bundle id from package %s\n Uninstall failed\n" , app_path );
886
+ } else {
887
+ AMDeviceConnect (device );
888
+ assert (AMDeviceIsPaired (device ));
889
+ assert (AMDeviceValidatePairing (device ) == 0 );
890
+ assert (AMDeviceStartSession (device ) == 0 );
891
+
892
+ assert (AMDeviceSecureUninstallApplication (0 , device , bundle_id , 0 , NULL , 0 ) == 0 );
893
+
894
+ assert (AMDeviceStopSession (device ) == 0 );
895
+ assert (AMDeviceDisconnect (device ) == 0 );
896
+
897
+ printf ("[ OK ] Uninstalled package with bundle id %s\n" , CFStringGetCStringPtr (bundle_id , CFStringGetSystemEncoding ()));
898
+ }
899
+ }
900
+
844
901
if (install ) {
902
+ printf ("------ Install phase ------\n" );
845
903
printf ("[ 0%%] Found device (%s), beginning install\n" , CFStringGetCStringPtr (found_device_id , CFStringGetSystemEncoding ()));
846
904
847
905
AMDeviceConnect (device );
@@ -929,6 +987,7 @@ void usage(const char* app) {
929
987
" -v, --verbose enable verbose output\n"
930
988
" -m, --noinstall directly start debugging without app install (-d not required)\n"
931
989
" -p, --port <number> port used for device, default: 12345 \n"
990
+ " -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) \n"
932
991
" -V, --version print the executable version \n" ,
933
992
app );
934
993
}
@@ -953,11 +1012,12 @@ int main(int argc, char *argv[]) {
953
1012
{ "version" , no_argument , NULL , 'V' },
954
1013
{ "noinstall" , no_argument , NULL , 'm' },
955
1014
{ "port" , required_argument , NULL , 'p' },
1015
+ { "uninstall" , no_argument , NULL , 'r' },
956
1016
{ NULL , 0 , NULL , 0 },
957
1017
};
958
1018
char ch ;
959
1019
960
- while ((ch = getopt_long (argc , argv , "VmcdvunIi :b:a:t:g:x:p:" , longopts , NULL )) != -1 )
1020
+ while ((ch = getopt_long (argc , argv , "VmcdvunrIi :b:a:t:g:x:p:" , longopts , NULL )) != -1 )
961
1021
{
962
1022
switch (ch ) {
963
1023
case 'm' :
@@ -1000,6 +1060,9 @@ int main(int argc, char *argv[]) {
1000
1060
case 'p' :
1001
1061
port = atoi (optarg );
1002
1062
break ;
1063
+ case 'r' :
1064
+ uninstall = 1 ;
1065
+ break ;
1003
1066
default :
1004
1067
usage (argv [0 ]);
1005
1068
return exitcode_error ;
@@ -1020,10 +1083,6 @@ int main(int argc, char *argv[]) {
1020
1083
timeout = 5 ;
1021
1084
}
1022
1085
1023
- if (!detect_only ) {
1024
- printf ("------ Install phase ------\n" );
1025
- }
1026
-
1027
1086
if (app_path ) {
1028
1087
assert (access (app_path , F_OK ) == 0 );
1029
1088
}
0 commit comments