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.
13 static Dtype status_dirproc PROTO ((void *callerdat, const char *dir,
14 const char *repos, const char *update_dir,
16 static int status_fileproc PROTO ((void *callerdat, struct file_info *finfo));
17 static int tag_list_proc PROTO((Node * p, void *closure));
20 static int long_format = 0;
21 static RCSNode *xrcsnode;
23 static const char *const status_usage[] =
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",
34 cvsstatus (argc, argv)
45 while ((c = getopt (argc, argv, "+vlR")) != -1)
70 if (current_parsed_root->isremote)
82 /* For a while, we tried setting SEND_NO_CONTENTS here so this
83 could be a fast operation. That prevents the
84 server from updating our timestamp if the timestamp is
85 changed but the file is unmodified. Worse, it is user-visible
86 (shows "locally modified" instead of "up to date" if
87 timestamp is changed but file is not). And there is no good
88 workaround (you might not want to run "cvs update"; "cvs -n
89 update" doesn't update CVS/Entries; "cvs diff --brief" or
90 something perhaps could be made to work but somehow that
91 seems nonintuitive to me even if so). Given that timestamps
92 seem to have the potential to get munged for any number of
93 reasons, it seems better to not rely too much on them. */
95 send_files (argc, argv, local, 0, 0);
97 send_file_names (argc, argv, SEND_EXPAND_WILD);
99 send_to_server ("status\012", 0);
100 err = get_responses_and_close ();
106 /* start the recursion processor */
107 err = start_recursion (status_fileproc, (FILESDONEPROC) NULL,
108 status_dirproc, (DIRLEAVEPROC) NULL, NULL,
110 W_LOCAL, 0, CVS_LOCK_READ, (char *) NULL, 1,
117 * display the status of a file
121 status_fileproc (callerdat, finfo)
123 struct file_info *finfo;
129 status = Classify_File (finfo, (char *) NULL, (char *) NULL, (char *) NULL,
131 sstat = "Classify Error";
138 sstat = "Needs Checkout";
141 sstat = "Needs Patch";
144 /* I _think_ that "unresolved" is correct; that if it has
145 been resolved then the status will change. But I'm not
147 sstat = "Unresolved Conflict";
150 sstat = "Locally Added";
153 sstat = "Locally Removed";
156 if ( vers->ts_conflict
157 && ( file_has_conflict ( finfo, vers->ts_conflict )
158 || file_has_markers ( finfo ) ) )
159 sstat = "File had conflicts on merge";
161 /* Note that we do not re Register() the file when we spot
162 * a resolved conflict like update_fileproc() does on the
163 * premise that status should not alter the sandbox.
165 sstat = "Locally Modified";
168 sstat = "Entry Invalid";
171 sstat = "Up-to-date";
174 sstat = "Needs Merge";
177 /* I don't think this case can occur here. Just print
183 ===================================================================\n", 0);
184 if (vers->ts_user == NULL)
186 cvs_output ("File: no file ", 0);
187 cvs_output (finfo->file, 0);
188 cvs_output ("\t\tStatus: ", 0);
189 cvs_output (sstat, 0);
190 cvs_output ("\n\n", 0);
195 buf = xmalloc (strlen (finfo->file) + strlen (sstat) + 80);
196 sprintf (buf, "File: %-17s\tStatus: %s\n\n", finfo->file, sstat);
201 if (vers->vn_user == NULL)
203 cvs_output (" Working revision:\tNo entry for ", 0);
204 cvs_output (finfo->file, 0);
205 cvs_output ("\n", 0);
207 else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
208 cvs_output (" Working revision:\tNew file!\n", 0);
209 #ifdef SERVER_SUPPORT
210 else if (server_active)
212 cvs_output (" Working revision:\t", 0);
213 cvs_output (vers->vn_user, 0);
214 cvs_output ("\n", 0);
219 cvs_output (" Working revision:\t", 0);
220 cvs_output (vers->vn_user, 0);
221 cvs_output ("\t", 0);
222 cvs_output (vers->ts_rcs, 0);
223 cvs_output ("\n", 0);
226 if (vers->vn_rcs == NULL)
227 cvs_output (" Repository revision:\tNo revision control file\n", 0);
230 cvs_output (" Repository revision:\t", 0);
231 cvs_output (vers->vn_rcs, 0);
232 cvs_output ("\t", 0);
233 cvs_output (vers->srcfile->path, 0);
234 cvs_output ("\n", 0);
241 edata = vers->entdata;
244 if (vers->vn_rcs == NULL)
246 cvs_output (" Sticky Tag:\t\t", 0);
247 cvs_output (edata->tag, 0);
248 cvs_output (" - MISSING from RCS file!\n", 0);
252 if (isdigit ((unsigned char) edata->tag[0]))
254 cvs_output (" Sticky Tag:\t\t", 0);
255 cvs_output (edata->tag, 0);
256 cvs_output ("\n", 0);
262 if (RCS_nodeisbranch (finfo->rcs, edata->tag))
263 branch = RCS_whatbranch(finfo->rcs, edata->tag);
265 cvs_output (" Sticky Tag:\t\t", 0);
266 cvs_output (edata->tag, 0);
267 cvs_output (" (", 0);
268 cvs_output (branch ? "branch" : "revision", 0);
269 cvs_output (": ", 0);
270 cvs_output (branch ? branch : vers->vn_rcs, 0);
271 cvs_output (")\n", 0);
278 else if (!really_quiet)
279 cvs_output (" Sticky Tag:\t\t(none)\n", 0);
283 cvs_output (" Sticky Date:\t\t", 0);
284 cvs_output (edata->date, 0);
285 cvs_output ("\n", 0);
287 else if (!really_quiet)
288 cvs_output (" Sticky Date:\t\t(none)\n", 0);
290 if (edata->options && edata->options[0])
292 cvs_output (" Sticky Options:\t", 0);
293 cvs_output (edata->options, 0);
294 cvs_output ("\n", 0);
296 else if (!really_quiet)
297 cvs_output (" Sticky Options:\t(none)\n", 0);
300 if (long_format && vers->srcfile)
302 List *symbols = RCS_symbols(vers->srcfile);
304 cvs_output ("\n Existing Tags:\n", 0);
307 xrcsnode = finfo->rcs;
308 (void) walklist (symbols, tag_list_proc, NULL);
311 cvs_output ("\tNo Tags Exist\n", 0);
314 cvs_output ("\n", 0);
320 * Print a warm fuzzy message
324 status_dirproc (callerdat, dir, repos, update_dir, entries)
328 const char *update_dir;
332 error (0, 0, "Examining %s", update_dir);
337 * Print out a tag and its type
340 tag_list_proc (p, closure)
347 if (RCS_nodeisbranch (xrcsnode, p->key))
348 branch = RCS_whatbranch(xrcsnode, p->key) ;
350 buf = xmalloc (80 + strlen (p->key)
351 + (branch ? strlen (branch) : strlen (p->data)));
352 sprintf (buf, "\t%-25s\t(%s: %s)\n", p->key,
353 branch ? "branch" : "revision",
354 branch ? branch : (char *)p->data);