bug-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

merged loginfo messages (new feature proposal & patch)


From: Kenneth Lorber
Subject: merged loginfo messages (new feature proposal & patch)
Date: Tue, 17 Jun 2003 10:34:28 -0400 (EDT)

I'm working on two projects at the moment in which the current behavior
of loginfo filters (in which the filter is called once for every directory
in which work is done) is becoming an annoyance because of the flood of
mail it generates.  While I'm aware of various external programs that
attempt to put the various entries back together, it was proposed that
I attempt a server-based solution - and here it is.

What this patch does is simply to call filters specified with a leading
hyphen only once per commit.  Due to the potentially large amount of
data such filters need to process, the paths, version numbers, log message
and so forth are passed on stdin instead of on the command line.

Patch includes docs, tests, and ChangeLog entries.  If it includes bugs,
oversights, or anything else someone doesn't like, I'm sure you'll let
me know :-)

Share and Enjoy,
keni

Index: NEWS
===================================================================
RCS file: /cvs/ccvs/NEWS,v
retrieving revision 1.133
diff -c -r1.133 NEWS
*** NEWS        10 Jun 2003 17:45:43 -0000      1.133
--- NEWS        17 Jun 2003 13:17:36 -0000
***************
*** 1,5 ****
--- 1,7 ----
  Changes since 1.12.1:
  
+ * Ability to run loginfo filters once per commit instead of once per 
directory.
+ 
  * New LocalKeyword and KeywordExpand options to CVSROOT/config which
  FreeBSD, OpenBSD, and NetBSD users may find familiar as the "tag" and
  "tagexpand" options used for many years. The CVSHeader keyword has
Index: doc/ChangeLog
===================================================================
RCS file: /cvs/ccvs/doc/ChangeLog,v
retrieving revision 1.768
diff -c -r1.768 ChangeLog
*** doc/ChangeLog       12 Jun 2003 20:40:08 -0000      1.768
--- doc/ChangeLog       17 Jun 2003 13:17:36 -0000
***************
*** 1,3 ****
--- 1,6 ----
+ 2003-06-13  Kenneth Lorber  <keni@his.com>
+       * cvs.texinfo (loginfo): Document merged logfile feature.
+ 
  2003-06-12  Derek Price  <derek@ximbiot.com>
  
        * stamp-vti: Regenerated.
Index: doc/cvs.texinfo
===================================================================
RCS file: /cvs/ccvs/doc/cvs.texinfo,v
retrieving revision 1.572
diff -c -r1.572 cvs.texinfo
*** doc/cvs.texinfo     11 Jun 2003 21:26:25 -0000      1.572
--- doc/cvs.texinfo     17 Jun 2003 13:17:38 -0000
***************
*** 13016,13021 ****
--- 13016,13026 ----
  @xref{commit files}, for a description of the syntax of
  the @file{loginfo} file.
  
+ Most filters will be run for each directory in which a change
+ occurs.  However, if the filter starts with a hyphen different
+ rules apply.  @xref(merged loginfo filters) for more information on
+ such filters.
+ 
  The user may specify a format string as
  part of the filter.  The string is composed of a
  @samp{%} followed by a space, or followed by a single
***************
*** 13069,13074 ****
--- 13074,13080 ----
  @menu
  * loginfo example::             Loginfo example
  * Keeping a checked out copy::  Updating a tree on every checkin
+ * merged loginfo filters::    Merged Loginfo Filters
  @end menu
  
  @c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
***************
*** 13155,13160 ****
--- 13161,13187 ----
  @c More info on some of the details?  The "sleep 2" is
  @c so if we are lucky the lock will be gone by the time
  @c we start and we can wait 2 seconds instead of 30.
+ 
+ @node merged loginfo filters
+ @appendixsubsubsec Merged loginfo filters
+ 
+ Filters starting with a hyphen are called only once, instead of for each
+ directory.  When setting up a merged loginfo filter, keep in mind that
+ the loginfo file is scanned for merged loginfo filters only once, thus this
+ feature should be used only for filters marked ALL, DEFAULT, or matching
+ all modules in a project.
+ 
+ No information is substituted on the command line; instead all information
+ is passed to the filter on stdin.
+ 
+ The data available on standard input consists of a line for each
+ file involved in the commit, information on the user, a blank line,
+ and the log message.  The per-file lines consist of 5 tab-separated
+ fields: a letter for the operation (A for add, D for delete, M for
+ modify), the old version number, the new version number, the
+ directory in the repository, and the filename.  The information on
+ the user consists of a line with 2 tab-separated fields:  a hypen
+ and an identification of the user.
  
  @c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  @node rcsinfo
Index: src/ChangeLog
===================================================================
RCS file: /cvs/ccvs/src/ChangeLog,v
retrieving revision 1.2471
diff -c -r1.2471 ChangeLog
*** src/ChangeLog       12 Jun 2003 20:38:22 -0000      1.2471
--- src/ChangeLog       17 Jun 2003 13:17:38 -0000
***************
*** 1,3 ****
--- 1,17 ----
+ 2003-06-12  Kenneth Lorber  <keni@his.com>
+       New feature: loginfo filters starting with a hyphen are called once
+       with details on stdin.
+       * cvs.h: Add definitions.
+       * commit.c: Initialize saved data area, call Save_Update_Logfile to
+       save each directory's data, and use mergedlog_filesdoneproc to
+       send the data once.
+       * logmsg.c: New functions: Save_Update_Logfile saves per-directory
+       information and calls fmt_proc2 to save per-file information.
+       logfile_write_merged sends the accumulated data to the filters.
+       * mkmodules.c: Add description of new feature.
+       * parseinfo.c: Changes to Parse_Info to select appropriate lines for
+       new and old functionality.
+ 
  2003-06-12  Derek Price  <derek@ximbiot.com>
  
        * root.c (parse_cvsroot, local_cvsroot): Parse trailing '/'s off the
Index: src/commit.c
===================================================================
RCS file: /cvs/ccvs/src/commit.c,v
retrieving revision 1.198
diff -c -r1.198 commit.c
*** src/commit.c        11 Jun 2003 18:24:57 -0000      1.198
--- src/commit.c        17 Jun 2003 13:17:39 -0000
***************
*** 21,26 ****
--- 21,29 ----
  #include "fileattr.h"
  #include "hardlink.h"
  
+ static void start_recursion_grouping(void);
+ static struct parse_info_heldinfo pih;
+ 
  static Dtype check_direntproc PROTO ((void *callerdat, char *dir,
                                      char *repos, char *update_dir,
                                      List *entries));
***************
*** 40,45 ****
--- 43,51 ----
  static int commit_filesdoneproc PROTO ((void *callerdat, int err,
                                        char *repository, char *update_dir,
                                        List *entries));
+ static int mergedlog_filesdoneproc PROTO ((void *callerdat, int err,
+                                       char *repository, char *update_dir,
+                                       List *entries));
  static int finaladd PROTO((struct file_info *finfo, char *revision, char *tag,
                           char *options));
  static int findmaxrev PROTO((Node * p, void *closure));
***************
*** 661,672 ****
       * Run the recursion processor to commit the files
       */
      write_dirnonbranch = 0;
!     if (noexec == 0)
        err = start_recursion
            ( commit_fileproc, commit_filesdoneproc,
              commit_direntproc, commit_dirleaveproc, NULL,
              argc, argv, local, W_LOCAL, aflag, CVS_LOCK_NONE,
              (char *) NULL, 1, (char *) NULL );
  
      /*
       * Unlock all the dirs and clean up
--- 667,687 ----
       * Run the recursion processor to commit the files
       */
      write_dirnonbranch = 0;
! 
!     if (noexec == 0){
!       start_recursion_grouping();
        err = start_recursion
            ( commit_fileproc, commit_filesdoneproc,
              commit_direntproc, commit_dirleaveproc, NULL,
              argc, argv, local, W_LOCAL, aflag, CVS_LOCK_NONE,
              (char *) NULL, 1, (char *) NULL );
+       if(!err)
+           err = start_recursion
+               ( NULL, mergedlog_filesdoneproc,
+                 NULL, NULL, NULL,
+                 argc, argv, local, W_LOCAL, aflag, CVS_LOCK_NONE,
+                 (char *) NULL, 1, (char *) NULL );
+     }
  
      /*
       * Unlock all the dirs and clean up
***************
*** 1419,1424 ****
--- 1434,1440 ----
  
      got_message = 0;
  
+     Save_Update_Logfile (repository, saved_message, (FILE *)0, ulist, &pih);
  
      Update_Logfile (repository, saved_message, (FILE *) 0, ulist);
  
***************
*** 2306,2312 ****
--- 2322,2364 ----
      free (ml);
  }
  
+ static void
+ start_recursion_grouping(){
+     memset(&pih, 0, sizeof(pih));
+ }
+ 
+ static int
+ mergedlog_filesdoneproc (callerdat, err, repository, update_dir, entries)
+     void *callerdat;
+     int err;
+     char *repository;
+     char *update_dir;
+     List *entries;
+ {
+     struct per_dir *pd;
+ 
+     /* We only want to run this once - the implication of this is that any
+      * entry in loginfo that needs to get triggered needs to use ALL, DEFAULT,
+      * or a regex that matches _all_ the repository names for the project.
+      */
+     if(pih.counter++ > 0) return err;
  
+     (void) Parse_Info (CVSROOTADM_LOGINFO, repository, logfile_write_merged,
+                      PIOPT_ALL | PIOPT_CALL_HYPHEN | PIOPT_CALL_HYPHEN_ONLY,
+                      &pih);
+ #define XFREE(x) if(x)free(x)
+     XFREE(pih.logmsg);
+     while(pih.pd){
+       pd = pih.pd;
+       pih.pd = pd->prev;
+       XFREE(pd->repository);
+       XFREE(pd->dir);
+       XFREE(pd->mod.str);
+       free(pd);
+     }
+ #undef XFREE
+     return err;
+ }
  
  /* vim:tabstop=8:shiftwidth=4
   */
Index: src/cvs.h
===================================================================
RCS file: /cvs/ccvs/src/cvs.h,v
retrieving revision 1.257
diff -c -r1.257 cvs.h
*** src/cvs.h   12 Jun 2003 20:38:22 -0000      1.257
--- src/cvs.h   17 Jun 2003 13:17:39 -0000
***************
*** 378,384 ****
  #define CVS_LOCK_WRITE        2
  
  /* Option flags for Parse_Info() */
! #define PIOPT_ALL 1   /* accept "all" keyword */
  
  extern char *program_name, *program_path, *command_name;
  extern char *Tmpdir, *Editor;
--- 378,409 ----
  #define CVS_LOCK_WRITE        2
  
  /* Option flags for Parse_Info() */
! #define PIOPT_ALL             1       /* accept "all" keyword */
! #define PIOPT_HYPHEN_OK               2       /* recognize leading hyphen as 
special*/
! #define PIOPT_CALL_HYPHEN     4       /* call callproc on hyphen lines */
! #define PIOPT_CALL_HYPHEN_ONLY        8       /* call callproc only on hyphen 
lines */
! 
! struct parse_info_heldinfo {
!     char *logmsg;
!     int counter;
!     struct per_dir {
!       struct per_dir *prev;
! 
!       char *repository;
!       char *dir;
!       char *srepos;
! 
!       struct dynstr {
!           int alloclen;
!           int len;
!           char *str;
!       } mod;
!     } *pd;
! };
! extern int logfile_write_merged PROTO ((char *, char *, void *));
! extern void Save_Update_Logfile PROTO ((char *, char *, FILE *, List *,
!       struct parse_info_heldinfo *));
! 
  
  extern char *program_name, *program_path, *command_name;
  extern char *Tmpdir, *Editor;
Index: src/diff.c
===================================================================
RCS file: /cvs/ccvs/src/diff.c,v
retrieving revision 1.96
diff -c -r1.96 diff.c
*** src/diff.c  2 Jun 2003 20:05:16 -0000       1.96
--- src/diff.c  17 Jun 2003 13:17:39 -0000
***************
*** 687,695 ****
                                   label1, label2,
                                   finfo->file );
  
        if (label1) free (label1);
        if (label2) free (label2);
-     }
  
      switch (status)
      {
--- 687,695 ----
                                   label1, label2,
                                   finfo->file );
  
+     }
        if (label1) free (label1);
        if (label2) free (label2);
  
      switch (status)
      {
Index: src/logmsg.c
===================================================================
RCS file: /cvs/ccvs/src/logmsg.c,v
retrieving revision 1.65
diff -c -r1.65 logmsg.c
*** src/logmsg.c        11 Jun 2003 18:24:57 -0000      1.65
--- src/logmsg.c        17 Jun 2003 13:17:39 -0000
***************
*** 1003,1005 ****
--- 1003,1120 ----
      *verifymsg_script = xstrdup (script);
      return (0);
  }
+ 
+ #ifndef max
+ # define max(a, b) (((a)>(b))?(a):(b))
+ #endif
+ 
+ static int
+ fmt_proc2(p, closure)
+     Node *p;
+     void *closure;
+ {
+     struct logfile_info *li = (struct logfile_info *) p->data;
+     int len;
+     char *op = "", *vold = li->rev_old, *vnew = li->rev_new;
+     struct parse_info_heldinfo *pih = (struct parse_info_heldinfo *)closure;
+     char *srepos = pih->pd->srepos;
+     struct dynstr *dsp = &pih->pd->mod;
+ 
+     if (!srepos) srepos = "";
+     if (!vold)
+       vold = "-";
+     if (!vnew)
+       vnew = "-";
+     switch (li->type) {
+     case T_MODIFIED:
+       op = "M";
+       break;
+     case T_ADDED:
+       op = "A";
+       break;
+     case T_REMOVED:
+       op = "R";
+       break;
+     default:
+       return (0);
+     }
+ 
+     len = 
strlen(op)+strlen(vold)+strlen(vnew)+strlen(srepos)+strlen(p->key)+6;
+     if ( (dsp->len + len) >= dsp->alloclen) {
+       dsp->alloclen = max(2*dsp->alloclen, dsp->len + len);
+       dsp->str = xrealloc(dsp->str, dsp->alloclen);
+     }
+     sprintf(&dsp->str[dsp->len],"%s\t%s\t%s\t%s\t%s\n",
+               op, vold, vnew, srepos, p->key);
+     dsp->len += len-1;
+     return (0);
+ }
+ 
+ void
+ Save_Update_Logfile(repository, message, logfp, changes, pih)
+     char *repository;
+     char *message;
+     FILE *logfp;
+     List *changes;
+     struct parse_info_heldinfo *pih;
+ {
+     char *cp;
+ 
+     /* nothing to do if the list is empty */
+     if (changes == NULL || changes->list->next == changes->list)
+       return;
+ 
+     if(!pih->logmsg) pih->logmsg = xstrdup(message);
+ 
+       /* push new directory data block */
+     {
+     struct per_dir *newpd = xmalloc(sizeof(struct per_dir));
+     memset(newpd, '\0', sizeof(struct per_dir));
+     newpd->prev = pih->pd;
+     pih->pd = newpd;
+     }
+ 
+     pih->pd->repository = xstrdup(repository);
+ 
+     cp = xgetwd ();
+     if (cp == NULL)
+       error(1, errno, "<cannot get working directory>\n\n");
+     else
+     {
+       pih->pd->dir = xmalloc(strlen(hostname)+1+strlen(cp)+1);
+       sprintf(pih->pd->dir, "%s:%s",hostname,cp);
+       free (cp);
+     }
+     pih->pd->srepos = Short_Repository(repository);
+     (void) walklist(changes, fmt_proc2, pih);
+ }
+ 
+ int
+ logfile_write_merged(repository, filter, udata)
+     char *repository;
+     char *filter;
+     void *udata;
+ {
+     struct parse_info_heldinfo *pih = (struct parse_info_heldinfo *)udata;
+     FILE *pipefp;
+     int pipestatus;
+     struct per_dir *pd;
+ 
+     if ((pipefp = run_popen (filter, "w")) == NULL)
+     {
+       if (!noexec)
+           error (0, 0, "cannot write entry to log filter: %s", filter);
+       return (1);
+     }
+ 
+     pd = pih->pd;
+     while (pd) {
+         (void) fprintf (pipefp, "%s", pd->mod.str);
+         pd = pd->prev;
+     }
+     (void) fprintf (pipefp, "-\t%s\n", getcaller());
+ 
+     fprintf(pipefp, "\n%s\n",pih->logmsg);
+     pipestatus = pclose (pipefp);
+     return ((pipestatus == -1) || (pipestatus == 127)) ? 1 : 0;
+ }
Index: src/mkmodules.c
===================================================================
RCS file: /cvs/ccvs/src/mkmodules.c,v
retrieving revision 1.68
diff -c -r1.68 mkmodules.c
*** src/mkmodules.c     20 May 2003 19:15:46 -0000      1.68
--- src/mkmodules.c     17 Jun 2003 13:17:39 -0000
***************
*** 59,64 ****
--- 59,69 ----
      "# If the name ALL appears as a regular expression it is always used\n",
      "# in addition to the first matching regex or DEFAULT.\n",
      "#\n",
+     "# There are two formats for the filter - \"traditional\" and \"merged\". 
 The\n",
+     "# traditional format filters are run on each directory and the merged 
format\n",
+     "# filters are run once for each commit.\n",
+     "# \n",
+     "# Traditional format:\n",
      "# You may specify a format string as part of the\n",
      "# filter.  The string is composed of a `%' followed\n",
      "# by a single format character, or followed by a set of format\n",
***************
*** 69,74 ****
--- 74,96 ----
      "#   V = old version number (pre-checkin)\n",
      "#   v = new version number (post-checkin)\n",
      "#\n",
+     "# Merged format:\n",
+     "# The loginfo file is scanned for merged loginfo filters only once, thus 
this\n",
+     "# feature should be used only for lines marked ALL, DEFAULT, or 
matching\n",
+     "# all modules in a project.\n",
+     "# \n",
+     "# Unlike traditional mode, no information is substituted on the command 
line.\n",
+     "# \n",
+     "# To trigger this type of filter, preceed the name of the filter program 
with\n",
+     "# a hyphen.  The data available on standard input consists of a line for 
each\n",
+     "# file involved in the commit, information on the user, a blank line, 
and the\n",
+     "# log message.\n",
+     "# The per-file lines consist of 5 tab-separated fields: a letter for 
the\n",
+     "# operation (A for add, D for delete, M for modify), the old version 
number,\n",
+     "# the new version number, the directory in the repository, and the 
filename.\n",
+     "# The information on the user consists of a line with 2 tab-separated 
fields:\n",
+     "# a hypen and an identification of the user.\n",
+     "# \n",
      "# For example:\n",
      "#DEFAULT (echo \"\"; id; echo %s; date; cat) >> 
$CVSROOT/CVSROOT/commitlog\n",
      "# or\n",
Index: src/parseinfo.c
===================================================================
RCS file: /cvs/ccvs/src/parseinfo.c,v
retrieving revision 1.45
diff -c -r1.45 parseinfo.c
*** src/parseinfo.c     11 Jun 2003 18:24:57 -0000      1.45
--- src/parseinfo.c     17 Jun 2003 13:17:39 -0000
***************
*** 19,24 ****
--- 19,26 ----
   *
   * Return 0 for success, -1 if there was not an INFOFILE, and >0 for failure.
   */
+ #define OPTSET(x) (opt & x)
+ 
  int
  Parse_Info( infofile, repository, callproc, opt, closure )
      char *infofile;
***************
*** 34,43 ****
--- 36,47 ----
      size_t line_allocated = 0;
      char *default_value = NULL;
      int default_line = 0;
+     int default_value_hyphen;
      char *expanded_value;
      int callback_done, line_number;
      char *cp, *exp, *value, *srepos;
      const char *regex_err;
+     int parse_info_hyphen;
  
      if (current_parsed_root == NULL)
      {
***************
*** 110,115 ****
--- 114,123 ----
        if ((cp = strrchr (value, '\n')) != NULL)
            *cp = '\0';
  
+       /* Set the hyphen flag and if needed  strip the hyphen */
+       parse_info_hyphen = (value[0] == '-');
+       value += parse_info_hyphen;
+ 
        /*
         * At this point, exp points to the regular expression, and value
         * points to the value to call the callback routine with.  Evaluate
***************
*** 128,133 ****
--- 136,142 ----
            }
            default_value = xstrdup(value);
            default_line = line_number;
+           default_value_hyphen = parse_info_hyphen;
            continue;
        }
  
***************
*** 136,142 ****
         * execute lots of ALL callbacks in addition to *one* regular matching
         * callback or default
         */
!       if (strcmp (exp, "ALL") == 0)
        {
            if (! (opt & PIOPT_ALL))
                error(0, 0, "Keyword `ALL' is ignored at line %d in %s file",
--- 145,157 ----
         * execute lots of ALL callbacks in addition to *one* regular matching
         * callback or default
         */
!       if (strcmp (exp, "ALL") == 0 &&
!           (
!               (parse_info_hyphen && OPTSET(PIOPT_CALL_HYPHEN))
!               ||
!               (!parse_info_hyphen && !OPTSET(PIOPT_CALL_HYPHEN))
!           )
!       )
        {
            if (! (opt & PIOPT_ALL))
                error(0, 0, "Keyword `ALL' is ignored at line %d in %s file",
***************
*** 164,178 ****
        }
        if (re_exec (srepos) == 0)
            continue;                           /* no match */
! 
!       /* it did, so do the callback and note that we did one */
!       if ((expanded_value = expand_path (value, infofile, line_number)) != 
NULL)
!       {
!           err += callproc( repository, expanded_value, closure );
!           free (expanded_value);
        }
!       else
!           err++;
        callback_done = 1;
      }
      if (ferror (fp_info))
--- 179,205 ----
        }
        if (re_exec (srepos) == 0)
            continue;                           /* no match */
!       /*
!        * If we have a hyphen line but aren't supposed to run it, we need to
!        * pretend we've run it.
!        */
! #define PIH parse_info_hyphen
! #define CALLH OPTSET(PIOPT_CALL_HYPHEN)
! #define CALLHO OPTSET(PIOPT_CALL_HYPHEN_ONLY)
!       if( (PIH && (CALLHO|CALLH)) ||(!PIH && !CALLHO) ){
!           /* it did, so do the callback and note that we did one */
!         (expanded_value = expand_path (value, infofile, line_number));
!           if (expanded_value != NULL)
!         {
!               err += callproc ( repository, expanded_value, closure );
!             free (expanded_value);
!         }
!           else
!               err++;
        }
! #undef CALLHO
! #undef CALLH
! #undef PIH
        callback_done = 1;
      }
      if (ferror (fp_info))
***************
*** 181,188 ****
        error (0, errno, "cannot close %s", infopath);
  
      /* if we fell through and didn't callback at all, do the default */
!     if (callback_done == 0 && default_value != NULL)
!     {
        if ((expanded_value = expand_path (default_value, infofile, 
default_line)) != NULL)
        {
            err += callproc( repository, expanded_value, closure );
--- 208,221 ----
        error (0, errno, "cannot close %s", infopath);
  
      /* if we fell through and didn't callback at all, do the default */
!     if (
!           (callback_done == 0 && default_value != NULL)
!       &&
!           (
!               (!OPTSET(PIOPT_CALL_HYPHEN) && !default_value_hyphen)
!               || (OPTSET(PIOPT_CALL_HYPHEN) && default_value_hyphen)
!           )
!     ) {
        if ((expanded_value = expand_path (default_value, infofile, 
default_line)) != NULL)
        {
            err += callproc( repository, expanded_value, closure );
Index: src/sanity.sh
===================================================================
RCS file: /cvs/ccvs/src/sanity.sh,v
retrieving revision 1.805
diff -c -r1.805 sanity.sh
*** src/sanity.sh       12 Jun 2003 20:38:22 -0000      1.805
--- src/sanity.sh       17 Jun 2003 13:17:41 -0000
***************
*** 15842,15847 ****
--- 15842,15923 ----
  done
  ${SPROG} [a-z]*: Rebuilding administrative file database"
  
+         # Test merged loginfo filter
+ 
+         rm -f $TESTDIR/testlog $TESTDIR/testlog2
+         echo "ALL sh -c \"echo 
x\${=MYENV}\${=OTHER}y\${=ZEE}=\$USER=\$CVSROOT= >>$TESTDIR/testlog; cat 
>/dev/null\"" > loginfo
+         echo "ALL -(echo TOP; cat) >>$TESTDIR/testlog2" >> loginfo
+ 
+         dotest info-12 "${testcvs} -q ci -m new-loginfo" \
+ "Checking in loginfo;
+ ${CVSROOT_DIRNAME}/CVSROOT/loginfo,v  <--  loginfo
+ new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
+ done
+ ${SPROG} [a-z]*: Rebuilding administrative file database"
+         cd ..
+ 
+         dotest info-13 "${testcvs} -q co first-dir" ''
+         cd first-dir
+         touch file1m
+         dotest info-14 "${testcvs} add file1m" \
+ "${SPROG}"' [a-z]*: scheduling file `file1m'\'' for addition
+ '"${SPROG}"' [a-z]*: use .'"${SPROG}"' commit. to add this file permanently'
+         echo "cvs -s OTHER=not-this -s MYENV=env-" >>$HOME/.cvsrc
+         dotest info-15 "${testcvs} -q -s OTHER=value ci -m add-it" \
+ "RCS file: ${CVSROOT_DIRNAME}/first-dir/file1m,v
+ done
+ Checking in file1m;
+ ${CVSROOT_DIRNAME}/first-dir/file1m,v  <--  file1m
+ initial revision: 1\.1
+ done
+ ${SPROG} [a-z]*: loginfo:1: no such user variable \${=ZEE}"
+         echo line0 >>file1m
+         dotest info-16 "${testcvs} -q -sOTHER=foo ci -m mod-it" \
+ "Checking in file1m;
+ ${CVSROOT_DIRNAME}/first-dir/file1m,v  <--  file1m
+ new revision: 1\.2; previous revision: 1\.1
+ done
+ ${SPROG} [a-z]*: loginfo:1: no such user variable \${=ZEE}"
+         echo line1 >>file1m
+         dotest info-17 "${testcvs} -q -s OTHER=value -s ZEE=z ci -m mod-it" \
+ "Checking in file1m;
+ ${CVSROOT_DIRNAME}/first-dir/file1m,v  <--  file1m
+ new revision: 1\.3; previous revision: 1\.2
+ done"
+         cd ..
+         dotest info-18 "cat $TESTDIR/testlog" 
"xenv-valueyz=${username}=${CVSROOT_DIRNAME}="
+ 
+           dotest info-19 "cat $TESTDIR/testlog2" \
+ 'TOP
+ M     1.3     1.4     CVSROOT loginfo
+ -     .*
+ 
+ new-loginfo
+ TOP
+ A     -       1.1     first-dir       file1m
+ -     .*
+ 
+ add-it
+ TOP
+ M     1.1     1.2     first-dir       file1m
+ -     .*
+ 
+ mod-it
+ TOP
+ M     1.2     1.3     first-dir       file1m
+ -     .*
+ 
+ mod-it'
+ 
+         cd CVSROOT
+         echo '# do nothing' >loginfo
+         dotest info-20 "${testcvs} -q -s ZEE=garbage ci -m nuke-loginfo" \
+ "Checking in loginfo;
+ ${CVSROOT_DIRNAME}/CVSROOT/loginfo,v  <--  loginfo
+ new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
+ done
+ ${SPROG} [a-z]*: Rebuilding administrative file database"
+ 
          # Now test verifymsg
          cat >${TESTDIR}/vscript <<EOF
  #!${TESTSHELL}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]