Annotation of src/usr.bin/cvs/status.c, Revision 1.96
1.96 ! stsp 1: /* $OpenBSD: status.c,v 1.95 2015/04/04 14:19:10 stsp 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.73 otto 19: #include <string.h>
1.87 tobias 20: #include <time.h>
1.73 otto 21: #include <unistd.h>
1.1 jfb 22:
23: #include "cvs.h"
1.68 joris 24: #include "remote.h"
1.1 jfb 25:
1.57 joris 26: void cvs_status_local(struct cvs_file *);
1.22 jfb 27:
1.64 xsa 28: static int show_sym = 0;
29:
1.22 jfb 30: struct cvs_cmd cvs_cmd_status = {
1.80 tobias 31: CVS_OP_STATUS, CVS_USE_WDIR, "status",
1.22 jfb 32: { "st", "stat" },
33: "Display status information on checked out files",
34: "[-lRv]",
1.64 xsa 35: "lRv",
1.22 jfb 36: NULL,
1.57 joris 37: cvs_status
1.10 joris 38: };
1.1 jfb 39:
1.57 joris 40: #define CVS_STATUS_SEP \
41: "==================================================================="
1.1 jfb 42:
1.57 joris 43: const char *status_tab[] = {
44: "Unknown",
45: "Locally Added",
46: "Locally Removed",
47: "Locally Modified",
48: "Up-to-date",
49: "Needs Checkout",
50: "Needs Checkout",
51: "Needs Merge",
52: "Needs Patch",
53: "Entry Invalid",
54: "Unresolved Conflict",
55: "Classifying error",
56: };
57:
58: int
59: cvs_status(int argc, char **argv)
1.1 jfb 60: {
1.58 joris 61: int ch, flags;
1.57 joris 62: char *arg = ".";
63: struct cvs_recursion cr;
1.1 jfb 64:
1.68 joris 65: flags = CR_RECURSE_DIRS;
1.58 joris 66:
1.57 joris 67: while ((ch = getopt(argc, argv, cvs_cmd_status.cmd_opts)) != -1) {
1.1 jfb 68: switch (ch) {
1.7 jfb 69: case 'l':
1.58 joris 70: flags &= ~CR_RECURSE_DIRS;
1.7 jfb 71: break;
72: case 'R':
1.79 tobias 73: flags |= CR_RECURSE_DIRS;
1.7 jfb 74: break;
75: case 'v':
1.64 xsa 76: show_sym = 1;
1.7 jfb 77: break;
1.1 jfb 78: default:
1.57 joris 79: fatal("%s", cvs_cmd_status.cmd_synopsis);
1.1 jfb 80: }
81: }
82:
1.57 joris 83: argc -= optind;
84: argv += optind;
1.1 jfb 85:
1.57 joris 86: cr.enterdir = NULL;
87: cr.leavedir = NULL;
1.68 joris 88:
89: if (current_cvsroot->cr_method == CVS_METHOD_LOCAL) {
90: flags |= CR_REPO;
91: cr.fileproc = cvs_status_local;
92: } else {
1.69 joris 93: cvs_client_connect_to_server();
1.68 joris 94: if (!(flags & CR_RECURSE_DIRS))
95: cvs_client_send_request("Argument -l");
96: if (show_sym)
97: cvs_client_send_request("Argument -v");
98: cr.fileproc = cvs_client_sendfile;
99: }
100:
1.58 joris 101: cr.flags = flags;
1.57 joris 102:
103: if (argc > 0)
104: cvs_file_run(argc, argv, &cr);
105: else
106: cvs_file_run(1, &arg, &cr);
1.68 joris 107:
108: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
109: cvs_client_send_files(argv, argc);
110: cvs_client_senddir(".");
111: cvs_client_send_request("status");
112: cvs_client_get_responses();
113: }
1.26 xsa 114:
1.1 jfb 115: return (0);
116: }
117:
1.57 joris 118: void
119: cvs_status_local(struct cvs_file *cf)
1.1 jfb 120: {
1.57 joris 121: size_t len;
1.70 joris 122: RCSNUM *head;
1.57 joris 123: const char *status;
1.96 ! stsp 124: struct rcs_delta *rdp;
1.94 deraadt 125: char buf[PATH_MAX + CVS_REV_BUFSZ + 128];
1.93 millert 126: char timebuf[CVS_TIME_BUFSZ], revbuf[CVS_REV_BUFSZ];
1.64 xsa 127: struct rcs_sym *sym;
1.1 jfb 128:
1.57 joris 129: cvs_log(LP_TRACE, "cvs_status_local(%s)", cf->file_path);
1.1 jfb 130:
1.77 joris 131: cvs_file_classify(cf, cvs_directory_tag);
1.15 jfb 132:
1.57 joris 133: if (cf->file_type == CVS_DIR) {
1.33 xsa 134: if (verbosity > 1)
1.57 joris 135: cvs_log(LP_NOTICE, "Examining %s", cf->file_path);
136: return;
1.33 xsa 137: }
1.89 joris 138:
1.91 joris 139: if (cf->file_status == FILE_UPTODATE &&
140: !(cf->file_flags & FILE_ON_DISK) &&
1.90 joris 141: !(cf->file_flags & FILE_USER_SUPPLIED))
1.89 joris 142: return;
1.15 jfb 143:
1.88 tobias 144: if (cf->file_rcs != NULL)
1.92 joris 145: head = cf->file_rcsrev;
1.88 tobias 146: else
1.83 joris 147: head = NULL;
1.78 tobias 148:
1.57 joris 149: cvs_printf("%s\n", CVS_STATUS_SEP);
1.5 jfb 150:
1.88 tobias 151: if (cf->file_rcs != NULL && head == NULL)
152: status = status_tab[FILE_UNKNOWN];
153: else
154: status = status_tab[cf->file_status];
155:
1.57 joris 156: if (cf->file_status == FILE_MODIFIED &&
157: cf->file_ent->ce_conflict != NULL)
158: status = "File had conflicts on merge";
159:
1.91 joris 160: if (!(cf->file_flags & FILE_ON_DISK)) {
1.71 xsa 161: (void)xsnprintf(buf, sizeof(buf), "no file %s\t",
162: cf->file_name);
1.63 xsa 163: } else
164: if (strlcpy(buf, cf->file_name, sizeof(buf)) >= sizeof(buf))
165: fatal("cvs_status_local: overflow");
166:
167: cvs_printf("File: %-17s\tStatus: %s\n\n", buf, status);
1.57 joris 168:
169: if (cf->file_ent == NULL) {
1.71 xsa 170: (void)xsnprintf(buf, sizeof(buf),
1.57 joris 171: "No entry for %s", cf->file_name);
1.88 tobias 172: } else if (cf->file_ent->ce_status == CVS_ENT_ADDED) {
1.57 joris 173: len = strlcpy(buf, "New file!", sizeof(buf));
174: if (len >= sizeof(buf))
175: fatal("cvs_status_local: truncation");
1.16 jfb 176: } else {
1.57 joris 177: rcsnum_tostr(cf->file_ent->ce_rev, revbuf, sizeof(revbuf));
1.35 xsa 178:
1.57 joris 179: if (cf->file_ent->ce_conflict == NULL) {
1.95 stsp 180: (void)strlcpy(timebuf, cf->file_ent->ce_time,
181: sizeof(timebuf));
1.57 joris 182: } else {
183: len = strlcpy(timebuf, cf->file_ent->ce_conflict,
184: sizeof(timebuf));
185: if (len >= sizeof(timebuf))
186: fatal("cvs_status_local: truncation");
187: }
1.35 xsa 188:
1.76 xsa 189: (void)strlcpy(buf, revbuf, sizeof(buf));
190: if (cvs_server_active == 0) {
191: (void)strlcat(buf, "\t", sizeof(buf));
192: (void)strlcat(buf, timebuf, sizeof(buf));
193: }
1.16 jfb 194: }
1.32 joris 195:
1.28 xsa 196: cvs_printf(" Working revision:\t%s\n", buf);
1.30 xsa 197:
1.57 joris 198: buf[0] = '\0';
1.88 tobias 199: if (cf->file_rcs == NULL) {
1.57 joris 200: len = strlcat(buf, "No revision control file", sizeof(buf));
1.88 tobias 201: if (len >= sizeof(buf))
202: fatal("cvs_status_local: truncation");
203: } else if (head == NULL) {
204: len = strlcat(buf, "No head revision", sizeof(buf));
1.57 joris 205: if (len >= sizeof(buf))
206: fatal("cvs_status_local: truncation");
1.30 xsa 207: } else {
1.70 joris 208: rcsnum_tostr(head, revbuf, sizeof(revbuf));
1.71 xsa 209: (void)xsnprintf(buf, sizeof(buf), "%s\t%s", revbuf,
1.57 joris 210: cf->file_rpath);
1.30 xsa 211: }
212:
213: cvs_printf(" Repository revision:\t%s\n", buf);
1.96 ! stsp 214:
! 215: if (cf->file_rcs != NULL && head != NULL) {
! 216: rdp = rcs_findrev(cf->file_rcs, head);
! 217: if (rdp == NULL) {
! 218: fatal("cvs_status_local: No head revision delta");
! 219: }
! 220:
! 221: cvs_printf(" Commit Identifier:\t%s\n",
! 222: (rdp->rd_commitid != NULL) ? rdp->rd_commitid : "(none)");
! 223: }
1.30 xsa 224:
1.57 joris 225: if (cf->file_ent != NULL) {
226: if (cf->file_ent->ce_tag != NULL)
1.60 xsa 227: cvs_printf(" Sticky Tag:\t\t%s\n",
1.57 joris 228: cf->file_ent->ce_tag);
1.60 xsa 229: else if (verbosity > 0)
230: cvs_printf(" Sticky Tag:\t\t(none)\n");
1.81 xsa 231:
232: if (cf->file_ent->ce_date != -1) {
1.87 tobias 233: struct tm datetm;
1.81 xsa 234: char datetmp[CVS_TIME_BUFSZ];
235:
1.87 tobias 236: gmtime_r(&(cf->file_ent->ce_date), &datetm);
1.81 xsa 237: (void)strftime(datetmp, sizeof(datetmp),
1.87 tobias 238: CVS_DATE_FMT, &datetm);
1.81 xsa 239:
240: cvs_printf(" Sticky Date:\t\t%s\n", datetmp);
241: } else if (verbosity > 0)
242: cvs_printf(" Sticky Date:\t\t(none)\n");
1.60 xsa 243:
1.57 joris 244: if (cf->file_ent->ce_opts != NULL)
245: cvs_printf(" Sticky Options:\t%s\n",
246: cf->file_ent->ce_opts);
1.60 xsa 247: else if (verbosity > 0)
248: cvs_printf(" Sticky Options:\t(none)\n");
1.64 xsa 249: }
250:
1.86 joris 251: if (cf->file_rcs != NULL && show_sym == 1) {
1.64 xsa 252: cvs_printf("\n");
253: cvs_printf(" Existing Tags:\n");
254:
255: if (!TAILQ_EMPTY(&(cf->file_rcs->rf_symbols))) {
256: TAILQ_FOREACH(sym,
257: &(cf->file_rcs->rf_symbols), rs_list) {
258: (void)rcsnum_tostr(sym->rs_num, revbuf,
259: sizeof(revbuf));
260:
261: cvs_printf("\t%-25s\t(%s: %s)\n", sym->rs_name,
262: RCSNUM_ISBRANCH(sym->rs_num) ? "branch" :
263: "revision", revbuf);
264: }
265: } else
266: cvs_printf("\tNo Tags Exist\n");
1.41 xsa 267: }
1.15 jfb 268:
1.25 xsa 269: cvs_printf("\n");
1.1 jfb 270: }