2 * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
4 * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
7 * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8 * Portions Copyright (C) 1989-1992, Brian Berliner
10 * You may distribute under the terms of the GNU General Public License as
11 * specified in the README file that comes with the CVS source distribution.
18 static Dtype status_dirproc (void *callerdat, const char *dir,
19 const char *repos, const char *update_dir,
21 static int status_fileproc (void *callerdat, struct file_info *finfo);
22 static int tag_list_proc (Node * p, void *closure);
25 static int long_format = 0;
26 static RCSNode *xrcsnode;
28 static const char *const status_usage[] =
30 "Usage: %s %s [-vlR] [files...]\n",
31 "\t-v\tVerbose format; includes tag information for the file\n",
32 "\t-l\tProcess this directory only (not recursive).\n",
33 "\t-R\tProcess directories recursively.\n",
34 "(Specify the --help global option for a list of other help options)\n",
39 cvsstatus (int argc, char **argv)
48 while ((c = getopt (argc, argv, "+vlR")) != -1)
73 if (current_parsed_root->isremote)
85 /* For a while, we tried setting SEND_NO_CONTENTS here so this
86 could be a fast operation. That prevents the
87 server from updating our timestamp if the timestamp is
88 changed but the file is unmodified. Worse, it is user-visible
89 (shows "locally modified" instead of "up to date" if
90 timestamp is changed but file is not). And there is no good
91 workaround (you might not want to run "cvs update"; "cvs -n
92 update" doesn't update CVS/Entries; "cvs diff --brief" or
93 something perhaps could be made to work but somehow that
94 seems nonintuitive to me even if so). Given that timestamps
95 seem to have the potential to get munged for any number of
96 reasons, it seems better to not rely too much on them. */
98 send_files (argc, argv, local, 0, 0);
100 send_file_names (argc, argv, SEND_EXPAND_WILD);
102 send_to_server ("status\012", 0);
103 err = get_responses_and_close ();
109 /* start the recursion processor */
110 err = start_recursion (status_fileproc, NULL, status_dirproc,
111 NULL, NULL, argc, argv, local, W_LOCAL,
112 0, CVS_LOCK_READ, NULL, 1, NULL);
118 * display the status of a file
122 status_fileproc (void *callerdat, struct file_info *finfo)
129 status = Classify_File (finfo, NULL, NULL, NULL, 1, 0, &vers, 0);
130 sstat = "Classify Error";
137 sstat = "Needs Checkout";
140 sstat = "Needs Patch";
143 /* FIXME - This message needs to be clearer. It comes up now
144 * only when a file exists or has been added in the local sandbox
145 * and a file of the same name has been committed indepenently to
146 * the repository from a different sandbox. It also comes up
147 * whether an update has been attempted or not, so technically, I
148 * think it is not actually a conflict yet.
150 sstat = "Unresolved Conflict";
153 sstat = "Locally Added";
156 sstat = "Locally Removed";
159 if ( vers->ts_conflict
160 && ( file_has_conflict ( finfo, vers->ts_conflict )
161 || file_has_markers ( finfo ) ) )
162 sstat = "File had conflicts on merge";
164 /* Note that we do not re Register() the file when we spot
165 * a resolved conflict like update_fileproc() does on the
166 * premise that status should not alter the sandbox.
168 sstat = "Locally Modified";
171 sstat = "Entry Invalid";
174 sstat = "Up-to-date";
177 sstat = "Needs Merge";
180 /* I don't think this case can occur here. Just print
186 ===================================================================\n", 0);
187 if (vers->ts_user == NULL)
189 cvs_output ("File: no file ", 0);
190 cvs_output (finfo->file, 0);
191 cvs_output ("\t\tStatus: ", 0);
192 cvs_output (sstat, 0);
193 cvs_output ("\n\n", 0);
198 buf = Xasprintf ("File: %-17s\tStatus: %s\n\n", finfo->file, sstat);
203 if (vers->vn_user == NULL)
205 cvs_output (" Working revision:\tNo entry for ", 0);
206 cvs_output (finfo->file, 0);
207 cvs_output ("\n", 0);
209 else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
210 cvs_output (" Working revision:\tNew file!\n", 0);
211 #ifdef SERVER_SUPPORT
212 else if (server_active)
214 cvs_output (" Working revision:\t", 0);
215 cvs_output (vers->vn_user, 0);
216 cvs_output ("\n", 0);
221 cvs_output (" Working revision:\t", 0);
222 cvs_output (vers->vn_user, 0);
224 /* Only add the UTC timezone if there is a time to use. */
225 if (strlen (vers->ts_rcs) > 0)
227 /* Convert from the asctime() format to ISO 8601 */
230 cvs_output ("\t", 0);
232 /* Allow conversion from CVS/Entries asctime() to ISO 8601 */
233 buf = Xasprintf ("%s UTC", vers->ts_rcs);
234 cvs_output_tagged ("date", buf);
237 cvs_output ("\n", 0);
240 if (vers->vn_rcs == NULL)
241 cvs_output (" Repository revision:\tNo revision control file\n", 0);
244 cvs_output (" Repository revision:\t", 0);
245 cvs_output (vers->vn_rcs, 0);
246 cvs_output ("\t", 0);
247 cvs_output (vers->srcfile->print_path, 0);
248 cvs_output ("\n", 0);
250 node = findnode(vers->srcfile->versions,vers->vn_rcs);
254 v=(RCSVers*)node->data;
255 node = findnode(v->other_delta,"commitid");
256 cvs_output(" Commit Identifier:\t", 0);
257 if(node && node->data)
258 cvs_output(node->data, 0);
260 cvs_output("(none)",0);
269 edata = vers->entdata;
272 if (vers->vn_rcs == NULL)
274 cvs_output (" Sticky Tag:\t\t", 0);
275 cvs_output (edata->tag, 0);
276 cvs_output (" - MISSING from RCS file!\n", 0);
280 if (isdigit ((unsigned char) edata->tag[0]))
282 cvs_output (" Sticky Tag:\t\t", 0);
283 cvs_output (edata->tag, 0);
284 cvs_output ("\n", 0);
290 if (RCS_nodeisbranch (finfo->rcs, edata->tag))
291 branch = RCS_whatbranch(finfo->rcs, edata->tag);
293 cvs_output (" Sticky Tag:\t\t", 0);
294 cvs_output (edata->tag, 0);
295 cvs_output (" (", 0);
296 cvs_output (branch ? "branch" : "revision", 0);
297 cvs_output (": ", 0);
298 cvs_output (branch ? branch : vers->vn_rcs, 0);
299 cvs_output (")\n", 0);
306 else if (!really_quiet)
307 cvs_output (" Sticky Tag:\t\t(none)\n", 0);
311 cvs_output (" Sticky Date:\t\t", 0);
312 cvs_output (edata->date, 0);
313 cvs_output ("\n", 0);
315 else if (!really_quiet)
316 cvs_output (" Sticky Date:\t\t(none)\n", 0);
318 if (edata->options && edata->options[0])
320 cvs_output (" Sticky Options:\t", 0);
321 cvs_output (edata->options, 0);
322 cvs_output ("\n", 0);
324 else if (!really_quiet)
325 cvs_output (" Sticky Options:\t(none)\n", 0);
328 if (long_format && vers->srcfile)
330 List *symbols = RCS_symbols(vers->srcfile);
332 cvs_output ("\n Existing Tags:\n", 0);
335 xrcsnode = finfo->rcs;
336 (void) walklist (symbols, tag_list_proc, NULL);
339 cvs_output ("\tNo Tags Exist\n", 0);
342 cvs_output ("\n", 0);
350 * Print a warm fuzzy message
354 status_dirproc (void *callerdat, const char *dir, const char *repos,
355 const char *update_dir, List *entries)
358 error (0, 0, "Examining %s", update_dir);
365 * Print out a tag and its type
368 tag_list_proc (Node *p, void *closure)
373 if (RCS_nodeisbranch (xrcsnode, p->key))
374 branch = RCS_whatbranch(xrcsnode, p->key) ;
376 buf = Xasprintf ("\t%-25s\t(%s: %s)\n", p->key,
377 branch ? "branch" : "revision",
378 branch ? branch : (char *)p->data);