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 (void *callerdat, const char *dir,
14 const char *repos, const char *update_dir,
16 static int status_fileproc (void *callerdat, struct file_info *finfo);
17 static int tag_list_proc (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 (int argc, char **argv)
43 while ((c = getopt (argc, argv, "+vlR")) != -1)
68 if (current_parsed_root->isremote)
80 /* For a while, we tried setting SEND_NO_CONTENTS here so this
81 could be a fast operation. That prevents the
82 server from updating our timestamp if the timestamp is
83 changed but the file is unmodified. Worse, it is user-visible
84 (shows "locally modified" instead of "up to date" if
85 timestamp is changed but file is not). And there is no good
86 workaround (you might not want to run "cvs update"; "cvs -n
87 update" doesn't update CVS/Entries; "cvs diff --brief" or
88 something perhaps could be made to work but somehow that
89 seems nonintuitive to me even if so). Given that timestamps
90 seem to have the potential to get munged for any number of
91 reasons, it seems better to not rely too much on them. */
93 send_files (argc, argv, local, 0, 0);
95 send_file_names (argc, argv, SEND_EXPAND_WILD);
97 send_to_server ("status\012", 0);
98 err = get_responses_and_close ();
104 /* start the recursion processor */
105 err = start_recursion
106 ( status_fileproc, (FILESDONEPROC) NULL,
107 status_dirproc, (DIRLEAVEPROC) NULL, NULL, argc, argv, local,
108 W_LOCAL, 0, CVS_LOCK_READ, (char *) NULL, 1, (char *) NULL);
114 * display the status of a file
118 status_fileproc (void *callerdat, struct file_info *finfo)
124 status = Classify_File (finfo, (char *) NULL, (char *) NULL, (char *) NULL,
126 sstat = "Classify Error";
133 sstat = "Needs Checkout";
136 sstat = "Needs Patch";
139 /* FIXME - This message needs to be clearer. It comes up now
140 * only when a file exists or has been added in the local sandbox
141 * and a file of the same name has been committed indepenently to
142 * the repository from a different sandbox. It also comes up
143 * whether an update has been attempted or not, so technically, I
144 * think it is not actually a conflict yet.
146 sstat = "Unresolved Conflict";
149 sstat = "Locally Added";
152 sstat = "Locally Removed";
155 if ( vers->ts_conflict
156 && ( file_has_conflict ( finfo, vers->ts_conflict )
157 || file_has_markers ( finfo ) ) )
158 sstat = "File had conflicts on merge";
160 /* Note that we do not re Register() the file when we spot
161 * a resolved conflict like update_fileproc() does on the
162 * premise that status should not alter the sandbox.
164 sstat = "Locally Modified";
167 sstat = "Entry Invalid";
170 sstat = "Up-to-date";
173 sstat = "Needs Merge";
176 /* I don't think this case can occur here. Just print
182 ===================================================================\n", 0);
183 if (vers->ts_user == NULL)
185 cvs_output ("File: no file ", 0);
186 cvs_output (finfo->file, 0);
187 cvs_output ("\t\tStatus: ", 0);
188 cvs_output (sstat, 0);
189 cvs_output ("\n\n", 0);
194 buf = xmalloc (strlen (finfo->file) + strlen (sstat) + 80);
195 sprintf (buf, "File: %-17s\tStatus: %s\n\n", finfo->file, sstat);
200 if (vers->vn_user == NULL)
202 cvs_output (" Working revision:\tNo entry for ", 0);
203 cvs_output (finfo->file, 0);
204 cvs_output ("\n", 0);
206 else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
207 cvs_output (" Working revision:\tNew file!\n", 0);
208 #ifdef SERVER_SUPPORT
209 else if (server_active)
211 cvs_output (" Working revision:\t", 0);
212 cvs_output (vers->vn_user, 0);
213 cvs_output ("\n", 0);
218 cvs_output (" Working revision:\t", 0);
219 cvs_output (vers->vn_user, 0);
220 cvs_output ("\t", 0);
221 cvs_output (vers->ts_rcs, 0);
222 cvs_output ("\n", 0);
225 if (vers->vn_rcs == NULL)
226 cvs_output (" Repository revision:\tNo revision control file\n", 0);
229 cvs_output (" Repository revision:\t", 0);
230 cvs_output (vers->vn_rcs, 0);
231 cvs_output ("\t", 0);
232 cvs_output (vers->srcfile->path, 0);
233 cvs_output ("\n", 0);
240 edata = vers->entdata;
243 if (vers->vn_rcs == NULL)
245 cvs_output (" Sticky Tag:\t\t", 0);
246 cvs_output (edata->tag, 0);
247 cvs_output (" - MISSING from RCS file!\n", 0);
251 if (isdigit ((unsigned char) edata->tag[0]))
253 cvs_output (" Sticky Tag:\t\t", 0);
254 cvs_output (edata->tag, 0);
255 cvs_output ("\n", 0);
261 if (RCS_nodeisbranch (finfo->rcs, edata->tag))
262 branch = RCS_whatbranch(finfo->rcs, edata->tag);
264 cvs_output (" Sticky Tag:\t\t", 0);
265 cvs_output (edata->tag, 0);
266 cvs_output (" (", 0);
267 cvs_output (branch ? "branch" : "revision", 0);
268 cvs_output (": ", 0);
269 cvs_output (branch ? branch : vers->vn_rcs, 0);
270 cvs_output (")\n", 0);
277 else if (!really_quiet)
278 cvs_output (" Sticky Tag:\t\t(none)\n", 0);
282 cvs_output (" Sticky Date:\t\t", 0);
283 cvs_output (edata->date, 0);
284 cvs_output ("\n", 0);
286 else if (!really_quiet)
287 cvs_output (" Sticky Date:\t\t(none)\n", 0);
289 if (edata->options && edata->options[0])
291 cvs_output (" Sticky Options:\t", 0);
292 cvs_output (edata->options, 0);
293 cvs_output ("\n", 0);
295 else if (!really_quiet)
296 cvs_output (" Sticky Options:\t(none)\n", 0);
299 if (long_format && vers->srcfile)
301 List *symbols = RCS_symbols(vers->srcfile);
303 cvs_output ("\n Existing Tags:\n", 0);
306 xrcsnode = finfo->rcs;
307 (void) walklist (symbols, tag_list_proc, NULL);
310 cvs_output ("\tNo Tags Exist\n", 0);
313 cvs_output ("\n", 0);
321 * Print a warm fuzzy message
325 status_dirproc (void *callerdat, const char *dir, const char *repos,
326 const char *update_dir, List *entries)
329 error (0, 0, "Examining %s", update_dir);
336 * Print out a tag and its type
339 tag_list_proc (Node *p, void *closure)
344 if (RCS_nodeisbranch (xrcsnode, p->key))
345 branch = RCS_whatbranch(xrcsnode, p->key) ;
347 buf = xmalloc (80 + strlen (p->key)
348 + (branch ? strlen (branch) : strlen (p->data)));
349 sprintf (buf, "\t%-25s\t(%s: %s)\n", p->key,
350 branch ? "branch" : "revision",
351 branch ? branch : (char *)p->data);