You are not logged in Log in Join
You are here: Home » DevHome » Subversion » postcommit_actions

Log in
Name

Password

 
 

History for postcommit_actions

??changed:
-
#!/usr/local/bin/python2.1

"""Apply checkin actions dictated by traffic_table.py, as checkins occur.

Special provisions to fork into the background, disconnected from tty, so
the user and (more critically) CVS locks aren't held just pending completion 
of notification and other potentially meandering actions.

Options:

 --verbose - operate in verbose mode, with output to OUTPUT_LOG in the
             detached copy, and to stdout before the detach (and forever if 
             --wait specified)

 --dryrun - do not actually do any of the activities

 --wait - do not fork into the background (and leave output in stdout/stderr)
          This is for internal use by the script when forking.

 --msgfile MSGFILENM - internal - get log message from MSGFILENM (and delete)

We expect to be invoked from loginfo with %{CVSROOT} %{sVv}: CVS expands
the loginfo %{sVv} into a single command-line token (bizarrely enough)
containing multiple, space-delimited parts:

  - The first part is the path of repository directory

  - Then comes a comma-concatenated string for each file being checked in,
    consisting of:

    - The file name,
    - The old version number, then
    - the new one, like so:

      filename,1.52,1.53

\(See the CVS loginfo docs for more format-string details.)

The actions are configured in traffic_table.py.  The only remaining relevant
one is:

 - email checkin messages to designated recipients

\(Versions of the script that supported automatic mirroring was removed
beginning at version 1.123.)"""

import sys, os, tempfile, time, pwd
SCRIPT_DIR = os.path.abspath(os.path.split(sys.argv[0])[0])
os.chdir(SCRIPT_DIR)                # Valid dir, having other local scripts.
import string
import getopt
import smtplib
import socket, whrandom, getpass

CVSROOT = os.path.split(SCRIPT_DIR)[0]
CVSROOT_ABS = os.path.abspath('..')
USE_LDAP = 1
LDAP_PORT = 389
LDAP_HOST = "your.ldap.host"
OFFICIAL_SENDER = "[email protected]"

# Ceiling on number of lines per file report (diff or "added"), at which point
# we go to excerpts from the beginning and end:
FILE_LINES_LIMIT = 1500
# Number of lines in beginning and end excerpts when FILE_LINES_LIMIT is hit:
FILE_EXCERPTS_LINES = 200

CUSTOM_TRAFFIC_TABLE = "%s/custom_traffic_table.py" % CVSROOT

import re

import traffic_table
import adjustlinks

# Hook up with an outboard file.
if os.path.exists(CUSTOM_TRAFFIC_TABLE):
    execfile(CUSTOM_TRAFFIC_TABLE)

# OUTPUT_LOG must be writable by anyone whose checkins will invoke this
# script in order for their logging to happen.
OUTPUT_LOG = "%s/cvs-postcommit_actions.log" % CVSROOT

# Set CVSMASTER to the email address of someone managing your CVS mirroring.
# Notices about any caught malfunctions will be sent to this address.
CVSMASTER = "[email protected]"

# You have to plug in the recipients email address via '%' string formatting.
MAIL_CMD = "/usr/lib/sendmail -t -f %s"

WAIT = 0                                # Fork unless --wait is requested.
DRYRUN = 0                              # '--dryrun' option
VERBOSE = 0                             # '--verbose' option default value
SCRIPT = "postcommit_actions"           # Will b set to argv[0], when obtained.

sVv_re = re.compile("(.*),([^,]+),([^,]+)")

def main(args):
    """Grok the args and the traffic_table and process accordingly."""

    global SCRIPT, DRYRUN, VERBOSE, WAIT

    orig_args = args[:]

    SCRIPT = args[0]
    try:
        opts, args = getopt.getopt(args[1:], "", ["verbose", "dryrun",
                                                  "wait", "msgfile=",
                                                  ])
    except getopt.error, err:
        complain("%s\n", err)
        raise SystemExit, 1

    msgfilenm = ""

    for opt, val in opts:
        if opt == "--verbose":
            VERBOSE = 1
            complain("%s: VERBOSE\n", SCRIPT)
        elif opt == "--dryrun":
            DRYRUN = 1
            complain("%s: DRYRUN\n", SCRIPT)
        elif opt == "--wait":
            WAIT = 1
            complain("%s: WAIT/Foreground\n", SCRIPT)
        elif opt == "--msgfile":
            # This is internal, for the script to pass itself a file.
            msgfilenm = val
        else:
            complain("Unrecognized option '%s'\n", opt)
            raise SystemExit, 1
    if VERBOSE:
        complain("Initial args: %s '%s'\n",
                 string.join(orig_args[:-1], " "),
                 orig_args[-1])
        complain("Working dir: %s\n" % safe_getcwd('/tmp'))

    if len(args) != 1:
        usage(); raise SystemExit, 1

    doing_directory = 0
    no_files = 1

    # The %{sVv} args are passed in as a single token - have to split them.
    split_args = string.split(args[0])
    repo = split_args[0]

    if len(split_args) == 0:
        subjs = ["<no files>", "", ""]
    elif len(split_args) == 1:
        subjs = split_args + ["", ""]
    elif split_args[1] == "-":
        subjs = split_args
        doing_directory = 1
    else:
        no_files = 0
        subjs = map(grok_file, split_args[1:])

    if VERBOSE:
        complain("CWD: %s, Repo: %s, ",
                 safe_getcwd('/tmp'), repo)
        complain("Subjects: %s\n", subjs)

    if not WAIT:
        detach(orig_args)

    entries = find_entries(repo)

    for entry in entries:
        wasVerbose = VERBOSE
        VERBOSE = entry.get('verbose', VERBOSE)
        selector_path = entry['path']
        addrs = entry.get('addrs')
        specials = entry.get('specials')

        if addrs:
            do_mail(repo, addrs, subjs, msgfilenm=msgfilenm,
                    doing_directory=doing_directory, no_files=no_files)

        if specials:
            subj_names = map(lambda x: x[0], subjs)
            for trigger, action in specials:
                if trigger in subj_names:
                    do_special(trigger, action, addrs)

        VERBOSE = wasVerbose

    if VERBOSE:
        complain("** Done **\n\n")

    if failures:
        handle_failures(orig_args)

    if msgfilenm:
        os.unlink(msgfilenm)

def detach(args):
    """Fork us into the background, with stdout and stderr to OUTPUT_LOG.

    We have to disconnect std io (in, out, and err) and run the program in
[423 more lines...]