xref: /openbsd-src/usr.bin/cvs/history.c (revision 06ccd5dad87daa7ede3ae33928857a729a8043ea)
1 /*	$OpenBSD: history.c,v 1.3 2004/07/30 01:49:23 jfb Exp $	*/
2 /*
3  * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. The name of the author may not be used to endorse or promote products
13  *    derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
18  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/param.h>
28 #include <sys/stat.h>
29 
30 #include <errno.h>
31 #include <stdio.h>
32 #include <fcntl.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <sysexits.h>
37 
38 #include "cvs.h"
39 #include "rcs.h"
40 #include "log.h"
41 #include "proto.h"
42 
43 #define CVS_HISTORY_MAXMOD    16
44 
45 /* history flags */
46 #define CVS_HF_A     0x01
47 #define CVS_HF_C     0x02
48 #define CVS_HF_E     0x04
49 #define CVS_HF_L     0x08
50 #define CVS_HF_M     0x10
51 #define CVS_HF_O     0x20
52 #define CVS_HF_T     0x40
53 #define CVS_HF_W     0x80
54 
55 #define CVS_HF_EXCL (CVS_HF_C|CVS_HF_E|CVS_HF_M|CVS_HF_O|CVS_HF_T|CVS_HF_X)
56 
57 static void  cvs_history_print  (struct cvs_hent *);
58 
59 
60 extern char *__progname;
61 
62 
63 /*
64  * cvs_history()
65  *
66  * Handle the `cvs history' command.
67  */
68 
69 int
70 cvs_history(int argc, char **argv)
71 {
72 	int ch, flags;
73 	u_int nbmod, rep;
74 	char *user, *zone, *tag, *cp;
75 	char *modules[CVS_HISTORY_MAXMOD], histpath[MAXPATHLEN];
76 	struct cvsroot *root;
77 	struct cvs_hent *hent;
78 	CVSHIST *hp;
79 
80 	tag = NULL;
81 	user = NULL;
82 	zone = "+0000";
83 	nbmod = 0;
84 	flags = 0;
85 	rep = 0;
86 
87 	while ((ch = getopt(argc, argv, "acelm:oTt:u:wx:z:")) != -1) {
88 		switch (ch) {
89 		case 'a':
90 			flags |= CVS_HF_A;
91 			break;
92 		case 'c':
93 			rep++;
94 			flags |= CVS_HF_C;
95 			break;
96 		case 'e':
97 			rep++;
98 			flags |= CVS_HF_E;
99 			break;
100 		case 'l':
101 			flags |= CVS_HF_L;
102 			break;
103 		case 'm':
104 			rep++;
105 			flags |= CVS_HF_M;
106 			if (nbmod == CVS_HISTORY_MAXMOD) {
107 				cvs_log(LP_ERR, "too many `-m' options");
108 				return (EX_USAGE);
109 			}
110 			modules[nbmod++] = optarg;
111 			break;
112 		case 'o':
113 			rep++;
114 			flags |= CVS_HF_O;
115 			break;
116 		case 'T':
117 			rep++;
118 			flags |= CVS_HF_T;
119 			break;
120 		case 't':
121 			tag = optarg;
122 			break;
123 		case 'u':
124 			user = optarg;
125 			break;
126 		case 'w':
127 			flags |= CVS_HF_W;
128 			break;
129 		case 'x':
130 			rep++;
131 			for (cp = optarg; *cp != '\0'; cp++) {
132 			}
133 			break;
134 		case 'z':
135 			zone = optarg;
136 			break;
137 		default:
138 			return (EX_USAGE);
139 		}
140 	}
141 
142 	if (rep > 1) {
143 		cvs_log(LP_ERR,
144 		    "Only one report type allowed from: \"-Tcomxe\"");
145 		return (EX_USAGE);
146 	}
147 	else if (rep == 0)
148 		flags |= CVS_HF_O;    /* use -o as default */
149 
150 	root = cvsroot_get(".");
151 	if (root->cr_method == CVS_METHOD_LOCAL) {
152 		snprintf(histpath, sizeof(histpath), "%s/%s", root->cr_dir,
153 		    CVS_PATH_HISTORY);
154 		hp = cvs_hist_open(histpath);
155 		if (hp == NULL) {
156 			return (EX_UNAVAILABLE);
157 		}
158 
159 		while ((hent = cvs_hist_getnext(hp)) != NULL) {
160 			cvs_history_print(hent);
161 		}
162 		cvs_hist_close(hp);
163 	}
164 	else {
165 		if (flags & CVS_HF_C)
166 			cvs_sendarg(root, "-c", 0);
167 
168 		if (flags & CVS_HF_O)
169 			cvs_sendarg(root, "-o", 0);
170 
171 		if (tag != NULL) {
172 			cvs_sendarg(root, "-t", 0);
173 			cvs_sendarg(root, tag, 0);
174 		}
175 		if (user != NULL) {
176 			cvs_sendarg(root, "-u", 0);
177 			cvs_sendarg(root, user, 0);
178 		}
179 
180 		cvs_sendarg(root, "-z", 0);
181 		cvs_sendarg(root, zone, 0);
182 
183 		cvs_sendreq(root, CVS_REQ_HISTORY, NULL);
184 	}
185 
186 	return (0);
187 }
188 
189 
190 static void
191 cvs_history_print(struct cvs_hent *hent)
192 {
193 	struct tm etime;
194 
195 	if (localtime_r(&(hent->ch_date), &etime) == NULL) {
196 		cvs_log(LP_ERROR, "failed to convert timestamp to structure");
197 		return;
198 	}
199 
200 	printf("%c %4d-%02d-%02d %02d:%02d +%04d %-16s %-16s\n",
201 	    hent->ch_event, etime.tm_year + 1900, etime.tm_mon + 1,
202 	    etime.tm_mday, etime.tm_hour, etime.tm_min,
203 	    0, hent->ch_user, hent->ch_repo);
204 }
205