Annotation of src/usr.bin/rcs/rlog.c, Revision 1.22
1.22 ! xsa 1: /* $OpenBSD: rlog.c,v 1.21 2006/01/23 17:08:45 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.20 xsa 33: static int rlog_file(const char *, const char *, RCSFILE *);
34: static void rlog_rev_print(struct rcs_delta *);
35: static char **rlog_strsplit(char *, const char *);
1.1 joris 36:
37: #define REVSEP "----------------------------"
38: #define REVEND \
1.6 xsa 39: "============================================================================="
1.1 joris 40:
1.20 xsa 41: static int hflag, Lflag, tflag, Nflag, wflag;
42: static char *slist = NULL;
43: static char *wlist = NULL;
1.1 joris 44:
1.21 xsa 45: void
46: rlog_usage(void)
47: {
48: fprintf(stderr,
49: "usage: rlog [-hLNqRTtV] [-sstates] [-w[logins]] "
50: "[-xsuffixes] file ...\n");
51: }
52:
1.1 joris 53: int
54: rlog_main(int argc, char **argv)
55: {
56: int Rflag;
57: int i, ch;
58: char fpath[MAXPATHLEN];
59: RCSFILE *file;
60:
61: hflag = Rflag = 0;
1.20 xsa 62: while ((ch = rcs_getopt(argc, argv, "hLNqRs:TtVw::x:")) != -1) {
1.1 joris 63: switch (ch) {
64: case 'h':
65: hflag = 1;
66: break;
1.11 xsa 67: case 'L':
68: Lflag = 1;
69: break;
1.1 joris 70: case 'N':
71: Nflag = 1;
72: break;
73: case 'q':
74: verbose = 0;
75: break;
76: case 'R':
77: Rflag = 1;
78: break;
1.20 xsa 79: case 's':
80: slist = rcs_optarg;
81: break;
1.8 xsa 82: case 'T':
83: /*
84: * kept for compatibility
85: */
86: break;
1.1 joris 87: case 't':
88: tflag = 1;
89: break;
90: case 'V':
91: printf("%s\n", rcs_version);
92: exit(0);
1.20 xsa 93: case 'w':
94: wflag = 1;
95: wlist = rcs_optarg;
96: break;
1.14 xsa 97: case 'x':
98: rcs_suffixes = rcs_optarg;
99: break;
1.1 joris 100: default:
1.21 xsa 101: (usage());
102: exit(1);
1.1 joris 103: }
104: }
105:
1.5 joris 106: argc -= rcs_optind;
107: argv += rcs_optind;
1.1 joris 108:
109: if (argc == 0) {
110: cvs_log(LP_ERR, "no input file");
111: (usage)();
112: exit(1);
113: }
114:
1.7 xsa 115: if ((hflag == 1) && (tflag == 1)) {
1.6 xsa 116: cvs_log(LP_WARN, "warning: -t overrides -h.");
1.7 xsa 117: hflag = 0;
118: }
1.6 xsa 119:
1.1 joris 120: for (i = 0; i < argc; i++) {
121: if (rcs_statfile(argv[i], fpath, sizeof(fpath)) < 0)
122: continue;
123:
1.17 niallo 124: if ((file = rcs_open(fpath, RCS_READ|RCS_PARSE_FULLY)) == NULL)
1.11 xsa 125: continue;
126:
127: if ((Lflag == 1) && (TAILQ_EMPTY(&(file->rf_locks)))) {
128: rcs_close(file);
129: continue;
130: }
131:
1.9 xsa 132: if (Rflag == 1) {
133: printf("%s\n", fpath);
1.11 xsa 134: rcs_close(file);
1.9 xsa 135: continue;
136: }
137:
138: rlog_file(argv[i], fpath, file);
139:
1.1 joris 140: rcs_close(file);
141: }
142:
143: return (0);
144: }
145:
146: static int
147: rlog_file(const char *fname, const char *fpath, RCSFILE *file)
148: {
149: char numb[64];
150: struct rcs_sym *sym;
151: struct rcs_access *acp;
1.20 xsa 152: struct rcs_delta *rdp;
1.10 xsa 153: struct rcs_lock *lkp;
1.1 joris 154:
1.12 xsa 155: printf("\nRCS file: %s", fpath);
1.6 xsa 156: printf("\nWorking file: %s", fname);
1.1 joris 157: printf("\nhead:");
158: if (file->rf_head != NULL)
159: printf(" %s", rcsnum_tostr(file->rf_head, numb, sizeof(numb)));
160:
161: printf("\nbranch:");
162: if (rcs_branch_get(file) != NULL) {
163: printf(" %s", rcsnum_tostr(rcs_branch_get(file),
164: numb, sizeof(numb)));
165: }
166:
167: printf("\nlocks: %s", (file->rf_flags & RCS_SLOCK) ? "strict" : "");
1.10 xsa 168: TAILQ_FOREACH(lkp, &(file->rf_locks), rl_list)
169: printf("\n\t%s: %s", lkp->rl_name,
170: rcsnum_tostr(lkp->rl_num, numb, sizeof(numb)));
1.1 joris 171: printf("\naccess list:\n");
172: TAILQ_FOREACH(acp, &(file->rf_access), ra_list)
173: printf("\t%s\n", acp->ra_name);
174:
175: if (Nflag == 0) {
176: printf("symbolic names:\n");
177: TAILQ_FOREACH(sym, &(file->rf_symbols), rs_list) {
178: printf("\t%s: %s\n", sym->rs_name,
179: rcsnum_tostr(sym->rs_num, numb, sizeof(numb)));
180: }
181: }
182:
183: printf("keyword substitution: %s\n",
184: file->rf_expand == NULL ? "kv" : file->rf_expand);
185:
1.20 xsa 186: printf("total revisions: %u", file->rf_ndelta);
187:
188: if ((hflag == 0) && (tflag == 0))
189: printf(";\tselected revisions:"); /* XXX */
190:
191: printf("\n");
192:
1.1 joris 193:
194: if ((hflag == 0) || (tflag == 1))
1.13 xsa 195: printf("description:\n%s", file->rf_desc);
1.1 joris 196:
1.20 xsa 197: if ((hflag == 0) && (tflag == 0)) {
198: TAILQ_FOREACH(rdp, &(file->rf_delta), rd_list)
199: rlog_rev_print(rdp);
200: }
1.1 joris 201:
202: printf("%s\n", REVEND);
203: return (0);
1.16 xsa 204: }
205:
206: static void
1.20 xsa 207: rlog_rev_print(struct rcs_delta *rdp)
1.16 xsa 208: {
1.20 xsa 209: int i, found;
210: char *author, numb[64];
211: char **sargv, **wargv;
212:
213: i = found = 0;
214: author = NULL;
215:
216: /* -sstates */
217: if (slist != NULL) {
218: sargv = rlog_strsplit(slist, ",");
219: for (i = 0; sargv[i] != NULL; i++) {
220: if (strcmp(rdp->rd_state, sargv[i]) == 0) {
221: found++;
222: break;
223: }
224: found = 0;
225: }
226: }
227: /* -w[logins] */
228: if (wflag == 1) {
229: if (wlist != NULL) {
230: wargv = rlog_strsplit(wlist, ",");
231: for (i = 0; wargv[i] != NULL; i++) {
232: if (strcmp(rdp->rd_author, wargv[i]) == 0) {
233: found++;
234: break;
235: }
236: found = 0;
237: }
238: } else {
239: if ((author = getlogin()) == NULL)
240: fatal("getlogin failed");
1.16 xsa 241:
1.20 xsa 242: if (strcmp(rdp->rd_author, author) == 0)
243: found++;
244: }
245: }
1.16 xsa 246:
1.20 xsa 247: /* XXX dirty... */
248: if ((((slist != NULL) && (wflag == 1)) && (found < 2)) ||
249: (((slist != NULL) || (wflag == 1)) && (found == 0)))
250: return;
251:
252: printf("%s\n", REVSEP);
253:
254: rcsnum_tostr(rdp->rd_num, numb, sizeof(numb));
255:
1.22 ! xsa 256: printf("revision %s", numb);
! 257: if (rdp->rd_locker != NULL)
! 258: printf("\tlocked by: %s;", rdp->rd_locker);
! 259: printf("\ndate: %d/%02d/%02d %02d:%02d:%02d;"
1.20 xsa 260: " author: %s; state: %s;\n",
261: rdp->rd_date.tm_year + 1900,
262: rdp->rd_date.tm_mon + 1,
263: rdp->rd_date.tm_mday, rdp->rd_date.tm_hour,
264: rdp->rd_date.tm_min, rdp->rd_date.tm_sec,
265: rdp->rd_author, rdp->rd_state);
266: printf("%s", rdp->rd_log);
267: }
1.16 xsa 268:
1.20 xsa 269: /*
270: * rlog_strsplit()
271: *
272: * Split a string <str> of <sep>-separated values and allocate
273: * an argument vector for the values found.
274: */
275: static char **
276: rlog_strsplit(char *str, const char *sep)
277: {
278: char **argv, **nargv;
279: char *cp, *p;
280: int i = 0;
281:
282: cp = xstrdup(str);
283: argv = (char **)xmalloc((i+1) * sizeof(char *));
284:
285: while ((p = strsep(&cp, sep)) != NULL) {
286: argv[i++] = p;
287: nargv = (char **)xrealloc((void *)argv, (i+1) * sizeof(char *));
288: argv = nargv;
1.16 xsa 289: }
1.20 xsa 290: argv[i] = NULL;
291:
292: return (argv);
1.1 joris 293: }