Thursday, April 14, 2011

What to do with multiple projects depending on the same source?

This is something I've come across twice in the past month and I'm not even certain how to phrase this as a Google query.

I'm actually using SVN for all of this, but it seems like this should be a general versioning problem.

We have two projects and one of them is dependent on some of the other's code. Due to API issues, it is not pragmatic to have some form of linkage between the products (and I don't want to have to configure all of the non-coders' machines to make this work).

I would imagine that if I put a copy of the shared code into the directory structure, I will end up overwriting all of the config files that SVN uses. This would mean that the version in the dependent project's directories would no longer be able to update.

Ex:

Project #1 needs to use the class MyExampleClass, however, MyExampleClass is something which is defined as a part of and needed by Project #2.

From stackoverflow
  • Look into svn:externals

  • Put all shared files in a separate folder in either one of the projects or in a separate one. Then use externals to reference that folder. Mixing files from different places in the same folder is a bad idea.

  • svn:externals will allow you to bring in files at a directory level. Like:

    Proj1\
      File1
      File2
    
    Proj2\
      File3
      File4
    

    Then in Proj2 you can svn:externals Proj1, and end up with:

    Proj2\
      Proj1\
        File1
        File2
      File3
      File4
    

    Now if you want to have files from 2 projects in 1 folder like:

    Proj2\
      File1 <- from Proj1
      File2 <- from Proj1
      File3
      File4
    

    Then I don't think SVN supports that.

    However, I have worked with other source control tools that would let you "link" a single file from one project to another anywhere you want (Borland StarTeam in particular).

    Wim Coenen : svn:externals supports file linking in svn 1.6. 1.6 RC3 is currently already available. The nightly build of tortoiseSVN is built against svn 1.6.
    rally25rs : @wcoenen: thanks for the info! looks like we are still on SVN 1.5.5 here... no wonder it wasn't working for me :)
  • We've used svn:externals pointing to shared code in practice for a few years now. We have had some interesting problems with it that you should probably consider before using it though. Here is the structure that we have:

    root
    +---common
    |   +---lib1
    |   |   \---trunk
    |   |       +---include
    |   |       \---src
    |   \---lib2
    |       \---trunk
    |           +---include
    |           \---src
    +---proj1
    |   \---trunk
    |       +---include
    |       |   \---common
    |       \---src
    |           \---common
    \---proj2
        \---trunk
            +---include
            |   \---common
            \---src
                \---common
    

    The common directories in both include and src in a project contain external definitions that pull in the common libraries:

    c:\dev> svn pget -v svn:externals proj1\trunk\src\common
    Properties on 'c:\dev\proj1\trunk\src\common':
      svn:externals : lib1 http://.../common/lib1/trunk/src
                      lib2 http://.../common/lib2/trunk/src
    

    The problem that we've run into is multifaceted but related to tagging and branching our source as the projects change throughout time. The externals definition that I showed above has a few pretty severe problems if you want to have reproducible builds:

    1. It refers to a dynamic target - trunk.
    2. It doesn't refer to an explicit revision.

    When you branch using svn copy, the externals are copied verbatim since they are really just properties attached to the object. Some of the other svn commands (commit, checkout, and export) actually interpret the properties. When you tag a project, you really want to preserve the state of the project for all time. This means that you have to "pin" the externals to a specific revision so you need to change the externals definition to explicit refer to the revision that you want (e.g., "lib1 -r42 http://.../common/lib1/trunk/src"). This solves one facet of the problem.

    If you have to maintain multiple incompatible branches of the common code, then you have to specify which branch you want explicitly along with (possibly) the revision.

    Needless to say, this can be a bit of a headache. Luckily someone out there in Subversion land write the svncopy.pl script that automates some of this mess. We are still (and have been) struggling with some of the difficulties supporting this in a field deployed product with a bunch of shared code and a mandate of three different versions in the field at any time.

    If you do go down this route, then be sure to consider how you will maintain the linkages as the projects grow and change. We've found that a little bit of time thinking about a process will go a long way here.

  • Externals, but do be aware of this issue:

    http://stackoverflow.com/questions/683716/subversion-update-externals-to-a-date

0 comments:

Post a Comment