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 * "commit" commits the present version to the RCS repository, AFTER
16 * having done a test on conflicts.
18 * The call is: cvs commit [options] files...
30 static Dtype check_direntproc PROTO ((void *callerdat, const char *dir,
32 const char *update_dir,
34 static int check_fileproc PROTO ((void *callerdat, struct file_info *finfo));
35 static int check_filesdoneproc PROTO ((void *callerdat, int err,
37 const char *update_dir,
39 static int checkaddfile PROTO((const char *file, const char *repository,
40 const char *tag, const char *options,
42 static Dtype commit_direntproc PROTO ((void *callerdat, const char *dir,
44 const char *update_dir,
46 static int commit_dirleaveproc PROTO ((void *callerdat, const char *dir,
47 int err, const char *update_dir,
49 static int commit_fileproc PROTO ((void *callerdat, struct file_info *finfo));
50 static int commit_filesdoneproc PROTO ((void *callerdat, int err,
51 const char *repository,
52 const char *update_dir,
54 static int finaladd PROTO((struct file_info *finfo, char *revision, char *tag,
56 static int findmaxrev PROTO((Node * p, void *closure));
57 static int lock_RCS PROTO((const char *user, RCSNode *rcs, const char *rev,
58 const char *repository));
59 static int precommit_list_proc PROTO((Node * p, void *closure));
60 static int precommit_proc PROTO((const char *repository, const char *filter));
61 static int remove_file PROTO ((struct file_info *finfo, char *tag,
63 static void fixaddfile PROTO((const char *rcs));
64 static void fixbranch PROTO((RCSNode *, char *branch));
65 static void unlockrcs PROTO((RCSNode *rcs));
66 static void ci_delproc PROTO((Node *p));
67 static void masterlist_delproc PROTO((Node *p));
71 Ctype status; /* as returned from Classify_File() */
72 char *rev; /* a numeric rev, if we know it */
73 char *tag; /* any sticky tag, or -r option */
74 char *options; /* Any sticky -k option */
78 List *ulist; /* list for Update_Logfile */
79 List *cilist; /* list with commit_info structs */
82 static int force_ci = 0;
83 static int got_message;
85 static char *saved_tag;
86 static char *write_dirtag;
87 static int write_dirnonbranch;
90 static List *saved_ulist;
91 static char *saved_message;
92 static time_t last_register_time;
94 static const char *const commit_usage[] =
96 "Usage: %s %s [-Rlf] [-m msg | -F logfile] [-r rev] files...\n",
97 " -R Process directories recursively.\n",
98 " -l Local directory only (not recursive).\n",
99 " -f Force the file to be committed; disables recursion.\n",
100 " -F logfile Read the log message from file.\n",
101 " -m msg Log message.\n",
102 " -r rev Commit to this branch or trunk revision.\n",
103 "(Specify the --help global option for a list of other help options)\n",
107 #ifdef CLIENT_SUPPORT
108 /* Identify a file which needs "? foo" or a Questionable request. */
110 /* The two fields for the Directory request. */
117 struct question *next;
125 /* This is used from dirent to filesdone time, for each directory,
126 to make a list of files we have already seen. */
129 /* Linked list of files which need "? foo" or a Questionable request. */
130 struct question *questionables;
132 /* Only good within functions called from the filesdoneproc. Stores
133 the repository (pointer into storage managed by the recursion
135 const char *repository;
137 /* Non-zero if we should force the commit. This is enabled by
138 either -f or -r options, unlike force_ci which is just -f. */
144 static Dtype find_dirent_proc PROTO ((void *callerdat, const char *dir,
145 const char *repository,
146 const char *update_dir,
150 find_dirent_proc (callerdat, dir, repository, update_dir, entries)
153 const char *repository;
154 const char *update_dir;
157 struct find_data *find_data = (struct find_data *)callerdat;
159 /* This check seems to slowly be creeping throughout CVS (update
160 and send_dirent_proc by CVS 1.5, diff in 31 Oct 1995. My guess
161 is that it (or some variant thereof) should go in all the
162 dirent procs. Unless someone has some better idea... */
166 /* initialize the ignore list for this directory */
167 find_data->ignlist = getlist ();
169 /* Print the same warm fuzzy as in check_direntproc, since that
170 code will never be run during client/server operation and we
171 want the messages to match. */
173 error (0, 0, "Examining %s", update_dir);
180 /* Here as a static until we get around to fixing ignore_files to pass
181 it along as an argument. */
182 static struct find_data *find_data_static;
186 static void find_ignproc PROTO ((const char *, const char *));
189 find_ignproc (file, dir)
195 p = (struct question *) xmalloc (sizeof (struct question));
196 p->dir = xstrdup (dir);
197 p->repos = xstrdup (find_data_static->repository);
198 p->file = xstrdup (file);
199 p->next = find_data_static->questionables;
200 find_data_static->questionables = p;
205 static int find_filesdoneproc PROTO ((void *callerdat, int err,
206 const char *repository,
207 const char *update_dir,
211 find_filesdoneproc (callerdat, err, repository, update_dir, entries)
214 const char *repository;
215 const char *update_dir;
218 struct find_data *find_data = (struct find_data *)callerdat;
219 find_data->repository = repository;
221 /* if this directory has an ignore list, process it then free it */
222 if (find_data->ignlist)
224 find_data_static = find_data;
225 ignore_files (find_data->ignlist, entries, update_dir, find_ignproc);
226 dellist (&find_data->ignlist);
229 find_data->repository = NULL;
236 static int find_fileproc PROTO ((void *callerdat, struct file_info *finfo));
238 /* Machinery to find out what is modified, added, and removed. It is
239 possible this should be broken out into a new client_classify function;
240 merging it with classify_file is almost sure to be a mess, though,
241 because classify_file has all kinds of repository processing. */
243 find_fileproc (callerdat, finfo)
245 struct file_info *finfo;
248 enum classify_type status;
250 struct find_data *args = (struct find_data *)callerdat;
251 struct logfile_info *data;
252 struct file_info xfinfo;
254 /* if this directory has an ignore list, add this file to it */
261 p->key = xstrdup (finfo->file);
262 if (addnode (args->ignlist, p) != 0)
267 xfinfo.repository = NULL;
270 vers = Version_TS (&xfinfo, NULL, saved_tag, NULL, 0, 0);
271 if (vers->vn_user == NULL)
273 if (vers->ts_user == NULL)
274 error (0, 0, "nothing known about `%s'", finfo->fullname);
276 error (0, 0, "use `%s add' to create an entry for %s",
277 program_name, finfo->fullname);
281 if (vers->vn_user[0] == '-')
283 if (vers->ts_user != NULL)
286 "`%s' should be removed and is still there (or is back"
287 " again)", finfo->fullname);
294 else if (strcmp (vers->vn_user, "0") == 0)
296 if (vers->ts_user == NULL)
298 /* This happens when one has `cvs add'ed a file, but it no
299 longer exists in the working directory at commit time.
300 FIXME: What classify_file does in this case is print
301 "new-born %s has disappeared" and removes the entry.
302 We probably should do the same. */
304 error (0, 0, "warning: new-born %s has disappeared",
306 status = T_REMOVE_ENTRY;
311 else if (vers->ts_user == NULL)
313 /* FIXME: What classify_file does in this case is print
314 "%s was lost". We probably should do the same. */
318 else if (vers->ts_rcs != NULL
319 && (args->force || strcmp (vers->ts_user, vers->ts_rcs) != 0))
320 /* If we are forcing commits, pretend that the file is
325 /* This covers unmodified files, as well as a variety of other
326 cases. FIXME: we probably should be printing a message and
327 returning 1 for many of those cases (but I'm not sure
328 exactly which ones). */
334 node->key = xstrdup (finfo->fullname);
336 data = (struct logfile_info *) xmalloc (sizeof (struct logfile_info));
338 data->tag = xstrdup (vers->tag);
339 data->rev_old = data->rev_new = NULL;
342 node->delproc = update_delproc;
344 (void)addnode (args->ulist, node);
354 static int copy_ulist PROTO ((Node *, void *));
357 copy_ulist (node, data)
361 struct find_data *args = (struct find_data *)data;
362 args->argv[args->argc++] = node->key;
365 #endif /* CLIENT_SUPPORT */
367 #ifdef SERVER_SUPPORT
368 # define COMMIT_OPTIONS "+nlRm:fF:r:"
369 #else /* !SERVER_SUPPORT */
370 # define COMMIT_OPTIONS "+lRm:fF:r:"
371 #endif /* SERVER_SUPPORT */
382 usage (commit_usage);
386 * For log purposes, do not allow "root" to commit files. If you look
387 * like root, but are really logged in as a non-root user, it's OK.
389 /* FIXME: Shouldn't this check be much more closely related to the
390 readonly user stuff (CVSROOT/readers, &c). That is, why should
391 root be able to "cvs init", "cvs import", &c, but not "cvs ci"? */
392 /* Who we are on the client side doesn't affect logging. */
393 if (geteuid () == (uid_t) 0 && !current_parsed_root->isremote)
397 if ((pw = (struct passwd *) getpwnam (getcaller ())) == NULL)
399 "your apparent username (%s) is unknown to this system",
401 if (pw->pw_uid == (uid_t) 0)
402 error (1, 0, "'root' is not allowed to commit files");
404 #endif /* CVS_BADROOT */
407 while ((c = getopt (argc, argv, COMMIT_OPTIONS)) != -1)
411 #ifdef SERVER_SUPPORT
413 /* Silently ignore -n for compatibility with old
416 if (!server_active) error(0, 0, "the `-n' option is obsolete");
418 #endif /* SERVER_SUPPORT */
420 #ifdef FORCE_USE_EDITOR
427 free (saved_message);
428 saved_message = NULL;
431 saved_message = xstrdup(optarg);
436 saved_tag = xstrdup (optarg);
446 local = 1; /* also disable recursion */
449 #ifdef FORCE_USE_EDITOR
458 usage (commit_usage);
465 /* numeric specified revision means we ignore sticky tags... */
466 if (saved_tag && isdigit ((unsigned char) *saved_tag))
468 char *p = saved_tag + strlen (saved_tag);
470 /* strip trailing dots and leading zeros */
471 while (*--p == '.') ;
473 while (saved_tag[0] == '0' && isdigit ((unsigned char) saved_tag[1]))
477 /* some checks related to the "-F logfile" option */
480 size_t size = 0, len;
483 error (1, 0, "cannot specify both a message and a log file");
485 get_file (logfile, logfile, "r", &saved_message, &size, &len);
488 #ifdef CLIENT_SUPPORT
489 if (current_parsed_root->isremote)
491 struct find_data find_args;
495 find_args.ulist = getlist ();
497 find_args.questionables = NULL;
498 find_args.ignlist = NULL;
499 find_args.repository = NULL;
501 /* It is possible that only a numeric tag should set this.
502 I haven't really thought about it much.
503 Anyway, I suspect that setting it unnecessarily only causes
504 a little unneeded network traffic. */
505 find_args.force = force_ci || saved_tag != NULL;
507 err = start_recursion (find_fileproc, find_filesdoneproc,
508 find_dirent_proc, (DIRLEAVEPROC) NULL,
510 argc, argv, local, W_LOCAL, 0, CVS_LOCK_NONE,
511 (char *) NULL, 0, (char *) NULL);
513 error (1, 0, "correct above errors first!");
515 if (find_args.argc == 0)
517 /* Nothing to commit. Exit now without contacting the
518 server (note that this means that we won't print "?
519 foo" for files which merit it, because we don't know
520 what is in the CVSROOT/cvsignore file). */
521 dellist (&find_args.ulist);
525 /* Now we keep track of which files we actually are going to
526 operate on, and only work with those files in the future.
527 This saves time--we don't want to search the file system
528 of the working directory twice. */
529 if (size_overflow_p (xtimes (find_args.argc, sizeof (char **))))
534 find_args.argv = xmalloc (xtimes (find_args.argc, sizeof (char **)));
536 walklist (find_args.ulist, copy_ulist, &find_args);
538 /* Do this before calling do_editor; don't ask for a log
539 message if we can't talk to the server. But do it after we
540 have made the checks that we can locally (to more quickly
541 catch syntax errors, the case where no files are modified,
542 added or removed, etc.).
544 On the other hand, calling start_server before do_editor
545 means that we chew up server resources the whole time that
546 the user has the editor open (hours or days if the user
547 forgets about it), which seems dubious. */
551 * We do this once, not once for each directory as in normal CVS.
552 * The protocol is designed this way. This is a feature.
555 do_editor (".", &saved_message, (char *)NULL, find_args.ulist);
557 /* We always send some sort of message, even if empty. */
558 option_with_arg ("-m", saved_message ? saved_message : "");
560 /* OK, now process all the questionable files we have been saving
566 p = find_args.questionables;
569 if (ign_inhibit_server || !supported_request ("Questionable"))
571 cvs_output ("? ", 2);
572 if (p->dir[0] != '\0')
574 cvs_output (p->dir, 0);
577 cvs_output (p->file, 0);
578 cvs_output ("\n", 1);
582 send_to_server ("Directory ", 0);
583 send_to_server (p->dir[0] == '\0' ? "." : p->dir, 0);
584 send_to_server ("\012", 1);
585 send_to_server (p->repos, 0);
586 send_to_server ("\012", 1);
588 send_to_server ("Questionable ", 0);
589 send_to_server (p->file, 0);
590 send_to_server ("\012", 1);
605 option_with_arg ("-r", saved_tag);
608 /* FIXME: This whole find_args.force/SEND_FORCE business is a
609 kludge. It would seem to be a server bug that we have to
610 say that files are modified when they are not. This makes
611 "cvs commit -r 2" across a whole bunch of files a very slow
612 operation (and it isn't documented in cvsclient.texi). I
613 haven't looked at the server code carefully enough to be
614 _sure_ why this is needed, but if it is because the "ci"
615 program, which we used to call, wanted the file to exist,
616 then it would be relatively simple to fix in the server. */
617 send_files (find_args.argc, find_args.argv, local, 0,
618 find_args.force ? SEND_FORCE : 0);
620 /* Sending only the names of the files which were modified, added,
621 or removed means that the server will only do an up-to-date
622 check on those files. This is different from local CVS and
623 previous versions of client/server CVS, but it probably is a Good
624 Thing, or at least Not Such A Bad Thing. */
625 send_file_names (find_args.argc, find_args.argv, 0);
626 free (find_args.argv);
627 dellist (&find_args.ulist);
629 send_to_server ("ci\012", 0);
630 err = get_responses_and_close ();
631 if (err != 0 && use_editor && saved_message != NULL)
633 /* If there was an error, don't nuke the user's carefully
634 constructed prose. This is something of a kludge; a better
635 solution is probably more along the lines of #150 in TODO
636 (doing a second up-to-date check before accepting the
637 log message has also been suggested, but that seems kind of
638 iffy because the real up-to-date check could still fail,
639 another error could occur, &c. Also, a second check would
640 slow things down). */
645 fp = cvs_temp_file (&fname);
647 error (1, 0, "cannot create temporary file %s",
648 fname ? fname : "(null)");
649 if (fwrite (saved_message, 1, strlen (saved_message), fp)
650 != strlen (saved_message))
651 error (1, errno, "cannot write temporary file %s", fname);
653 error (0, errno, "cannot close temporary file %s", fname);
654 error (0, 0, "saving log message in %s", fname);
661 if (saved_tag != NULL)
662 tag_check_valid (saved_tag, argc, argv, local, aflag, "");
664 /* XXX - this is not the perfect check for this */
666 write_dirtag = saved_tag;
670 lock_tree_for_write (argc, argv, local, W_LOCAL, aflag);
673 * Set up the master update list and hard link list
677 #ifdef PRESERVE_PERMISSIONS_SUPPORT
680 hardlist = getlist ();
683 * We need to save the working directory so that
684 * check_fileproc can construct a full pathname for each file.
686 working_dir = xgetwd();
691 * Run the recursion processor to verify the files are all up-to-date
693 err = start_recursion (check_fileproc, check_filesdoneproc,
694 check_direntproc, (DIRLEAVEPROC) NULL, NULL, argc,
695 argv, local, W_LOCAL, aflag, CVS_LOCK_NONE,
696 (char *) NULL, 1, (char *) NULL);
700 error (1, 0, "correct above errors first!");
704 * Run the recursion processor to commit the files
706 write_dirnonbranch = 0;
708 err = start_recursion (commit_fileproc, commit_filesdoneproc,
709 commit_direntproc, commit_dirleaveproc, NULL,
710 argc, argv, local, W_LOCAL, aflag, CVS_LOCK_NONE,
711 (char *) NULL, 1, (char *) NULL);
714 * Unlock all the dirs and clean up
722 /* see if we need to sleep before returning to avoid time-stamp races */
723 if (last_register_time)
725 sleep_past (last_register_time);
733 /* This routine determines the status of a given file and retrieves
734 the version information that is associated with that file. */
738 classify_file_internal (finfo, vers)
739 struct file_info *finfo;
742 int save_noexec, save_quiet, save_really_quiet;
745 /* FIXME: Do we need to save quiet as well as really_quiet? Last
746 time I glanced at Classify_File I only saw it looking at really_quiet
748 save_noexec = noexec;
750 save_really_quiet = really_quiet;
751 noexec = quiet = really_quiet = 1;
753 /* handle specified numeric revision specially */
754 if (saved_tag && isdigit ((unsigned char) *saved_tag))
756 /* If the tag is for the trunk, make sure we're at the head */
757 if (numdots (saved_tag) < 2)
759 status = Classify_File (finfo, (char *) NULL, (char *) NULL,
760 (char *) NULL, 1, aflag, vers, 0);
761 if (status == T_UPTODATE || status == T_MODIFIED ||
767 xstatus = Classify_File (finfo, saved_tag, (char *) NULL,
768 (char *) NULL, 1, aflag, vers, 0);
769 if (xstatus == T_REMOVE_ENTRY)
771 else if (status == T_MODIFIED && xstatus == T_CONFLICT)
782 * The revision is off the main trunk; make sure we're
783 * up-to-date with the head of the specified branch.
785 xtag = xstrdup (saved_tag);
786 if ((numdots (xtag) & 1) != 0)
788 cp = strrchr (xtag, '.');
791 status = Classify_File (finfo, xtag, (char *) NULL,
792 (char *) NULL, 1, aflag, vers, 0);
793 if ((status == T_REMOVE_ENTRY || status == T_CONFLICT)
794 && (cp = strrchr (xtag, '.')) != NULL)
796 /* pluck one more dot off the revision */
799 status = Classify_File (finfo, xtag, (char *) NULL,
800 (char *) NULL, 1, aflag, vers, 0);
801 if (status == T_UPTODATE || status == T_REMOVE_ENTRY)
804 /* now, muck with vers to make the tag correct */
806 (*vers)->tag = xstrdup (saved_tag);
811 status = Classify_File (finfo, saved_tag, (char *) NULL, (char *) NULL,
813 noexec = save_noexec;
815 really_quiet = save_really_quiet;
823 * Check to see if a file is ok to commit and make sure all files are
828 check_fileproc (callerdat, finfo)
830 struct file_info *finfo;
835 List *ulist, *cilist;
837 struct commit_info *ci;
838 struct logfile_info *li;
840 size_t cvsroot_len = strlen (current_parsed_root->directory);
842 if (!finfo->repository)
844 error (0, 0, "nothing known about `%s'", finfo->fullname);
848 if (strncmp (finfo->repository, current_parsed_root->directory,
850 && ISDIRSEP (finfo->repository[cvsroot_len])
851 && strncmp (finfo->repository + cvsroot_len + 1,
853 sizeof (CVSROOTADM) - 1) == 0
854 && ISDIRSEP (finfo->repository[cvsroot_len + sizeof (CVSROOTADM)])
855 && strcmp (finfo->repository + cvsroot_len + sizeof (CVSROOTADM) + 1,
858 error (1, 0, "cannot check in to %s", finfo->repository);
860 status = classify_file_internal (finfo, &vers);
863 * If the force-commit option is enabled, and the file in question
864 * appears to be up-to-date, just make it look modified so that
865 * it will be committed.
867 if (force_ci && status == T_UPTODATE)
876 error (0, 0, "Up-to-date check failed for `%s'", finfo->fullname);
884 * some quick sanity checks; if no numeric -r option specified:
885 * - can't have a sticky date
886 * - can't have a sticky tag that is not a branch
888 * - if status is T_REMOVED, file must not exist and its entry
889 * can't have a numeric sticky tag.
890 * - if status is T_ADDED, rcs file must not exist unless on
891 * a branch or head is dead
892 * - if status is T_ADDED, can't have a non-trunk numeric rev
893 * - if status is T_MODIFIED and a Conflict marker exists, don't
894 * allow the commit if timestamp is identical or if we find
895 * an RCS_MERGE_PAT in the file.
897 if (!saved_tag || !isdigit ((unsigned char) *saved_tag))
902 "cannot commit with sticky date for file `%s'",
907 if (status == T_MODIFIED && vers->tag &&
908 !RCS_isbranch (finfo->rcs, vers->tag))
911 "sticky tag `%s' for file `%s' is not a branch",
912 vers->tag, finfo->fullname);
917 if (status == T_CONFLICT && !force_ci)
920 "file `%s' had a conflict and has not been modified",
925 if (status == T_MODIFIED && !force_ci && file_has_markers (finfo))
927 /* Make this a warning, not an error, because we have
928 no way of knowing whether the "conflict indicators"
929 are really from a conflict or whether they are part
930 of the document itself (cvs.texinfo and sanity.sh in
931 CVS itself, for example, tend to want to have strings
932 like ">>>>>>>" at the start of a line). Making people
933 kludge this the way they need to kludge keyword
934 expansion seems undesirable. And it is worse than
935 keyword expansion, because there is no -ko
939 warning: file `%s' seems to still contain conflict indicators",
943 if (status == T_REMOVED)
945 if (vers->ts_user != NULL)
948 "`%s' should be removed and is still there (or is"
949 " back again)", finfo->fullname);
954 if (vers->tag && isdigit ((unsigned char) *vers->tag))
956 /* Remove also tries to forbid this, but we should check
957 here. I'm only _sure_ about somewhat obscure cases
958 (hacking the Entries file, using an old version of
959 CVS for the remove and a new one for the commit), but
960 there might be other cases. */
962 "cannot remove file `%s' which has a numeric sticky"
963 " tag of `%s'", finfo->fullname, vers->tag);
968 if (status == T_ADDED)
970 if (vers->tag == NULL)
972 if (finfo->rcs != NULL &&
973 !RCS_isdead (finfo->rcs, finfo->rcs->head))
976 "cannot add file `%s' when RCS file `%s' already exists",
977 finfo->fullname, finfo->rcs->path);
982 else if (isdigit ((unsigned char) *vers->tag) &&
983 numdots (vers->tag) > 1)
986 "cannot add file `%s' with revision `%s'; must be on trunk",
987 finfo->fullname, vers->tag);
993 /* done with consistency checks; now, to get on with the commit */
994 if (finfo->update_dir[0] == '\0')
997 xdir = finfo->update_dir;
998 if ((p = findnode (mulist, xdir)) != NULL)
1000 ulist = ((struct master_lists *) p->data)->ulist;
1001 cilist = ((struct master_lists *) p->data)->cilist;
1005 struct master_lists *ml;
1008 cilist = getlist ();
1010 p->key = xstrdup (xdir);
1012 ml = (struct master_lists *)
1013 xmalloc (sizeof (struct master_lists));
1015 ml->cilist = cilist;
1017 p->delproc = masterlist_delproc;
1018 (void) addnode (mulist, p);
1021 /* first do ulist, then cilist */
1023 p->key = xstrdup (finfo->file);
1025 p->delproc = update_delproc;
1026 li = ((struct logfile_info *)
1027 xmalloc (sizeof (struct logfile_info)));
1029 li->tag = xstrdup (vers->tag);
1030 li->rev_old = xstrdup (vers->vn_rcs);
1033 (void) addnode (ulist, p);
1036 p->key = xstrdup (finfo->file);
1038 p->delproc = ci_delproc;
1039 ci = (struct commit_info *) xmalloc (sizeof (struct commit_info));
1040 ci->status = status;
1042 if (isdigit ((unsigned char) *vers->tag))
1043 ci->rev = xstrdup (vers->tag);
1045 ci->rev = RCS_whatbranch (finfo->rcs, vers->tag);
1047 ci->rev = (char *) NULL;
1048 ci->tag = xstrdup (vers->tag);
1049 ci->options = xstrdup(vers->options);
1051 (void) addnode (cilist, p);
1053 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1056 /* Add this file to hardlist, indexed on its inode. When
1057 we are done, we can find out what files are hardlinked
1058 to a given file by looking up its inode in hardlist. */
1061 struct hardlink_info *hlinfo;
1063 /* Get the full pathname of the current file. */
1064 fullpath = xmalloc (strlen(working_dir) +
1065 strlen(finfo->fullname) + 2);
1066 sprintf (fullpath, "%s/%s", working_dir, finfo->fullname);
1068 /* To permit following links in subdirectories, files
1069 are keyed on finfo->fullname, not on finfo->name. */
1070 linkp = lookup_file_by_inode (fullpath);
1072 /* If linkp is NULL, the file doesn't exist... maybe
1073 we're doing a remove operation? */
1076 /* Create a new hardlink_info node, which will record
1077 the current file's status and the links listed in its
1078 `hardlinks' delta field. We will append this
1079 hardlink_info node to the appropriate hardlist entry. */
1080 hlinfo = (struct hardlink_info *)
1081 xmalloc (sizeof (struct hardlink_info));
1082 hlinfo->status = status;
1083 linkp->data = hlinfo;
1090 error (0, 0, "nothing known about `%s'", finfo->fullname);
1091 freevers_ts (&vers);
1096 error (0, 0, "CVS internal error: unknown status %d", status);
1100 freevers_ts (&vers);
1107 * By default, return the code that tells do_recursion to examine all
1112 check_direntproc (callerdat, dir, repos, update_dir, entries)
1116 const char *update_dir;
1123 error (0, 0, "Examining %s", update_dir);
1131 * Walklist proc to run pre-commit checks
1134 precommit_list_proc (p, closure)
1138 struct logfile_info *li = p->data;
1139 if (li->type == T_ADDED
1140 || li->type == T_MODIFIED
1141 || li->type == T_REMOVED)
1151 * Callback proc for pre-commit checking
1154 precommit_proc (repository, filter)
1155 const char *repository;
1158 /* see if the filter is there, only if it's a full path */
1159 if (isabsolute (filter))
1163 s = xstrdup (filter);
1164 for (cp = s; *cp; cp++)
1165 if (isspace ((unsigned char) *cp))
1172 error (0, errno, "cannot find pre-commit filter `%s'", s);
1174 return 1; /* so it fails! */
1180 run_arg (repository);
1181 (void) walklist (saved_ulist, precommit_list_proc, NULL);
1182 return run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY);
1188 * Run the pre-commit checks for the dir
1192 check_filesdoneproc (callerdat, err, repos, update_dir, entries)
1196 const char *update_dir;
1202 /* find the update list for this dir */
1203 p = findnode (mulist, update_dir);
1205 saved_ulist = ((struct master_lists *) p->data)->ulist;
1207 saved_ulist = (List *) NULL;
1209 /* skip the checks if there's nothing to do */
1210 if (saved_ulist == NULL || saved_ulist->list->next == saved_ulist->list)
1213 /* run any pre-commit checks */
1214 if ((n = Parse_Info (CVSROOTADM_COMMITINFO, repos, precommit_proc, 1)) > 0)
1216 error (0, 0, "Pre-commit check failed");
1226 * Do the work of committing a file
1229 static char *sbranch;
1233 commit_fileproc (callerdat, finfo)
1235 struct file_info *finfo;
1239 List *ulist, *cilist;
1240 struct commit_info *ci;
1242 /* Keep track of whether write_dirtag is a branch tag.
1243 Note that if it is a branch tag in some files and a nonbranch tag
1244 in others, treat it as a nonbranch tag. It is possible that case
1245 should elicit a warning or an error. */
1246 if (write_dirtag != NULL
1247 && finfo->rcs != NULL)
1249 char *rev = RCS_getversion (finfo->rcs, write_dirtag, NULL, 1, NULL);
1251 && !RCS_nodeisbranch (finfo->rcs, write_dirtag))
1252 write_dirnonbranch = 1;
1257 if (finfo->update_dir[0] == '\0')
1258 p = findnode (mulist, ".");
1260 p = findnode (mulist, finfo->update_dir);
1263 * if p is null, there were file type command line args which were
1264 * all up-to-date so nothing really needs to be done
1268 ulist = ((struct master_lists *) p->data)->ulist;
1269 cilist = ((struct master_lists *) p->data)->cilist;
1272 * At this point, we should have the commit message unless we were called
1273 * with files as args from the command line. In that latter case, we
1274 * need to get the commit message ourselves
1279 if (!server_active && use_editor)
1280 do_editor (finfo->update_dir, &saved_message,
1281 finfo->repository, ulist);
1282 do_verify (&saved_message, finfo->repository);
1285 p = findnode (cilist, finfo->file);
1290 if (ci->status == T_MODIFIED)
1292 if (finfo->rcs == NULL)
1293 error (1, 0, "internal error: no parsed RCS file");
1294 if (lock_RCS (finfo->file, finfo->rcs, ci->rev,
1295 finfo->repository) != 0)
1297 unlockrcs (finfo->rcs);
1302 else if (ci->status == T_ADDED)
1304 if (checkaddfile (finfo->file, finfo->repository, ci->tag, ci->options,
1307 if (finfo->rcs != NULL)
1308 fixaddfile (finfo->rcs->path);
1313 /* adding files with a tag, now means adding them on a branch.
1314 Since the branch test was done in check_fileproc for
1315 modified files, we need to stub it in again here. */
1319 /* If numeric, it is on the trunk; check_fileproc enforced
1321 && !isdigit ((unsigned char) ci->tag[0]))
1323 if (finfo->rcs == NULL)
1324 error (1, 0, "internal error: no parsed RCS file");
1327 ci->rev = RCS_whatbranch (finfo->rcs, ci->tag);
1328 err = Checkin ('A', finfo, ci->rev,
1329 ci->tag, ci->options, saved_message);
1332 unlockrcs (finfo->rcs);
1333 fixbranch (finfo->rcs, sbranch);
1336 (void) time (&last_register_time);
1338 ci->status = T_UPTODATE;
1343 * Add the file for real
1345 if (ci->status == T_ADDED)
1347 char *xrev = (char *) NULL;
1349 if (ci->rev == NULL)
1351 /* find the max major rev number in this directory */
1353 (void) walklist (finfo->entries, findmaxrev, NULL);
1354 if (finfo->rcs->head) {
1355 /* resurrecting: include dead revision */
1356 int thisrev = atoi (finfo->rcs->head);
1357 if (thisrev > maxrev)
1362 xrev = xmalloc (20);
1363 (void) sprintf (xrev, "%d", maxrev);
1366 /* XXX - an added file with symbolic -r should add tag as well */
1367 err = finaladd (finfo, ci->rev ? ci->rev : xrev, ci->tag, ci->options);
1371 else if (ci->status == T_MODIFIED)
1373 err = Checkin ('M', finfo, ci->rev, ci->tag,
1374 ci->options, saved_message);
1376 (void) time (&last_register_time);
1380 unlockrcs (finfo->rcs);
1381 fixbranch (finfo->rcs, sbranch);
1384 else if (ci->status == T_REMOVED)
1386 err = remove_file (finfo, ci->tag, saved_message);
1387 #ifdef SERVER_SUPPORT
1388 if (server_active) {
1389 server_scratch_entry_only ();
1390 server_updated (finfo,
1393 /* Doesn't matter, it won't get checked. */
1397 (unsigned char *) NULL,
1398 (struct buffer *) NULL);
1403 /* Clearly this is right for T_MODIFIED. I haven't thought so much
1404 about T_ADDED or T_REMOVED. */
1405 notify_do ('C', finfo->file, getcaller (), NULL, NULL, finfo->repository);
1410 /* on failure, remove the file from ulist */
1411 p = findnode (ulist, finfo->file);
1417 /* On success, retrieve the new version number of the file and
1418 copy it into the log information (see logmsg.c
1419 (logfile_write) for more details). We should only update
1420 the version number for files that have been added or
1421 modified but not removed since classify_file_internal
1422 will return the version number of a file even after it has
1423 been removed from the archive, which is not the behavior we
1424 want for our commitlog messages; we want the old version
1425 number and then "NONE." */
1427 if (ci->status != T_REMOVED)
1429 p = findnode (ulist, finfo->file);
1433 struct logfile_info *li;
1435 (void) classify_file_internal (finfo, &vers);
1437 li->rev_new = xstrdup (vers->vn_rcs);
1438 freevers_ts (&vers);
1442 if (SIG_inCrSect ())
1451 * Log the commit and clean up the update list
1455 commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
1458 const char *repository;
1459 const char *update_dir;
1465 assert (repository);
1467 p = findnode (mulist, update_dir);
1471 ulist = ((struct master_lists *) p->data)->ulist;
1475 Update_Logfile (repository, saved_message, (FILE *) 0, ulist);
1477 /* Build the administrative files if necessary. */
1481 if (strncmp (current_parsed_root->directory, repository,
1482 strlen (current_parsed_root->directory)) != 0)
1484 "internal error: repository (%s) doesn't begin with root (%s)",
1485 repository, current_parsed_root->directory);
1486 p = repository + strlen (current_parsed_root->directory);
1489 if (strcmp ("CVSROOT", p) == 0
1490 /* Check for subdirectories because people may want to create
1491 subdirectories and list files therein in checkoutlist. */
1492 || strncmp ("CVSROOT/", p, strlen ("CVSROOT/")) == 0
1495 /* "Database" might a little bit grandiose and/or vague,
1496 but "checked-out copies of administrative files, unless
1497 in the case of modules and you are using ndbm in which
1498 case modules.{pag,dir,db}" is verbose and excessively
1499 focused on how the database is implemented. */
1501 /* mkmodules requires the absolute name of the CVSROOT directory.
1502 Remove anything after the `CVSROOT' component -- this is
1503 necessary when committing in a subdirectory of CVSROOT. */
1504 char *admin_dir = xstrdup (repository);
1505 int cvsrootlen = strlen ("CVSROOT");
1506 assert (admin_dir[p - repository + cvsrootlen] == '\0'
1507 || admin_dir[p - repository + cvsrootlen] == '/');
1508 admin_dir[p - repository + cvsrootlen] = '\0';
1510 cvs_output (program_name, 0);
1511 cvs_output (" ", 1);
1512 cvs_output (cvs_cmd_name, 0);
1513 cvs_output (": Rebuilding administrative file database\n", 0);
1514 mkmodules (admin_dir);
1525 * Get the log message for a dir
1529 commit_direntproc (callerdat, dir, repos, update_dir, entries)
1533 const char *update_dir;
1543 /* find the update list for this dir */
1544 p = findnode (mulist, update_dir);
1546 ulist = ((struct master_lists *) p->data)->ulist;
1548 ulist = (List *) NULL;
1550 /* skip the files as an optimization */
1551 if (ulist == NULL || ulist->list->next == ulist->list)
1552 return R_SKIP_FILES;
1554 /* get commit message */
1555 real_repos = Name_Repository (dir, update_dir);
1557 if (!server_active && use_editor)
1558 do_editor (update_dir, &saved_message, real_repos, ulist);
1559 do_verify (&saved_message, real_repos);
1567 * Process the post-commit proc if necessary
1571 commit_dirleaveproc (callerdat, dir, err, update_dir, entries)
1575 const char *update_dir;
1578 /* update the per-directory tag info */
1579 /* FIXME? Why? The "commit examples" node of cvs.texinfo briefly
1580 mentions commit -r being sticky, but apparently in the context of
1581 this being a confusing feature! */
1582 if (err == 0 && write_dirtag != NULL)
1584 char *repos = Name_Repository (NULL, update_dir);
1585 WriteTag (NULL, write_dirtag, NULL, write_dirnonbranch,
1596 * find the maximum major rev number in an entries file
1599 findmaxrev (p, closure)
1604 Entnode *entdata = p->data;
1606 if (entdata->type != ENT_FILE)
1608 thisrev = atoi (entdata->version);
1609 if (thisrev > maxrev)
1615 * Actually remove a file by moving it to the attic
1616 * XXX - if removing a ,v file that is a relative symbolic link to
1617 * another ,v file, we probably should add a ".." component to the
1618 * link to keep it relative after we move it into the attic.
1620 Return value is 0 on success, or >0 on error (in which case we have
1621 printed an error message). */
1623 remove_file (finfo, tag, message)
1624 struct file_info *finfo;
1643 if (finfo->rcs == NULL)
1644 error (1, 0, "internal error: no parsed RCS file");
1647 if (tag && !(branch = RCS_nodeisbranch (finfo->rcs, tag)))
1649 /* a symbolic tag is specified; just remove the tag from the file */
1650 if ((retcode = RCS_deltag (finfo->rcs, tag)) != 0)
1653 error (0, retcode == -1 ? errno : 0,
1654 "failed to remove tag `%s' from `%s'", tag,
1658 RCS_rewrite (finfo->rcs, NULL, NULL);
1659 Scratch_Entry (finfo->entries, finfo->file);
1663 /* we are removing the file from either the head or a branch */
1664 /* commit a new, dead revision. */
1666 /* Print message indicating that file is going to be removed. */
1667 cvs_output ("Removing ", 0);
1668 cvs_output (finfo->fullname, 0);
1669 cvs_output (";\n", 0);
1677 rev = RCS_whatbranch (finfo->rcs, tag);
1680 error (0, 0, "cannot find branch \"%s\".", tag);
1684 branchname = RCS_getbranch (finfo->rcs, rev, 1);
1685 if (branchname == NULL)
1687 /* no revision exists on this branch. use the previous
1688 revision but do not lock. */
1689 corev = RCS_gettag (finfo->rcs, tag, 1, (int *) NULL);
1690 prev_rev = xstrdup (corev);
1694 corev = xstrdup (rev);
1695 prev_rev = xstrdup (branchname);
1699 } else /* Not a branch */
1701 /* Get current head revision of file. */
1702 prev_rev = RCS_head (finfo->rcs);
1705 /* if removing without a tag or a branch, then make sure the default
1706 branch is the trunk. */
1707 if (!tag && !branch)
1709 if (RCS_setbranch (finfo->rcs, NULL) != 0)
1711 error (0, 0, "cannot change branch to default for %s",
1715 RCS_rewrite (finfo->rcs, NULL, NULL);
1718 /* check something out. Generally this is the head. If we have a
1719 particular rev, then name it. */
1720 retcode = RCS_checkout (finfo->rcs, finfo->file, rev ? corev : NULL,
1721 (char *) NULL, (char *) NULL, RUN_TTY,
1722 (RCSCHECKOUTPROC) NULL, (void *) NULL);
1726 "failed to check out `%s'", finfo->fullname);
1730 /* Except when we are creating a branch, lock the revision so that
1731 we can check in the new revision. */
1734 if (RCS_lock (finfo->rcs, rev ? corev : NULL, 1) == 0)
1735 RCS_rewrite (finfo->rcs, NULL, NULL);
1741 retcode = RCS_checkin (finfo->rcs, finfo->file, message, rev, 0,
1742 RCS_FLAGS_DEAD | RCS_FLAGS_QUIET);
1746 error (0, retcode == -1 ? errno : 0,
1747 "failed to commit dead revision for `%s'", finfo->fullname);
1748 if (prev_rev != NULL)
1752 /* At this point, the file has been committed as removed. We should
1753 probably tell the history file about it */
1754 corev = rev ? RCS_getbranch (finfo->rcs, rev, 1) : RCS_head (finfo->rcs);
1755 history_write ('R', NULL, corev, finfo->file, finfo->repository);
1761 old_path = xstrdup (finfo->rcs->path);
1763 RCS_setattic (finfo->rcs, 1);
1765 /* Print message that file was removed. */
1766 cvs_output (old_path, 0);
1767 cvs_output (" <-- ", 0);
1768 cvs_output (finfo->file, 0);
1769 cvs_output ("\nnew revision: delete; previous revision: ", 0);
1770 cvs_output (prev_rev, 0);
1771 cvs_output ("\ndone\n", 0);
1776 Scratch_Entry (finfo->entries, finfo->file);
1783 * Do the actual checkin for added files
1786 finaladd (finfo, rev, tag, options)
1787 struct file_info *finfo;
1794 ret = Checkin ('A', finfo, rev, tag, options, saved_message);
1797 char *tmp = xmalloc (strlen (finfo->file) + sizeof (CVSADM)
1798 + sizeof (CVSEXT_LOG) + 10);
1799 (void) sprintf (tmp, "%s/%s%s", CVSADM, finfo->file, CVSEXT_LOG);
1800 if (unlink_file (tmp) < 0
1801 && !existence_error (errno))
1802 error (0, errno, "cannot remove %s", tmp);
1805 else if (finfo->rcs != NULL)
1806 fixaddfile (finfo->rcs->path);
1808 (void) time (&last_register_time);
1816 * Unlock an rcs file
1824 if ((retcode = RCS_unlock (rcs, NULL, 1)) != 0)
1825 error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
1826 "could not unlock %s", rcs->path);
1828 RCS_rewrite (rcs, NULL, NULL);
1834 * remove a partially added file. if we can parse it, leave it alone.
1836 * FIXME: Every caller that calls this function can access finfo->rcs (the
1837 * parsed RCSNode data), so we should be able to detect that the file needs
1838 * to be removed without reparsing the file as we do below.
1845 int save_really_quiet;
1847 save_really_quiet = really_quiet;
1849 if ((rcsfile = RCS_parsercsfile (rcs)) == NULL)
1851 if (unlink_file (rcs) < 0)
1852 error (0, errno, "cannot remove %s", rcs);
1855 freercsnode (&rcsfile);
1856 really_quiet = save_really_quiet;
1862 * put the branch back on an rcs file
1865 fixbranch (rcs, branch)
1873 if ((retcode = RCS_setbranch (rcs, branch)) != 0)
1874 error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
1875 "cannot restore branch to %s for %s", branch, rcs->path);
1876 RCS_rewrite (rcs, NULL, NULL);
1883 * do the initial part of a file add for the named file. if adding
1884 * with a tag, put the file in the Attic and point the symbolic tag
1885 * at the committed revision.
1888 * file The name of the file in the workspace.
1889 * repository The repository directory to expect to find FILE,v in.
1890 * tag The name or rev num of the branch being added to, if any.
1891 * options Any RCS keyword expansion options specified by the user.
1892 * rcsnode A pointer to the pre-parsed RCSNode for this file, if the file
1893 * exists in the repository. If this is NULL, assume the file
1894 * does not yet exist.
1898 * 1 on errors, after printing any appropriate error messages.
1901 * This function will return an error when any of the following functions do:
1906 * RCS_parse (called to verify the newly created archive file)
1911 checkaddfile (file, repository, tag, options, rcsnode)
1913 const char *repository;
1915 const char *options;
1920 int newfile = 0; /* Set to 1 if we created a new RCS archive. */
1922 int adding_on_branch;
1924 assert (rcsnode != NULL);
1926 /* Callers expect to be able to use either "" or NULL to mean the
1927 default keyword expansion. */
1928 if (options != NULL && options[0] == '\0')
1930 if (options != NULL)
1931 assert (options[0] == '-' && options[1] == 'k');
1933 /* If numeric, it is on the trunk; check_fileproc enforced
1935 adding_on_branch = tag != NULL && !isdigit ((unsigned char) tag[0]);
1937 if (*rcsnode == NULL)
1941 size_t descalloc = 0;
1945 if ( adding_on_branch )
1948 rcsname = xmalloc (strlen (repository)
1953 (void) sprintf (rcsname, "%s/%s", repository, CVSATTIC);
1954 omask = umask ( cvsumask );
1955 if (CVS_MKDIR (rcsname, 0777 ) != 0 && errno != EEXIST)
1956 error (1, errno, "cannot make directory `%s'", rcsname);
1957 (void) umask ( omask );
1958 (void) sprintf (rcsname,
1967 rcsname = xmalloc (strlen (repository)
1971 (void) sprintf (rcsname,
1978 /* this is the first time we have ever seen this file; create
1980 fname = xmalloc (strlen (file) + sizeof (CVSADM)
1981 + sizeof (CVSEXT_LOG) + 10);
1982 (void) sprintf (fname, "%s/%s%s", CVSADM, file, CVSEXT_LOG);
1983 /* If the file does not exist, no big deal. In particular, the
1984 server does not (yet at least) create CVSEXT_LOG files. */
1986 /* FIXME: Should be including update_dir in the appropriate
1988 get_file (fname, fname, "r", &desc, &descalloc, &desclen);
1991 /* From reading the RCS 5.7 source, "rcs -i" adds a newline to the
1992 end of the log message if the message is nonempty.
1993 Do it. RCS also deletes certain whitespace, in cleanlogmsg,
1994 which we don't try to do here. */
1997 expand_string (&desc, &descalloc, desclen + 1);
1998 desc[desclen++] = '\012';
2001 /* Set RCS keyword expansion options. */
2002 if (options != NULL)
2007 /* This message is an artifact of the time when this
2008 was implemented via "rcs -i". It should be revised at
2009 some point (does the "initial revision" in the message from
2010 RCS_checkin indicate that this is a new file? Or does the
2011 "RCS file" message serve some function?). */
2012 cvs_output ("RCS file: ", 0);
2013 cvs_output (rcsname, 0);
2014 cvs_output ("\ndone\n", 0);
2016 if (add_rcs_file (NULL, rcsname, file, NULL, opt,
2017 NULL, NULL, 0, NULL,
2018 desc, desclen, NULL) != 0)
2020 if (rcsname != NULL)
2024 rcs = RCS_parsercsfile (rcsname);
2026 if (rcsname != NULL)
2034 /* file has existed in the past. Prepare to resurrect. */
2040 oldexpand = RCS_getexpand (rcs);
2041 if ((oldexpand != NULL
2043 && strcmp (options + 2, oldexpand) != 0)
2044 || (oldexpand == NULL && options != NULL))
2046 /* We tell the user about this, because it means that the
2047 old revisions will no longer retrieve the way that they
2049 error (0, 0, "changing keyword expansion mode to %s", options);
2050 RCS_setexpand (rcs, options + 2);
2053 if (!adding_on_branch)
2055 /* We are adding on the trunk, so move the file out of the
2057 if (!(rcs->flags & INATTIC))
2059 error (0, 0, "warning: expected %s to be in Attic",
2063 /* Begin a critical section around the code that spans the
2064 first commit on the trunk of a file that's already been
2065 committed on a branch. */
2068 if (RCS_setattic (rcs, 0))
2074 rev = RCS_getversion (rcs, tag, NULL, 1, (int *) NULL);
2076 if (lock_RCS (file, rcs, rev, repository))
2078 error (0, 0, "cannot lock revision %s in `%s'.",
2079 rev ? rev : tag ? tag : "HEAD", rcs->path);
2089 /* when adding a file for the first time, and using a tag, we need
2090 to create a dead revision on the trunk. */
2091 if (adding_on_branch)
2099 /* move the new file out of the way. */
2100 fname = xmalloc (strlen (file) + sizeof (CVSADM)
2101 + sizeof (CVSPREFIX) + 10);
2102 (void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
2103 rename_file (file, fname);
2105 /* Create empty FILE. Can't use copy_file with a DEVNULL
2106 argument -- copy_file now ignores device files. */
2107 fp = fopen (file, "w");
2109 error (1, errno, "cannot open %s for writing", file);
2110 if (fclose (fp) < 0)
2111 error (0, errno, "cannot close %s", file);
2113 tmp = xmalloc (strlen (file) + strlen (tag) + 80);
2114 /* commit a dead revision. */
2115 (void) sprintf (tmp, "file %s was initially added on branch %s.",
2117 retcode = RCS_checkin (rcs, NULL, tmp, NULL, 0,
2118 RCS_FLAGS_DEAD | RCS_FLAGS_QUIET);
2122 error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
2123 "could not create initial dead revision %s", rcs->path);
2128 /* put the new file back where it was */
2129 rename_file (fname, file);
2132 /* double-check that the file was written correctly */
2134 rcs = RCS_parse (file, repository);
2137 error (0, 0, "could not read %s in %s", file, repository);
2142 /* and lock it once again. */
2143 if (lock_RCS (file, rcs, NULL, repository))
2145 error (0, 0, "cannot lock initial revision in `%s'.",
2151 /* when adding with a tag, we need to stub a branch, if it
2152 doesn't already exist. */
2153 if (!RCS_nodeisbranch (rcs, tag))
2155 /* branch does not exist. Stub it. */
2159 time_t headtime = -1;
2165 fixbranch (rcs, sbranch);
2167 head = RCS_getversion (rcs, NULL, NULL, 0, (int *) NULL);
2169 error (1, 0, "No head revision in archive file `%s'.",
2171 magicrev = RCS_magicrev (rcs, head);
2173 /* If this is not a new branch, then we will want a dead
2174 version created before this one. */
2176 headtime = RCS_getrevtime (rcs, head, 0, 0);
2178 retcode = RCS_settag (rcs, tag, magicrev);
2179 RCS_rewrite (rcs, NULL, NULL);
2186 error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
2187 "could not stub branch %s for %s", tag, rcs->path);
2190 /* We need to add a dead version here to avoid -rtag -Dtime
2191 checkout problems between when the head version was
2193 if (!newfile && headtime != -1)
2195 /* move the new file out of the way. */
2196 fname = xmalloc (strlen (file) + sizeof (CVSADM)
2197 + sizeof (CVSPREFIX) + 10);
2198 (void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
2199 rename_file (file, fname);
2201 /* Create empty FILE. Can't use copy_file with a DEVNULL
2202 argument -- copy_file now ignores device files. */
2203 fp = fopen (file, "w");
2205 error (1, errno, "cannot open %s for writing", file);
2206 if (fclose (fp) < 0)
2207 error (0, errno, "cannot close %s", file);
2209 /* As we will be hacking the delta date, put the time
2210 this was added into the log message. */
2213 tmp = xmalloc (strlen (file) + strlen (tag) + 80);
2215 (void) sprintf (tmp,
2216 "file %s was added on branch %s on %d-%02d-%02d %02d:%02d:%02d +0000",
2218 ct->tm_year + (ct->tm_year < 100 ? 0 : 1900),
2219 ct->tm_mon + 1, ct->tm_mday,
2220 ct->tm_hour, ct->tm_min, ct->tm_sec);
2222 /* commit a dead revision. */
2223 revnum = RCS_whatbranch (rcs, tag);
2224 retcode = RCS_checkin (rcs, NULL, tmp, revnum, headtime,
2233 error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
2234 "could not created dead stub %s for %s", tag,
2239 /* put the new file back where it was */
2240 rename_file (fname, file);
2243 /* double-check that the file was written correctly */
2245 rcs = RCS_parse (file, repository);
2248 error (0, 0, "could not read %s", rcs->path);
2256 /* lock the branch. (stubbed branches need not be locked.) */
2257 if (lock_RCS (file, rcs, NULL, repository))
2259 error (0, 0, "cannot lock head revision in `%s'.", rcs->path);
2264 if (*rcsnode != rcs)
2266 freercsnode(rcsnode);
2271 fileattr_newfile (file);
2273 /* At this point, we used to set the file mode of the RCS file
2274 based on the mode of the file in the working directory. If we
2275 are creating the RCS file for the first time, add_rcs_file does
2276 this already. If we are re-adding the file, then perhaps it is
2277 consistent to preserve the old file mode, just as we preserve
2278 the old keyword expansion mode.
2280 If we decide that we should change the modes, then we can't do
2281 it here anyhow. At this point, the RCS file may be owned by
2282 somebody else, so a chmod will fail. We need to instead do the
2283 chmod after rewriting it.
2285 FIXME: In general, I think the file mode (and the keyword
2286 expansion mode) should be associated with a particular revision
2287 of the file, so that it is possible to have different revisions
2288 of a file have different modes. */
2293 if (retval != 0 && SIG_inCrSect ())
2301 * Attempt to place a lock on the RCS file; returns 0 if it could and 1 if it
2302 * couldn't. If the RCS file currently has a branch as the head, we must
2303 * move the head back to the trunk before locking the file, and be sure to
2304 * put the branch back as the head if there are any errors.
2307 lock_RCS (user, rcs, rev, repository)
2311 const char *repository;
2313 char *branch = NULL;
2317 * For a specified, numeric revision of the form "1" or "1.1", (or when
2318 * no revision is specified ""), definitely move the branch to the trunk
2319 * before locking the RCS file.
2321 * The assumption is that if there is more than one revision on the trunk,
2322 * the head points to the trunk, not a branch... and as such, it's not
2323 * necessary to move the head in this case.
2326 || (rev && isdigit ((unsigned char) *rev) && numdots (rev) < 2))
2328 branch = xstrdup (rcs->branch);
2331 if (RCS_setbranch (rcs, NULL) != 0)
2333 error (0, 0, "cannot change branch to default for %s",
2340 err = RCS_lock (rcs, NULL, 1);
2344 RCS_lock (rcs, rev, 1);
2347 /* We used to call RCS_rewrite here, and that might seem
2348 appropriate in order to write out the locked revision
2349 information. However, such a call would actually serve no
2350 purpose. CVS locks will prevent any interference from other
2351 CVS processes. The comment above rcs_internal_lockfile
2352 explains that it is already unsafe to use RCS and CVS
2353 simultaneously. It follows that writing out the locked
2354 revision information here would add no additional security.
2356 If we ever do care about it, the proper fix is to create the
2357 RCS lock file before calling this function, and maintain it
2358 until the checkin is complete.
2360 The call to RCS_lock is still required at present, since in
2361 some cases RCS_checkin will determine which revision to check
2362 in by looking for a lock. FIXME: This is rather roundabout,
2363 and a more straightforward approach would probably be easier to
2368 if (sbranch != NULL)
2374 /* try to restore the branch if we can on error */
2376 fixbranch (rcs, branch);
2386 * free an UPDATE node's data
2392 struct logfile_info *li = p->data;
2404 * Free the commit_info structure in p.
2410 struct commit_info *ci = p->data;
2422 * Free the commit_info structure in p.
2425 masterlist_delproc (p)
2428 struct master_lists *ml = p->data;
2430 dellist (&ml->ulist);
2431 dellist (&ml->cilist);