xref: /openbsd-src/usr.bin/cvs/history.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
1 /*	$OpenBSD: history.c,v 1.5 2004/12/07 17:10:56 tedu 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 int
69 cvs_history(int argc, char **argv)
70 {
71 	int ch, flags;
72 	u_int nbmod, rep;
73 	char *user, *zone, *tag, *cp;
74 	char *modules[CVS_HISTORY_MAXMOD], histpath[MAXPATHLEN];
75 	struct cvsroot *root;
76 	struct cvs_hent *hent;
77 	CVSHIST *hp;
78 
79 	tag = NULL;
80 	user = NULL;
81 	zone = "+0000";
82 	nbmod = 0;
83 	flags = 0;
84 	rep = 0;
85 
86 	while ((ch = getopt(argc, argv, "acelm:oTt:u:wx:z:")) != -1) {
87 		switch (ch) {
88 		case 'a':
89 			flags |= CVS_HF_A;
90 			break;
91 		case 'c':
92 			rep++;
93 			flags |= CVS_HF_C;
94 			break;
95 		case 'e':
96 			rep++;
97 			flags |= CVS_HF_E;
98 			break;
99 		case 'l':
100 			flags |= CVS_HF_L;
101 			break;
102 		case 'm':
103 			rep++;
104 			flags |= CVS_HF_M;
105 			if (nbmod == CVS_HISTORY_MAXMOD) {
106 				cvs_log(LP_ERR, "too many `-m' options");
107 				return (EX_USAGE);
108 			}
109 			modules[nbmod++] = optarg;
110 			break;
111 		case 'o':
112 			rep++;
113 			flags |= CVS_HF_O;
114 			break;
115 		case 'T':
116 			rep++;
117 			flags |= CVS_HF_T;
118 			break;
119 		case 't':
120 			tag = optarg;
121 			break;
122 		case 'u':
123 			user = optarg;
124 			break;
125 		case 'w':
126 			flags |= CVS_HF_W;
127 			break;
128 		case 'x':
129 			rep++;
130 			for (cp = optarg; *cp != '\0'; cp++) {
131 			}
132 			break;
133 		case 'z':
134 			zone = optarg;
135 			break;
136 		default:
137 			return (EX_USAGE);
138 		}
139 	}
140 
141 	if (rep > 1) {
142 		cvs_log(LP_ERR,
143 		    "Only one report type allowed from: \"-Tcomxe\"");
144 		return (EX_USAGE);
145 	} else if (rep == 0)
146 		flags |= CVS_HF_O;    /* use -o as default */
147 
148 	root = cvsroot_get(".");
149 	if (root->cr_method == CVS_METHOD_LOCAL) {
150 		snprintf(histpath, sizeof(histpath), "%s/%s", root->cr_dir,
151 		    CVS_PATH_HISTORY);
152 		hp = cvs_hist_open(histpath);
153 		if (hp == NULL) {
154 			return (EX_UNAVAILABLE);
155 		}
156 
157 		while ((hent = cvs_hist_getnext(hp)) != NULL) {
158 			cvs_history_print(hent);
159 		}
160 		cvs_hist_close(hp);
161 	} else {
162 		if (flags & CVS_HF_C)
163 			cvs_sendarg(root, "-c", 0);
164 
165 		if (flags & CVS_HF_O)
166 			cvs_sendarg(root, "-o", 0);
167 
168 		if (tag != NULL) {
169 			cvs_sendarg(root, "-t", 0);
170 			cvs_sendarg(root, tag, 0);
171 		}
172 		if (user != NULL) {
173 			cvs_sendarg(root, "-u", 0);
174 			cvs_sendarg(root, user, 0);
175 		}
176 
177 		cvs_sendarg(root, "-z", 0);
178 		cvs_sendarg(root, zone, 0);
179 
180 		cvs_sendreq(root, CVS_REQ_HISTORY, NULL);
181 	}
182 
183 	return (0);
184 }
185 
186 
187 static void
188 cvs_history_print(struct cvs_hent *hent)
189 {
190 	struct tm etime;
191 
192 	if (localtime_r(&(hent->ch_date), &etime) == NULL) {
193 		cvs_log(LP_ERROR, "failed to convert timestamp to structure");
194 		return;
195 	}
196 
197 	printf("%c %4d-%02d-%02d %02d:%02d +%04d %-16s %-16s\n",
198 	    hent->ch_event, etime.tm_year + 1900, etime.tm_mon + 1,
199 	    etime.tm_mday, etime.tm_hour, etime.tm_min,
200 	    0, hent->ch_user, hent->ch_repo);
201 }
202