cvs-syncmail-2.3/0000755000225600002620000000000010274677117014455 5ustar csaccacsacca00000000000000cvs-syncmail-2.3/syncmail0000644000225600002620000003317410274676773016236 0ustar csaccacsacca00000000000000#! /usr/bin/python # Copyright (c) 2002, 2003, 2004 Barry Warsaw, Fred Drake, and contributors # All rights reserved. # See the accompanying LICENSE file for details. # NOTE: SourceForge currently runs Python 2.2.3, so we need to remain # compatible with at least that version. Python 2.2.2 or newer is # currently required. """Complicated notification for CVS checkins. This script is used to provide email notifications of changes to the CVS repository. These email changes will include context diffs of the changes. Really big diffs will be trimmed. This script is run from a CVS loginfo file (see $CVSROOT/CVSROOT/loginfo). To set this up, create a loginfo entry that looks something like this: mymodule /path/to/this/script %%s some-email-addr@your.domain In this example, whenever a checkin that matches `mymodule' is made, this script is invoked, which will generate the diff containing email, and send it to some-email-addr@your.domain. Note: This module used to also do repository synchronizations via rsync-over-ssh, but since the repository has been moved to SourceForge, this is no longer necessary. The syncing functionality has been ripped out in the 3.0, which simplifies it considerably. Access the 2.x versions to refer to this functionality. Because of this, the script is misnamed. It no longer makes sense to run this script from the command line. Doing so will only print out this usage information. Usage: %(PROGRAM)s [options] <%%S> email-addr [email-addr ...] Where options are: --cvsroot= Use as the environment variable CVSROOT. Otherwise this variable must exist in the environment. --context=# -C # Include # lines of context around lines that differ (default: 2). -c Produce a context diff (default). -m hostname --mailhost hostname The hostname of an available SMTP server. The default is 'localhost'. -u Produce a unified diff (smaller). -S TEXT --subject-prefix=TEXT Prepend TEXT to the email subject line. -R ADDR --reply-to=ADDR Add a "Reply-To: ADDR" header to the email message. --quiet / -q Don't print as much status to stdout. --fromhost=hostname -f hostname The hostname that email messages appear to be coming from. The From: header of the outgoing message will look like user@hostname. By default, hostname is the machine's fully qualified domain name. --help / -h Print this text. The rest of the command line arguments are: <%%S> CVS %%s loginfo expansion. When invoked by CVS, this will be a single string containing the directory the checkin is being made in, relative to $CVSROOT, followed by the list of files that are changing. If the %%s in the loginfo file is %%{sVv}, context diffs for each of the modified files are included in any email messages that are generated. email-addrs At least one email address. """ __version__ = '$Revision: 2.3 $' import os import re import pwd import sys import time import getopt import socket import smtplib from cStringIO import StringIO from email.Utils import formataddr # Which SMTP server to do we connect to? MAILHOST = 'localhost' MAILPORT = 25 # Diff trimming stuff DIFF_HEAD_LINES = 20 DIFF_TAIL_LINES = 20 DIFF_TRUNCATE_IF_LARGER = 1000 COMMASPACE = ', ' PROGRAM = sys.argv[0] BINARY_EXPLANATION_LINES = [ "(This appears to be a binary file; contents omitted.)\n" ] NOVERSION = "Couldn't generate diff; no version number found for file: %s" BACKSLASH = "Couldn't generate diff: backslash in filespec's filename: %s" def usage(code, msg=''): print __doc__ % globals() if msg: print msg sys.exit(code) def calculate_diff(entry, contextlines): file = entry.name oldrev = entry.revision newrev = entry.new_revision # Make sure we can find a CVS version number if oldrev is None and newrev is None: return NOVERSION % file if file.find("'") <> -1: # Those crazy users put single-quotes in their file names! Now we # have to escape everything that is meaningful inside double-quotes. filestr = filestr.replace('\\', '\\\\') filestr = filestr.replace('`', '\`') filestr = filestr.replace('"', '\"') filestr = filestr.replace('$', '\$') # and quote it with double-quotes. filestr = '"' + filestr + '"' else: # quote it with single-quotes. filestr = "'" + file + "'" if oldrev is None: # File is being added. try: if os.path.exists(file): fp = open(file) else: update_cmd = "cvs -fn update -r %s -p %s" % (newrev, filestr) fp = os.popen(update_cmd) lines = fp.readlines() fp.close() # Is this a binary file? Let's look at the first few # lines to figure it out: for line in lines[:5]: for c in line.rstrip(): if c.isspace(): continue if c < ' ' or c > chr(127): lines = BINARY_EXPLANATION_LINES[:] break lines.insert(0, '--- NEW FILE: %s ---\n' % file) except IOError, e: lines = ['***** Error reading new file: ', str(e), '\n***** file: ', file, ' cwd: ', os.getcwd()] elif newrev is None: lines = ['--- %s DELETED ---\n' % file] else: # File has been changed. # This /has/ to happen in the background, otherwise we'll run into CVS # lock contention. What a crock. if contextlines > 0: difftype = "-C " + str(contextlines) else: difftype = "-u" diffcmd = "/usr/bin/cvs -f diff -kk %s --minimal -r %s -r %s %s" \ % (difftype, oldrev, newrev, filestr) fp = os.popen(diffcmd) lines = fp.readlines() # ignore the error code, it always seems to be 1 :( fp.close() if len(lines) > DIFF_TRUNCATE_IF_LARGER: removedlines = len(lines) - DIFF_HEAD_LINES - DIFF_TAIL_LINES del lines[DIFF_HEAD_LINES:-DIFF_TAIL_LINES] lines.insert(DIFF_HEAD_LINES, '[...%d lines suppressed...]\n' % removedlines) return ''.join(lines) rfc822_specials_re = re.compile(r'[\(\)\<\>\@\,\;\:\\\"\.\[\]]') def quotename(name): if name and rfc822_specials_re.search(name): return '"%s"' % name.replace('"', '\\"') else: return name def blast_mail(subject, people, entries, contextlines, fromhost, replyto): # cannot wait for child process or that will cause parent to retain cvs # lock for too long. Urg! if not os.fork(): # in the child # give up the lock you cvs thang! time.sleep(2) # Create the smtp connection to the localhost conn = smtplib.SMTP() conn.connect(MAILHOST, MAILPORT) pwinfo = pwd.getpwuid(os.getuid()) user = pwinfo[0] name = pwinfo[4] domain = fromhost or socket.getfqdn() address = '%s@%s' % (user, domain) s = StringIO() datestamp = time.strftime('%a, %d %b %Y %H:%M:%S +0000', time.gmtime(time.time())) vars = {'author' : formataddr((name, address)), 'people' : COMMASPACE.join(people), 'subject' : subject, 'version' : __version__, 'date' : datestamp, } print >> s, '''\ From: %(author)s To: %(people)s''' % vars if replyto: print >> s, 'Reply-To: %s' % replyto print >>s, '''\ Subject: %(subject)s Date: %(date)s X-Mailer: Python syncmail %(version)s ''' % vars s.write(sys.stdin.read()) # append the diffs if available print >> s for entry in entries: print >> s, calculate_diff(entry, contextlines) resp = conn.sendmail(address, people, s.getvalue()) conn.close() os._exit(0) class CVSEntry: def __init__(self, name, revision, timestamp, conflict, options, tagdate): self.name = name self.revision = revision self.timestamp = timestamp self.conflict = conflict self.options = options self.tagdate = tagdate def get_entry(prefix, mapping, line, filename): line = line.strip() parts = line.split("/") _, name, revision, timestamp, options, tagdate = parts key = namekey(prefix, name) try: entry = mapping[key] except KeyError: if revision == "0": revision = None if timestamp.find("+") != -1: timestamp, conflict = tuple(timestamp.split("+")) else: conflict = None entry = CVSEntry(key, revision, timestamp, conflict, options, tagdate) mapping[key] = entry return entry def namekey(prefix, name): if prefix: return os.path.join(prefix, name) else: return name def load_change_info(prefix=None): if prefix is not None: entries_fn = os.path.join(prefix, "CVS", "Entries") else: entries_fn = os.path.join("CVS", "Entries") entries_log_fn = entries_fn + ".Log" mapping = {} f = open(entries_fn) while 1: line = f.readline() if not line: break ## if line.strip() == "D": ## continue # we could recurse down subdirs, except the Entries.Log files # we need haven't been written to the subdirs yet, so it # doesn't do us any good ## if line[0] == "D": ## name = line.split("/")[1] ## dirname = namekey(prefix, name) ## if os.path.isdir(dirname): ## m = load_change_info(dirname) ## mapping.update(m) if line[0] == "/": # normal file get_entry(prefix, mapping, line, entries_fn) # else: bogus Entries line f.close() if os.path.isfile(entries_log_fn): f = open(entries_log_fn) while 1: line = f.readline() if not line: break if line[1:2] != ' ': # really old version of CVS break entry = get_entry(prefix, mapping, line[2:], entries_log_fn) parts = line.split("/")[1:] if line[0] == "A": # adding a file entry.new_revision = parts[1] elif line[0] == "R": # removing a file entry.new_revision = None f.close() for entry in mapping.values(): if not hasattr(entry, "new_revision"): # We're running as part of a commit from a local # filesystem access to the repository, so we're looking at # a working copy. There may be lots of files we are # supposed to ignore. del mapping[entry.name] return mapping def load_branch_name(): tag_fn = os.path.join("CVS", "Tag") if os.path.isfile(tag_fn): f = open(tag_fn) line = f.readline().strip() f.close() if line[:1] == "T": return line[1:] return None # scan args for options def main(): # XXX Should really move all the options to an object, just to # avoid threading so many positional args through everything. try: opts, args = getopt.getopt( sys.argv[1:], 'hC:cuS:R:qf:m:', ['fromhost=', 'context=', 'cvsroot=', 'mailhost=', 'subject-prefix=', 'reply-to=', 'help', 'quiet']) except getopt.error, msg: usage(1, msg) # parse the options contextlines = 2 verbose = 1 subject_prefix = "" replyto = None fromhost = None for opt, arg in opts: if opt in ('-h', '--help'): usage(0) elif opt == '--cvsroot': os.environ['CVSROOT'] = arg elif opt in ('-C', '--context'): contextlines = int(arg) elif opt == '-c': if contextlines <= 0: contextlines = 2 elif opt == '-u': contextlines = 0 elif opt in ('-S', '--subject-prefix'): subject_prefix = arg elif opt in ('-R', '--reply-to'): replyto = arg elif opt in ('-q', '--quiet'): verbose = 0 elif opt in ('-f', '--fromhost'): fromhost = arg elif opt in ('-m', '--mailhost'): global MAILHOST MAILHOST = arg # What follows is the specification containing the files that were # modified. The argument actually must be split, with the first component # containing the directory the checkin is being made in, relative to # $CVSROOT, followed by the list of files that are changing. if not args: usage(1, 'No CVS module specified') subject = subject_prefix + args[0] specs = args[0].split() del args[0] # The remaining args should be the email addresses if not args: usage(1, 'No recipients specified') # Now do the mail command people = args if specs[-3:] == ['-', 'Imported', 'sources']: print 'Not sending email for imported sources.' return branch = load_branch_name() changes = load_change_info() if verbose: print 'Mailing %s...' % COMMASPACE.join(people) print 'Generating notification message...' blast_mail(subject, people, changes.values(), contextlines, fromhost, replyto) if verbose: print 'Generating notification message... done.' if __name__ == '__main__': main() sys.exit(0) cvs-syncmail-2.3/branchctl0000644000225600002620000002653710274677017016354 0ustar csaccacsacca00000000000000#! /usr/bin/env python # # Script to control whether CVS branches are open or closed for # changes. # # This is intended to be called from the commitinfo hook. """\ Script which controls the use of branches within a CVS repository. Usage: %(PROGRAM)s [options] [<%%S> [email-addr ...]] Where options are: --config=file Use file as the configuration file. By default, a file named %(DEFAULT_CONFIGURATION_FILE)s is used if it exists. If the name of the configuration file is relative, it is interpreted as relative to the CVSROOT administrative directory of the repository. --config is incompatible with --no-config. --no-config Do not use a configuration file. This can be used to disable the use of the default configuration file. --no-config is incompatible with --config. --cvsroot= Use as the environment variable CVSROOT. Otherwise this variable must exist in the environment. --quiet / -q Don't print as much status to stdout. --help / -h Print this text. """ # The configuration data can co-exist in the same configuration file # with the configuration for the "new-world" version of syncmail. import getopt import os import re import socket import string import sys try: from socket import getfqdn except ImportError: def getfqdn(): # Python 1.5.2 :( hostname = socket.gethostname() byaddr = socket.gethostbyaddr(socket.gethostbyname(hostname)) aliases = byaddr[1] aliases.insert(0, byaddr[0]) aliases.insert(0, hostname) for fqdn in aliases: if '.' in fqdn: break else: fqdn = 'localhost.localdomain' return fqdn DEFAULT_CONFIGURATION_FILE = "branchctl.conf" DEFAULT_CONFIGURATION = { "verbose": "true", "open": "true", "closed-message": "", "cross-branch-commits": "true", } def usage(code, msg=''): print __doc__ % globals() if msg: print msg sys.exit(code) class CVSEntry: def __init__(self, name, revision, timestamp, conflict, options, tagdate): self.name = name self.revision = revision self.timestamp = timestamp self.conflict = conflict self.options = options self.tagdate = tagdate def get_entry(prefix, mapping, line, filename): line = string.strip(line) parts = string.split(line, "/") _, name, revision, timestamp, options, tagdate = parts tagdate = string.rstrip(tagdate) or None if tagdate: assert tagdate[0] == "T" tagdate = tagdate[1:] key = namekey(prefix, name) try: entry = mapping[key] except KeyError: if revision == "0": revision = None if "+" in timestamp: timestamp, conflict = tuple(string.split(timestamp, "+")) else: conflict = None entry = CVSEntry(key, revision, timestamp, conflict, options, tagdate) mapping[key] = entry return entry def namekey(prefix, name): if prefix: return os.path.join(prefix, name) else: return name def load_entries(prefix=None): if prefix is not None: entries_fn = os.path.join(prefix, "CVS", "Entries") else: entries_fn = os.path.join("CVS", "Entries") mapping = {} f = open(entries_fn) while 1: line = f.readline() if not line: break ## if string.strip(line) == "D": ## continue # we could recurse down subdirs, except the Entries.Log files # we need haven't been written to the subdirs yet, so it # doesn't do us any good ## if line[0] == "D": ## name = string.split(line, "/")[1] ## dirname = namekey(prefix, name) ## if os.path.isdir(dirname): ## m = load_entries(dirname) ## mapping.update(m) if line[0] == "/": # normal file get_entry(prefix, mapping, line, entries_fn) # else: bogus Entries line f.close() return mapping def load_branch_name(): tag_fn = os.path.join("CVS", "Tag") if os.path.isfile(tag_fn): f = open(tag_fn) line = string.strip(f.readline()) f.close() if line[:1] == "T": return line[1:] return None TRUE_VALUES = ('true', 'on', 'enabled') FALSE_VALUES = ('false', 'off', 'disabled') class OptionLookup: def __init__(self, dicts, branch=None): self._dicts = dicts self._replace = Replacer({ "BRANCH": branch or "", "CVSROOT": os.environ.get("CVSROOT", ""), "HOSTNAME": os.environ.get("HOSTNAME") or getfqdn(), }) def get(self, option): for dict in self._dicts: v = dict.get(option) if v is not None: return self._replace(v) return None def getbool(self, option): v = self.get(option) if v is not None: v = string.lower(v) if v in TRUE_VALUES: v = 1 elif v in FALSE_VALUES: v = 0 else: raise ValueError("illegal boolean value: %s" % `v`) return v def getint(self, option): v = self.get(option) if v is not None: v = int(v) return v def getaddress(self, option): """Return (host, port) for a host:port or host string. The port, if ommitted, will be None. """ v = self.get(option) if v is None: return MAILHOST, MAILPORT elif ":" in v: h, p = tuple(string.split(v, ":")) p = int(p) return h or MAILHOST, p else: return v, MAILPORT # Support for $VARIABLE replacement. class Replacer: def __init__(self, vars): self._vars = vars rx = re.compile(r"\$([a-zA-Z][a-zA-Z_]*\b|\{[a-zA-Z][a-zA-Z_]*\})") self._search = rx.search def __call__(self, v): v, name, suffix = self._split(v) while name: v = v + self._vars.get(name, "") prefix, name, suffix = self._split(suffix) v = v + prefix return v def _split(self, s): m = self._search(s) if m is not None: name = m.group(1) if name[0] == "{": name = name[1:-1] return s[:m.start()], name, s[m.end():] else: return s, None, '' def get_section_as_dict(config, section): d = {} if config.has_section(section): for opt in config.options(section): d[opt] = config.get(section, opt, raw=1) return d from ConfigParser import ConfigParser class ConfigParser(ConfigParser): # Regular expressions for parsing section headers and options, # from the Python 2.3 version of ConfigParser. SECTCRE = re.compile( r'\[' # [ r'(?P
[^]]+)' # very permissive! r'\]' # ] ) # For compatibility with older versions: __SECTCRE = SECTCRE class ConfigurationDatabase: def __init__(self, filename, cmdline, args): self.args = args self.cmdline = cmdline self.config = None if filename and os.path.isfile(filename): self.config = ConfigParser() if hasattr(self.config, "readfp"): self.config.readfp(open(filename), filename) else: # We have to use this old method for compatibility with # ancient versions of Python. self.config.read([filename]) def get_config(self, branch): dicts = [] if self.config: cp = self.config if branch: dicts.append(get_section_as_dict(cp, "branch " + branch)) dicts.append(get_section_as_dict(cp, "branch")) dicts.append(self.cmdline) dicts.append(get_section_as_dict(cp, "general")) else: dicts.append(self.cmdline) dicts = filter(None, dicts) dicts.append(DEFAULT_CONFIGURATION) return Options(OptionLookup(dicts, branch), self.args) class OptionsBase: def __init__(self, config, args): self.args = args self.verbose = config.getbool('verbose') fn = os.path.join("CVS", "Repository") if os.path.isfile(fn): f = open(fn) self.repodir = string.strip(f.readline()) f.close() else: self.repodir = os.curdir def get_admin_file(name): if os.environ.has_key("CVSROOT"): p = os.path.join(os.environ["CVSROOT"], "CVSROOT", name) return os.path.abspath(p) else: return os.path.join("CVSROOT", name) def load_configuration(args): cmdline, args = load_cmdline(args) if cmdline.has_key('config-file'): cfgfile = get_admin_file(cmdline['config-file']) del cmdline['config-file'] else: defconfig = get_admin_file(DEFAULT_CONFIGURATION_FILE) if os.path.isfile(defconfig): cfgfile = defconfig else: cfgfile = None return ConfigurationDatabase(cfgfile, cmdline, args) class Options(OptionsBase): def __init__(self, config, args): OptionsBase.__init__(self, config, args) self.open = config.getbool("open") self.closed_message = config.get("closed-message") self.cross_commits = config.getbool("cross-branch-commits") def load_cmdline(args): try: opts, args = getopt.getopt(args, 'hq', ['cvsroot=', 'config=', 'no-config', 'help', 'quiet']) except getopt.error, msg: usage(2, msg) cmdline = {} def set(option, value, cmdline=cmdline): if cmdline.has_key(option): usage(2, "can't set option more than once") cmdline[option] = value for opt, arg in opts: if opt in ('-h', '--help'): usage(0) elif opt == '--cvsroot': os.environ["CVSROOT"] = arg elif opt == "--config": set('config-file', arg) elif opt == '--no-config': set('config-file', '') elif opt in ('-q', '--quiet'): set('verbose', 'false') return cmdline, args def main(): branch = load_branch_name() configdb = load_configuration(sys.argv[1:]) changes = load_entries().values() d = {} for change in changes: tag = change.tagdate or branch if d.has_key(tag): d[tag].append(change) else: d[tag] = [change] denied = 0 crossed_branches = len(d) > 1 for tag in d.keys(): config = configdb.get_config(tag) if tag: branchname = "branch " + tag else: branchname = "trunk" if not config.open: if not denied: denied = 1 print why = config.closed_message if why: print branchname, "is closed:", why else: print branchname, "is closed" if crossed_branches and not config.cross_commits: if not denied: denied = 1 print print branchname, "does not permit cross-branch commits" if denied: print sys.exit(1) if __name__ == '__main__': main() cvs-syncmail-2.3/README0000644000225600002620000000116510274677036015340 0ustar csaccacsacca00000000000000README for syncmail, a notification program for CVS checkins. syncmail is a script that is used to provide email notification of changes to a CVS repository. For more information, including installation instructions, read the syncmail(1) manpage, or type "syncmail --help". This project is maintained at SourceForge: http://sourceforge.net/projects/cvs-syncmail/ And there is a mailing list for discussing syncmail: cvs-syncmail-talk@lists.sourceforge.net See the LICENSE file for copyright information. Our thanks to Zooko for helping improve the security of the script. -Barry Warsaw & Fred Drake (maintainers) cvs-syncmail-2.3/LICENSE0000644000225600002620000000302110274677065015460 0ustar csaccacsacca00000000000000Copyright (c) 2002, 2003, Barry Warsaw, Fred Drake, and contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the names of the authors nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cvs-syncmail-2.3/tests/0000775000225600002620000000000010274677113015615 5ustar csaccacsacca00000000000000cvs-syncmail-2.3/docs/0000775000225600002620000000000010274700240015367 5ustar csaccacsacca00000000000000cvs-syncmail-2.3/doc/branchctl.sgml0000644000225600002620000003042110274677170020045 0ustar csaccacsacca00000000000000 manpage.1'. You may view the manual page with: `docbook-to-man manpage.sgml | nroff -man | less'. A typical entry in a Makefile or Makefile.am is: manpage.1: manpage.sgml docbook-to-man $< > $@ --> Fred"> Drake"> July 14, 2003"> 1"> fdrake@acm.org"> branchctl"> Debian GNU/Linux"> GNU"> SourceForge"> ]>
&dhemail;
&dhfirstname; &dhsurname; 2003 &dhusername; &dhdate;
&dhucpackage; &dhsection; &dhpackage; Control access to CVS repositories by branch &dhpackage; --config file --no-config --cvsroot path | Description &dhpackage; takes care of disallowing checkins for branches that have been marked "off-limits". In any large project using CVS branches, some branches will be active, some will have been merged into other branches or the trunk, and others will have been bypassed. CVS really does not provide tools to make easy to determine which branches are still being used, and it's easy for someone new to a project to find an interesting tangent in a branch and start working on it, even though the branch has been abandoned or has already been merged into another branch where the features of the original branch are to be maintained. CVS also allows a single commit to affect files on more than one branch; this is possible by committing two files in one working directory after using cvs up -r to move one of them to a different branch. &dhpackage; allows the repository administrator to disallow such commits. &dhpackage; works by integrating with CVS in the repository using the configuration files in the repository's CVSROOT module. When CVS executes commands from the commitinfo file, &dhpackage; is invoked if it has been configured. Setting Up branchctl Setting up &dhpackage; is not difficult, but there are usually several steps: Install &dhpackage;. This is usually done by adding it to your CVS repository, but it may be located in a directory on the default PATH, or just about anywhere else. Configure CVS to invoke &dhpackage;. This is a matter of adding and/or changing some of the configuration files in the CVSROOT module in the repository. Install &dhpackage; &dhpackage; consists of a single Python script; it does not need any supplemental data files. There are two approaches to installing the script: check it into the repository or place it in a shared location on the CVS server . To install &dhpackage; by checking it into the repository itself, check out a working copy of the CVSROOT module. Add the name &dhpackage; to the file checkoutlist in that directory as well, and commit that change. This will cause a copy of &dhpackage; to be checked out into the repository itself. Copy te &dhpackage; script into the directory, make sure that it is executable by everyone (you should use chmod a+x &dhpackage; for this), and use the cvs add and cvs commit commands to add it to the repository. Once the commit is complete, a checked-out copy of the &dhpackage; script should be located in the repository in the CVSROOT directory in the repository. This is the usual way of integrating &dhpackage; into a CVS repository. To install &dhpackage; outside of the repository, find a location for the script. This can be in a "bin" directory such as /usr/local/bin/, or can be in some other location. The only requirement is that all users of the repository be able to execute the script (you should use chmod a+x &dhpackage; for this). This approach requires direct access to the CVS server machine, and is most useful if several repositories are going to share a single copy of &dhpackage; (maybe to ensure the same version is used for each; it's not large enough for disk space to be an issue). Configure CVS to use &dhpackage; Getting the CVS server to invoke &dhpackage; requires editing one more file in the CVSROOT module of the repository. Even if you're using a shared installation of &dhpackage;, this configuration needs to be performed for each repository. The commitinfo file in the CVSROOT module needs to be modified to invoke &dhpackage; when appropriate. Just when is appropriate depends entirely on your project. If your commitinfo file still contains the comments that cvs init copies in, this is a good time to read them if you haven't. If the file does not already contain any configuration lines, you can simply add to the end of the file. Here are some example lines to get you started: DEFAULT $CVSROOT/CVSROOT/branchctl ProjectOne $CVSROOT/CVSROOT/branchctl --no-config ProjectTwo $CVSROOT/CVSROOT/branchctl --config project-two.conf The first line causes the default configuration file, &dhpackage;.conf, to be used everywhere that doesn't use an alternate invocation of &dhpackage;. The second line tells CVS to use &dhpackage;'s internal configuration defaults instead of reading a configuration file, but to only do so in the the ProjectOne directory of the repository. The third line tells CVS to run &dhpackage; using a separate configuration file for the ProjectTwo directory in the repository. To finish the repository configuration, commit the changes you've made. Once the CVS server has reported that it is "Rebuilding administrative file database", your repository is configured to use &dhpackage;. Options When an option includes an argument, you may specify the argument either separate ("-d output") or mashed ("-doutput"). &dhpackage; supports both. For long options which include an argument, the argument may be separated from the option ("--fromhost example.com") or mashed, but with an equals sign between the option and the argument ("--fromhost=example.com"). Use file as the configuration file for &dhpackage;. By default, a file named &dhpackage;.conf is used if it exists. If the name of the configuration file is relative, it is interpreted as relative to the CVSROOT administrative directory of the repository. is incompatible with . Do not use a configuration file for &dhpackage;. This can be used to disable the use of the default configuration file. is incompatible with . Note that it's not normally useful to specify this option, but it may be useful when you want to allow changes to any branch within a single CVS module, but use a more sophisticated configuration for the rest of the repository. Use path as the value for the CVSROOT environment variable. This is usually not needed. Print a summary of the command line options to standard output. Bugs There are probably some bugs. If you find them, please report them to the maintainers using the bug tracker. See Also The &dhpackage; page on &sourceforge;. The CVS home page. Author &dhpackage; was originally written by Fred Drake. This manual page was written by &dhusername; &dhemail;.
cvs-syncmail-2.3/doc/syncmail.sgml0000644000225600002620000004354710274677202017735 0ustar csaccacsacca00000000000000 manpage.1'. You may view the manual page with: `docbook-to-man manpage.sgml | nroff -man | less'. A typical entry in a Makefile or Makefile.am is: manpage.1: manpage.sgml docbook-to-man $< > $@ --> Fred"> Drake"> July 15, 2003"> 1"> fdrake@acm.org"> syncmail"> Debian GNU/Linux"> GNU"> SourceForge"> ]>
&dhemail;
&dhfirstname; &dhsurname; 2002 &dhusername; &dhdate;
&dhucpackage; &dhsection; &dhpackage; Send email notifications of CVS activity &dhpackage; --cvsroot path --context-C lines -c -u | --fromhost hostname -f hostname --mailhost hostname -m hostname --reply-to email-address -R email-address --subject-prefix string -S string | %{sSv} email Description &dhpackage; sends out notifications of CVS commits via email, including the patch that was applied for changed files, the content of new files, or notes about files that were removed. In any large project, keeping track of changes is difficult. CVS does a reasonable job of allowing source changes to be controlled and managed, but does not provide tools to make it easier to work with a changing code base. The hardest part of working on a dynamic project with many changing modules is knowing when changes occur, and what those changes are. Software developers often are heavy email users, spending huge amounts of time working with their email software. Open source developers are among the most serious email addicts out there, sorting through hundreds of emails a day, since this is often the only way to stay in touch with users and fellow developers. Clearly, we need more email. &dhpackage; works by integrating with CVS in the repository using the configuration files in the repository's CVSROOT module. When CVS executes commands from the loginfo file, &dhpackage; is invoked if its been configured, and it sends email to one or more email addresses specified on the command line. Setting Up syncmail Setting up &dhpackage; is not difficult, but there are usually several steps: Set up a mailing list. Strictly speaking, this is optional, but with most good mailing list managers, it's easier to maintain a mailing list than it is to continually update a list of individual email addresses on the &dhpackage; command line. How this is done depends on many things, but not &dhpackage;, so will not be further covered here. Install &dhpackage;. This is usually done by adding it to your CVS repository, but it may be located in a directory on the default PATH, or just about anywhere else. Configure CVS to invoke &dhpackage;. This is a matter of adding and/or changing some of the configuration files in the CVSROOT module in the repository. Install &dhpackage; &dhpackage; consists of a single Python script; it does not need any supplemental data files. There are two approaches to installing the script: check it into the repository or place it in a shared location on the CVS server . To install &dhpackage; by checking it into the repository itself, check out a working copy of the CVSROOT module. Add the name syncmail to the file checkoutlist in that directory as well, and commit that change. This will cause a copy of &dhpackage; to be checked out into the repository itself. Copy te &dhpackage; script into the directory, make sure that it is executable by everyone (you should use chmod a+x syncmail for this), and use the cvs add and cvs commit commands to add it to the repository. Once the commit is complete, a checked-out copy of the &dhpackage; script should be located in the repository in the CVSROOT directory in the repository. This is the usual way of integrating &dhpackage; into a CVS repository. To install &dhpackage; outside of the repository, find a location for the script. This can be in a "bin" directory such as /usr/local/bin/, or can be in some other location. The only requirement is that all users of the repository be able to execute the script (you should use chmod a+x syncmail for this). This approach requires direct access to the CVS server machine, and is most useful if several repositories are going to share a single copy of &dhpackage; (maybe to ensure the same version is used for each; it's not large enough for disk space to be an issue). Configure CVS to use &dhpackage; Getting the CVS server to invoke &dhpackage; requires editing one more file in the CVSROOT module of the repository. Even if you're using a single installation of &dhpackage;, this configuration needs to be performed for each repository. The loginfo file in the CVSROOT module needs to be modified to invoke &dhpackage; when appropriate. Just when is appropriate depends entirely on your project. If your loginfo file still contains the comments that cvs init copies in, this is a good time to read them if you haven't. If the file does not already contain any configuration lines, you can simply add to the end of the file. Here are two example lines to get you started: CVSROOT $CVSROOT/CVSROOT/syncmail %{sVv} you@example.com DEFAULT $CVSROOT/CVSROOT/syncmail %{sVv} myproject-checkins@example.com This will cause email to be sent to two different places, with which depending on what files in the repository are affected. For administrative files in the CVSROOT module, email will be sent to you@example.com; you should probably list all your project administrators here. For all other files, email will be sent to the addresses you specify. If you have several sub-products for which you want different checkin lists, you can change the "DEFAULT" label to match the subtree that you want to go to each list, with a separate line for each distinct prefix. For example, if your repository includes the modules "one" and "two", you could use the following: CVSROOT $CVSROOT/CVSROOT/syncmail %{sVv} you@example.com one/ $CVSROOT/CVSROOT/syncmail %{sVv} myproject-one-cvs@example.com two/ $CVSROOT/CVSROOT/syncmail %{sVv} myproject-two-cvs@exmaple.com Note that %{sSv} is magic that CVS understands and replaces with information about the files that are affected; be sure to enter that exactly as shown, just before the email addresses. Command line options for &dhpackage; should be placed between the name of the &dhpackage; command and the %{sSv}. You can still have a "DEFAULT" line that gets used for any additional subprojects. If you do not have a stock loginfo file, then you can probably figure out what you need to do to combine the information above with your existing changes. If the command lines in the file become too long for comfort, some helper scripts can be added to the CVSROOT module (remember to add their names to the checkoutlist as well!). To finish the repository configuration, commit the changes you've made. Once the CVS server has reported that it is "Rebuilding administrative file database", your repository is configured to use &dhpackage;. Options When an option includes an argument, you may specify the argument either separate ("-d output") or mashed ("-doutput"). &dhpackage; supports both. For long options which include an argument, the argument may be separated from the option ("--fromhost example.com") or mashed, but with an equals sign between the option and the argument ("--fromhost=example.com"). Use path as the value for the CVSROOT environment variable. This is usually not needed. Generate context diffs with lines lines of context displayed on either side of the changed portion. Generate context diffs with two lines of context shown on either side of the changed portion. This is the default. Generate unified diffs instead of context diffs. Unified diffs are typically shorted than context diffs, but many users find it easier to read context diffs. Do not display progress information to the user. By default, &dhpackage; will display the email addresses it is sending mail to and note when it starts generating the notification email and when it is done sending the email. Specify the host name that email should appear to come from. By default, &dhpackage; uses the fully qualified name for the host it's running on, and lets the local MTA take care of host name translation. Specify the host name that should be used to submit mail via SMTP. By default, &dhpackage; uses localhost. Specify an email address that should be used for the Reply-To header in email. This header is not normally used. Provide a string that is pre-pended to the subject of generated email. This prefix is often of the form '[Checkins]', allowing mail filters to easily identify mail from syncmail for a specific CVS repository or project. This is often not needed if mail is being sent to a mailing list manager that adds a prefix of it's own. Print a summary of the command line options to standard output. Bugs There are probably some bugs. If you find them, please report them to the maintainers using the bug tracker. Alternatives Other people have written tools that serve similar purposes, but not all of these are meant to support CVS repositories accessed from remote locations (anything other than direct filesystem access). A mostly-equivalent package, written in Perl, is available as cvs-syncmail (Perl version). log_accum is another Perl implementation, but there appears to be no authoritative source of information for this package. Please inform the &dhpackage; maintainers if you can provide current references to these efforts. See Also The &dhpackage; page on &sourceforge;. The CVS home page. Author &dhpackage; was originally written by Barry Warsaw to send mail based on checkins to the Python project. Barry continues to maintain &dhpackage; with help from &dhusername; and others. This manual page was written by &dhusername; &dhemail;.
cvs-syncmail-2.3/doc/branchctl.10000644000225600002620000001616610274677360017256 0ustar csaccacsacca00000000000000.\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "BRANCHCTL" "1" "21 July 2003" "" "" .SH NAME branchctl \- Control access to CVS repositories by branch .SH SYNOPSIS \fBbranchctl\fR [ \fB--config \fIfile\fB\fR ] [ \fB--no-config\fR ] [ \fB--cvsroot \fIpath\fB\fR ] [ \fB--help | -h\fR ] .SH "DESCRIPTION" .PP \fBbranchctl\fR takes care of disallowing checkins for branches that have been marked "off-limits". .PP In any large project using CVS branches, some branches will be active, some will have been merged into other branches or the trunk, and others will have been bypassed. CVS really does not provide tools to make easy to determine which branches are still being used, and it's easy for someone new to a project to find an interesting tangent in a branch and start working on it, even though the branch has been abandoned or has already been merged into another branch where the features of the original branch are to be maintained. .PP CVS also allows a single commit to affect files on more than one branch; this is possible by committing two files in one working directory after using \fBcvs up -r\fR to move one of them to a different branch. \fBbranchctl\fR allows the repository administrator to disallow such commits. .PP branchctl works by integrating with CVS in the repository using the configuration files in the repository's CVSROOT module. When CVS executes commands from the \fIcommitinfo\fR file, branchctl is invoked if it has been configured. .SH "SETTING UP BRANCHCTL" .PP Setting up branchctl is not difficult, but there are usually several steps: .TP 3 1. Install branchctl. This is usually done by adding it to your CVS repository, but it may be located in a directory on the default \fBPATH\fR, or just about anywhere else. .TP 3 2. Configure CVS to invoke branchctl. This is a matter of adding and/or changing some of the configuration files in the CVSROOT module in the repository. .SS "INSTALL BRANCHCTL" .PP branchctl consists of a single Python script; it does not need any supplemental data files. There are two approaches to installing the script: check it into the repository, or place it in a shared location on the CVS server. .PP To install branchctl by checking it into the repository itself, check out a working copy of the CVSROOT module. Add the name branchctl to the file \fIcheckoutlist\fR in that directory as well, and commit that change. This will cause a copy of branchctl to be checked out into the repository itself. Copy te branchctl script into the directory, make sure that it is executable by everyone (you should use \fBchmod a+x branchctl\fR for this), and use the \fBcvs add\fR and \fBcvs commit\fR commands to add it to the repository. Once the commit is complete, a checked-out copy of the branchctl script should be located in the repository in the \fICVSROOT\fR directory in the repository. This is the usual way of integrating branchctl into a CVS repository. .PP To install branchctl outside of the repository, find a location for the script. This can be in a "bin" directory such as \fI/usr/local/bin/\fR, or can be in some other location. The only requirement is that all users of the repository be able to execute the script (you should use \fBchmod a+x branchctl\fR for this). This approach requires direct access to the CVS server machine, and is most useful if several repositories are going to share a single copy of branchctl (maybe to ensure the same version is used for each; it's not large enough for disk space to be an issue). .SS "CONFIGURE CVS TO USE BRANCHCTL" .PP Getting the CVS server to invoke branchctl requires editing one more file in the \fICVSROOT\fR module of the repository. Even if you're using a shared installation of branchctl, this configuration needs to be performed for each repository. .PP The \fIcommitinfo\fR file in the \fICVSROOT\fR module needs to be modified to invoke branchctl when appropriate. Just when is appropriate depends entirely on your project. If your \fIcommitinfo\fR file still contains the comments that \fBcvs init\fR copies in, this is a good time to read them if you haven't. If the file does not already contain any configuration lines, you can simply add to the end of the file. .PP Here are some example lines to get you started: .nf DEFAULT $CVSROOT/CVSROOT/branchctl ProjectOne $CVSROOT/CVSROOT/branchctl --no-config ProjectTwo $CVSROOT/CVSROOT/branchctl --config project-two.conf .fi .PP The first line causes the default configuration file, \fIbranchctl.conf\fR, to be used everywhere that doesn't use an alternate invocation of branchctl. .PP The second line tells CVS to use branchctl's internal configuration defaults instead of reading a configuration file, but to only do so in the the \fIProjectOne\fR directory of the repository. .PP The third line tells CVS to run branchctl using a separate configuration file for the \fIProjectTwo\fR directory in the repository. .PP To finish the repository configuration, commit the changes you've made. Once the CVS server has reported that it is "Rebuilding administrative file database", your repository is configured to use branchctl. .SH "OPTIONS" .PP When an option includes an argument, you may specify the argument either separate ("-d output") or mashed ("-doutput"). branchctl supports both. For long options which include an argument, the argument may be separated from the option ("--fromhost example.com") or mashed, but with an equals sign between the option and the argument ("--fromhost=example.com"). .TP \fB--config \fIfile\fB\fR Use \fIfile\fR as the configuration file for branchctl. By default, a file named \fIbranchctl.conf\fR is used if it exists. If the name of the configuration file is relative, it is interpreted as relative to the \fICVSROOT\fR administrative directory of the repository. \fB--config\fR is incompatible with \fB--no-config\fR. .TP \fB--no-config\fR Do not use a configuration file for branchctl. This can be used to disable the use of the default configuration file. \fB--no-config\fR is incompatible with \fB--config\fR. Note that it's not normally useful to specify this option, but it may be useful when you want to allow changes to any branch within a single CVS module, but use a more sophisticated configuration for the rest of the repository. .TP \fB--cvsroot \fIpath\fB\fR Use \fIpath\fR as the value for the \fBCVSROOT\fR environment variable. This is usually not needed. .TP \fB--help\fR .TP \fB-h\fR Print a summary of the command line options to standard output. .SH "BUGS" .PP There are probably some bugs. If you find them, please report them to the maintainers using the bug tracker . .SH "SEE ALSO" .PP The branchctl page on SourceForge . .PP The CVS home page . .SH "AUTHOR" .PP branchctl was originally written by Fred Drake. .PP This manual page was written by Fred L. Drake, Jr. . cvs-syncmail-2.3/doc/syncmail.10000644000225600002620000002503210274677350017124 0ustar csaccacsacca00000000000000.\" This manpage has been automatically generated by docbook2man .\" from a DocBook document. This tool can be found at: .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . .TH "SYNCMAIL" "1" "15 July 2003" "" "" .SH NAME syncmail \- Send email notifications of CVS activity .SH SYNOPSIS \fBsyncmail\fR [ \fB--cvsroot \fIpath\fB\fR ] [ \fB [ --context | -C ] \fIlines\fB\fR ] [ \fB-c\fR ] [ \fB-u\fR ] [ \fB--quiet | -q\fR ] [ \fB--fromhost \fIhostname\fB\fR ] [ \fB-f \fIhostname\fB\fR ] [ \fB--mailhost \fIhostname\fB\fR ] [ \fB-m \fIhostname\fB\fR ] [ \fB--reply-to \fIemail-address\fB\fR ] [ \fB-R \fIemail-address\fB\fR ] [ \fB--subject-prefix \fIstring\fB\fR ] [ \fB-S \fIstring\fB\fR ] [ \fB--help | -h\fR ] \fB%{sSv}\fR \fBemail\fR\fI ...\fR .SH "DESCRIPTION" .PP \fBsyncmail\fR sends out notifications of CVS commits via email, including the patch that was applied for changed files, the content of new files, or notes about files that were removed. .PP In any large project, keeping track of changes is difficult. CVS does a reasonable job of allowing source changes to be controlled and managed, but does not provide tools to make it easier to work with a changing code base. The hardest part of working on a dynamic project with many changing modules is knowing when changes occur, and what those changes are. .PP Software developers often are heavy email users, spending huge amounts of time working with their email software. Open source developers are among the most serious email addicts out there, sorting through hundreds of emails a day, since this is often the only way to stay in touch with users and fellow developers. .PP \fBClearly, we need more email.\fR .PP syncmail works by integrating with CVS in the repository using the configuration files in the repository's CVSROOT module. When CVS executes commands from the \fIloginfo\fR file, syncmail is invoked if its been configured, and it sends email to one or more email addresses specified on the command line. .SH "SETTING UP SYNCMAIL" .PP Setting up syncmail is not difficult, but there are usually several steps: .TP 3 1. Set up a mailing list. Strictly speaking, this is optional, but with most good mailing list managers, it's easier to maintain a mailing list than it is to continually update a list of individual email addresses on the syncmail command line. How this is done depends on many things, but not syncmail, so will not be further covered here. .TP 3 2. Install syncmail. This is usually done by adding it to your CVS repository, but it may be located in a directory on the default \fBPATH\fR, or just about anywhere else. .TP 3 3. Configure CVS to invoke syncmail. This is a matter of adding and/or changing some of the configuration files in the CVSROOT module in the repository. .SS "INSTALL SYNCMAIL" .PP syncmail consists of a single Python script; it does not need any supplemental data files. There are two approaches to installing the script: check it into the repository, or place it in a shared location on the CVS server. .PP To install syncmail by checking it into the repository itself, check out a working copy of the CVSROOT module. Add the name syncmail to the file \fIcheckoutlist\fR in that directory as well, and commit that change. This will cause a copy of syncmail to be checked out into the repository itself. Copy te syncmail script into the directory, make sure that it is executable by everyone (you should use \fBchmod a+x syncmail\fR for this), and use the \fBcvs add\fR and \fBcvs commit\fR commands to add it to the repository. Once the commit is complete, a checked-out copy of the syncmail script should be located in the repository in the \fICVSROOT\fR directory in the repository. This is the usual way of integrating syncmail into a CVS repository. .PP To install syncmail outside of the repository, find a location for the script. This can be in a "bin" directory such as \fI/usr/local/bin/\fR, or can be in some other location. The only requirement is that all users of the repository be able to execute the script (you should use \fBchmod a+x syncmail\fR for this). This approach requires direct access to the CVS server machine, and is most useful if several repositories are going to share a single copy of syncmail (maybe to ensure the same version is used for each; it's not large enough for disk space to be an issue). .SS "CONFIGURE CVS TO USE SYNCMAIL" .PP Getting the CVS server to invoke syncmail requires editing one more file in the CVSROOT module of the repository. Even if you're using a single installation of syncmail, this configuration needs to be performed for each repository. .PP The \fIloginfo\fR file in the CVSROOT module needs to be modified to invoke syncmail when appropriate. Just when is appropriate depends entirely on your project. If your \fIloginfo\fR file still contains the comments that \fBcvs init\fR copies in, this is a good time to read them if you haven't. If the file does not already contain any configuration lines, you can simply add to the end of the file. .PP Here are two example lines to get you started: .nf CVSROOT $CVSROOT/CVSROOT/syncmail %{sVv} you@example.com DEFAULT $CVSROOT/CVSROOT/syncmail %{sVv} myproject-checkins@example.com .fi .PP This will cause email to be sent to two different places, with which depending on what files in the repository are affected. For administrative files in the CVSROOT module, email will be sent to ; you should probably list all your project administrators here. For all other files, email will be sent to the addresses you specify. .PP If you have several sub-products for which you want different checkin lists, you can change the "DEFAULT" label to match the subtree that you want to go to each list, with a separate line for each distinct prefix. For example, if your repository includes the modules "one" and "two", you could use the following: .nf CVSROOT $CVSROOT/CVSROOT/syncmail %{sVv} you@example.com one/ $CVSROOT/CVSROOT/syncmail %{sVv} myproject-one-cvs@example.com two/ $CVSROOT/CVSROOT/syncmail %{sVv} myproject-two-cvs@exmaple.com .fi .PP Note that %{sSv} is magic that CVS understands and replaces with information about the files that are affected; be sure to enter that exactly as shown, just before the email addresses. Command line options for syncmail should be placed between the name of the syncmail command and the %{sSv}. .PP You can still have a "DEFAULT" line that gets used for any additional subprojects. .PP If you do \fBnot\fR have a stock \fIloginfo\fR file, then you can probably figure out what you need to do to combine the information above with your existing changes. If the command lines in the file become too long for comfort, some helper scripts can be added to the CVSROOT module (remember to add their names to the \fIcheckoutlist\fR as well!). .PP To finish the repository configuration, commit the changes you've made. Once the CVS server has reported that it is "Rebuilding administrative file database", your repository is configured to use syncmail. .SH "OPTIONS" .PP When an option includes an argument, you may specify the argument either separate ("-d output") or mashed ("-doutput"). syncmail supports both. For long options which include an argument, the argument may be separated from the option ("--fromhost example.com") or mashed, but with an equals sign between the option and the argument ("--fromhost=example.com"). .TP \fB--cvsroot \fIpath\fB\fR Use \fIpath\fR as the value for the \fBCVSROOT\fR environment variable. This is usually not needed. .TP \fB--context \fIlines\fB\fR .TP \fB-C \fIlines\fB\fR Generate context diffs with \fIlines\fR lines of context displayed on either side of the changed portion. .TP \fB-c\fR Generate context diffs with two lines of context shown on either side of the changed portion. This is the default. .TP \fB-u\fR Generate unified diffs instead of context diffs. Unified diffs are typically shorted than context diffs, but many users find it easier to read context diffs. .TP \fB--quiet\fR .TP \fB-q\fR Do not display progress information to the user. By default, syncmail will display the email addresses it is sending mail to and note when it starts generating the notification email and when it is done sending the email. .TP \fB--fromhost \fIhostname\fB\fR .TP \fB-f \fIhostname\fB\fR Specify the host name that email should appear to come from. By default, syncmail uses the fully qualified name for the host it's running on, and lets the local MTA take care of host name translation. .TP \fB--mailhost \fIhostname\fB\fR .TP \fB-m \fIhostname\fB\fR Specify the host name that should be used to submit mail via SMTP. By default, syncmail uses \fBlocalhost\fR. .TP \fB--reply-to \fIemail-address\fB\fR .TP \fB-R \fIemail-address\fB\fR Specify an email address that should be used for the Reply-To header in email. This header is not normally used. .TP \fB--subject-prefix \fIstring\fB\fR .TP \fB-S \fIstring\fB\fR Provide a string that is pre-pended to the subject of generated email. This prefix is often of the form \&'[Checkins]', allowing mail filters to easily identify mail from syncmail for a specific CVS repository or project. This is often not needed if mail is being sent to a mailing list manager that adds a prefix of it's own. .TP \fB--help\fR .TP \fB-h\fR Print a summary of the command line options to standard output. .SH "BUGS" .PP There are probably some bugs. If you find them, please report them to the maintainers using the bug tracker . .SH "ALTERNATIVES" .PP Other people have written tools that serve similar purposes, but not all of these are meant to support CVS repositories accessed from remote locations (anything other than direct filesystem access). .PP A mostly-equivalent package, written in Perl, is available as cvs-syncmail (Perl version) . .PP \fBlog_accum\fR is another Perl implementation, but there appears to be no authoritative source of information for this package. .PP Please inform the syncmail maintainers if you can provide current references to these efforts. .SH "SEE ALSO" .PP The syncmail page on SourceForge . .PP The CVS home page . .SH "AUTHOR" .PP syncmail was originally written by Barry Warsaw to send mail based on checkins to the Python project. Barry continues to maintain syncmail with help from Fred L. Drake, Jr. and others. .PP This manual page was written by Fred L. Drake, Jr. . cvs-syncmail-2.3/doc/.cvsignore0000644000225600002620000000003310274677311017212 0ustar csaccacsacca00000000000000manpage.links manpage.refs