Django Subversion Repository Structure

The last couple of days I have been racking my brain to come up with an appropriate Subversion repository structure for my django development. My requirements are simple really:
  1. A single repository must contain all of my django projects. This is required since I am hosting my development on google code, and they only provide you with one repository..
  2. Each django application should be "versioned" independently. This allows me to release new versions of applications independently from django projects. It also allows different django projects to use various versions of the same application.
  3. Each django project should be "versioned" independently.
  4. The structure should support both branches and tags. Tags are releases of either applications or projects, while branches are bigger developments that could span a couple of tags or releases.
  5. It must be possible to patch tags or releases easily.
  6. Django projects should be able to reference specific versions of the django applications.
These requirements have led me to a structure which looks like this:

/
  /django-app
    /app_1
      /trunk/app_1
      /tags
        /1.0/app_1
        /2.0/app_1
      /branches
        /awsome_new_feature/app_1
  /django-projects
    /project_1
      /trunk
        /project_1
          /apps
      /tags
        /1.0
          /project_1
        /1.1/project_1      /branches
        /client_color_test/app_1

It is quite easy to see that requirements 1 to 4 are easily satisfied by this structure. Requirement 5 is also met; as long as all patches on a tag or release are done in another tag or release that is related to the original tag, by way of the version number. So if a patch needs to be done to version 1.0 of an application the procedure would be to create a tag from the version 1.0 tag and name it something like version 1.1. Then apply any changes to the version 1.1 tag and release a new package from the version 1.1 tag. This way the original version 1.0 tag or release stays untouched.

Requirement 6 is met but not in the structure itself, but by employing a very nifty feature in Subversion called, externals. (By the way, the repeated project and application names (project1/trunk/application1 and project_1/tags/1.0/project_1) in the repository tree was introduced to make the use of externals more transparent, as can be see below.) The external property gets added to the project directory under the /trunk of the project. In my case I add an external that looks a bit like the following (it assumes that you are in the django-projects/project_1/trunk directory):

svn propget svn:externals project_1 ^/django-apps/app_1/trunk apps
svn propget svn:externals project_1 ^/django-apps/app_1/tags/1.0 apps
The first example add the externals property to my project_1 directory linking my project_1 to the trunk of app_1. When a checkout is done the app_1/trunk contents will be checked out into the project_1/apps directory. The second example will link the release version 1.0 of the same application rather than the trunk version of the application to project_1.

One of the problems with this scheme is that if you reference the trunk of an application and create a release, then the release will also reference the trunk. However, this is easily managed by always developing against release versions of applications. Obviously this is not always possible and in these cases vigilant management of the projects will be required to ensure that a project release doesn't accidentally reference incorrect versions of applications. I can see the possibility of writing some code to validate these rules.

Thats it for now. I am quite excited to start using this structure.

No comments:

Post a Comment