LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 913|回复: 0

Running Arbitrary Scripts Under CVS

[复制链接]
发表于 2003-10-6 20:21:56 | 显示全部楼层 |阅读模式
Running Arbitrary Scripts Under CVS
by Jennifer Vesperman, author of Essential CVS
06/05/2003  



CVS is a useful version control tool. Version control is not the only aspect of building a project or maintaining a service, though. This article is about the hooks CVS includes to allow you to expand it and integrate it with other tools.

Five files in the CVSROOT directory of the repository enable you to run arbitrary scripts when a file is committed or tagged. Common uses for these files include interfacing CVS to a bug management system, a change tracker, or another tool; enforcing compliance with a project policy; and triggering processes such as automated export programs.

CVS uses one file during tagging and four files during committing:

commitinfo before the files in a directory are committed.
loginfo after the files in a directory are committed.
verifymsg after the log message is entered, but before files are committed.
rcsinfo for the template for the log message in a commit.
taginfo before each tag or rtag operation.
Syntax
Each line of these files should contain a rule with the following syntax: name_pattern action. name_pattern should match a directory in the repository, and CVS will apply this rule to all files in that directory. The pattern used is a regular expression, described in info cvs. CVS tests the pattern against the directory's relative path, starting at the repository root directory.

There are two special patterns, ALL and DEFAULT. An ALL rule is used on files in any directory. A DEFAULT rule is used if no other patterns (excluding ALL) match.

action is a command-line template for the path to a script (or commit message template), plus any parameters required for that script or template. The script or template must be able to read from standard input (stdin). CVS will append its own parameters to actions.

Lines in scripting files that start with the hash symbol (#) are comments and are ignored.

commitinfo
commitinfo scripts are often used to verify whether checked-in files conform to company standards or to enforce exclusive development. CVS passes the relative directory path and a list of all files in that directory involved in the commit as parameters. If the action of the rule returns a non-zero value, the commit does not proceed.

CVS makes a set of normal-format files from the data it receives from the CVS client, storing them in a temporary directory. If the action reads (or tries to modify) the file, it reads the file in the temporary directory. Any modifications are discarded after the action is processed.

loginfo
The loginfo file is most often used to control where (aside from the RCS files) the log information from a 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.

CVS passes the log message from the commit as well as the repository path being committed to, followed by an expanded format string, all on standard input. The format string is part of the action and controls the information that CVS passes to the script or command. The string consists of a % followed by a space, a single variable, or a set of variables enclosed in braces {}. The variables are:

s
Expands to the name of the current file being processed.
V
Expands to the file's revision number prior to the commit.
v
Expands to the file's revision number after the commit.
When CVS process the format string, the output is in the form variable_expansion [variable_expansion...]. CVS will generate a variable expansion for each file that was committed, consisting of a comma-separated set of strings. %{sV} would be expanded to a string like main.c,1.3. Dollar signs ($), backticks (`), backslashes (\), and quotation marks (") in the repository path or filename will be escaped with backslashes.

verifymsg
The scripts in the verifymsg file often either check or modify the log message you enter when you commit files. CVS passes the path to a temporary file containing the commit log message and copies the log message on standard input (stdin). If the script returns a non-zero value, the commit does not proceed.

The script can modify the log message. The RereadLogAfterVerify option in the config file in the repository's CVSROOT directory determines whether the original or the modified log message is used.

The ALL pattern is not supported in the verifymsg file.

rcsinfo
The rcsinfo file doesn't contain scripts to run, it contains the path to a template file for CVS to display when it opens the editor for a log message. Unless you remove them in editing, the contents of the template file are stored as part of the log message in addition to whatever you add. Lines that start with CVS: will be stripped by CVS.

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. 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.

taginfo
taginfo scripts are often used to check that tagnames meet standards, to interact with other programs, or to log tag operations. CVS appends a parameter string in the following format: tagname operation repository_path file_revision_pair [file_revision_pair...]. The file_revision_pair is a space-separated pair of filenames and revision numbers, and there is a pair for each file to be tagged.

The operations CVS provides are add, mov, and del. CVS provides mov when the tag moving option -F is used, del when the tag deletion option -d is used, and add when a new tag is added. If the script exits with a non-zero exit status, the tag (or rtag) operation will not proceed.

Processing
CVS processes the scripting files separately for each directory in the current commit or tag command, calling the script in the scripting file once for each directory it matches. It runs the first rule that matches, or the DEFAULT rule (if any) if there are no matching rules. It also runs any ALL rules.

If any script contains a CVS command, the command that calls the script will not finish until the script does. This can trigger a deadlock if a directory has been locked by the original CVS command, which can't release the lock until the script is finished, but the script can't run until those same locks are released. The deadlock situation can be prevented by having your script call any CVS commands in the background or simply by calling the script in the background.

If the repository is not on the same computer as the client, the script or command in the action is run on the repository computer.

Security
Scripts in these files are run by the user calling CVS, not necessarily the user who added the script. Ensure that only trustworthy users have write access to the CVSROOT directory and the scripting files.

Note: all users must have read and execute access to the CVSROOT directory and write access to the history and val-tags files.

Integration Example: Bugzilla
Bugzilla can accept bug-tracking data via an email form. This integration example relies on it being configured to do so.

Use the rcsinfo file to make a template with the Bugzilla @bugid, @resolution, and @message fields, and the verifymsg file to run a script that ensures that the bug ID, at least, has been filled in. In this example, the verifymsg file then emails the log message to Bugzilla. Bugzilla needs the bug ID in the email subject (which must have the format [Bug XXXX]). The rest of the log message can be sent as the email body.

The script below uses the read command to get the bug ID from the first line of the log message then mails the bug ID and the rest of the input to the user bugzilla on the same computer. The script returns 1 if the format was wrong, which cancels the commit.

#! /bin/bash
read prompt bugid
if [ $prompt != '@bugid' ]; then
        return 1
else
        mail -s "[Bug $bugid]" bugzilla
fi
return 0
This is a template file for rcsinfo to call. Your users should enter the bug ID, resolution status, and a log message to the right of each of these prompts.

CVS: Put the bug ID here
@bugid
CVS: Put the resolution string here. Valid resolutions are...
@resolution
CVS: Record any message you want to add here.
@message
The next example shows the lines in the verifymsg and rcsinfo files that would call these scripts for a project called example, if the scripts were called bugzilla-mail and bugzilla-template.

# In verifymsg, call the script bugzilla-mail
^example\(/\|$\) /var/lib/cvsroot/CVSROOT/scripts/bugzilla-mail

# In rcsinfo, call bugzilla-template
^example\(/\|$\) /var/lib/cvsroot/CVSROOT/scripts/bugzilla-template
Final Words
CVS follows the general Unix ethos of doing one thing and doing it well. These files can allow you expand CVS beyond source and version control, or to integrate CVS with other programs.

Further Reading
man cvs
man 5 cvs
info cvs
CVS Pocket Reference, by Gregor N. Purdy (O'Reilly and Associates)
Essential CVS, by Jennifer Vesperman (O'Reilly and Associates)
From the Big Scary Demons column: "BSD Tricks: CVS"
Sourceforge has several articles on CVS. See sections 6 and 7 on the Sourceforge Site Docs page.
Jennifer Vesperman is the author of Essential CVS. She writes for the O'Reilly Network, the Linux Documentation Project, and occasionally Linux.Com.
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表