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...
28 static Dtype check_direntproc (void *callerdat, const char *dir,
29 const char *repos, const char *update_dir,
31 static int check_fileproc (void *callerdat, struct file_info *finfo);
32 static int check_filesdoneproc (void *callerdat, int err, const char *repos,
33 const char *update_dir, List *entries);
34 static int checkaddfile (const char *file, const char *repository,
35 const char *tag, const char *options,
37 static Dtype commit_direntproc (void *callerdat, const char *dir,
38 const char *repos, const char *update_dir,
40 static int commit_dirleaveproc (void *callerdat, const char *dir, int err,
41 const char *update_dir, List *entries);
42 static int commit_fileproc (void *callerdat, struct file_info *finfo);
43 static int commit_filesdoneproc (void *callerdat, int err,
44 const char *repository,
45 const char *update_dir, List *entries);
46 static int finaladd (struct file_info *finfo, char *revision, char *tag,
48 static int findmaxrev (Node * p, void *closure);
49 static int lock_RCS (const char *user, RCSNode *rcs, const char *rev,
50 const char *repository);
51 static int precommit_list_to_args_proc (Node * p, void *closure);
52 static int precommit_proc (const char *repository, const char *filter,
54 static int remove_file (struct file_info *finfo, char *tag,
56 static void fixaddfile (const char *rcs);
57 static void fixbranch (RCSNode *, char *branch);
58 static void unlockrcs (RCSNode *rcs);
59 static void ci_delproc (Node *p);
60 static void masterlist_delproc (Node *p);
64 Ctype status; /* as returned from Classify_File() */
65 char *rev; /* a numeric rev, if we know it */
66 char *tag; /* any sticky tag, or -r option */
67 char *options; /* Any sticky -k option */
71 List *ulist; /* list for Update_Logfile */
72 List *cilist; /* list with commit_info structs */
75 static int check_valid_edit = 0;
76 static int force_ci = 0;
77 static int got_message;
79 static char *saved_tag;
80 static char *write_dirtag;
81 static int write_dirnonbranch;
84 static char *saved_message;
85 static time_t last_register_time;
87 static const char *const commit_usage[] =
89 "Usage: %s %s [-cRlf] [-m msg | -F logfile] [-r rev] files...\n",
90 " -c Check for valid edits before committing.\n",
91 " -R Process directories recursively.\n",
92 " -l Local directory only (not recursive).\n",
93 " -f Force the file to be committed; disables recursion.\n",
94 " -F logfile Read the log message from file.\n",
95 " -m msg Log message.\n",
96 " -r rev Commit to this branch or trunk revision.\n",
97 "(Specify the --help global option for a list of other help options)\n",
101 #ifdef CLIENT_SUPPORT
102 /* Identify a file which needs "? foo" or a Questionable request. */
105 /* The two fields for the Directory request. */
112 struct question *next;
121 /* This is used from dirent to filesdone time, for each directory,
122 to make a list of files we have already seen. */
125 /* Linked list of files which need "? foo" or a Questionable request. */
126 struct question *questionables;
128 /* Only good within functions called from the filesdoneproc. Stores
129 the repository (pointer into storage managed by the recursion
131 const char *repository;
133 /* Non-zero if we should force the commit. This is enabled by
134 either -f or -r options, unlike force_ci which is just -f. */
141 find_dirent_proc (void *callerdat, const char *dir, const char *repository,
142 const char *update_dir, List *entries)
144 struct find_data *find_data = callerdat;
146 /* This check seems to slowly be creeping throughout CVS (update
147 and send_dirent_proc by CVS 1.5, diff in 31 Oct 1995. My guess
148 is that it (or some variant thereof) should go in all the
149 dirent procs. Unless someone has some better idea... */
153 /* initialize the ignore list for this directory */
154 find_data->ignlist = getlist ();
156 /* Print the same warm fuzzy as in check_direntproc, since that
157 code will never be run during client/server operation and we
158 want the messages to match. */
160 error (0, 0, "Examining %s", update_dir);
167 /* Here as a static until we get around to fixing ignore_files to pass
168 it along as an argument. */
169 static struct find_data *find_data_static;
174 find_ignproc (const char *file, const char *dir)
178 p = xmalloc (sizeof (struct question));
179 p->dir = xstrdup (dir);
180 p->repos = xstrdup (find_data_static->repository);
181 p->file = xstrdup (file);
182 p->next = find_data_static->questionables;
183 find_data_static->questionables = p;
189 find_filesdoneproc (void *callerdat, int err, const char *repository,
190 const char *update_dir, List *entries)
192 struct find_data *find_data = callerdat;
193 find_data->repository = repository;
195 /* if this directory has an ignore list, process it then free it */
196 if (find_data->ignlist)
198 find_data_static = find_data;
199 ignore_files (find_data->ignlist, entries, update_dir, find_ignproc);
200 dellist (&find_data->ignlist);
203 find_data->repository = NULL;
210 /* Machinery to find out what is modified, added, and removed. It is
211 possible this should be broken out into a new client_classify function;
212 merging it with classify_file is almost sure to be a mess, though,
213 because classify_file has all kinds of repository processing. */
215 find_fileproc (void *callerdat, struct file_info *finfo)
218 enum classify_type status;
220 struct find_data *args = callerdat;
221 struct logfile_info *data;
222 struct file_info xfinfo;
224 /* if this directory has an ignore list, add this file to it */
231 p->key = xstrdup (finfo->file);
232 if (addnode (args->ignlist, p) != 0)
237 xfinfo.repository = NULL;
240 vers = Version_TS (&xfinfo, NULL, saved_tag, NULL, 0, 0);
241 if (vers->vn_user == NULL)
243 if (vers->ts_user == NULL)
244 error (0, 0, "nothing known about `%s'", finfo->fullname);
246 error (0, 0, "use `%s add' to create an entry for `%s'",
247 program_name, finfo->fullname);
251 if (vers->vn_user[0] == '-')
253 if (vers->ts_user != NULL)
256 "`%s' should be removed and is still there (or is back"
257 " again)", finfo->fullname);
264 else if (strcmp (vers->vn_user, "0") == 0)
266 if (vers->ts_user == NULL)
268 /* This happens when one has `cvs add'ed a file, but it no
269 longer exists in the working directory at commit time.
270 FIXME: What classify_file does in this case is print
271 "new-born %s has disappeared" and removes the entry.
272 We probably should do the same. */
274 error (0, 0, "warning: new-born %s has disappeared",
276 status = T_REMOVE_ENTRY;
281 else if (vers->ts_user == NULL)
283 /* FIXME: What classify_file does in this case is print
284 "%s was lost". We probably should do the same. */
288 else if (vers->ts_rcs != NULL
289 && (args->force || strcmp (vers->ts_user, vers->ts_rcs) != 0))
290 /* If we are forcing commits, pretend that the file is
295 /* This covers unmodified files, as well as a variety of other
296 cases. FIXME: we probably should be printing a message and
297 returning 1 for many of those cases (but I'm not sure
298 exactly which ones). */
304 node->key = xstrdup (finfo->fullname);
306 data = xmalloc (sizeof (struct logfile_info));
308 data->tag = xstrdup (vers->tag);
309 data->rev_old = data->rev_new = NULL;
312 node->delproc = update_delproc;
314 (void)addnode (args->ulist, node);
325 copy_ulist (Node *node, void *data)
327 struct find_data *args = data;
328 args->argv[args->argc++] = node->key;
331 #endif /* CLIENT_SUPPORT */
335 #ifdef SERVER_SUPPORT
336 # define COMMIT_OPTIONS "+cnlRm:fF:r:"
337 #else /* !SERVER_SUPPORT */
338 # define COMMIT_OPTIONS "+clRm:fF:r:"
339 #endif /* SERVER_SUPPORT */
341 commit (int argc, char **argv)
348 usage (commit_usage);
352 * For log purposes, do not allow "root" to commit files. If you look
353 * like root, but are really logged in as a non-root user, it's OK.
355 /* FIXME: Shouldn't this check be much more closely related to the
356 readonly user stuff (CVSROOT/readers, &c). That is, why should
357 root be able to "cvs init", "cvs import", &c, but not "cvs ci"? */
358 /* Who we are on the client side doesn't affect logging. */
359 if (geteuid () == (uid_t) 0 && !current_parsed_root->isremote)
363 if ((pw = getpwnam (getcaller ())) == NULL)
365 "your apparent username (%s) is unknown to this system",
367 if (pw->pw_uid == (uid_t) 0)
368 error (1, 0, "'root' is not allowed to commit files");
370 #endif /* CVS_BADROOT */
373 while ((c = getopt (argc, argv, COMMIT_OPTIONS)) != -1)
378 check_valid_edit = 1;
380 #ifdef SERVER_SUPPORT
382 /* Silently ignore -n for compatibility with old
386 #endif /* SERVER_SUPPORT */
388 #ifdef FORCE_USE_EDITOR
395 free (saved_message);
396 saved_message = NULL;
399 saved_message = xstrdup (optarg);
404 saved_tag = xstrdup (optarg);
414 check_valid_edit = 0;
415 local = 1; /* also disable recursion */
418 #ifdef FORCE_USE_EDITOR
427 usage (commit_usage);
434 /* numeric specified revision means we ignore sticky tags... */
435 if (saved_tag && isdigit ((unsigned char) *saved_tag))
437 char *p = saved_tag + strlen (saved_tag);
439 /* strip trailing dots and leading zeros */
440 while (*--p == '.') ;
442 while (saved_tag[0] == '0' && isdigit ((unsigned char) saved_tag[1]))
446 /* some checks related to the "-F logfile" option */
449 size_t size = 0, len;
452 error (1, 0, "cannot specify both a message and a log file");
454 get_file (logfile, logfile, "r", &saved_message, &size, &len);
457 #ifdef CLIENT_SUPPORT
458 if (current_parsed_root->isremote)
460 struct find_data find_args;
464 find_args.ulist = getlist ();
466 find_args.questionables = NULL;
467 find_args.ignlist = NULL;
468 find_args.repository = NULL;
470 /* It is possible that only a numeric tag should set this.
471 I haven't really thought about it much.
472 Anyway, I suspect that setting it unnecessarily only causes
473 a little unneeded network traffic. */
474 find_args.force = force_ci || saved_tag != NULL;
476 err = start_recursion
477 (find_fileproc, find_filesdoneproc, find_dirent_proc, NULL,
478 &find_args, argc, argv, local, W_LOCAL, 0, CVS_LOCK_NONE,
481 error (1, 0, "correct above errors first!");
483 if (find_args.argc == 0)
485 /* Nothing to commit. Exit now without contacting the
486 server (note that this means that we won't print "?
487 foo" for files which merit it, because we don't know
488 what is in the CVSROOT/cvsignore file). */
489 dellist (&find_args.ulist);
493 /* Now we keep track of which files we actually are going to
494 operate on, and only work with those files in the future.
495 This saves time--we don't want to search the file system
496 of the working directory twice. */
497 if (size_overflow_p (xtimes (find_args.argc, sizeof (char **))))
502 find_args.argv = xnmalloc (find_args.argc, sizeof (char **));
504 walklist (find_args.ulist, copy_ulist, &find_args);
506 /* Do this before calling do_editor; don't ask for a log
507 message if we can't talk to the server. But do it after we
508 have made the checks that we can locally (to more quickly
509 catch syntax errors, the case where no files are modified,
510 added or removed, etc.).
512 On the other hand, calling start_server before do_editor
513 means that we chew up server resources the whole time that
514 the user has the editor open (hours or days if the user
515 forgets about it), which seems dubious. */
519 * We do this once, not once for each directory as in normal CVS.
520 * The protocol is designed this way. This is a feature.
523 do_editor (".", &saved_message, NULL, find_args.ulist);
525 /* We always send some sort of message, even if empty. */
526 option_with_arg ("-m", saved_message ? saved_message : "");
528 /* OK, now process all the questionable files we have been saving
534 p = find_args.questionables;
537 if (ign_inhibit_server || !supported_request ("Questionable"))
539 cvs_output ("? ", 2);
540 if (p->dir[0] != '\0')
542 cvs_output (p->dir, 0);
545 cvs_output (p->file, 0);
546 cvs_output ("\n", 1);
550 /* This used to send the Directory line of its own accord,
551 * but skipped some of the other processing like checking
552 * for whether the server would accept "Relative-directory"
553 * requests. Relying on send_a_repository() to do this
554 * picks up these checks but also:
556 * 1. Causes the "Directory" request to be sent only once
558 * 2. Causes the global TOPLEVEL_REPOS to be set.
559 * 3. Causes "Static-directory" and "Sticky" requests
560 * to sometimes be sent.
562 * (1) is almost certainly a plus. (2) & (3) may or may
563 * not be useful sometimes, and will ocassionally cause a
564 * little extra network traffic. The additional network
565 * traffic is probably already saved several times over and
566 * certainly cancelled out via the multiple "Directory"
567 * request suppression of (1).
569 send_a_repository (p->dir, p->repos, p->dir);
571 send_to_server ("Questionable ", 0);
572 send_to_server (p->file, 0);
573 send_to_server ("\012", 1);
586 if (check_valid_edit)
590 option_with_arg ("-r", saved_tag);
593 /* FIXME: This whole find_args.force/SEND_FORCE business is a
594 kludge. It would seem to be a server bug that we have to
595 say that files are modified when they are not. This makes
596 "cvs commit -r 2" across a whole bunch of files a very slow
597 operation (and it isn't documented in cvsclient.texi). I
598 haven't looked at the server code carefully enough to be
599 _sure_ why this is needed, but if it is because the "ci"
600 program, which we used to call, wanted the file to exist,
601 then it would be relatively simple to fix in the server. */
602 send_files (find_args.argc, find_args.argv, local, 0,
603 find_args.force ? SEND_FORCE : 0);
605 /* Sending only the names of the files which were modified, added,
606 or removed means that the server will only do an up-to-date
607 check on those files. This is different from local CVS and
608 previous versions of client/server CVS, but it probably is a Good
609 Thing, or at least Not Such A Bad Thing. */
610 send_file_names (find_args.argc, find_args.argv, 0);
611 free (find_args.argv);
612 dellist (&find_args.ulist);
614 send_to_server ("ci\012", 0);
615 err = get_responses_and_close ();
616 if (err != 0 && use_editor && saved_message != NULL)
618 /* If there was an error, don't nuke the user's carefully
619 constructed prose. This is something of a kludge; a better
620 solution is probably more along the lines of #150 in TODO
621 (doing a second up-to-date check before accepting the
622 log message has also been suggested, but that seems kind of
623 iffy because the real up-to-date check could still fail,
624 another error could occur, &c. Also, a second check would
625 slow things down). */
630 fp = cvs_temp_file (&fname);
632 error (1, 0, "cannot create temporary file %s", fname);
633 if (fwrite (saved_message, 1, strlen (saved_message), fp)
634 != strlen (saved_message))
635 error (1, errno, "cannot write temporary file %s", fname);
637 error (0, errno, "cannot close temporary file %s", fname);
638 error (0, 0, "saving log message in %s", fname);
645 if (saved_tag != NULL)
646 tag_check_valid (saved_tag, argc, argv, local, aflag, "", false);
648 /* XXX - this is not the perfect check for this */
650 write_dirtag = saved_tag;
654 lock_tree_promotably (argc, argv, local, W_LOCAL, aflag);
657 * Set up the master update list and hard link list
661 #ifdef PRESERVE_PERMISSIONS_SUPPORT
664 hardlist = getlist ();
667 * We need to save the working directory so that
668 * check_fileproc can construct a full pathname for each file.
670 working_dir = xgetcwd ();
675 * Run the recursion processor to verify the files are all up-to-date
677 err = start_recursion (check_fileproc, check_filesdoneproc,
678 check_direntproc, NULL, NULL, argc, argv, local,
679 W_LOCAL, aflag, CVS_LOCK_NONE, NULL, 1, NULL);
681 error (1, 0, "correct above errors first!");
684 * Run the recursion processor to commit the files
686 write_dirnonbranch = 0;
688 err = start_recursion (commit_fileproc, commit_filesdoneproc,
689 commit_direntproc, commit_dirleaveproc, NULL,
690 argc, argv, local, W_LOCAL, aflag,
691 CVS_LOCK_WRITE, NULL, 1, NULL);
694 * Unlock all the dirs and clean up
699 /* see if we need to sleep before returning to avoid time-stamp races */
700 if (!server_active && last_register_time)
702 sleep_past (last_register_time);
710 /* This routine determines the status of a given file and retrieves
711 the version information that is associated with that file. */
715 classify_file_internal (struct file_info *finfo, Vers_TS **vers)
717 int save_noexec, save_quiet, save_really_quiet;
720 /* FIXME: Do we need to save quiet as well as really_quiet? Last
721 time I glanced at Classify_File I only saw it looking at really_quiet
723 save_noexec = noexec;
725 save_really_quiet = really_quiet;
726 noexec = quiet = really_quiet = 1;
728 /* handle specified numeric revision specially */
729 if (saved_tag && isdigit ((unsigned char) *saved_tag))
731 /* If the tag is for the trunk, make sure we're at the head */
732 if (numdots (saved_tag) < 2)
734 status = Classify_File (finfo, NULL, NULL,
735 NULL, 1, aflag, vers, 0);
736 if (status == T_UPTODATE || status == T_MODIFIED ||
742 xstatus = Classify_File (finfo, saved_tag, NULL,
743 NULL, 1, aflag, vers, 0);
744 if (xstatus == T_REMOVE_ENTRY)
746 else if (status == T_MODIFIED && xstatus == T_CONFLICT)
757 * The revision is off the main trunk; make sure we're
758 * up-to-date with the head of the specified branch.
760 xtag = xstrdup (saved_tag);
761 if ((numdots (xtag) & 1) != 0)
763 cp = strrchr (xtag, '.');
766 status = Classify_File (finfo, xtag, NULL,
767 NULL, 1, aflag, vers, 0);
768 if ((status == T_REMOVE_ENTRY || status == T_CONFLICT)
769 && (cp = strrchr (xtag, '.')) != NULL)
771 /* pluck one more dot off the revision */
774 status = Classify_File (finfo, xtag, NULL,
775 NULL, 1, aflag, vers, 0);
776 if (status == T_UPTODATE || status == T_REMOVE_ENTRY)
779 /* now, muck with vers to make the tag correct */
781 (*vers)->tag = xstrdup (saved_tag);
786 status = Classify_File (finfo, saved_tag, NULL, NULL, 1, 0, vers, 0);
787 noexec = save_noexec;
789 really_quiet = save_really_quiet;
797 * Check to see if a file is ok to commit and make sure all files are
802 check_fileproc (void *callerdat, struct file_info *finfo)
807 List *ulist, *cilist;
809 struct commit_info *ci;
810 struct logfile_info *li;
813 size_t cvsroot_len = strlen (current_parsed_root->directory);
815 if (!finfo->repository)
817 error (0, 0, "nothing known about `%s'", finfo->fullname);
821 if (strncmp (finfo->repository, current_parsed_root->directory,
823 && ISSLASH (finfo->repository[cvsroot_len])
824 && strncmp (finfo->repository + cvsroot_len + 1,
826 sizeof (CVSROOTADM) - 1) == 0
827 && ISSLASH (finfo->repository[cvsroot_len + sizeof (CVSROOTADM)])
828 && strcmp (finfo->repository + cvsroot_len + sizeof (CVSROOTADM) + 1,
831 error (1, 0, "cannot check in to %s", finfo->repository);
833 status = classify_file_internal (finfo, &vers);
836 * If the force-commit option is enabled, and the file in question
837 * appears to be up-to-date, just make it look modified so that
838 * it will be committed.
840 if (force_ci && status == T_UPTODATE)
849 error (0, 0, "Up-to-date check failed for `%s'", finfo->fullname);
859 * some quick sanity checks; if no numeric -r option specified:
860 * - can't have a sticky date
861 * - can't have a sticky tag that is not a branch
863 * - if status is T_REMOVED, file must not exist and its entry
864 * can't have a numeric sticky tag.
865 * - if status is T_ADDED, rcs file must not exist unless on
866 * a branch or head is dead
867 * - if status is T_ADDED, can't have a non-trunk numeric rev
868 * - if status is T_MODIFIED and a Conflict marker exists, don't
869 * allow the commit if timestamp is identical or if we find
870 * an RCS_MERGE_PAT in the file.
872 if (!saved_tag || !isdigit ((unsigned char) *saved_tag))
877 "cannot commit with sticky date for file `%s'",
881 if (status == T_MODIFIED && vers->tag &&
882 !RCS_isbranch (finfo->rcs, vers->tag))
885 "sticky tag `%s' for file `%s' is not a branch",
886 vers->tag, finfo->fullname);
890 if (status == T_CONFLICT && !force_ci)
893 "file `%s' had a conflict and has not been modified",
897 if (status == T_MODIFIED && !force_ci && file_has_markers (finfo))
899 /* Make this a warning, not an error, because we have
900 no way of knowing whether the "conflict indicators"
901 are really from a conflict or whether they are part
902 of the document itself (cvs.texinfo and sanity.sh in
903 CVS itself, for example, tend to want to have strings
904 like ">>>>>>>" at the start of a line). Making people
905 kludge this the way they need to kludge keyword
906 expansion seems undesirable. And it is worse than
907 keyword expansion, because there is no -ko
911 warning: file `%s' seems to still contain conflict indicators",
915 if (status == T_REMOVED)
917 if (vers->ts_user != NULL)
920 "`%s' should be removed and is still there (or is"
921 " back again)", finfo->fullname);
925 if (vers->tag && isdigit ((unsigned char) *vers->tag))
927 /* Remove also tries to forbid this, but we should check
928 here. I'm only _sure_ about somewhat obscure cases
929 (hacking the Entries file, using an old version of
930 CVS for the remove and a new one for the commit), but
931 there might be other cases. */
933 "cannot remove file `%s' which has a numeric sticky"
934 " tag of `%s'", finfo->fullname, vers->tag);
939 if (status == T_ADDED)
941 if (vers->tag == NULL)
943 if (finfo->rcs != NULL &&
944 !RCS_isdead (finfo->rcs, finfo->rcs->head))
947 "cannot add file `%s' when RCS file `%s' already exists",
948 finfo->fullname, finfo->rcs->path);
952 else if (isdigit ((unsigned char) *vers->tag) &&
953 numdots (vers->tag) > 1)
956 "cannot add file `%s' with revision `%s'; must be on trunk",
957 finfo->fullname, vers->tag);
962 /* done with consistency checks; now, to get on with the commit */
963 if (finfo->update_dir[0] == '\0')
966 xdir = finfo->update_dir;
967 if ((p = findnode (mulist, xdir)) != NULL)
969 ulist = ((struct master_lists *) p->data)->ulist;
970 cilist = ((struct master_lists *) p->data)->cilist;
974 struct master_lists *ml;
976 ml = xmalloc (sizeof (struct master_lists));
977 ulist = ml->ulist = getlist ();
978 cilist = ml->cilist = getlist ();
981 p->key = xstrdup (xdir);
984 p->delproc = masterlist_delproc;
985 (void) addnode (mulist, p);
988 /* first do ulist, then cilist */
990 p->key = xstrdup (finfo->file);
992 p->delproc = update_delproc;
993 li = xmalloc (sizeof (struct logfile_info));
996 if (check_valid_edit)
998 char *editors = NULL;
1001 editors = fileattr_get0 (finfo->file, "_editors");
1002 if (editors != NULL)
1004 char *caller = getcaller ();
1012 p = strchr (p, '>');
1018 if (strcmp (caller, p0) == 0)
1022 p = strchr (p + 1, ',');
1031 if (strcmp (caller, p0) == 0)
1040 if (check_valid_edit && editor == NULL)
1042 error (0, 0, "Valid edit does not exist for %s",
1044 freevers_ts (&vers);
1048 li->tag = xstrdup (vers->tag);
1049 li->rev_old = xstrdup (vers->vn_rcs);
1052 (void) addnode (ulist, p);
1055 p->key = xstrdup (finfo->file);
1057 p->delproc = ci_delproc;
1058 ci = xmalloc (sizeof (struct commit_info));
1059 ci->status = status;
1061 if (isdigit ((unsigned char) *vers->tag))
1062 ci->rev = xstrdup (vers->tag);
1064 ci->rev = RCS_whatbranch (finfo->rcs, vers->tag);
1067 ci->tag = xstrdup (vers->tag);
1068 ci->options = xstrdup (vers->options);
1070 (void) addnode (cilist, p);
1072 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1075 /* Add this file to hardlist, indexed on its inode. When
1076 we are done, we can find out what files are hardlinked
1077 to a given file by looking up its inode in hardlist. */
1080 struct hardlink_info *hlinfo;
1082 /* Get the full pathname of the current file. */
1083 fullpath = Xasprintf ("%s/%s", working_dir, finfo->fullname);
1085 /* To permit following links in subdirectories, files
1086 are keyed on finfo->fullname, not on finfo->name. */
1087 linkp = lookup_file_by_inode (fullpath);
1089 /* If linkp is NULL, the file doesn't exist... maybe
1090 we're doing a remove operation? */
1093 /* Create a new hardlink_info node, which will record
1094 the current file's status and the links listed in its
1095 `hardlinks' delta field. We will append this
1096 hardlink_info node to the appropriate hardlist entry. */
1097 hlinfo = xmalloc (sizeof (struct hardlink_info));
1098 hlinfo->status = status;
1099 linkp->data = hlinfo;
1108 error (0, 0, "nothing known about `%s'", finfo->fullname);
1113 error (0, 0, "CVS internal error: unknown status %d", status);
1121 freevers_ts (&vers);
1128 * By default, return the code that tells do_recursion to examine all
1133 check_direntproc (void *callerdat, const char *dir, const char *repos,
1134 const char *update_dir, List *entries)
1140 error (0, 0, "Examining %s", update_dir);
1148 * Walklist proc to generate an arg list from the line in commitinfo
1151 precommit_list_to_args_proc (p, closure)
1155 struct format_cmdline_walklist_closure *c = closure;
1156 struct logfile_info *li;
1162 if (p->data == NULL) return 1;
1166 /* foreach requested attribute */
1173 if (li->type == T_ADDED
1174 || li->type == T_MODIFIED
1175 || li->type == T_REMOVED)
1182 "Unknown format character or not a list attribute: %c",
1187 /* copy the attribute into an argument */
1190 arg = cmdlineescape (c->quotes, arg);
1194 arg = cmdlinequote ('"', arg);
1197 expand_string (c->buf, c->length, doff + strlen (arg));
1199 strncpy (d, arg, strlen (arg));
1203 /* and always put the extra space on. we'll have to back up a char
1204 * when we're done, but that seems most efficient
1207 expand_string (c->buf, c->length, doff + 1);
1211 /* correct our original pointer into the buff */
1219 * Callback proc for pre-commit checking
1222 precommit_proc (const char *repository, const char *filter, void *closure)
1224 char *newfilter = NULL;
1226 const char *srepos = Short_Repository (repository);
1227 List *ulist = closure;
1229 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1230 if (!strchr (filter, '%'))
1233 "warning: commitinfo line contains no format strings:\n"
1235 "Appending defaults (\" %%r/%%p %%s\"), but please be aware that this usage is\n"
1236 "deprecated.", filter);
1237 newfilter = Xasprintf ("%s %%r/%%p %%s", filter);
1240 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1243 * Cast any NULL arguments as appropriate pointers as this is an
1244 * stdarg function and we need to be certain the caller gets what
1247 cmdline = format_cmdline (
1248 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1250 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1252 "c", "s", cvs_cmd_name,
1253 #ifdef SERVER_SUPPORT
1254 "R", "s", referrer ? referrer->original : "NONE",
1255 #endif /* SERVER_SUPPORT */
1257 "r", "s", current_parsed_root->directory,
1258 "s", ",", ulist, precommit_list_to_args_proc,
1262 if (newfilter) free (newfilter);
1264 if (!cmdline || !strlen (cmdline))
1266 if (cmdline) free (cmdline);
1267 error (0, 0, "precommit proc resolved to the empty string!");
1271 run_setup (cmdline);
1274 return run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL | RUN_REALLY);
1280 * Run the pre-commit checks for the dir
1284 check_filesdoneproc (void *callerdat, int err, const char *repos,
1285 const char *update_dir, List *entries)
1291 /* find the update list for this dir */
1292 p = findnode (mulist, update_dir);
1294 saved_ulist = ((struct master_lists *) p->data)->ulist;
1298 /* skip the checks if there's nothing to do */
1299 if (saved_ulist == NULL || saved_ulist->list->next == saved_ulist->list)
1302 /* run any pre-commit checks */
1303 n = Parse_Info (CVSROOTADM_COMMITINFO, repos, precommit_proc, PIOPT_ALL,
1307 error (0, 0, "Pre-commit check failed");
1317 * Do the work of committing a file
1320 static char *sbranch;
1324 commit_fileproc (void *callerdat, struct file_info *finfo)
1328 List *ulist, *cilist;
1329 struct commit_info *ci;
1331 /* Keep track of whether write_dirtag is a branch tag.
1332 Note that if it is a branch tag in some files and a nonbranch tag
1333 in others, treat it as a nonbranch tag. It is possible that case
1334 should elicit a warning or an error. */
1335 if (write_dirtag != NULL
1336 && finfo->rcs != NULL)
1338 char *rev = RCS_getversion (finfo->rcs, write_dirtag, NULL, 1, NULL);
1340 && !RCS_nodeisbranch (finfo->rcs, write_dirtag))
1341 write_dirnonbranch = 1;
1346 if (finfo->update_dir[0] == '\0')
1347 p = findnode (mulist, ".");
1349 p = findnode (mulist, finfo->update_dir);
1352 * if p is null, there were file type command line args which were
1353 * all up-to-date so nothing really needs to be done
1357 ulist = ((struct master_lists *) p->data)->ulist;
1358 cilist = ((struct master_lists *) p->data)->cilist;
1361 * At this point, we should have the commit message unless we were called
1362 * with files as args from the command line. In that latter case, we
1363 * need to get the commit message ourselves
1368 if (!server_active && use_editor)
1369 do_editor (finfo->update_dir, &saved_message,
1370 finfo->repository, ulist);
1371 do_verify (&saved_message, finfo->repository, ulist);
1374 p = findnode (cilist, finfo->file);
1379 if (ci->status == T_MODIFIED)
1381 if (finfo->rcs == NULL)
1382 error (1, 0, "internal error: no parsed RCS file");
1383 if (lock_RCS (finfo->file, finfo->rcs, ci->rev,
1384 finfo->repository) != 0)
1386 unlockrcs (finfo->rcs);
1391 else if (ci->status == T_ADDED)
1393 if (checkaddfile (finfo->file, finfo->repository, ci->tag, ci->options,
1396 if (finfo->rcs != NULL)
1397 fixaddfile (finfo->rcs->path);
1402 /* adding files with a tag, now means adding them on a branch.
1403 Since the branch test was done in check_fileproc for
1404 modified files, we need to stub it in again here. */
1408 /* If numeric, it is on the trunk; check_fileproc enforced
1410 && !isdigit ((unsigned char) ci->tag[0]))
1412 if (finfo->rcs == NULL)
1413 error (1, 0, "internal error: no parsed RCS file");
1416 ci->rev = RCS_whatbranch (finfo->rcs, ci->tag);
1417 err = Checkin ('A', finfo, ci->rev,
1418 ci->tag, ci->options, saved_message);
1421 unlockrcs (finfo->rcs);
1422 fixbranch (finfo->rcs, sbranch);
1425 (void) time (&last_register_time);
1427 ci->status = T_UPTODATE;
1432 * Add the file for real
1434 if (ci->status == T_ADDED)
1438 if (ci->rev == NULL)
1440 /* find the max major rev number in this directory */
1442 (void) walklist (finfo->entries, findmaxrev, NULL);
1443 if (finfo->rcs->head)
1445 /* resurrecting: include dead revision */
1446 int thisrev = atoi (finfo->rcs->head);
1447 if (thisrev > maxrev)
1452 xrev = Xasprintf ("%d", maxrev);
1455 /* XXX - an added file with symbolic -r should add tag as well */
1456 err = finaladd (finfo, ci->rev ? ci->rev : xrev, ci->tag, ci->options);
1460 else if (ci->status == T_MODIFIED)
1462 err = Checkin ('M', finfo, ci->rev, ci->tag,
1463 ci->options, saved_message);
1465 (void) time (&last_register_time);
1469 unlockrcs (finfo->rcs);
1470 fixbranch (finfo->rcs, sbranch);
1473 else if (ci->status == T_REMOVED)
1475 err = remove_file (finfo, ci->tag, saved_message);
1476 #ifdef SERVER_SUPPORT
1479 server_scratch_entry_only ();
1480 server_updated (finfo,
1483 /* Doesn't matter, it won't get checked. */
1493 /* Clearly this is right for T_MODIFIED. I haven't thought so much
1494 about T_ADDED or T_REMOVED. */
1495 notify_do ('C', finfo->file, finfo->update_dir, getcaller (), NULL, NULL,
1501 /* on failure, remove the file from ulist */
1502 p = findnode (ulist, finfo->file);
1508 /* On success, retrieve the new version number of the file and
1509 copy it into the log information (see logmsg.c
1510 (logfile_write) for more details). We should only update
1511 the version number for files that have been added or
1512 modified but not removed since classify_file_internal
1513 will return the version number of a file even after it has
1514 been removed from the archive, which is not the behavior we
1515 want for our commitlog messages; we want the old version
1516 number and then "NONE." */
1518 if (ci->status != T_REMOVED)
1520 p = findnode (ulist, finfo->file);
1524 struct logfile_info *li;
1526 (void) classify_file_internal (finfo, &vers);
1528 li->rev_new = xstrdup (vers->vn_rcs);
1529 freevers_ts (&vers);
1533 if (SIG_inCrSect ())
1542 * Log the commit and clean up the update list
1546 commit_filesdoneproc (void *callerdat, int err, const char *repository,
1547 const char *update_dir, List *entries)
1552 assert (repository);
1554 p = findnode (mulist, update_dir);
1558 ulist = ((struct master_lists *) p->data)->ulist;
1562 /* Build the administrative files if necessary. */
1566 if (strncmp (current_parsed_root->directory, repository,
1567 strlen (current_parsed_root->directory)) != 0)
1569 "internal error: repository (%s) doesn't begin with root (%s)",
1570 repository, current_parsed_root->directory);
1571 p = repository + strlen (current_parsed_root->directory);
1574 if (strcmp ("CVSROOT", p) == 0
1575 /* Check for subdirectories because people may want to create
1576 subdirectories and list files therein in checkoutlist. */
1577 || strncmp ("CVSROOT/", p, strlen ("CVSROOT/")) == 0
1580 /* "Database" might a little bit grandiose and/or vague,
1581 but "checked-out copies of administrative files, unless
1582 in the case of modules and you are using ndbm in which
1583 case modules.{pag,dir,db}" is verbose and excessively
1584 focused on how the database is implemented. */
1586 /* mkmodules requires the absolute name of the CVSROOT directory.
1587 Remove anything after the `CVSROOT' component -- this is
1588 necessary when committing in a subdirectory of CVSROOT. */
1589 char *admin_dir = xstrdup (repository);
1590 int cvsrootlen = strlen ("CVSROOT");
1591 assert (admin_dir[p - repository + cvsrootlen] == '\0'
1592 || admin_dir[p - repository + cvsrootlen] == '/');
1593 admin_dir[p - repository + cvsrootlen] = '\0';
1597 cvs_output (program_name, 0);
1598 cvs_output (" ", 1);
1599 cvs_output (cvs_cmd_name, 0);
1600 cvs_output (": Rebuilding administrative file database\n", 0);
1602 mkmodules (admin_dir);
1604 WriteTemplate (".", 1, repository);
1608 /* FIXME: This used to be above the block above. The advantage of being
1609 * here is that it is not called until after all possible writes from this
1610 * process are complete. The disadvantage is that a fatal error during
1611 * update of CVSROOT can prevent the loginfo script from being called.
1613 * A more general solution I have been considering is calling a generic
1614 * "postwrite" hook from the remove write lock routine.
1616 Update_Logfile (repository, saved_message, NULL, ulist);
1624 * Get the log message for a dir
1628 commit_direntproc (void *callerdat, const char *dir, const char *repos,
1629 const char *update_dir, List *entries)
1638 /* find the update list for this dir */
1639 p = findnode (mulist, update_dir);
1641 ulist = ((struct master_lists *) p->data)->ulist;
1645 /* skip the files as an optimization */
1646 if (ulist == NULL || ulist->list->next == ulist->list)
1647 return R_SKIP_FILES;
1649 /* get commit message */
1651 real_repos = Name_Repository (dir, update_dir);
1652 if (!server_active && use_editor)
1653 do_editor (update_dir, &saved_message, real_repos, ulist);
1654 do_verify (&saved_message, real_repos, ulist);
1662 * Process the post-commit proc if necessary
1666 commit_dirleaveproc (void *callerdat, const char *dir, int err,
1667 const char *update_dir, List *entries)
1669 /* update the per-directory tag info */
1670 /* FIXME? Why? The "commit examples" node of cvs.texinfo briefly
1671 mentions commit -r being sticky, but apparently in the context of
1672 this being a confusing feature! */
1673 if (err == 0 && write_dirtag != NULL)
1675 char *repos = Name_Repository (NULL, update_dir);
1676 WriteTag (NULL, write_dirtag, NULL, write_dirnonbranch,
1687 * find the maximum major rev number in an entries file
1690 findmaxrev (Node *p, void *closure)
1693 Entnode *entdata = p->data;
1695 if (entdata->type != ENT_FILE)
1697 thisrev = atoi (entdata->version);
1698 if (thisrev > maxrev)
1704 * Actually remove a file by moving it to the attic
1705 * XXX - if removing a ,v file that is a relative symbolic link to
1706 * another ,v file, we probably should add a ".." component to the
1707 * link to keep it relative after we move it into the attic.
1709 Return value is 0 on success, or >0 on error (in which case we have
1710 printed an error message). */
1712 remove_file (struct file_info *finfo, char *tag, char *message)
1729 if (finfo->rcs == NULL)
1730 error (1, 0, "internal error: no parsed RCS file");
1733 if (tag && !(branch = RCS_nodeisbranch (finfo->rcs, tag)))
1735 /* a symbolic tag is specified; just remove the tag from the file */
1736 if ((retcode = RCS_deltag (finfo->rcs, tag)) != 0)
1739 error (0, retcode == -1 ? errno : 0,
1740 "failed to remove tag `%s' from `%s'", tag,
1744 RCS_rewrite (finfo->rcs, NULL, NULL);
1745 Scratch_Entry (finfo->entries, finfo->file);
1749 /* we are removing the file from either the head or a branch */
1750 /* commit a new, dead revision. */
1758 rev = RCS_whatbranch (finfo->rcs, tag);
1761 error (0, 0, "cannot find branch \"%s\".", tag);
1765 branchname = RCS_getbranch (finfo->rcs, rev, 1);
1766 if (branchname == NULL)
1768 /* no revision exists on this branch. use the previous
1769 revision but do not lock. */
1770 corev = RCS_gettag (finfo->rcs, tag, 1, NULL);
1771 prev_rev = xstrdup (corev);
1775 corev = xstrdup (rev);
1776 prev_rev = xstrdup (branchname);
1780 } else /* Not a branch */
1782 /* Get current head revision of file. */
1783 prev_rev = RCS_head (finfo->rcs);
1786 /* if removing without a tag or a branch, then make sure the default
1787 branch is the trunk. */
1788 if (!tag && !branch)
1790 if (RCS_setbranch (finfo->rcs, NULL) != 0)
1792 error (0, 0, "cannot change branch to default for %s",
1796 RCS_rewrite (finfo->rcs, NULL, NULL);
1799 /* check something out. Generally this is the head. If we have a
1800 particular rev, then name it. */
1801 retcode = RCS_checkout (finfo->rcs, finfo->file, rev ? corev : NULL,
1802 NULL, NULL, RUN_TTY, NULL, NULL);
1806 "failed to check out `%s'", finfo->fullname);
1810 /* Except when we are creating a branch, lock the revision so that
1811 we can check in the new revision. */
1814 if (RCS_lock (finfo->rcs, rev ? corev : NULL, 1) == 0)
1815 RCS_rewrite (finfo->rcs, NULL, NULL);
1821 retcode = RCS_checkin (finfo->rcs, NULL, finfo->file, message,
1822 rev, 0, RCS_FLAGS_DEAD | RCS_FLAGS_QUIET);
1826 error (0, retcode == -1 ? errno : 0,
1827 "failed to commit dead revision for `%s'", finfo->fullname);
1830 /* At this point, the file has been committed as removed. We should
1831 probably tell the history file about it */
1832 history_write ('R', NULL, finfo->rcs->head, finfo->file, finfo->repository);
1837 old_path = xstrdup (finfo->rcs->path);
1839 RCS_setattic (finfo->rcs, 1);
1841 /* Print message that file was removed. */
1844 cvs_output (old_path, 0);
1845 cvs_output (" <-- ", 0);
1846 if (finfo->update_dir && strlen (finfo->update_dir))
1848 cvs_output (finfo->update_dir, 0);
1849 cvs_output ("/", 1);
1851 cvs_output (finfo->file, 0);
1852 cvs_output ("\nnew revision: delete; previous revision: ", 0);
1853 cvs_output (prev_rev, 0);
1854 cvs_output ("\n", 0);
1861 Scratch_Entry (finfo->entries, finfo->file);
1868 * Do the actual checkin for added files
1871 finaladd (struct file_info *finfo, char *rev, char *tag, char *options)
1875 ret = Checkin ('A', finfo, rev, tag, options, saved_message);
1878 char *tmp = Xasprintf ("%s/%s%s", CVSADM, finfo->file, CVSEXT_LOG);
1879 if (unlink_file (tmp) < 0
1880 && !existence_error (errno))
1881 error (0, errno, "cannot remove %s", tmp);
1884 else if (finfo->rcs != NULL)
1885 fixaddfile (finfo->rcs->path);
1887 (void) time (&last_register_time);
1895 * Unlock an rcs file
1898 unlockrcs (RCSNode *rcs)
1902 if ((retcode = RCS_unlock (rcs, NULL, 1)) != 0)
1903 error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
1904 "could not unlock %s", rcs->path);
1906 RCS_rewrite (rcs, NULL, NULL);
1912 * remove a partially added file. if we can parse it, leave it alone.
1914 * FIXME: Every caller that calls this function can access finfo->rcs (the
1915 * parsed RCSNode data), so we should be able to detect that the file needs
1916 * to be removed without reparsing the file as we do below.
1919 fixaddfile (const char *rcs)
1922 int save_really_quiet;
1924 save_really_quiet = really_quiet;
1926 if ((rcsfile = RCS_parsercsfile (rcs)) == NULL)
1928 if (unlink_file (rcs) < 0)
1929 error (0, errno, "cannot remove %s", rcs);
1932 freercsnode (&rcsfile);
1933 really_quiet = save_really_quiet;
1939 * put the branch back on an rcs file
1942 fixbranch (RCSNode *rcs, char *branch)
1948 if ((retcode = RCS_setbranch (rcs, branch)) != 0)
1949 error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
1950 "cannot restore branch to %s for %s", branch, rcs->path);
1951 RCS_rewrite (rcs, NULL, NULL);
1958 * do the initial part of a file add for the named file. if adding
1959 * with a tag, put the file in the Attic and point the symbolic tag
1960 * at the committed revision.
1963 * file The name of the file in the workspace.
1964 * repository The repository directory to expect to find FILE,v in.
1965 * tag The name or rev num of the branch being added to, if any.
1966 * options Any RCS keyword expansion options specified by the user.
1967 * rcsnode A pointer to the pre-parsed RCSNode for this file, if the file
1968 * exists in the repository. If this is NULL, assume the file
1969 * does not yet exist.
1973 * 1 on errors, after printing any appropriate error messages.
1976 * This function will return an error when any of the following functions do:
1981 * RCS_parse (called to verify the newly created archive file)
1986 checkaddfile (const char *file, const char *repository, const char *tag,
1987 const char *options, RCSNode **rcsnode)
1991 int newfile = 0; /* Set to 1 if we created a new RCS archive. */
1993 int adding_on_branch;
1995 assert (rcsnode != NULL);
1997 /* Callers expect to be able to use either "" or NULL to mean the
1998 default keyword expansion. */
1999 if (options != NULL && options[0] == '\0')
2001 if (options != NULL)
2002 assert (options[0] == '-' && options[1] == 'k');
2004 /* If numeric, it is on the trunk; check_fileproc enforced
2006 adding_on_branch = tag != NULL && !isdigit ((unsigned char) tag[0]);
2008 if (*rcsnode == NULL)
2012 size_t descalloc = 0;
2016 if (adding_on_branch)
2019 rcsname = xmalloc (strlen (repository)
2024 (void) sprintf (rcsname, "%s/%s", repository, CVSATTIC);
2025 omask = umask (cvsumask);
2026 if (CVS_MKDIR (rcsname, 0777) != 0 && errno != EEXIST)
2027 error (1, errno, "cannot make directory `%s'", rcsname);
2028 (void) umask (omask);
2029 (void) sprintf (rcsname,
2037 rcsname = Xasprintf ("%s/%s%s", repository, file, RCSEXT);
2039 /* this is the first time we have ever seen this file; create
2041 fname = Xasprintf ("%s/%s%s", CVSADM, file, CVSEXT_LOG);
2042 /* If the file does not exist, no big deal. In particular, the
2043 server does not (yet at least) create CVSEXT_LOG files. */
2045 /* FIXME: Should be including update_dir in the appropriate
2047 get_file (fname, fname, "r", &desc, &descalloc, &desclen);
2050 /* From reading the RCS 5.7 source, "rcs -i" adds a newline to the
2051 end of the log message if the message is nonempty.
2052 Do it. RCS also deletes certain whitespace, in cleanlogmsg,
2053 which we don't try to do here. */
2056 expand_string (&desc, &descalloc, desclen + 1);
2057 desc[desclen++] = '\012';
2060 /* Set RCS keyword expansion options. */
2061 if (options != NULL)
2066 if (add_rcs_file (NULL, rcsname, file, NULL, opt,
2067 NULL, NULL, 0, NULL,
2068 desc, desclen, NULL, 0) != 0)
2070 if (rcsname != NULL)
2074 rcs = RCS_parsercsfile (rcsname);
2076 if (rcsname != NULL)
2084 /* file has existed in the past. Prepare to resurrect. */
2090 oldexpand = RCS_getexpand (rcs);
2091 if ((oldexpand != NULL
2093 && strcmp (options + 2, oldexpand) != 0)
2094 || (oldexpand == NULL && options != NULL))
2096 /* We tell the user about this, because it means that the
2097 old revisions will no longer retrieve the way that they
2099 error (0, 0, "changing keyword expansion mode to %s", options);
2100 RCS_setexpand (rcs, options + 2);
2103 if (!adding_on_branch)
2105 /* We are adding on the trunk, so move the file out of the
2107 if (!(rcs->flags & INATTIC))
2109 error (0, 0, "warning: expected %s to be in Attic",
2113 /* Begin a critical section around the code that spans the
2114 first commit on the trunk of a file that's already been
2115 committed on a branch. */
2118 if (RCS_setattic (rcs, 0))
2124 rev = RCS_getversion (rcs, tag, NULL, 1, NULL);
2126 if (lock_RCS (file, rcs, rev, repository))
2128 error (0, 0, "cannot lock revision %s in `%s'.",
2129 rev ? rev : tag ? tag : "HEAD", rcs->path);
2139 /* when adding a file for the first time, and using a tag, we need
2140 to create a dead revision on the trunk. */
2141 if (adding_on_branch)
2149 /* move the new file out of the way. */
2150 fname = Xasprintf ("%s/%s%s", CVSADM, CVSPREFIX, file);
2151 rename_file (file, fname);
2153 /* Create empty FILE. Can't use copy_file with a DEVNULL
2154 argument -- copy_file now ignores device files. */
2155 fp = fopen (file, "w");
2157 error (1, errno, "cannot open %s for writing", file);
2158 if (fclose (fp) < 0)
2159 error (0, errno, "cannot close %s", file);
2161 tmp = Xasprintf ("file %s was initially added on branch %s.",
2163 /* commit a dead revision. */
2164 retcode = RCS_checkin (rcs, NULL, NULL, tmp, NULL, 0,
2165 RCS_FLAGS_DEAD | RCS_FLAGS_QUIET);
2169 error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
2170 "could not create initial dead revision %s", rcs->path);
2175 /* put the new file back where it was */
2176 rename_file (fname, file);
2179 /* double-check that the file was written correctly */
2181 rcs = RCS_parse (file, repository);
2184 error (0, 0, "could not read %s", rcs->path);
2189 /* and lock it once again. */
2190 if (lock_RCS (file, rcs, NULL, repository))
2192 error (0, 0, "cannot lock initial revision in `%s'.",
2198 /* when adding with a tag, we need to stub a branch, if it
2199 doesn't already exist. */
2200 if (!RCS_nodeisbranch (rcs, tag))
2202 /* branch does not exist. Stub it. */
2206 time_t headtime = -1;
2212 fixbranch (rcs, sbranch);
2214 head = RCS_getversion (rcs, NULL, NULL, 0, NULL);
2216 error (1, 0, "No head revision in archive file `%s'.",
2218 magicrev = RCS_magicrev (rcs, head);
2220 /* If this is not a new branch, then we will want a dead
2221 version created before this one. */
2223 headtime = RCS_getrevtime (rcs, head, 0, 0);
2225 retcode = RCS_settag (rcs, tag, magicrev);
2226 RCS_rewrite (rcs, NULL, NULL);
2233 error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
2234 "could not stub branch %s for %s", tag, rcs->path);
2237 /* We need to add a dead version here to avoid -rtag -Dtime
2238 checkout problems between when the head version was
2240 if (!newfile && headtime != -1)
2242 /* move the new file out of the way. */
2243 fname = Xasprintf ("%s/%s%s", CVSADM, CVSPREFIX, file);
2244 rename_file (file, fname);
2246 /* Create empty FILE. Can't use copy_file with a DEVNULL
2247 argument -- copy_file now ignores device files. */
2248 fp = fopen (file, "w");
2250 error (1, errno, "cannot open %s for writing", file);
2251 if (fclose (fp) < 0)
2252 error (0, errno, "cannot close %s", file);
2254 /* As we will be hacking the delta date, put the time
2255 this was added into the log message. */
2258 tmp = Xasprintf ("file %s was added on branch %s on %d-%02d-%02d %02d:%02d:%02d +0000",
2260 ct->tm_year + (ct->tm_year < 100 ? 0 : 1900),
2261 ct->tm_mon + 1, ct->tm_mday,
2262 ct->tm_hour, ct->tm_min, ct->tm_sec);
2264 /* commit a dead revision. */
2265 revnum = RCS_whatbranch (rcs, tag);
2266 retcode = RCS_checkin (rcs, NULL, NULL, tmp, revnum, headtime,
2275 error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
2276 "could not created dead stub %s for %s", tag,
2281 /* put the new file back where it was */
2282 rename_file (fname, file);
2285 /* double-check that the file was written correctly */
2287 rcs = RCS_parse (file, repository);
2290 error (0, 0, "could not read %s", rcs->path);
2298 /* lock the branch. (stubbed branches need not be locked.) */
2299 if (lock_RCS (file, rcs, NULL, repository))
2301 error (0, 0, "cannot lock head revision in `%s'.", rcs->path);
2306 if (*rcsnode != rcs)
2308 freercsnode (rcsnode);
2313 fileattr_newfile (file);
2315 /* At this point, we used to set the file mode of the RCS file
2316 based on the mode of the file in the working directory. If we
2317 are creating the RCS file for the first time, add_rcs_file does
2318 this already. If we are re-adding the file, then perhaps it is
2319 consistent to preserve the old file mode, just as we preserve
2320 the old keyword expansion mode.
2322 If we decide that we should change the modes, then we can't do
2323 it here anyhow. At this point, the RCS file may be owned by
2324 somebody else, so a chmod will fail. We need to instead do the
2325 chmod after rewriting it.
2327 FIXME: In general, I think the file mode (and the keyword
2328 expansion mode) should be associated with a particular revision
2329 of the file, so that it is possible to have different revisions
2330 of a file have different modes. */
2335 if (retval != 0 && SIG_inCrSect ())
2343 * Attempt to place a lock on the RCS file; returns 0 if it could and 1 if it
2344 * couldn't. If the RCS file currently has a branch as the head, we must
2345 * move the head back to the trunk before locking the file, and be sure to
2346 * put the branch back as the head if there are any errors.
2349 lock_RCS (const char *user, RCSNode *rcs, const char *rev,
2350 const char *repository)
2352 char *branch = NULL;
2356 * For a specified, numeric revision of the form "1" or "1.1", (or when
2357 * no revision is specified ""), definitely move the branch to the trunk
2358 * before locking the RCS file.
2360 * The assumption is that if there is more than one revision on the trunk,
2361 * the head points to the trunk, not a branch... and as such, it's not
2362 * necessary to move the head in this case.
2365 || (rev && isdigit ((unsigned char) *rev) && numdots (rev) < 2))
2367 branch = xstrdup (rcs->branch);
2370 if (RCS_setbranch (rcs, NULL) != 0)
2372 error (0, 0, "cannot change branch to default for %s",
2379 err = RCS_lock (rcs, NULL, 1);
2383 RCS_lock (rcs, rev, 1);
2386 /* We used to call RCS_rewrite here, and that might seem
2387 appropriate in order to write out the locked revision
2388 information. However, such a call would actually serve no
2389 purpose. CVS locks will prevent any interference from other
2390 CVS processes. The comment above rcs_internal_lockfile
2391 explains that it is already unsafe to use RCS and CVS
2392 simultaneously. It follows that writing out the locked
2393 revision information here would add no additional security.
2395 If we ever do care about it, the proper fix is to create the
2396 RCS lock file before calling this function, and maintain it
2397 until the checkin is complete.
2399 The call to RCS_lock is still required at present, since in
2400 some cases RCS_checkin will determine which revision to check
2401 in by looking for a lock. FIXME: This is rather roundabout,
2402 and a more straightforward approach would probably be easier to
2407 if (sbranch != NULL)
2413 /* try to restore the branch if we can on error */
2415 fixbranch (rcs, branch);
2425 * free an UPDATE node's data
2428 update_delproc (Node *p)
2430 struct logfile_info *li = p->data;
2442 * Free the commit_info structure in p.
2445 ci_delproc (Node *p)
2447 struct commit_info *ci = p->data;
2459 * Free the commit_info structure in p.
2462 masterlist_delproc (Node *p)
2464 struct master_lists *ml = p->data;
2466 dellist (&ml->ulist);
2467 dellist (&ml->cilist);