Search code examples
svnsvn-externals

Troubles with svn:externals inside another svn:externals


I have some troubles in checking out a tagged version in my svn repository and most likely because of an inner 'svn:externals' that is not referring to the correct revision. Lets consider simplified situation:

I have a first svn repository which looked like this at revision XXX1:

Repo1 (@ Rev XXX1)
  tags
    ...
  trunk
    Folder1
      ExternalRefToFolder2 (svn:externals '../Folder2')
    Folder2
      SomeFile1.txt
      SomeFile2.txt

And which has been refactored to (at head revision):

Repo1 (@ HEAD1)
  tags
    ...
  trunk
    Folder1
      SomeFile1.txt
      SomeFile2.txt

I.E: For the good or for the bad, the external reference to Folder2 has been removed and replaced by file copy between revisions XXX1 and HEAD1.

I also have a second repository on the same server which looks like this:

Repo2 (@ HEAD2) 
  tags
    1.0.0
      ExternalToRepo1 (svn:externals -rXXX1 ^/../Repo1/trunk)
  trunk
    ExternalToRepo1 (svn:externals ^/../Repo1/trunk)

I.E.: Again, for the good or for the bad, the second repository is referencing first one using an external reference (revision HEAD1 in trunk and revision XXX1 in tagged version so as to freeze everything at correct revision).

The issue

  • When I'm checking-out the trunk of Repo2, I have no issue. That is Repo1 is checked-out with its single Folder1.

  • When I'm checking out the tag 1.0.0 of Repo2, then svn complains that it cannot find http://server//Repo1//trunk//Folder2 at HEAD1 revision.

So it all looks like that even if the tag 1.0.0 is referring to Repo1/trunk in its correct XXX1 revision; the inner external svn:externals '../Folder2' is interpreted as if based from HEAD1 (instead of revision XXX1 as I would have had expected).

Is this behavior normal, and how may I work around the issue ?

NB: Svn version I have is 1.7.8 (r1419671) compiled december 12th, 2012

Edit

Another way to reproduce the issue is to check-out or simply browse Repo1 at revision XXX1. svn:externals '../Folder2' will then still be relative to HEAD1 so guess there's no much solution.


Solution

  • Using svn:externals as a poor man's dependency management or code duplication avoidance scheme are the source of your woes. Nesting them is not double bad, it's multiplicative. I recommend this excellent long answer about the badness with externals

    You're never going to have great results using svn:externals for internal stuff, however if you keep using them you can mitigate the pain by:

    1. Follow the advice of the red book and never make an external pull in the head:

    You should seriously consider using explicit revision numbers in all of your externals definitions. Doing so means that you get to decide when to pull down a different snapshot of external information, and exactly which snapshot to pull. Besides avoiding the surprise of getting changes to third-party repositories that you might not have any control over, using explicit revision numbers also means that as you backdate your working copy to a previous revision, your externals definitions will also revert to the way they looked in that previous revision, which in turn means that the external working copies will be updated to match the way they looked back when your repository was at that previous revision. For software projects, this could be the difference between a successful and a failed build of an older snapshot of your complex codebase.

    1. If you don't do the above, create your tags with svncopy.pl. It will 'pin' the revisions of your externals to whatever they are when you create the tag.

    You didn't mention why you have multiple repositories - is it possible you may benefit from consolidation?
    You didn't mention what language/tooling your working with. I'm pretty sure there is a better way for you to meet your requirements. For example, if it's a java app with a few librairies you're pulling in via the externals - you'll be happier if you build the libraries separately and publish them using some maven like substance and then resolve them when you build your app.