Rabu, 01 April 2009

Automated Commit and Build Number Incrementing

For some projects, I like to commit and increment my build number every time I compile. Not every project, but on some. In other cases, I only want to automatically commit and increment the build number when I do a Release configuration build.

Apple provides a tool called agvtool which stands for Apple Generic Versioning Tool. But, you generally don't want to use it while you have an Xcode project open, so incorporating it into a run script build phase is not advised.

I've found a few examples on the internet of scripts that incorporate the Subversion build number, but they didn't quite fit my needs. The ones I found were written in Perl and Python, and I'm not particularly comfortable in either of those languages, so I decided to write my own in Ruby, with which I have a much higher comfort level, rather than tweak those existing ones to meet my needs.

This script does not utilize the versioning system built-into Xcode, but rather directly sets the Bundle Version based on the Subversion version number. It also does a commit if there have been any changes since the last build before grabbing the version number from Subversion.

To use this script, right-click on your Target where you want to use this and select Add->New Build Phase->New Run Script Build Phase.

When the window opens up, set the Shell to
/usr/bin/ruby
and then paste the following script into the window if you want to commit and increment on every build:

def get_file_as_string(filename)
data = ''
f = File.open(filename, "r")
f.each_line do |line|
data += line
end
return data
end

# commit if any changes
%x[svn -m 'automated build commit' commit]

svn_version = %x[svnversion -n]
parts = svn_version.split(":")
new_version = parts[1]

# Figure out where the Info.plist file is
project_dir = ENV['PROJECT_DIR']
infoplist_file = ENV['INFOPLIST_FILE']
plist_filename = "#{project_dir}/#{infoplist_file}"
infoplist = get_file_as_string("/Users/jeff/dev/FlyPaper/Resources/Info.plist")
start_of_key = infoplist.index("CFBundleVersion")
start_of_value = infoplist.index("<string>", start_of_key)
end_of_value = infoplist.index("</string>", start_of_value) + "</string>".length
old_value = infoplist[start_of_value, end_of_value - start_of_value]

new_key = "<string>#{new_version}</string>"
new_info_plist = "#{infoplist[0, start_of_value]}#{new_key}\n#{infoplist[end_of_value+1, infoplist.length - (end_of_value+1)]}"

File.open(plist_filename, 'w') {|f| f.write(new_info_plist) }


or use this script if you only want to commit and increment the build number on builds using the Release configuration:

def get_file_as_string(filename)
data = ''
f = File.open(filename, "r")
f.each_line do |line|
data += line
end
return data
end

if ENV['BUILD_STYLE'] == "Release"
# commit if any changes
%x[svn -m 'automated build commit' commit]
end

svn_version = %x[svnversion -n]
parts = svn_version.split(":")
new_version = parts[1]

# Figure out where the Info.plist file is
project_dir = ENV['PROJECT_DIR']
infoplist_file = ENV['INFOPLIST_FILE']
plist_filename = "#{project_dir}/#{infoplist_file}"
infoplist = get_file_as_string("/Users/jeff/dev/FlyPaper/Resources/Info.plist")
start_of_key = infoplist.index("CFBundleVersion")
start_of_value = infoplist.index("<string>", start_of_key)
end_of_value = infoplist.index("</string>", start_of_value) + "</string>".length
old_value = infoplist[start_of_value, end_of_value - start_of_value]

new_key = "<string>#{new_version}</string>"
new_info_plist = "#{infoplist[0, start_of_value]}#{new_key}\n#{infoplist[end_of_value+1, infoplist.length - (end_of_value+1)]}"

File.open(plist_filename, 'w') {|f| f.write(new_info_plist) }


After you paste it in, close the window. You might want to rename the run script build phase to something more meaningful. You can do that by right-clicking on it and selecting Rename from the menu that pops up. Also, you need to drag the new build phase up so that it fires before the Copy Bundle Resources phase so that the commit happens before it builds the application. Otherwise, the application will always reflect the previous version number in the Get Info window.

That's all you have to do. Now, whenever you build or do a Release build, Xcode will commit your files to the Subversion repository if there have been changes, then set the bundle version to the value currently in Subversion. Now, this script has not been extensively tested. If you have problems, let me know about them, and I will try to fix any issues that arise.

0 komentar:

Posting Komentar

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Lady Gaga, Salman Khan