As an example, the XNA and System Testing snake simulation was scaled to demonstrate SVN Externals.
However, all code here is in trunk; larger scale development requires release tags and feature branches. Let's check it out!
Pre Requisites
This post assumes you already have Tortoise SVN installed on Windows and svnx installed on Mac OS/X.
Also, consider configuring the $SVN_EDITOR on Windows and Mac OS/X in order to edit SVN properties:
set SVN_EDITOR=notepad.exe ; Windows PC export SVN_EDITOR=vi ; Mac OS/XConventions
This post uses the following convention to substitute "$DEMO" for root node of all demo code samples:
$DEMO = https://svn/Demo ; Subversion $DEMO = C:\svn\Demo ; Windows PC $DEMO = /svn/Demo ; Mac OS/X
Subversion
Create top level Demo node in Subversion SVN. Add 1x sub-node for XNA library and 4x sub-nodes for each client: WP7, Windows, Android, iOS. Ensure all sub-nodes have branches, tags and trunk folders:
Alias | Platform | Development | Framework | Description | Source Code |
XNA | Windows PC | Visual Studio 2010 | XNA 4.0 | Game library | Download |
WP7 | Windows PC | Visual Studio 2010 | XNA 4.0 | Game client | Download |
Win | Windows PC | Visual Studio 2012 | MonoGame 3.4 | Game client | Download |
And | Mac OS/X | Xamarin Studio | MonoGame 3.5 | Game client | Download |
iOS | Mac OS/X | Xamarin Studio | MonoGame 3.5 | Game client | Download |
Tagging
Before beginning new development, it's often best practice to tag your current release build from trunk.
Note: when you create a tag in Subversion, you are not tagging the SVN Externals repository, you are tagging your working copy. If you do not specify the revision then SVN Update will always get latest!
Therefore, you should always explicitly set the revision of svn:externals property when you create a tag:
svn propset svn:externals 'Common -r2276 $DEMO/XNA/trunk/XNA.Common' .
If you have Tortoise SVN 1.9.4 installed then you can use the new --pin-externals option for svn copy. This will automatically set the SVN revision in the tag for you without manual lookup in the SVN logs.
svn copy --pin-externals svn:externals $DEMO/trunk $DEMO/tags/1.0.0.0 -m "1.0.0.0"
For completeness, here are all TAGS 1.0.0.0 cut from previous SVN Externals Application blog post:
Alias | Command |
XNA | svn copy --pin-externals $DEMO/XNA/trunk $DEMO/XNA/tags/1.0.0.0-XNA -m "1.0.0.0-XNA" |
WP7 | svn copy --pin-externals $DEMO/WP7/trunk $DEMO/WP7/tags/1.0.0.0-WP7 -m "1.0.0.0-WP7" |
Win | svn copy --pin-externals $DEMO/Win/trunk $DEMO/Win/tags/1.0.0.0-XNA -m "1.0.0.0-Win" |
And | svn copy --pin-externals $DEMO/And/trunk $DEMO/And/tags/1.0.0.0-And -m "1.0.0.0-And" |
iOS | svn copy --pin-externals $DEMO/iOS/trunk $DEMO/iOS/tags/1.0.0.0-iOS -m "1.0.0.0-iOS" |
SVN Upgrade
On Mac OS/X it is most likely that you cannot use the new --pin-externals option for svn copy as the svn version is too low. Here are some basic instructions to upgrade to, for example, SVN 1.8 on Mac OS/X.
However, upgrading may cause svnx incompatibility. Also, higher versions may require an upgrade to serf. A better approach may be to cut all tags on Windows PC and SVN Update all tags on Mac OS/X.
Branching
Larger features usually require longer development time and it's often best practice to cut feature branch from trunk. Applying SVN Externals to branching and merging back into trunk may result in a similar flow:
1. Cut branches: XNA library and Win client (and other clients)
2. Update SVN Externals in Win client to XNA branch (not trunk)
3. Make all code feature changes in XNA library and Win client
4. Merge XNA library [trunk down to branch + branch up to trunk]
5. Merge Win client [trunk down to branch + branch up to trunk]
6. Delete dead branches cut from above accordingly
Implementation
1. Cut branches: XNA library and Win client (and other clients)
svn copy $DEMO/XNA/trunk $DEMO/XNA/branches/FeatureX -m "FeatureX" svn copy $DEMO/Win/trunk $DEMO/Win/branches/FeatureX -m "FeatureX"
2. Update SVN Externals in Win client to XNA branch (not trunk)
Launch command prompt, navigate to $DEMO\Win\branches\FeatureX\$FOLDER where $FOLDER is the parent folder that hosts Windows Game project. Common branched XNA library code will be linked here.
cd $DEMO/Win/branches/FeatureX svn propget -R svn:externals cd $FOLDER svn propedit svn:externals .Edit SVN Externals Subversion Properties from previous to current:
Previous | Current |
$DEMO/XNA/trunk/XNA.Common Common | $DEMO/XNA/branches/FeatureX/XNA.Common Common |
svn update svn commit -m "Update branch"
3. Make all code feature changes in XNA library and Win client
After making all code changes to feature branch, ensure you increment the build number for next release. Navigate to game client AssemblyInfo.cs file. Increment AssemblyVersion + AssemblyFileVersion values:
For example increment version from previous "1.0.0.0" to current "1.1.0.0"
Platform | File | Property |
Android | AndroidManifest.xml | Increment Version number |
iOS | Info.plist | Increment Version |
4. Merge XNA library [trunk down to branch + branch up to trunk]
First, merge trunk down to branch (as changes may have been checked-in on trunk prior to the merge)
cd $DEMO/XNA/branches/FeatureX svn update svn merge $DEMO/XNA/trunk svn commit -m "Merge trunk down to branch"
Next, merge branch up to trunk to (re-)integrate changes from shared XNA library to all upstream clients
cd $DEMO/XNA/trunk svn update svn merge --reintegrate $DEMO/XNA/branches/FeatureX svn commit -m "Merge branch up to trunk"
5. Merge Win client [trunk down to branch + branch up to trunk]
Important: first revert SVN Externals in Win client to XNA trunk as XNA trunk and branch are now synch'd
cd $DEMO/Win/branches/FeatureX svn propget -R svn:externals cd $FOLDER svn propedit svn:externals .Edit SVN Externals Subversion Properties from previous to current:
Previous | Current |
$DEMO/XNA/branches/FeatureX/XNA.Common Common | $DEMO/XNA/trunk/XNA.Common Common |
svn update svn commit -m "Revert branch"
Next, merge trunk down to branch
cd $DEMO/Win/branches/FeatureX svn update svn merge $DEMO/Win/trunk svn commit -m "Merge trunk down to branch"
Finally, merge branch up to trunk
cd $DEMO/Win/trunk svn update svn merge --reintegrate $DEMO/Win/branches/FeatureX svn commit -m "Merge branch up to trunk"
6. Delete dead branches cut from above accordingly
svn delete $DEMO/XNA/branches/FeatureX -m "Delete branch" svn delete $DEMO/Win/branches/FeatureX -m "Delete branch"
For completeness, here is one way to remove the SVN Externals property from working copy folder:
svn propdel svn:externals $DEMO/Win/branches/FeatureX/$FOLDER
Tagging
When it is appropriate, tag the new build as per updated build version number 1.1.0.0 from above:
Alias | Command |
XNA | svn copy --pin-externals $DEMO/XNA/trunk $DEMO/XNA/tags/1.1.0.0-XNA -m "1.1.0.0-XNA" |
WP7 | svn copy --pin-externals $DEMO/WP7/trunk $DEMO/WP7/tags/1.1.0.0-WP7 -m "1.1.0.0-WP7" |
Win | svn copy --pin-externals $DEMO/Win/trunk $DEMO/Win/tags/1.1.0.0-XNA -m "1.1.0.0-Win" |
And | svn copy --pin-externals $DEMO/And/trunk $DEMO/And/tags/1.1.0.0-And -m "1.1.0.0-And" |
iOS | svn copy --pin-externals $DEMO/iOS/trunk $DEMO/iOS/tags/1.1.0.0-iOS -m "1.1.0.0-iOS" |
Summary
To summarize, here code has been shared from a single external library across multiple game clients; However, SVN Externals could be used to scale out shared data + content across multiple clients too!