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 could be clearer. It comes up
144 * 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, as well as when a
147 * timestamp hasn't changed since a merge resulted in conflicts.
148 * It also comes up whether an update has been attempted or not, so
149 * technically, I think the double-add case is not actually a
152 sstat
= "Unresolved Conflict";
155 sstat
= "Locally Added";
158 sstat
= "Locally Removed";
161 if (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);
213 cvs_output (" Working revision:\t", 0);
214 cvs_output (vers
->vn_user
, 0);
216 /* Only add the UTC timezone if there is a time to use. */
217 if (!server_active
&& strlen (vers
->ts_rcs
) > 0)
219 /* Convert from the asctime() format to ISO 8601 */
222 cvs_output ("\t", 0);
224 /* Allow conversion from CVS/Entries asctime() to ISO 8601 */
225 buf
= Xasprintf ("%s UTC", vers
->ts_rcs
);
226 cvs_output_tagged ("date", buf
);
229 cvs_output ("\n", 0);
232 if (vers
->vn_rcs
== NULL
)
233 cvs_output (" Repository revision:\tNo revision control file\n", 0);
236 cvs_output (" Repository revision:\t", 0);
237 cvs_output (vers
->vn_rcs
, 0);
238 cvs_output ("\t", 0);
239 cvs_output (vers
->srcfile
->print_path
, 0);
240 cvs_output ("\n", 0);
242 node
= findnode(vers
->srcfile
->versions
,vers
->vn_rcs
);
246 v
=(RCSVers
*)node
->data
;
247 node
= findnode(v
->other_delta
,"commitid");
248 cvs_output(" Commit Identifier:\t", 0);
249 if(node
&& node
->data
)
250 cvs_output(node
->data
, 0);
252 cvs_output("(none)",0);
261 edata
= vers
->entdata
;
264 if (vers
->vn_rcs
== NULL
)
266 cvs_output (" Sticky Tag:\t\t", 0);
267 cvs_output (edata
->tag
, 0);
268 cvs_output (" - MISSING from RCS file!\n", 0);
272 if (isdigit ((unsigned char) edata
->tag
[0]))
274 cvs_output (" Sticky Tag:\t\t", 0);
275 cvs_output (edata
->tag
, 0);
276 cvs_output ("\n", 0);
282 if (RCS_nodeisbranch (finfo
->rcs
, edata
->tag
))
283 branch
= RCS_whatbranch(finfo
->rcs
, edata
->tag
);
285 cvs_output (" Sticky Tag:\t\t", 0);
286 cvs_output (edata
->tag
, 0);
287 cvs_output (" (", 0);
288 cvs_output (branch
? "branch" : "revision", 0);
289 cvs_output (": ", 0);
290 cvs_output (branch
? branch
: vers
->vn_rcs
, 0);
291 cvs_output (")\n", 0);
298 else if (!really_quiet
)
299 cvs_output (" Sticky Tag:\t\t(none)\n", 0);
303 cvs_output (" Sticky Date:\t\t", 0);
304 cvs_output (edata
->date
, 0);
305 cvs_output ("\n", 0);
307 else if (!really_quiet
)
308 cvs_output (" Sticky Date:\t\t(none)\n", 0);
310 if (edata
->options
&& edata
->options
[0])
312 cvs_output (" Sticky Options:\t", 0);
313 cvs_output (edata
->options
, 0);
314 cvs_output ("\n", 0);
316 else if (!really_quiet
)
317 cvs_output (" Sticky Options:\t(none)\n", 0);
320 if (long_format
&& vers
->srcfile
)
322 List
*symbols
= RCS_symbols(vers
->srcfile
);
324 cvs_output ("\n Existing Tags:\n", 0);
327 xrcsnode
= finfo
->rcs
;
328 (void) walklist (symbols
, tag_list_proc
, NULL
);
331 cvs_output ("\tNo Tags Exist\n", 0);
334 cvs_output ("\n", 0);
342 * Print a warm fuzzy message
346 status_dirproc (void *callerdat
, const char *dir
, const char *repos
,
347 const char *update_dir
, List
*entries
)
350 error (0, 0, "Examining %s", update_dir
);
357 * Print out a tag and its type
360 tag_list_proc (Node
*p
, void *closure
)
365 if (RCS_nodeisbranch (xrcsnode
, p
->key
))
366 branch
= RCS_whatbranch(xrcsnode
, p
->key
) ;
368 buf
= Xasprintf ("\t%-25s\t(%s: %s)\n", p
->key
,
369 branch
? "branch" : "revision",
370 branch
? branch
: (char *)p
->data
);