Problems using branches in monotone
This is a step by step example of the problems which arise from the way monotone serves branches. Most of these problems come down to the fact that monotone does not serve (accept or receive) revisions unless they carry a certificate for a branch within the collection the server serves. Unfortunately it is very easy to create a branch within the collection which contains revisions "from" branches outside the collection.
A simple example
In this example bar.org is an organisation which produces software licensed under the GPL. The software is therefore freely available and may be modified and incorporated into other products. foo.com is a company which does just this - it takes the BAR development framework and modifies it in ways specific to the products foo.com produces.
Both bar.org and foo.com use monotone to maintain and to publish their source. Remember that the source is GPL, so they have to publish it, but they don't have the time to invest a whole lot of effort in this. monotone seems ideal. The (published) bar.org branch is bar.org.dev.
Initially Mr Foo of foo.com doesn't much expect to fold any changes back into the bar.org and he knows that the changes he's making are much more than bug fixes. Mr Foo does, however, need to track bar.org.dev - it's a work in progress. What is more he can't publish his changes as the branch bar.org.dev - that would lead to confusion and disaster. He could create bar.org.dev.bar, but partying on the bar.org namespace seems impolite at best. Consequently he creates the branch com.foo.foobar.
The problems start as soon as he creates this branch...
Initial development in bar.org
This story is told as a shell script - these commands can be copied into a bash shell and run. This will recreate the databases involved and demonstrate the problems.
Mr Bar of bar.org does the initial development of BAR:
Mr Bar has completed his development, at this point he edits the bar.org monotonerc to allow anonymous read access and starts up a monotone server to release BAR to the world:
Mr Foo's branch development
Mr Foo learns about BAR and decides to use it for his own companies products. He finds it does a lot but a lot more needs to be done.
Mr Foo has completed his development and tested the result. He releases the product and also puts up a monotone server to satisfy the GPL requirements:
An unpleasant user experience
firstname.lastname@example.org finds out about FoobAR? and, after discovering the product is released under the GPL, goes to seek out the source. Mr Foo's web site directs him to the monotone server. Joe attempts to download the source:
Joe sees something like this:
But list branches does not list anything.
Problem 1: remotely served branches don't work
Joe spends several days ;-) trying to work out why the monotone pull outputs nice hopeful messages about getting data yet fails to list any branches. Eventually, after Mr Bar has spent some time trying to work out what is going on, Mr Bar realises that his server isn't serving the base revisions which were in org.bar.dev.
So he tells Joe to get the base from foo.org - Mr Bar does not want to serve up what he knows to be an out-of-date revision of org.foo.dev:
This is annoying, but hardly a show stopper. People who wish to see the GPL source of FoobAR? must first download the GPL source of BAR. (And it must be first - even though com.foo.foobar was successfully downloaded before org.bar.dev the list branches after the org.bar.dev pull shows only org.bar.dev.)
Mr Foo continues work
Unfortunately at this point Mr Foo realises that v2 is not going to work without some major bugfixes in BAR. He talks to Mr Bar and Mr Bar makes the required changes:
Joe attempts to update to v2
This appears to have worked:
Notice, however, that the changes do not include anything after Mr Foo pulled the changes from the latest BAR into his branch.
Problem 2: a pull may fail partially without error or warning
It's very difficult for Joe to know that the apparently updated tree is missing important changes. Eventually Joe might work it out but if, on the way there, he happens to pull the latest changes from bar.org the problem may well mysteriously disappear.
The problem here is that monotone pull is failing to indicate the failure. Despite this it leaves Joe's database with a error state:
This actually makes things worse - it looks like something has gone wrong and caused database damage. After both pulls (org.bar.dev then com.foo.foobar) have completed the problem goes away:
Mr Foo and Mr Bar decide to cooperate
At this point Mr Foo and Mr Bar decide to fold the com.foo.foobar branch back in to the BAR main line of development. Mr Bar pulls Mr Foo's code and manages the merge:
That was easy - no merge was necessary.
Mr Foo syncs up his database too:
Joe updates too - no problems, in fact at this point all three working trees are identical (apart from the
Both Mr Foo and Mr Bar are very happy at this point with monotone. Unfortunately this is about to change, very drastically.
The new user
Jane is a regular BAR user, uninterested in the foo.com company:
This looks fine, but the working copy only contains the changes up to the point where the foo.com changes were merged back in. Jane can "fix" this by pulling the foobar changes from foo.com, but in general each pull only moves up the revision tree to the extent permitted by revisions in that server.
Problem 3: mixing branches from different servers makes pulls increasingly difficult.
In the limit every single revision might require a separate pull from a separate server. NOTE: this may be wrong, it may just require one pull from every involved server. Worse, there is no way to know which server contains the next revision, because that information is not revealed by the logs even with --debug!
Mr Bar has suddenly found himself with an unintended support headache. If he had known this would happen we would never have used monotone to merge Mr Foo's changes back in - he would have just copied and pasted the changed files. In desparation Mr Bar tries:
This does work - it simply means the server serves all the branches in the database.
This is probably what will happen with the current system - every monotone server will serve all the branches it contatins. Truely separate developments will be in separate databases. This seems highly undesireable.
A suggested solution
There are a number of ways of solving these problems. The simplest, however, would seem to be to complete the closure on a collection, so that the heads of all the branches in the collection plus all their ancestors are served regardless of the branch certificate on an individual revision.
An obvious extension is to permit particular revisions to be served or to allow a branch to be served without it's derived branches - for example com.foo.foobar but not com.foo.foobar.unstable.
This is, perhaps, a suggestion to change the underlying model - serve one or more revisions - which means the given revisions plus all revisions necessary to build them. This would allow a server to serve disjoint sets of branches - for example com.foo.foobar and com.foo.footools without serving everything named com.foo.*
The real world example
The actual databases which led to discovery of these problems are somewhat larger - the monotone database file is about 30MByte (and apparently growing quite rapidly). The original branch was org.openembedded.dev in the OpenEmbedded monotone database. The separate development branch was org.nslu2-linux.openembedded. After the base problem was encountered the latter was changed to org.openembedded.nslu2-linux, however the databases still show the original contents.
monotone --db=local-oe.db pull ewi546.ewi.utwente.nl org
monotone --db=local-nslu2.db pull mtn.nslu2-linux.org org
At present both database serves serve org, and both databases contain most of the same revisions.
monotone version information