Annotation of src/usr.bin/cvs/status.c, Revision 1.55
1.55 ! xsa 1: /* $OpenBSD: status.c,v 1.54 2006/01/30 17:58:47 xsa Exp $ */
1.1 jfb 2: /*
3: * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
1.41 xsa 4: * Copyright (c) 2005 Xavier Santolaria <xsa@openbsd.org>
1.4 tedu 5: * All rights reserved.
1.1 jfb 6: *
1.4 tedu 7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
1.1 jfb 10: *
1.4 tedu 11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
1.1 jfb 13: * 2. The name of the author may not be used to endorse or promote products
1.4 tedu 14: * derived from this software without specific prior written permission.
1.1 jfb 15: *
16: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
1.4 tedu 25: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.1 jfb 26: */
27:
1.51 xsa 28: #include "includes.h"
1.1 jfb 29:
30: #include "cvs.h"
31: #include "log.h"
32: #include "proto.h"
33:
34:
1.15 jfb 35: #define CVS_STATUS_SEP \
36: "==================================================================="
37:
1.31 xsa 38: /* Keep this sorted as it is now. See file.h for status values. */
1.1 jfb 39: const char *cvs_statstr[] = {
40: "Unknown",
1.15 jfb 41: "Up-to-date",
1.1 jfb 42: "Locally Modified",
1.29 xsa 43: "Locally Added",
44: "Locally Removed",
45: "Unresolved Conflict",
1.1 jfb 46: "Patched",
1.16 jfb 47: "Needs Checkout",
1.1 jfb 48: };
1.33 xsa 49:
1.1 jfb 50:
1.41 xsa 51: static int cvs_status_init (struct cvs_cmd *, int, char **, int *);
52: static int cvs_status_remote (CVSFILE *, void *);
53: static int cvs_status_local (CVSFILE *, void *);
1.22 jfb 54: static int cvs_status_pre_exec (struct cvsroot *);
55:
56: struct cvs_cmd cvs_cmd_status = {
57: CVS_OP_STATUS, CVS_REQ_STATUS, "status",
58: { "st", "stat" },
59: "Display status information on checked out files",
60: "[-lRv]",
61: "lRv",
62: NULL,
63: CF_SORT | CF_IGNORE | CF_RECURSE,
64: cvs_status_init,
65: cvs_status_pre_exec,
1.20 jfb 66: cvs_status_remote,
1.22 jfb 67: cvs_status_local,
68: NULL,
69: NULL,
1.10 joris 70: CVS_CMD_ALLOWSPEC | CVS_CMD_SENDDIR | CVS_CMD_SENDARGS2
71: };
1.1 jfb 72:
1.10 joris 73: static int verbose = 0;
1.1 jfb 74:
1.22 jfb 75: static int
76: cvs_status_init(struct cvs_cmd *cmd, int argc, char **argv, int *arg)
1.1 jfb 77: {
1.10 joris 78: int ch;
1.1 jfb 79:
1.22 jfb 80: while ((ch = getopt(argc, argv, cmd->cmd_opts)) != -1) {
1.1 jfb 81: switch (ch) {
1.7 jfb 82: case 'l':
1.22 jfb 83: cmd->file_flags &= ~CF_RECURSE;
1.7 jfb 84: break;
85: case 'R':
1.22 jfb 86: cmd->file_flags |= CF_RECURSE;
1.7 jfb 87: break;
88: case 'v':
89: verbose = 1;
90: break;
1.1 jfb 91: default:
1.14 joris 92: return (CVS_EX_USAGE);
1.1 jfb 93: }
94: }
95:
1.10 joris 96: *arg = optind;
97: return (0);
98: }
1.1 jfb 99:
1.22 jfb 100: static int
101: cvs_status_pre_exec(struct cvsroot *root)
1.10 joris 102: {
1.26 xsa 103: if (root->cr_method != CVS_METHOD_LOCAL) {
1.50 joris 104: if (verbose == 1)
105: cvs_sendarg(root, "-v", 0);
1.26 xsa 106: }
107:
1.1 jfb 108: return (0);
109: }
110:
111: /*
1.20 jfb 112: * cvs_status_remote()
1.1 jfb 113: *
114: * Get the status of a single file.
115: */
1.22 jfb 116: static int
1.20 jfb 117: cvs_status_remote(CVSFILE *cfp, void *arg)
1.1 jfb 118: {
1.44 xsa 119: char fpath[MAXPATHLEN];
1.1 jfb 120: struct cvsroot *root;
121:
1.5 jfb 122: root = CVS_DIR_ROOT(cfp);
1.1 jfb 123:
1.6 jfb 124: if (cfp->cf_type == DT_DIR) {
1.15 jfb 125: if (cfp->cf_cvstat == CVS_FST_UNKNOWN)
1.50 joris 126: cvs_sendreq(root, CVS_REQ_QUESTIONABLE, cfp->cf_name);
1.15 jfb 127: else
1.50 joris 128: cvs_senddir(root, cfp);
129: return (0);
1.6 jfb 130: }
1.1 jfb 131:
1.5 jfb 132: cvs_file_getpath(cfp, fpath, sizeof(fpath));
1.1 jfb 133:
1.50 joris 134: cvs_sendentry(root, cfp);
1.15 jfb 135:
136: switch (cfp->cf_cvstat) {
137: case CVS_FST_UNKNOWN:
1.50 joris 138: cvs_sendreq(root, CVS_REQ_QUESTIONABLE, cfp->cf_name);
1.15 jfb 139: break;
140: case CVS_FST_UPTODATE:
1.50 joris 141: cvs_sendreq(root, CVS_REQ_UNCHANGED, cfp->cf_name);
1.15 jfb 142: break;
1.17 joris 143: case CVS_FST_ADDED:
1.15 jfb 144: case CVS_FST_MODIFIED:
1.50 joris 145: cvs_sendreq(root, CVS_REQ_MODIFIED, cfp->cf_name);
146: cvs_sendfile(root, fpath);
1.55 ! xsa 147: break;
1.15 jfb 148: default:
149: break;
150: }
151:
1.50 joris 152: return (0);
1.15 jfb 153: }
154:
1.22 jfb 155: static int
156: cvs_status_local(CVSFILE *cf, void *arg)
1.15 jfb 157: {
1.35 xsa 158: size_t n;
159: char buf[MAXNAMLEN], fpath[MAXPATHLEN], rcspath[MAXPATHLEN];
160: char numbuf[64], timebuf[32];
1.15 jfb 161: RCSFILE *rf;
1.41 xsa 162: struct rcs_sym *sym;
1.15 jfb 163:
1.33 xsa 164: if (cf->cf_type == DT_DIR) {
165: if (verbosity > 1)
1.43 xsa 166: cvs_log(LP_NOTICE, "Examining %s", cf->cf_name);
1.15 jfb 167: return (0);
1.33 xsa 168: }
1.15 jfb 169:
1.22 jfb 170: cvs_file_getpath(cf, fpath, sizeof(fpath));
1.49 xsa 171: cvs_rcs_getpath(cf, rcspath, sizeof(rcspath));
1.1 jfb 172:
1.46 joris 173: rf = NULL;
1.37 xsa 174: if (cf->cf_cvstat != CVS_FST_UNKNOWN &&
175: cf->cf_cvstat != CVS_FST_ADDED) {
1.53 xsa 176: if ((rf = rcs_open(rcspath, RCS_READ)) == NULL)
177: fatal("cvs_status_local: rcs_open `%s': %s", rcspath,
1.54 xsa 178: rcs_errstr(rcs_errno));
1.30 xsa 179: }
1.5 jfb 180:
1.16 jfb 181: buf[0] = '\0';
1.47 xsa 182:
183: if (cf->cf_cvstat == CVS_FST_UNKNOWN)
184: cvs_log(LP_WARN, "nothing known about %s", cf->cf_name);
185:
1.30 xsa 186: if (cf->cf_cvstat == CVS_FST_LOST || cf->cf_cvstat == CVS_FST_UNKNOWN)
1.27 xsa 187: strlcpy(buf, "no file ", sizeof(buf));
1.22 jfb 188: strlcat(buf, cf->cf_name, sizeof(buf));
1.16 jfb 189:
1.28 xsa 190: cvs_printf(CVS_STATUS_SEP "\nFile: %-17s\tStatus: %s\n\n",
1.22 jfb 191: buf, cvs_statstr[cf->cf_cvstat]);
1.16 jfb 192:
1.22 jfb 193: if (cf->cf_cvstat == CVS_FST_UNKNOWN) {
1.52 xsa 194: strlcpy(buf, "No entry for ", sizeof(buf));
195: strlcat(buf, cf->cf_name, sizeof(buf));
1.37 xsa 196: } else if (cf->cf_cvstat == CVS_FST_ADDED) {
1.52 xsa 197: strlcpy(buf, "New file!", sizeof(buf));
1.16 jfb 198: } else {
1.37 xsa 199: rcsnum_tostr(cf->cf_lrev, numbuf, sizeof(numbuf));
1.52 xsa 200: strlcpy(buf, numbuf, sizeof(buf));
1.35 xsa 201:
202: /* Display etime in local mode only. */
203: if (cvs_cmdop != CVS_OP_SERVER) {
204: strlcat(buf, "\t", sizeof(buf));
205:
206: ctime_r(&(cf->cf_etime), timebuf);
207: n = strlen(timebuf);
208: if ((n > 0) && (timebuf[n - 1] == '\n'))
1.36 xsa 209: timebuf[--n] = '\0';
1.35 xsa 210:
211: strlcat(buf, timebuf, sizeof(buf));
212: }
1.16 jfb 213: }
1.32 joris 214:
1.28 xsa 215: cvs_printf(" Working revision:\t%s\n", buf);
1.30 xsa 216:
1.37 xsa 217: if (cf->cf_cvstat == CVS_FST_UNKNOWN ||
218: cf->cf_cvstat == CVS_FST_ADDED) {
1.52 xsa 219: strlcpy(buf, "No revision control file", sizeof(buf));
1.30 xsa 220: } else {
1.52 xsa 221: strlcpy(buf, rcsnum_tostr(rf->rf_head, numbuf, sizeof(numbuf)),
222: sizeof(buf));
223: strlcat(buf, "\t", sizeof(buf));
224: strlcat(buf, rcspath, sizeof(buf));
1.30 xsa 225: }
226:
227: cvs_printf(" Repository revision:\t%s\n", buf);
228:
229: /* If the file is unknown, no other output is needed after this. */
1.37 xsa 230: if (cf->cf_cvstat == CVS_FST_UNKNOWN) {
231: cvs_printf("\n");
1.30 xsa 232: return (0);
1.37 xsa 233: }
1.30 xsa 234:
1.38 xsa 235: if (cf->cf_tag != NULL)
236: cvs_printf(" Sticky Tag:\t\t%s\n", cf->cf_tag);
237: else if (verbosity > 0)
238: cvs_printf(" Sticky Tag:\t\t(none)\n");
239:
240: /* XXX */
241: if (verbosity > 0)
242: cvs_printf(" Sticky Date:\t\t%s\n", "(none)");
243:
244: if (cf->cf_opts != NULL)
245: cvs_printf(" Sticky Options:\t%s\n", cf->cf_opts);
246: else if (verbosity > 0)
247: cvs_printf(" Sticky Options:\t(none)\n");
1.41 xsa 248:
1.48 xsa 249: if (verbose == 1) {
1.41 xsa 250: cvs_printf("\n");
251: cvs_printf(" Existing Tags:\n");
252:
253: if (!TAILQ_EMPTY(&(rf->rf_symbols))) {
254: TAILQ_FOREACH(sym, &(rf->rf_symbols), rs_list) {
255: rcsnum_tostr(sym->rs_num, numbuf,
256: sizeof(numbuf));
257:
258: cvs_printf("\t%-25s\t(%s: %s)\n",
1.45 xsa 259: sym->rs_name,
1.41 xsa 260: RCSNUM_ISBRANCH(sym->rs_num) ? "branch" :
261: "revision", numbuf);
262: }
263: } else {
264: cvs_printf("\tNo Tags Exist\n");
265: }
266: }
1.15 jfb 267:
1.25 xsa 268: cvs_printf("\n");
1.46 joris 269:
270: if (rf != NULL)
271: rcs_close(rf);
1.15 jfb 272:
273: return (0);
1.1 jfb 274: }