views:

257

answers:

5

Hi,

What I have

I have a C++ code base and svn is used for VCS.

My code uses several 3rd party products. We use different version of each product and use it on different OS (Linux and Windows).

The 3rd products (with the required version) are present in on compilation machines and are used at compilation time, so the relationship between code and the used 3rd party version is loosely coupled.

What I want

I want to change the situation. The idea is to utilize svn vendor branch. In contrast to what described in svn vendor branch, we will store binary version of 3rd party product and not code itself. This is since we never patch 3rd party code.

svn:external will be used to use an appropriate version of 3rd party product. Here a skeleton of svn repository:

svn_repo/vendor/product1/OS1/ver1 <- mymodule using it
         vendor/product1/OS2/ver1 <- mymodule using it
         vendor/product1/OS1/ver2
         vendor/product1/OS1/ver2

         vendor/product2/OS1/ver1
         vendor/product2/OS2/ver1
         vendor/product2/OS1/ver2 <- mymodule using it
         vendor/product2/OS1/ver2 <- mymodule using it

         mymodule/   <- this is my actual code referring to a particular 
                        products from vendor/ using svn:external
         mymodule/vendor/product1/OS1   <- reference to vendor/product1/OS1/ver1
         mymodule/vendor/product1/OS2   <- reference to vendor/product1/OS2/ver1
         mymodule/vendor/product2/OS1   <- reference to vendor/product1/OS1/ver2
         mymodule/vendor/product3/OS2   <- reference to vendor/product1/OS2/ver2

Question

In svn red book in vendor branch chapter, it is proposed to maintain a current/ containing the latest release of 3rd party product, so from the example we end up with:

   repos/vendor/libcomplex/current - contains 1.1
   repos/vendor/libcomplex/1.0
   repos/vendor/libcomplex/1.1

Since we don't patch 3rd party code I don't see any point to maintain current/. This looks too have to maintain it, therefore you can see that svn is supplied with auxiliary perl script *svn_load_dirs.pl* to aid.

My guess current/ is required to:

  1. To make different versions svn releted and then svn comparable.
  2. As a side the version are stored in more efficient way in svn repository.

I don't see we really need those.

So the question is if we can safely bypass handling of current/ in vendor branch?

Thanks

+2  A: 

I would say this is alright. This is a common situation with third-party libraries, where you often don't have, or want to maintain, the source code. It is perfectly acceptable in this case to store the version of the binary you want instead, since from the perspective of your product, that is the source.

Avi
+4  A: 

We follow a similar approach to what you propose i.e. bring vendor binaries into our repository and then use relative pathing to those binaries using svn:externals. It's working fine and I like that we have no external repository dependencies.

You can even consider just maintaining a single copy of each binary for each operating system, i.e. forgot about specifying version in the directory name, just use the Subversion revision as the controller. This is done using an explicit revision number in your svn:externals property, which you should probably be doing anyway.

So svn:externals on mymodule/vendor/product1/OS1 would be set as -rXXX ^/vendor/product1/OS1 where XXX is the revision containing the appropriate version mymodule uses.

For example, under our tools directory we have nunit binaries. If nunit releases a new version, we update tools\nunit and document in the log the release details. All our projects referencing nunit can (optionally) start using the new version by just changing the revision number of the svn:externals property for the project in question. If any project doesn't want the update, they do nothing :)

Si
+1  A: 

Yes, you can safely bypass handling of current/ in your branch. In that book, they're using current/ as a trunk/ for the 3rd party code, and tagging it with releases that're imported from the vendor.

Harold L
+1  A: 

Using a 'current' directory and svn_load_dirs is designed so that you can keep your local changes just as you say. It keeps a continuous history for the files from one version to the next. This allows the merge process to detect what's changed in the base and allow you to keep your changes, just like rebasing a branch from trunk. Otherwise the file is considered new each time and this 'rebasing' tries to replace the file completely rather than merge the new bits in.

Since you're dealing with binaries and not patching them at all, you're safe to ignore it.

Jim T
+1  A: 

I found this article helpful in planning my own vendor branch. However, I decided to create the /current/ folder anyway for a few versions just to see how significant the savings were. I figured I could delete it later if it wasn't worth the overhead.

I decided to post only major releases to /current/, then create a branch for each major version and apply patches to the branch. Finally, a tag for each resulting level of code. This fits well with the vendor's pattern for releases, in which patches (third segment of version stays the same) only modify the files needed, but releases (third segment changes) tag every file.

15.1.0.1901
-> update trunk
  -> copy trunk to new branches/15.1.0
  -> copy branches/15.1.0 to tags/15.1.0.1901
15.1.0.2233
-> update branches/15.1.0
  -> copy branches/15.1.0 to tags/15.1.0.2233
15.1.1.3064
-> update trunk
  -> copy trunk to new branches/15.1.1
  -> copy branches/15.1.1 to tags/15.1.1.3064
15.1.0.3299 (bug fix for 15.1.0)
-> update branches/15.1.0
  -> copy branches/15.1.0 to tags/15.1.0.3299

The vendor code is about 180MB, mostly .NET 3.5 DLLs with a few PDB and XML files. I found the space saving was significant, even on the commit against trunk where I went from 15.1.0 to 15.1.1 where every DLL had changes.

Version     -> size of repos/db/revs file
15.1.0.2782 -> 19,076 KB
15.1.0.2845 ->     78 KB
15.1.0.2892 ->    130 KB
15.1.0.2907 ->    981 KB
15.1.0.2948 ->  1,021 KB
15.1.1.2998 ->  3,334 KB (new branch)
15.1.1.3064 ->    477 KB

Assuming each update checked in on its own was 19MB, I'd be up to about 133MB now instead of 26MB, a savings of 80%. Now I'm not starved for disk space either, and Subversion definitely does a great job storing it compactly regardless, but I see this as a pretty nice savings, and well worth the structure and extra copy operations.

Your mileage may vary, naturally. In my case, having all the historical versions is very useful: My team supports many clients, each of whom may be using a different version of the vendor's software. The forensic value of knowing which files the vendor changed also helps to predict whether a patch will affect our enhancements.

Bruce