diff options
Diffstat (limited to 'usr.bin/cvs/status.c')
-rw-r--r-- | usr.bin/cvs/status.c | 315 |
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); } |