386BSD 0.1 development
[unix-history] / usr / othersrc / public / cvs-1.3 / src / classify.c
CommitLineData
fe37a9c9
WJ
1/*
2 * Copyright (c) 1992, Brian Berliner and Jeff Polk
3 * Copyright (c) 1989-1992, Brian Berliner
4 *
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 1.3 kit.
7 *
8 */
9
10#include "cvs.h"
11
12#ifndef lint
13static char rcsid[] = "@(#)classify.c 1.11 92/03/31";
14#endif
15
16#if __STDC__
17static void sticky_ck (char *file, int aflag, Vers_TS * vers, List * entries);
18#else
19static void sticky_ck ();
20#endif /* __STDC__ */
21
22/*
23 * Classify the state of a file
24 */
25Ctype
26Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
27 entries, srcfiles, versp)
28 char *file;
29 char *tag;
30 char *date;
31 char *options;
32 int force_tag_match;
33 int aflag;
34 char *repository;
35 List *entries;
36 List *srcfiles;
37 Vers_TS **versp;
38{
39 Vers_TS *vers;
40 Ctype ret;
41
42 /* get all kinds of good data about the file */
43 vers = Version_TS (repository, options, tag, date, file,
44 force_tag_match, 0, entries, srcfiles);
45
46 if (vers->vn_user == NULL)
47 {
48 /* No entry available, ts_rcs is invalid */
49 if (vers->vn_rcs == NULL)
50 {
51 /* there is no RCS file either */
52 if (vers->ts_user == NULL)
53 {
54 /* there is no user file */
55 if (!force_tag_match || !(vers->tag || vers->date))
56 if (!really_quiet)
57 error (0, 0, "nothing known about %s", file);
58 ret = T_UNKNOWN;
59 }
60 else
61 {
62 /* there is a user file */
63 if (!force_tag_match || !(vers->tag || vers->date))
64 if (!really_quiet)
65 error (0, 0, "use `cvs add' to create an entry for %s",
66 file);
67 ret = T_UNKNOWN;
68 }
69 }
70 else
71 {
72 /* there is an rcs file */
73
74 if (vers->ts_user == NULL)
75 {
76 /* There is no user file; needs checkout */
77 ret = T_CHECKOUT;
78 }
79 else
80 {
81 /*
82 * There is a user file; print a warning and add it to the
83 * conflict list, only if it is indeed different from what we
84 * plan to extract
85 */
86 if (No_Difference (file, vers, entries))
87 {
88 /* the files were different so it is a conflict */
89 if (!really_quiet)
90 error (0, 0, "move away %s; it is in the way", file);
91 ret = T_CONFLICT;
92 }
93 else
94 /* since there was no difference, still needs checkout */
95 ret = T_CHECKOUT;
96 }
97 }
98 }
99 else if (strcmp (vers->vn_user, "0") == 0)
100 {
101 /* An entry for a new-born file; ts_rcs is dummy */
102
103 if (vers->ts_user == NULL)
104 {
105 /*
106 * There is no user file, but there should be one; remove the
107 * entry
108 */
109 if (!really_quiet)
110 error (0, 0, "warning: new-born %s has disappeared", file);
111 ret = T_REMOVE_ENTRY;
112 }
113 else
114 {
115 /* There is a user file */
116
117 if (vers->vn_rcs == NULL)
118 /* There is no RCS file, added file */
119 ret = T_ADDED;
120 else
121 {
122 /*
123 * There is an RCS file, so someone else must have checked
124 * one in behind our back; conflict
125 */
126 if (!really_quiet)
127 error (0, 0,
128 "conflict: %s created independently by second party",
129 file);
130 ret = T_CONFLICT;
131 }
132 }
133 }
134 else if (vers->vn_user[0] == '-')
135 {
136 /* An entry for a removed file, ts_rcs is invalid */
137
138 if (vers->ts_user == NULL)
139 {
140 char tmp[PATH_MAX];
141
142 /* There is no user file (as it should be) */
143
144 (void) sprintf (tmp, "-%s", vers->vn_rcs ? vers->vn_rcs : "");
145
146 if (vers->vn_rcs == NULL)
147 {
148
149 /*
150 * There is no RCS file; this is all-right, but it has been
151 * removed independently by a second party; remove the entry
152 */
153 ret = T_REMOVE_ENTRY;
154 }
155 else if (strcmp (tmp, vers->vn_user) == 0)
156
157 /*
158 * The RCS file is the same version as the user file was, and
159 * that's OK; remove it
160 */
161 ret = T_REMOVED;
162 else
163 {
164
165 /*
166 * The RCS file is a newer version than the removed user file
167 * and this is definitely not OK; make it a conflict.
168 */
169 if (!really_quiet)
170 error (0, 0,
171 "conflict: removed %s was modified by second party",
172 file);
173 ret = T_CONFLICT;
174 }
175 }
176 else
177 {
178 /* The user file shouldn't be there */
179 if (!really_quiet)
180 error (0, 0, "%s should be removed and is still there", file);
181 ret = T_REMOVED;
182 }
183 }
184 else
185 {
186 /* A normal entry, TS_Rcs is valid */
187 if (vers->vn_rcs == NULL)
188 {
189 /* There is no RCS file */
190
191 if (vers->ts_user == NULL)
192 {
193 /* There is no user file, so just remove the entry */
194 if (!really_quiet)
195 error (0, 0, "warning: %s is not (any longer) pertinent",
196 file);
197 ret = T_REMOVE_ENTRY;
198 }
199 else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
200 {
201
202 /*
203 * The user file is still unmodified, so just remove it from
204 * the entry list
205 */
206 if (!really_quiet)
207 error (0, 0, "%s is no longer in the repository", file);
208 ret = T_REMOVE_ENTRY;
209 }
210 else
211 {
212 /*
213 * The user file has been modified and since it is no longer
214 * in the repository, a conflict is raised
215 */
216 if (No_Difference (file, vers, entries))
217 {
218 /* they are different -> conflict */
219 if (!really_quiet)
220 error (0, 0,
221 "conflict: %s is modified but no longer in the repository",
222 file);
223 ret = T_CONFLICT;
224 }
225 else
226 {
227 /* they weren't really different */
228 if (!really_quiet)
229 error (0, 0,
230 "warning: %s is not (any longer) pertinent",
231 file);
232 ret = T_REMOVE_ENTRY;
233 }
234 }
235 }
236 else if (strcmp (vers->vn_rcs, vers->vn_user) == 0)
237 {
238 /* The RCS file is the same version as the user file */
239
240 if (vers->ts_user == NULL)
241 {
242
243 /*
244 * There is no user file, so note that it was lost and
245 * extract a new version
246 */
247 if (strcmp (command_name, "update") == 0)
248 if (!really_quiet)
249 error (0, 0, "warning: %s was lost", file);
250 ret = T_CHECKOUT;
251 }
252 else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
253 {
254
255 /*
256 * The user file is still unmodified, so nothing special at
257 * all to do -- no lists updated, unless the sticky -k option
258 * has changed. If the sticky tag has changed, we just need
259 * to re-register the entry
260 */
261 if (vers->entdata->options &&
262 strcmp (vers->entdata->options, vers->options) != 0)
263 ret = T_CHECKOUT;
264 else
265 {
266 sticky_ck (file, aflag, vers, entries);
267 ret = T_UPTODATE;
268 }
269 }
270 else
271 {
272
273 /*
274 * The user file appears to have been modified, but we call
275 * No_Difference to verify that it really has been modified
276 */
277 if (No_Difference (file, vers, entries))
278 {
279
280 /*
281 * they really are different; modified if we aren't
282 * changing any sticky -k options, else needs merge
283 */
284#ifdef XXX_FIXME_WHEN_RCSMERGE_IS_FIXED
285 if (strcmp (vers->entdata->options ?
286 vers->entdata->options : "", vers->options) == 0)
287 ret = T_MODIFIED;
288 else
289 ret = T_NEEDS_MERGE;
290#else
291 ret = T_MODIFIED;
292 sticky_ck (file, aflag, vers, entries);
293#endif
294 }
295 else
296 {
297 /* file has not changed; check out if -k changed */
298 if (strcmp (vers->entdata->options ?
299 vers->entdata->options : "", vers->options) != 0)
300 {
301 ret = T_CHECKOUT;
302 }
303 else
304 {
305
306 /*
307 * else -> note that No_Difference will Register the
308 * file already for us, using the new tag/date. This
309 * is the desired behaviour
310 */
311 ret = T_UPTODATE;
312 }
313 }
314 }
315 }
316 else
317 {
318 /* The RCS file is a newer version than the user file */
319
320 if (vers->ts_user == NULL)
321 {
322 /* There is no user file, so just get it */
323
324 if (strcmp (command_name, "update") == 0)
325 if (!really_quiet)
326 error (0, 0, "warning: %s was lost", file);
327 ret = T_CHECKOUT;
328 }
329 else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
330 {
331
332 /*
333 * The user file is still unmodified, so just get it as well
334 */
335 ret = T_CHECKOUT;
336 }
337 else
338 {
339 if (No_Difference (file, vers, entries))
340 /* really modified, needs to merge */
341 ret = T_NEEDS_MERGE;
342 else
343 /* not really modified, check it out */
344 ret = T_CHECKOUT;
345 }
346 }
347 }
348
349 /* free up the vers struct, or just return it */
350 if (versp != (Vers_TS **) NULL)
351 *versp = vers;
352 else
353 freevers_ts (&vers);
354
355 /* return the status of the file */
356 return (ret);
357}
358
359static void
360sticky_ck (file, aflag, vers, entries)
361 char *file;
362 int aflag;
363 Vers_TS *vers;
364 List *entries;
365{
366 if (aflag || vers->tag || vers->date)
367 {
368 char *enttag = vers->entdata->tag;
369 char *entdate = vers->entdata->date;
370
371 if ((enttag && vers->tag && strcmp (enttag, vers->tag)) ||
372 ((enttag && !vers->tag) || (!enttag && vers->tag)) ||
373 (entdate && vers->date && strcmp (entdate, vers->date)) ||
374 ((entdate && !vers->date) || (!entdate && vers->date)))
375 {
376 Register (entries, file, vers->vn_user, vers->ts_rcs,
377 vers->options, vers->tag, vers->date);
378 }
379 }
380}