#include "cvs.h"
static Dtype status_dirproc (void *callerdat, const char *dir,
const char *repos, const char *update_dir,
List *entries);
static int status_fileproc (void *callerdat, struct file_info *finfo);
static int tag_list_proc (Node * p, void *closure);
static int local = 0;
static int long_format = 0;
static RCSNode *xrcsnode;
static const char *const status_usage[] =
{
"Usage: %s %s [-vlR] [files...]\n",
"\t-v\tVerbose format; includes tag information for the file\n",
"\t-l\tProcess this directory only (not recursive).\n",
"\t-R\tProcess directories recursively.\n",
"(Specify the --help global option for a list of other help options)\n",
NULL
};
int
cvsstatus (int argc, char **argv)
{
int c;
int err = 0;
if (argc == -1)
usage (status_usage);
optind = 0;
while ((c = getopt (argc, argv, "+vlR")) != -1)
{
switch (c)
{
case 'v':
long_format = 1;
break;
case 'l':
local = 1;
break;
case 'R':
local = 0;
break;
case '?':
default:
usage (status_usage);
break;
}
}
argc -= optind;
argv += optind;
wrap_setup ();
#ifdef CLIENT_SUPPORT
if (current_parsed_root->isremote)
{
start_server ();
ign_setup ();
if (long_format)
send_arg("-v");
if (local)
send_arg("-l");
send_arg ("--");
send_files (argc, argv, local, 0, 0);
send_file_names (argc, argv, SEND_EXPAND_WILD);
send_to_server ("status\012", 0);
err = get_responses_and_close ();
return err;
}
#endif
err = start_recursion (status_fileproc, NULL, status_dirproc,
NULL, NULL, argc, argv, local, W_LOCAL,
0, CVS_LOCK_READ, NULL, 1, NULL);
return (err);
}
static int
status_fileproc (void *callerdat, struct file_info *finfo)
{
Ctype status;
char *sstat;
Vers_TS *vers;
Node *node;
status = Classify_File (finfo, NULL, NULL, NULL, 1, 0, &vers, 0);
sstat = "Classify Error";
switch (status)
{
case T_UNKNOWN:
sstat = "Unknown";
break;
case T_CHECKOUT:
sstat = "Needs Checkout";
break;
case T_PATCH:
sstat = "Needs Patch";
break;
case T_CONFLICT:
sstat = "Unresolved Conflict";
break;
case T_ADDED:
sstat = "Locally Added";
break;
case T_REMOVED:
sstat = "Locally Removed";
break;
case T_MODIFIED:
if (file_has_markers (finfo))
sstat = "File had conflicts on merge";
else
sstat = "Locally Modified";
break;
case T_REMOVE_ENTRY:
sstat = "Entry Invalid";
break;
case T_UPTODATE:
sstat = "Up-to-date";
break;
case T_NEEDS_MERGE:
sstat = "Needs Merge";
break;
case T_TITLE:
break;
}
cvs_output ("\
===================================================================\n", 0);
if (vers->ts_user == NULL)
{
cvs_output ("File: no file ", 0);
cvs_output (finfo->file, 0);
cvs_output ("\t\tStatus: ", 0);
cvs_output (sstat, 0);
cvs_output ("\n\n", 0);
}
else
{
char *buf;
buf = Xasprintf ("File: %-17s\tStatus: %s\n\n", finfo->file, sstat);
cvs_output (buf, 0);
free (buf);
}
if (vers->vn_user == NULL)
{
cvs_output (" Working revision:\tNo entry for ", 0);
cvs_output (finfo->file, 0);
cvs_output ("\n", 0);
}
else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
cvs_output (" Working revision:\tNew file!\n", 0);
else
{
cvs_output (" Working revision:\t", 0);
cvs_output (vers->vn_user, 0);
if (!server_active && strlen (vers->ts_rcs) > 0)
{
char *buf;
cvs_output ("\t", 0);
buf = Xasprintf ("%s UTC", vers->ts_rcs);
cvs_output_tagged ("date", buf);
free (buf);
}
cvs_output ("\n", 0);
}
if (vers->vn_rcs == NULL)
cvs_output (" Repository revision:\tNo revision control file\n", 0);
else
{
cvs_output (" Repository revision:\t", 0);
cvs_output (vers->vn_rcs, 0);
cvs_output ("\t", 0);
cvs_output (vers->srcfile->print_path, 0);
cvs_output ("\n", 0);
node = findnode(vers->srcfile->versions,vers->vn_rcs);
if (node)
{
RCSVers *v;
v=(RCSVers*)node->data;
node = findnode(v->other_delta,"commitid");
cvs_output(" Commit Identifier:\t", 0);
if(node && node->data)
cvs_output(node->data, 0);
else
cvs_output("(none)",0);
cvs_output("\n",0);
}
}
if (vers->entdata)
{
Entnode *edata;
edata = vers->entdata;
if (edata->tag)
{
if (vers->vn_rcs == NULL)
{
cvs_output (" Sticky Tag:\t\t", 0);
cvs_output (edata->tag, 0);
cvs_output (" - MISSING from RCS file!\n", 0);
}
else
{
if (isdigit ((unsigned char) edata->tag[0]))
{
cvs_output (" Sticky Tag:\t\t", 0);
cvs_output (edata->tag, 0);
cvs_output ("\n", 0);
}
else
{
char *branch = NULL;
if (RCS_nodeisbranch (finfo->rcs, edata->tag))
branch = RCS_whatbranch(finfo->rcs, edata->tag);
cvs_output (" Sticky Tag:\t\t", 0);
cvs_output (edata->tag, 0);
cvs_output (" (", 0);
cvs_output (branch ? "branch" : "revision", 0);
cvs_output (": ", 0);
cvs_output (branch ? branch : vers->vn_rcs, 0);
cvs_output (")\n", 0);
if (branch)
free (branch);
}
}
}
else if (!really_quiet)
cvs_output (" Sticky Tag:\t\t(none)\n", 0);
if (edata->date)
{
cvs_output (" Sticky Date:\t\t", 0);
cvs_output (edata->date, 0);
cvs_output ("\n", 0);
}
else if (!really_quiet)
cvs_output (" Sticky Date:\t\t(none)\n", 0);
if (edata->options && edata->options[0])
{
cvs_output (" Sticky Options:\t", 0);
cvs_output (edata->options, 0);
cvs_output ("\n", 0);
}
else if (!really_quiet)
cvs_output (" Sticky Options:\t(none)\n", 0);
}
if (long_format && vers->srcfile)
{
List *symbols = RCS_symbols(vers->srcfile);
cvs_output ("\n Existing Tags:\n", 0);
if (symbols)
{
xrcsnode = finfo->rcs;
(void) walklist (symbols, tag_list_proc, NULL);
}
else
cvs_output ("\tNo Tags Exist\n", 0);
}
cvs_output ("\n", 0);
freevers_ts (&vers);
return (0);
}
static Dtype
status_dirproc (void *callerdat, const char *dir, const char *repos,
const char *update_dir, List *entries)
{
if (!quiet)
error (0, 0, "Examining %s", update_dir);
return (R_PROCESS);
}
static int
tag_list_proc (Node *p, void *closure)
{
char *branch = NULL;
char *buf;
if (RCS_nodeisbranch (xrcsnode, p->key))
branch = RCS_whatbranch(xrcsnode, p->key) ;
buf = Xasprintf ("\t%-25s\t(%s: %s)\n", p->key,
branch ? "branch" : "revision",
branch ? branch : (char *)p->data);
cvs_output (buf, 0);
free (buf);
if (branch)
free (branch);
return (0);
}