]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/cvs/src/status.c
This commit was generated by cvs2svn to compensate for changes in r55682,
[FreeBSD/FreeBSD.git] / contrib / cvs / src / status.c
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 source distribution.
7  * 
8  * Status Information
9  */
10
11 #include "cvs.h"
12
13 static Dtype status_dirproc PROTO ((void *callerdat, char *dir,
14                                     char *repos, char *update_dir,
15                                     List *entries));
16 static int status_fileproc PROTO ((void *callerdat, struct file_info *finfo));
17 static int tag_list_proc PROTO((Node * p, void *closure));
18
19 static int local = 0;
20 static int long_format = 0;
21 static RCSNode *xrcsnode;
22
23 static const char *const status_usage[] =
24 {
25     "Usage: %s %s [-vlR] [files...]\n",
26     "\t-v\tVerbose format; includes tag information for the file\n",
27     "\t-l\tProcess this directory only (not recursive).\n",
28     "\t-R\tProcess directories recursively.\n",
29     "(Specify the --help global option for a list of other help options)\n",
30     NULL
31 };
32
33 int
34 cvsstatus (argc, argv)
35     int argc;
36     char **argv;
37 {
38     int c;
39     int err = 0;
40
41     if (argc == -1)
42         usage (status_usage);
43
44     optind = 0;
45     while ((c = getopt (argc, argv, "+vlR")) != -1)
46     {
47         switch (c)
48         {
49             case 'v':
50                 long_format = 1;
51                 break;
52             case 'l':
53                 local = 1;
54                 break;
55             case 'R':
56                 local = 0;
57                 break;
58             case '?':
59             default:
60                 usage (status_usage);
61                 break;
62         }
63     }
64     argc -= optind;
65     argv += optind;
66
67     wrap_setup ();
68
69 #ifdef CLIENT_SUPPORT
70     if (client_active)
71     {
72         start_server ();
73
74         ign_setup ();
75
76         if (long_format)
77             send_arg("-v");
78         if (local)
79             send_arg("-l");
80
81         /* For a while, we tried setting SEND_NO_CONTENTS here so this
82            could be a fast operation.  That prevents the
83            server from updating our timestamp if the timestamp is
84            changed but the file is unmodified.  Worse, it is user-visible
85            (shows "locally modified" instead of "up to date" if
86            timestamp is changed but file is not).  And there is no good
87            workaround (you might not want to run "cvs update"; "cvs -n
88            update" doesn't update CVS/Entries; "cvs diff --brief" or
89            something perhaps could be made to work but somehow that
90            seems nonintuitive to me even if so).  Given that timestamps
91            seem to have the potential to get munged for any number of
92            reasons, it seems better to not rely too much on them.  */
93
94         send_files (argc, argv, local, 0, 0);
95
96         send_file_names (argc, argv, SEND_EXPAND_WILD);
97
98         send_to_server ("status\012", 0);
99         err = get_responses_and_close ();
100
101         return err;
102     }
103 #endif
104
105     /* start the recursion processor */
106     err = start_recursion (status_fileproc, (FILESDONEPROC) NULL,
107                            status_dirproc, (DIRLEAVEPROC) NULL, NULL,
108                            argc, argv, local,
109                            W_LOCAL, 0, 1, (char *) NULL, 1);
110
111     return (err);
112 }
113
114 /*
115  * display the status of a file
116  */
117 /* ARGSUSED */
118 static int
119 status_fileproc (callerdat, finfo)
120     void *callerdat;
121     struct file_info *finfo;
122 {
123     Ctype status;
124     char *sstat;
125     Vers_TS *vers;
126
127     status = Classify_File (finfo, (char *) NULL, (char *) NULL, (char *) NULL,
128                             1, 0, &vers, 0);
129     sstat = "Classify Error";
130     switch (status)
131     {
132         case T_UNKNOWN:
133             sstat = "Unknown";
134             break;
135         case T_CHECKOUT:
136             sstat = "Needs Checkout";
137             break;
138 #ifdef SERVER_SUPPORT
139         case T_PATCH:
140             sstat = "Needs Patch";
141             break;
142 #endif
143         case T_CONFLICT:
144             /* I _think_ that "unresolved" is correct; that if it has
145                been resolved then the status will change.  But I'm not
146                sure about that.  */
147             sstat = "Unresolved Conflict";
148             break;
149         case T_ADDED:
150             sstat = "Locally Added";
151             break;
152         case T_REMOVED:
153             sstat = "Locally Removed";
154             break;
155         case T_MODIFIED:
156             if (vers->ts_conflict)
157                 sstat = "File had conflicts on merge";
158             else
159                 sstat = "Locally Modified";
160             break;
161         case T_REMOVE_ENTRY:
162             sstat = "Entry Invalid";
163             break;
164         case T_UPTODATE:
165             sstat = "Up-to-date";
166             break;
167         case T_NEEDS_MERGE:
168             sstat = "Needs Merge";
169             break;
170         case T_TITLE:
171             /* I don't think this case can occur here.  Just print
172                "Classify Error".  */
173             break;
174     }
175
176     cvs_output ("\
177 ===================================================================\n", 0);
178     if (vers->ts_user == NULL)
179     {
180         cvs_output ("File: no file ", 0);
181         cvs_output (finfo->file, 0);
182         cvs_output ("\t\tStatus: ", 0);
183         cvs_output (sstat, 0);
184         cvs_output ("\n\n", 0);
185     }
186     else
187     {
188         char *buf;
189         buf = xmalloc (strlen (finfo->file) + strlen (sstat) + 80);
190         sprintf (buf, "File: %-17s\tStatus: %s\n\n", finfo->file, sstat);
191         cvs_output (buf, 0);
192         free (buf);
193     }
194
195     if (vers->vn_user == NULL)
196     {
197         cvs_output ("   Working revision:\tNo entry for ", 0);
198         cvs_output (finfo->file, 0);
199         cvs_output ("\n", 0);
200     }
201     else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
202         cvs_output ("   Working revision:\tNew file!\n", 0);
203 #ifdef SERVER_SUPPORT
204     else if (server_active)
205     {
206         cvs_output ("   Working revision:\t", 0);
207         cvs_output (vers->vn_user, 0);
208         cvs_output ("\n", 0);
209     }
210 #endif
211     else
212     {
213         cvs_output ("   Working revision:\t", 0);
214         cvs_output (vers->vn_user, 0);
215         cvs_output ("\t", 0);
216         cvs_output (vers->ts_rcs, 0);
217         cvs_output ("\n", 0);
218     }
219
220     if (vers->vn_rcs == NULL)
221         cvs_output ("   Repository revision:\tNo revision control file\n", 0);
222     else
223     {
224         cvs_output ("   Repository revision:\t", 0);
225         cvs_output (vers->vn_rcs, 0);
226         cvs_output ("\t", 0);
227         cvs_output (vers->srcfile->path, 0);
228         cvs_output ("\n", 0);
229     }
230
231     if (vers->entdata)
232     {
233         Entnode *edata;
234
235         edata = vers->entdata;
236         if (edata->tag)
237         {
238             if (vers->vn_rcs == NULL)
239             {
240                 cvs_output ("   Sticky Tag:\t\t", 0);
241                 cvs_output (edata->tag, 0);
242                 cvs_output (" - MISSING from RCS file!\n", 0);
243             }
244             else
245             {
246                 if (isdigit ((unsigned char) edata->tag[0]))
247                 {
248                     cvs_output ("   Sticky Tag:\t\t", 0);
249                     cvs_output (edata->tag, 0);
250                     cvs_output ("\n", 0);
251                 }
252                 else
253                 {
254                     char *branch = NULL;
255
256                     if (RCS_nodeisbranch (finfo->rcs, edata->tag))
257                         branch = RCS_whatbranch(finfo->rcs, edata->tag);
258
259                     cvs_output ("   Sticky Tag:\t\t", 0);
260                     cvs_output (edata->tag, 0);
261                     cvs_output (" (", 0);
262                     cvs_output (branch ? "branch" : "revision", 0);
263                     cvs_output (": ", 0);
264                     cvs_output (branch ? branch : vers->vn_rcs, 0);
265                     cvs_output (")\n", 0);
266
267                     if (branch)
268                         free (branch);
269                 }
270             }
271         }
272         else if (!really_quiet)
273             cvs_output ("   Sticky Tag:\t\t(none)\n", 0);
274
275         if (edata->date)
276         {
277             cvs_output ("   Sticky Date:\t\t", 0);
278             cvs_output (edata->date, 0);
279             cvs_output ("\n", 0);
280         }
281         else if (!really_quiet)
282             cvs_output ("   Sticky Date:\t\t(none)\n", 0);
283
284         if (edata->options && edata->options[0])
285         {
286             cvs_output ("   Sticky Options:\t", 0);
287             cvs_output (edata->options, 0);
288             cvs_output ("\n", 0);
289         }
290         else if (!really_quiet)
291             cvs_output ("   Sticky Options:\t(none)\n", 0);
292     }
293
294     if (long_format && vers->srcfile)
295     {
296         List *symbols = RCS_symbols(vers->srcfile);
297
298         cvs_output ("\n   Existing Tags:\n", 0);
299         if (symbols)
300         {
301             xrcsnode = finfo->rcs;
302             (void) walklist (symbols, tag_list_proc, NULL);
303         }
304         else
305             cvs_output ("\tNo Tags Exist\n", 0);
306     }
307
308     cvs_output ("\n", 0);
309     freevers_ts (&vers);
310     return (0);
311 }
312
313 /*
314  * Print a warm fuzzy message
315  */
316 /* ARGSUSED */
317 static Dtype
318 status_dirproc (callerdat, dir, repos, update_dir, entries)
319     void *callerdat;
320     char *dir;
321     char *repos;
322     char *update_dir;
323     List *entries;
324 {
325     if (!quiet)
326         error (0, 0, "Examining %s", update_dir);
327     return (R_PROCESS);
328 }
329
330 /*
331  * Print out a tag and its type
332  */
333 static int
334 tag_list_proc (p, closure)
335     Node *p;
336     void *closure;
337 {
338     char *branch = NULL;
339     char *buf;
340
341     if (RCS_nodeisbranch (xrcsnode, p->key))
342         branch = RCS_whatbranch(xrcsnode, p->key) ;
343
344     buf = xmalloc (80 + strlen (p->key)
345                    + (branch ? strlen (branch) : strlen (p->data)));
346     sprintf (buf, "\t%-25s\t(%s: %s)\n", p->key,
347              branch ? "branch" : "revision",
348              branch ? branch : p->data);
349     cvs_output (buf, 0);
350     free (buf);
351
352     if (branch)
353         free (branch);
354
355     return (0);
356 }