Annotation of src/usr.bin/cvs/status.c, Revision 1.99
1.99 ! joris 1: /* $OpenBSD: status.c,v 1.98 2016/11/03 20:13:41 joris Exp $ */
1.1 jfb 2: /*
1.57 joris 3: * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
1.81 xsa 4: * Copyright (c) 2005-2008 Xavier Santolaria <xsa@openbsd.org>
1.1 jfb 5: *
1.57 joris 6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
1.1 jfb 9: *
1.57 joris 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1 jfb 17: */
18:
1.97 joris 19: #include <stdlib.h>
1.73 otto 20: #include <string.h>
1.87 tobias 21: #include <time.h>
1.73 otto 22: #include <unistd.h>
1.1 jfb 23:
24: #include "cvs.h"
1.68 joris 25: #include "remote.h"
1.1 jfb 26:
1.57 joris 27: void cvs_status_local(struct cvs_file *);
1.22 jfb 28:
1.64 xsa 29: static int show_sym = 0;
30:
1.22 jfb 31: struct cvs_cmd cvs_cmd_status = {
1.80 tobias 32: CVS_OP_STATUS, CVS_USE_WDIR, "status",
1.22 jfb 33: { "st", "stat" },
34: "Display status information on checked out files",
35: "[-lRv]",
1.64 xsa 36: "lRv",
1.22 jfb 37: NULL,
1.57 joris 38: cvs_status
1.10 joris 39: };
1.1 jfb 40:
1.57 joris 41: #define CVS_STATUS_SEP \
42: "==================================================================="
1.1 jfb 43:
1.57 joris 44: const char *status_tab[] = {
45: "Unknown",
46: "Locally Added",
47: "Locally Removed",
48: "Locally Modified",
49: "Up-to-date",
50: "Needs Checkout",
51: "Needs Checkout",
52: "Needs Merge",
53: "Needs Patch",
54: "Entry Invalid",
55: "Unresolved Conflict",
56: "Classifying error",
57: };
58:
59: int
60: cvs_status(int argc, char **argv)
1.1 jfb 61: {
1.58 joris 62: int ch, flags;
1.57 joris 63: char *arg = ".";
64: struct cvs_recursion cr;
1.1 jfb 65:
1.68 joris 66: flags = CR_RECURSE_DIRS;
1.58 joris 67:
1.57 joris 68: while ((ch = getopt(argc, argv, cvs_cmd_status.cmd_opts)) != -1) {
1.1 jfb 69: switch (ch) {
1.7 jfb 70: case 'l':
1.58 joris 71: flags &= ~CR_RECURSE_DIRS;
1.7 jfb 72: break;
73: case 'R':
1.79 tobias 74: flags |= CR_RECURSE_DIRS;
1.7 jfb 75: break;
76: case 'v':
1.64 xsa 77: show_sym = 1;
1.7 jfb 78: break;
1.1 jfb 79: default:
1.57 joris 80: fatal("%s", cvs_cmd_status.cmd_synopsis);
1.1 jfb 81: }
82: }
83:
1.57 joris 84: argc -= optind;
85: argv += optind;
1.1 jfb 86:
1.57 joris 87: cr.enterdir = NULL;
88: cr.leavedir = NULL;
1.68 joris 89:
90: if (current_cvsroot->cr_method == CVS_METHOD_LOCAL) {
91: flags |= CR_REPO;
92: cr.fileproc = cvs_status_local;
93: } else {
1.69 joris 94: cvs_client_connect_to_server();
1.68 joris 95: if (!(flags & CR_RECURSE_DIRS))
96: cvs_client_send_request("Argument -l");
97: if (show_sym)
98: cvs_client_send_request("Argument -v");
99: cr.fileproc = cvs_client_sendfile;
100: }
101:
1.58 joris 102: cr.flags = flags;
1.57 joris 103:
104: if (argc > 0)
105: cvs_file_run(argc, argv, &cr);
106: else
107: cvs_file_run(1, &arg, &cr);
1.68 joris 108:
109: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
110: cvs_client_send_files(argv, argc);
111: cvs_client_senddir(".");
112: cvs_client_send_request("status");
113: cvs_client_get_responses();
114: }
1.26 xsa 115:
1.1 jfb 116: return (0);
117: }
118:
1.57 joris 119: void
120: cvs_status_local(struct cvs_file *cf)
1.1 jfb 121: {
1.57 joris 122: size_t len;
1.97 joris 123: RCSNUM *head, *brev;
1.57 joris 124: const char *status;
1.96 stsp 125: struct rcs_delta *rdp;
1.94 deraadt 126: char buf[PATH_MAX + CVS_REV_BUFSZ + 128];
1.93 millert 127: char timebuf[CVS_TIME_BUFSZ], revbuf[CVS_REV_BUFSZ];
1.64 xsa 128: struct rcs_sym *sym;
1.1 jfb 129:
1.57 joris 130: cvs_log(LP_TRACE, "cvs_status_local(%s)", cf->file_path);
1.1 jfb 131:
1.77 joris 132: cvs_file_classify(cf, cvs_directory_tag);
1.15 jfb 133:
1.57 joris 134: if (cf->file_type == CVS_DIR) {
1.33 xsa 135: if (verbosity > 1)
1.57 joris 136: cvs_log(LP_NOTICE, "Examining %s", cf->file_path);
137: return;
1.33 xsa 138: }
1.89 joris 139:
1.91 joris 140: if (cf->file_status == FILE_UPTODATE &&
141: !(cf->file_flags & FILE_ON_DISK) &&
1.90 joris 142: !(cf->file_flags & FILE_USER_SUPPLIED))
1.89 joris 143: return;
1.15 jfb 144:
1.88 tobias 145: if (cf->file_rcs != NULL)
1.92 joris 146: head = cf->file_rcsrev;
1.88 tobias 147: else
1.83 joris 148: head = NULL;
1.78 tobias 149:
1.57 joris 150: cvs_printf("%s\n", CVS_STATUS_SEP);
1.5 jfb 151:
1.88 tobias 152: if (cf->file_rcs != NULL && head == NULL)
153: status = status_tab[FILE_UNKNOWN];
154: else
155: status = status_tab[cf->file_status];
156:
1.57 joris 157: if (cf->file_status == FILE_MODIFIED &&
158: cf->file_ent->ce_conflict != NULL)
159: status = "File had conflicts on merge";
160:
1.91 joris 161: if (!(cf->file_flags & FILE_ON_DISK)) {
1.71 xsa 162: (void)xsnprintf(buf, sizeof(buf), "no file %s\t",
163: cf->file_name);
1.63 xsa 164: } else
165: if (strlcpy(buf, cf->file_name, sizeof(buf)) >= sizeof(buf))
166: fatal("cvs_status_local: overflow");
167:
168: cvs_printf("File: %-17s\tStatus: %s\n\n", buf, status);
1.57 joris 169:
170: if (cf->file_ent == NULL) {
1.71 xsa 171: (void)xsnprintf(buf, sizeof(buf),
1.57 joris 172: "No entry for %s", cf->file_name);
1.88 tobias 173: } else if (cf->file_ent->ce_status == CVS_ENT_ADDED) {
1.57 joris 174: len = strlcpy(buf, "New file!", sizeof(buf));
175: if (len >= sizeof(buf))
176: fatal("cvs_status_local: truncation");
1.16 jfb 177: } else {
1.57 joris 178: rcsnum_tostr(cf->file_ent->ce_rev, revbuf, sizeof(revbuf));
1.35 xsa 179:
1.57 joris 180: if (cf->file_ent->ce_conflict == NULL) {
1.98 joris 181: if (cvs_server_active == 0) {
182: (void)strlcpy(timebuf, cf->file_ent->ce_time,
183: sizeof(timebuf));
184: } else {
185: timebuf[0] = '\0';
186: }
1.57 joris 187: } else {
188: len = strlcpy(timebuf, cf->file_ent->ce_conflict,
189: sizeof(timebuf));
190: if (len >= sizeof(timebuf))
191: fatal("cvs_status_local: truncation");
192: }
1.35 xsa 193:
1.76 xsa 194: (void)strlcpy(buf, revbuf, sizeof(buf));
195: if (cvs_server_active == 0) {
196: (void)strlcat(buf, "\t", sizeof(buf));
197: (void)strlcat(buf, timebuf, sizeof(buf));
198: }
1.16 jfb 199: }
1.32 joris 200:
1.28 xsa 201: cvs_printf(" Working revision:\t%s\n", buf);
1.30 xsa 202:
1.57 joris 203: buf[0] = '\0';
1.88 tobias 204: if (cf->file_rcs == NULL) {
1.57 joris 205: len = strlcat(buf, "No revision control file", sizeof(buf));
1.88 tobias 206: if (len >= sizeof(buf))
207: fatal("cvs_status_local: truncation");
208: } else if (head == NULL) {
209: len = strlcat(buf, "No head revision", sizeof(buf));
1.57 joris 210: if (len >= sizeof(buf))
211: fatal("cvs_status_local: truncation");
1.30 xsa 212: } else {
1.70 joris 213: rcsnum_tostr(head, revbuf, sizeof(revbuf));
1.71 xsa 214: (void)xsnprintf(buf, sizeof(buf), "%s\t%s", revbuf,
1.57 joris 215: cf->file_rpath);
1.30 xsa 216: }
217:
218: cvs_printf(" Repository revision:\t%s\n", buf);
1.96 stsp 219:
220: if (cf->file_rcs != NULL && head != NULL) {
221: rdp = rcs_findrev(cf->file_rcs, head);
222: if (rdp == NULL) {
223: fatal("cvs_status_local: No head revision delta");
224: }
225:
226: cvs_printf(" Commit Identifier:\t%s\n",
227: (rdp->rd_commitid != NULL) ? rdp->rd_commitid : "(none)");
228: }
1.30 xsa 229:
1.57 joris 230: if (cf->file_ent != NULL) {
1.97 joris 231: if (cf->file_ent->ce_tag != NULL) {
232: if ((brev = rcs_sym_getrev(cf->file_rcs,
233: cf->file_ent->ce_tag)) == NULL) {
234: (void)strlcpy(buf, "- MISSING from RCS file!",
235: sizeof(buf));
236: } else {
237: rcsnum_tostr(brev, revbuf, sizeof(revbuf));
1.99 ! joris 238: if (RCSNUM_ISBRANCH(brev)) {
! 239: xsnprintf(buf, sizeof(buf),
! 240: "(branch: %s)", revbuf);
! 241: } else {
! 242: xsnprintf(buf, sizeof(buf),
! 243: "(revision: %s)", revbuf);
! 244: }
1.97 joris 245: free(brev);
246: }
247:
248: cvs_printf(" Sticky Tag:\t\t%s %s\n",
249: cf->file_ent->ce_tag, buf);
250: } else if (verbosity > 0) {
1.60 xsa 251: cvs_printf(" Sticky Tag:\t\t(none)\n");
1.97 joris 252: }
1.81 xsa 253:
254: if (cf->file_ent->ce_date != -1) {
1.87 tobias 255: struct tm datetm;
1.81 xsa 256: char datetmp[CVS_TIME_BUFSZ];
257:
1.87 tobias 258: gmtime_r(&(cf->file_ent->ce_date), &datetm);
1.81 xsa 259: (void)strftime(datetmp, sizeof(datetmp),
1.87 tobias 260: CVS_DATE_FMT, &datetm);
1.81 xsa 261:
262: cvs_printf(" Sticky Date:\t\t%s\n", datetmp);
263: } else if (verbosity > 0)
264: cvs_printf(" Sticky Date:\t\t(none)\n");
1.60 xsa 265:
1.57 joris 266: if (cf->file_ent->ce_opts != NULL)
267: cvs_printf(" Sticky Options:\t%s\n",
268: cf->file_ent->ce_opts);
1.60 xsa 269: else if (verbosity > 0)
270: cvs_printf(" Sticky Options:\t(none)\n");
1.64 xsa 271: }
272:
1.86 joris 273: if (cf->file_rcs != NULL && show_sym == 1) {
1.64 xsa 274: cvs_printf("\n");
275: cvs_printf(" Existing Tags:\n");
276:
277: if (!TAILQ_EMPTY(&(cf->file_rcs->rf_symbols))) {
278: TAILQ_FOREACH(sym,
279: &(cf->file_rcs->rf_symbols), rs_list) {
280: (void)rcsnum_tostr(sym->rs_num, revbuf,
281: sizeof(revbuf));
282:
283: cvs_printf("\t%-25s\t(%s: %s)\n", sym->rs_name,
284: RCSNUM_ISBRANCH(sym->rs_num) ? "branch" :
285: "revision", revbuf);
286: }
287: } else
288: cvs_printf("\tNo Tags Exist\n");
1.41 xsa 289: }
1.15 jfb 290:
1.25 xsa 291: cvs_printf("\n");
1.1 jfb 292: }