2 * Copyright (c) 1992, Brian Berliner and Jeff Polk
3 * Copyright (c) 1989-1992, Brian Berliner
5 * You may distribute under the terms of the GNU General Public License as
6 * specified in the README file that comes with the CVS source distribution.
12 static void sticky_ck PROTO ((struct file_info *finfo, int aflag,
16 * Classify the state of a file
19 Classify_File (finfo, tag, date, options, force_tag_match, aflag, versp,
21 struct file_info *finfo;
25 /* Keyword expansion options. Can be either NULL or "" to
26 indicate none are specified here. */
37 /* get all kinds of good data about the file */
38 vers = Version_TS (finfo, options, tag, date,
41 if (vers->vn_user == NULL)
43 /* No entry available, ts_rcs is invalid */
44 if (vers->vn_rcs == NULL)
46 /* there is no RCS file either */
47 if (vers->ts_user == NULL)
49 /* there is no user file */
50 /* FIXME: Why do we skip this message if vers->tag or
51 vers->date is set? It causes "cvs update -r tag98 foo"
52 to silently do nothing, which is seriously confusing
53 behavior. "cvs update foo" gives this message, which
54 is what I would expect. */
55 if (!force_tag_match || !(vers->tag || vers->date))
57 error (0, 0, "nothing known about %s", finfo->fullname);
62 /* there is a user file */
63 /* FIXME: Why do we skip this message if vers->tag or
64 vers->date is set? It causes "cvs update -r tag98 foo"
65 to silently do nothing, which is seriously confusing
66 behavior. "cvs update foo" gives this message, which
67 is what I would expect. */
68 if (!force_tag_match || !(vers->tag || vers->date))
70 error (0, 0, "use `%s add' to create an entry for %s",
71 program_name, finfo->fullname);
75 else if (RCS_isdead (vers->srcfile, vers->vn_rcs))
77 /* there is an RCS file, but it's dead */
78 if (vers->ts_user == NULL)
82 error (0, 0, "use `%s add' to create an entry for %s",
83 program_name, finfo->fullname);
87 else if (!pipeout && vers->ts_user && No_Difference (finfo, vers))
89 /* the files were different so it is a conflict */
91 error (0, 0, "move away %s; it is in the way",
96 /* no user file or no difference, just checkout */
99 else if (strcmp (vers->vn_user, "0") == 0)
101 /* An entry for a new-born file; ts_rcs is dummy */
103 if (vers->ts_user == NULL)
112 * There is no user file, but there should be one; remove the
116 error (0, 0, "warning: new-born %s has disappeared",
118 ret = T_REMOVE_ENTRY;
121 else if (vers->vn_rcs == NULL ||
122 RCS_isdead (vers->srcfile, vers->vn_rcs))
123 /* No RCS file or RCS file revision is dead */
133 if (vers->srcfile->flags & INATTIC
134 && vers->srcfile->flags & VALID)
136 /* This file has been added on some branch other than
137 the one we are looking at. In the branch we are
138 looking at, the file was already valid. */
141 "conflict: %s has been added, but already exists",
147 * There is an RCS file, so someone else must have checked
148 * one in behind our back; conflict
152 "conflict: %s created independently by second party",
159 else if (vers->vn_user[0] == '-')
161 /* An entry for a removed file, ts_rcs is invalid */
163 if (vers->ts_user == NULL)
165 /* There is no user file (as it should be) */
167 if (vers->vn_rcs == NULL
168 || RCS_isdead (vers->srcfile, vers->vn_rcs))
172 * There is no RCS file; this is all-right, but it has been
173 * removed independently by a second party; remove the entry
175 ret = T_REMOVE_ENTRY;
177 else if (strcmp (vers->vn_rcs, vers->vn_user + 1) == 0)
179 * The RCS file is the same version as the user file was, and
180 * that's OK; remove it
185 * The RCS file doesn't match the user's file, but it doesn't
186 * matter in this case
193 * The RCS file is a newer version than the removed user file
194 * and this is definitely not OK; make it a conflict.
198 "conflict: removed %s was modified by second party",
205 /* The user file shouldn't be there */
207 error (0, 0, "%s should be removed and is still there",
214 /* A normal entry, TS_Rcs is valid */
215 if (vers->vn_rcs == NULL || RCS_isdead (vers->srcfile, vers->vn_rcs))
217 /* There is no RCS file */
219 if (vers->ts_user == NULL)
221 /* There is no user file, so just remove the entry */
223 error (0, 0, "warning: %s is not (any longer) pertinent",
225 ret = T_REMOVE_ENTRY;
227 else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
231 * The user file is still unmodified, so just remove it from
235 error (0, 0, "%s is no longer in the repository",
237 ret = T_REMOVE_ENTRY;
239 else if (No_Difference (finfo, vers))
241 /* they are different -> conflict */
244 "conflict: %s is modified but no longer in the repository",
250 /* they weren't really different */
253 "warning: %s is not (any longer) pertinent",
255 ret = T_REMOVE_ENTRY;
258 else if (strcmp (vers->vn_rcs, vers->vn_user) == 0)
260 /* The RCS file is the same version as the user file */
262 if (vers->ts_user == NULL)
266 * There is no user file, so note that it was lost and
267 * extract a new version
269 /* Comparing the cvs_cmd_name against "update", in
270 addition to being an ugly way to operate, means
271 that this message does not get printed by the
272 server. That might be considered just a straight
273 bug, although there is one subtlety: that case also
274 gets hit when a patch fails and the client fetches
275 a file. I'm not sure there is currently any way
276 for the server to distinguish those two cases. */
277 if (strcmp (cvs_cmd_name, "update") == 0)
279 error (0, 0, "warning: %s was lost", finfo->fullname);
282 else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
286 * The user file is still unmodified, so nothing special at
287 * all to do -- no lists updated, unless the sticky -k option
288 * has changed. If the sticky tag has changed, we just need
289 * to re-register the entry
291 /* TODO: decide whether we need to check file permissions
292 for a mismatch, and return T_CONFLICT if so. */
293 if (vers->entdata->options &&
294 strcmp (vers->entdata->options, vers->options) != 0)
298 sticky_ck (finfo, aflag, vers);
302 else if (No_Difference (finfo, vers))
306 * they really are different; modified if we aren't
307 * changing any sticky -k options, else needs merge
309 #ifdef XXX_FIXME_WHEN_RCSMERGE_IS_FIXED
310 if (strcmp (vers->entdata->options ?
311 vers->entdata->options : "", vers->options) == 0)
317 sticky_ck (finfo, aflag, vers);
320 else if (strcmp (vers->entdata->options ?
321 vers->entdata->options : "", vers->options) != 0)
323 /* file has not changed; check out if -k changed */
330 * else -> note that No_Difference will Register the
331 * file already for us, using the new tag/date. This
332 * is the desired behaviour
339 /* The RCS file is a newer version than the user file */
341 if (vers->ts_user == NULL)
343 /* There is no user file, so just get it */
345 /* See comment at other "update" compare, for more
346 thoughts on this comparison. */
347 if (strcmp (cvs_cmd_name, "update") == 0)
349 error (0, 0, "warning: %s was lost", finfo->fullname);
352 else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
356 * The user file is still unmodified, so just get it as well
358 if (strcmp (vers->entdata->options ?
359 vers->entdata->options : "", vers->options) != 0
360 || (vers->srcfile != NULL
361 && (vers->srcfile->flags & INATTIC) != 0))
366 else if (No_Difference (finfo, vers))
367 /* really modified, needs to merge */
369 else if ((strcmp (vers->entdata->options ?
370 vers->entdata->options : "", vers->options)
372 || (vers->srcfile != NULL
373 && (vers->srcfile->flags & INATTIC) != 0))
374 /* not really modified, check it out */
381 /* free up the vers struct, or just return it */
382 if (versp != (Vers_TS **) NULL)
387 /* return the status of the file */
392 sticky_ck (finfo, aflag, vers)
393 struct file_info *finfo;
397 if (aflag || vers->tag || vers->date)
399 char *enttag = vers->entdata->tag;
400 char *entdate = vers->entdata->date;
402 if ((enttag && vers->tag && strcmp (enttag, vers->tag)) ||
403 ((enttag && !vers->tag) || (!enttag && vers->tag)) ||
404 (entdate && vers->date && strcmp (entdate, vers->date)) ||
405 ((entdate && !vers->date) || (!entdate && vers->date)))
407 Register (finfo->entries, finfo->file, vers->vn_user, vers->ts_rcs,
408 vers->options, vers->tag, vers->date, vers->ts_conflict);
410 #ifdef SERVER_SUPPORT
413 /* We need to update the entries line on the client side.
414 It is possible we will later update it again via
415 server_updated or some such, but that is OK. */
416 server_update_entries
417 (finfo->file, finfo->update_dir, finfo->repository,
418 strcmp (vers->ts_rcs, vers->ts_user) == 0 ?
419 SERVER_UPDATED : SERVER_MERGED);