diff options
author | 1996-10-18 04:18:46 +0000 | |
---|---|---|
committer | 1996-10-18 04:18:46 +0000 | |
commit | 7e4d5a85f91e22adbbb2241021e71287d24b0996 (patch) | |
tree | c0434cf3e92c0f93e6c3f461c97996cd81d53b06 /gnu/usr.bin/cvs/src/commit.c | |
parent | Missing files from import (diff) | |
download | wireguard-openbsd-7e4d5a85f91e22adbbb2241021e71287d24b0996.tar.xz wireguard-openbsd-7e4d5a85f91e22adbbb2241021e71287d24b0996.zip |
Integrate local changes
Diffstat (limited to 'gnu/usr.bin/cvs/src/commit.c')
-rw-r--r-- | gnu/usr.bin/cvs/src/commit.c | 736 |
1 files changed, 459 insertions, 277 deletions
diff --git a/gnu/usr.bin/cvs/src/commit.c b/gnu/usr.bin/cvs/src/commit.c index ac81790e934..5d9c804e9b3 100644 --- a/gnu/usr.bin/cvs/src/commit.c +++ b/gnu/usr.bin/cvs/src/commit.c @@ -14,34 +14,44 @@ * */ +#include <assert.h> #include "cvs.h" #include "getline.h" #include "edit.h" #include "fileattr.h" -static Dtype check_direntproc PROTO((char *dir, char *repos, char *update_dir)); -static int check_fileproc PROTO((struct file_info *finfo)); -static int check_filesdoneproc PROTO((int err, char *repos, char *update_dir)); +static Dtype check_direntproc PROTO ((void *callerdat, char *dir, + char *repos, char *update_dir, + List *entries)); +static int check_fileproc PROTO ((void *callerdat, struct file_info *finfo)); +static int check_filesdoneproc PROTO ((void *callerdat, int err, + char *repos, char *update_dir, + List *entries)); static int checkaddfile PROTO((char *file, char *repository, char *tag, char *options, RCSNode **rcsnode)); -static Dtype commit_direntproc PROTO((char *dir, char *repos, char *update_dir)); -static int commit_dirleaveproc PROTO((char *dir, int err, char *update_dir)); -static int commit_fileproc PROTO((struct file_info *finfo)); -static int commit_filesdoneproc PROTO((int err, char *repository, char *update_dir)); -static int finaladd PROTO((char *file, char *revision, char *tag, - char *options, char *update_dir, - char *repository, List *entries)); +static Dtype commit_direntproc PROTO ((void *callerdat, char *dir, + char *repos, char *update_dir, + List *entries)); +static int commit_dirleaveproc PROTO ((void *callerdat, char *dir, + int err, char *update_dir, + List *entries)); +static int commit_fileproc PROTO ((void *callerdat, struct file_info *finfo)); +static int commit_filesdoneproc PROTO ((void *callerdat, int err, + char *repository, char *update_dir, + List *entries)); +static int finaladd PROTO((struct file_info *finfo, char *revision, char *tag, + char *options)); static int findmaxrev PROTO((Node * p, void *closure)); -static int lock_RCS PROTO((char *user, char *rcs, char *rev, char *repository)); -static int lockrcsfile PROTO((char *file, char *repository, char *rev)); +static int lock_RCS PROTO((char *user, RCSNode *rcs, char *rev, + char *repository)); static int precommit_list_proc PROTO((Node * p, void *closure)); static int precommit_proc PROTO((char *repository, char *filter)); -static int remove_file PROTO((char *file, char *repository, char *tag, - char *message, List *entries, RCSNode *rcsnode)); +static int remove_file PROTO ((struct file_info *finfo, char *tag, + char *message)); static void fix_rcs_modes PROTO((char *rcs, char *user)); static void fixaddfile PROTO((char *file, char *repository)); -static void fixbranch PROTO((char *file, char *repository, char *branch)); -static void unlockrcs PROTO((char *file, char *repository)); +static void fixbranch PROTO((RCSNode *, char *branch)); +static void unlockrcs PROTO((RCSNode *rcs)); static void ci_delproc PROTO((Node *p)); static void masterlist_delproc PROTO((Node *p)); static void locate_rcs PROTO((char *file, char *repository, char *rcs)); @@ -85,37 +95,146 @@ static const char *const commit_usage[] = }; #ifdef CLIENT_SUPPORT +/* Identify a file which needs "? foo" or a Questionable request. */ +struct question { + /* The two fields for the Directory request. */ + char *dir; + char *repos; + + /* The file name. */ + char *file; + + struct question *next; +}; + struct find_data { List *ulist; int argc; char **argv; + + /* This is used from dirent to filesdone time, for each directory, + to make a list of files we have already seen. */ + List *ignlist; + + /* Linked list of files which need "? foo" or a Questionable request. */ + struct question *questionables; + + /* Only good within functions called from the filesdoneproc. Stores + the repository (pointer into storage managed by the recursion + processor. */ + char *repository; }; -/* Pass as a static until we get around to fixing start_recursion to - pass along a void * where we can stash it. */ -struct find_data *find_data_static; +static Dtype find_dirent_proc PROTO ((void *callerdat, char *dir, + char *repository, char *update_dir, + List *entries)); -static int find_fileproc PROTO ((struct file_info *finfo)); +static Dtype +find_dirent_proc (callerdat, dir, repository, update_dir, entries) + void *callerdat; + char *dir; + char *repository; + char *update_dir; + List *entries; +{ + struct find_data *find_data = (struct find_data *)callerdat; + + /* initialize the ignore list for this directory */ + find_data->ignlist = getlist (); + return R_PROCESS; +} + +/* Here as a static until we get around to fixing ignore_files to pass + it along as an argument. */ +static struct find_data *find_data_static; + +static void find_ignproc PROTO ((char *, char *)); + +static void +find_ignproc (file, dir) + char *file; + char *dir; +{ + struct question *p; + + p = (struct question *) xmalloc (sizeof (struct question)); + p->dir = xstrdup (dir); + p->repos = xstrdup (find_data_static->repository); + p->file = xstrdup (file); + p->next = find_data_static->questionables; + find_data_static->questionables = p; +} + +static int find_filesdoneproc PROTO ((void *callerdat, int err, + char *repository, char *update_dir, + List *entries)); + +static int +find_filesdoneproc (callerdat, err, repository, update_dir, entries) + void *callerdat; + int err; + char *repository; + char *update_dir; + List *entries; +{ + struct find_data *find_data = (struct find_data *)callerdat; + find_data->repository = repository; + + /* if this directory has an ignore list, process it then free it */ + if (find_data->ignlist) + { + find_data_static = find_data; + ignore_files (find_data->ignlist, entries, update_dir, find_ignproc); + dellist (&find_data->ignlist); + } + + find_data->repository = NULL; + + return err; +} + +static int find_fileproc PROTO ((void *callerdat, struct file_info *finfo)); /* Machinery to find out what is modified, added, and removed. It is possible this should be broken out into a new client_classify function; merging it with classify_file is almost sure to be a mess, though, because classify_file has all kinds of repository processing. */ static int -find_fileproc (finfo) +find_fileproc (callerdat, finfo) + void *callerdat; struct file_info *finfo; { Vers_TS *vers; enum classify_type status; Node *node; - struct find_data *args = find_data_static; + struct find_data *args = (struct find_data *)callerdat; + struct logfile_info *data; + struct file_info xfinfo; + + /* if this directory has an ignore list, add this file to it */ + if (args->ignlist) + { + Node *p; + + p = getnode (); + p->type = FILES; + p->key = xstrdup (finfo->file); + if (addnode (args->ignlist, p) != 0) + freenode (p); + } - vers = Version_TS ((char *)NULL, (char *)NULL, (char *)NULL, - (char *)NULL, - finfo->file, 0, 0, finfo->entries, (RCSNode *)NULL); + xfinfo = *finfo; + xfinfo.repository = NULL; + xfinfo.rcs = NULL; + + vers = Version_TS (&xfinfo, NULL, NULL, NULL, 0, 0); if (vers->ts_user == NULL && vers->vn_user != NULL && vers->vn_user[0] == '-') + /* FIXME: If vn_user is starts with "-" but ts_user is + non-NULL, what classify_file does is print "%s should be + removed and is still there". I'm not sure what it does + then. We probably should do the same. */ status = T_REMOVED; else if (vers->vn_user == NULL) { @@ -129,6 +248,9 @@ find_fileproc (finfo) else if (vers->ts_user != NULL && vers->vn_user != NULL && vers->vn_user[0] == '0') + /* FIXME: If vn_user is "0" but ts_user is NULL, what classify_file + does is print "new-born %s has disappeared" and removes the entry. + We probably should do the same. */ status = T_ADDED; else if (vers->ts_user != NULL && vers->ts_rcs != NULL @@ -146,13 +268,18 @@ find_fileproc (finfo) node = getnode (); node->key = xstrdup (finfo->fullname); + data = (struct logfile_info *) xmalloc (sizeof (struct logfile_info)); + data->type = status; + data->tag = xstrdup (vers->tag); + node->type = UPDATE; node->delproc = update_delproc; - node->data = (char *) status; + node->data = (char *) data; (void)addnode (args->ulist, node); ++args->argc; + freevers_ts (&vers); return 0; } @@ -270,7 +397,7 @@ commit (argc, argv) error (1, 0, "cannot specify both a message and a log file"); /* FIXME: Why is this binary? Needs more investigation. */ - if ((logfd = open (logfile, O_RDONLY | OPEN_BINARY)) < 0) + if ((logfd = CVS_OPEN (logfile, O_RDONLY | OPEN_BINARY)) < 0) error (1, errno, "cannot open log file %s", logfile); if (fstat(logfd, &statbuf) < 0) @@ -294,21 +421,25 @@ commit (argc, argv) ign_setup (); - /* Note that we don't do ignore file processing here, and we - don't call ignore_files. This means that we won't print "? - foo" for stray files. Sounds OK, the doc only promises - that update does that. */ find_args.ulist = getlist (); find_args.argc = 0; - find_data_static = &find_args; - err = start_recursion (find_fileproc, (FILESDONEPROC) NULL, - (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, - argc, argv, local, W_LOCAL, 0, 0, - (char *)NULL, 0, 0); + find_args.questionables = NULL; + find_args.ignlist = NULL; + find_args.repository = NULL; + + err = start_recursion (find_fileproc, find_filesdoneproc, + find_dirent_proc, (DIRLEAVEPROC) NULL, + (void *)&find_args, + argc, argv, local, W_LOCAL, 0, 0, + (char *)NULL, 0); if (err) error (1, 0, "correct above errors first!"); if (find_args.argc == 0) + /* Nothing to commit. Exit now without contacting the + server (note that this means that we won't print "? + foo" for files which merit it, because we don't know + what is in the CVSROOT/cvsignore file). */ return 0; /* Now we keep track of which files we actually are going to @@ -319,12 +450,16 @@ commit (argc, argv) find_args.argc = 0; walklist (find_args.ulist, copy_ulist, &find_args); - /* - * Do this before calling do_editor; don't ask for a log - * message if we can't talk to the server. But do it after we - * have made the checks that we can locally (to more quickly - * catch syntax errors, the case where no files are modified, - * added or removed, etc.). */ + /* Do this before calling do_editor; don't ask for a log + message if we can't talk to the server. But do it after we + have made the checks that we can locally (to more quickly + catch syntax errors, the case where no files are modified, + added or removed, etc.). + + On the other hand, calling start_server before do_editor + means that we chew up server resources the whole time that + the user has the editor open (hours or days if the user + forgets about it), which seems dubious. */ start_server (); /* @@ -337,6 +472,47 @@ commit (argc, argv) /* We always send some sort of message, even if empty. */ option_with_arg ("-m", message); + /* OK, now process all the questionable files we have been saving + up. */ + { + struct question *p; + struct question *q; + + p = find_args.questionables; + while (p != NULL) + { + if (ign_inhibit_server || !supported_request ("Questionable")) + { + cvs_output ("? ", 2); + if (p->dir[0] != '\0') + { + cvs_output (p->dir, 0); + cvs_output ("/", 1); + } + cvs_output (p->file, 0); + cvs_output ("\n", 1); + } + else + { + send_to_server ("Directory ", 0); + send_to_server (p->dir[0] == '\0' ? "." : p->dir, 0); + send_to_server ("\012", 1); + send_to_server (p->repos, 0); + send_to_server ("\012", 1); + + send_to_server ("Questionable ", 0); + send_to_server (p->file, 0); + send_to_server ("\012", 1); + } + free (p->dir); + free (p->repos); + free (p->file); + q = p->next; + free (p); + p = q; + } + } + if (local) send_arg("-l"); if (force_ci) @@ -378,9 +554,8 @@ commit (argc, argv) * Run the recursion processor to verify the files are all up-to-date */ err = start_recursion (check_fileproc, check_filesdoneproc, - check_direntproc, (DIRLEAVEPROC) NULL, argc, - argv, local, W_LOCAL, aflag, 0, (char *) NULL, 1, - 0); + check_direntproc, (DIRLEAVEPROC) NULL, NULL, argc, + argv, local, W_LOCAL, aflag, 0, (char *) NULL, 1); if (err) { lock_tree_cleanup (); @@ -392,9 +567,9 @@ commit (argc, argv) */ if (noexec == 0) err = start_recursion (commit_fileproc, commit_filesdoneproc, - commit_direntproc, commit_dirleaveproc, + commit_direntproc, commit_dirleaveproc, NULL, argc, argv, local, W_LOCAL, aflag, 0, - (char *) NULL, 1, 0); + (char *) NULL, 1); /* * Unlock all the dirs and clean up @@ -422,7 +597,8 @@ commit (argc, argv) */ /* ARGSUSED */ static int -check_fileproc (finfo) +check_fileproc (callerdat, finfo) + void *callerdat; struct file_info *finfo; { Ctype status; @@ -431,6 +607,7 @@ check_fileproc (finfo) List *ulist, *cilist; Vers_TS *vers; struct commit_info *ci; + struct logfile_info *li; int save_noexec, save_quiet, save_really_quiet; save_noexec = noexec; @@ -444,19 +621,16 @@ check_fileproc (finfo) /* If the tag is for the trunk, make sure we're at the head */ if (numdots (tag) < 2) { - status = Classify_File (finfo->file, (char *) NULL, (char *) NULL, - (char *) NULL, 1, aflag, finfo->repository, - finfo->entries, finfo->rcs, &vers, finfo->update_dir, 0); + status = Classify_File (finfo, (char *) NULL, (char *) NULL, + (char *) NULL, 1, aflag, &vers, 0); if (status == T_UPTODATE || status == T_MODIFIED || status == T_ADDED) { Ctype xstatus; freevers_ts (&vers); - xstatus = Classify_File (finfo->file, tag, (char *) NULL, - (char *) NULL, 1, aflag, finfo->repository, - finfo->entries, finfo->rcs, &vers, finfo->update_dir, - 0); + xstatus = Classify_File (finfo, tag, (char *) NULL, + (char *) NULL, 1, aflag, &vers, 0); if (xstatus == T_REMOVE_ENTRY) status = T_MODIFIED; else if (status == T_MODIFIED && xstatus == T_CONFLICT) @@ -479,19 +653,16 @@ check_fileproc (finfo) cp = strrchr (xtag, '.'); *cp = '\0'; } - status = Classify_File (finfo->file, xtag, (char *) NULL, - (char *) NULL, 1, aflag, finfo->repository, - finfo->entries, finfo->rcs, &vers, finfo->update_dir, 0); + status = Classify_File (finfo, xtag, (char *) NULL, + (char *) NULL, 1, aflag, &vers, 0); if ((status == T_REMOVE_ENTRY || status == T_CONFLICT) && (cp = strrchr (xtag, '.')) != NULL) { /* pluck one more dot off the revision */ *cp = '\0'; freevers_ts (&vers); - status = Classify_File (finfo->file, xtag, (char *) NULL, - (char *) NULL, 1, aflag, finfo->repository, - finfo->entries, finfo->rcs, &vers, finfo->update_dir, - 0); + status = Classify_File (finfo, xtag, (char *) NULL, + (char *) NULL, 1, aflag, &vers, 0); if (status == T_UPTODATE || status == T_REMOVE_ENTRY) status = T_MODIFIED; } @@ -502,9 +673,8 @@ check_fileproc (finfo) } } else - status = Classify_File (finfo->file, tag, (char *) NULL, (char *) NULL, - 1, 0, finfo->repository, finfo->entries, finfo->rcs, &vers, - finfo->update_dir, 0); + status = Classify_File (finfo, tag, (char *) NULL, (char *) NULL, + 1, 0, &vers, 0); noexec = save_noexec; quiet = save_quiet; really_quiet = save_really_quiet; @@ -538,7 +708,8 @@ check_fileproc (finfo) * - can't have a sticky tag that is not a branch * Also, * - if status is T_REMOVED, can't have a numeric tag - * - if status is T_ADDED, rcs file must not exist + * - if status is T_ADDED, rcs file must not exist unless on + * a branch * - if status is T_ADDED, can't have a non-trunk numeric rev * - if status is T_MODIFIED and a Conflict marker exists, don't * allow the commit if timestamp is identical or if we find @@ -632,18 +803,22 @@ check_fileproc (finfo) } if (status == T_ADDED) { - char rcs[PATH_MAX]; - - /* Don't look in the attic; if it exists there we will - move it back out in checkaddfile. */ - sprintf(rcs, "%s/%s%s", finfo->repository, finfo->file, RCSEXT); - if (isreadable (rcs)) + if (vers->tag == NULL) { - error (0, 0, - "cannot add file `%s' when RCS file `%s' already exists", - finfo->fullname, rcs); - freevers_ts (&vers); - return (1); + char rcs[PATH_MAX]; + + /* Don't look in the attic; if it exists there we + will move it back out in checkaddfile. */ + sprintf(rcs, "%s/%s%s", finfo->repository, finfo->file, + RCSEXT); + if (isreadable (rcs)) + { + error (0, 0, + "cannot add file `%s' when RCS file `%s' already exists", + finfo->fullname, rcs); + freevers_ts (&vers); + return (1); + } } if (vers->tag && isdigit (*vers->tag) && numdots (vers->tag) > 1) @@ -689,7 +864,11 @@ check_fileproc (finfo) p->key = xstrdup (finfo->file); p->type = UPDATE; p->delproc = update_delproc; - p->data = (char *) status; + li = ((struct logfile_info *) + xmalloc (sizeof (struct logfile_info))); + li->type = status; + li->tag = xstrdup (vers->tag); + p->data = (char *) li; (void) addnode (ulist, p); p = getnode (); @@ -730,10 +909,12 @@ check_fileproc (finfo) */ /* ARGSUSED */ static Dtype -check_direntproc (dir, repos, update_dir) +check_direntproc (callerdat, dir, repos, update_dir, entries) + void *callerdat; char *dir; char *repos; char *update_dir; + List *entries; { if (!quiet) error (0, 0, "Examining %s", update_dir); @@ -749,8 +930,12 @@ precommit_list_proc (p, closure) Node *p; void *closure; { - if (p->data == (char *) T_ADDED || p->data == (char *) T_MODIFIED || - p->data == (char *) T_REMOVED) + struct logfile_info *li; + + li = (struct logfile_info *) p->data; + if (li->type == T_ADDED + || li->type == T_MODIFIED + || li->type == T_REMOVED) { run_arg (p->key); } @@ -797,10 +982,12 @@ precommit_proc (repository, filter) */ /* ARGSUSED */ static int -check_filesdoneproc (err, repos, update_dir) +check_filesdoneproc (callerdat, err, repos, update_dir, entries) + void *callerdat; int err; char *repos; char *update_dir; + List *entries; { int n; Node *p; @@ -834,14 +1021,14 @@ static char sbranch[PATH_MAX]; /* ARGSUSED */ static int -commit_fileproc (finfo) +commit_fileproc (callerdat, finfo) + void *callerdat; struct file_info *finfo; { Node *p; int err = 0; List *ulist, *cilist; struct commit_info *ci; - char rcs[PATH_MAX]; if (finfo->update_dir[0] == '\0') p = findnode (mulist, "."); @@ -875,9 +1062,12 @@ commit_fileproc (finfo) ci = (struct commit_info *) p->data; if (ci->status == T_MODIFIED) { - if (lockrcsfile (finfo->file, finfo->repository, ci->rev) != 0) + if (finfo->rcs == NULL) + error (1, 0, "internal error: no parsed RCS file"); + if (lock_RCS (finfo->file, finfo->rcs, ci->rev, + finfo->repository) != 0) { - unlockrcs (finfo->file, finfo->repository); + unlockrcs (finfo->rcs); err = 1; goto out; } @@ -896,15 +1086,17 @@ commit_fileproc (finfo) Since the branch test was done in check_fileproc for modified files, we need to stub it in again here. */ - if (ci->tag) { - locate_rcs (finfo->file, finfo->repository, rcs); + if (ci->tag) + { + if (finfo->rcs == NULL) + error (1, 0, "internal error: no parsed RCS file"); ci->rev = RCS_whatbranch (finfo->rcs, ci->tag); - err = Checkin ('A', finfo->file, finfo->update_dir, finfo->repository, rcs, ci->rev, - ci->tag, ci->options, message, finfo->entries); + err = Checkin ('A', finfo, finfo->rcs->path, ci->rev, + ci->tag, ci->options, message); if (err != 0) { - unlockrcs (finfo->file, finfo->repository); - fixbranch (finfo->file, finfo->repository, sbranch); + unlockrcs (finfo->rcs); + fixbranch (finfo->rcs, sbranch); } (void) time (&last_register_time); @@ -932,36 +1124,37 @@ commit_fileproc (finfo) } /* XXX - an added file with symbolic -r should add tag as well */ - err = finaladd (finfo->file, ci->rev ? ci->rev : xrev, ci->tag, ci->options, - finfo->update_dir, finfo->repository, finfo->entries); + err = finaladd (finfo, ci->rev ? ci->rev : xrev, ci->tag, ci->options); if (xrev) free (xrev); } else if (ci->status == T_MODIFIED) { - locate_rcs (finfo->file, finfo->repository, rcs); - err = Checkin ('M', finfo->file, finfo->update_dir, finfo->repository, - rcs, ci->rev, ci->tag, - ci->options, message, finfo->entries); + err = Checkin ('M', finfo, + finfo->rcs->path, ci->rev, ci->tag, + ci->options, message); (void) time (&last_register_time); if (err != 0) { - unlockrcs (finfo->file, finfo->repository); - fixbranch (finfo->file, finfo->repository, sbranch); + unlockrcs (finfo->rcs); + fixbranch (finfo->rcs, sbranch); } } else if (ci->status == T_REMOVED) { - err = remove_file (finfo->file, finfo->repository, ci->tag, message, - finfo->entries, finfo->rcs); + err = remove_file (finfo, ci->tag, message); #ifdef SERVER_SUPPORT if (server_active) { server_scratch_entry_only (); - server_updated (finfo->file, finfo->update_dir, finfo->repository, + server_updated (finfo, + NULL, + /* Doesn't matter, it won't get checked. */ - SERVER_UPDATED, (struct stat *) NULL, + SERVER_UPDATED, + + (struct stat *) NULL, (unsigned char *) NULL); } #endif @@ -988,12 +1181,13 @@ out: */ /* ARGSUSED */ static int -commit_filesdoneproc (err, repository, update_dir) +commit_filesdoneproc (callerdat, err, repository, update_dir, entries) + void *callerdat; int err; char *repository; char *update_dir; + List *entries; { - char *xtag = (char *) NULL; Node *p; List *ulist; @@ -1005,21 +1199,17 @@ commit_filesdoneproc (err, repository, update_dir) got_message = 0; - /* see if we need to specify a per-directory or -r option tag */ - if (tag == NULL) - ParseTag (&xtag, (char **) NULL); - Update_Logfile (repository, message, tag ? tag : xtag, (FILE *) 0, ulist); - if (xtag) - free (xtag); + Update_Logfile (repository, message, (FILE *) 0, ulist); /* Build the administrative files if necessary. */ { char *p; - if (strncmp (CVSroot, repository, strlen (CVSroot)) != 0) - error (0, 0, "internal error: repository doesn't begin with root"); - p = repository + strlen (CVSroot); + if (strncmp (CVSroot_directory, repository, + strlen (CVSroot_directory)) != 0) + error (0, 0, "internal error: repository (%s) doesn't begin with root (%s)", repository, CVSroot_directory); + p = repository + strlen (CVSroot_directory); if (*p == '/') ++p; if (strcmp ("CVSROOT", p) == 0) @@ -1042,7 +1232,7 @@ commit_filesdoneproc (err, repository, update_dir) { FILE *fp; - if ((fp = fopen (CVSADM_CIPROG, "r")) != NULL) + if ((fp = CVS_FOPEN (CVSADM_CIPROG, "r")) != NULL) { char *line; int line_length; @@ -1092,10 +1282,12 @@ commit_filesdoneproc (err, repository, update_dir) */ /* ARGSUSED */ static Dtype -commit_direntproc (dir, repos, update_dir) +commit_direntproc (callerdat, dir, repos, update_dir, entries) + void *callerdat; char *dir; char *repos; char *update_dir; + List *entries; { Node *p; List *ulist; @@ -1132,10 +1324,12 @@ commit_direntproc (dir, repos, update_dir) */ /* ARGSUSED */ static int -commit_dirleaveproc (dir, err, update_dir) +commit_dirleaveproc (callerdat, dir, err, update_dir, entries) + void *callerdat; char *dir; int err; char *update_dir; + List *entries; { /* update the per-directory tag info */ if (err == 0 && write_dirtag != NULL) @@ -1164,6 +1358,8 @@ findmaxrev (p, closure) Entnode *entdata; entdata = (Entnode *) p->data; + if (entdata->type != ENT_FILE) + return (0); cp = strchr (entdata->version, '.'); if (cp != NULL) *cp = '\0'; @@ -1182,17 +1378,13 @@ findmaxrev (p, closure) * link to keep it relative after we move it into the attic. */ static int -remove_file (file, repository, tag, message, entries, rcsnode) - char *file; - char *repository; +remove_file (finfo, tag, message) + struct file_info *finfo; char *tag; char *message; - List *entries; - RCSNode *rcsnode; { mode_t omask; int retcode; - char rcs[PATH_MAX]; char *tmp; int branch; @@ -1200,6 +1392,7 @@ remove_file (file, repository, tag, message, entries, rcsnode) char *corev; char *rev; char *prev_rev; + char *old_path; corev = NULL; rev = NULL; @@ -1207,20 +1400,22 @@ remove_file (file, repository, tag, message, entries, rcsnode) retcode = 0; - locate_rcs (file, repository, rcs); + if (finfo->rcs == NULL) + error (1, 0, "internal error: no parsed RCS file"); branch = 0; - if (tag && !(branch = RCS_isbranch (rcsnode, tag))) + if (tag && !(branch = RCS_isbranch (finfo->rcs, tag))) { /* a symbolic tag is specified; just remove the tag from the file */ - if ((retcode = RCS_deltag (rcs, tag, 1)) != 0) + if ((retcode = RCS_deltag (finfo->rcs, tag, 1)) != 0) { if (!quiet) error (0, retcode == -1 ? errno : 0, - "failed to remove tag `%s' from `%s'", tag, rcs); + "failed to remove tag `%s' from `%s'", tag, + finfo->fullname); return (1); } - Scratch_Entry (entries, file); + Scratch_Entry (finfo->entries, finfo->file); return (0); } @@ -1228,32 +1423,27 @@ remove_file (file, repository, tag, message, entries, rcsnode) /* commit a new, dead revision. */ /* Print message indicating that file is going to be removed. */ - (void) printf ("Removing %s;\n", file); + (void) printf ("Removing %s;\n", finfo->fullname); rev = NULL; - lockflag = RCS_FLAGS_LOCK; + lockflag = 1; if (branch) { char *branchname; - rev = RCS_whatbranch (rcsnode, tag); + rev = RCS_whatbranch (finfo->rcs, tag); if (rev == NULL) { error (0, 0, "cannot find branch \"%s\".", tag); return (1); } - if (rcsnode == NULL) - { - error (0, 0, "boy, I'm confused."); - return (1); - } - branchname = RCS_getbranch (rcsnode, rev, 1); + branchname = RCS_getbranch (finfo->rcs, rev, 1); if (branchname == NULL) { /* no revision exists on this branch. use the previous revision but do not lock. */ - corev = RCS_gettag (rcsnode, tag, 1, 0); + corev = RCS_gettag (finfo->rcs, tag, 1, (int *) NULL); prev_rev = xstrdup(rev); lockflag = 0; } else @@ -1265,24 +1455,18 @@ remove_file (file, repository, tag, message, entries, rcsnode) } else /* Not a branch */ { - /* Get current head revision of file. */ - if (rcsnode == NULL) - { - error (0, 0, "could not find parsed rcsfile %s", file); - return (1); - } - prev_rev = RCS_head (rcsnode); + prev_rev = RCS_head (finfo->rcs); } /* if removing without a tag or a branch, then make sure the default branch is the trunk. */ if (!tag && !branch) { - if (RCS_setbranch (rcs, NULL) != 0) + if (RCS_setbranch (finfo->rcs, NULL) != 0) { error (0, 0, "cannot change branch to default for %s", - rcs); + finfo->fullname); return (1); } } @@ -1293,71 +1477,82 @@ remove_file (file, repository, tag, message, entries, rcsnode) temp directory which is the kludgy way in which server.c tells time_stamp that the file is no longer around. Remove it so we can create temp files with that name (ignore errors). */ - unlink_file (file); + unlink_file (finfo->file); } #endif /* check something out. Generally this is the head. If we have a - particular rev, then name it. except when creating a branch, - lock the rev we're checking out. */ - retcode = RCS_checkout (rcs, "", rev ? corev : NULL, NULL, RUN_TTY, - lockflag, 1); + particular rev, then name it. */ + retcode = RCS_checkout (finfo->rcs, finfo->file, rev ? corev : NULL, + (char *) NULL, (char *) NULL, RUN_TTY); if (retcode != 0) { if (!quiet) error (0, retcode == -1 ? errno : 0, - "failed to check out `%s'", rcs); + "failed to check out `%s'", finfo->fullname); return (1); } + /* Except when we are creating a branch, lock the revision so that + we can check in the new revision. */ + if (lockflag) + RCS_lock (finfo->rcs, rev ? corev : NULL, 0); + if (corev != NULL) free (corev); - retcode = RCS_checkin (rcs, NULL, message, rev, RCS_FLAGS_DEAD, 1); + retcode = RCS_checkin (finfo->rcs->path, finfo->file, message, rev, + RCS_FLAGS_DEAD | RCS_FLAGS_QUIET); if (retcode != 0) { if (!quiet) error (0, retcode == -1 ? errno : 0, - "failed to commit dead revision for `%s'", rcs); + "failed to commit dead revision for `%s'", finfo->fullname); return (1); } if (rev != NULL) free (rev); + old_path = finfo->rcs->path; if (!branch) { /* this was the head; really move it into the Attic */ - tmp = xmalloc(strlen(repository) + + tmp = xmalloc(strlen(finfo->repository) + sizeof('/') + sizeof(CVSATTIC) + sizeof('/') + - strlen(file) + + strlen(finfo->file) + sizeof(RCSEXT) + 1); - (void) sprintf (tmp, "%s/%s", repository, CVSATTIC); + (void) sprintf (tmp, "%s/%s", finfo->repository, CVSATTIC); omask = umask (cvsumask); (void) CVS_MKDIR (tmp, 0777); (void) umask (omask); - (void) sprintf (tmp, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT); + (void) sprintf (tmp, "%s/%s/%s%s", finfo->repository, CVSATTIC, finfo->file, RCSEXT); - if (strcmp (rcs, tmp) != 0 - && rename (rcs, tmp) == -1 - && (isreadable (rcs) || !isreadable (tmp))) + if (strcmp (finfo->rcs->path, tmp) != 0 + && CVS_RENAME (finfo->rcs->path, tmp) == -1 + && (isreadable (finfo->rcs->path) || !isreadable (tmp))) { free(tmp); return (1); } - free(tmp); + /* The old value of finfo->rcs->path is in old_path, and is + freed below. */ + finfo->rcs->path = tmp; } /* Print message that file was removed. */ - (void) printf ("%s <-- %s\n", rcs, file); + (void) printf ("%s <-- %s\n", old_path, finfo->file); (void) printf ("new revision: delete; "); (void) printf ("previous revision: %s\n", prev_rev); (void) printf ("done\n"); free(prev_rev); - Scratch_Entry (entries, file); + if (old_path != finfo->rcs->path) + free (old_path); + + Scratch_Entry (finfo->entries, finfo->file); return (0); } @@ -1365,29 +1560,25 @@ remove_file (file, repository, tag, message, entries, rcsnode) * Do the actual checkin for added files */ static int -finaladd (file, rev, tag, options, update_dir, repository, entries) - char *file; +finaladd (finfo, rev, tag, options) + struct file_info *finfo; char *rev; char *tag; char *options; - char *update_dir; - char *repository; - List *entries; { int ret; char tmp[PATH_MAX]; char rcs[PATH_MAX]; - locate_rcs (file, repository, rcs); - ret = Checkin ('A', file, update_dir, repository, rcs, rev, tag, options, - message, entries); + locate_rcs (finfo->file, finfo->repository, rcs); + ret = Checkin ('A', finfo, rcs, rev, tag, options, message); if (ret == 0) { - (void) sprintf (tmp, "%s/%s%s", CVSADM, file, CVSEXT_LOG); + (void) sprintf (tmp, "%s/%s%s", CVSADM, finfo->file, CVSEXT_LOG); (void) unlink_file (tmp); } else - fixaddfile (file, repository); + fixaddfile (finfo->file, finfo->repository); (void) time (&last_register_time); @@ -1398,18 +1589,14 @@ finaladd (file, rev, tag, options, update_dir, repository, entries) * Unlock an rcs file */ static void -unlockrcs (file, repository) - char *file; - char *repository; +unlockrcs (rcs) + RCSNode *rcs; { - char rcs[PATH_MAX]; - int retcode = 0; - - locate_rcs (file, repository, rcs); + int retcode; if ((retcode = RCS_unlock (rcs, NULL, 0)) != 0) error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0, - "could not unlock %s", rcs); + "could not unlock %s", rcs->path); } /* @@ -1438,20 +1625,17 @@ fixaddfile (file, repository) * put the branch back on an rcs file */ static void -fixbranch (file, repository, branch) - char *file; - char *repository; +fixbranch (rcs, branch) + RCSNode *rcs; char *branch; { - char rcs[PATH_MAX]; - int retcode = 0; + int retcode; if (branch != NULL && branch[0] != '\0') { - locate_rcs (file, repository, rcs); if ((retcode = RCS_setbranch (rcs, branch)) != 0) error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0, - "cannot restore branch to %s for %s", branch, rcs); + "cannot restore branch to %s for %s", branch, rcs->path); } } @@ -1474,15 +1658,21 @@ checkaddfile (file, repository, tag, options, rcsnode) mode_t omask; int retcode = 0; int newfile = 0; + RCSNode *rcsfile = NULL; if (tag) { - (void) sprintf(rcs, "%s/%s", repository, CVSATTIC); - omask = umask (cvsumask); - if (CVS_MKDIR (rcs, 0777) != 0 && errno != EEXIST) - error (1, errno, "cannot make directory `%s'", rcs);; - (void) umask (omask); - (void) sprintf (rcs, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT); + (void) sprintf (rcs, "%s/%s%s", repository, file, RCSEXT); + if (! isreadable (rcs)) + { + (void) sprintf(rcs, "%s/%s", repository, CVSATTIC); + omask = umask (cvsumask); + if (CVS_MKDIR (rcs, 0777) != 0 && errno != EEXIST) + error (1, errno, "cannot make directory `%s'", rcs);; + (void) umask (omask); + (void) sprintf (rcs, "%s/%s/%s%s", repository, CVSATTIC, file, + RCSEXT); + } } else locate_rcs (file, repository, rcs); @@ -1492,7 +1682,12 @@ checkaddfile (file, repository, tag, options, rcsnode) /* file has existed in the past. Prepare to resurrect. */ char oldfile[PATH_MAX]; char *rev; - RCSNode *rcsfile; + + if ((rcsfile = *rcsnode) == NULL) + { + error (0, 0, "could not find parsed rcsfile %s", file); + return (1); + } if (tag == NULL) { @@ -1502,7 +1697,7 @@ checkaddfile (file, repository, tag, options, rcsnode) sprintf (rcs, "%s/%s%s", repository, file, RCSEXT); if (strcmp (oldfile, rcs) == 0 - || rename (oldfile, rcs) != 0 + || CVS_RENAME (oldfile, rcs) != 0 || isreadable (oldfile) || !isreadable (rcs)) { @@ -1510,17 +1705,13 @@ checkaddfile (file, repository, tag, options, rcsnode) file); return (1); } + free (rcsfile->path); + rcsfile->path = xstrdup (rcs); } - if ((rcsfile = *rcsnode) == NULL) - { - error (0, 0, "could not find parsed rcsfile %s", file); - return (1); - } - - rev = RCS_getversion (rcsfile, tag, NULL, 1, 0); + rev = RCS_getversion (rcsfile, tag, NULL, 1, (int *) NULL); /* and lock it */ - if (lock_RCS (file, rcs, rev, repository)) { + if (lock_RCS (file, rcsfile, rev, repository)) { error (0, 0, "cannot lock `%s'.", rcs); free (rev); return (1); @@ -1567,7 +1758,7 @@ checkaddfile (file, repository, tag, options, rcsnode) (void) sprintf (tmp, "file %s was initially added on branch %s.", file, tag); retcode = RCS_checkin (rcs, NULL, tmp, NULL, - RCS_FLAGS_DEAD | RCS_FLAGS_QUIET, 0); + RCS_FLAGS_DEAD | RCS_FLAGS_QUIET); free (tmp); if (retcode != 0) { @@ -1578,9 +1769,22 @@ checkaddfile (file, repository, tag, options, rcsnode) /* put the new file back where it was */ rename_file (fname, file); - + + assert (rcsfile == NULL); + rcsfile = RCS_parse (file, repository); + if (rcsfile == NULL) + { + error (0, 0, "could not read %s", rcs); + return (1); + } + if (rcsnode != NULL) + { + assert (*rcsnode == NULL); + *rcsnode = rcsfile; + } + /* and lock it once again. */ - if (lock_RCS (file, rcs, NULL, repository)) { + if (lock_RCS (file, rcsfile, NULL, repository)) { error (0, 0, "cannot lock `%s'.", rcs); return (1); } @@ -1590,54 +1794,56 @@ checkaddfile (file, repository, tag, options, rcsnode) { /* when adding with a tag, we need to stub a branch, if it doesn't already exist. */ - RCSNode *rcsfile; - rcsfile = RCS_parse (file, repository); if (rcsfile == NULL) { - error (0, 0, "could not read %s", rcs); - return (1); + if (rcsnode != NULL && *rcsnode != NULL) + rcsfile = *rcsnode; + else + { + rcsfile = RCS_parse (file, repository); + if (rcsfile == NULL) + { + error (0, 0, "could not read %s", rcs); + return (1); + } + } } - + if (!RCS_nodeisbranch (rcsfile, tag)) { /* branch does not exist. Stub it. */ char *head; char *magicrev; - head = RCS_getversion (rcsfile, NULL, NULL, 0, 0); + head = RCS_getversion (rcsfile, NULL, NULL, 0, (int *) NULL); magicrev = RCS_magicrev (rcsfile, head); - if ((retcode = RCS_settag(rcs, tag, magicrev)) != 0) + + retcode = RCS_settag (rcsfile, tag, magicrev); + + free (head); + free (magicrev); + + if (retcode != 0) { error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0, "could not stub branch %s for %s", tag, rcs); return (1); } - - freercsnode (&rcsfile); - - /* reparse the file, then add it to our list. */ - rcsfile = RCS_parse (file, repository); - if (rcsfile == NULL) - { - error (0, 0, "could not reparse %s", rcs); - return (1); - } - - free (head); - free (magicrev); } else { /* lock the branch. (stubbed branches need not be locked.) */ - if (lock_RCS (file, rcs, NULL, repository)) { + if (lock_RCS (file, rcsfile, NULL, repository)) { error (0, 0, "cannot lock `%s'.", rcs); return (1); } } - if (rcsnode) - freercsnode(rcsnode); - *rcsnode = rcsfile; + if (rcsnode && *rcsnode != rcsfile) + { + freercsnode(rcsnode); + *rcsnode = rcsfile; + } } fileattr_newfile (file); @@ -1647,24 +1853,6 @@ checkaddfile (file, repository, tag, options, rcsnode) } /* - * Lock the rcs file ``file'' - */ -static int -lockrcsfile (file, repository, rev) - char *file; - char *repository; - char *rev; -{ - char rcs[PATH_MAX]; - - locate_rcs (file, repository, rcs); - if (lock_RCS (file, rcs, rev, repository) != 0) - return (1); - else - return (0); -} - -/* * Attempt to place a lock on the RCS file; returns 0 if it could and 1 if it * couldn't. If the RCS file currently has a branch as the head, we must * move the head back to the trunk before locking the file, and be sure to @@ -1673,11 +1861,10 @@ lockrcsfile (file, repository, rev) static int lock_RCS (user, rcs, rev, repository) char *user; - char *rcs; + RCSNode *rcs; char *rev; char *repository; { - RCSNode *rcsfile; char *branch = NULL; int err = 0; @@ -1692,29 +1879,19 @@ lock_RCS (user, rcs, rev, repository) */ if (rev == NULL || (rev && isdigit (*rev) && numdots (rev) < 2)) { - if ((rcsfile = RCS_parsercsfile (rcs)) == NULL) - { - /* invalid rcs file? */ - err = 1; - } - else + branch = xstrdup (rcs->branch); + if (branch != NULL) { - /* rcsfile is valid */ - branch = xstrdup (rcsfile->branch); - freercsnode (&rcsfile); - if (branch != NULL) + if (RCS_setbranch (rcs, NULL) != 0) { - if (RCS_setbranch (rcs, NULL) != 0) - { - error (0, 0, "cannot change branch to default for %s", - rcs); - if (branch) - free (branch); - return (1); - } + error (0, 0, "cannot change branch to default for %s", + rcs->path); + if (branch) + free (branch); + return (1); } - err = RCS_lock(rcs, NULL, 0); } + err = RCS_lock(rcs, NULL, 0); } else { @@ -1735,7 +1912,7 @@ lock_RCS (user, rcs, rev, repository) /* try to restore the branch if we can on error */ if (branch != NULL) - fixbranch (user, repository, branch); + fixbranch (rcs, branch); if (branch) free (branch); @@ -1757,18 +1934,23 @@ fix_rcs_modes (rcs, user) { struct stat sb; - if (stat (user, &sb) != -1) + if ( CVS_STAT (user, &sb) != -1) (void) chmod (rcs, (int) sb.st_mode & ~0222); } /* - * free an UPDATE node's data (really nothing to do) + * free an UPDATE node's data */ void update_delproc (p) Node *p; { - p->data = (char *) NULL; + struct logfile_info *li; + + li = (struct logfile_info *) p->data; + if (li->tag) + free (li->tag); + free (li); } /* |