In a previous article, I discussed with you how I might deal with the challenge of maintaining two separate but similar web sites in a Mercurial source control system. These sites don’t really follow the Version->Maintenance->Next Version linear development process. Instead, they have common code and separate themes. I mentioned three options for dealing with this issue:
- Let’s say it’s only a few files that are different – what then? Perhaps the easiest way of handling this situation is to just maintain the second set of files in the same database. No need for branching!
- But what if I have a good portion of files that will need to differ? Say 100 or more? What then? The best option in that scenario would probably be to split the differing “theme” files out of the database completely using its Convert extension. Then I’d end up with three databases: the common code and two sets of differing “theme” code, one each for Site A and Site B. The upside is that future maintenance is painless and a big bonus is that creating a third site will be a breeze. The downside is that you need to know in advance what the differing code will be and, more importantly, you’ll have to rewrite much of the common code to allow for different entry points, parameters and scenarios. This is the most time consuming of our options but also the best option for future code stability.
- Finally, if you believe that the common code will change infrequently, you can avoid site merges and instead use the hg export and import commands to merge only certain transactions to the other branch. This last choice may seem the most expedient – especially if you’ll have many small differences in the common code – but it’s also the most error prone. Should another developer accidentally do a push and merge, you’d better know how to recover from it.
Today, I’m going to discuss the second case – how to use the Mercurial Convert extension to split an existing repository.
The Convert extension was originally designed to convert other SCM databases (ie: Subversion) into Mercurial databases. But you can also use it to split an existing Mercurial database.
First things first, you need to enable the Convert extension by adding this line to the [extensions] section of your .hgrc:
hgext.convert=
Next, you need to inspect your current database and decide how it should be split. Let’s say the root of your current repository looked something like this:
index.php libraries common.so look.so feel.so common common1.php common2.php theme look.php feel.php
In our scenario, the new common code repository should include index.php, the common.so library under libraries and the common directory.
Our new “theme” code repository should include everything else – basically, all files with the words “look” or “feel” in them.
The convert utility doesn’t actually make any changes to the original database. It just copies information out of it. When we’re finished, we’ll have three databases: the unchanged original, a new common database and a new theme database.
First, change diretories to the original repository’s parent:
# cd ..
To use the Convert extension, we need to indicate a text file which tells the converter which files to include in the new repository. This is called a “file map”. In it, use the “include” and “exclude” directives to indicate which files should be copied to the new repository. In our scenario, we’ll create two file maps. The first will be called common_filemap.txt and will look like this:
include index.php exclude libraries include libraries/common.so include common exclude theme
The second file will be called theme_filemap.txt and look like this:
include libraries/look.so include libraries/feel.so include theme
Now we run the conversion tool again the original repository with the name of the new repository:
# hg convert --filemap common_filemap.txt original_repo new_common_repo
# hg convert --filemap common_filemap.txt original_repo new_theme_repo
Voila! You now have three databases: the original unchanged “original_repo”, the new common code repository “new_common_repo” and the new theme code repository “new_theme_repo”. Now that the job is finished, we can archive the original repository and start using the new ones.
The third article in this series will show you another approach to maintaining similar yet differing code. Stay tuned!
