@@ -4,7 +4,7 @@ import Q = require('q');
44import tl = require( 'vsts-task-lib/task' ) ;
55import { ToolRunner } from 'vsts-task-lib/toolrunner' ;
66
7- var userProvisioningProfilesPath = path . join ( tl . getVariable ( 'HOME' ) , 'Library' , 'MobileDevice' , 'Provisioning Profiles' ) ;
7+ var userProvisioningProfilesPath = tl . resolve ( tl . getVariable ( 'HOME' ) , 'Library' , 'MobileDevice' , 'Provisioning Profiles' ) ;
88
99/**
1010 * Creates a temporary keychain and installs the P12 cert in the temporary keychain
@@ -18,31 +18,26 @@ export async function installCertInTemporaryKeychain(keychainPath : string, keyc
1818 await deleteKeychain ( keychainPath ) ;
1919
2020 //create keychain
21- var createKeychainCommand : ToolRunner = tl . createToolRunner ( tl . which ( 'security' , true ) ) ;
22- createKeychainCommand . arg ( [ 'create-keychain' , '-p' , keychainPwd ] ) ;
23- createKeychainCommand . pathArg ( keychainPath ) ;
21+ var createKeychainCommand : ToolRunner = tl . tool ( tl . which ( 'security' , true ) ) ;
22+ createKeychainCommand . arg ( [ 'create-keychain' , '-p' , keychainPwd , keychainPath ] ) ;
2423 await createKeychainCommand . exec ( ) ;
2524
2625 //update keychain settings
27- var keychainSettingsCommand : ToolRunner = tl . createToolRunner ( tl . which ( 'security' , true ) ) ;
28- keychainSettingsCommand . arg ( [ 'set-keychain-settings' , '-lut' , '7200' ] ) ;
29- keychainSettingsCommand . pathArg ( keychainPath ) ;
26+ var keychainSettingsCommand : ToolRunner = tl . tool ( tl . which ( 'security' , true ) ) ;
27+ keychainSettingsCommand . arg ( [ 'set-keychain-settings' , '-lut' , '7200' , keychainPath ] ) ;
3028 await keychainSettingsCommand . exec ( ) ;
3129
3230 //unlock keychain
3331 await unlockKeychain ( keychainPath , keychainPwd ) ;
3432
3533 //import p12 cert into the keychain
36- var importP12Command : ToolRunner = tl . createToolRunner ( tl . which ( 'security' , true ) ) ;
37- importP12Command . arg ( 'import' ) ;
38- importP12Command . pathArg ( p12CertPath ) ;
39- importP12Command . arg ( [ '-P' , p12Pwd , '-A' , '-t' , 'cert' , '-f' , 'pkcs12' , '-k' ] ) ;
40- importP12Command . pathArg ( keychainPath ) ;
34+ var importP12Command : ToolRunner = tl . tool ( tl . which ( 'security' , true ) ) ;
35+ importP12Command . arg ( [ 'import' , p12CertPath , '-P' , p12Pwd , '-A' , '-t' , 'cert' , '-f' , 'pkcs12' , '-k' , keychainPath ] ) ;
4136 await importP12Command . exec ( ) ;
4237
4338 //list the keychains to get current keychains in search path
4439 var listAllOutput : string ;
45- var listAllCommand : ToolRunner = tl . createToolRunner ( tl . which ( 'security' , true ) ) ;
40+ var listAllCommand : ToolRunner = tl . tool ( tl . which ( 'security' , true ) ) ;
4641 listAllCommand . arg ( [ 'list-keychain' , '-d' , 'user' ] ) ;
4742 listAllCommand . on ( 'stdout' , function ( data ) {
4843 if ( data ) {
@@ -68,11 +63,11 @@ export async function installCertInTemporaryKeychain(keychainPath : string, keyc
6863 //login keychain is not in the search path,
6964 //this might have happened with the 2.1.21 version of Xcode task
7065 //add it back explicitly, this can be removed after a couple of sprints
71- allKeychainsArr . push ( path . join ( tl . getVariable ( 'HOME' ) , 'Library' , 'Keychains' , 'login.keychain' ) ) ;
66+ allKeychainsArr . push ( tl . resolve ( tl . getVariable ( 'HOME' ) , 'Library' , 'Keychains' , 'login.keychain' ) ) ;
7267 }
7368
7469 //add the temporary keychain to list path along with existing keychains
75- var listAddCommand : ToolRunner = tl . createToolRunner ( tl . which ( 'security' , true ) ) ;
70+ var listAddCommand : ToolRunner = tl . tool ( tl . which ( 'security' , true ) ) ;
7671 listAddCommand . arg ( [ 'list-keychain' , '-d' , 'user' , '-s' , keychainPath ] ) ;
7772 for ( var i : number = 0 ; i < allKeychainsArr . length ; i ++ ) {
7873 listAddCommand . arg ( allKeychainsArr [ i ] . trim ( ) . replace ( / " / gm, '' ) ) ;
@@ -81,7 +76,7 @@ export async function installCertInTemporaryKeychain(keychainPath : string, keyc
8176 await listAddCommand . exec ( ) ;
8277
8378 var listVerifyOutput : string ;
84- var listVerifyCommand : ToolRunner = tl . createToolRunner ( tl . which ( 'security' , true ) ) ;
79+ var listVerifyCommand : ToolRunner = tl . tool ( tl . which ( 'security' , true ) ) ;
8580 listVerifyCommand . arg ( [ 'list-keychain' , '-d' , 'user' ] ) ;
8681 listVerifyCommand . on ( 'stdout' , function ( data ) {
8782 if ( data ) {
@@ -108,9 +103,8 @@ export async function installCertInTemporaryKeychain(keychainPath : string, keyc
108103 */
109104export async function findSigningIdentity ( keychainPath : string ) {
110105 var signIdentity : string ;
111- var findIdentityCmd : ToolRunner = tl . createToolRunner ( tl . which ( 'security' , true ) ) ;
112- findIdentityCmd . arg ( [ 'find-identity' , '-v' , '-p' , 'codesigning' ] ) ;
113- findIdentityCmd . pathArg ( keychainPath ) ;
106+ var findIdentityCmd : ToolRunner = tl . tool ( tl . which ( 'security' , true ) ) ;
107+ findIdentityCmd . arg ( [ 'find-identity' , '-v' , '-p' , 'codesigning' , keychainPath ] ) ;
114108 findIdentityCmd . on ( 'stdout' , function ( data ) {
115109 if ( data ) {
116110 var matches = data . toString ( ) . trim ( ) . match ( / " ( .+ ) " / g) ;
@@ -140,9 +134,8 @@ export async function getProvisioningProfileUUID(provProfilePath: string) {
140134
141135 //find the provisioning profile UUID
142136 var provProfileDetails : string ;
143- var getProvProfileDetailsCmd : ToolRunner = tl . createToolRunner ( tl . which ( 'security' , true ) ) ;
144- getProvProfileDetailsCmd . arg ( [ 'cms' , '-D' , '-i' ] ) ;
145- getProvProfileDetailsCmd . pathArg ( provProfilePath ) ;
137+ var getProvProfileDetailsCmd : ToolRunner = tl . tool ( tl . which ( 'security' , true ) ) ;
138+ getProvProfileDetailsCmd . arg ( [ 'cms' , '-D' , '-i' , provProfilePath ] ) ;
146139 getProvProfileDetailsCmd . on ( 'stdout' , function ( data ) {
147140 if ( data ) {
148141 if ( provProfileDetails ) {
@@ -165,9 +158,8 @@ export async function getProvisioningProfileUUID(provProfilePath: string) {
165158 //use PlistBuddy to figure out the UUID
166159 var provProfileUUID : string ;
167160 var plist = tl . which ( '/usr/libexec/PlistBuddy' , true ) ;
168- var plistTool : ToolRunner = tl . createToolRunner ( plist ) ;
169- plistTool . arg ( [ '-c' , 'Print UUID' ] ) ;
170- plistTool . pathArg ( tmpPlist ) ;
161+ var plistTool : ToolRunner = tl . tool ( plist ) ;
162+ plistTool . arg ( [ '-c' , 'Print UUID' , tmpPlist ] ) ;
171163 plistTool . on ( 'stdout' , function ( data ) {
172164 if ( data ) {
173165 provProfileUUID = data . toString ( ) ;
@@ -176,19 +168,16 @@ export async function getProvisioningProfileUUID(provProfilePath: string) {
176168 await plistTool . exec ( ) ;
177169
178170 //delete the temporary plist file
179- var deletePlistCommand : ToolRunner = tl . createToolRunner ( tl . which ( 'rm' , true ) ) ;
180- deletePlistCommand . arg ( '-f' ) ;
181- deletePlistCommand . pathArg ( tmpPlist ) ;
171+ var deletePlistCommand : ToolRunner = tl . tool ( tl . which ( 'rm' , true ) ) ;
172+ deletePlistCommand . arg ( [ '-f' , tmpPlist ] ) ;
182173 await deletePlistCommand . exec ( ) ;
183174
184175 if ( provProfileUUID ) {
185176 //copy the provisioning profile file to ~/Library/MobileDevice/Provisioning Profiles
186177 tl . mkdirP ( userProvisioningProfilesPath ) ; // Path may not exist if Xcode has not been run yet.
187178 var pathToProvProfile : string = getProvisioningProfilePath ( provProfileUUID ) ;
188- var copyProvProfileCmd : ToolRunner = tl . createToolRunner ( tl . which ( 'cp' , true ) ) ;
189- copyProvProfileCmd . arg ( '-f' ) ;
190- copyProvProfileCmd . pathArg ( provProfilePath ) ; //source
191- copyProvProfileCmd . pathArg ( pathToProvProfile ) ; //dest
179+ var copyProvProfileCmd : ToolRunner = tl . tool ( tl . which ( 'cp' , true ) ) ;
180+ copyProvProfileCmd . arg ( [ '-f' , provProfilePath , pathToProvProfile ] ) ;
192181 await copyProvProfileCmd . exec ( ) ;
193182
194183 return provProfileUUID ;
@@ -197,15 +186,103 @@ export async function getProvisioningProfileUUID(provProfilePath: string) {
197186 }
198187}
199188
189+
190+ /**
191+ * Find the type of the provisioning profile - development, app-store or ad-hoc
192+ * @param provProfilePath
193+ * @returns {string } type
194+ */
195+ export async function getProvisioningProfileType ( provProfilePath : string ) {
196+ var provProfileType : string ;
197+ try {
198+ //find the provisioning profile details
199+ var provProfileDetails :string ;
200+ var getProvProfileDetailsCmd :ToolRunner = tl . tool ( tl . which ( 'security' , true ) ) ;
201+ getProvProfileDetailsCmd . arg ( [ 'cms' , '-D' , '-i' , provProfilePath ] ) ;
202+ getProvProfileDetailsCmd . on ( 'stdout' , function ( data ) {
203+ if ( data ) {
204+ if ( provProfileDetails ) {
205+ provProfileDetails = provProfileDetails . concat ( data . toString ( ) . trim ( ) . replace ( / [ , \n \r \f \v ] / gm, '' ) ) ;
206+ } else {
207+ provProfileDetails = data . toString ( ) . trim ( ) . replace ( / [ , \n \r \f \v ] / gm, '' ) ;
208+ }
209+ }
210+ } )
211+ await getProvProfileDetailsCmd . exec ( ) ;
212+
213+ if ( provProfileDetails ) {
214+ //write the provisioning profile to a plist
215+ var tmpPlist = '_xcodetasktmp.plist' ;
216+ fs . writeFileSync ( tmpPlist , provProfileDetails ) ;
217+ } else {
218+ throw tl . loc ( 'ProvProfileDetailsNotFound' , provProfilePath ) ;
219+ }
220+
221+ //get ProvisionsAllDevices - this will exist for enterprise profiles
222+ var provisionsAllDevices : string = await printFromPlist ( 'ProvisionsAllDevices' , tmpPlist ) ;
223+ tl . debug ( 'provisionsAllDevices = ' + provisionsAllDevices ) ;
224+ if ( provisionsAllDevices && provisionsAllDevices . toLowerCase ( ) === 'true' ) {
225+ //ProvisionsAllDevices = true in enterprise profiles
226+ provProfileType = 'enterprise' ;
227+ } else {
228+ var getTaskAllow : string = await printFromPlist ( 'Entitlements:get-task-allow' , tmpPlist ) ;
229+ tl . debug ( 'getTaskAllow = ' + getTaskAllow ) ;
230+ if ( getTaskAllow && getTaskAllow . trim ( ) . toLowerCase ( ) === 'true' ) {
231+ //get-task-allow = true means it is a development profile
232+ provProfileType = 'development' ;
233+ } else {
234+ var provisionedDevices :string = await printFromPlist ( 'ProvisionedDevices' , tmpPlist ) ;
235+ if ( ! provisionedDevices ) {
236+ // no provisioned devices for non-development profile means it is an app-store profile
237+ provProfileType = 'app-store' ;
238+ } else {
239+ // non-development profile with provisioned devices - use ad-hoc
240+ provProfileType = 'ad-hoc' ;
241+ }
242+ }
243+ }
244+
245+ //delete the temporary plist file
246+ var deletePlistCommand :ToolRunner = tl . tool ( tl . which ( 'rm' , true ) ) ;
247+ deletePlistCommand . arg ( [ '-f' , tmpPlist ] ) ;
248+ await deletePlistCommand . exec ( ) ;
249+ } catch ( err ) {
250+ tl . debug ( err ) ;
251+ }
252+
253+ return provProfileType ;
254+ }
255+
256+ async function printFromPlist ( itemToPrint : string , plistPath : string ) {
257+ var plist = tl . which ( '/usr/libexec/PlistBuddy' , true ) ;
258+ var plistTool :ToolRunner = tl . tool ( plist ) ;
259+ plistTool . arg ( [ '-c' , 'Print ' + itemToPrint , plistPath ] ) ;
260+
261+ var printedValue : string ;
262+ plistTool . on ( 'stdout' , function ( data ) {
263+ if ( data ) {
264+ printedValue = data . toString ( ) ;
265+ }
266+ } ) ;
267+
268+ try {
269+ await plistTool . exec ( ) ;
270+ } catch ( err ) {
271+ tl . debug ( 'Exception when looking for ' + itemToPrint + ' in plist.' ) ;
272+ printedValue = null ;
273+ }
274+
275+ return printedValue ;
276+ }
277+
200278/**
201279 * Delete specified iOS keychain
202280 * @param keychainPath
203281 */
204282export async function deleteKeychain ( keychainPath : string ) {
205283 if ( fs . existsSync ( keychainPath ) ) {
206- var deleteKeychainCommand : ToolRunner = tl . createToolRunner ( tl . which ( 'security' , true ) ) ;
207- deleteKeychainCommand . arg ( 'delete-keychain' ) ;
208- deleteKeychainCommand . pathArg ( keychainPath ) ;
284+ var deleteKeychainCommand : ToolRunner = tl . tool ( tl . which ( 'security' , true ) ) ;
285+ deleteKeychainCommand . arg ( [ 'delete-keychain' , keychainPath ] ) ;
209286 await deleteKeychainCommand . exec ( ) ;
210287 }
211288}
@@ -217,9 +294,8 @@ export async function deleteKeychain(keychainPath: string) {
217294 */
218295export async function unlockKeychain ( keychainPath : string , keychainPwd : string ) {
219296 //unlock the keychain
220- var unlockCommand : ToolRunner = tl . createToolRunner ( tl . which ( 'security' , true ) ) ;
221- unlockCommand . arg ( [ 'unlock-keychain' , '-p' , keychainPwd ] ) ;
222- unlockCommand . pathArg ( keychainPath ) ;
297+ var unlockCommand : ToolRunner = tl . tool ( tl . which ( 'security' , true ) ) ;
298+ unlockCommand . arg ( [ 'unlock-keychain' , '-p' , keychainPwd , keychainPath ] ) ;
223299 await unlockCommand . exec ( ) ;
224300}
225301
@@ -233,23 +309,22 @@ export async function deleteProvisioningProfile(uuid: string) {
233309 if ( fs . existsSync ( provProfilePath ) ) {
234310 tl . warning ( 'Deleting provisioning profile: ' + provProfilePath ) ;
235311
236- var deleteProfileCommand : ToolRunner = tl . createToolRunner ( tl . which ( 'rm' , true ) ) ;
237- deleteProfileCommand . arg ( '-f' ) ;
238- deleteProfileCommand . pathArg ( provProfilePath ) ;
312+ var deleteProfileCommand : ToolRunner = tl . tool ( tl . which ( 'rm' , true ) ) ;
313+ deleteProfileCommand . arg ( [ '-f' , provProfilePath ] ) ;
239314 await deleteProfileCommand . exec ( ) ;
240315 }
241316}
242317
243318function getProvisioningProfilePath ( uuid : string ) : string {
244- return path . join ( userProvisioningProfilesPath , uuid . trim ( ) . concat ( '.mobileprovision' ) ) ;
319+ return tl . resolve ( userProvisioningProfilesPath , uuid . trim ( ) . concat ( '.mobileprovision' ) ) ;
245320}
246321
247322/**
248323 * Gets the path to the iOS default keychain
249324 */
250325export async function getDefaultKeychainPath ( ) {
251326 var defaultKeychainPath : string ;
252- var getKeychainCmd : ToolRunner = tl . createToolRunner ( tl . which ( 'security' , true ) ) ;
327+ var getKeychainCmd : ToolRunner = tl . tool ( tl . which ( 'security' , true ) ) ;
253328 getKeychainCmd . arg ( 'default-keychain' ) ;
254329 getKeychainCmd . on ( 'stdout' , function ( data ) {
255330 if ( data ) {
0 commit comments