summaryrefslogtreecommitdiff
path: root/usr.bin/cvs/status.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/cvs/status.c')
-rw-r--r--usr.bin/cvs/status.c315
1 files changed, 107 insertions, 208 deletions
diff --git a/usr.bin/cvs/status.c b/usr.bin/cvs/status.c
index b7d5e786b6c..57901f34b25 100644
--- a/usr.bin/cvs/status.c
+++ b/usr.bin/cvs/status.c
@@ -1,28 +1,18 @@
-/* $OpenBSD: status.c,v 1.56 2006/04/14 02:45:35 deraadt Exp $ */
+/* $OpenBSD: status.c,v 1.57 2006/05/27 03:30:31 joris Exp $ */
/*
- * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
- * Copyright (c) 2005 Xavier Santolaria <xsa@openbsd.org>
- * All rights reserved.
+ * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
@@ -31,244 +21,153 @@
#include "log.h"
#include "proto.h"
-
-#define CVS_STATUS_SEP \
- "==================================================================="
-
-/* Keep this sorted as it is now. See file.h for status values. */
-const char *cvs_statstr[] = {
- "Unknown",
- "Up-to-date",
- "Locally Modified",
- "Locally Added",
- "Locally Removed",
- "Unresolved Conflict",
- "Patched",
- "Needs Checkout",
-};
-
-
-static int cvs_status_init (struct cvs_cmd *, int, char **, int *);
-static int cvs_status_remote (CVSFILE *, void *);
-static int cvs_status_local (CVSFILE *, void *);
-static int cvs_status_pre_exec (struct cvsroot *);
+int cvs_status(int, char **);
+void cvs_status_local(struct cvs_file *);
struct cvs_cmd cvs_cmd_status = {
CVS_OP_STATUS, CVS_REQ_STATUS, "status",
{ "st", "stat" },
"Display status information on checked out files",
"[-lRv]",
- "lRv",
+ "lRv:",
NULL,
- CF_SORT | CF_IGNORE | CF_RECURSE,
- cvs_status_init,
- cvs_status_pre_exec,
- cvs_status_remote,
- cvs_status_local,
- NULL,
- NULL,
- CVS_CMD_ALLOWSPEC | CVS_CMD_SENDDIR | CVS_CMD_SENDARGS2
+ cvs_status
};
-static int verbose = 0;
+#define CVS_STATUS_SEP \
+ "==================================================================="
-static int
-cvs_status_init(struct cvs_cmd *cmd, int argc, char **argv, int *arg)
+const char *status_tab[] = {
+ "Unknown",
+ "Locally Added",
+ "Locally Removed",
+ "Locally Modified",
+ "Up-to-date",
+ "Needs Checkout",
+ "Needs Checkout",
+ "Needs Merge",
+ "Needs Patch",
+ "Entry Invalid",
+ "Unresolved Conflict",
+ "Classifying error",
+};
+
+int
+cvs_status(int argc, char **argv)
{
int ch;
+ char *arg = ".";
+ struct cvs_recursion cr;
- while ((ch = getopt(argc, argv, cmd->cmd_opts)) != -1) {
+ while ((ch = getopt(argc, argv, cvs_cmd_status.cmd_opts)) != -1) {
switch (ch) {
case 'l':
- cmd->file_flags &= ~CF_RECURSE;
break;
case 'R':
- cmd->file_flags |= CF_RECURSE;
break;
case 'v':
- verbose = 1;
break;
default:
- return (CVS_EX_USAGE);
+ fatal("%s", cvs_cmd_status.cmd_synopsis);
}
}
- *arg = optind;
- return (0);
-}
+ argc -= optind;
+ argv += optind;
-static int
-cvs_status_pre_exec(struct cvsroot *root)
-{
- if (root->cr_method != CVS_METHOD_LOCAL) {
- if (verbose == 1)
- cvs_sendarg(root, "-v", 0);
- }
+ cr.enterdir = NULL;
+ cr.leavedir = NULL;
+ cr.local = cvs_status_local;
+ cr.remote = NULL;
- return (0);
-}
-
-/*
- * cvs_status_remote()
- *
- * Get the status of a single file.
- */
-static int
-cvs_status_remote(CVSFILE *cfp, void *arg)
-{
- char fpath[MAXPATHLEN];
- struct cvsroot *root;
-
- root = CVS_DIR_ROOT(cfp);
-
- if (cfp->cf_type == DT_DIR) {
- if (cfp->cf_cvstat == CVS_FST_UNKNOWN)
- cvs_sendreq(root, CVS_REQ_QUESTIONABLE, cfp->cf_name);
- else
- cvs_senddir(root, cfp);
- return (0);
- }
-
- cvs_file_getpath(cfp, fpath, sizeof(fpath));
-
- cvs_sendentry(root, cfp);
-
- switch (cfp->cf_cvstat) {
- case CVS_FST_UNKNOWN:
- cvs_sendreq(root, CVS_REQ_QUESTIONABLE, cfp->cf_name);
- break;
- case CVS_FST_UPTODATE:
- cvs_sendreq(root, CVS_REQ_UNCHANGED, cfp->cf_name);
- break;
- case CVS_FST_ADDED:
- case CVS_FST_MODIFIED:
- cvs_sendreq(root, CVS_REQ_MODIFIED, cfp->cf_name);
- cvs_sendfile(root, fpath);
- break;
- default:
- break;
- }
+ if (argc > 0)
+ cvs_file_run(argc, argv, &cr);
+ else
+ cvs_file_run(1, &arg, &cr);
return (0);
}
-static int
-cvs_status_local(CVSFILE *cf, void *arg)
+void
+cvs_status_local(struct cvs_file *cf)
{
- size_t n;
- char buf[MAXNAMLEN], fpath[MAXPATHLEN], rcspath[MAXPATHLEN];
- char numbuf[64], timebuf[32];
- RCSFILE *rf;
- struct rcs_sym *sym;
+ int l;
+ size_t len;
+ const char *status;
+ char buf[128], timebuf[32], revbuf[32];
- if (cf->cf_type == DT_DIR) {
- if (verbosity > 1)
- cvs_log(LP_NOTICE, "Examining %s", cf->cf_name);
- return (0);
- }
+ cvs_log(LP_TRACE, "cvs_status_local(%s)", cf->file_path);
- cvs_file_getpath(cf, fpath, sizeof(fpath));
- cvs_rcs_getpath(cf, rcspath, sizeof(rcspath));
+ cvs_file_classify(cf);
- rf = NULL;
- if (cf->cf_cvstat != CVS_FST_UNKNOWN &&
- cf->cf_cvstat != CVS_FST_ADDED) {
- if ((rf = rcs_open(rcspath, RCS_READ)) == NULL)
- fatal("cvs_status_local: rcs_open `%s': %s", rcspath,
- rcs_errstr(rcs_errno));
+ if (cf->file_type == CVS_DIR) {
+ if (verbosity > 1)
+ cvs_log(LP_NOTICE, "Examining %s", cf->file_path);
+ return;
}
- buf[0] = '\0';
-
- if (cf->cf_cvstat == CVS_FST_UNKNOWN)
- cvs_log(LP_WARN, "nothing known about %s", cf->cf_name);
+ cvs_printf("%s\n", CVS_STATUS_SEP);
- if (cf->cf_cvstat == CVS_FST_LOST || cf->cf_cvstat == CVS_FST_UNKNOWN)
- strlcpy(buf, "no file ", sizeof(buf));
- strlcat(buf, cf->cf_name, sizeof(buf));
+ status = status_tab[cf->file_status];
+ if (cf->file_status == FILE_MODIFIED &&
+ cf->file_ent->ce_conflict != NULL)
+ status = "File had conflicts on merge";
- cvs_printf(CVS_STATUS_SEP "\nFile: %-17s\tStatus: %s\n\n",
- buf, cvs_statstr[cf->cf_cvstat]);
+ cvs_printf("File: %-17s\tStatus: %s\n\n", cf->file_name, status);
- if (cf->cf_cvstat == CVS_FST_UNKNOWN) {
- strlcpy(buf, "No entry for ", sizeof(buf));
- strlcat(buf, cf->cf_name, sizeof(buf));
- } else if (cf->cf_cvstat == CVS_FST_ADDED) {
- strlcpy(buf, "New file!", sizeof(buf));
+ if (cf->file_ent == NULL) {
+ l = snprintf(buf, sizeof(buf),
+ "No entry for %s", cf->file_name);
+ if (l == -1 || l >= (int)sizeof(buf))
+ fatal("cvs_status_local: overflow");
+ } else if (cf->file_status == FILE_ADDED) {
+ len = strlcpy(buf, "New file!", sizeof(buf));
+ if (len >= sizeof(buf))
+ fatal("cvs_status_local: truncation");
} else {
- rcsnum_tostr(cf->cf_lrev, numbuf, sizeof(numbuf));
- strlcpy(buf, numbuf, sizeof(buf));
-
- /* Display etime in local mode only. */
- if (cvs_cmdop != CVS_OP_SERVER) {
- strlcat(buf, "\t", sizeof(buf));
+ rcsnum_tostr(cf->file_ent->ce_rev, revbuf, sizeof(revbuf));
- ctime_r(&(cf->cf_etime), timebuf);
- n = strlen(timebuf);
- if (n > 0 && timebuf[n - 1] == '\n')
- timebuf[--n] = '\0';
-
- strlcat(buf, timebuf, sizeof(buf));
+ if (cf->file_ent->ce_conflict == NULL) {
+ ctime_r(&(cf->file_ent->ce_mtime), timebuf);
+ if (timebuf[strlen(timebuf) - 1] == '\n')
+ timebuf[strlen(timebuf) - 1] = '\0';
+ } else {
+ len = strlcpy(timebuf, cf->file_ent->ce_conflict,
+ sizeof(timebuf));
+ if (len >= sizeof(timebuf))
+ fatal("cvs_status_local: truncation");
}
+
+ l = snprintf(buf, sizeof(buf), "%s\t%s", revbuf, timebuf);
+ if (l == -1 || l >= (int)sizeof(buf))
+ fatal("cvs_status_local: overflow");
}
cvs_printf(" Working revision:\t%s\n", buf);
- if (cf->cf_cvstat == CVS_FST_UNKNOWN ||
- cf->cf_cvstat == CVS_FST_ADDED) {
- strlcpy(buf, "No revision control file", sizeof(buf));
+ buf[0] = '\0';
+ if (cf->file_rcs == NULL) {
+ len = strlcat(buf, "No revision control file", sizeof(buf));
+ if (len >= sizeof(buf))
+ fatal("cvs_status_local: truncation");
} else {
- strlcpy(buf, rcsnum_tostr(rf->rf_head, numbuf, sizeof(numbuf)),
- sizeof(buf));
- strlcat(buf, "\t", sizeof(buf));
- strlcat(buf, rcspath, sizeof(buf));
+ rcsnum_tostr(cf->file_rcs->rf_head, revbuf, sizeof(revbuf));
+ l = snprintf(buf, sizeof(buf), "%s\t%s", revbuf,
+ cf->file_rpath);
+ if (l == -1 || l >= (int)sizeof(buf))
+ fatal("cvs_status_local: overflow");
}
cvs_printf(" Repository revision:\t%s\n", buf);
- /* If the file is unknown, no other output is needed after this. */
- if (cf->cf_cvstat == CVS_FST_UNKNOWN) {
- cvs_printf("\n");
- return (0);
- }
-
- if (cf->cf_tag != NULL)
- cvs_printf(" Sticky Tag:\t\t%s\n", cf->cf_tag);
- else if (verbosity > 0)
- cvs_printf(" Sticky Tag:\t\t(none)\n");
-
- /* XXX */
- if (verbosity > 0)
- cvs_printf(" Sticky Date:\t\t%s\n", "(none)");
-
- if (cf->cf_opts != NULL)
- cvs_printf(" Sticky Options:\t%s\n", cf->cf_opts);
- else if (verbosity > 0)
- cvs_printf(" Sticky Options:\t(none)\n");
-
- if (verbose == 1) {
- cvs_printf("\n");
- cvs_printf(" Existing Tags:\n");
-
- if (!TAILQ_EMPTY(&(rf->rf_symbols))) {
- TAILQ_FOREACH(sym, &(rf->rf_symbols), rs_list) {
- rcsnum_tostr(sym->rs_num, numbuf,
- sizeof(numbuf));
-
- cvs_printf("\t%-25s\t(%s: %s)\n",
- sym->rs_name,
- RCSNUM_ISBRANCH(sym->rs_num) ? "branch" :
- "revision", numbuf);
- }
- } else {
- cvs_printf("\tNo Tags Exist\n");
- }
+ if (cf->file_ent != NULL) {
+ if (cf->file_ent->ce_tag != NULL)
+ cvs_printf(" Sticky Tag:\t%s\n",
+ cf->file_ent->ce_tag);
+ if (cf->file_ent->ce_opts != NULL)
+ cvs_printf(" Sticky Options:\t%s\n",
+ cf->file_ent->ce_opts);
}
cvs_printf("\n");
-
- if (rf != NULL)
- rcs_close(rf);
-
- return (0);
}