static void append_arg (const struct cl_decoded_option *arg) { static unsigned int newargsize; if (g77_new_decoded_options == g77_x_decoded_options && g77_newargc < g77_xargc && options_same (arg, &g77_x_decoded_options[g77_newargc])) { ++g77_newargc; return; /* Nothing new here. */ } if (g77_new_decoded_options == g77_x_decoded_options) { /* Make new arglist. */ unsigned int i; newargsize = (g77_xargc << 2) + 20; /* This should handle all. */ g77_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize); /* Copy what has been done so far. */ for (i = 0; i < g77_newargc; ++i) g77_new_decoded_options[i] = g77_x_decoded_options[i]; }
/* * Classify the state of a file */ Ctype Classify_File (struct file_info *finfo, const char *tag, const char *date, const char *options, int force_tag_match, int aflag, Vers_TS **versp, int pipeout, int force_time_mismatch, int ignore_keywords) /* Keyword expansion options can be either NULL or "" to indicate none are specified here. */ { Vers_TS *vers; Ctype ret; kflag kf,kf_ent; TRACE(3,"Classify_File (%s)",PATCH_NULL(finfo->file)); /* get all kinds of good data about the file */ vers = Version_TS (finfo, options, tag, date, force_tag_match, 0, 0); TRACE(3,"vn_rcs=%s",PATCH_NULL(vers->vn_rcs)); RCS_get_kflags(vers->options,false,kf); if(vers->entdata) RCS_get_kflags(vers->entdata->options,false,kf_ent); if(force_time_mismatch) { xfree(vers->ts_user); vers->ts_user=xstrdup("modified"); } if (vers->vn_user == NULL) { /* No entry available, ts_rcs is invalid */ if (vers->vn_rcs == NULL) { /* there is no RCS file either */ if (vers->ts_user == NULL) { /* there is no user file */ /* FIXME: Why do we skip this message if vers->tag or vers->date is set? It causes "cvs update -r tag98 foo" to silently do nothing, which is seriously confusing behavior. "cvs update foo" gives this message, which is what I would expect. */ if (!force_tag_match || !(vers->tag || vers->date)) { if (!really_quiet) error (0, 0, "nothing known about %s", fn_root(finfo->fullname)); } ret = T_UNKNOWN; } else { /* there is a user file */ /* FIXME: Why do we skip this message if vers->tag or vers->date is set? It causes "cvs update -r tag98 foo" to silently do nothing, which is seriously confusing behavior. "cvs update foo" gives this message, which is what I would expect. */ if (!force_tag_match || !(vers->tag || vers->date)) if (!really_quiet) error (0, 0, "use `%s add' to create an entry for %s", program_name, fn_root(finfo->fullname)); ret = T_UNKNOWN; } } else if (RCS_isdead (vers->srcfile, vers->vn_rcs)) { /* there is an RCS file, but it's dead */ if (vers->ts_user == NULL) ret = T_UPTODATE; else { error (0, 0, "use `%s add' to create an entry for %s", program_name, fn_root(finfo->fullname)); ret = T_UNKNOWN; } } else if (vers->ts_user && !strcmp(vers->ts_user,"0") && !strcmp(finfo->file,RCSREPOVERSION)) { /* It's a directory entry, but there isn't one in the repository */ ret = T_UNKNOWN; } else if (!pipeout && vers->ts_user && No_Difference(finfo, vers, (kf.flags&KFLAG_STATIC || kf_ent.flags&KFLAG_STATIC), ignore_keywords)) { /* the files were different so it is a conflict */ if (!really_quiet) error (0, 0, "move away %s; it is in the way", fn_root(finfo->fullname)); ret = T_CONFLICT; } else { /* no user file or no difference, just checkout */ ret = T_CHECKOUT; } } else if (strcmp (vers->vn_user, "0") == 0) { /* An entry for a new-born file; ts_rcs is dummy */ if (vers->ts_user == NULL) { /* * There is no user file, but there should be one; remove the * entry */ if(!really_quiet) error (0, 0, "warning: new-born %s has disappeared", fn_root(finfo->fullname)); ret = T_REMOVE_ENTRY; } else if (vers->vn_rcs == NULL || RCS_isdead (vers->srcfile, vers->vn_rcs)) /* No RCS file or RCS file revision is dead */ ret = T_ADDED; else { if (vers->srcfile->flags & VALID) { /* This file has been added on some branch other than the one we are looking at. In the branch we are looking at, the file was already valid. */ if (!really_quiet) error (0, 0, "conflict: %s has been added, but already exists", fn_root(finfo->fullname)); } else { /* * There is an RCS file, so someone else must have checked * one in behind our back; conflict */ if (!really_quiet) error (0, 0, "conflict: %s created independently by second party", fn_root(finfo->fullname)); } ret = T_CONFLICT; } } else if (vers->vn_user[0] == '-') { /* An entry for a removed file, ts_rcs is invalid */ if (vers->ts_user == NULL) { /* There is no user file (as it should be) */ if (vers->vn_rcs == NULL || RCS_isdead (vers->srcfile, vers->vn_rcs)) { /* * There is no RCS file; this is all-right, but it has been * removed independently by a second party; remove the entry */ ret = T_REMOVE_ENTRY; } else if (strcmp (vers->vn_rcs, vers->vn_user + 1) == 0) /* * The RCS file is the same version as the user file was, and * that's OK; remove it */ ret = T_REMOVED; else if (pipeout) /* * The RCS file doesn't match the user's file, but it doesn't * matter in this case */ ret = T_NEEDS_MERGE; else { /* * The RCS file is a newer version than the removed user file * and this is definitely not OK; make it a conflict. */ if (!really_quiet) error (0, 0, "conflict: removed %s was modified by second party", fn_root(finfo->fullname)); ret = T_CONFLICT; } } else { /* The user file shouldn't be there */ if (!really_quiet) error (0, 0, "%s should be removed and is still there", fn_root(finfo->fullname)); ret = T_REMOVED; } } else { /* A normal entry, TS_Rcs is valid */ if (vers->vn_rcs == NULL || RCS_isdead (vers->srcfile, vers->vn_rcs)) { /* There is no RCS file */ if (vers->ts_user == NULL) { /* There is no user file, so just remove the entry */ if (!really_quiet) error (0, 0, "warning: %s is not (any longer) pertinent", fn_root(finfo->fullname)); ret = T_REMOVE_ENTRY; } else if (!strcmp (vers->ts_user, vers->ts_rcs)) { /* * The user file is still unmodified, so just remove it from * the entry list */ if (!really_quiet) error (0, 0, "%s is no longer in the repository", fn_root(finfo->fullname)); ret = T_REMOVE_ENTRY; } else if (No_Difference (finfo, vers, (kf.flags&KFLAG_STATIC || kf_ent.flags&KFLAG_STATIC), ignore_keywords)) { /* they are different -> conflict */ if (!really_quiet) error (0, 0, "conflict: %s is modified but no longer in the repository", fn_root(finfo->fullname)); ret = T_CONFLICT; } else { /* they weren't really different */ if (!really_quiet) error (0, 0, "warning: %s is not (any longer) pertinent", fn_root(finfo->fullname)); ret = T_REMOVE_ENTRY; } } else if (strcmp (vers->vn_rcs, vers->vn_user) == 0) { /* The RCS file is the same version as the user file */ if (vers->ts_user == NULL) { /* * There is no user file, so note that it was lost and * extract a new version */ /* Comparing the command_name against "update", in addition to being an ugly way to operate, means that this message does not get printed by the server. That might be considered just a straight bug, although there is one subtlety: that case also gets hit when a patch fails and the client fetches a file. I'm not sure there is currently any way for the server to distinguish those two cases. */ if (strcmp (command_name, "update") == 0) if (!really_quiet) error (0, 0, "warning: %s was lost", fn_root(finfo->fullname)); ret = T_CHECKOUT; } else if (!strcmp(vers->ts_user,"0") && !strcmp(finfo->file,RCSREPOVERSION)) { /* This is a directory... The only important entry is the version*/ ret = T_UPTODATE; } else if (strcmp (vers->ts_user, vers->ts_rcs) == 0) { /* Check for expansion option changes */ if (options && !options_same(vers->entdata->options,vers->options)) ret = T_CHECKOUT; else { if(aflag && !options_same(vers->entdata->options, vers->options)) ret = T_CHECKOUT; else ret = T_UPTODATE; /* Changing the expansion option now requires a commit -f, which makes sense (since you might have a sandbox specially checked out as -kb for example) */ sticky_ck (finfo, aflag, vers); } } else if (vers->entdata->merge_from_tag_1[0]) { ret = T_MODIFIED; } else if (No_Difference (finfo, vers, (kf.flags&KFLAG_STATIC || kf_ent.flags&KFLAG_STATIC), ignore_keywords)) { ret = T_MODIFIED; sticky_ck (finfo, aflag, vers); } else if (!options_same(vers->entdata->options,vers->options)) { /* file has not changed; check out if -k changed */ ret = T_CHECKOUT; } else { /* * else -> note that No_Difference will Register the * file already for us, using the new tag/date. This * is the desired behaviour */ ret = T_UPTODATE; } } else { /* The RCS file is a newer version than the user file */ if (vers->ts_user == NULL) { /* There is no user file, so just get it */ /* See comment at other "update" compare, for more thoughts on this comparison. */ if (strcmp (command_name, "update") == 0) if (!really_quiet) error (0, 0, "warning: %s was lost", fn_root(finfo->fullname)); ret = T_CHECKOUT; } else if (!strcmp (vers->ts_user, vers->ts_rcs)) { /* * The user file is still unmodified, so just get it as well */ if (!options_same(vers->entdata->options,vers->options)) ret = T_CHECKOUT; else ret = T_PATCH; } else if (No_Difference (finfo, vers, (kf.flags&KFLAG_STATIC || kf_ent.flags&KFLAG_STATIC), ignore_keywords)) /* really modified, needs to merge */ ret = T_NEEDS_MERGE; else if(!options_same(vers->entdata->options,vers->options)) /* not really modified, check it out */ ret = T_CHECKOUT; else ret = T_PATCH; } } /* free up the vers struct, or just return it */ if (versp != (Vers_TS **) NULL) *versp = vers; else freevers_ts (&vers); /* return the status of the file */ return (ret); }