Open up the Info.plist file and add two properties with keys GitShaHash, and GitState. These values will be overwritten during the build process. I have seen similar scripts that work by storing the hash in CFBundleVersion instead. However, OS X uses CFBundleVersion to compare versions of the same app, and the Mac App Store also requires updates to have a sequential CFBundleVersion. Since the git hash is not sequential, it's better to just leave CFBundleVersion alone and relegate it to an under the hood value.
Select the project target, and add a run script build phase:
Copy and paste the script in. This is a perl scrip so the shell must be set to /usr/bin/perl . Note that the line “my $INFO …” is set for Mac app bundles, you can switch the commented lines around for iOS apps.
use strict; use warnings; die "$0: Must be run from Xcode" unless $ENV{"BUILT_PRODUCTS_DIR"}; my $FH; my $output; # SHA hash : open $FH, "xcrun git rev-parse HEAD|" or die; $output = <$FH>; close($FH); chomp( $output ); my $gitShaHash = $output; # clean state : $output = `xcrun git status`; my $gitState; if ( index( $output, "nothing to commit (working directory clean)" ) != -1 ) { $gitState = "clean"; } else { $gitState = "dirty"; } print "gitShaHash : $gitShaHash\n"; print "gitState : $gitState"; # Update Info.plist in build product. Use defaults command #my $INFO = "$ENV{BUILT_PRODUCTS_DIR}/$ENV{WRAPPER_NAME}/Info"; #iOS my $INFO = "$ENV{BUILT_PRODUCTS_DIR}/$ENV{WRAPPER_NAME}/Contents/Info"; #OSX my @defaults = ( 'defaults', 'write', $INFO, 'GitShaHash', "$gitShaHash" ); system( @defaults ); @defaults = ( 'defaults', 'write', $INFO, 'GitState', "$gitState" ); system( @defaults );
All done, now the values will be generated every time you build and the values can be accessed easily from the Info.plist using code:
NSURL *url = [[[NSBundle mainBundle] bundleURL] URLByAppendingPathComponent:@"Contents/Info.plist"]; NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:url]; NSString *hash = [dictionary objectForKey:@"GitShaHash"]; NSString *state = [dictionary objectForKey:@"GitState"];
It’s a good idea to place the values within the about panel or a similar location. The hash can make it easier to track issues with beta testers. And the git state makes it easier to prevent dirty builds from being distributed.