1 /* $OpenBSD: history.c,v 1.35 2008/01/31 10:15:05 tobias Exp $ */ 2 /* 3 * Copyright (c) 2007 Joris Vink <joris@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/stat.h> 19 20 #include <ctype.h> 21 #include <errno.h> 22 #include <pwd.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <unistd.h> 26 27 #include "cvs.h" 28 #include "remote.h" 29 30 void cvs_history_local(struct cvs_file *); 31 32 struct cvs_cmd cvs_cmd_history = { 33 CVS_OP_HISTORY, CVS_USE_WDIR, "history", 34 { "hi", "his" }, /* omghi2you */ 35 "Display history of actions done in the base repository", 36 "[-ac]", 37 "ac", 38 NULL, 39 cvs_history 40 }; 41 42 /* keep in sync with the defines for history stuff in cvs.h */ 43 const char historytab[] = { 44 'T', 45 'O', 46 'E', 47 'F', 48 'W', 49 'U', 50 'G', 51 'C', 52 'M', 53 'A', 54 'R', 55 '\0' 56 }; 57 58 #define HISTORY_ALL_USERS 0x01 59 #define HISTORY_DISPLAY_ARCHIVED 0x02 60 61 void 62 cvs_history_add(int type, struct cvs_file *cf, const char *argument) 63 { 64 FILE *fp; 65 char *cwd; 66 char revbuf[CVS_REV_BUFSZ], repo[MAXPATHLEN], fpath[MAXPATHLEN]; 67 68 if (cvs_nolog == 1) 69 return; 70 71 if (cvs_cmdop == CVS_OP_CHECKOUT || cvs_cmdop == CVS_OP_EXPORT) { 72 if (type != CVS_HISTORY_CHECKOUT && 73 type != CVS_HISTORY_EXPORT) 74 return; 75 } 76 77 cvs_log(LP_TRACE, "cvs_history_add(`%c', `%s', `%s')", 78 historytab[type], (cf != NULL) ? cf->file_name : "", argument); 79 80 if (cvs_server_active == 1) { 81 cwd = "<remote>"; 82 } else { 83 if ((cwd = getcwd(NULL, MAXPATHLEN)) == NULL) 84 fatal("cvs_history_add: getcwd: %s", strerror(errno)); 85 } 86 87 /* construct repository field */ 88 if (cvs_cmdop != CVS_OP_CHECKOUT && cvs_cmdop != CVS_OP_EXPORT) { 89 cvs_get_repository_name(".", repo, sizeof(repo)); 90 } else { 91 strlcpy(repo, argument, sizeof(repo)); 92 } 93 94 /* construct revision field */ 95 revbuf[0] = '\0'; 96 if (cvs_cmdop != CVS_OP_CHECKOUT && cvs_cmdop != CVS_OP_EXPORT) { 97 switch (type) { 98 case CVS_HISTORY_TAG: 99 strlcpy(revbuf, argument, sizeof(revbuf)); 100 break; 101 case CVS_HISTORY_CHECKOUT: 102 case CVS_HISTORY_EXPORT: 103 /* copy TAG or DATE to revbuf */ 104 break; 105 case CVS_HISTORY_UPDATE_MERGED: 106 case CVS_HISTORY_UPDATE_MERGED_ERR: 107 case CVS_HISTORY_COMMIT_MODIFIED: 108 case CVS_HISTORY_COMMIT_ADDED: 109 case CVS_HISTORY_COMMIT_REMOVED: 110 case CVS_HISTORY_UPDATE_CO: 111 rcsnum_tostr(cf->file_rcs->rf_head, 112 revbuf, sizeof(revbuf)); 113 break; 114 } 115 } 116 117 (void)xsnprintf(fpath, sizeof(fpath), "%s/%s", 118 current_cvsroot->cr_dir, CVS_PATH_HISTORY); 119 120 if ((fp = fopen(fpath, "a")) != NULL) { 121 fprintf(fp, "%c%x|%s|%s|%s|%s|%s\n", 122 historytab[type], time(NULL), getlogin(), cwd, repo, 123 revbuf, (cf != NULL) ? cf->file_name : argument); 124 125 (void)fclose(fp); 126 } else { 127 cvs_log(LP_ERR, "failed to add entry to history file"); 128 } 129 130 if (cvs_server_active != 1) 131 xfree(cwd); 132 } 133 134 int 135 cvs_history(int argc, char **argv) 136 { 137 int ch, flags; 138 139 flags = 0; 140 141 while ((ch = getopt(argc, argv, cvs_cmd_history.cmd_opts)) != -1) { 142 switch (ch) { 143 case 'a': 144 flags |= HISTORY_ALL_USERS; 145 break; 146 case 'c': 147 flags |= HISTORY_DISPLAY_ARCHIVED; 148 break; 149 default: 150 fatal("%s", cvs_cmd_history.cmd_synopsis); 151 } 152 } 153 154 argc -= optind; 155 argv += optind; 156 157 return (0); 158 } 159