The modules2 file provides a lower level definition of modules than the modules file. Clients see the modules2 structure as if it existed physically on the server.
The modules provides different types of module, which are 'high level', in that checking out a module is equivalent to calling checkout multiple times on different directories. This approach works well for simple cases, but breaks down in the more complex cases, causing unwanted interactions with the update command for example.
The modules2 has only one way of describing a module, but operates on a much lower level. Clients are unaware that the directory structure that they are checking out does not actually exist, and all cvs commands behave as normal. A file or directory defined by modules2 may have a completely different name to its real name, and updates/merging will be handled correctly even if multiple clients checkout under different names.
Which file you choose depends on your requirements. It isn't recommend that usage is mixed between the two files as they both serve a similar function and it would get confusing.
The modules2 file is structured in a similar way to the familiar Windows .ini file. Each section defines a module, and within each section is a description of the files and directories within that module.
An example modules2 file is:
[pets] dog cat [people] brother sister [household] pets people
Checking out 'household' will create the directory structure:
household pets dog cat people brother sister
In this example the 'household', 'pets', and 'people' directories don't have any files in them - they're just containers. However let's say we want to put the files listing pet food in the pets directory, above all the pet specific directories.
Modules2 lets you override what goes in the root of a module, to overlay another module in it:
[pets] / = !petfood dog cat [people] brother sister [household] pets people
Now when we checkout we get the same directory structure as above, but the pets directory contains the contents of 'petfood'. Note also we said that we don't want any subdirectories of petfood, using the '!' prefix. This makes sure that the directory is never recursed into, even during an update -d. We still get the 'dog' and 'cat' directory of course.
You can simply rename an entire directory tree using this method. The following:
[project1] / = myproject [project2] / = myproject junk = total_junk = project/old_project = myproject/junk
project1 will checkout the entire myproject tree. project2 is the same, except the 'junk' directory is removed, and moved to project/oldproject. The total_junk directory is hidden completely.
You can also mask certain files within a directory, or certain subdirectories using an extended regular expression.
[project1] / = myproject [project2] / = myproject (*\.cpp$|*\.[ch]$|*/$) junk = total_junk = project/old_project = myproject/junk
Directories are subject to the same filtering, except they have a '/' directory separator after their name. If you just want to filter some files and allow subdirectories then add '|*/$' as an option.
(need to be more verbose here: FIXME)
The '+' prefix stops processing, so that entries that would be potentially recursive can be defined to be nonrecursive.
Spaces can be used in the file, delimited by quotes or using backslash escapes. File separators must always be forward slashes.
Comments are on a line beginning '#'