diff options
Diffstat (limited to 'contrib/cvs/src/commit.c')
-rw-r--r-- | contrib/cvs/src/commit.c | 709 |
1 files changed, 330 insertions, 379 deletions
diff --git a/contrib/cvs/src/commit.c b/contrib/cvs/src/commit.c index 0d19d31..1548045 100644 --- a/contrib/cvs/src/commit.c +++ b/contrib/cvs/src/commit.c @@ -21,40 +21,44 @@ #include "fileattr.h" #include "hardlink.h" -static Dtype check_direntproc PROTO ((void *callerdat, char *dir, - char *repos, char *update_dir, - List *entries)); +static Dtype check_direntproc PROTO ((void *callerdat, const char *dir, + const char *repos, + const 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 ((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)); + const char *repos, + const char *update_dir, + List *entries)); +static int checkaddfile PROTO((const char *file, const char *repository, + const char *tag, const char *options, + RCSNode **rcsnode)); +static Dtype commit_direntproc PROTO ((void *callerdat, const char *dir, + const char *repos, + const char *update_dir, + List *entries)); +static int commit_dirleaveproc PROTO ((void *callerdat, const char *dir, + int err, const 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)); + const char *repository, + const 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, RCSNode *rcs, char *rev, - char *repository)); +static int lock_RCS PROTO((const char *user, RCSNode *rcs, const char *rev, + const char *repository)); static int precommit_list_proc PROTO((Node * p, void *closure)); -static int precommit_proc PROTO((char *repository, char *filter)); +static int precommit_proc PROTO((const char *repository, const char *filter)); static int remove_file PROTO ((struct file_info *finfo, char *tag, char *message)); -static void fixaddfile PROTO((char *file, char *repository)); +static void fixaddfile PROTO((const char *rcs)); 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 char *locate_rcs PROTO((char *file, char *repository)); struct commit_info { @@ -71,7 +75,6 @@ struct master_lists static int force_ci = 0; static int got_message; -static int run_module_prog = 1; static int aflag; static char *saved_tag; static char *write_dirtag; @@ -84,8 +87,7 @@ static time_t last_register_time; static const char *const commit_usage[] = { - "Usage: %s %s [-nRlf] [-m msg | -F logfile] [-r rev] files...\n", - " -n Do not run the module program (if any).\n", + "Usage: %s %s [-Rlf] [-m msg | -F logfile] [-r rev] files...\n", " -R Process directories recursively.\n", " -l Local directory only (not recursive).\n", " -f Force the file to be committed; disables recursion.\n", @@ -124,23 +126,26 @@ struct find_data { /* Only good within functions called from the filesdoneproc. Stores the repository (pointer into storage managed by the recursion processor. */ - char *repository; + const char *repository; /* Non-zero if we should force the commit. This is enabled by either -f or -r options, unlike force_ci which is just -f. */ int force; }; -static Dtype find_dirent_proc PROTO ((void *callerdat, char *dir, - char *repository, char *update_dir, - List *entries)); + + +static Dtype find_dirent_proc PROTO ((void *callerdat, const char *dir, + const char *repository, + const char *update_dir, + List *entries)); static Dtype find_dirent_proc (callerdat, dir, repository, update_dir, entries) void *callerdat; - char *dir; - char *repository; - char *update_dir; + const char *dir; + const char *repository; + const char *update_dir; List *entries; { struct find_data *find_data = (struct find_data *)callerdat; @@ -164,16 +169,20 @@ find_dirent_proc (callerdat, dir, repository, update_dir, entries) 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 PROTO ((const char *, const char *)); static void find_ignproc (file, dir) - char *file; - char *dir; + const char *file; + const char *dir; { struct question *p; @@ -185,16 +194,19 @@ find_ignproc (file, dir) find_data_static->questionables = p; } + + static int find_filesdoneproc PROTO ((void *callerdat, int err, - char *repository, char *update_dir, - List *entries)); + const char *repository, + const char *update_dir, + List *entries)); static int find_filesdoneproc (callerdat, err, repository, update_dir, entries) void *callerdat; int err; - char *repository; - char *update_dir; + const char *repository; + const char *update_dir; List *entries; { struct find_data *find_data = (struct find_data *)callerdat; @@ -258,27 +270,43 @@ find_fileproc (callerdat, finfo) freevers_ts (&vers); return 1; } - if (vers->ts_user == NULL) + if (vers->vn_user[0] == '-') + { + if (vers->ts_user != NULL) + { + error (0, 0, + "`%s' should be removed and is still there (or is back" + " again)", finfo->fullname); + freevers_ts (&vers); + return 1; + } + /* else */ + status = T_REMOVED; + } + else if (strcmp (vers->vn_user, "0") == 0) { - if (strcmp (vers->vn_user, "0") == 0) + if (vers->ts_user == NULL) + { /* This happens when one has `cvs add'ed a file, but it no longer exists in the working directory at commit time. FIXME: What classify_file does in this case is print "new-born %s has disappeared" and removes the entry. We probably should do the same. */ - status = T_ADDED; - else if (vers->vn_user[0] == '-') - status = T_REMOVED; - else - { - /* FIXME: What classify_file does in this case is print - "%s was lost". We probably should do the same. */ - freevers_ts (&vers); - return 0; + if (!really_quiet) + error (0, 0, "warning: new-born %s has disappeared", + finfo->fullname); + status = T_REMOVE_ENTRY; } + else + status = T_ADDED; + } + else if (vers->ts_user == NULL) + { + /* FIXME: What classify_file does in this case is print + "%s was lost". We probably should do the same. */ + freevers_ts (&vers); + return 0; } - else if (strcmp (vers->vn_user, "0") == 0) - status = T_ADDED; else if (vers->ts_rcs != NULL && (args->force || strcmp (vers->ts_user, vers->ts_rcs) != 0)) /* If we are forcing commits, pretend that the file is @@ -304,7 +332,7 @@ find_fileproc (callerdat, finfo) node->type = UPDATE; node->delproc = update_delproc; - node->data = (char *) data; + node->data = data; (void)addnode (args->ulist, node); ++args->argc; @@ -326,6 +354,11 @@ copy_ulist (node, data) } #endif /* CLIENT_SUPPORT */ +#ifdef SERVER_SUPPORT +# define COMMIT_OPTIONS "+nlRm:fF:r:" +#else /* !SERVER_SUPPORT */ +# define COMMIT_OPTIONS "+lRm:fF:r:" +#endif /* SERVER_SUPPORT */ int commit (argc, argv) int argc; @@ -364,13 +397,17 @@ commit (argc, argv) #endif /* CVS_BADROOT */ optind = 0; - while ((c = getopt (argc, argv, "+nlRm:fF:r:")) != -1) + while( ( c = getopt( argc, argv, COMMIT_OPTIONS ) ) != -1 ) { switch (c) { +#ifdef SERVER_SUPPORT case 'n': - run_module_prog = 0; + /* Silently ignore -n for compatibility with old + * clients. + */ break; +#endif /* SERVER_SUPPORT */ case 'm': #ifdef FORCE_USE_EDITOR use_editor = 1; @@ -425,7 +462,8 @@ commit (argc, argv) /* strip trailing dots and leading zeros */ while (*--p == '.') ; p[1] = '\0'; - while (*saved_tag == '0') ++saved_tag; + while (saved_tag[0] == '0' && isdigit ((unsigned char) saved_tag[1])) + ++saved_tag; } /* some checks related to the "-F logfile" option */ @@ -462,7 +500,7 @@ commit (argc, argv) find_dirent_proc, (DIRLEAVEPROC) NULL, (void *)&find_args, argc, argv, local, W_LOCAL, 0, CVS_LOCK_NONE, - (char *)NULL, 0); + (char *) NULL, 0, (char *) NULL); if (err) error (1, 0, "correct above errors first!"); @@ -551,8 +589,6 @@ commit (argc, argv) send_arg("-l"); if (force_ci) send_arg("-f"); - if (!run_module_prog) - send_arg("-n"); option_with_arg ("-r", saved_tag); send_arg ("--"); @@ -643,7 +679,7 @@ commit (argc, argv) err = start_recursion (check_fileproc, check_filesdoneproc, check_direntproc, (DIRLEAVEPROC) NULL, NULL, argc, argv, local, W_LOCAL, aflag, CVS_LOCK_NONE, - (char *) NULL, 1); + (char *) NULL, 1, (char *) NULL); if (err) { Lock_Cleanup (); @@ -658,7 +694,7 @@ commit (argc, argv) err = start_recursion (commit_fileproc, commit_filesdoneproc, commit_direntproc, commit_dirleaveproc, NULL, argc, argv, local, W_LOCAL, aflag, CVS_LOCK_NONE, - (char *) NULL, 1); + (char *) NULL, 1, (char *) NULL); /* * Unlock all the dirs and clean up @@ -778,7 +814,7 @@ check_fileproc (callerdat, finfo) struct file_info *finfo; { Ctype status; - char *xdir; + const char *xdir; Node *p; List *ulist, *cilist; Vers_TS *vers; @@ -832,7 +868,8 @@ check_fileproc (callerdat, finfo) * - can't have a sticky date * - 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_REMOVED, file must not exist and its entry + * can't have a numeric sticky tag. * - if status is T_ADDED, rcs file must not exist unless on * a branch or head is dead * - if status is T_ADDED, can't have a non-trunk numeric rev @@ -862,29 +899,13 @@ check_fileproc (callerdat, finfo) } if (status == T_MODIFIED && !force_ci && vers->ts_conflict) { - char *filestamp; - int retcode; - /* * We found a "conflict" marker. * * If the timestamp on the file is the same as the * timestamp stored in the Entries file, we block the commit. */ -#ifdef SERVER_SUPPORT - if (server_active) - retcode = vers->ts_conflict[0] != '='; - else { - filestamp = time_stamp (finfo->file); - retcode = strcmp (vers->ts_conflict, filestamp); - free (filestamp); - } -#else - filestamp = time_stamp (finfo->file); - retcode = strcmp (vers->ts_conflict, filestamp); - free (filestamp); -#endif - if (retcode == 0) + if ( file_has_conflict ( finfo, vers->ts_conflict ) ) { error (0, 0, "file `%s' had a conflict and has not been modified", @@ -912,20 +933,30 @@ warning: file `%s' seems to still contain conflict indicators", } } - if (status == T_REMOVED - && vers->tag - && isdigit ((unsigned char) *vers->tag)) + if (status == T_REMOVED) { - /* Remove also tries to forbid this, but we should check - here. I'm only _sure_ about somewhat obscure cases - (hacking the Entries file, using an old version of - CVS for the remove and a new one for the commit), but - there might be other cases. */ - error (0, 0, - "cannot remove file `%s' which has a numeric sticky tag of `%s'", - finfo->fullname, vers->tag); - freevers_ts (&vers); - return (1); + if (vers->ts_user != NULL) + { + error (0, 0, + "`%s' should be removed and is still there (or is" + " back again)", finfo->fullname); + freevers_ts (&vers); + return 1; + } + + if (vers->tag && isdigit ((unsigned char) *vers->tag)) + { + /* Remove also tries to forbid this, but we should check + here. I'm only _sure_ about somewhat obscure cases + (hacking the Entries file, using an old version of + CVS for the remove and a new one for the commit), but + there might be other cases. */ + error (0, 0, + "cannot remove file `%s' which has a numeric sticky" + " tag of `%s'", finfo->fullname, vers->tag); + freevers_ts (&vers); + return (1); + } } if (status == T_ADDED) { @@ -975,7 +1006,7 @@ warning: file `%s' seems to still contain conflict indicators", xmalloc (sizeof (struct master_lists)); ml->ulist = ulist; ml->cilist = cilist; - p->data = (char *) ml; + p->data = ml; p->delproc = masterlist_delproc; (void) addnode (mulist, p); } @@ -991,7 +1022,7 @@ warning: file `%s' seems to still contain conflict indicators", li->tag = xstrdup (vers->tag); li->rev_old = xstrdup (vers->vn_rcs); li->rev_new = NULL; - p->data = (char *) li; + p->data = li; (void) addnode (ulist, p); p = getnode (); @@ -1009,7 +1040,7 @@ warning: file `%s' seems to still contain conflict indicators", ci->rev = (char *) NULL; ci->tag = xstrdup (vers->tag); ci->options = xstrdup(vers->options); - p->data = (char *) ci; + p->data = ci; (void) addnode (cilist, p); #ifdef PRESERVE_PERMISSIONS_SUPPORT @@ -1042,7 +1073,7 @@ warning: file `%s' seems to still contain conflict indicators", hlinfo = (struct hardlink_info *) xmalloc (sizeof (struct hardlink_info)); hlinfo->status = status; - linkp->data = (char *) hlinfo; + linkp->data = hlinfo; } } #endif @@ -1063,6 +1094,8 @@ warning: file `%s' seems to still contain conflict indicators", return (0); } + + /* * By default, return the code that tells do_recursion to examine all * directories @@ -1071,9 +1104,9 @@ warning: file `%s' seems to still contain conflict indicators", static Dtype check_direntproc (callerdat, dir, repos, update_dir, entries) void *callerdat; - char *dir; - char *repos; - char *update_dir; + const char *dir; + const char *repos; + const char *update_dir; List *entries; { if (!isdir (dir)) @@ -1093,9 +1126,7 @@ precommit_list_proc (p, closure) Node *p; void *closure; { - struct logfile_info *li; - - li = (struct logfile_info *) p->data; + struct logfile_info *li = p->data; if (li->type == T_ADDED || li->type == T_MODIFIED || li->type == T_REMOVED) @@ -1110,8 +1141,8 @@ precommit_list_proc (p, closure) */ static int precommit_proc (repository, filter) - char *repository; - char *filter; + const char *repository; + const char *filter; { /* see if the filter is there, only if it's a full path */ if (isabsolute (filter)) @@ -1148,8 +1179,8 @@ static int check_filesdoneproc (callerdat, err, repos, update_dir, entries) void *callerdat; int err; - char *repos; - char *update_dir; + const char *repos; + const char *update_dir; List *entries; { int n; @@ -1244,7 +1275,7 @@ commit_fileproc (callerdat, finfo) if (p == NULL) return (0); - ci = (struct commit_info *) p->data; + ci = p->data; if (ci->status == T_MODIFIED) { if (finfo->rcs == NULL) @@ -1262,7 +1293,8 @@ commit_fileproc (callerdat, finfo) if (checkaddfile (finfo->file, finfo->repository, ci->tag, ci->options, &finfo->rcs) != 0) { - fixaddfile (finfo->file, finfo->repository); + if (finfo->rcs != NULL) + fixaddfile (finfo->rcs->path); err = 1; goto out; } @@ -1282,7 +1314,7 @@ commit_fileproc (callerdat, finfo) if (ci->rev) free (ci->rev); ci->rev = RCS_whatbranch (finfo->rcs, ci->tag); - err = Checkin ('A', finfo, finfo->rcs->path, ci->rev, + err = Checkin ('A', finfo, ci->rev, ci->tag, ci->options, saved_message); if (err != 0) { @@ -1327,8 +1359,7 @@ commit_fileproc (callerdat, finfo) } else if (ci->status == T_MODIFIED) { - err = Checkin ('M', finfo, - finfo->rcs->path, ci->rev, ci->tag, + err = Checkin ('M', finfo, ci->rev, ci->tag, ci->options, saved_message); (void) time (&last_register_time); @@ -1376,7 +1407,7 @@ out: copy it into the log information (see logmsg.c (logfile_write) for more details). We should only update the version number for files that have been added or - modified but not removed. Why? classify_file_internal + modified but not removed since classify_file_internal will return the version number of a file even after it has been removed from the archive, which is not the behavior we want for our commitlog messages; we want the old version @@ -1391,7 +1422,7 @@ out: struct logfile_info *li; (void) classify_file_internal (finfo, &vers); - li = (struct logfile_info *) p->data; + li = p->data; li->rev_new = xstrdup (vers->vn_rcs); freevers_ts (&vers); } @@ -1411,8 +1442,8 @@ static int commit_filesdoneproc (callerdat, err, repository, update_dir, entries) void *callerdat; int err; - char *repository; - char *update_dir; + const char *repository; + const char *update_dir; List *entries; { Node *p; @@ -1426,12 +1457,11 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries) got_message = 0; - Update_Logfile (repository, saved_message, (FILE *) 0, ulist); /* Build the administrative files if necessary. */ { - char *p; + const char *p; if (strncmp (current_parsed_root->directory, repository, strlen (current_parsed_root->directory)) != 0) @@ -1464,63 +1494,13 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries) cvs_output (program_name, 0); cvs_output (" ", 1); - cvs_output (command_name, 0); + cvs_output (cvs_cmd_name, 0); cvs_output (": Rebuilding administrative file database\n", 0); mkmodules (admin_dir); free (admin_dir); } } - if (err == 0 && run_module_prog) - { - FILE *fp; - - if ((fp = CVS_FOPEN (CVSADM_CIPROG, "r")) != NULL) - { - char *line; - int line_length; - size_t line_chars_allocated; - char *repos; - - line = NULL; - line_chars_allocated = 0; - line_length = getline (&line, &line_chars_allocated, fp); - if (line_length > 0) - { - /* Remove any trailing newline. */ - if (line[line_length - 1] == '\n') - line[--line_length] = '\0'; - repos = Name_Repository ((char *) NULL, update_dir); - run_setup (line); - run_arg (repos); - cvs_output (program_name, 0); - cvs_output (" ", 1); - cvs_output (command_name, 0); - cvs_output (": Executing '", 0); - run_print (stdout); - cvs_output ("'\n", 0); - cvs_flushout (); - (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); - free (repos); - } - else - { - if (ferror (fp)) - error (0, errno, "warning: error reading %s", - CVSADM_CIPROG); - } - if (line != NULL) - free (line); - if (fclose (fp) < 0) - error (0, errno, "warning: cannot close %s", CVSADM_CIPROG); - } - else - { - if (! existence_error (errno)) - error (0, errno, "warning: cannot open %s", CVSADM_CIPROG); - } - } - return (err); } @@ -1531,9 +1511,9 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries) static Dtype commit_direntproc (callerdat, dir, repos, update_dir, entries) void *callerdat; - char *dir; - char *repos; - char *update_dir; + const char *dir; + const char *repos; + const char *update_dir; List *entries; { Node *p; @@ -1575,9 +1555,9 @@ commit_direntproc (callerdat, dir, repos, update_dir, entries) static int commit_dirleaveproc (callerdat, dir, err, update_dir, entries) void *callerdat; - char *dir; + const char *dir; int err; - char *update_dir; + const char *update_dir; List *entries; { /* update the per-directory tag info */ @@ -1604,15 +1584,14 @@ findmaxrev (p, closure) void *closure; { int thisrev; - Entnode *entdata; + Entnode *entdata = p->data; - entdata = (Entnode *) p->data; if (entdata->type != ENT_FILE) - return (0); + return 0; thisrev = atoi (entdata->version); if (thisrev > maxrev) maxrev = thisrev; - return (0); + return 0; } /* @@ -1657,11 +1636,11 @@ remove_file (finfo, tag, message) error (0, retcode == -1 ? errno : 0, "failed to remove tag `%s' from `%s'", tag, finfo->fullname); - return (1); + return 1; } RCS_rewrite (finfo->rcs, NULL, NULL); Scratch_Entry (finfo->entries, finfo->file); - return (0); + return 0; } /* we are removing the file from either the head or a branch */ @@ -1691,12 +1670,12 @@ remove_file (finfo, tag, message) /* no revision exists on this branch. use the previous revision but do not lock. */ corev = RCS_gettag (finfo->rcs, tag, 1, (int *) NULL); - prev_rev = xstrdup(rev); + prev_rev = xstrdup (corev); lockflag = 0; } else { corev = xstrdup (rev); - prev_rev = xstrdup(branchname); + prev_rev = xstrdup (branchname); free (branchname); } @@ -1788,10 +1767,8 @@ finaladd (finfo, rev, tag, options) char *options; { int ret; - char *rcs; - rcs = locate_rcs (finfo->file, finfo->repository); - ret = Checkin ('A', finfo, rcs, rev, tag, options, saved_message); + ret = Checkin ('A', finfo, rev, tag, options, saved_message); if (ret == 0) { char *tmp = xmalloc (strlen (finfo->file) + sizeof (CVSADM) @@ -1802,11 +1779,10 @@ finaladd (finfo, rev, tag, options) error (0, errno, "cannot remove %s", tmp); free (tmp); } - else - fixaddfile (finfo->file, finfo->repository); + else if (finfo->rcs != NULL) + fixaddfile (finfo->rcs->path); (void) time (&last_register_time); - free (rcs); return (ret); } @@ -1827,19 +1803,22 @@ unlockrcs (rcs) RCS_rewrite (rcs, NULL, NULL); } + + /* * remove a partially added file. if we can parse it, leave it alone. + * + * FIXME: Every caller that calls this function can access finfo->rcs (the + * parsed RCSNode data), so we should be able to detect that the file needs + * to be removed without reparsing the file as we do below. */ static void -fixaddfile (file, repository) - char *file; - char *repository; +fixaddfile (rcs) + const char *rcs; { RCSNode *rcsfile; - char *rcs; int save_really_quiet; - rcs = locate_rcs (file, repository); save_really_quiet = really_quiet; really_quiet = 1; if ((rcsfile = RCS_parsercsfile (rcs)) == NULL) @@ -1850,9 +1829,10 @@ fixaddfile (file, repository) else freercsnode (&rcsfile); really_quiet = save_really_quiet; - free (rcs); } + + /* * put the branch back on an rcs file */ @@ -1876,25 +1856,46 @@ fixbranch (rcs, branch) * do the initial part of a file add for the named file. if adding * with a tag, put the file in the Attic and point the symbolic tag * at the committed revision. + * + * INPUTS + * file The name of the file in the workspace. + * repository The repository directory to expect to find FILE,v in. + * tag The name or rev num of the branch being added to, if any. + * options Any RCS keyword expansion options specified by the user. + * rcsnode A pointer to the pre-parsed RCSNode for this file, if the file + * exists in the repository. If this is NULL, assume the file + * does not yet exist. + * + * RETURNS + * 0 on success. + * 1 on errors, after printing any appropriate error messages. + * + * ERRORS + * This function will return an error when any of the following functions do: + * add_rcs_file + * RCS_setattic + * lock_RCS + * RCS_checkin + * RCS_parse (called to verify the newly created archive file) + * RCS_settag */ static int checkaddfile (file, repository, tag, options, rcsnode) - char *file; - char *repository; - char *tag; - char *options; + const char *file; + const char *repository; + const char *tag; + const char *options; RCSNode **rcsnode; { - char *rcs; + RCSNode *rcs; char *fname; - mode_t omask; - int retcode = 0; - int newfile = 0; - RCSNode *rcsfile = NULL; - int retval; + int newfile = 0; /* Set to 1 if we created a new RCS archive. */ + int retval = 1; int adding_on_branch; + assert (rcsnode != NULL); + /* Callers expect to be able to use either "" or NULL to mean the default keyword expansion. */ if (options != NULL && options[0] == '\0') @@ -1906,103 +1907,49 @@ checkaddfile (file, repository, tag, options, rcsnode) this. */ adding_on_branch = tag != NULL && !isdigit ((unsigned char) tag[0]); - if (adding_on_branch) - { - rcs = xmalloc (strlen (repository) + strlen (file) - + sizeof (RCSEXT) + sizeof (CVSATTIC) + 10); - (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 - rcs = locate_rcs (file, repository); - - if (isreadable (rcs)) + if (*rcsnode == NULL) { - /* file has existed in the past. Prepare to resurrect. */ - char *rev; - char *oldexpand; + char *rcsname; + char *desc = NULL; + size_t descalloc = 0; + size_t desclen = 0; + const char *opt; - if ((rcsfile = *rcsnode) == NULL) + if ( adding_on_branch ) { - error (0, 0, "could not find parsed rcsfile %s", file); - retval = 1; - goto out; - } - - oldexpand = RCS_getexpand (rcsfile); - if ((oldexpand != NULL - && options != NULL - && strcmp (options + 2, oldexpand) != 0) - || (oldexpand == NULL && options != NULL)) - { - /* We tell the user about this, because it means that the - old revisions will no longer retrieve the way that they - used to. */ - error (0, 0, "changing keyword expansion mode to %s", options); - RCS_setexpand (rcsfile, options + 2); - } - - if (!adding_on_branch) - { - /* We are adding on the trunk, so move the file out of the - Attic. */ - if (!(rcsfile->flags & INATTIC)) - { - error (0, 0, "warning: expected %s to be in Attic", - rcsfile->path); - } - - sprintf (rcs, "%s/%s%s", repository, file, RCSEXT); - - /* Begin a critical section around the code that spans the - first commit on the trunk of a file that's already been - committed on a branch. */ - SIG_beginCrSect (); - - if (RCS_setattic (rcsfile, 0)) - { - retval = 1; - goto out; - } + mode_t omask; + rcsname = xmalloc (strlen (repository) + + sizeof (CVSATTIC) + + strlen (file) + + sizeof (RCSEXT) + + 3); + (void) sprintf (rcsname, "%s/%s", repository, CVSATTIC); + omask = umask ( cvsumask ); + if (CVS_MKDIR (rcsname, 0777 ) != 0 && errno != EEXIST) + error (1, errno, "cannot make directory `%s'", rcsname); + (void) umask ( omask ); + (void) sprintf (rcsname, + "%s/%s/%s%s", + repository, + CVSATTIC, + file, + RCSEXT); } - - rev = RCS_getversion (rcsfile, tag, NULL, 1, (int *) NULL); - /* and lock it */ - if (lock_RCS (file, rcsfile, rev, repository)) + else { - error (0, 0, "cannot lock `%s'.", rcs); - if (rev != NULL) - free (rev); - retval = 1; - goto out; + rcsname = xmalloc (strlen (repository) + + strlen (file) + + sizeof (RCSEXT) + + 2); + (void) sprintf (rcsname, + "%s/%s%s", + repository, + file, + RCSEXT); } - if (rev != NULL) - free (rev); - } - else - { /* this is the first time we have ever seen this file; create - an rcs file. */ - - char *desc; - size_t descalloc; - size_t desclen; - - char *opt; - - desc = NULL; - descalloc = 0; - desclen = 0; + an RCS file. */ fname = xmalloc (strlen (file) + sizeof (CVSADM) + sizeof (CVSEXT_LOG) + 10); (void) sprintf (fname, "%s/%s%s", CVSADM, file, CVSEXT_LOG); @@ -2036,25 +1983,79 @@ checkaddfile (file, repository, tag, options, rcsnode) RCS_checkin indicate that this is a new file? Or does the "RCS file" message serve some function?). */ cvs_output ("RCS file: ", 0); - cvs_output (rcs, 0); + cvs_output (rcsname, 0); cvs_output ("\ndone\n", 0); - if (add_rcs_file (NULL, rcs, file, NULL, opt, + if (add_rcs_file (NULL, rcsname, file, NULL, opt, NULL, NULL, 0, NULL, desc, desclen, NULL) != 0) { - retval = 1; + if (rcsname != NULL) + free (rcsname); goto out; } - rcsfile = RCS_parsercsfile (rcs); + rcs = RCS_parsercsfile (rcsname); newfile = 1; + if (rcsname != NULL) + free (rcsname); if (desc != NULL) free (desc); - if (rcsnode != NULL) + *rcsnode = rcs; + } + else + { + /* file has existed in the past. Prepare to resurrect. */ + char *rev; + char *oldexpand; + + rcs = *rcsnode; + + oldexpand = RCS_getexpand (rcs); + if ((oldexpand != NULL + && options != NULL + && strcmp (options + 2, oldexpand) != 0) + || (oldexpand == NULL && options != NULL)) + { + /* We tell the user about this, because it means that the + old revisions will no longer retrieve the way that they + used to. */ + error (0, 0, "changing keyword expansion mode to %s", options); + RCS_setexpand (rcs, options + 2); + } + + if (!adding_on_branch) + { + /* We are adding on the trunk, so move the file out of the + Attic. */ + if (!(rcs->flags & INATTIC)) + { + error (0, 0, "warning: expected %s to be in Attic", + rcs->path); + } + + /* Begin a critical section around the code that spans the + first commit on the trunk of a file that's already been + committed on a branch. */ + SIG_beginCrSect (); + + if (RCS_setattic (rcs, 0)) + { + goto out; + } + } + + rev = RCS_getversion (rcs, tag, NULL, 1, (int *) NULL); + /* and lock it */ + if (lock_RCS (file, rcs, rev, repository)) { - assert (*rcsnode == NULL); - *rcsnode = rcsfile; + error (0, 0, "cannot lock `%s'.", rcs->path); + if (rev != NULL) + free (rev); + goto out; } + + if (rev != NULL) + free (rev); } /* when adding a file for the first time, and using a tag, we need @@ -2065,6 +2066,7 @@ checkaddfile (file, repository, tag, options, rcsnode) { char *tmp; FILE *fp; + int retcode; /* move the new file out of the way. */ fname = xmalloc (strlen (file) + sizeof (CVSADM) @@ -2084,14 +2086,13 @@ checkaddfile (file, repository, tag, options, rcsnode) /* commit a dead revision. */ (void) sprintf (tmp, "file %s was initially added on branch %s.", file, tag); - retcode = RCS_checkin (rcsfile, NULL, tmp, NULL, + retcode = RCS_checkin (rcs, NULL, tmp, NULL, RCS_FLAGS_DEAD | RCS_FLAGS_QUIET); free (tmp); if (retcode != 0) { error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0, - "could not create initial dead revision %s", rcs); - retval = 1; + "could not create initial dead revision %s", rcs->path); goto out; } @@ -2100,56 +2101,39 @@ checkaddfile (file, repository, tag, options, rcsnode) free (fname); /* double-check that the file was written correctly */ - freercsnode (&rcsfile); - rcsfile = RCS_parse (file, repository); - if (rcsfile == NULL) + freercsnode (&rcs); + rcs = RCS_parse (file, repository); + if (rcs == NULL) { - error (0, 0, "could not read %s", rcs); - retval = 1; + error (0, 0, "could not read %s", rcs->path); goto out; } - if (rcsnode != NULL) - *rcsnode = rcsfile; + *rcsnode = rcs; /* and lock it once again. */ - if (lock_RCS (file, rcsfile, NULL, repository)) + if (lock_RCS (file, rcs, NULL, repository)) { - error (0, 0, "cannot lock `%s'.", rcs); - retval = 1; + error (0, 0, "cannot lock `%s'.", rcs->path); goto out; } } /* when adding with a tag, we need to stub a branch, if it doesn't already exist. */ - - if (rcsfile == NULL) - { - if (rcsnode != NULL && *rcsnode != NULL) - rcsfile = *rcsnode; - else - { - rcsfile = RCS_parse (file, repository); - if (rcsfile == NULL) - { - error (0, 0, "could not read %s", rcs); - retval = 1; - goto out; - } - } - } - - if (!RCS_nodeisbranch (rcsfile, tag)) + if (!RCS_nodeisbranch (rcs, tag)) { /* branch does not exist. Stub it. */ char *head; char *magicrev; + int retcode; + + fixbranch (rcs, sbranch); - head = RCS_getversion (rcsfile, NULL, NULL, 0, (int *) NULL); - magicrev = RCS_magicrev (rcsfile, head); + head = RCS_getversion (rcs, NULL, NULL, 0, (int *) NULL); + magicrev = RCS_magicrev (rcs, head); - retcode = RCS_settag (rcsfile, tag, magicrev); - RCS_rewrite (rcsfile, NULL, NULL); + retcode = RCS_settag (rcs, tag, magicrev); + RCS_rewrite (rcs, NULL, NULL); free (head); free (magicrev); @@ -2157,26 +2141,24 @@ checkaddfile (file, repository, tag, options, rcsnode) if (retcode != 0) { error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0, - "could not stub branch %s for %s", tag, rcs); - retval = 1; + "could not stub branch %s for %s", tag, rcs->path); goto out; } } else { /* lock the branch. (stubbed branches need not be locked.) */ - if (lock_RCS (file, rcsfile, NULL, repository)) + if (lock_RCS (file, rcs, NULL, repository)) { - error (0, 0, "cannot lock `%s'.", rcs); - retval = 1; + error (0, 0, "cannot lock `%s'.", rcs->path); goto out; } } - if (rcsnode && *rcsnode != rcsfile) + if (*rcsnode != rcs) { freercsnode(rcsnode); - *rcsnode = rcsfile; + *rcsnode = rcs; } } @@ -2204,7 +2186,6 @@ checkaddfile (file, repository, tag, options, rcsnode) out: if (retval != 0 && SIG_inCrSect ()) SIG_endCrSect (); - free (rcs); return retval; } @@ -2216,10 +2197,10 @@ checkaddfile (file, repository, tag, options, rcsnode) */ static int lock_RCS (user, rcs, rev, repository) - char *user; + const char *user; RCSNode *rcs; - char *rev; - char *repository; + const char *rev; + const char *repository; { char *branch = NULL; int err = 0; @@ -2248,11 +2229,11 @@ lock_RCS (user, rcs, rev, repository) return (1); } } - err = RCS_lock(rcs, NULL, 1); + err = RCS_lock (rcs, NULL, 1); } else { - (void) RCS_lock(rcs, rev, 1); + RCS_lock (rcs, rev, 1); } /* We used to call RCS_rewrite here, and that might seem @@ -2298,9 +2279,8 @@ void update_delproc (p) Node *p; { - struct logfile_info *li; + struct logfile_info *li = p->data; - li = (struct logfile_info *) p->data; if (li->tag) free (li->tag); if (li->rev_old) @@ -2317,9 +2297,8 @@ static void ci_delproc (p) Node *p; { - struct commit_info *ci; + struct commit_info *ci = p->data; - ci = (struct commit_info *) p->data; if (ci->rev) free (ci->rev); if (ci->tag) @@ -2336,37 +2315,9 @@ static void masterlist_delproc (p) Node *p; { - struct master_lists *ml; + struct master_lists *ml = p->data; - ml = (struct master_lists *) p->data; dellist (&ml->ulist); dellist (&ml->cilist); free (ml); } - -/* Find an RCS file in the repository. Most parts of CVS will want to - rely instead on RCS_parse which performs a similar operation and is - called by recurse.c which then puts the result in useful places - like the rcs field of struct file_info. - - REPOSITORY is the repository (including the directory) and FILE is - the filename within that directory (without RCSEXT). Returns a - newly-malloc'd array containing the absolute pathname of the RCS - file that was found. */ -static char * -locate_rcs (file, repository) - char *file; - char *repository; -{ - char *rcs; - - rcs = xmalloc (strlen (repository) + strlen (file) + sizeof (RCSEXT) + 10); - (void) sprintf (rcs, "%s/%s%s", repository, file, RCSEXT); - if (!isreadable (rcs)) - { - (void) sprintf (rcs, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT); - if (!isreadable (rcs)) - (void) sprintf (rcs, "%s/%s%s", repository, file, RCSEXT); - } - return rcs; -} |