The commit support files

The -i flag in the modules file can be used to run a certain program whenever files are committed (The modules file). The files described in this section provide other, more flexible, ways to run programs whenever something is committed.

There are three kind of programs that can be run on commit. They are specified in files in the repository, as described below. The following table summarizes the file names and the purpose of the corresponding programs.

commitinfo

The program is responsible for checking that the commit is allowed. If it exits with a non-zero exit status the commit will be aborted.

verifymsg

The specified program is used to evaluate the log message, and possibly verify that it contains all required fields. This is most useful in combination with the rcsinfo file, which can hold a log message template (Rcsinfo).

editinfo

The specified program is used to edit the log message, and possibly verify that it contains all required fields. This is most useful in combination with the rcsinfo file, which can hold a log message template (Rcsinfo). (obsolete)

loginfo

The specified program is called when the commit is complete. It receives the log message and some additional information and can store the log message in a file, or mail it to appropriate persons, or maybe post it to a local newsgroup, or… Your imagination is the limit!

The common syntax

The administrative files such as commitinfo, loginfo, rcsinfo, verifymsg, etc., all have a common format. The purpose of the files are described later on. The common syntax is described here.

Each line contains the following:

Blank lines are ignored. Lines that start with the character # are treated as comments. Long lines unfortunately can not be broken in two parts in any way.

The first regular expression that matches the current directory name in the repository is used. The rest of the line is used as a file name or command-line as appropriate.

Commitinfo

The commitinfo file defines programs to execute whenever cvs commit is about to execute. These programs are used for pre-commit checking to verify that the modified, added and removed files are really ready to be committed. This could be used, for instance, to verify that the changed files conform to to your site's standards for coding practice.

As mentioned earlier, each line in the commitinfo file consists of a regular expression and a command-line template. The template can include a program name and any number of arguments you wish to supply to it. The full path to the current source repository is appended to the template, followed by the file names of any files involved in the commit (added, removed, and modified files).

The first line with a regular expression matching the directory within the repository will be used. If the command returns a non-zero exit status the commit will be aborted.

If the repository name does not match any of the regular expressions in this file, the DEFAULT line is used, if it is specified.

All occurrences of the name ALL appearing as a regular expression are used in addition to the first matching regular expression or the name DEFAULT.

The command will be run in the root of the workspace containing the new versions of any files the user would like to modify (commit), or in a copy of the workspace on the server (远程源码库 在 第 2 章). If a file is being removed, there will be no copy of the file under the current directory. If a file is being added, there will be no corresponding archive file in the repository unless the file is being resurrected.

Note that both the repository directory and the corresponding Attic (Attic目录 在 第 2 章) directory may need to be checked to locate the archive file corresponding to any given file being committed. Much of the information about the specific commit request being made, including the destination branch, commit message, and command line options specified, is not available to the command.

Verifying log messages

Once you have entered a log message, you can evaluate that message to check for specific content, such as a bug ID. Use the verifymsg file to specify a program that is used to verify the log message. This program could be a simple script that checks that the entered message contains the required fields.

The verifymsg file is often most useful together with the rcsinfo file, which can be used to specify a log message template.

Each line in the verifymsg file consists of a regular expression and a command-line template. The template must include a program name, and can include any number of arguments. The full path to the current log message template file is appended to the template.

One thing that should be noted is that the ALL keyword is not supported. If more than one matching line is found, the first one is used. This can be useful for specifying a default verification script in a directory, and then overriding it in a subdirectory.

If the repository name does not match any of the regular expressions in this file, the DEFAULT line is used, if it is specified.

If the verification script exits with a non-zero exit status, the commit is aborted.

In the default configuration, CVS allows the verification script to change the log message. This is controlled via the RereadLogAfterVerify CVSROOT/config option.

When RereadLogAfterVerify=always or RereadLogAfterVerify=stat, the log message will either always be reread after the verification script is run or reread only if the log message file status has changed.

The CVSROOT/config configuration file, for more on CVSROOT/config options.

It is NOT a good idea for a verifymsg script to interact directly with the user in the various client/server methods. For the pserver method, there is no protocol support for communicating between verifymsg and the client on the remote end. For the ext and server methods, it is possible for CVS to become confused by the characters going along the same channel as the CVS protocol messages. See 远程源码库 在 第 2 章, for more information on client/server setups. In addition, at the time the verifymsg script runs, the CVS server has locks in place in the repository. If control is returned to the user here then other users may be stuck waiting for access to the repository.

This option can be useful if you find yourself using an rcstemplate that needs to be modified to remove empty elements or to fill in default values. It can also be useful if the rcstemplate has changed in the repository and the CVS/Template was not updated, but is able to be adapted to the new format by the verification script that is run by verifymsg.

An example of an update might be to change all occurrences of 'BugId:' to be 'DefectId:' (which can be useful if the rcstemplate has recently been changed and there are still checked-out user trees with cached copies in the CVS/Template file of the older version).

Another example of an update might be to delete a line that contains 'BugID: none' from the log message after validation of that value as being allowed is made.

The following is a little silly example of a verifymsg file, together with the corresponding rcsinfo file, the log message template and an verification script. We begin with the log message template. We want to always record a bug-id number on the first line of the log message. The rest of log message is free text. The following template is found in the file /usr/cvssupport/tc.template.

BugId:

The script /usr/cvssupport/bugid.verify is used to evaluate the log message.

#!/bin/sh
#
#       bugid.verify filename
#
#  Verify that the log message contains a valid bugid
#  on the first line.
#
if head -1 < $1 | grep '^BugId:[ ]*[0-9][0-9]*$' > /dev/null; then
    exit 0
elif head -1 < $1 | grep '^BugId:[ ]*none$' > /dev/null; then
    # It is okay to allow commits with 'BugId: none',
    # but do not put that text into the real log message.
    grep -v '^BugId:[ ]*none$' > $1.rewrite
    mv $1.rewrite $1
    exit 0
else
    echo "No BugId found."
    exit 1
fi

The verifymsg file contains this line:

^tc     /usr/cvssupport/bugid.verify

The rcsinfo file contains this line:

^tc     /usr/cvssupport/tc.template

The config file contains this line:

RereadLogAfterVerify=always

Editinfo

NOTE: The editinfo feature has been rendered obsolete. To set a default editor for log messages use the EDITOR environment variable (附录 D) or the -e global option (全局选项 在 附录 A). See Verifying log messages, for information on the use of the verifymsg feature for evaluating log messages.

If you want to make sure that all log messages look the same way, you can use the editinfo file to specify a program that is used to edit the log message. This program could be a custom-made editor that always enforces a certain style of the log message, or maybe a simple shell script that calls an editor, and checks that the entered message contains the required fields.

If no matching line is found in the editinfo file, the editor specified in the environment variable $CVSEDITOR is used instead. If that variable is not set, then the environment variable $EDITOR is used instead. If that variable is not set a default will be used. See 提交修改 在 第 1 章.

The editinfo file is often most useful together with the rcsinfo file, which can be used to specify a log message template.

Each line in the editinfo file consists of a regular expression and a command-line template. The template must include a program name, and can include any number of arguments. The full path to the current log message template file is appended to the template.

One thing that should be noted is that the ALL keyword is not supported. If more than one matching line is found, the first one is used. This can be useful for specifying a default edit script in a module, and then overriding it in a subdirectory.

If the repository name does not match any of the regular expressions in this file, the DEFAULT line is used, if it is specified.

If the edit script exits with a non-zero exit status, the commit is aborted.

Note: when cvs is accessing a remote repository, or when the -m or -F options to cvs commit are used, editinfo will not be consulted. There is no good workaround for this; use verifymsg instead.

Editinfo example

The following is a little silly example of a editinfo file, together with the corresponding rcsinfo file, the log message template and an editor script. We begin with the log message template. We want to always record a bug-id number on the first line of the log message. The rest of log message is free text. The following template is found in the file /usr/cvssupport/tc.template.

BugId:

The script /usr/cvssupport/bugid.edit is used to edit the log message.

#!/bin/sh
#
#       bugid.edit filename
#
#  Call $EDITOR on FILENAME, and verify that the
#  resulting file contains a valid bugid on the first
#  line.
if [ "x$EDITOR" = "x" ]; then EDITOR=vi; fi
if [ "x$CVSEDITOR" = "x" ]; then CVSEDITOR=$EDITOR; fi
$CVSEDITOR $1
until head -1|grep '^BugId:[ ]*[0-9][0-9]*$' < $1
do  echo -n  "No BugId found.  Edit again? ([y]/n)"
    read ans
    case ${ans} in
        n*) exit 1;;
    esac
    $CVSEDITOR $1
done

The editinfo file contains this line:

^tc     /usr/cvssupport/bugid.edit

The rcsinfo file contains this line:

^tc     /usr/cvssupport/tc.template

Loginfo

The loginfo file is used to control where cvs commit log information is sent. The first entry on a line is a regular expression which is tested against the directory that the change is being made to, relative to the $CVSROOT. If a match is found, then the remainder of the line is a filter program that should expect log information on its standard input.

If the repository name does not match any of the regular expressions in this file, the DEFAULT line is used, if it is specified.

All occurrences of the name ALL appearing as a regular expression are used in addition to the first matching regular expression or DEFAULT.

The first matching regular expression is used.

The commit support files, for a description of the syntax of the loginfo file.

The user may specify a format string as part of the filter. The string is composed of a % followed by a space, or followed by a single format character, or followed by a set of format characters surrounded by { and } as separators. The format characters are:

s

file name

V

old version number (pre-checkin)

v

new version number (post-checkin)

All other characters that appear in a format string expand to an empty field (commas separating fields are still provided).

For example, some valid format strings are %, %s, %{s}, and %{sVv}.

The output will be a space separated string of tokens enclosed in quotation marks ("). Any embedded dollar signs ($), backticks (`), backslashes (\), or quotation marks will be preceded by a backslash (this allows the shell to correctly parse it as a single string, reguardless of the characters it contains). For backwards compatibility, the first token will be the repository subdirectory. The rest of the tokens will be comma-delimited lists of the information requested in the format string. For example, if /u/src/master/yoyodyne/tc is the repository, %{sVv} is the format string, and three files (ChangeLog, Makefile, foo.c) were modified, the output might be:

"yoyodyne/tc ChangeLog,1.1,1.2 Makefile,1.3,1.4 foo.c,1.12,1.13"

As another example, %{} means that only the name of the repository will be generated.

Note: when cvs is accessing a remote repository, loginfo will be run on the remote (i.e., server) side, not the client side (远程源码库 在 第 2 章).

Loginfo example

The following loginfo file, together with the tiny shell-script below, appends all log messages to the file $CVSROOT/CVSROOT/commitlog, and any commits to the administrative files (inside the CVSROOT directory) are also logged in /usr/adm/cvsroot-log. Commits to the prog1 directory are mailed to ceder.

ALL             /usr/local/bin/cvs-log $CVSROOT/CVSROOT/commitlog $USER
^CVSROOT        /usr/local/bin/cvs-log /usr/adm/cvsroot-log
^prog1          Mail -s %s ceder

The shell-script /usr/local/bin/cvs-log looks like this:

#!/bin/sh
(echo "------------------------------------------------------";
 echo -n $2"  ";
 date;
 echo;
 cat) >> $1

Keeping a checked out copy

It is often useful to maintain a directory tree which contains files which correspond to the latest version in the repository. For example, other developers might want to refer to the latest sources without having to check them out, or you might be maintaining a web site with cvs and want every checkin to cause the files used by the web server to be updated.

The way to do this is by having loginfo invoke cvs update. Doing so in the naive way will cause a problem with locks, so the cvs update must be run in the background. Here is an example for unix (this should all be on one line):

^cyclic-pages		(date; cat; (sleep 2; cd /u/www/local-docs;
 cvs -q update -d) &) >> $CVSROOT/CVSROOT/updatelog 2>&1

This will cause checkins to repository directories starting with cyclic-pages to update the checked out tree in /u/www/local-docs.