7.3. Running ScriptsIn the repository's CVSROOT directory, there are several scripting files that allow you to run scripts while a project is being committed, tagged, updated, or modified in other ways. The scripts called from scripting files are often used to interact with other programs or to enforce standards.
Example 7-6 shows a commitinfo scripting file that runs a layout-testing program called indent-tester on the wizzard project files. CVS calls scripts in commitinfo before files are committed. Example 7-6. Sample commitinfo file
When a project file is committed, CVS searches the commitinfo file for rules that match the project file's path; if CVS finds a rule, it runs the script given in that rule. The rule in Example 7-6 matches all files in the src directory (and its subdirectories) of the wizzard project and tells CVS to run the indent-tester script on those files, also providing the parameters the script expects. (Later in this chapter, Example 7-8 shows the indent-tester script that can be used to enforce indentation standards for a project.) CVS processes the scripting files separately for each directory that is affected by a command, and it calls the script in the scripting file once for each directory it matches. If you run cvs commit wizzard, CVS checks commitinfo for patterns that match wizzard and runs the script once for the files in the wizzard directory, then does the same for each subdirectory, checking for patterns that match wizzard/doc and processing its files, followed by wizzard/lib and wizzard/src. 7.3.1. Working with Scripting FilesThe scripting files are all stored in your repository's CVSROOT directory. The purpose of each file is described in the section of this chapter named for that file. Most of these files use a common syntax.
The common syntax is rule-based, one line per rule, and each rule consists of a pattern to be matched and an action to be taken. When CVS reads a scripting file, it tries to match the pattern to project files. If the pattern matches the file that CVS is currently processing, CVS runs the action. The action is usually a pathname to a script and parameters for that script. The common syntax is described in the next section. To edit any of the scripting files, check out the file with the following command: cvs -d repository_path checkout CVSROOT/filename Edit the file with any text editor, then commit the file with cvs commit. CVS stores these files in the repository's CVSROOT directory in both plain-text and RCS formats and updates both types of file every time a file is committed. When you check them out, you'll only see the plain-text format in the CVSROOT sandbox directory. You can also store the scripts you call from these files in your repository's CVSROOT directory or a subdirectory of CVSROOT. Add such scripts to the checkoutlist file in CVSROOT, so that they are automatically exported to the CVSROOT directory when they're committed. The checkoutlist file is described in Chapter 6.
Do not attempt to interact with the user from scripts called from the scripting files. Some remote-access methods do not support such interaction at all, and other methods can be affected by having unexpected data go through their socket. Users other than the one involved in the interaction may also be left waiting on the first user until the interaction is complete. If any script contains a CVS command, be aware that the command that calls the script will not finish until the script does. You may find that some directories have been locked by the original command, which can't finish and release them until the script is finished, but the script can't finish because the second command can't run until those same locks are released. This situation can be prevented by having your script call any CVS commands in the background or by calling the script in the background (which probably necessitates having the script report any errors by email to the repository or project administrator). Scripts called from all files except the modules file are run on the computer that hosts the repository. Two of the modules scripts run on the sandbox computer; the others run on the repository computer. If you do not provide a full path for a script, CVS searches the user's PATH environment variable. To prevent the wrong script from being called, I recommend using the full path in all scripting files. Your repository administrator may limit your access to the scripting files for security reasons. Work with the repository administrator; you are asking for permission to run arbitrary scripts, so try to address her concerns. 7.3.2. Common SyntaxMost of the scripting files in CVSROOTincluding commitinfo, loginfo, editinfo, rcsinfo, and verifymsgshare a common syntax. The modules file does not use the common syntax, as described in the next section. If your version of CVS is older than 1.12.6, see the "Common Syntax: Pre-1.12.6" sidebar for information on the syntax you should use.
In versions later than 1.12.6, whether you use the new or old syntax for the scripting files is controlled by the configuration option UseNewInfoFmtStrings. The valid options are yes (to use the new syntax) and no (to use the syntax prior to 1.12.6). These options are set in the config file, normally stored in the CVSROOT directory.
The file syntax is as follows: name-pattern action format_string The name-pattern is a regular expression that must match a relative path within the repository, or one of the special words DEFAULT and ALL. It is separated from the action by one or more spaces or tabs. Regular expressions are explained in Chapter 11. The action is a command-line template, or the filename (and path) of a script plus any parameters required for that script. Good practice is to use the full pathname of the script, with the $CVSROOT variable standing in for the repository path. You may embed one or more format strings in the template or among the script's parameters; you may also use the variables listed later in this chapter, in the section CVSROOT Variables. The character # at the start of a line signals a comment. Blank lines are ignored. There is no way to break a long line in current versions of CVS. CVS processes the file by matching the current repository directory to the regular expression. It looks for the first matching line, and runs the action provided on that line, and also runs the actions on any line with a name-pattern of ALL. Note that DEFAULT as a name-pattern is deemed to match everything, so ensure that it is the last name-pattern other than ALL. Even though you can call several actions with separate ALL lines, the actions are not guaranteed to run in sequence. If you have inter-dependent actions, use a script called by a single ALL line, rather than a set of ALL lines. The format strings are processed by CVS before being passed to the action's script or command. Before processing, the format string consists of a %, followed by a single variable optionally enclosed in braces ({ }), or by a set of variables enclosed in braces. Some of the variables represent individual values, and other represent list values. A set of variables enclosed in braces must all represent list values. Each value represented by a format string variable is passed to its script as a single argument, irrespective of white space within the value. A list on its own is passed as a single argument for each element of the list. A set of list values are also passed as a single argument for each element of each list, but are collated. For instance, %{sVv} in the taginfo file will produce a list of arguments in the format file1 oldversion1 newversion1 file2 oldversion2 newversion2 file3 oldversion3 newversion3. The format string variables which are valid in all files represent single values, and are:
7.3.3. The modules FileThe modules file is used to define CVS modules. A project is defined by the project root directory and contains all files and subdirectories; a module can be an arbitrary set of directories and files. Once a module is defined, the files and directories it describes can be checked out into a sandbox by either the module name or the name of the repository directory (or directories) it represents. The modules file can also specify scripts to run when CVS acts on a file within a module. Each module definition needs to be on a line of its own. When adding directories to module definitions, use relative paths from the repository root directory. Example 7-7 shows a modules file. The lines in the file are explained in the following sections on module definition. Example 7-7. CVSROOT/modules
7.3.3.1. Alias modulesAn alias module can group files and directories into a single module, regardless of where they are stored in the repository tree. The syntax for an alias module definition is: module-name -a path [path...]
The path may be an existing module, a pathname to a file, or a directory path, and there may be any number of paths. If the path leads to a directory, the directory and all subdirectories and files are included in the module. If you wish to exclude a subdirectory in an alias module, use an exclamation mark (!) in front of the directory name. Alias modules cannot have options, nor can you specify scripts to run for them. If you need to use options or scripts, you can define an alias module as part of a regular module, or you can simply use a regular module instead. Alias modules are easier to use than are regular modules (described in the next section). You define alias modules with a space-separated list of all the items you want in the module; regular modules have a more complicated syntax. You can also add multiple directories, files, and modules in an alias module; a regular module allows only one directory. The singer project in Example 7-7 defines an alias module that includes all files and directories in the chorus directory, except those under the subdirectories tenor and bass. This project also includes the descant file from the music directory. When you use an alias module's name in a CVS command which acts on the repository, CVS treats the module name as if the list of items in the path were used instead. When you use an alias module in the checkout command, CVS creates a separate sandbox for each item in the path. 7.3.3.2. Regular modulesA regular module defines options for a project. It can also define subsets of a project or group modules together. If you have a particularly complex project, you may need to define your project with a combination of alias and regular modules. Using alias modules in a complex definition allows you to add multiple directories with one alias, and the regular module allows you to define options to use when calling that module. The syntax to define a regular module is: module-name [options] [directory [filename|subdir...]] [&module...] The directory should be a path relative to the repository root directory. If filenames or subdirectory names are included, they should refer to files or subdirectories in the directory. The module definition then applies only to those files or subdirectories. Note that you need a space between the directory and the files within the directory, and you can define only one directory within a regular module. You can include an existing module in a regular module by prefixing the existing module name with an ampersand (&) and listing it in the regular module definition. The existing module can be an alias or a regular module. If it is not defined in the modules file, it must be a directory path relative to the repository's root directory. This rule is illustrated in the wizsinger module definition in Example 7-7, which includes two existing modules. The sequence of the module definitions doesn't matter; you can include a module in an earlier line than the module's own definition. 7.3.3.3. Module options and scriptsMost of the options for a regular module define scripts to run immediately after a CVS command on the files in the module. Here is the full list of options:
The scripts designated in the modules file run after their respective processes have been completed. If the repository is not on the same computer as the client, CVS stores the scripts for the -i and -u options in the Checkin.prog and Update.prog files in the CVS subdirectories in the sandbox. These scripts will run on the client computer (and are no longer available, as of 1.11.6). All other scripts called from the modules file run on the repository server computer.
The sandbox copies of the Checkin.prog and Update.prog files are not changed when the modules file or the repository computer's copies of the scripts are changed. If you change a module definition or the commit or update scripts for your project, your users must release and recreate their sandboxes. 7.3.4. The commitinfo FileThe commitinfo file is processed before a file is committed and is usually used to enforce project standards for file format or content. It runs very early in the commit, during the tests to determine which files have changed. commitinfo uses the syntax described in "Common Syntax" earlier in this chapter, with one rule per line and each rule consisting of the following elements: name_pattern action format_string If a name_pattern matches the name and path of the directory or module parameter to cvs commit, CVS calls the action and appends as parameters the result of the expanded format_string. In addition to the usual format string variables, it allows s, a list variable containing the names of the files to be committed. The name_pattern may contain DEFAULT, but not ALL.
If you run cvs commit from a sandbox directory without specifying a project, CVS tries to match the repository path that corresponds to your current sandbox directory with a rule in commitinfo. If you run cvs commit with a file or directory parameter, CVS tries to match the repository path that corresponds to that parameter. CVS makes a set of normal-format files from the data it receives from the CVS client and stores them in a temporary directory to allow the action to read a normal file rather than an RCS file. If CVS is running in client/server mode, the script or command in the action runs on the repository computer in a directory that is a copy of the sandbox directory being committed. If this script returns a nonzero value, the commit does not proceed. The script cannot change the file that is being checked; so although you can use a layout-testing program such as the one shown in the following example, you cannot successfully use one that modifies the layout. Example 7-8 shows an indentation tester that can be used with the commitinfo file in Example 7-6. Note that this tester assumes that all files it is called for can be tested validly with indent. Example 7-8. Indentation tester
7.3.5. The loginfo FileThe loginfo file is processed after files have been committed to the repository. During a commit, the file is processed once per directory, after each directory's changes have been successfully stored. During an import, the file is processed once, after the import is complete. During a directory add, it's processed after the directory has been created. loginfo uses the syntax described in "Common Syntax" earlier in this chapter, with one rule per line and each rule consisting of the following elements: name_pattern action format_string If a name_pattern matches the name and path of the directory parameter to cvs commit, CVS calls the action and passes it the log message from the commit on the standard input. CVS also passes the repository path being committed to, followed by an expanded format string. The action can consist of a script, a shell command, or a group of shell commands that will run as one command. The script or command in the action runs on the repository computer. The name_pattern supports both DEFAULT and ALL. In addition to the standard format string variables, loginfo supports:
The loginfo file is usually used to control where (aside from the repository) the log information from cvs commit is sent. It can also be used to trigger actions, such as notifying all developers of changes, maintaining a file that logs a record of changes, or exporting the changed files to a file server. Example 7-9 shows a loginfo file that emails the log message for every change to the user cvsadmin. This file also runs the changelog script that is stored in CVSROOT for every file that is committed to the wizzard project. The line for the teppic project demonstrates a way to call an export script in the background. Example 7-9. A loginfo file
7.3.6. The postadmin FileThe postadmin file defines programs to run after any cvs admin command that modifies a file is run. These programs run on the repository computer. This file is available only in versions 1.12.10 and later. This file uses the standard scripting file syntax, and supports both DEFAULT and ALL. 7.3.7. The postproxy FileThe postproxy file defines programs to run after a secondary server has completed a connection to a primary server, and before the secondary server releases the connection to the client. These programs run on the secondary server, and are called once per directory. It is recommended that the postproxy file include a command to update the secondary server's copy of the repository. This file is available only in versions 1.12.10 and later. This file uses the standard scripting file syntax, and supports both DEFAULT and ALL. It has the additional format variable P, the repository path of the primary server. 7.3.8. The posttag FileThe posttag file defines programs to run after any cvs tag or rtag command that modifies a file is run. These programs run on the repository computer. This file is available only in versions 1.12.10 and later. This file uses the standard scripting file syntax, and supports both DEFAULT and ALL. It permits the same format string attributes as the taginfo file: see the later section "The taginfo File" for more information. 7.3.9. The postwatch FileThe postwatch file defines programs to run after any cvs watch, edit, or unedit command that modifies the repository's watch administrative file, fileattr. See Chapter 6 (specifically the information on fileattr) for more information on which commands are affected. These programs run on the repository computer. This file is available only in versions 1.12.10 and later. This file uses the standard scripting file syntax, and supports both DEFAULT and ALL. Note that edit and unedit do not always contact the server, and sometimes cache their notification to be run later. 7.3.10. The preproxy FileThe preproxy file defines programs to run before a secondary server connects to a primary server, and after the client has contacted the secondary server. These programs run on the secondary server, and are called once, from the top directory specified by the client's request. This file is available only in versions 1.12.10 and later. This file uses the standard scripting file syntax, and supports both DEFAULT and ALL. It has the additional format variable P, the repository path of the primary server. 7.3.11. The rcsinfo FileThe rcsinfo file is processed before a file is committed. It uses the syntax described in "Common Syntax" earlier in this chapter. The action in each rule of an rcsinfo file should not be a path to a script; it should be a path to a template file that will be displayed when CVS asks the user for a log message during a cvs commit operation. If you run cvs commit from a sandbox directory, CVS tries to match the repository path that corresponds to your current sandbox directory with a rule in rcsinfo. If you run cvs commit with a file, directory, or module parameter, CVS tries to match the repository path that corresponds to that parameter. The DEFAULT and ALL rules described in "Common Syntax" are honored. There is no need for a format string. If CVS finds a match, it displays the contents of the template file when it opens an editor to receive a log message. If there is a matching rule and an ALL rule in rcsinfo, CVS displays the contents of the file each rule refers to (that is, it displays the contents of two files). Subject to any editing you do when you commit, the contents of the template file (or files) are stored as part of the log message.
If CVS is running in client/server mode, it stores a copy of the template file in the Template file in the CVS subdirectory of the sandbox when the sandbox is checked out. In CVS versions prior to 1.12.1, this file is not updated with other sandbox files, so if the rcsinfo file or the templates it refers to are changed, your users should release and recreate their sandboxes. (In 1.12.1, the behavior was changed, and template files are updated with other sandbox files.) 7.3.12. The taginfo FileThe taginfo file is processed before a file is tagged using either the tag or the rtag commands. taginfo uses the syntax described in "Common Syntax," earlier in this chapter, with one rule per line and each rule consisting of the following elements: name_pattern action format_string If a name_pattern matches the name and path of the directory or module parameter to cvs tag or cvs rtag, CVS calls the script or command in the action and appends as parameters the result of the expanded format_string. It supports both DEFAULT and ALL. In addition to the usual format string variables, it allows:
If CVS is running in client/server mode, the script given in the action runs on the repository computer. If the script exits with a nonzero exit status, the tag or rtag operation does not proceed. The script cannot modify the tag. The taginfo file is often used to enforce tag name standards in a project. Example 7-10 shows the first part of a parser subroutine that returns 1 if a tag name doesn't fit the project's standards and 0 if it does. Example 7-10. Parsing tag names
7.3.13. The verifymsg FileThe verifymsg file is processed before a file is committed and after you enter the cvs commit log message, either in the editor that CVS opens or by using the -m message or -F file options to cvs commit. verifymsg uses the syntax described in "Common Syntax" of this chapter, with one rule per line and each rule consisting of the following elements: name_pattern action format_string If a name_pattern matches the name and path of the directory or module parameter to cvs commit, CVS calls the action and appends as parameters the result of the expanded format_string. It supports DEFAULT but not ALL. In addition to the usual format string variables, it allows:
If the repository is not on the same computer as the client, the script given in the action runs on the repository computer. If the script returns a nonzero value, the commit does not proceed. The verifymsg file is usually used to enforce project standards for commit log messages, and the script often either checks or modifies the log message you enter when you commit files. The script can modify the log message, and the RereadLogAfterVerify option in the config file in the repository's CVSROOT directory determines whether the original or the modified log message is used. (If the log message is reread, CVS reads it from the temporary file.) See Chapter 6 for information on the config file. |