The modules2 file

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.

How the modules2 file differs from the modules file

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.

Modules2 syntax

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.

The special character '!' stops recursion to directories below the one specified (-l option).

The special character '+' stops parsing of that line, so that you can avoid infinte loops.

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 '#'

Items in (...) are an extended regular expression applied to the filenames. All files which do not match are ignored.

Modules2 limitations

Using modules defined with the modules2 file has some consequences that may not be immediately apparent. The most common of these is what happens when the module is 'checked out' and a user adds a directory, Where will that directory reside in the repository?

Another problem is what if a file is added to a directory that is based on a regular expression, and the new file does not meet the regular expression? Will the file add OK, and if it does add OK, where in the repository is it (it will not checkout because it does not match the regular expression).

The most commonly reported problems are with changes to the modules2 and effecting checkouts of earlier tags. ie: you build your project and tag it, then at a later date you expect that if you checkout that same tag, you will get the same files - but changes to modules2 made after the tag, may alter the results (this is the same behaviour for the older 'modules' too).

Customers often define 'modules2' and test it with Trunk or HEAD, but don't fully test the impact of checkouts on other branches. The modules2 will behave the same way for every branch and tag.

Running Audit reports or even the 'History' command on these modules can also lead to unexpected results - because they exist both as the 'original'.

Modules2 is not designed so that you can 'combine' or 'merge' directories or files from separate directories to a single directory.