Date: Tue, 1 Dec 1998 09:28:00 -0800 From: John Cavanaugh To: bug-cvs@gnu.org Subject: PATCH: Re: Questions/Comments on another history.c patch Content-Type: multipart/mixed; boundary=4Ckj6UjgE2iN1+kY --4Ckj6UjgE2iN1+kY Content-Type: text/plain; charset=us-ascii Here is a final update to the patches I sent you. This patch includes both the fully bounded queries as well as the reduced memory. [I had to make a slight modification to my code since it was much less forgiving about any corruptions in the history file. In my old version cvs would segfault if it encountered a corrupt line in the history file, now it just blissfully continues with the next line.... -;) On Tue, Nov 24, 1998 at 08:27:04PM -0500, Jim Kingdon wrote: > > Attached is a patch that processes the history file line by line. > > I've added this to www.cyclic.com. You should replace it with this one... Thanks. ----------------------------------------------------------------------- John Cavanaugh Hewlett-Packard Company Project Engineer 1400 Fountaingrove Pkwy EESof Division Santa Rosa, CA 95403-1799 Email: cavanaug@sr.hp.com Phone: 707-577-4780 707-577-3948 (Fax) ----------------------------------------------------------------------- As I grow older, I pay less attention to what men say. I just watch what they do. -- Andrew Carnegie ----------------------------------------------------------------------- --4Ckj6UjgE2iN1+kY Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=hist_patch Index: history.c =================================================================== RCS file: /cvs/tools/src/cvs-src/src/history.c,v retrieving revision 1.1 retrieving revision 1.8 diff -c -r1.1 -r1.8 *** history.c 1998/10/08 23:17:04 1.1 --- history.c 1998/12/01 07:22:25 1.8 *************** *** 17,23 **** * X is a single character showing the type of event: * T "Tag" cmd. * O "Checkout" cmd. ! * E "Export" cmd. * F "Release" cmd. * W "Update" cmd - No User file, Remove from Entries file. * U "Update" cmd - File was checked out over User file. --- 17,23 ---- * X is a single character showing the type of event: * T "Tag" cmd. * O "Checkout" cmd. ! * E "Export" cmd. * F "Release" cmd. * W "Update" cmd - No User file, Remove from Entries file. * U "Update" cmd - File was checked out over User file. *************** *** 212,217 **** --- 212,218 ---- #define FILE_INCREMENT 128 #define MODULE_INCREMENT 5 #define HREC_INCREMENT 128 + #define HISTORY_BUF_INCREMENT 1024 static short report_count; *************** *** 243,248 **** --- 244,250 ---- static char *backto; /* -D option, or 0 if not specified. RCS format. */ static char * since_date; + static char * to_date; static struct hrec *last_since_tag; static struct hrec *last_backto; *************** *** 374,379 **** --- 376,383 ---- if (argc == -1) usage (history_usg); + since_date = NULL; + to_date = NULL; since_rev = xstrdup (""); since_tag = xstrdup (""); backto = xstrdup (""); *************** *** 414,425 **** histfile = optarg; break; case 'D': /* Since specified date */ ! if (*since_rev || *since_tag || *backto) ! { ! error (0, 0, "date overriding rev/tag/backto"); ! *since_rev = *since_tag = *backto = '\0'; ! } ! since_date = Make_Date (optarg); break; case 'b': /* Since specified file/Repos */ if (since_date || *since_rev || *since_tag) --- 418,440 ---- histfile = optarg; break; case 'D': /* Since specified date */ ! if (since_date==NULL) ! { ! if (*since_rev || *since_tag || *backto) ! { ! error (0, 0, "date overriding rev/tag/backto"); ! *since_rev = *since_tag = *backto = '\0'; ! } ! since_date = Make_Date (optarg); ! } ! else ! { ! if (to_date != NULL) ! error (1, 0, "no more than two dates can be specified"); ! to_date = Make_Date (optarg); ! if (RCS_datecmp(to_date, since_date) < 0) ! error (1, 0, "invalid date range specified"); ! } break; case 'b': /* Since specified file/Repos */ if (since_date || *since_rev || *since_tag) *************** *** 429,434 **** --- 444,450 ---- if (since_date != NULL) free (since_date); since_date = NULL; + to_date = NULL; } free (backto); backto = xstrdup (optarg); *************** *** 453,458 **** --- 469,475 ---- if (since_date != NULL) free (since_date); since_date = NULL; + to_date = NULL; } free (since_rev); since_rev = xstrdup (optarg); *************** *** 465,470 **** --- 482,488 ---- if (since_date != NULL) free (since_date); since_date = NULL; + to_date = NULL; } free (since_tag); since_tag = xstrdup (optarg); *************** *** 558,563 **** --- 576,583 ---- send_arg("-X"); if (since_date) client_senddate (since_date); + if (to_date) + client_senddate (to_date); if (backto[0] != '\0') option_with_arg ("-b", backto); for (f1 = file_list; f1 < &file_list[file_count]; ++f1) *************** *** 719,730 **** } if (trace) ! #ifdef SERVER_SUPPORT ! fprintf (stderr, "%c-> fopen(%s,a)\n", ! (server_active) ? 'S' : ' ', fname); ! #else ! fprintf (stderr, "-> fopen(%s,a)\n", fname); ! #endif if (noexec) goto out; fd = CVS_OPEN (fname, O_WRONLY | O_APPEND | O_CREAT | OPEN_BINARY, 0666); --- 739,746 ---- } if (trace) ! fprintf (stderr, "%s-> fopen(%s,a)\n", ! CLIENT_SERVER_STR, fname); if (noexec) goto out; fd = CVS_OPEN (fname, O_WRONLY | O_APPEND | O_CREAT | OPEN_BINARY, 0666); *************** *** 985,996 **** unsigned long date; memset ((char *) hr, 0, sizeof (*hr)); - while (isspace (*line)) - line++; - if (!(rtn = strchr (line, '\n'))) - return (""); - *rtn++ = '\0'; hr->type = line++; (void) sscanf (line, "%lx", &date); hr->date = date; --- 1001,1009 ---- unsigned long date; memset ((char *) hr, 0, sizeof (*hr)); + rtn = line+strlen(line)+1; + hr->type = line++; (void) sscanf (line, "%lx", &date); hr->date = date; *************** *** 1009,1015 **** hr->end = line + off; } else ! hr->end = line - 1; /* A handy pointer to '\0' */ NEXT_BAR (repos); NEXT_BAR (rev); hr->idx = idx++; --- 1022,1028 ---- hr->end = line + off; } else ! hr->end = '\0'; NEXT_BAR (repos); NEXT_BAR (rev); hr->idx = idx++; *************** *** 1017,1022 **** --- 1030,1036 ---- hr->mod = line; NEXT_BAR (file); /* This returns ptr to next line or final '\0' */ + return (rtn); /* If it falls through, go on to next record */ } *************** *** 1024,1031 **** * (history record) array elements with the ones we need to print. * * Logic: ! * - Read the whole history file into a single buffer. ! * - Walk through the buffer, parsing lines out of the buffer. * 1. Split line into pointer and integer fields in the "next" hrec. * 2. Apply tests to the hrec to see if it is wanted. * 3. If it *is* wanted, bump the hrec pointer down by one. --- 1038,1044 ---- * (history record) array elements with the ones we need to print. * * Logic: ! * - Walk through the history file line by line * 1. Split line into pointer and integer fields in the "next" hrec. * 2. Apply tests to the hrec to see if it is wanted. * 3. If it *is* wanted, bump the hrec pointer down by one. *************** *** 1034,1075 **** read_hrecs (fname) char *fname; { ! char *cp, *cp2; ! int i, fd; struct hrec *hr; - struct stat st_buf; ! if ((fd = CVS_OPEN (fname, O_RDONLY | OPEN_BINARY)) < 0) error (1, errno, "cannot open history file: %s", fname); - if (fstat (fd, &st_buf) < 0) - error (1, errno, "can't stat history file"); - - /* Exactly enough space for lines data */ - if (!(i = st_buf.st_size)) - error (1, 0, "history file is empty"); - cp = xmalloc (i + 2); - - if (read (fd, cp, i) != i) - error (1, errno, "cannot read log file"); - (void) close (fd); - - if (*(cp + i - 1) != '\n') - { - *(cp + i) = '\n'; /* Make sure last line ends in '\n' */ - i++; - } - *(cp + i) = '\0'; - for (cp2 = cp; cp2 - cp < i; cp2++) - { - if (*cp2 != '\n' && !isprint (*cp2)) - *cp2 = ' '; - } - hrec_max = HREC_INCREMENT; hrec_head = (struct hrec *) xmalloc (hrec_max * sizeof (struct hrec)); ! while (*cp) { if (hrec_count == hrec_max) { --- 1047,1065 ---- read_hrecs (fname) char *fname; { ! char *cp_base, *cp1, *cp2; ! int i; ! FILE *fd; struct hrec *hr; ! if ((fd = CVS_FOPEN (fname, "r")) < 0) error (1, errno, "cannot open history file: %s", fname); hrec_max = HREC_INCREMENT; hrec_head = (struct hrec *) xmalloc (hrec_max * sizeof (struct hrec)); + cp_base = cp1 = (char *) xmalloc (HISTORY_BUF_INCREMENT * PATH_MAX); ! while ( fscanf(fd,"%s",cp1)!=EOF ) { if (hrec_count == hrec_max) { *************** *** 1087,1098 **** } } hr = hrec_head + hrec_count; ! cp = fill_hrec (cp, hr); /* cp == next line or '\0' at end of buffer */ if (select_hrec (hr)) hrec_count++; } /* Special selection problem: If "since_tag" is set, we have saved every * record from the 1st occurrence of "since_tag", when we want to save --- 1077,1114 ---- } } + + cp2=cp1; i=0; + while (*cp2 != '\0') + { + if (*cp2 == '|') i++; + cp2++; + } + + if (i==5) + { hr = hrec_head + hrec_count; ! cp2 = fill_hrec(cp1, hr); if (select_hrec (hr)) + { hrec_count++; + + if ( ( (HISTORY_BUF_INCREMENT-1)*PATH_MAX - (int) (cp1 - cp_base) ) < 0 ) + cp_base = cp1 = (char *) xmalloc (HISTORY_BUF_INCREMENT * PATH_MAX); + else + cp1=cp2; /* Only advance the index if its a match.... */ + } + } + else + { + if (trace) + { + fprintf (stderr, "Warning: Your $CVSROOT/history file has corruptions.\n"); + fprintf (stderr, "Contact your cvs administrator with this information\n"); + } } + } /* Special selection problem: If "since_tag" is set, we have saved every * record from the 1st occurrence of "since_tag", when we want to save *************** *** 1111,1116 **** --- 1127,1134 ---- hrec_count -= (last_backto - hrec_head); hrec_head = last_backto; } + + fclose(fd); } /* Utility program for determining whether "find" is inside "string" */ *************** *** 1150,1156 **** int count; /* "Since" checking: The argument parser guarantees that only one of the ! * following four choices is set: * * 1. If "since_date" is set, it contains the date specified on the * command line. hr->date fields earlier than "since_date" are ignored. --- 1168,1174 ---- int count; /* "Since" checking: The argument parser guarantees that only one of the ! * following five choices is set: * * 1. If "since_date" is set, it contains the date specified on the * command line. hr->date fields earlier than "since_date" are ignored. *************** *** 1169,1180 **** * repository field with a *prefix* matching "backto" are saved. * The field "last_backto" is set to the last one of these. As in * 3. above, "select_hrec" adjusts to include the last one later on. */ ! if (since_date) { char *ourdate = date_from_time_t (hr->date); ! if (RCS_datecmp (ourdate, since_date) < 0) return (0); free (ourdate); --- 1187,1203 ---- * repository field with a *prefix* matching "backto" are saved. * The field "last_backto" is set to the last one of these. As in * 3. above, "select_hrec" adjusts to include the last one later on. + * 5. If "since_date" & "to_date" is set, they contain the dates specified + * on the command line. hr->date fields earlier than "since_date" & after + * "to_date" are ignored. */ ! if (since_date || to_date) { char *ourdate = date_from_time_t (hr->date); ! if (since_date && RCS_datecmp (ourdate, since_date) < 0) ! return (0); ! if (to_date && RCS_datecmp (to_date, ourdate) < 0) return (0); free (ourdate); --4Ckj6UjgE2iN1+kY--