Commit | Line | Data |
---|---|---|
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 | |
13 | static char rcsid[] = "@(#)classify.c 1.11 92/03/31"; | |
14 | #endif | |
15 | ||
16 | #if __STDC__ | |
17 | static void sticky_ck (char *file, int aflag, Vers_TS * vers, List * entries); | |
18 | #else | |
19 | static void sticky_ck (); | |
20 | #endif /* __STDC__ */ | |
21 | ||
22 | /* | |
23 | * Classify the state of a file | |
24 | */ | |
25 | Ctype | |
26 | Classify_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 | ||
359 | static void | |
360 | sticky_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 | } |