9

So, I'm already familiar with this:
http://svnbook.red-bean.com/en/1.5/svn.advanced.vendorbr.html

My question is how do you handle a vendor branch that has both a stable release and an alpha/beta branch that you want to integrate?

So, say you follow the original example from the SVN book. You'd have:

svn://localhost/home/svn/vendor/libcomplex/current
svn://localhost/home/svn/vendor/libcomplex/1.0
svn://localhost/home/svn/vendor/libcomplex/1.1 (same as current)

Now, say you have two versions of your own 'calc' app:

calc (this is essentially trunk == calc 2.0)
calc-1.0 (released to public)

Let's say calc-1.0 uses libcomplex 1.0 and calc (in trunk) used libcomplex 1.1, which is still being developed.

There's a bug in libcomplex 1.0 and a new version is released to fix that bug: libcomplex 1.0.1. The libcomplex maintainers have also included this bugfix into libcomplex 1.1.

You're not ready to release calc 2.0, so you need to integrate libcomplex 1.0.1 into your vendor branch and then update calc-1.0 to make a bug-fix release.

Where does it go?

You can't put it at svn://localhost/home/svn/vendor/libcomplex/current because 1.1 currently lives there.

Do you copy svn://localhost/home/svn/vendor/libcomplex/1.0 to svn://localhost/home/svn/vendor/libcomplex/1.0.1 and then bring in the new release? That way you could use svn to merge the diff between 1.0 and 1.0.1 to calc-1.0.

3 Answers3

3

The recommended practice is to create a branch for your release. That way, it doesn't matter what changes you make in trunk to your vendor folders. You can then update the 1.0 release branch with the 1.0.1 version of libcomplex, and that would not have affected trunk (calc 2.0).

This won't work if calc 1.0 and calc 2.0 live side by side in the same branch however.

The next thing to do is to not have "current". Just refer directly to the version that you are using. eg, leave your folder structure as:

vendor/libcomplex/1.0
vendor/libcomplex/1.1
vendor/libcomplex/1.0.1

and never overwrite these files. Then calc 2.0 can refer to version 1.1 of libcomplex, and calc 1.0 can refer to 1.0.1.

Your last option, (and not really recommended), is to use svn tags (see complex tags). They allow you to mix and match versions, so you could technically create a tag to represent the patch release of your calc 1.0 with the old version of libcomplex.

Nader Shirazie
  • 10,736
  • 2
  • 37
  • 43
  • In my previous example, I do have a branch for my release: calc 1.0. The vendor folders aren't contained under calc. Are you suggesting that /vendor be branched as well? To be clear here is the example I'm describing: /vendor/libcomplex/ /calc/trunk/ /calc/branches/1.0/ Your suggestion to not use "current" and just use the folder structures won't properly allow for merging changes between versions into trunk, thus defeating the purpose. You need this change history to allow for merging changes into trunk where you have modified the original vendor source. – Amir Ebrahimi Aug 18 '09 at 16:55
  • My approach is for works when all you're doing is using released versions. If you're also modifying the source, then may be useful to treat the vendor code as your own code (ie include it in your trunk branch rather than have vendor as a separate folder). However your approach makes sense as well. Create the vendor/libcomplex/1.0.1 branch, merge any customisations, and update the calc 1.0 release to point to vendor/libcomplex/1.0.1, then release calc 1.0.1. Whenever libcomplex 1.1 is ready, merge customisations, build calc2.0, and you're good to go. Trunk never points to 1.0.1 – Nader Shirazie Aug 19 '09 at 01:13
2

The idea behind vendor branches seems to be that they should reflect what the vendor's own repository might look like. So, current represents the vendor's trunk, and the tagged versions represent the vendor's own tags, created when each version is released.

Given this, the answer to the question becomes fairly clear. In order to have released 1.0, 1.1 and then 1.0.1, the vendor presumably has a branch for 1.0.x bugfixed versions while continuing to work on 1.1 and later versions on their trunk. Our vendor branch should mirror this setup.

That is, we also need a branch (within our vendor branch) for 1.0.x bugfixed versions. This should be created from current at the time when it contained 1.0, and may be named something like current-1.0.x. This branch can then be updated to hold 1.0.1, which can then be tagged and copied into our own tree as usual.

user200783
  • 13,722
  • 12
  • 69
  • 135
2

I work like this with external libraries:

project/myProject/{branches,trunk}
vendor/libcomplex/1.0 
vendor/libcomplex/1.0.1
vendor/libcomplex/2.0.0
mypatched-vendor/libcomplex/1.0
mypatched-vendor/libcomplex/1.0.1
mypatched-vendor/libcomplex/2.0.0

Where vendor/<lib>/<version> is never changed after import and mypatched-vendor is started with svn cp vendor/<lib>/<version> mypatched-vendor/<lib>/<version>.

Now diffing vendor/libcomplex/1.0 mypatched-vendor/libcomplex/1.0 should give you patches to be merged to the just imported 1.0.1 version.

I'm probably in the minority, but I like svn:externals properties. Quite many IDEs don't like them so use with discretion. The reason is this. I can now edit my main project:

checkout project/myProject/trunk to myprj-trunk in you check out run.

svn propedit svn:externals .
# with
libcomplex  URLTO/mypatched-vendor/libcomplex/1.0

When I want to test a new lib version I simply edit that property to another place and run update. This has also the effect that I don't accidentally commit anything to libcomplex part of the tree even if I've change some files on WC. I have to be under that directory or specially commit changes there.

Now upgrading, fixes, branches of my project are easily moved to new libcomplex versions without more than the initial merge to mypathed-vendor. All my project branches only need propchange and testing. Also it's relatively easy to get library dependencies for my projects IMHO.

The last nice thing about externals is that when starting a new project and upstream is also heavily developed and uses svn you can reference upstream as external if you don't need to patch that library. And when upstream breaks your project you can hold upstream version for a while with -rNUM options like:

libcomplex -r21 UPSTREAMURLTO/mypatched-vendor/libcomplex/trunk

One definite drawback to svn:externals is that the externals url has to be accessible with the same URI from all checkout variants of your project.

But using externals allows your to keep vendor repo separate from your project repo.

Manwe
  • 401
  • 2
  • 11