2 * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
4 * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
7 * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8 * Portions Copyright (C) 1989-1992, Brian Berliner
10 * You may distribute under the terms of the GNU General Public License as
11 * specified in the README file that comes with the CVS source distribution.
15 * Add or delete a symbolic name to an RCS file, or a collection of RCS files.
16 * Tag uses the checked out revision in the current directory, rtag uses
17 * the modules database, if necessary.
25 static int rtag_proc PROTO((int argc, char **argv, char *xwhere,
26 char *mwhere, char *mfile, int shorten,
27 int local_specified, char *mname, char *msg));
28 static int check_fileproc PROTO ((void *callerdat, struct file_info *finfo));
29 static int check_filesdoneproc PROTO ((void *callerdat, int err,
31 const char *update_dir,
33 static int pretag_proc PROTO((const char *repository, const char *filter));
34 static void masterlist_delproc PROTO((Node *p));
35 static void tag_delproc PROTO((Node *p));
36 static int pretag_list_proc PROTO((Node *p, void *closure));
38 static Dtype tag_dirproc PROTO ((void *callerdat, const char *dir,
39 const char *repos, const char *update_dir,
41 static int rtag_fileproc PROTO ((void *callerdat, struct file_info *finfo));
42 static int rtag_delete PROTO((RCSNode *rcsfile));
43 static int tag_fileproc PROTO ((void *callerdat, struct file_info *finfo));
45 static char *numtag; /* specific revision to tag */
46 static int numtag_validated = 0;
47 static char *date = NULL;
48 static char *symtag; /* tag to add or delete */
49 static int delete_flag; /* adding a tag by default */
50 static int branch_mode; /* make an automagic "branch" tag */
51 static int disturb_branch_tags = 0; /* allow -F,-d to disturb branch tags */
52 static int force_tag_match = 1; /* force tag to match by default */
53 static int force_tag_move; /* don't force tag to move by default */
54 static int check_uptodate; /* no uptodate-check by default */
55 static int attic_too; /* remove tag from Attic files */
74 static const char rtag_opts[] = "+aBbdFflnQqRr:D:";
75 static const char *const rtag_usage[] =
77 "Usage: %s %s [-abdFflnR] [-r rev|-D date] tag modules...\n",
78 "\t-a\tClear tag from removed files that would not otherwise be tagged.\n",
79 "\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n",
80 "\t-B\tAllows -F and -d to disturb branch tags. Use with extreme care.\n",
81 "\t-d\tDelete the given tag.\n",
82 "\t-F\tMove tag if it already exists.\n",
83 "\t-f\tForce a head revision match if tag/date not found.\n",
84 "\t-l\tLocal directory only, not recursive.\n",
85 "\t-n\tNo execution of 'tag program'.\n",
86 "\t-R\tProcess directories recursively.\n",
87 "\t-r rev\tExisting revision/tag.\n",
88 "\t-D\tExisting date.\n",
89 "(Specify the --help global option for a list of other help options)\n",
93 static const char tag_opts[] = "+BbcdFflQqRr:D:";
94 static const char *const tag_usage[] =
96 "Usage: %s %s [-bcdFflR] [-r rev|-D date] tag [files...]\n",
97 "\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n",
98 "\t-B\tAllows -F and -d to disturb branch tags. Use with extreme care.\n",
99 "\t-c\tCheck that working files are unmodified.\n",
100 "\t-d\tDelete the given tag.\n",
101 "\t-F\tMove tag if it already exists.\n",
102 "\t-f\tForce a head revision match if tag/date not found.\n",
103 "\t-l\tLocal directory only, not recursive.\n",
104 "\t-R\tProcess directories recursively.\n",
105 "\t-r rev\tExisting revision/tag.\n",
106 "\t-D\tExisting date.\n",
107 "(Specify the --help global option for a list of other help options)\n",
116 int local = 0; /* recursive by default */
119 int run_module_prog = 1;
121 is_rtag = (strcmp (cvs_cmd_name, "rtag") == 0);
124 usage (is_rtag ? rtag_usage : tag_usage);
127 while ((c = getopt (argc, argv, is_rtag ? rtag_opts : tag_opts)) != -1)
138 disturb_branch_tags = 1;
160 /* The CVS 1.5 client sends these options (in addition to
161 Global_option requests), so we must ignore them. */
164 "-q or -Q must be specified before \"%s\"",
176 date = Make_Date (optarg);
180 usage (is_rtag ? rtag_usage : tag_usage);
187 if (argc < (is_rtag ? 2 : 1))
188 usage (is_rtag ? rtag_usage : tag_usage);
194 error (1, 0, "-r and -D options are mutually exclusive");
195 if (delete_flag && branch_mode)
196 error (0, 0, "warning: -b ignored with -d options");
197 RCS_check_tag (symtag);
199 #ifdef CLIENT_SUPPORT
200 if (current_parsed_root->isremote)
202 /* We're the client side. Fire up the remote server. */
211 if (disturb_branch_tags)
219 if (!force_tag_match)
223 if (!run_module_prog)
227 option_with_arg ("-r", numtag);
229 client_senddate (date);
238 for (i = 0; i < argc; ++i)
240 send_to_server ("rtag\012", 0);
244 send_files (argc, argv, local, 0,
246 /* I think the -c case is like "cvs status", in
247 which we really better be correct rather than
248 being fast; it is just too confusing otherwise. */
249 check_uptodate ? 0 : SEND_NO_CONTENTS);
250 send_file_names (argc, argv, SEND_EXPAND_WILD);
251 send_to_server ("tag\012", 0);
254 return get_responses_and_close ();
263 for (i = 0; i < argc; i++)
265 /* XXX last arg should be repository, but doesn't make sense here */
266 history_write ('T', (delete_flag ? "D" : (numtag ? numtag :
267 (date ? date : "A"))), symtag, argv[i], "");
268 err += do_module (db, argv[i], TAG,
269 delete_flag ? "Untagging" : "Tagging",
270 rtag_proc, (char *) NULL, 0, local, run_module_prog,
277 err = rtag_proc (argc + 1, argv - 1, NULL, NULL, NULL, 0, local, NULL,
285 * callback proc for doing the real work of tagging
289 rtag_proc (argc, argv, xwhere, mwhere, mfile, shorten, local_specified,
301 /* Begin section which is identical to patch_proc--should this
302 be abstracted out somehow? */
311 repository = xmalloc (strlen (current_parsed_root->directory) + strlen (argv[0])
312 + (mfile == NULL ? 0 : strlen (mfile) + 1) + 2);
313 (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
314 where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile) + 1)
316 (void) strcpy (where, argv[0]);
318 /* if mfile isn't null, we need to set up to do only part of the module */
324 /* if the portion of the module is a path, put the dir part on repos */
325 if ((cp = strrchr (mfile, '/')) != NULL)
328 (void) strcat (repository, "/");
329 (void) strcat (repository, mfile);
330 (void) strcat (where, "/");
331 (void) strcat (where, mfile);
335 /* take care of the rest */
336 path = xmalloc (strlen (repository) + strlen (mfile) + 5);
337 (void) sprintf (path, "%s/%s", repository, mfile);
340 /* directory means repository gets the dir tacked on */
341 (void) strcpy (repository, path);
342 (void) strcat (where, "/");
343 (void) strcat (where, mfile);
355 /* cd to the starting repository */
356 if ( CVS_CHDIR (repository) < 0)
358 error (0, errno, "cannot chdir to %s", repository);
363 /* End section which is identical to patch_proc. */
365 if (delete_flag || force_tag_move || attic_too || numtag)
366 which = W_REPOS | W_ATTIC;
377 if (numtag != NULL && !numtag_validated)
379 tag_check_valid (numtag, argc - 1, argv + 1, local_specified, 0, repository);
380 numtag_validated = 1;
383 /* check to make sure they are authorized to tag all the
384 specified files in the repository */
387 err = start_recursion (check_fileproc, check_filesdoneproc,
388 (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
389 argc - 1, argv + 1, local_specified, which, 0,
390 CVS_LOCK_READ, where, 1, repository);
394 error (1, 0, "correct the above errors first!");
397 /* It would be nice to provide consistency with respect to
398 commits; however CVS lacks the infrastructure to do that (see
399 Concurrency in cvs.texinfo and comment in do_recursion). */
401 /* start the recursion processor */
402 err = start_recursion (is_rtag ? rtag_fileproc : tag_fileproc,
403 (FILESDONEPROC) NULL, tag_dirproc,
404 (DIRLEAVEPROC) NULL, NULL, argc - 1, argv + 1,
405 local_specified, which, 0, CVS_LOCK_WRITE, where, 1,
407 if ( which & W_REPOS ) free ( repository );
414 /* check file that is to be tagged */
415 /* All we do here is add it to our list */
418 check_fileproc (callerdat, finfo)
420 struct file_info *finfo;
428 switch (Classify_File (finfo, (char *) NULL, (char *) NULL,
429 (char *) NULL, 1, 0, &vers, 0))
443 error (0, 0, "%s is locally modified", finfo->fullname);
449 vers = Version_TS (finfo, NULL, NULL, NULL, 0, 0);
451 if (finfo->update_dir[0] == '\0')
454 xdir = finfo->update_dir;
455 if ((p = findnode (mtlist, xdir)) != NULL)
457 tlist = ((struct master_lists *) p->data)->tlist;
461 struct master_lists *ml;
465 p->key = xstrdup (xdir);
467 ml = (struct master_lists *)
468 xmalloc (sizeof (struct master_lists));
471 p->delproc = masterlist_delproc;
472 (void) addnode (mtlist, p);
476 p->key = xstrdup (finfo->file);
478 p->delproc = tag_delproc;
479 if (vers->srcfile == NULL)
482 error (0, 0, "nothing known about %s", finfo->file);
488 /* Here we duplicate the calculation in tag_fileproc about which
489 version we are going to tag. There probably are some subtle races
490 (e.g. numtag is "foo" which gets moved between here and
492 if (!is_rtag && numtag == NULL && date == NULL)
493 p->data = xstrdup (vers->vn_user);
495 p->data = RCS_getversion (vers->srcfile, numtag, date,
496 force_tag_match, NULL);
503 oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1,
505 if (oversion == NULL)
509 /* Deleting a tag which did not exist is a noop and
510 should not be logged. */
514 else if (delete_flag)
517 p->data = xstrdup (oversion);
519 else if (strcmp(oversion, p->data) == 0)
523 else if (!force_tag_move)
527 if (oversion != NULL)
538 (void) addnode (tlist, p);
543 check_filesdoneproc (callerdat, err, repos, update_dir, entries)
547 const char *update_dir;
553 p = findnode(mtlist, update_dir);
556 tlist = ((struct master_lists *) p->data)->tlist;
560 tlist = (List *) NULL;
562 if ((tlist == NULL) || (tlist->list->next == tlist->list))
566 if ((n = Parse_Info(CVSROOTADM_TAGINFO, repos, pretag_proc, 1)) > 0)
568 error (0, 0, "Pre-tag check failed");
575 pretag_proc (repository, filter)
576 const char *repository;
579 if (filter[0] == '/')
584 for (cp=s; *cp; cp++)
586 if (isspace ((unsigned char) *cp))
594 error (0, errno, "cannot find pre-tag filter '%s'", s);
602 run_arg (delete_flag ? "del" : force_tag_move ? "mov" : "add");
603 run_arg (repository);
604 walklist(tlist, pretag_list_proc, NULL);
605 return (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL));
609 masterlist_delproc(p)
612 struct master_lists *ml = p->data;
632 pretag_list_proc(p, closure)
646 * Called to rtag a particular file, as appropriate with the options that were
651 rtag_fileproc (callerdat, finfo)
653 struct file_info *finfo;
659 /* find the parsed RCS data */
660 if ((rcsfile = finfo->rcs) == NULL)
664 * For tagging an RCS file which is a symbolic link, you'd best be
665 * running with RCS 5.6, since it knows how to handle symbolic links
666 * correctly without breaking your link!
670 return (rtag_delete (rcsfile));
673 * If we get here, we are adding a tag. But, if -a was specified, we
674 * need to check to see if a -r or -D option was specified. If neither
675 * was specified and the file is in the Attic, remove the tag.
677 if (attic_too && (!numtag && !date))
679 if ((rcsfile->flags & VALID) && (rcsfile->flags & INATTIC))
680 return (rtag_delete (rcsfile));
683 version = RCS_getversion (rcsfile, numtag, date, force_tag_match,
687 /* If -a specified, clean up any old tags */
689 (void) rtag_delete (rcsfile);
691 if (!quiet && !force_tag_match)
693 error (0, 0, "cannot find tag `%s' in `%s'",
694 numtag ? numtag : "head", rcsfile->path);
700 && isdigit ((unsigned char) *numtag)
701 && strcmp (numtag, version) != 0)
705 * We didn't find a match for the numeric tag that was specified, but
706 * that's OK. just pass the numeric tag on to rcs, to be tagged as
707 * specified. Could get here if one tried to tag "1.1.1" and there
708 * was a 1.1.1 branch with some head revision. In this case, we want
709 * the tag to reference "1.1.1" and not the revision at the head of
710 * the branch. Use a symbolic tag for that.
712 rev = branch_mode ? RCS_magicrev (rcsfile, version) : numtag;
713 retcode = RCS_settag(rcsfile, symtag, numtag);
715 RCS_rewrite (rcsfile, NULL, NULL);
722 * As an enhancement for the case where a tag is being re-applied to
723 * a large body of a module, make one extra call to RCS_getversion to
724 * see if the tag is already set in the RCS file. If so, check to
725 * see if it needs to be moved. If not, do nothing. This will
726 * likely save a lot of time when simply moving the tag to the
727 * "current" head revisions of a module -- which I have found to be a
728 * typical tagging operation.
730 rev = branch_mode ? RCS_magicrev (rcsfile, version) : version;
731 oversion = RCS_getversion (rcsfile, symtag, (char *) NULL, 1,
733 if (oversion != NULL)
735 int isbranch = RCS_nodeisbranch (finfo->rcs, symtag);
738 * if versions the same and neither old or new are branches don't
739 * have to do anything
741 if (strcmp (version, oversion) == 0 && !branch_mode && !isbranch)
750 /* we're NOT going to move the tag */
751 (void) printf ("W %s", finfo->fullname);
753 (void) printf (" : %s already exists on %s %s",
754 symtag, isbranch ? "branch" : "version",
756 (void) printf (" : NOT MOVING tag to %s %s\n",
757 branch_mode ? "branch" : "version", rev);
760 if (branch_mode) free(rev);
763 else /* force_tag_move is set and... */
764 if ((isbranch && !disturb_branch_tags) ||
765 (!isbranch && disturb_branch_tags))
767 error(0,0, "%s: Not moving %s tag `%s' from %s to %s%s.",
769 isbranch ? "branch" : "non-branch",
770 symtag, oversion, rev,
771 isbranch ? "" : " due to `-B' option");
772 if (branch_mode) free(rev);
779 retcode = RCS_settag(rcsfile, symtag, rev);
781 RCS_rewrite (rcsfile, NULL, NULL);
786 error (1, retcode == -1 ? errno : 0,
787 "failed to set tag `%s' to revision `%s' in `%s'",
788 symtag, rev, rcsfile->path);
801 * If -d is specified, "force_tag_match" is set, so that this call to
802 * RCS_getversion() will return a NULL version string if the symbolic
803 * tag does not exist in the RCS file.
805 * If the -r flag was used, numtag is set, and we only delete the
806 * symtag from files that have numtag.
808 * This is done here because it's MUCH faster than just blindly calling
809 * "rcs" to remove the tag... trust me.
812 rtag_delete (rcsfile)
816 int retcode, isbranch;
820 version = RCS_getversion (rcsfile, numtag, (char *) NULL, 1,
827 version = RCS_getversion (rcsfile, symtag, (char *) NULL, 1,
834 isbranch = RCS_nodeisbranch (rcsfile, symtag);
835 if ((isbranch && !disturb_branch_tags) ||
836 (!isbranch && disturb_branch_tags))
840 "Not removing %s tag `%s' from `%s'%s.",
841 isbranch ? "branch" : "non-branch",
842 symtag, rcsfile->path,
843 isbranch ? "" : " due to `-B' option");
847 if ((retcode = RCS_deltag(rcsfile, symtag)) != 0)
850 error (0, retcode == -1 ? errno : 0,
851 "failed to remove tag `%s' from `%s'", symtag,
855 RCS_rewrite (rcsfile, NULL, NULL);
861 * Called to tag a particular file (the currently checked out version is
862 * tagged with the specified tag - or the specified tag is deleted).
866 tag_fileproc (callerdat, finfo)
868 struct file_info *finfo;
870 char *version, *oversion;
871 char *nversion = NULL;
877 vers = Version_TS (finfo, NULL, NULL, NULL, 0, 0);
879 if ((numtag != NULL) || (date != NULL))
881 nversion = RCS_getversion(vers->srcfile,
886 if (nversion == NULL)
887 goto free_vars_and_return;
894 * If -d is specified, "force_tag_match" is set, so that this call to
895 * RCS_getversion() will return a NULL version string if the symbolic
896 * tag does not exist in the RCS file.
898 * This is done here because it's MUCH faster than just blindly calling
899 * "rcs" to remove the tag... trust me.
902 version = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1,
904 if (version == NULL || vers->srcfile == NULL)
905 goto free_vars_and_return;
909 isbranch = RCS_nodeisbranch (finfo->rcs, symtag);
910 if ((isbranch && !disturb_branch_tags) ||
911 (!isbranch && disturb_branch_tags))
915 "Not removing %s tag `%s' from `%s'%s.",
916 isbranch ? "branch" : "non-branch",
917 symtag, vers->srcfile->path,
918 isbranch ? "" : " due to `-B' option");
920 goto free_vars_and_return;
923 if ((retcode = RCS_deltag(vers->srcfile, symtag)) != 0)
926 error (0, retcode == -1 ? errno : 0,
927 "failed to remove tag %s from %s", symtag,
928 vers->srcfile->path);
930 goto free_vars_and_return;
932 RCS_rewrite (vers->srcfile, NULL, NULL);
937 cvs_output ("D ", 2);
938 cvs_output (finfo->fullname, 0);
939 cvs_output ("\n", 1);
942 goto free_vars_and_return;
946 * If we are adding a tag, we need to know which version we have checked
947 * out and we'll tag that version.
949 if (nversion == NULL)
951 version = vers->vn_user;
959 goto free_vars_and_return;
961 else if (strcmp (version, "0") == 0)
964 error (0, 0, "couldn't tag added but un-commited file `%s'", finfo->file);
965 goto free_vars_and_return;
967 else if (version[0] == '-')
970 error (0, 0, "skipping removed but un-commited file `%s'", finfo->file);
971 goto free_vars_and_return;
973 else if (vers->srcfile == NULL)
976 error (0, 0, "cannot find revision control file for `%s'", finfo->file);
977 goto free_vars_and_return;
981 * As an enhancement for the case where a tag is being re-applied to a
982 * large number of files, make one extra call to RCS_getversion to see
983 * if the tag is already set in the RCS file. If so, check to see if it
984 * needs to be moved. If not, do nothing. This will likely save a lot of
985 * time when simply moving the tag to the "current" head revisions of a
986 * module -- which I have found to be a typical tagging operation.
988 rev = branch_mode ? RCS_magicrev (vers->srcfile, version) : version;
989 oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1,
991 if (oversion != NULL)
993 int isbranch = RCS_nodeisbranch (finfo->rcs, symtag);
996 * if versions the same and neither old or new are branches don't have
999 if (strcmp (version, oversion) == 0 && !branch_mode && !isbranch)
1004 goto free_vars_and_return;
1007 if (!force_tag_move)
1009 /* we're NOT going to move the tag */
1010 cvs_output ("W ", 2);
1011 cvs_output (finfo->fullname, 0);
1012 cvs_output (" : ", 0);
1013 cvs_output (symtag, 0);
1014 cvs_output (" already exists on ", 0);
1015 cvs_output (isbranch ? "branch" : "version", 0);
1016 cvs_output (" ", 0);
1017 cvs_output (oversion, 0);
1018 cvs_output (" : NOT MOVING tag to ", 0);
1019 cvs_output (branch_mode ? "branch" : "version", 0);
1020 cvs_output (" ", 0);
1021 cvs_output (rev, 0);
1022 cvs_output ("\n", 1);
1026 goto free_vars_and_return;
1028 else /* force_tag_move == 1 and... */
1029 if ((isbranch && !disturb_branch_tags) ||
1030 (!isbranch && disturb_branch_tags))
1032 error(0,0, "%s: Not moving %s tag `%s' from %s to %s%s.",
1034 isbranch ? "branch" : "non-branch",
1035 symtag, oversion, rev,
1036 isbranch ? "" : " due to `-B' option");
1040 goto free_vars_and_return;
1045 if ((retcode = RCS_settag(vers->srcfile, symtag, rev)) != 0)
1047 error (1, retcode == -1 ? errno : 0,
1048 "failed to set tag %s to revision %s in %s",
1049 symtag, rev, vers->srcfile->path);
1053 goto free_vars_and_return;
1057 RCS_rewrite (vers->srcfile, NULL, NULL);
1059 /* more warm fuzzies */
1062 cvs_output ("T ", 2);
1063 cvs_output (finfo->fullname, 0);
1064 cvs_output ("\n", 1);
1067 free_vars_and_return:
1068 if (nversion != NULL)
1070 freevers_ts (&vers);
1075 * Print a warm fuzzy message
1079 tag_dirproc (callerdat, dir, repos, update_dir, entries)
1083 const char *update_dir;
1087 if (ignore_directory (update_dir))
1089 /* print the warm fuzzy message */
1091 error (0, 0, "Ignoring %s", update_dir);
1096 error (0, 0, "%s %s", delete_flag ? "Untagging" : "Tagging", update_dir);
1100 /* Code relating to the val-tags file. Note that this file has no way
1101 of knowing when a tag has been deleted. The problem is that there
1102 is no way of knowing whether a tag still exists somewhere, when we
1103 delete it some places. Using per-directory val-tags files (in
1104 CVSREP) might be better, but that might slow down the process of
1105 verifying that a tag is correct (maybe not, for the likely cases,
1106 if carefully done), and/or be harder to implement correctly. */
1113 static int val_fileproc PROTO ((void *callerdat, struct file_info *finfo));
1116 val_fileproc (callerdat, finfo)
1118 struct file_info *finfo;
1121 struct val_args *args = (struct val_args *)callerdat;
1124 if ((rcsdata = finfo->rcs) == NULL)
1125 /* Not sure this can happen, after all we passed only
1126 W_REPOS | W_ATTIC. */
1129 tag = RCS_gettag (rcsdata, args->name, 1, (int *) NULL);
1132 /* FIXME: should find out a way to stop the search at this point. */
1141 /* This routine determines whether a tag appears in CVSROOT/val-tags.
1143 * The val-tags file will be open read-only when IDB is NULL. Since writes to
1144 * val-tags always append to it, the lack of locking is okay. The worst case
1145 * race condition might misinterpret a partially written "foobar" matched, for
1146 * instance, a request for "f", "foo", of "foob". Such a mismatch would be
1147 * caught harmlessly later.
1149 * Before CVS adds a tag to val-tags, it will lock val-tags for write and
1150 * verify that the tag is still not present to avoid adding it twice.
1153 * This function expects its parent to handle any necessary locking of the
1157 * idb When this value is NULL, the val-tags file is opened in
1158 * in read-only mode. When present, the val-tags file is opened
1159 * in read-write mode and the DBM handle is stored in *IDB.
1160 * name The tag to search for.
1163 * *idb The val-tags file opened for read/write, or NULL if it couldn't
1167 * Exits with an error message if the val-tags file cannot be opened for
1168 * read (failure to open val-tags read/write is harmless - see below).
1171 * true 1. If NAME exists in val-tags.
1172 * 2. If IDB is non-NULL and val-tags cannot be opened for write.
1173 * This allows callers to ignore the harmless inability to
1174 * update the val-tags cache.
1175 * false If the file could be opened and the tag is not present.
1177 static int is_in_val_tags PROTO((DBM **idb, const char *name));
1179 is_in_val_tags (idb, name)
1184 char *valtags_filename;
1188 /* Casting out const should be safe here - input datums are not
1189 * written to by the myndbm functions.
1191 mytag.dptr = (char *)name;
1192 mytag.dsize = strlen (name);
1194 valtags_filename = xmalloc (strlen (current_parsed_root->directory)
1196 + sizeof CVSROOTADM_VALTAGS + 3);
1197 sprintf (valtags_filename, "%s/%s/%s", current_parsed_root->directory,
1198 CVSROOTADM, CVSROOTADM_VALTAGS);
1202 db = dbm_open (valtags_filename, O_RDWR, 0666);
1207 if (!existence_error (errno))
1209 error (0, errno, "warning: cannot open %s read/write",
1215 omask = umask (cvsumask);
1216 db = dbm_open (valtags_filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
1220 error (0, errno, "warning: cannot create %s",
1234 db = dbm_open (valtags_filename, O_RDONLY, 0444);
1235 if (!db && !existence_error (errno))
1236 error (1, errno, "cannot read %s", valtags_filename);
1239 /* If the file merely fails to exist, we just keep going and create
1240 it later if need be. */
1247 val = dbm_fetch (db, mytag);
1248 if (val.dptr != NULL)
1249 /* Found. The tag is valid. */
1252 /* FIXME: should check errors somehow (add dbm_error to myndbm.c?). */
1254 if (!idb) dbm_close (db);
1257 free (valtags_filename);
1263 /* Add a tag to the CVSROOT/val-tags cache. Establishes a write lock and
1264 * reverifies that the tag does not exist before adding it.
1266 static void add_to_val_tags PROTO((const char *name));
1268 add_to_val_tags (name)
1277 val_tags_lock (current_parsed_root->directory);
1279 /* Check for presence again since we have a lock now. */
1280 if (is_in_val_tags (&db, name))
1282 clear_val_tags_lock ();
1288 /* Casting out const should be safe here - input datums are not
1289 * written to by the myndbm functions.
1291 mytag.dptr = (char *)name;
1292 mytag.dsize = strlen (name);
1296 if (dbm_store (db, mytag, value, DBM_REPLACE) < 0)
1297 error (0, errno, "failed to store %s into val-tags", name);
1300 clear_val_tags_lock ();
1305 static Dtype val_direntproc PROTO ((void *, const char *, const char *,
1306 const char *, List *));
1309 val_direntproc (callerdat, dir, repository, update_dir, entries)
1312 const char *repository;
1313 const char *update_dir;
1316 /* This is not quite right--it doesn't get right the case of "cvs
1317 update -d -r foobar" where foobar is a tag which exists only in
1318 files in a directory which does not exist yet, but which is
1319 about to be created. */
1325 /* Check to see whether NAME is a valid tag. If so, return. If not
1326 print an error message and exit. ARGC, ARGV, LOCAL, and AFLAG specify
1327 which files we will be operating on.
1329 REPOSITORY is the repository if we need to cd into it, or NULL if
1330 we are already there, or "" if we should do a W_LOCAL recursion.
1331 Sorry for three cases, but the "" case is needed in case the
1332 working directories come from diverse parts of the repository, the
1333 NULL case avoids an unneccesary chdir, and the non-NULL, non-""
1334 case is needed for checkout, where we don't want to chdir if the
1335 tag is found in CVSROOTADM_VALTAGS, but there is not (yet) any
1338 tag_check_valid (name, argc, argv, local, aflag, repository)
1346 struct val_args the_val_args;
1347 struct saved_cwd cwd;
1350 /* Numeric tags require only a syntactic check. */
1351 if (isdigit ((unsigned char) name[0]))
1354 for (p = name; *p != '\0'; ++p)
1356 if (!(isdigit ((unsigned char) *p) || *p == '.'))
1358 Numeric tag %s contains characters other than digits and '.'", name);
1363 /* Special tags are always valid. */
1364 if (strcmp (name, TAG_BASE) == 0
1365 || strcmp (name, TAG_HEAD) == 0)
1371 /* Verify that the tag is valid syntactically. Some later code once made
1372 * assumptions about this.
1374 RCS_check_tag (name);
1376 if (is_in_val_tags (NULL, name)) return;
1378 /* We didn't find the tag in val-tags, so look through all the RCS files
1379 to see whether it exists there. Yes, this is expensive, but there
1380 is no other way to cope with a tag which might have been created
1381 by an old version of CVS, from before val-tags was invented.
1383 Since we need this code anyway, we also use it to create
1384 entries in val-tags in general (that is, the val-tags entry
1385 will get created the first time the tag is used, not when the
1388 the_val_args.name = name;
1389 the_val_args.found = 0;
1391 which = W_REPOS | W_ATTIC;
1393 if (repository != NULL)
1395 if (repository[0] == '\0')
1399 if (save_cwd (&cwd))
1401 if (CVS_CHDIR (repository) < 0)
1402 error (1, errno, "cannot change to %s directory", repository);
1406 start_recursion (val_fileproc, (FILESDONEPROC) NULL,
1407 val_direntproc, (DIRLEAVEPROC) NULL,
1408 (void *)&the_val_args,
1409 argc, argv, local, which, aflag,
1410 CVS_LOCK_READ, NULL, 1, repository);
1411 if (repository != NULL && repository[0] != '\0')
1413 if (restore_cwd (&cwd, NULL))
1418 if (!the_val_args.found)
1419 error (1, 0, "no such tag %s", name);
1421 /* The tags is valid but not mentioned in val-tags. Add it. */
1422 add_to_val_tags (name);
1428 * Check whether a join tag is valid. This is just like
1429 * tag_check_valid, but we must stop before the colon if there is one.
1433 tag_check_valid_join (join_tag, argc, argv, local, aflag, repository)
1443 c = xstrdup (join_tag);
1444 s = strchr (c, ':');
1447 if (isdigit ((unsigned char) join_tag[0]))
1449 "Numeric join tag %s may not contain a date specifier",
1453 /* hmmm... I think it makes sense to allow -j:<date>, but
1454 * for now this fixes a bug where CVS just spins and spins (I
1455 * think in the RCS code) looking for a zero length tag.
1459 "argument to join may not contain a date specifier without a tag");
1462 tag_check_valid (c, argc, argv, local, aflag, repository);