In a subversion repository, the organization of the paths is of fundamental importance for the everyday work and usability. We want to follow the standard (but not enforced) basic hierarchy of a project hosted on SVN, which consists of the 3 directories:
trunk: the main trunk of development
tags: fixed versions of the project identified by symbolic names
branches: branches of evolution of the project parallel to the trunk
Out development model requires the necessity to have package level tags and branches. At the same time, we need something that can be used as a tag on the whole project. Moreover, LHCb unique CVS repository is hosting many CMT projects and a global tag is pointless, but we can profit from the possibility of check out a complete tagged project in one command.
Version 2.0
After having gained more experience with the usage model of the Gaudi SVN repository, I think we need to restructure it.
Motivation
Even though the previous structure is valid, it makes working with whole projects more problematic that what it could be. Mainly because of the usage of svn:externals, which is more powerful than the CVS aliases, but it is not flexible enough for our use case (URL pointing to the repository may change).
For Gaudi the package tags and the project tags have more or less the same importance (LHCb uses local tags while Atlas and other experiments use only the project tags), and for Dirac (which is being migrated to SVN too) the local tags were never used. This, essentially, means that the projects tags are more important than what was thought when devising the first structure of the repository.
Proposal 2
A structure that allows good integration between project-level and package-level tags can be achieved with something like:
Version 1.0
Proposal
The repository contains the 3 main directories packages, projects and distribution.
packages will contain one directory per package, each of them with the 3 standard directories trunk, tags and branches. In case of CMT "hats", we can have packages/Hat/Package/trunk etc. The list of known packages can be obtained scanning the content of the directory packages, going down one level to take into account the possibility of hats. The scanning is very inefficient, so we can add a property called modules to the packages directory containing a newline-separated list of the known modules. This property can be updated automatically with a cron job or on demand.
The projects directory will contain one directory per hosted project (as container of packages), with the usual 3 standard directories. The content of the trunk for one this projects is only the content of the cmt directory that lives at the project level:
projects/GAUDI/trunk/project.cmt
The distribution directory contains the 3 standard directories. The tags and branches directory will have one subdirectory per hosted project, each of them containing one directory per "global tag". Those global tag directories will be empty and the internal structure will be described with svn externals definitions. External definitions are metadata of a directory that instruct svn to populate the directory checking out the subdirectories from other svn locations (more or less as cvs module aliases). The trunk directory will contain one empty directory per project, that, with the externals definitions, will allow to check out the trunks of all the related packages in one go.
Note: due to the non-locality of the external definitions (svn allows to check out from different repositories), we cannot use the same distribution sub directory for the public anonymous access and the read/write access, so distribution/trunk/GAUDI should be used by developers, while anonymous users will have to use distribution/tags/GAUDI/GAUDI_HEAD which will checkout the same files as trunk, but using the read-only http protocol.
mkdir -p GAUDI/GAUDI_v20r0
cd GAUDI/GAUDI_v20r0
cvs -d $GAUDICVS checkout -r GAUDI_v20r0 all
svn
mkdir GAUDI
cd GAUDI
svn checkout $GAUDISVN/distribution/tags/GAUDI/GAUDI_v20r0
Commit
The commit is identical in CVS and Subversion
Commit the changes in the current directory (and subdirectories)
cvs
cvs commit
svn
svn commit
Commit the changes of a single file
cvs
cvs commit "myfile"
svn
svn commit "myfile"
Update
I want to distinguish between two use cases:
simple update: synchronize the local copy with the latest (or a specific) revision of the repository
update with tags: move from a tagged local version to the head one or to a branch
Simple Update
Nothing really special:
cvs
cvs update
svn
svn update
The way to select a revision or a moment in time a slightly different, but easy to sort out using the help.
Update with Tags
This is the complex part, since tags do not exists (as such) in Subversion. With SVN, tags are represented by copies of the trunk directory, so moving the working copy from a tag to another (or trunk or branch) means changing the path of the origin of the working copy.
Move the working copy from the current tag to the trunk/HEAD (assuming you are in the top directory of the package)
cvs
cvs update -APd
svn
svn switch $GAUDISVN/packages/MyPackage/trunk
Move the working copy from the current tag to the another tag (assuming you are in the top directory of the package)
To just check if there are changes in the repository that you didn't get yet, you can do a "dry-run" update with cvs. That does not exist in svn, you have to ask the status of the repository.
cvs
cvs update -n
svn
svn status -u
or
svn status --show-updates
Comparison (diff)
Comparison between the base of the working copy and the working copy