1*86d7f5d3SJohn Marino /*
2*86d7f5d3SJohn Marino * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
3*86d7f5d3SJohn Marino *
4*86d7f5d3SJohn Marino * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
5*86d7f5d3SJohn Marino * and others.
6*86d7f5d3SJohn Marino *
7*86d7f5d3SJohn Marino * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8*86d7f5d3SJohn Marino * Portions Copyright (C) 1989-1992, Brian Berliner
9*86d7f5d3SJohn Marino *
10*86d7f5d3SJohn Marino * You may distribute under the terms of the GNU General Public License as
11*86d7f5d3SJohn Marino * specified in the README file that comes with the CVS source distribution.
12*86d7f5d3SJohn Marino *
13*86d7f5d3SJohn Marino */
14*86d7f5d3SJohn Marino
15*86d7f5d3SJohn Marino #include "cvs.h"
16*86d7f5d3SJohn Marino
17*86d7f5d3SJohn Marino static void sticky_ck (struct file_info *finfo, int aflag,
18*86d7f5d3SJohn Marino Vers_TS * vers);
19*86d7f5d3SJohn Marino
20*86d7f5d3SJohn Marino /*
21*86d7f5d3SJohn Marino * Classify the state of a file.
22*86d7f5d3SJohn Marino *
23*86d7f5d3SJohn Marino * INPUTS
24*86d7f5d3SJohn Marino * finfo Information about the file to be classified.
25*86d7f5d3SJohn Marino * tag
26*86d7f5d3SJohn Marino * date
27*86d7f5d3SJohn Marino * options Keyword expansion options. Can be either NULL or "" to
28*86d7f5d3SJohn Marino * indicate none are specified here.
29*86d7f5d3SJohn Marino * force_tag_match
30*86d7f5d3SJohn Marino * aflag
31*86d7f5d3SJohn Marino * versp
32*86d7f5d3SJohn Marino * pipeout Did the user pass the "pipeout" flag to request that
33*86d7f5d3SJohn Marino * all output go to STDOUT rather than to a file or files?
34*86d7f5d3SJohn Marino *
35*86d7f5d3SJohn Marino * RETURNS
36*86d7f5d3SJohn Marino * A Ctype (defined as an enum) describing the state of the file relative to
37*86d7f5d3SJohn Marino * the repository. See the definition of Ctype for more.
38*86d7f5d3SJohn Marino */
39*86d7f5d3SJohn Marino Ctype
Classify_File(struct file_info * finfo,char * tag,char * date,char * options,int force_tag_match,int aflag,Vers_TS ** versp,int pipeout)40*86d7f5d3SJohn Marino Classify_File (struct file_info *finfo, char *tag, char *date, char *options,
41*86d7f5d3SJohn Marino int force_tag_match, int aflag, Vers_TS **versp, int pipeout)
42*86d7f5d3SJohn Marino {
43*86d7f5d3SJohn Marino Vers_TS *vers;
44*86d7f5d3SJohn Marino Ctype ret;
45*86d7f5d3SJohn Marino
46*86d7f5d3SJohn Marino /* get all kinds of good data about the file */
47*86d7f5d3SJohn Marino vers = Version_TS (finfo, options, tag, date,
48*86d7f5d3SJohn Marino force_tag_match, 0);
49*86d7f5d3SJohn Marino
50*86d7f5d3SJohn Marino if (vers->vn_user == NULL)
51*86d7f5d3SJohn Marino {
52*86d7f5d3SJohn Marino /* No entry available, ts_rcs is invalid */
53*86d7f5d3SJohn Marino if (vers->vn_rcs == NULL)
54*86d7f5d3SJohn Marino {
55*86d7f5d3SJohn Marino /* there is no RCS file either */
56*86d7f5d3SJohn Marino if (vers->ts_user == NULL)
57*86d7f5d3SJohn Marino {
58*86d7f5d3SJohn Marino /* there is no user file */
59*86d7f5d3SJohn Marino /* FIXME: Why do we skip this message if vers->tag or
60*86d7f5d3SJohn Marino vers->date is set? It causes "cvs update -r tag98 foo"
61*86d7f5d3SJohn Marino to silently do nothing, which is seriously confusing
62*86d7f5d3SJohn Marino behavior. "cvs update foo" gives this message, which
63*86d7f5d3SJohn Marino is what I would expect. */
64*86d7f5d3SJohn Marino if (!force_tag_match || !(vers->tag || vers->date))
65*86d7f5d3SJohn Marino if (!really_quiet)
66*86d7f5d3SJohn Marino error (0, 0, "nothing known about `%s'",
67*86d7f5d3SJohn Marino finfo->fullname);
68*86d7f5d3SJohn Marino ret = T_UNKNOWN;
69*86d7f5d3SJohn Marino }
70*86d7f5d3SJohn Marino else
71*86d7f5d3SJohn Marino {
72*86d7f5d3SJohn Marino /* there is a user file */
73*86d7f5d3SJohn Marino /* FIXME: Why do we skip this message if vers->tag or
74*86d7f5d3SJohn Marino vers->date is set? It causes "cvs update -r tag98 foo"
75*86d7f5d3SJohn Marino to silently do nothing, which is seriously confusing
76*86d7f5d3SJohn Marino behavior. "cvs update foo" gives this message, which
77*86d7f5d3SJohn Marino is what I would expect. */
78*86d7f5d3SJohn Marino if (!force_tag_match || !(vers->tag || vers->date))
79*86d7f5d3SJohn Marino if (!really_quiet)
80*86d7f5d3SJohn Marino error (0, 0, "use `%s add' to create an entry for `%s'",
81*86d7f5d3SJohn Marino program_name, finfo->fullname);
82*86d7f5d3SJohn Marino ret = T_UNKNOWN;
83*86d7f5d3SJohn Marino }
84*86d7f5d3SJohn Marino }
85*86d7f5d3SJohn Marino else if (RCS_isdead (vers->srcfile, vers->vn_rcs))
86*86d7f5d3SJohn Marino {
87*86d7f5d3SJohn Marino /* there is an RCS file, but it's dead */
88*86d7f5d3SJohn Marino if (vers->ts_user == NULL)
89*86d7f5d3SJohn Marino ret = T_UPTODATE;
90*86d7f5d3SJohn Marino else
91*86d7f5d3SJohn Marino {
92*86d7f5d3SJohn Marino error (0, 0, "use `%s add' to create an entry for `%s'",
93*86d7f5d3SJohn Marino program_name, finfo->fullname);
94*86d7f5d3SJohn Marino ret = T_UNKNOWN;
95*86d7f5d3SJohn Marino }
96*86d7f5d3SJohn Marino }
97*86d7f5d3SJohn Marino else if (!pipeout && vers->ts_user && No_Difference (finfo, vers))
98*86d7f5d3SJohn Marino {
99*86d7f5d3SJohn Marino /* the files were different so it is a conflict */
100*86d7f5d3SJohn Marino if (!really_quiet)
101*86d7f5d3SJohn Marino error (0, 0, "move away `%s'; it is in the way",
102*86d7f5d3SJohn Marino finfo->fullname);
103*86d7f5d3SJohn Marino ret = T_CONFLICT;
104*86d7f5d3SJohn Marino }
105*86d7f5d3SJohn Marino else
106*86d7f5d3SJohn Marino /* no user file or no difference, just checkout */
107*86d7f5d3SJohn Marino ret = T_CHECKOUT;
108*86d7f5d3SJohn Marino }
109*86d7f5d3SJohn Marino else if (strcmp (vers->vn_user, "0") == 0)
110*86d7f5d3SJohn Marino {
111*86d7f5d3SJohn Marino /* An entry for a new-born file; ts_rcs is dummy */
112*86d7f5d3SJohn Marino
113*86d7f5d3SJohn Marino if (vers->ts_user == NULL)
114*86d7f5d3SJohn Marino {
115*86d7f5d3SJohn Marino if (pipeout)
116*86d7f5d3SJohn Marino {
117*86d7f5d3SJohn Marino ret = T_CHECKOUT;
118*86d7f5d3SJohn Marino }
119*86d7f5d3SJohn Marino else
120*86d7f5d3SJohn Marino {
121*86d7f5d3SJohn Marino /*
122*86d7f5d3SJohn Marino * There is no user file, but there should be one; remove the
123*86d7f5d3SJohn Marino * entry
124*86d7f5d3SJohn Marino */
125*86d7f5d3SJohn Marino if (!really_quiet)
126*86d7f5d3SJohn Marino error (0, 0, "warning: new-born `%s' has disappeared",
127*86d7f5d3SJohn Marino finfo->fullname);
128*86d7f5d3SJohn Marino ret = T_REMOVE_ENTRY;
129*86d7f5d3SJohn Marino }
130*86d7f5d3SJohn Marino }
131*86d7f5d3SJohn Marino else if (vers->vn_rcs == NULL ||
132*86d7f5d3SJohn Marino RCS_isdead (vers->srcfile, vers->vn_rcs))
133*86d7f5d3SJohn Marino /* No RCS file or RCS file revision is dead */
134*86d7f5d3SJohn Marino ret = T_ADDED;
135*86d7f5d3SJohn Marino else
136*86d7f5d3SJohn Marino {
137*86d7f5d3SJohn Marino if (pipeout)
138*86d7f5d3SJohn Marino {
139*86d7f5d3SJohn Marino ret = T_CHECKOUT;
140*86d7f5d3SJohn Marino }
141*86d7f5d3SJohn Marino else
142*86d7f5d3SJohn Marino {
143*86d7f5d3SJohn Marino if (vers->srcfile->flags & INATTIC
144*86d7f5d3SJohn Marino && vers->srcfile->flags & VALID)
145*86d7f5d3SJohn Marino {
146*86d7f5d3SJohn Marino /* This file has been added on some branch other than
147*86d7f5d3SJohn Marino the one we are looking at. In the branch we are
148*86d7f5d3SJohn Marino looking at, the file was already valid. */
149*86d7f5d3SJohn Marino if (!really_quiet)
150*86d7f5d3SJohn Marino error (0, 0,
151*86d7f5d3SJohn Marino "conflict: `%s' has been added, but already exists",
152*86d7f5d3SJohn Marino finfo->fullname);
153*86d7f5d3SJohn Marino }
154*86d7f5d3SJohn Marino else
155*86d7f5d3SJohn Marino {
156*86d7f5d3SJohn Marino /*
157*86d7f5d3SJohn Marino * There is an RCS file, so someone else must have checked
158*86d7f5d3SJohn Marino * one in behind our back; conflict
159*86d7f5d3SJohn Marino */
160*86d7f5d3SJohn Marino if (!really_quiet)
161*86d7f5d3SJohn Marino error (0, 0,
162*86d7f5d3SJohn Marino "conflict: `%s' created independently by"
163*86d7f5d3SJohn Marino " second party",
164*86d7f5d3SJohn Marino finfo->fullname);
165*86d7f5d3SJohn Marino }
166*86d7f5d3SJohn Marino ret = T_CONFLICT;
167*86d7f5d3SJohn Marino }
168*86d7f5d3SJohn Marino }
169*86d7f5d3SJohn Marino }
170*86d7f5d3SJohn Marino else if (vers->vn_user[0] == '-')
171*86d7f5d3SJohn Marino {
172*86d7f5d3SJohn Marino /* An entry for a removed file, ts_rcs is invalid */
173*86d7f5d3SJohn Marino
174*86d7f5d3SJohn Marino if (vers->ts_user == NULL)
175*86d7f5d3SJohn Marino {
176*86d7f5d3SJohn Marino /* There is no user file (as it should be) */
177*86d7f5d3SJohn Marino
178*86d7f5d3SJohn Marino if (vers->vn_rcs == NULL
179*86d7f5d3SJohn Marino || RCS_isdead (vers->srcfile, vers->vn_rcs))
180*86d7f5d3SJohn Marino {
181*86d7f5d3SJohn Marino
182*86d7f5d3SJohn Marino /*
183*86d7f5d3SJohn Marino * There is no RCS file; this is all-right, but it has been
184*86d7f5d3SJohn Marino * removed independently by a second party; remove the entry
185*86d7f5d3SJohn Marino */
186*86d7f5d3SJohn Marino ret = T_REMOVE_ENTRY;
187*86d7f5d3SJohn Marino }
188*86d7f5d3SJohn Marino else if (strcmp (vers->vn_rcs, vers->vn_user + 1) == 0)
189*86d7f5d3SJohn Marino /*
190*86d7f5d3SJohn Marino * The RCS file is the same version as the user file was, and
191*86d7f5d3SJohn Marino * that's OK; remove it
192*86d7f5d3SJohn Marino */
193*86d7f5d3SJohn Marino ret = T_REMOVED;
194*86d7f5d3SJohn Marino else if (pipeout)
195*86d7f5d3SJohn Marino /*
196*86d7f5d3SJohn Marino * The RCS file doesn't match the user's file, but it doesn't
197*86d7f5d3SJohn Marino * matter in this case
198*86d7f5d3SJohn Marino */
199*86d7f5d3SJohn Marino ret = T_NEEDS_MERGE;
200*86d7f5d3SJohn Marino else
201*86d7f5d3SJohn Marino {
202*86d7f5d3SJohn Marino
203*86d7f5d3SJohn Marino /*
204*86d7f5d3SJohn Marino * The RCS file is a newer version than the removed user file
205*86d7f5d3SJohn Marino * and this is definitely not OK; make it a conflict.
206*86d7f5d3SJohn Marino */
207*86d7f5d3SJohn Marino if (!really_quiet)
208*86d7f5d3SJohn Marino error (0, 0,
209*86d7f5d3SJohn Marino "conflict: removed `%s' was modified by"
210*86d7f5d3SJohn Marino " second party",
211*86d7f5d3SJohn Marino finfo->fullname);
212*86d7f5d3SJohn Marino ret = T_CONFLICT;
213*86d7f5d3SJohn Marino }
214*86d7f5d3SJohn Marino }
215*86d7f5d3SJohn Marino else
216*86d7f5d3SJohn Marino {
217*86d7f5d3SJohn Marino /* The user file shouldn't be there */
218*86d7f5d3SJohn Marino if (!really_quiet)
219*86d7f5d3SJohn Marino error (0, 0, "`%s' should be removed and is still there",
220*86d7f5d3SJohn Marino finfo->fullname);
221*86d7f5d3SJohn Marino ret = T_REMOVED;
222*86d7f5d3SJohn Marino }
223*86d7f5d3SJohn Marino }
224*86d7f5d3SJohn Marino else
225*86d7f5d3SJohn Marino {
226*86d7f5d3SJohn Marino /* A normal entry, TS_Rcs is valid */
227*86d7f5d3SJohn Marino if (vers->vn_rcs == NULL || RCS_isdead (vers->srcfile, vers->vn_rcs))
228*86d7f5d3SJohn Marino {
229*86d7f5d3SJohn Marino /* There is no RCS file */
230*86d7f5d3SJohn Marino
231*86d7f5d3SJohn Marino if (vers->ts_user == NULL)
232*86d7f5d3SJohn Marino {
233*86d7f5d3SJohn Marino /* There is no user file, so just remove the entry */
234*86d7f5d3SJohn Marino if (!really_quiet)
235*86d7f5d3SJohn Marino error (0, 0, "warning: `%s' is not (any longer) pertinent",
236*86d7f5d3SJohn Marino finfo->fullname);
237*86d7f5d3SJohn Marino ret = T_REMOVE_ENTRY;
238*86d7f5d3SJohn Marino }
239*86d7f5d3SJohn Marino else if (strcmp (vers->ts_user, vers->ts_rcs)
240*86d7f5d3SJohn Marino && No_Difference (finfo, vers))
241*86d7f5d3SJohn Marino {
242*86d7f5d3SJohn Marino /* they are different -> conflict */
243*86d7f5d3SJohn Marino if (!really_quiet)
244*86d7f5d3SJohn Marino error (0, 0,
245*86d7f5d3SJohn Marino "conflict: `%s' is modified but no longer in the"
246*86d7f5d3SJohn Marino " repository",
247*86d7f5d3SJohn Marino finfo->fullname);
248*86d7f5d3SJohn Marino ret = T_CONFLICT;
249*86d7f5d3SJohn Marino }
250*86d7f5d3SJohn Marino else
251*86d7f5d3SJohn Marino {
252*86d7f5d3SJohn Marino
253*86d7f5d3SJohn Marino /*
254*86d7f5d3SJohn Marino * The user file is still unmodified, so just remove it from
255*86d7f5d3SJohn Marino * the entry list
256*86d7f5d3SJohn Marino */
257*86d7f5d3SJohn Marino if (!really_quiet)
258*86d7f5d3SJohn Marino error (0, 0, "`%s' is no longer in the repository",
259*86d7f5d3SJohn Marino finfo->fullname);
260*86d7f5d3SJohn Marino ret = T_REMOVE_ENTRY;
261*86d7f5d3SJohn Marino }
262*86d7f5d3SJohn Marino }
263*86d7f5d3SJohn Marino else if (strcmp (vers->vn_rcs, vers->vn_user) == 0)
264*86d7f5d3SJohn Marino {
265*86d7f5d3SJohn Marino /* The RCS file is the same version as the user file */
266*86d7f5d3SJohn Marino
267*86d7f5d3SJohn Marino if (vers->ts_user == NULL)
268*86d7f5d3SJohn Marino {
269*86d7f5d3SJohn Marino
270*86d7f5d3SJohn Marino /*
271*86d7f5d3SJohn Marino * There is no user file, so note that it was lost and
272*86d7f5d3SJohn Marino * extract a new version
273*86d7f5d3SJohn Marino */
274*86d7f5d3SJohn Marino /* Comparing the cvs_cmd_name against "update", in
275*86d7f5d3SJohn Marino addition to being an ugly way to operate, means
276*86d7f5d3SJohn Marino that this message does not get printed by the
277*86d7f5d3SJohn Marino server. That might be considered just a straight
278*86d7f5d3SJohn Marino bug, although there is one subtlety: that case also
279*86d7f5d3SJohn Marino gets hit when a patch fails and the client fetches
280*86d7f5d3SJohn Marino a file. I'm not sure there is currently any way
281*86d7f5d3SJohn Marino for the server to distinguish those two cases. */
282*86d7f5d3SJohn Marino if (strcmp (cvs_cmd_name, "update") == 0)
283*86d7f5d3SJohn Marino if (!really_quiet)
284*86d7f5d3SJohn Marino error (0, 0, "warning: `%s' was lost", finfo->fullname);
285*86d7f5d3SJohn Marino ret = T_CHECKOUT;
286*86d7f5d3SJohn Marino }
287*86d7f5d3SJohn Marino else if (!strcmp (vers->ts_user,
288*86d7f5d3SJohn Marino vers->ts_conflict
289*86d7f5d3SJohn Marino ? vers->ts_conflict : vers->ts_rcs))
290*86d7f5d3SJohn Marino {
291*86d7f5d3SJohn Marino
292*86d7f5d3SJohn Marino /*
293*86d7f5d3SJohn Marino * The user file is still unmodified, so nothing special at
294*86d7f5d3SJohn Marino * all to do -- no lists updated, unless the sticky -k option
295*86d7f5d3SJohn Marino * has changed. If the sticky tag has changed, we just need
296*86d7f5d3SJohn Marino * to re-register the entry
297*86d7f5d3SJohn Marino */
298*86d7f5d3SJohn Marino /* TODO: decide whether we need to check file permissions
299*86d7f5d3SJohn Marino for a mismatch, and return T_CONFLICT if so. */
300*86d7f5d3SJohn Marino if (vers->entdata->options &&
301*86d7f5d3SJohn Marino strcmp (vers->entdata->options, vers->options) != 0)
302*86d7f5d3SJohn Marino ret = T_CHECKOUT;
303*86d7f5d3SJohn Marino else if (vers->ts_conflict)
304*86d7f5d3SJohn Marino ret = T_CONFLICT;
305*86d7f5d3SJohn Marino else
306*86d7f5d3SJohn Marino {
307*86d7f5d3SJohn Marino sticky_ck (finfo, aflag, vers);
308*86d7f5d3SJohn Marino ret = T_UPTODATE;
309*86d7f5d3SJohn Marino }
310*86d7f5d3SJohn Marino }
311*86d7f5d3SJohn Marino else if (No_Difference (finfo, vers))
312*86d7f5d3SJohn Marino {
313*86d7f5d3SJohn Marino
314*86d7f5d3SJohn Marino /*
315*86d7f5d3SJohn Marino * they really are different; modified if we aren't
316*86d7f5d3SJohn Marino * changing any sticky -k options, else needs merge
317*86d7f5d3SJohn Marino */
318*86d7f5d3SJohn Marino #ifdef XXX_FIXME_WHEN_RCSMERGE_IS_FIXED
319*86d7f5d3SJohn Marino if (strcmp (vers->entdata->options ?
320*86d7f5d3SJohn Marino vers->entdata->options : "", vers->options) == 0)
321*86d7f5d3SJohn Marino ret = T_MODIFIED;
322*86d7f5d3SJohn Marino else
323*86d7f5d3SJohn Marino ret = T_NEEDS_MERGE;
324*86d7f5d3SJohn Marino #else
325*86d7f5d3SJohn Marino /* Files with conflict markers and new timestamps fall through
326*86d7f5d3SJohn Marino * here, but they need to. T_CONFLICT is an error in
327*86d7f5d3SJohn Marino * commit_fileproc, whereas T_MODIFIED with conflict markers
328*86d7f5d3SJohn Marino * is caught but only warned about. Similarly, update_fileproc
329*86d7f5d3SJohn Marino * currently reregisters a file that was conflicted but lost
330*86d7f5d3SJohn Marino * its markers.
331*86d7f5d3SJohn Marino */
332*86d7f5d3SJohn Marino ret = T_MODIFIED;
333*86d7f5d3SJohn Marino sticky_ck (finfo, aflag, vers);
334*86d7f5d3SJohn Marino #endif
335*86d7f5d3SJohn Marino }
336*86d7f5d3SJohn Marino else if (strcmp (vers->entdata->options ?
337*86d7f5d3SJohn Marino vers->entdata->options : "", vers->options) != 0)
338*86d7f5d3SJohn Marino {
339*86d7f5d3SJohn Marino /* file has not changed; check out if -k changed */
340*86d7f5d3SJohn Marino ret = T_CHECKOUT;
341*86d7f5d3SJohn Marino }
342*86d7f5d3SJohn Marino else
343*86d7f5d3SJohn Marino {
344*86d7f5d3SJohn Marino
345*86d7f5d3SJohn Marino /*
346*86d7f5d3SJohn Marino * else -> note that No_Difference will Register the
347*86d7f5d3SJohn Marino * file already for us, using the new tag/date. This
348*86d7f5d3SJohn Marino * is the desired behaviour
349*86d7f5d3SJohn Marino */
350*86d7f5d3SJohn Marino ret = T_UPTODATE;
351*86d7f5d3SJohn Marino }
352*86d7f5d3SJohn Marino }
353*86d7f5d3SJohn Marino else
354*86d7f5d3SJohn Marino {
355*86d7f5d3SJohn Marino /* The RCS file is a newer version than the user file */
356*86d7f5d3SJohn Marino
357*86d7f5d3SJohn Marino if (vers->ts_user == NULL)
358*86d7f5d3SJohn Marino {
359*86d7f5d3SJohn Marino /* There is no user file, so just get it */
360*86d7f5d3SJohn Marino
361*86d7f5d3SJohn Marino /* See comment at other "update" compare, for more
362*86d7f5d3SJohn Marino thoughts on this comparison. */
363*86d7f5d3SJohn Marino if (strcmp (cvs_cmd_name, "update") == 0)
364*86d7f5d3SJohn Marino if (!really_quiet)
365*86d7f5d3SJohn Marino error (0, 0, "warning: `%s' was lost", finfo->fullname);
366*86d7f5d3SJohn Marino ret = T_CHECKOUT;
367*86d7f5d3SJohn Marino }
368*86d7f5d3SJohn Marino else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
369*86d7f5d3SJohn Marino {
370*86d7f5d3SJohn Marino
371*86d7f5d3SJohn Marino /*
372*86d7f5d3SJohn Marino * The user file is still unmodified, so just get it as well
373*86d7f5d3SJohn Marino */
374*86d7f5d3SJohn Marino if (strcmp (vers->entdata->options ?
375*86d7f5d3SJohn Marino vers->entdata->options : "", vers->options) != 0
376*86d7f5d3SJohn Marino || (vers->srcfile != NULL
377*86d7f5d3SJohn Marino && (vers->srcfile->flags & INATTIC) != 0))
378*86d7f5d3SJohn Marino ret = T_CHECKOUT;
379*86d7f5d3SJohn Marino else
380*86d7f5d3SJohn Marino ret = T_PATCH;
381*86d7f5d3SJohn Marino }
382*86d7f5d3SJohn Marino else if (No_Difference (finfo, vers))
383*86d7f5d3SJohn Marino /* really modified, needs to merge */
384*86d7f5d3SJohn Marino ret = T_NEEDS_MERGE;
385*86d7f5d3SJohn Marino else if ((strcmp (vers->entdata->options ?
386*86d7f5d3SJohn Marino vers->entdata->options : "", vers->options)
387*86d7f5d3SJohn Marino != 0)
388*86d7f5d3SJohn Marino || (vers->srcfile != NULL
389*86d7f5d3SJohn Marino && (vers->srcfile->flags & INATTIC) != 0))
390*86d7f5d3SJohn Marino /* not really modified, check it out */
391*86d7f5d3SJohn Marino ret = T_CHECKOUT;
392*86d7f5d3SJohn Marino else
393*86d7f5d3SJohn Marino ret = T_PATCH;
394*86d7f5d3SJohn Marino }
395*86d7f5d3SJohn Marino }
396*86d7f5d3SJohn Marino
397*86d7f5d3SJohn Marino /* free up the vers struct, or just return it */
398*86d7f5d3SJohn Marino if (versp != NULL)
399*86d7f5d3SJohn Marino *versp = vers;
400*86d7f5d3SJohn Marino else
401*86d7f5d3SJohn Marino freevers_ts (&vers);
402*86d7f5d3SJohn Marino
403*86d7f5d3SJohn Marino /* return the status of the file */
404*86d7f5d3SJohn Marino return (ret);
405*86d7f5d3SJohn Marino }
406*86d7f5d3SJohn Marino
407*86d7f5d3SJohn Marino static void
sticky_ck(struct file_info * finfo,int aflag,Vers_TS * vers)408*86d7f5d3SJohn Marino sticky_ck (struct file_info *finfo, int aflag, Vers_TS *vers)
409*86d7f5d3SJohn Marino {
410*86d7f5d3SJohn Marino if (aflag || vers->tag || vers->date)
411*86d7f5d3SJohn Marino {
412*86d7f5d3SJohn Marino char *enttag = vers->entdata->tag;
413*86d7f5d3SJohn Marino char *entdate = vers->entdata->date;
414*86d7f5d3SJohn Marino
415*86d7f5d3SJohn Marino if ((enttag && vers->tag && strcmp (enttag, vers->tag)) ||
416*86d7f5d3SJohn Marino ((enttag && !vers->tag) || (!enttag && vers->tag)) ||
417*86d7f5d3SJohn Marino (entdate && vers->date && strcmp (entdate, vers->date)) ||
418*86d7f5d3SJohn Marino ((entdate && !vers->date) || (!entdate && vers->date)))
419*86d7f5d3SJohn Marino {
420*86d7f5d3SJohn Marino Register (finfo->entries, finfo->file, vers->vn_user, vers->ts_rcs,
421*86d7f5d3SJohn Marino vers->options, vers->tag, vers->date, vers->ts_conflict);
422*86d7f5d3SJohn Marino
423*86d7f5d3SJohn Marino #ifdef SERVER_SUPPORT
424*86d7f5d3SJohn Marino if (server_active)
425*86d7f5d3SJohn Marino {
426*86d7f5d3SJohn Marino /* We need to update the entries line on the client side.
427*86d7f5d3SJohn Marino It is possible we will later update it again via
428*86d7f5d3SJohn Marino server_updated or some such, but that is OK. */
429*86d7f5d3SJohn Marino server_update_entries
430*86d7f5d3SJohn Marino (finfo->file, finfo->update_dir, finfo->repository,
431*86d7f5d3SJohn Marino strcmp (vers->ts_rcs, vers->ts_user) == 0 ?
432*86d7f5d3SJohn Marino SERVER_UPDATED : SERVER_MERGED);
433*86d7f5d3SJohn Marino }
434*86d7f5d3SJohn Marino #endif
435*86d7f5d3SJohn Marino }
436*86d7f5d3SJohn Marino }
437*86d7f5d3SJohn Marino }
438