Annotation of src/usr.bin/rcs/rlog.c, Revision 1.32
1.32 ! xsa 1: /* $OpenBSD: rlog.c,v 1.31 2006/03/20 17:14:47 xsa Exp $ */
1.1 joris 2: /*
3: * Copyright (c) 2005 Joris Vink <joris@openbsd.org>
1.20 xsa 4: * Copyright (c) 2005, 2006 Xavier Santolaria <xsa@openbsd.org>
1.1 joris 5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: *
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. The name of the author may not be used to endorse or promote products
14: * derived from this software without specific prior written permission.
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
25: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26: */
27:
1.18 xsa 28: #include "includes.h"
1.1 joris 29:
1.19 xsa 30: #include "rcsprog.h"
1.3 niallo 31: #include "diff.h"
1.1 joris 32:
1.32 ! xsa 33: static void rlog_file(const char *, const char *);
! 34: static void rlog_rev_print(struct rcs_delta *);
1.1 joris 35:
36: #define REVSEP "----------------------------"
37: #define REVEND \
1.6 xsa 38: "============================================================================="
1.1 joris 39:
1.23 xsa 40: static int hflag, Lflag, lflag, tflag, Nflag, wflag;
41: static char *llist = NULL;
1.20 xsa 42: static char *slist = NULL;
43: static char *wlist = NULL;
1.23 xsa 44: static RCSFILE *file;
1.1 joris 45:
1.21 xsa 46: void
47: rlog_usage(void)
48: {
49: fprintf(stderr,
1.25 jmc 50: "usage: rlog [-bhLNqRtV] [-ddates] [-l[lockers]] [-r[revs]]\n"
1.28 xsa 51: " [-sstates] [-w[logins]] [-xsuffixes]\n"
52: " [-ztz] file ...\n");
1.21 xsa 53: }
54:
1.1 joris 55: int
56: rlog_main(int argc, char **argv)
57: {
58: int Rflag;
59: int i, ch;
60: char fpath[MAXPATHLEN];
61:
62: hflag = Rflag = 0;
1.26 joris 63: while ((ch = rcs_getopt(argc, argv, "hLl::NqRs:TtVw::x:z:")) != -1) {
1.1 joris 64: switch (ch) {
65: case 'h':
66: hflag = 1;
67: break;
1.11 xsa 68: case 'L':
69: Lflag = 1;
70: break;
1.23 xsa 71: case 'l':
72: lflag = 1;
73: llist = rcs_optarg;
74: break;
1.1 joris 75: case 'N':
76: Nflag = 1;
77: break;
78: case 'q':
79: verbose = 0;
80: break;
81: case 'R':
82: Rflag = 1;
83: break;
1.20 xsa 84: case 's':
85: slist = rcs_optarg;
86: break;
1.8 xsa 87: case 'T':
88: /*
89: * kept for compatibility
90: */
91: break;
1.1 joris 92: case 't':
93: tflag = 1;
94: break;
95: case 'V':
96: printf("%s\n", rcs_version);
97: exit(0);
1.29 ray 98: /* NOTREACHED */
1.20 xsa 99: case 'w':
100: wflag = 1;
101: wlist = rcs_optarg;
102: break;
1.14 xsa 103: case 'x':
104: rcs_suffixes = rcs_optarg;
105: break;
1.26 joris 106: case 'z':
107: timezone_flag = rcs_optarg;
1.27 xsa 108: break;
1.1 joris 109: default:
1.21 xsa 110: (usage());
111: exit(1);
1.1 joris 112: }
113: }
114:
1.5 joris 115: argc -= rcs_optind;
116: argv += rcs_optind;
1.1 joris 117:
118: if (argc == 0) {
119: cvs_log(LP_ERR, "no input file");
120: (usage)();
121: exit(1);
122: }
123:
1.7 xsa 124: if ((hflag == 1) && (tflag == 1)) {
1.6 xsa 125: cvs_log(LP_WARN, "warning: -t overrides -h.");
1.7 xsa 126: hflag = 0;
127: }
1.6 xsa 128:
1.1 joris 129: for (i = 0; i < argc; i++) {
130: if (rcs_statfile(argv[i], fpath, sizeof(fpath)) < 0)
131: continue;
132:
1.17 niallo 133: if ((file = rcs_open(fpath, RCS_READ|RCS_PARSE_FULLY)) == NULL)
1.11 xsa 134: continue;
135:
136: if ((Lflag == 1) && (TAILQ_EMPTY(&(file->rf_locks)))) {
137: rcs_close(file);
138: continue;
139: }
140:
1.9 xsa 141: if (Rflag == 1) {
142: printf("%s\n", fpath);
1.11 xsa 143: rcs_close(file);
1.9 xsa 144: continue;
145: }
146:
1.23 xsa 147: rlog_file(argv[i], fpath);
1.9 xsa 148:
1.1 joris 149: rcs_close(file);
150: }
151:
152: return (0);
153: }
154:
1.32 ! xsa 155: static void
1.23 xsa 156: rlog_file(const char *fname, const char *fpath)
1.1 joris 157: {
158: char numb[64];
159: struct rcs_sym *sym;
160: struct rcs_access *acp;
1.20 xsa 161: struct rcs_delta *rdp;
1.10 xsa 162: struct rcs_lock *lkp;
1.1 joris 163:
1.12 xsa 164: printf("\nRCS file: %s", fpath);
1.6 xsa 165: printf("\nWorking file: %s", fname);
1.1 joris 166: printf("\nhead:");
167: if (file->rf_head != NULL)
168: printf(" %s", rcsnum_tostr(file->rf_head, numb, sizeof(numb)));
169:
170: printf("\nbranch:");
171: if (rcs_branch_get(file) != NULL) {
172: printf(" %s", rcsnum_tostr(rcs_branch_get(file),
173: numb, sizeof(numb)));
174: }
175:
176: printf("\nlocks: %s", (file->rf_flags & RCS_SLOCK) ? "strict" : "");
1.10 xsa 177: TAILQ_FOREACH(lkp, &(file->rf_locks), rl_list)
178: printf("\n\t%s: %s", lkp->rl_name,
179: rcsnum_tostr(lkp->rl_num, numb, sizeof(numb)));
1.1 joris 180: printf("\naccess list:\n");
181: TAILQ_FOREACH(acp, &(file->rf_access), ra_list)
182: printf("\t%s\n", acp->ra_name);
183:
184: if (Nflag == 0) {
185: printf("symbolic names:\n");
186: TAILQ_FOREACH(sym, &(file->rf_symbols), rs_list) {
187: printf("\t%s: %s\n", sym->rs_name,
188: rcsnum_tostr(sym->rs_num, numb, sizeof(numb)));
189: }
190: }
191:
192: printf("keyword substitution: %s\n",
193: file->rf_expand == NULL ? "kv" : file->rf_expand);
194:
1.20 xsa 195: printf("total revisions: %u", file->rf_ndelta);
196:
197: if ((hflag == 0) && (tflag == 0))
198: printf(";\tselected revisions:"); /* XXX */
199:
200: printf("\n");
201:
1.1 joris 202:
203: if ((hflag == 0) || (tflag == 1))
1.13 xsa 204: printf("description:\n%s", file->rf_desc);
1.1 joris 205:
1.20 xsa 206: if ((hflag == 0) && (tflag == 0)) {
207: TAILQ_FOREACH(rdp, &(file->rf_delta), rd_list)
208: rlog_rev_print(rdp);
209: }
1.1 joris 210:
211: printf("%s\n", REVEND);
1.16 xsa 212: }
213:
214: static void
1.20 xsa 215: rlog_rev_print(struct rcs_delta *rdp)
1.16 xsa 216: {
1.20 xsa 217: int i, found;
218: char *author, numb[64];
1.23 xsa 219: char **largv, **sargv, **wargv;
1.20 xsa 220:
221: i = found = 0;
222: author = NULL;
223:
1.23 xsa 224: /* -l[lockers] */
225: if (lflag == 1) {
226: /* if no locks at all, abort. */
227: if (TAILQ_EMPTY(&(file->rf_locks)))
228: return;
229: else
230: if (rdp->rd_locker != NULL)
231: found++;
232:
233: if (llist != NULL) {
234: /* if locker is empty, no need to go further. */
235: if (rdp->rd_locker == NULL)
236: return;
1.30 xsa 237: largv = cvs_strsplit(llist, ",");
1.23 xsa 238: for (i = 0; largv[i] != NULL; i++) {
239: if (strcmp(rdp->rd_locker, largv[i]) == 0) {
240: found++;
241: break;
242: }
243: found = 0;
244: }
1.31 xsa 245: xfree(largv);
1.23 xsa 246: }
247: }
1.20 xsa 248: /* -sstates */
249: if (slist != NULL) {
1.30 xsa 250: sargv = cvs_strsplit(slist, ",");
1.20 xsa 251: for (i = 0; sargv[i] != NULL; i++) {
252: if (strcmp(rdp->rd_state, sargv[i]) == 0) {
253: found++;
254: break;
255: }
256: found = 0;
257: }
1.31 xsa 258: xfree(sargv);
1.20 xsa 259: }
260: /* -w[logins] */
261: if (wflag == 1) {
262: if (wlist != NULL) {
1.30 xsa 263: wargv = cvs_strsplit(wlist, ",");
1.20 xsa 264: for (i = 0; wargv[i] != NULL; i++) {
265: if (strcmp(rdp->rd_author, wargv[i]) == 0) {
266: found++;
267: break;
268: }
269: found = 0;
270: }
1.31 xsa 271: xfree(wargv);
1.20 xsa 272: } else {
273: if ((author = getlogin()) == NULL)
274: fatal("getlogin failed");
1.16 xsa 275:
1.20 xsa 276: if (strcmp(rdp->rd_author, author) == 0)
277: found++;
278: }
279: }
1.16 xsa 280:
1.20 xsa 281: /* XXX dirty... */
1.23 xsa 282: if (((((slist != NULL) && (wflag == 1)) ||
283: ((slist != NULL) && (lflag == 1)) ||
284: ((lflag == 1) && (wflag == 1))) && (found < 2)) ||
285: ((((slist != NULL) && (lflag == 1) && (wflag == 1)) ||
286: ((slist != NULL) || (lflag == 1) || (wflag == 1))) && (found == 0)))
1.20 xsa 287: return;
288:
289: printf("%s\n", REVSEP);
290:
291: rcsnum_tostr(rdp->rd_num, numb, sizeof(numb));
292:
1.22 xsa 293: printf("revision %s", numb);
294: if (rdp->rd_locker != NULL)
295: printf("\tlocked by: %s;", rdp->rd_locker);
296: printf("\ndate: %d/%02d/%02d %02d:%02d:%02d;"
1.20 xsa 297: " author: %s; state: %s;\n",
298: rdp->rd_date.tm_year + 1900,
299: rdp->rd_date.tm_mon + 1,
300: rdp->rd_date.tm_mday, rdp->rd_date.tm_hour,
301: rdp->rd_date.tm_min, rdp->rd_date.tm_sec,
302: rdp->rd_author, rdp->rd_state);
303: printf("%s", rdp->rd_log);
1.1 joris 304: }