On Thu, 2003-08-28 at 22:24, Fabian Fagerholm wrote: > How do I manage a new Debian package with Subversion? Thanks to jcollins@asgardsrealm.net and joeyh@debian.org for their insight into this issue. I will try to summarize everything in this reply to myself. Managing Debian packages with Subversion The following assumes you have basic knowledge of Subversion (SVN). If you need to read up on its installation and usage, please consult the Subversion Book by Ben Collins-Sussman, Brian W. Fitzpatrick, C. Michael Pilato, available from the Subversion site at http://subversion.tigris.org/ or the book's site http://svnbook.red-bean.com/. What are we trying to accomplish? We want to manage Debian packages with Subversion. In other words, we want to store all the files related to a Debian "source package" in a Subversion repository, including the upstream source. When making changes to the packaging, or when updating the package to a new upstream version, we want to check out our "project" (our package) from the repository, make the required changes, and then commit the changes back into the repository. Also, when we are satisfied with the state of the packaging and want to release a new version, we want to automate certain steps such as tagging the current state of the repository with an appropriate name and version number (corresponding to the debian package version), exporting this tag and building the package. Where appropriate, we want to use the "Subversion way" of doing these things, meaning we want to take full advantage of the features provided by Subversion. Choosing your repository structure While there are several ways of structuring your repository, common practise is to have trunk/, branches/ and tags/ directories and divide the content among these. Two questions arise: * Should the repository have trunk/, branches/ and tags/ at the top level, each containing project directories -- or should the top level be divided by project, and each project directory contain trunk/, branches/ and tags/? * Should there be an additional top-level directory called vendor/, containing the upstream source -- or should the upstream source be treated as just another branch? We thus have 2x2 choices: A. Use vendor/ for upstream source. A. Per-project trunk/, branches/, tags/ and vendor/. B. Repository-wide trunk/, branches/, tags/ and vendor/. B. Use a regular branch for upstream source. A. Per-project trunk/, branches/ and tags. B. Repository-wide trunk/, branches/ and tags/. Choosing one is largely a matter of taste. The repository will look clean and structured to newcomers if the top-level directory is divided by project (sub-option A). It might also add to ease of comprehension to have upstream sources in vendor/ (option A). But there are some technical considerations if you want to use the svn:externals property (see the Subversion Book for details) to pull in several project directories at once. (TODO: explain this further) Option A.A.: Per-project trunk/, branches/, tags/ and vendor/ The repository will have the following structure: projectA/ trunk/ branches/ tags/ vendor/ projectB/ trunk/ branches/ tags/ vendor/ ... The idea of this layout is to reflect the logical structure in the repository. Internally, Subversion makes no distinction between a directory called trunk and a directory called tags. Only your use of these directories dictate their meaning. To Subversion, it's all the same. Option A.B.: Repository-wide trunk/, branches/, tags/ and vendor/ The repository will have the following structure: trunk/ projectA/ projectB/ ... branches/ projectA/ projectB/ ... tags/ projectA/ projectB/ ... vendor/ projectA/ projectB/ ... The advantage of this might be that the svn:externals property might work better. (TODO: verify, why) Option B.A.: Per-project trunk/, branches/ and tags/ The repository will have the following structure: projectA/ trunk/ branches/ tags/ projectB/ trunk/ branches/ tags/ ... Here, the logical structure is reflected in the repository, but the upstream sources are considered just another branch. Vendor tags are considered just another set of tags. This approach is fine, but there is no technical reason to do so. Subversion doesn't care. Option B.B.: Repository-wide trunk/, branches/ and tags/ The repository will have the following structure: trunk/ projectA/ projectB/ ... branches/ projectA/ projectB/ ... tags/ projectA/ projectB/ ... As in B.A., upstream sources and tags are not treated specially. This might also work better with svn:externals. (TODO: check, why) As noted before, the choice is largely a matter of taste. However, take into account that Subversion doesn't care how you structure your repository. The only tehcnical consideration is when using the svn:externals property. (TODO: verify this and add the explanation above, then adjust this to reflect the explanation) In the following, we will simply refer to the option name (A.A., A.B., etc.) when explaining the differences between the options. Populating your project When starting to package a new Debian package, the following steps are performed: * Download the upstream source and unpack it. * Enter the upstream source directory and import it (svn import) into the appropriate directory: * A.A. projectX/vendor/current * A.B. vendor/projectX/current * B.A. projectX/branches/upstream * B.B. branches/projectX/upstream * Tag the state of what you just imported (svn copy): * A.A. projectX/vendor/<version> * A.B. vendor/projectX/<version> * B.A. projectX/tags/upstream/<version> * B.B. tags/projectX/upstream/<version> * Populate trunk/ from the imported upstream source (svn copy): * A.A. projectX/trunk * A.B. projectX/trunk * B.A. trunk/projectX * B.B. trunk/projectX * Check out the trunk you just created into a directory called project-<version> (svn co). * Debianize by dh_make. Note for people who have just read the New Maintainer's Guide: skip the -f flag. If you have the environment variable EMAIL set up correctly, you can skip the -e flag as well. You just need to run dh_make in the newly created directory. * Add the new debian/ directory to subversion's control (svn add). * Adjust packaging scripts as needed. Don't do any big changes yet, you just want to modify the control and README.Debian files, and perhaps some of the most obvious files in debian/. Try to think about the most initial state of packaging you want to start with. * Finally, commit the changes (svn commit). Working with the project There is nothing special about working with the Debian package from a Subversion point of view. You just follow these steps: * Check out HEAD (the latest version) of your trunk (svn co) or update the trunk directory (svn update). * Make the required changes. * Commit (svn commit). Try to structure the changes. Think about what you are going to do, and define one task. Carry out the task, then commit. Pick another task, carry it out, commit. And so on. This way, each commit will take the package from one defined state to the next, and the commit changelog will help you find the change that broke your package. You'll be able to say "I made a mistake in revision 123, I'll have to undo it". Then you can go back to the state before the mistake was made, and undo it in the next revision. Several Subversion commands help you here -- see the Subversion book for details. Updating to a new upstream version Having populated your repository in the manner described above, the following procedure will allow you to move your packaging to a new upstream version, resolving any conflicts between your modified version and the new upstream version. (This section is largely based on the Subversion Book) * Download the new upstream source and unpack it. * Use the svn_load_dirs tool to update the current upstream version and tag it (this will be committed immediately): * A.A. svn_load_dirs -t <version> url://host/repos/projectX/vendor current /path/to/new/version * A.B. svn_load_dirs -t <version> url://host/repos/vendor/projectX current /path/to/new/version * B.A. svn_load_dirs -t tags/upstream/<version> url://host/repos/projectX/ branches/upstream /path/to/new/version * B.B. svn_load_dirs -t tags/projectX/upstream/<version> url://host/repos/ branches/projectX/upstream /path/to/new/version * (TODO: verify that all of the above are correct) * The above might produce conflicts between the versions. You must resolve these conflicts, so it may be neccessary to familiarize yourself with the changes introduces by upstream between the versions. (You should do so in any case...) * Check out HEAD (the latest version) of your trunk (svn co). * Merge the differences between the previous upstream version and the current (new) upstream version into your trunk (svn merge): svn merge url://to/previous/version url://to/current/version trunk * You must again resolve any resulting conflicts. * Commit the new version (svn commit). Remember, if you follow the advice below about tagging your releases, then you have well-defined checkpoints to roll back to if anything goes wrong. Making a release When you are ready to make a release of your package, you should tag the current state of trunk with the appropriate version number: * A.A. projectX/tags/<version> * A.B. projectX/tags/<version> * B.A. tags/projectX/<version> * B.B. tags/projectX/<version> Then export (svn export) the current tag and build the package. You also need to export the upstream source and turn it into an .orig.tar.gz. Jamin W. Collins has provided the following script to automate the build (TODO: adjust the script to allow for different repository layouts and make it do the exporting, tarring of .orig.tar.gz, building and cleaning up all in one sweep. The script currently assumes that trunk is a directory containing the SVN working copy and that .orig.tar.gz is provided.) --8<-- #!/bin/sh if [ -d trunk ]; then read LINE < ./trunk/debian/changelog PROJ=`echo $LINE | cut -f 1 -d " "` VER=`echo $LINE | sed s/'[^(]*(\([^)]*\).*'/'\1'/ | cut -f 1 -d '-'` if [ -d "${PROJ}-${VER}" ]; then rm -fr "${PROJ}-${VER}" fi svn export trunk ${PROJ}-${VER} cd ${PROJ}-${VER} debuild -rfakeroot -us -uc else echo "*** trunk directory does not exist ***" exit 1 fi --8<-- Final words I would welcome additions and corrections to this document. -- Fabian Fagerholm <fabbe@paniq.net>
Attachment:
signature.asc
Description: This is a digitally signed message part