diff --git a/src/ChangeLog b/src/ChangeLog index d1676912c9d42bdb453b8937480fe0704dc465bc..bd82b22c6c5bdf3d65e871f49e7ef1338d4daed7 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,20 @@ 2008-10-02 Derek R. Price <derek@ximbiot.com> + * history.c: Some cleanup. + (expand_modules): Removed this stub function. + (get_history_log_name): Don't return const since it is freshly + allocated. + (history_write): Add version number to history records. Use tag + fields like other record types. + (fill_hrec): Load version number & postprocess history records as + needed. Zero records with memset. + (read_hrecs_file): Don't zero records redundantly with fill_hrec(). + (report_hrecs): Find tag data in the same place as other record types. + * sanity.sh (basic2-64): Expect new tag records. + * tag.c: Some cleanup. + (cvstag): Move history log call to... + (tag_filesdoneproc): ...here, where we have more information. + * modules.c (my_module): Clean up TRACE. * subr.h [NULL2DOT, NULL2MT]: Add parens for safety. diff --git a/src/history.c b/src/history.c index 8e159068e8bab935ec7b6bdf75a97b643d160afe..734f38a0eeabe4cfe9cbe5ad1d881a25054be4bf 100644 --- a/src/history.c +++ b/src/history.c @@ -20,6 +20,7 @@ #include "history.h" /* GNULIB */ +#include "quote.h" #include "save-cwd.h" /* CVS */ @@ -222,19 +223,19 @@ static struct hrec char *mod; /* The module within which the file is contained */ time_t date; /* Calculated from date stored in record */ long idx; /* Index of record, for "stable" sort. */ + unsigned long version; /* Version number for line + * interpretation. + */ const char *source_file_name; /* For error messages. */ long source_line_num; /* For error messages. */ } *hrec_head; static long hrec_idx; -static void fill_hrec (const char *source_file_name, long source_line_num, - char *line, struct hrec * hr); static int accept_hrec (struct hrec * hr, struct hrec * lr); static int select_hrec (struct hrec * hr); static int sort_order (const void *l, const void *r); static int within (char *find, char *string); -static void expand_modules (void); static void read_hrecs (List *flist); static void report_hrecs (void); static void save_file (char *dir, char *name, char *module); @@ -396,9 +397,9 @@ sort_order (const void *l, const void *r) /* Get the name of the history log, either from CVSROOT/config, or via the - * hard-coded default. + * hard-coded default. Return the result in freshly allocated memory. */ -static const char * +static char * get_history_log_name (time_t now) { char *log_name; @@ -420,14 +421,9 @@ get_history_log_name (time_t now) } if (!config->HistoryLogPath) - { /* Use the default. */ - log_name = xmalloc (strlen (current_parsed_root->directory) - + sizeof (CVSROOTADM) - + sizeof (CVSROOTADM_HISTORY) + 3); - sprintf (log_name, "%s/%s/%s", current_parsed_root->directory, - CVSROOTADM, CVSROOTADM_HISTORY); - } + log_name = dir_append_dirs (current_parsed_root->directory, CVSROOTADM, + CVSROOTADM_HISTORY, NULL); return log_name; } @@ -690,15 +686,12 @@ history (int argc, char **argv) if (all_users) save_user (""); - if (mod_list) - expand_modules (); - if (tag_report) { if (!strchr (rec_types, 'T')) { rec_types = xrealloc (rec_types, strlen (rec_types) + 5); - (void) strcat (rec_types, "T"); + strcat (rec_types, "T"); } } else if (extract || extract_all) @@ -789,11 +782,10 @@ history (int argc, char **argv) read_hrecs (flist); if (hrec_count > 0) qsort (hrec_head, hrec_count, sizeof (struct hrec), sort_order); - report_hrecs (); - free_hrecs (); + report_hrecs(); + free_hrecs(); dellist (&flist); - if (since_date != NULL) - free (since_date); + if (since_date) free (since_date); free (since_rev); free (since_tag); free (backto); @@ -812,19 +804,21 @@ history_write (int type, const char *update_dir, const char *revs, { char *fname = NULL; char *workdir; - char *username = getcaller (); + char *username = getcaller(); int fd; char *line; - char *slash = "", *cp; + char *cp; const char *cp2, *repos; int i; static char *tilde = ""; static char *PrCurDir = NULL; time_t now; +#define HISTORY_VERSION 1l + + TRACE (TRACE_FUNCTION, "history_write (%d, %s, %s, %s, %s)", + type, update_dir, TRACE_NULL (revs), name, repository); - if (logoff) /* History is turned off by noexec or - * readonlyfs. - */ + if (logoff) /* History is turned off by noexec or readonlyfs. */ return; if (!strchr (config->logHistory, type)) return; @@ -838,9 +832,9 @@ history_write (int type, const char *update_dir, const char *revs, { char *pwdir; - pwdir = get_homedir (); + pwdir = get_homedir(); PrCurDir = CurDir; - if (pwdir != NULL) + if (pwdir) { /* Assumes neither CurDir nor pwdir ends in '/' */ i = strlen (pwdir); @@ -858,7 +852,7 @@ history_write (int type, const char *update_dir, const char *revs, if (save_cwd (&cwd)) error (1, errno, "Failed to save current directory."); - if (CVS_CHDIR (pwdir) < 0 || (homedir = xgetcwd ()) == NULL) + if (CVS_CHDIR (pwdir) < 0 || !(homedir = xgetcwd())) homedir = pwdir; if (restore_cwd (&cwd)) @@ -880,17 +874,7 @@ history_write (int type, const char *update_dir, const char *revs, } } - if (type == 'T') - { - repos = update_dir; - update_dir = ""; - } - else if (update_dir && *update_dir) - slash = "/"; - else - update_dir = ""; - - workdir = Xasprintf ("%s%s%s%s", tilde, PrCurDir, slash, update_dir); + workdir = dir_append_dirs (tilde, PrCurDir, update_dir, NULL); /* * "workdir" is the directory where the file "name" is. ("^~" == $HOME) @@ -930,6 +914,8 @@ history_write (int type, const char *update_dir, const char *revs, * "repos". On the other hand, we *can* run off the top of "repos". * * Only "compress" if we save characters. + * + * As of CVS 1.12.14, the 7th field is a hex version number 1. */ cp = workdir + strlen (workdir) - 1; @@ -940,16 +926,15 @@ history_write (int type, const char *update_dir, const char *revs, if (i > 2) { i = strlen (repos) - i; - (void) sprintf ((cp + 1), "*%x", i); + sprintf (cp + 1, "*%x", i); } - if (!revs) - revs = ""; now = time (NULL); - line = Xasprintf ("%c%08lx|%s|%s|%s|%s|%s\n", type, (long) now, - username, workdir, repos, revs, name); + line = Xasprintf ("%c%08lx|%s|%s|%s|%s|%s|%lx\n", type, + (long) now, username, workdir, repos, NULL2MT (revs), + name, HISTORY_VERSION); - fname = (char *) get_history_log_name (now); + fname = get_history_log_name (now); if (!history_lock (current_parsed_root->directory)) /* history_lock() will already have printed an error on failure. */ @@ -960,11 +945,12 @@ history_write (int type, const char *update_dir, const char *revs, { if (!really_quiet) error (0, errno, - "warning: cannot open history file `%s' for write", fname); + "warning: cannot open history file %s for write", + quote (fname)); goto out; } - TRACE (TRACE_FUNCTION, "open (`%s', a)", fname); + TRACE (TRACE_FUNCTION, "open (%s, a)", quote (fname)); /* Lessen some race conditions on non-Posix-compliant hosts. * @@ -975,18 +961,18 @@ history_write (int type, const char *update_dir, const char *revs, * unnecessary. */ if (lseek (fd, (off_t) 0, SEEK_END) == -1) - error (1, errno, "cannot seek to end of history file: %s", fname); + error (1, errno, "cannot seek to end of history file: %s", + quote (fname)); if (write (fd, line, strlen (line)) < 0) - error (1, errno, "cannot write to history file: %s", fname); + error (1, errno, "cannot write to history file: %s", quote (fname)); free (line); - if (close (fd) != 0) - error (1, errno, "cannot close history file: %s", fname); + if (close (fd)) + error (1, errno, "cannot close history file: %s", quote (fname)); free (workdir); out: - if (fname) - free (fname); - clear_history_lock (); + if (fname) free (fname); + clear_history_lock(); } @@ -1012,6 +998,8 @@ save_user (char *name) user_list[user_count++] = xstrdup (name); } + + /* * save_file() adds file name and associated module to the file list to select. * @@ -1059,6 +1047,8 @@ save_file (char *dir, char *name, char *module) } } + + static void save_module (char *module) { @@ -1076,10 +1066,7 @@ save_module (char *module) mod_list[mod_count++] = xstrdup (module); } -static void -expand_modules (void) -{ -} + /* fill_hrec * @@ -1089,14 +1076,13 @@ expand_modules (void) * * Split it into 7 parts and drop the parts into a "struct hrec". * Return a pointer to the character following the newline. - * */ #define NEXT_BAR(here) do { \ while (isspace (*line)) line++; \ hr->here = line; \ while ((c = *line++) && c != '|') ; \ - if (!c) return; line[-1] = '\0'; \ + if (!c) goto done_reading; line[-1] = '\0'; \ } while (0) static void @@ -1105,9 +1091,11 @@ fill_hrec (const char *source_file_name, long source_line_num, { char *cp; int c; + static bool warned_version; + + /* initialize new records */ + memset (hr, 0, sizeof (struct hrec)); - hr->type = hr->user = hr->dir = hr->repos = hr->rev = hr->file = - hr->end = hr->mod = NULL; hr->date = -1; hr->idx = ++hrec_idx; hr->source_file_name = source_file_name; @@ -1119,11 +1107,11 @@ fill_hrec (const char *source_file_name, long source_line_num, hr->type = line++; hr->date = strtoul (line, &cp, 16); if (cp == line || *cp != '|') - return; + goto done_reading; line = cp + 1; NEXT_BAR (user); NEXT_BAR (dir); - if ((cp = strrchr (hr->dir, '*')) != NULL) + if (cp = strrchr (hr->dir, '*')) { *cp++ = '\0'; hr->end = line + strtoul (cp, NULL, 16); @@ -1136,9 +1124,52 @@ fill_hrec (const char *source_file_name, long source_line_num, hr->mod = line; NEXT_BAR (file); + + /* There is a version number. This started in CVS 1.12.14. */ + hr->version = strtoul (line, &cp, 16); + if (cp == line || *cp != '|') + goto done_reading; + line = cp + 1; + +done_reading: + /* Post-process the history record based on the version number. + * + * If each case converts the record into the state required for the + * next version up, it may eventually become a little processor intensive, + * but it's going to be very easy to maintain. + */ + switch (hr->version) + { + case 0: + /* Prior to version 1, tag records had the tag op stored in the + * repository field and a toplevel repository stored in the module + * field. + */ + if (*hr->type == 'T') + { + char *tmp = hr->mod; + hr->mod = hr->repos; + hr->repos = tmp; + } + /* Done converting to version 1. Fall through in case we need to + * continue converting to a later version. + */ + case 1: + /* This contains what we currently expect. */ + break; + default: + if (!really_quiet && !warned_version) + { + error (0, 0, "unrecognized history record version: %ul", + hr->version); + warned_version = true; + } + break; + } } + #ifndef STAT_BLOCKSIZE #if HAVE_STRUCT_STAT_ST_BLKSIZE #define STAT_BLOCKSIZE(s) (s).st_blksize @@ -1172,19 +1203,19 @@ read_hrecs_file (Node *p, void *closure) if ((fd = CVS_OPEN (fname, O_RDONLY | OPEN_BINARY)) < 0) { - error (0, errno, "cannot open history file `%s'", fname); + error (0, errno, "cannot open history file %s", quote (fname)); return 0; } if (fstat (fd, &st_buf) < 0) { - error (0, errno, "can't stat history file `%s'", fname); + error (0, errno, "can't stat history file %s", quote (fname)); return 0; } if (!(st_buf.st_size)) { - error (0, 0, "history file `%s' is empty", fname); + error (0, 0, "history file %s is empty", quote (fname)); return 0; } @@ -1201,10 +1232,9 @@ read_hrecs_file (Node *p, void *closure) if (nl >= cpend) { if (nl - cp >= STAT_BLOCKSIZE (st_buf)) - { - error(1, 0, "line %ld of history file `%s' too long (> %lu)", - line_num, fname, (unsigned long) STAT_BLOCKSIZE(st_buf)); - } + error(1, 0, "line %ld of history file %s too long (> %lu)", + line_num, quote (fname), + (unsigned long) STAT_BLOCKSIZE(st_buf)); if (nl > cp) memmove (cpstart, cp, nl - cp); nl = cpstart + (nl - cp); @@ -1237,9 +1267,6 @@ read_hrecs_file (Node *p, void *closure) error (1, 0, "Too many history records in history file."); hrec_head = xnrealloc (hrec_head, hrec_max, sizeof (struct hrec)); - /* initialize newly added records */ - memset (&hrec_head[hrec_count], 0, - HREC_INCREMENT * sizeof (struct hrec)); if (last_since_tag) last_since_tag = hrec_head + (last_since_tag - old_head); if (last_backto) @@ -1536,6 +1563,8 @@ select_hrec (struct hrec *hr) return 1; /* Select this record unless rejected above. */ } + + /* The "sort_order" routine (when handed to qsort) has arranged for the * hrecs files to be in the right order for the report. * @@ -1553,17 +1582,17 @@ report_hrecs (void) if (*since_tag && !last_since_tag) { - (void) printf ("No tag found: %s\n", since_tag); + printf ("No tag found: %s\n", since_tag); return; } else if (*backto && !last_backto) { - (void) printf ("No module, file or repository with: %s\n", backto); + printf ("No module, file or repository with: %s\n", backto); return; } else if (hrec_count < 1) { - (void) printf ("No records selected.\n"); + printf ("No records selected.\n"); return; } @@ -1583,23 +1612,20 @@ report_hrecs (void) ty = *(lr->type); repos = xstrdup (lr->repos); - if ((cp = strrchr (repos, '/')) != NULL) + user_len = MAX (user_len, strlen (lr->user)); + if (ty != 'T') { - if (lr->mod && STREQ (++cp, lr->mod)) + if (cp = strrchr (repos, '/')) { - (void) strcpy (cp, "*"); + if (lr->mod && STREQ (++cp, lr->mod)) + strcpy (cp, "*"); } + file_len = MAX (file_len, strlen (lr->file)); + repos_len = MAX (repos_len, strlen (repos)); + rev_len = MAX (rev_len, strlen (lr->rev));; + if (lr->mod) + mod_len = MAX (mod_len, strlen (lr->mod)); } - if ((i = strlen (lr->user)) > user_len) - user_len = i; - if ((i = strlen (lr->file)) > file_len) - file_len = i; - if (ty != 'T' && (i = strlen (repos)) > repos_len) - repos_len = i; - if (ty != 'T' && (i = strlen (lr->rev)) > rev_len) - rev_len = i; - if (lr->mod && (i = strlen (lr->mod)) > mod_len) - mod_len = i; free (repos); } @@ -1631,46 +1657,40 @@ report_hrecs (void) else tm = localtime (&(lr->date)); - (void) printf ("%c %04d-%02d-%02d %02d:%02d %s %-*s", ty, - tm->tm_year+1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, - tm->tm_min, tz_name, user_len, lr->user); + printf ("%c %04d-%02d-%02d %02d:%02d %s %-*s", ty, + tm->tm_year+1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, + tm->tm_min, tz_name, user_len, lr->user); workdir = xmalloc (strlen (lr->dir) + strlen (lr->end) + 10); - (void) sprintf (workdir, "%s%s", lr->dir, lr->end); - if ((cp = strrchr (workdir, '/')) != NULL) + sprintf (workdir, "%s%s", lr->dir, lr->end); + if (cp = strrchr (workdir, '/')) { if (lr->mod && STREQ (++cp, lr->mod)) - { - (void) strcpy (cp, "*"); - } + strcpy (cp, "*"); } repos = xmalloc (strlen (lr->repos) + 10); - (void) strcpy (repos, lr->repos); - if ((cp = strrchr (repos, '/')) != NULL) + strcpy (repos, lr->repos); + if (cp = strrchr (repos, '/')) { if (lr->mod && STREQ (++cp, lr->mod)) - { - (void) strcpy (cp, "*"); - } + strcpy (cp, "*"); } switch (ty) { case 'T': - /* 'T'ag records: repository is a "tag type", rev is the tag */ - (void) printf (" %-*s [%s:%s]", mod_len, lr->mod, lr->rev, - repos); + /* 'T'ag records: module is a "tag type", rev is the tag */ + printf (" %-*s [%s:%s]", repos_len, repos, lr->rev, lr->mod); if (working) - (void) printf (" {%s}", workdir); + printf (" {%s}", workdir); break; case 'F': case 'E': case 'O': if (lr->rev && *(lr->rev)) - (void) printf (" [%s]", lr->rev); - (void) printf (" %-*s =%s%-*s %s", repos_len, repos, lr->mod, - mod_len + 1 - (int) strlen (lr->mod), - "=", workdir); + printf (" [%s]", lr->rev); + printf (" %-*s =%s%-*s %s", repos_len, repos, lr->mod, + mod_len + 1 - (int) strlen (lr->mod), "=", workdir); break; case 'W': case 'U': @@ -1681,15 +1701,15 @@ report_hrecs (void) case 'A': case 'R': case 'X': - (void) printf (" %-*s %-*s %-*s =%s= %s", rev_len, lr->rev, - file_len, lr->file, repos_len, repos, - lr->mod ? lr->mod : "", workdir); + printf (" %-*s %-*s %-*s =%s= %s", rev_len, lr->rev, + file_len, lr->file, repos_len, repos, + NULL2MT (lr->mod), workdir); break; default: - (void) printf ("Hey! What is this junk? RecType[0x%2.2x]", ty); + printf ("Hey! What is this junk? RecType[0x%2.2x]", ty); break; } - (void) putchar ('\n'); + putchar ('\n'); free (workdir); free (repos); } diff --git a/src/sanity.sh b/src/sanity.sh index 5ca0381f8031193997b749b78171e8989f269273..7f268bddfc6f173044eecba322f901ff55b3d4bf 100755 --- a/src/sanity.sh +++ b/src/sanity.sh @@ -5275,53 +5275,81 @@ ${SPROG} update: Updating dir1/dir2" # ditch that notion and require GNU expr (or dejagnu or....) # since it seems to be so painful. - dotest basic2-64 "${testcvs} his -x TOFWUPCGMAR -a" \ -"O [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir =first-dir= ${TESTDIR}/\* -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6 first-dir == ${TESTDIR} -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7 first-dir == ${TESTDIR} -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6 first-dir/dir1 == ${TESTDIR} -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7 first-dir/dir1 == ${TESTDIR} -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6 first-dir/dir1/dir2 == ${TESTDIR} -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7 first-dir/dir1/dir2 == ${TESTDIR} -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14 first-dir == ${TESTDIR} -M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir == ${TESTDIR} -R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7 first-dir == ${TESTDIR} -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14 first-dir/dir1 == ${TESTDIR} -M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir/dir1 == ${TESTDIR} -R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7 first-dir/dir1 == ${TESTDIR} -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14 first-dir/dir1/dir2 == ${TESTDIR} -M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir/dir1/dir2 == ${TESTDIR} -R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7 first-dir/dir1/dir2 == ${TESTDIR} -F [0-9-]* [0-9:]* ${PLUS}0000 ${username} =first-dir= ${TESTDIR}/\* -T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-head:A\] -T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-tag:rtagged-by-head\] -T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-revision:1\.1\] -O [0-9-]* [0-9:]* ${PLUS}0000 ${username} \[1\.1\] first-dir =first-dir= ${TESTDIR}/\* -U [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir == ${TESTDIR}/first-dir -W [0-9-]* [0-9:]* ${PLUS}0000 ${username} file7 first-dir == ${TESTDIR}/first-dir" \ -"O [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir =first-dir= <remote>/\* -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6 first-dir == <remote> -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7 first-dir == <remote> -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6 first-dir/dir1 == <remote> -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7 first-dir/dir1 == <remote> -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6 first-dir/dir1/dir2 == <remote> -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7 first-dir/dir1/dir2 == <remote> -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14 first-dir == <remote> -M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir == <remote> -R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7 first-dir == <remote> -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14 first-dir/dir1 == <remote> -M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir/dir1 == <remote> -R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7 first-dir/dir1 == <remote> -A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14 first-dir/dir1/dir2 == <remote> -M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir/dir1/dir2 == <remote> -R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7 first-dir/dir1/dir2 == <remote> -F [0-9-]* [0-9:]* ${PLUS}0000 ${username} =first-dir= <remote>/\* -T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-head:A\] -T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-tag:rtagged-by-head\] -T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-revision:1\.1\] -O [0-9-]* [0-9:]* ${PLUS}0000 ${username} \[1\.1\] first-dir =first-dir= <remote>/\* -[UP] [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir == <remote> -W [0-9-]* [0-9:]* ${PLUS}0000 ${username} file7 first-dir == <remote>" + dotest basic2-64 "$testcvs history -x TOFWUPCGMAR -a" \ +"O [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir =first-dir= $TESTDIR/\* +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file6 first-dir == $TESTDIR +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file7 first-dir == $TESTDIR +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file6 first-dir/dir1 == $TESTDIR +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file7 first-dir/dir1 == $TESTDIR +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file6 first-dir/dir1/dir2 == $TESTDIR +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file7 first-dir/dir1/dir2 == $TESTDIR +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir \[second-dive:A\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1 \[second-dive:A\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1/dir2 \[second-dive:A\] +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file14 first-dir == $TESTDIR +M [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.2 file6 first-dir == $TESTDIR +R [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.2 file7 first-dir == $TESTDIR +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file14 first-dir/dir1 == $TESTDIR +M [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.2 file6 first-dir/dir1 == $TESTDIR +R [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.2 file7 first-dir/dir1 == $TESTDIR +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file14 first-dir/dir1/dir2 == $TESTDIR +M [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.2 file6 first-dir/dir1/dir2 == $TESTDIR +R [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.2 file7 first-dir/dir1/dir2 == $TESTDIR +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir \[third-dive:A\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1 \[third-dive:A\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1/dir2 \[third-dive:A\] +F [0-9-]* [0-9:]* ${PLUS}0000 $username =first-dir= $TESTDIR/\* +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir \[rtagged-by-head:A\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1 \[rtagged-by-head:A\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1/dir2 \[rtagged-by-head:A\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir \[rtagged-by-tag:rtagged-by-head\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1 \[rtagged-by-tag:rtagged-by-head\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1/dir2 \[rtagged-by-tag:rtagged-by-head\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir \[rtagged-by-revision:1.1\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1 \[rtagged-by-revision:1.1\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1/dir2 \[rtagged-by-revision:1.1\] +O [0-9-]* [0-9:]* ${PLUS}0000 $username \[1\.1\] first-dir =first-dir= $TESTDIR/\* +U [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.2 file6 first-dir == $TESTDIR/first-dir +W [0-9-]* [0-9:]* ${PLUS}0000 $username file7 first-dir == $TESTDIR/first-dir +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir \[rtagged-by-revision:D\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir \[rtagged-by-revision:A\]" \ +"O [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir =first-dir= <remote>/\* +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file6 first-dir == <remote> +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file7 first-dir == <remote> +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file6 first-dir/dir1 == <remote> +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file7 first-dir/dir1 == <remote> +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file6 first-dir/dir1/dir2 == <remote> +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file7 first-dir/dir1/dir2 == <remote> +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir \[second-dive:A\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1 \[second-dive:A\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1/dir2 \[second-dive:A\] +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file14 first-dir == <remote> +M [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.2 file6 first-dir == <remote> +R [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.2 file7 first-dir == <remote> +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file14 first-dir/dir1 == <remote> +M [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.2 file6 first-dir/dir1 == <remote> +R [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.2 file7 first-dir/dir1 == <remote> +A [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.1 file14 first-dir/dir1/dir2 == <remote> +M [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.2 file6 first-dir/dir1/dir2 == <remote> +R [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.2 file7 first-dir/dir1/dir2 == <remote> +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir \[third-dive:A\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1 \[third-dive:A\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1/dir2 \[third-dive:A\] +F [0-9-]* [0-9:]* ${PLUS}0000 $username =first-dir= <remote>/\* +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir \[rtagged-by-head:A\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1 \[rtagged-by-head:A\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1/dir2 \[rtagged-by-head:A\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir \[rtagged-by-tag:rtagged-by-head\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1 \[rtagged-by-tag:rtagged-by-head\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1/dir2 \[rtagged-by-tag:rtagged-by-head\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir \[rtagged-by-revision:1.1\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1 \[rtagged-by-revision:1.1\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir/dir1/dir2 \[rtagged-by-revision:1.1\] +O [0-9-]* [0-9:]* ${PLUS}0000 $username \[1\.1\] first-dir =first-dir= <remote>/\* +[UP] [0-9-]* [0-9:]* ${PLUS}0000 $username 1\.2 file6 first-dir == <remote> +W [0-9-]* [0-9:]* ${PLUS}0000 $username file7 first-dir == <remote> +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir \[rtagged-by-revision:D\] +T [0-9-]* [0-9:]* ${PLUS}0000 $username first-dir \[rtagged-by-revision:A\]" fi dokeep diff --git a/src/tag.c b/src/tag.c index 6bf5796aa1dbeb8f79d2ce9df5ea297a19c6e518..4b8caa31924d14f09297886359fb509c6c5a08e6 100644 --- a/src/tag.c +++ b/src/tag.c @@ -226,9 +226,9 @@ cvstag (int argc, char **argv) if (current_parsed_root->isremote) { /* We're the client side. Fire up the remote server. */ - start_server (); + start_server(); - ign_setup (); + ign_setup(); if (attic_too) send_arg ("-a"); @@ -277,7 +277,7 @@ cvstag (int argc, char **argv) send_to_server ("tag\012", 0); } - return get_responses_and_close (); + return get_responses_and_close(); } #endif @@ -285,12 +285,9 @@ cvstag (int argc, char **argv) { DBM *db; int i; - db = open_module (); + db = open_module(); for (i = 0; i < argc; i++) { - /* XXX last arg should be repository, but doesn't make sense here */ - history_write ('T', (delete_flag ? "D" : (numtag ? numtag : - (date ? date : "A"))), symtag, argv[i], ""); err += do_module (db, argv[i], TAG, delete_flag ? "Untagging" : "Tagging", rtag_proc, NULL, 0, local, run_module_prog, @@ -414,6 +411,19 @@ tag_filesdoneproc (void *callerdat, int err, const char *repository, if (list_isempty (tlist)) return err; + /* FIXME: This is more information than used to be logged about tags, but + * it still isn't enough to distinguish between a tag of everything in the + * directory and a tags of a subset of the files. + * + * I was thinking maybe a new 't' history type that logged individual + * tagged files, including the revision that was tagged. This would make + * it possible to recover deleted branches and tags using the history + * file and `cvs admin'. + */ + history_write ('T', update_dir, symtag, + delete_flag ? "D" : numtag ? numtag : date ? date : "A", + repository); + ppd.tlist = tlist; ppd.delete_flag = delete_flag; ppd.force_tag_move = force_tag_move; @@ -1000,7 +1010,7 @@ rtag_fileproc (void *callerdat, struct file_info *finfo) { /* If -a specified, clean up any old tags */ if (attic_too) - (void)rtag_delete (rcsfile); + rtag_delete (rcsfile); if (!quiet && !force_tag_match) { @@ -1043,7 +1053,7 @@ rtag_fileproc (void *callerdat, struct file_info *finfo) */ rev = branch_mode ? RCS_magicrev (rcsfile, version) : version; oversion = RCS_getversion (rcsfile, symtag, NULL, 1, NULL); - if (oversion != NULL) + if (oversion) { int isbranch = RCS_nodeisbranch (finfo->rcs, symtag); @@ -1085,18 +1095,15 @@ rtag_fileproc (void *callerdat, struct file_info *finfo) free (oversion); } retcode = RCS_settag (rcsfile, symtag, rev); - if (retcode == 0) + if (!retcode) RCS_rewrite (rcsfile, NULL, NULL); } - if (retcode != 0) - { + if (retcode) error (1, retcode == -1 ? errno : 0, - "failed to set tag `%s' to revision `%s' in `%s'", - symtag, rev, rcsfile->path); - retval = 1; - goto free_vars_and_return; - } + "failed to set tag %s to revision %s in %s", + quote_n (0, symtag), quote_n (1, rev), + quote_n (2, rcsfile->path)); free_vars_and_return: if (branch_mode && rev) free (rev); @@ -1401,6 +1408,7 @@ tag_dirproc (void *callerdat, const char *dir, const char *repos, if (!quiet) error (0, 0, "%s %s", delete_flag ? "Untagging" : "Tagging", NULL2DOT (update_dir)); + return R_PROCESS; }