When I was using Subversion for version control in working on my Mac apps in Xcode, I had come to use a build script phase to tack on the subversion revision number as the last part to the version number:
-
REV=`svnversion -n "${PROJECT_DIR}"`
-
REV=${REV/#[0-9]*:/}
-
REV=${REV//[^0-9]/}
-
BASE=`/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "${PROJECT_DIR}/Info.plist"`
-
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $BASE.$REV" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
This takes the CFBundleVersion from the project’s Info.plist, adds a period and the subversion revision number, and injects that into the Info.plist of the built product.
When I made the move to Mercurial, I couldn’t quite do this anymore. While subversion revision numbers are monotone increasing and consistent everywhere (they are the unique identifiers of a particular version), Mercurial’s “revision numbers” are local to a particular instance of the repository and may not match up from one instance to another. Mercurial uses a hash as the unique identifier of a particular version, and these hexadecimal hashes are not monotone, making them unsuitable for use in CFBundleVersion.
Though it took some time, I’ve finally come to a system with Mercurial that I think is workable:
-
HG_LAST_TAG_TIMESTAMP=$(/usr/local/bin/hg log -r "$(/usr/local/bin/hg log -r '.' –template '{latesttag}' –repository "${PROJECT_DIR}|>")" –template "{date|hgdate}\n" –repository "${PROJECT_DIR}" | cut -f1 -d' ')
-
HG_TIP_TIMESTAMP=$(/usr/local/bin/hg log -r '.' –template "{date|hgdate}\n" –repository "${PROJECT_DIR}" | cut -f1 -d' ')
-
REV=$(( ($HG_TIP_TIMESTAMP – $HG_LAST_TAG_TIMESTAMP) / 60 ))
-
BASE=`/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "${PROJECT_DIR}/Info.plist"`
-
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $BASE.$REV" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
This calculates the number of minutes between the most recent tagged ancestor of the tip and the tip itself and adds that to the CFBundleVersion. Because it’s time-based, it is guaranteed to be monotone increasing, consistent, and unique (well, provided multiple commits don’t happen within a 1-minute span, which is safe for me).