diff options
Diffstat (limited to 'contrib/cvs/src/logmsg.c')
-rw-r--r-- | contrib/cvs/src/logmsg.c | 988 |
1 files changed, 0 insertions, 988 deletions
diff --git a/contrib/cvs/src/logmsg.c b/contrib/cvs/src/logmsg.c deleted file mode 100644 index 6878aaf..0000000 --- a/contrib/cvs/src/logmsg.c +++ /dev/null @@ -1,988 +0,0 @@ -/* - * Copyright (C) 1986-2005 The Free Software Foundation, Inc. - * - * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, - * and others. - * - * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk - * Portions Copyright (C) 1989-1992, Brian Berliner - * - * You may distribute under the terms of the GNU General Public License as - * specified in the README file that comes with the CVS source distribution. - * - * $FreeBSD$ - */ - -#include <assert.h> - -#include "cvs.h" -#include "getline.h" - -static int find_type PROTO((Node * p, void *closure)); -static int fmt_proc PROTO((Node * p, void *closure)); -static int logfile_write PROTO((const char *repository, const char *filter, - const char *message, FILE * logfp, - List * changes)); -static int rcsinfo_proc PROTO((const char *repository, const char *template)); -static int title_proc PROTO((Node * p, void *closure)); -static int update_logfile_proc PROTO((const char *repository, - const char *filter)); -static void setup_tmpfile PROTO((FILE * xfp, char *xprefix, List * changes)); -static int editinfo_proc PROTO((const char *repository, const char *template)); -static int verifymsg_proc PROTO((const char *repository, const char *script)); - -static FILE *fp; -static char *str_list; -static char *str_list_format; /* The format for str_list's contents. */ -static char *editinfo_editor; -static char *verifymsg_script; -static Ctype type; - -/* - * Should the logmsg be re-read during the do_verify phase? - * RereadLogAfterVerify=no|stat|yes - * LOGMSG_REREAD_NEVER - never re-read the logmsg - * LOGMSG_REREAD_STAT - re-read the logmsg only if it has changed - * LOGMSG_REREAD_ALWAYS - always re-read the logmsg - */ -int RereadLogAfterVerify = LOGMSG_REREAD_ALWAYS; - -/* - * Puts a standard header on the output which is either being prepared for an - * editor session, or being sent to a logfile program. The modified, added, - * and removed files are included (if any) and formatted to look pretty. */ -static char *prefix; -static int col; -static char *tag; -static void -setup_tmpfile (xfp, xprefix, changes) - FILE *xfp; - char *xprefix; - List *changes; -{ - /* set up statics */ - fp = xfp; - prefix = xprefix; - - type = T_MODIFIED; - if (walklist (changes, find_type, NULL) != 0) - { - (void) fprintf (fp, "%sModified Files:\n", prefix); - col = 0; - (void) walklist (changes, fmt_proc, NULL); - (void) fprintf (fp, "\n"); - if (tag != NULL) - { - free (tag); - tag = NULL; - } - } - type = T_ADDED; - if (walklist (changes, find_type, NULL) != 0) - { - (void) fprintf (fp, "%sAdded Files:\n", prefix); - col = 0; - (void) walklist (changes, fmt_proc, NULL); - (void) fprintf (fp, "\n"); - if (tag != NULL) - { - free (tag); - tag = NULL; - } - } - type = T_REMOVED; - if (walklist (changes, find_type, NULL) != 0) - { - (void) fprintf (fp, "%sRemoved Files:\n", prefix); - col = 0; - (void) walklist (changes, fmt_proc, NULL); - (void) fprintf (fp, "\n"); - if (tag != NULL) - { - free (tag); - tag = NULL; - } - } -} - -/* - * Looks for nodes of a specified type and returns 1 if found - */ -static int -find_type (p, closure) - Node *p; - void *closure; -{ - struct logfile_info *li = p->data; - - if (li->type == type) - return (1); - else - return (0); -} - -/* - * Breaks the files list into reasonable sized lines to avoid line wrap... - * all in the name of pretty output. It only works on nodes whose types - * match the one we're looking for - */ -static int -fmt_proc (p, closure) - Node *p; - void *closure; -{ - struct logfile_info *li; - - li = p->data; - if (li->type == type) - { - if (li->tag == NULL - ? tag != NULL - : tag == NULL || strcmp (tag, li->tag) != 0) - { - if (col > 0) - (void) fprintf (fp, "\n"); - (void) fputs (prefix, fp); - col = strlen (prefix); - while (col < 6) - { - (void) fprintf (fp, " "); - ++col; - } - - if (li->tag == NULL) - (void) fprintf (fp, "No tag"); - else - (void) fprintf (fp, "Tag: %s", li->tag); - - if (tag != NULL) - free (tag); - tag = xstrdup (li->tag); - - /* Force a new line. */ - col = 70; - } - - if (col == 0) - { - (void) fprintf (fp, "%s\t", prefix); - col = 8; - } - else if (col > 8 && (col + (int) strlen (p->key)) > 70) - { - (void) fprintf (fp, "\n%s\t", prefix); - col = 8; - } - (void) fprintf (fp, "%s ", p->key); - col += strlen (p->key) + 1; - } - return (0); -} - -/* - * Builds a temporary file using setup_tmpfile() and invokes the user's - * editor on the file. The header garbage in the resultant file is then - * stripped and the log message is stored in the "message" argument. - * - * If REPOSITORY is non-NULL, process rcsinfo for that repository; if it - * is NULL, use the CVSADM_TEMPLATE file instead. REPOSITORY should be - * NULL when running in client mode. - */ -void -do_editor (dir, messagep, repository, changes) - const char *dir; - char **messagep; - const char *repository; - List *changes; -{ - static int reuse_log_message = 0; - char *line; - int line_length; - size_t line_chars_allocated; - char *fname; - struct stat pre_stbuf, post_stbuf; - int retcode = 0; - - assert (!current_parsed_root->isremote != !repository); - - if (noexec || reuse_log_message) - return; - - /* Abort creation of temp file if no editor is defined */ - if (strcmp (Editor, "") == 0 && !editinfo_editor) - error(1, 0, "no editor defined, must use -e or -m"); - - /* Create a temporary file */ - /* FIXME - It's possible we should be relying on cvs_temp_file to open - * the file here - we get race conditions otherwise. - */ - fname = cvs_temp_name (); - again: - if ((fp = CVS_FOPEN (fname, "w+")) == NULL) - error (1, 0, "cannot create temporary file %s", fname); - - if (*messagep) - { - (void) fputs (*messagep, fp); - - if ((*messagep)[0] == '\0' || - (*messagep)[strlen (*messagep) - 1] != '\n') - (void) fprintf (fp, "\n"); - } - else - (void) fprintf (fp, "\n"); - - if (repository != NULL) - /* tack templates on if necessary */ - (void) Parse_Info (CVSROOTADM_RCSINFO, repository, rcsinfo_proc, 1); - else - { - FILE *tfp; - char buf[1024]; - size_t n; - size_t nwrite; - - /* Why "b"? */ - tfp = CVS_FOPEN (CVSADM_TEMPLATE, "rb"); - if (tfp == NULL) - { - if (!existence_error (errno)) - error (1, errno, "cannot read %s", CVSADM_TEMPLATE); - } - else - { - while (!feof (tfp)) - { - char *p = buf; - n = fread (buf, 1, sizeof buf, tfp); - nwrite = n; - while (nwrite > 0) - { - n = fwrite (p, 1, nwrite, fp); - nwrite -= n; - p += n; - } - if (ferror (tfp)) - error (1, errno, "cannot read %s", CVSADM_TEMPLATE); - } - if (fclose (tfp) < 0) - error (0, errno, "cannot close %s", CVSADM_TEMPLATE); - } - } - - (void) fprintf (fp, - "%s----------------------------------------------------------------------\n", - CVSEDITPREFIX); - (void) fprintf (fp, - "%sEnter Log. Lines beginning with `%.*s' are removed automatically\n%s\n", - CVSEDITPREFIX, CVSEDITPREFIXLEN, CVSEDITPREFIX, - CVSEDITPREFIX); - if (dir != NULL && *dir) - (void) fprintf (fp, "%sCommitting in %s\n%s\n", CVSEDITPREFIX, - dir, CVSEDITPREFIX); - if (changes != NULL) - setup_tmpfile (fp, CVSEDITPREFIX, changes); - (void) fprintf (fp, - "%s----------------------------------------------------------------------\n", - CVSEDITPREFIX); - - /* finish off the temp file */ - if (fclose (fp) == EOF) - error (1, errno, "%s", fname); - if ( CVS_STAT (fname, &pre_stbuf) == -1) - pre_stbuf.st_mtime = 0; - - if (editinfo_editor) - free (editinfo_editor); - editinfo_editor = (char *) NULL; - if (!current_parsed_root->isremote && repository != NULL) - (void) Parse_Info (CVSROOTADM_EDITINFO, repository, editinfo_proc, 0); - - /* run the editor */ - run_setup (editinfo_editor ? editinfo_editor : Editor); - run_arg (fname); - if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, - RUN_NORMAL | RUN_SIGIGNORE)) != 0) - error (editinfo_editor ? 1 : 0, retcode == -1 ? errno : 0, - editinfo_editor ? "Logfile verification failed" : - "warning: editor session failed"); - - /* put the entire message back into the *messagep variable */ - - fp = open_file (fname, "r"); - - if (*messagep) - free (*messagep); - - if ( CVS_STAT (fname, &post_stbuf) != 0) - error (1, errno, "cannot find size of temp file %s", fname); - - if (post_stbuf.st_size == 0) - *messagep = NULL; - else - { - /* On NT, we might read less than st_size bytes, but we won't - read more. So this works. */ - *messagep = (char *) xmalloc (post_stbuf.st_size + 1); - (*messagep)[0] = '\0'; - } - - line = NULL; - line_chars_allocated = 0; - - if (*messagep) - { - size_t message_len = post_stbuf.st_size + 1; - size_t offset = 0; - while (1) - { - line_length = getline (&line, &line_chars_allocated, fp); - if (line_length == -1) - { - if (ferror (fp)) - error (0, errno, "warning: cannot read %s", fname); - break; - } - if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0) - continue; - if (offset + line_length >= message_len) - expand_string (messagep, &message_len, - offset + line_length + 1); - (void) strcpy (*messagep + offset, line); - offset += line_length; - } - } - if (fclose (fp) < 0) - error (0, errno, "warning: cannot close %s", fname); - - /* canonicalize emply messages */ - if (*messagep != NULL && - (**messagep == '\0' || strcmp (*messagep, "\n") == 0)) - { - free (*messagep); - *messagep = NULL; - } - - if (pre_stbuf.st_mtime == post_stbuf.st_mtime || *messagep == NULL) - { - for (;;) - { - (void) printf ("\nLog message unchanged or not specified\n"); - (void) printf ("a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs\n"); - (void) printf ("Action: (continue) "); - (void) fflush (stdout); - line_length = getline (&line, &line_chars_allocated, stdin); - if (line_length < 0) - { - error (0, errno, "cannot read from stdin"); - if (unlink_file (fname) < 0) - error (0, errno, - "warning: cannot remove temp file %s", fname); - error (1, 0, "aborting"); - } - else if (line_length == 0 - || *line == '\n' || *line == 'c' || *line == 'C') - break; - if (*line == 'a' || *line == 'A') - { - if (unlink_file (fname) < 0) - error (0, errno, "warning: cannot remove temp file %s", fname); - error (1, 0, "aborted by user"); - } - if (*line == 'e' || *line == 'E') - goto again; - if (*line == '!') - { - reuse_log_message = 1; - break; - } - (void) printf ("Unknown input\n"); - } - } - if (line) - free (line); - if (unlink_file (fname) < 0) - error (0, errno, "warning: cannot remove temp file %s", fname); - free (fname); -} - -/* Runs the user-defined verification script as part of the commit or import - process. This verification is meant to be run whether or not the user - included the -m atribute. unlike the do_editor function, this is - independant of the running of an editor for getting a message. - */ -void -do_verify (messagep, repository) - char **messagep; - const char *repository; -{ - FILE *fp; - char *fname; - int retcode = 0; - - struct stat pre_stbuf, post_stbuf; - - if (current_parsed_root->isremote) - /* The verification will happen on the server. */ - return; - - /* FIXME? Do we really want to skip this on noexec? What do we do - for the other administrative files? */ - if (noexec || repository == NULL) - return; - - /* Get the name of the verification script to run */ - - if (Parse_Info (CVSROOTADM_VERIFYMSG, repository, verifymsg_proc, 0) > 0) - error (1, 0, "Message verification failed"); - - if (!verifymsg_script) - return; - - /* open a temporary file, write the message to the - temp file, and close the file. */ - - if ((fp = cvs_temp_file (&fname)) == NULL) - error (1, errno, "cannot create temporary file %s", - fname ? fname : "(null)"); - - if (*messagep != NULL) - fputs (*messagep, fp); - if (*messagep == NULL || - (*messagep)[0] == '\0' || - (*messagep)[strlen (*messagep) - 1] != '\n') - putc ('\n', fp); - if (fclose (fp) == EOF) - error (1, errno, "%s", fname); - - if (RereadLogAfterVerify == LOGMSG_REREAD_STAT) - { - /* Remember the status of the temp file for later */ - if ( CVS_STAT (fname, &pre_stbuf) != 0 ) - error (1, errno, "cannot stat temp file %s", fname); - - /* - * See if we need to sleep before running the verification - * script to avoid time-stamp races. - */ - sleep_past (pre_stbuf.st_mtime); - } - - run_setup (verifymsg_script); - run_arg (fname); - if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, - RUN_NORMAL | RUN_SIGIGNORE)) != 0) - { - /* Since following error() exits, delete the temp file now. */ - if (unlink_file (fname) < 0) - error (0, errno, "cannot remove %s", fname); - - error (1, retcode == -1 ? errno : 0, - "Message verification failed"); - } - - /* Get the mod time and size of the possibly new log message - * in always and stat modes. - */ - if (RereadLogAfterVerify == LOGMSG_REREAD_ALWAYS || - RereadLogAfterVerify == LOGMSG_REREAD_STAT) - { - if ( CVS_STAT (fname, &post_stbuf) != 0 ) - error (1, errno, "cannot find size of temp file %s", fname); - } - - /* And reread the log message in `always' mode or in `stat' mode when it's - * changed - */ - if (RereadLogAfterVerify == LOGMSG_REREAD_ALWAYS || - (RereadLogAfterVerify == LOGMSG_REREAD_STAT && - (pre_stbuf.st_mtime != post_stbuf.st_mtime || - pre_stbuf.st_size != post_stbuf.st_size))) - { - /* put the entire message back into the *messagep variable */ - - if (*messagep) free (*messagep); - - if (post_stbuf.st_size == 0) - *messagep = NULL; - else - { - char *line = NULL; - int line_length; - size_t line_chars_allocated = 0; - char *p; - - if ( (fp = open_file (fname, "r")) == NULL ) - error (1, errno, "cannot open temporary file %s", fname); - - /* On NT, we might read less than st_size bytes, - but we won't read more. So this works. */ - p = *messagep = (char *) xmalloc (post_stbuf.st_size + 1); - *messagep[0] = '\0'; - - while (1) - { - line_length = getline (&line, - &line_chars_allocated, - fp); - if (line_length == -1) - { - if (ferror (fp)) - /* Fail in this case because otherwise we will have no - * log message - */ - error (1, errno, "cannot read %s", fname); - break; - } - if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0) - continue; - (void) strcpy (p, line); - p += line_length; - } - if (line) free (line); - if (fclose (fp) < 0) - error (0, errno, "warning: cannot close %s", fname); - } - } - - /* Delete the temp file */ - - if (unlink_file (fname) < 0) - error (0, errno, "cannot remove %s", fname); - free (fname); - free (verifymsg_script); - verifymsg_script = NULL; -} - -/* - * callback proc for Parse_Info for rcsinfo templates this routine basically - * copies the matching template onto the end of the tempfile we are setting - * up - */ -/* ARGSUSED */ -static int -rcsinfo_proc (repository, template) - const char *repository; - const char *template; -{ - static char *last_template; - FILE *tfp; - - /* nothing to do if the last one included is the same as this one */ - if (last_template && strcmp (last_template, template) == 0) - return (0); - if (last_template) - free (last_template); - last_template = xstrdup (template); - - if ((tfp = CVS_FOPEN (template, "r")) != NULL) - { - char *line = NULL; - size_t line_chars_allocated = 0; - - while (getline (&line, &line_chars_allocated, tfp) >= 0) - (void) fputs (line, fp); - if (ferror (tfp)) - error (0, errno, "warning: cannot read %s", template); - if (fclose (tfp) < 0) - error (0, errno, "warning: cannot close %s", template); - if (line) - free (line); - return (0); - } - else - { - error (0, errno, "Couldn't open rcsinfo template file %s", template); - return (1); - } -} - -/* - * Uses setup_tmpfile() to pass the updated message on directly to any - * logfile programs that have a regular expression match for the checked in - * directory in the source repository. The log information is fed into the - * specified program as standard input. - */ -static FILE *logfp; -static const char *message; -static List *changes; - -void -Update_Logfile (repository, xmessage, xlogfp, xchanges) - const char *repository; - const char *xmessage; - FILE *xlogfp; - List *xchanges; -{ - /* nothing to do if the list is empty */ - if (xchanges == NULL || xchanges->list->next == xchanges->list) - return; - - /* set up static vars for update_logfile_proc */ - message = xmessage; - logfp = xlogfp; - changes = xchanges; - - /* call Parse_Info to do the actual logfile updates */ - (void) Parse_Info (CVSROOTADM_LOGINFO, repository, update_logfile_proc, 1); -} - - - -/* - * callback proc to actually do the logfile write from Update_Logfile - */ -static int -update_logfile_proc (repository, filter) - const char *repository; - const char *filter; -{ - return logfile_write (repository, filter, message, logfp, changes); -} - - - -/* - * concatenate each filename/version onto str_list - */ -static int -title_proc (p, closure) - Node *p; - void *closure; -{ - char *c; - struct logfile_info *li = p->data; - - if (li->type == type) - { - /* Until we decide on the correct logging solution when we add - directories or perform imports, T_TITLE nodes will only - tack on the name provided, regardless of the format string. - You can verify that this assumption is safe by checking the - code in add.c (add_directory) and import.c (import). */ - - str_list = xrealloc (str_list, strlen (str_list) + 5); - (void) strcat (str_list, " "); - - if (li->type == T_TITLE) - { - str_list = xrealloc (str_list, - strlen (str_list) + strlen (p->key) + 5); - (void) strcat (str_list, p->key); - } - else - { - /* All other nodes use the format string. */ - - for (c = str_list_format; *c != '\0'; c++) - { - switch (*c) - { - case 's': - str_list = - xrealloc (str_list, - strlen (str_list) + strlen (p->key) + 5); - (void) strcat (str_list, p->key); - break; - case 'V': - str_list = - xrealloc (str_list, - (strlen (str_list) - + (li->rev_old ? strlen (li->rev_old) : 0) - + 10) - ); - (void) strcat (str_list, (li->rev_old - ? li->rev_old : "NONE")); - break; - case 'v': - str_list = - xrealloc (str_list, - (strlen (str_list) - + (li->rev_new ? strlen (li->rev_new) : 0) - + 10) - ); - (void) strcat (str_list, (li->rev_new - ? li->rev_new : "NONE")); - break; - /* All other characters, we insert an empty field (but - we do put in the comma separating it from other - fields). This way if future CVS versions add formatting - characters, one can write a loginfo file which at least - won't blow up on an old CVS. */ - /* Note that people who have to deal with spaces in file - and directory names are using space to get a known - delimiter for the directory name, so it's probably - not a good idea to ever define that as a formatting - character. */ - } - if (*(c + 1) != '\0') - { - str_list = xrealloc (str_list, strlen (str_list) + 5); - (void) strcat (str_list, ","); - } - } - } - } - return (0); -} - -/* - * Writes some stuff to the logfile "filter" and returns the status of the - * filter program. - */ -static int -logfile_write (repository, filter, message, logfp, changes) - const char *repository; - const char *filter; - const char *message; - FILE *logfp; - List *changes; -{ - FILE *pipefp; - char *prog; - char *cp; - int c; - int pipestatus; - char *fmt_percent; /* the location of the percent sign - that starts the format string. */ - - assert (repository); - - /* The user may specify a format string as part of the filter. - Originally, `%s' was the only valid string. The string that - was substituted for it was: - - <repository-name> <file1> <file2> <file3> ... - - Each file was either a new directory/import (T_TITLE), or a - added (T_ADDED), modified (T_MODIFIED), or removed (T_REMOVED) - file. - - It is desirable to preserve that behavior so lots of commitlog - scripts won't die when they get this new code. At the same - time, we'd like to pass other information about the files (like - version numbers, statuses, or checkin times). - - The solution is to allow a format string that allows us to - specify those other pieces of information. The format string - will be composed of `%' followed by a single format character, - or followed by a set of format characters surrounded by `{' and - `}' as separators. The format characters are: - - s = file name - V = old version number (pre-checkin) - v = new version number (post-checkin) - - For example, valid format strings are: - - %{} - %s - %{s} - %{sVv} - - There's no reason that more items couldn't be added (like - modification date or file status [added, modified, updated, - etc.]) -- the code modifications would be minimal (logmsg.c - (title_proc) and commit.c (check_fileproc)). - - The output will be a string of tokens separated by spaces. For - backwards compatibility, the the first token will be the - repository name. The rest of the tokens will be - comma-delimited lists of the information requested in the - format string. For example, if `/u/src/master' is the - repository, `%{sVv}' is the format string, and three files - (ChangeLog, Makefile, foo.c) were modified, the output might - be: - - /u/src/master ChangeLog,1.1,1.2 Makefile,1.3,1.4 foo.c,1.12,1.13 - - Why this duplicates the old behavior when the format string is - `%s' is left as an exercise for the reader. */ - - fmt_percent = strchr (filter, '%'); - if (fmt_percent) - { - int len; - const char *srepos; - char *fmt_begin, *fmt_end; /* beginning and end of the - format string specified in - filter. */ - char *fmt_continue; /* where the string continues - after the format string (we - might skip a '}') somewhere - in there... */ - - /* Grab the format string. */ - - if ((*(fmt_percent + 1) == ' ') || (*(fmt_percent + 1) == '\0')) - { - /* The percent stands alone. This is an error. We could - be treating ' ' like any other formatting character, but - using it as a formatting character seems like it would be - a mistake. */ - - /* Would be nice to also be giving the line number. */ - error (0, 0, "loginfo: '%%' not followed by formatting character"); - fmt_begin = fmt_percent + 1; - fmt_end = fmt_begin; - fmt_continue = fmt_begin; - } - else if (*(fmt_percent + 1) == '{') - { - /* The percent has a set of characters following it. */ - - fmt_begin = fmt_percent + 2; - fmt_end = strchr (fmt_begin, '}'); - if (fmt_end) - { - /* Skip over the '}' character. */ - - fmt_continue = fmt_end + 1; - } - else - { - /* There was no close brace -- assume that format - string continues to the end of the line. */ - - /* Would be nice to also be giving the line number. */ - error (0, 0, "loginfo: '}' missing"); - fmt_end = fmt_begin + strlen (fmt_begin); - fmt_continue = fmt_end; - } - } - else - { - /* The percent has a single character following it. FIXME: - %% should expand to a regular percent sign. */ - - fmt_begin = fmt_percent + 1; - fmt_end = fmt_begin + 1; - fmt_continue = fmt_end; - } - - len = fmt_end - fmt_begin; - str_list_format = xmalloc (len + 1); - strncpy (str_list_format, fmt_begin, len); - str_list_format[len] = '\0'; - - /* Allocate an initial chunk of memory. As we build up the string - we will realloc it. */ - if (!str_list) - str_list = xmalloc (1); - str_list[0] = '\0'; - - /* Add entries to the string. Don't bother looking for - entries if the format string is empty. */ - - if (str_list_format[0] != '\0') - { - type = T_TITLE; - (void) walklist (changes, title_proc, NULL); - type = T_ADDED; - (void) walklist (changes, title_proc, NULL); - type = T_MODIFIED; - (void) walklist (changes, title_proc, NULL); - type = T_REMOVED; - (void) walklist (changes, title_proc, NULL); - } - - free (str_list_format); - - /* Construct the final string. */ - - srepos = Short_Repository (repository); - - prog = cp = xmalloc ((fmt_percent - filter) + 2 * strlen (srepos) - + 2 * strlen (str_list) + strlen (fmt_continue) - + 10); - (void) memcpy (cp, filter, fmt_percent - filter); - cp += fmt_percent - filter; - *cp++ = '"'; - cp = shell_escape (cp, srepos); - cp = shell_escape (cp, str_list); - *cp++ = '"'; - (void) strcpy (cp, fmt_continue); - - /* To be nice, free up some memory. */ - - free (str_list); - str_list = (char *) NULL; - } - else - { - /* There's no format string. */ - prog = xstrdup (filter); - } - - if ((pipefp = run_popen (prog, "w")) == NULL) - { - if (!noexec) - error (0, 0, "cannot write entry to log filter: %s", prog); - free (prog); - return (1); - } - (void) fprintf (pipefp, "Update of %s\n", repository); - (void) fprintf (pipefp, "In directory %s:", hostname); - cp = xgetwd (); - if (cp == NULL) - fprintf (pipefp, "<cannot get working directory: %s>\n\n", - strerror (errno)); - else - { - fprintf (pipefp, "%s\n\n", cp); - free (cp); - } - - setup_tmpfile (pipefp, "", changes); - (void) fprintf (pipefp, "Log Message:\n%s\n", (message) ? message : ""); - if (logfp != (FILE *) 0) - { - (void) fprintf (pipefp, "Status:\n"); - rewind (logfp); - while ((c = getc (logfp)) != EOF) - (void) putc ((char) c, pipefp); - } - free (prog); - pipestatus = pclose (pipefp); - return ((pipestatus == -1) || (pipestatus == 127)) ? 1 : 0; -} - -/* - * We choose to use the *last* match within the editinfo file for this - * repository. This allows us to have a global editinfo program for the - * root of some hierarchy, for example, and different ones within different - * sub-directories of the root (like a special checker for changes made to - * the "src" directory versus changes made to the "doc" or "test" - * directories. - */ -/* ARGSUSED */ -static int -editinfo_proc(repository, editor) - const char *repository; - const char *editor; -{ - /* nothing to do if the last match is the same as this one */ - if (editinfo_editor && strcmp (editinfo_editor, editor) == 0) - return (0); - if (editinfo_editor) - free (editinfo_editor); - - editinfo_editor = xstrdup (editor); - return (0); -} - -/* This routine is calld by Parse_Info. it asigns the name of the - * message verification script to the global variable verify_script - */ -static int -verifymsg_proc (repository, script) - const char *repository; - const char *script; -{ - if (verifymsg_script && strcmp (verifymsg_script, script) == 0) - return (0); - if (verifymsg_script) - free (verifymsg_script); - verifymsg_script = xstrdup (script); - return (0); -} |