1*84c3cb67Sxsa /* $OpenBSD: getlog.c,v 1.25 2005/05/19 15:37:50 xsa Exp $ */ 26c121f58Sjfb /* 36c121f58Sjfb * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> 46c121f58Sjfb * All rights reserved. 56c121f58Sjfb * 66c121f58Sjfb * Redistribution and use in source and binary forms, with or without 76c121f58Sjfb * modification, are permitted provided that the following conditions 86c121f58Sjfb * are met: 96c121f58Sjfb * 106c121f58Sjfb * 1. Redistributions of source code must retain the above copyright 116c121f58Sjfb * notice, this list of conditions and the following disclaimer. 126c121f58Sjfb * 2. The name of the author may not be used to endorse or promote products 136c121f58Sjfb * derived from this software without specific prior written permission. 146c121f58Sjfb * 156c121f58Sjfb * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 166c121f58Sjfb * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 176c121f58Sjfb * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 186c121f58Sjfb * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 196c121f58Sjfb * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 206c121f58Sjfb * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 216c121f58Sjfb * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 226c121f58Sjfb * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 236c121f58Sjfb * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 246c121f58Sjfb * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 256c121f58Sjfb */ 266c121f58Sjfb 276c121f58Sjfb #include <sys/param.h> 286c121f58Sjfb 296c121f58Sjfb #include <stdlib.h> 306c121f58Sjfb #include <stdio.h> 316c121f58Sjfb #include <unistd.h> 326c121f58Sjfb #include <errno.h> 336c121f58Sjfb #include <string.h> 346c121f58Sjfb #include <paths.h> 356c121f58Sjfb 366c121f58Sjfb #include "cvs.h" 376c121f58Sjfb #include "log.h" 38a96bf98bSjfb #include "file.h" 39dc6a6879Sjfb #include "proto.h" 406c121f58Sjfb 416c121f58Sjfb 426c121f58Sjfb #define CVS_GLOG_RFONLY 0x01 436c121f58Sjfb #define CVS_GLOG_HDONLY 0x02 446c121f58Sjfb 456c121f58Sjfb 466c121f58Sjfb #define CVS_GETLOG_REVSEP "----------------------------" 476c121f58Sjfb #define CVS_GETLOG_REVEND \ 486c121f58Sjfb "=============================================================================" 496c121f58Sjfb 50874e0b9fSjfb static int cvs_getlog_remote (CVSFILE *, void *); 519931af54Sjfb static int cvs_getlog_local (CVSFILE *, void *); 52*84c3cb67Sxsa static int cvs_getlog_options(char *, int, char **, int *); 53*84c3cb67Sxsa static int cvs_getlog_sendflags(struct cvsroot *); 546c121f58Sjfb 5516cfc147Sjoris struct cvs_cmd_info cvs_getlog = { 5616cfc147Sjoris cvs_getlog_options, 57*84c3cb67Sxsa cvs_getlog_sendflags, 58874e0b9fSjfb cvs_getlog_remote, 5916cfc147Sjoris NULL, NULL, 60fcc15918Sjoris CF_IGNORE | CF_RECURSE, 6116cfc147Sjoris CVS_REQ_LOG, 6216cfc147Sjoris CVS_CMD_SENDDIR | CVS_CMD_ALLOWSPEC | CVS_CMD_SENDARGS2 6316cfc147Sjoris }; 646c121f58Sjfb 65874e0b9fSjfb static int log_rfonly = 0; 66874e0b9fSjfb static int log_honly = 0; 67*84c3cb67Sxsa static int log_lhonly = 0; 68874e0b9fSjfb static int log_notags = 0; 6916cfc147Sjoris 70*84c3cb67Sxsa static int 7116cfc147Sjoris cvs_getlog_options(char *opt, int argc, char **argv, int *arg) 726c121f58Sjfb { 7316cfc147Sjoris int ch; 746c121f58Sjfb 7516cfc147Sjoris while ((ch = getopt(argc, argv, opt)) != -1) { 7616cfc147Sjoris switch (ch) { 77*84c3cb67Sxsa case 'b': 78*84c3cb67Sxsa break; 796c121f58Sjfb case 'd': 806c121f58Sjfb break; 816c121f58Sjfb case 'h': 82874e0b9fSjfb log_honly = 1; 836c121f58Sjfb break; 846c121f58Sjfb case 'l': 8516cfc147Sjoris cvs_getlog.file_flags &= ~CF_RECURSE; 866c121f58Sjfb break; 87874e0b9fSjfb case 'N': 88874e0b9fSjfb log_notags = 1; 89874e0b9fSjfb break; 906c121f58Sjfb case 'R': 91874e0b9fSjfb log_rfonly = 1; 926c121f58Sjfb break; 936c121f58Sjfb case 'r': 946c121f58Sjfb break; 95*84c3cb67Sxsa case 's': 96*84c3cb67Sxsa break; 97*84c3cb67Sxsa case 't': 98*84c3cb67Sxsa log_lhonly = 1; 99*84c3cb67Sxsa break; 100*84c3cb67Sxsa case 'w': 101*84c3cb67Sxsa break; 1026c121f58Sjfb default: 10331274bbfSjoris return (CVS_EX_USAGE); 1046c121f58Sjfb } 1056c121f58Sjfb } 1066c121f58Sjfb 10716cfc147Sjoris *arg = optind; 1086c121f58Sjfb return (0); 1096c121f58Sjfb } 1106c121f58Sjfb 111*84c3cb67Sxsa static int 112*84c3cb67Sxsa cvs_getlog_sendflags(struct cvsroot *root) 113*84c3cb67Sxsa { 114*84c3cb67Sxsa if (log_honly && (cvs_sendarg(root, "-h", 0) < 0)) 115*84c3cb67Sxsa return (CVS_EX_PROTO); 116*84c3cb67Sxsa if (log_notags && (cvs_sendarg(root, "-N", 0) < 0)) 117*84c3cb67Sxsa return (CVS_EX_PROTO); 118*84c3cb67Sxsa if (log_rfonly && (cvs_sendarg(root, "-R", 0) < 0)) 119*84c3cb67Sxsa return (CVS_EX_PROTO); 120*84c3cb67Sxsa if (log_lhonly && (cvs_sendarg(root, "-t", 0) < 0)) 121*84c3cb67Sxsa return (CVS_EX_PROTO); 122*84c3cb67Sxsa 123*84c3cb67Sxsa return (0); 124*84c3cb67Sxsa } 1256c121f58Sjfb 126a96bf98bSjfb /* 127874e0b9fSjfb * cvs_getlog_remote() 128a96bf98bSjfb * 129a96bf98bSjfb */ 130a96bf98bSjfb static int 131874e0b9fSjfb cvs_getlog_remote(CVSFILE *cf, void *arg) 132a96bf98bSjfb { 13325c4314aSjfb int ret; 134c710bc5aSjfb char *repo, fpath[MAXPATHLEN]; 135a96bf98bSjfb struct cvsroot *root; 136df745765Sjfb 13725c4314aSjfb ret = 0; 13825c4314aSjfb root = CVS_DIR_ROOT(cf); 13925c4314aSjfb repo = CVS_DIR_REPO(cf); 140a96bf98bSjfb 141b5f0ecd9Sjfb if (cf->cf_type == DT_DIR) { 14225c4314aSjfb if (cf->cf_cvstat == CVS_FST_UNKNOWN) 14325c4314aSjfb ret = cvs_sendreq(root, CVS_REQ_QUESTIONABLE, 144c710bc5aSjfb CVS_FILE_NAME(cf)); 14525c4314aSjfb else 14625c4314aSjfb ret = cvs_senddir(root, cf); 14725c4314aSjfb return (ret); 148a96bf98bSjfb } 149a96bf98bSjfb 15025c4314aSjfb cvs_file_getpath(cf, fpath, sizeof(fpath)); 151a96bf98bSjfb 152bb029937Sjfb if (cvs_sendentry(root, cf) < 0) { 1539931af54Sjfb return (-1); 154a96bf98bSjfb } 155a96bf98bSjfb 156a96bf98bSjfb switch (cf->cf_cvstat) { 15725c4314aSjfb case CVS_FST_UNKNOWN: 158874e0b9fSjfb ret = cvs_sendreq(root, CVS_REQ_QUESTIONABLE, cf->cf_name); 15925c4314aSjfb break; 160a96bf98bSjfb case CVS_FST_UPTODATE: 161874e0b9fSjfb ret = cvs_sendreq(root, CVS_REQ_UNCHANGED, cf->cf_name); 162a96bf98bSjfb break; 163a96bf98bSjfb case CVS_FST_ADDED: 164a96bf98bSjfb case CVS_FST_MODIFIED: 165874e0b9fSjfb ret = cvs_sendreq(root, CVS_REQ_ISMODIFIED, cf->cf_name); 166a96bf98bSjfb break; 167a96bf98bSjfb default: 16825c4314aSjfb break; 169a96bf98bSjfb } 17025c4314aSjfb 17125c4314aSjfb return (ret); 172a96bf98bSjfb } 173df745765Sjfb 1746c121f58Sjfb 1759931af54Sjfb 1769931af54Sjfb static int 1779931af54Sjfb cvs_getlog_local(CVSFILE *cf, void *arg) 1789931af54Sjfb { 1796842d763Sxsa int nrev, l; 180874e0b9fSjfb char rcspath[MAXPATHLEN], numbuf[64]; 1819931af54Sjfb char *repo; 1829931af54Sjfb RCSFILE *rf; 1839931af54Sjfb struct rcs_sym *sym; 1849931af54Sjfb struct rcs_delta *rdp; 185874e0b9fSjfb struct rcs_access *acp; 1869931af54Sjfb struct cvsroot *root; 1879931af54Sjfb 1889931af54Sjfb if (cf->cf_cvstat == CVS_FST_UNKNOWN) { 189874e0b9fSjfb cvs_log(LP_WARN, "nothing known about %s", cf->cf_name); 1909931af54Sjfb return (0); 1919931af54Sjfb } 1929931af54Sjfb 193874e0b9fSjfb if (cf->cf_type == DT_DIR) { 194874e0b9fSjfb cvs_log(LP_INFO, "Logging %s", cf->cf_name); 1959931af54Sjfb return (0); 196874e0b9fSjfb } 1979931af54Sjfb 1989931af54Sjfb nrev = 0; 1999931af54Sjfb root = CVS_DIR_ROOT(cf); 2009931af54Sjfb repo = CVS_DIR_REPO(cf); 2019931af54Sjfb 2026842d763Sxsa l = snprintf(rcspath, sizeof(rcspath), "%s/%s/%s%s", 2039931af54Sjfb root->cr_dir, repo, CVS_FILE_NAME(cf), RCS_FILE_EXT); 2046842d763Sxsa if (l == -1 || l >= (int)sizeof(rcspath)) { 2056842d763Sxsa errno = ENAMETOOLONG; 2066842d763Sxsa cvs_log(LP_ERRNO, "%s", rcspath); 2076842d763Sxsa return (-1); 2086842d763Sxsa } 2099931af54Sjfb 210874e0b9fSjfb if (log_rfonly) { 211874e0b9fSjfb cvs_printf("%s\n", rcspath); 212874e0b9fSjfb return (0); 213874e0b9fSjfb } 214874e0b9fSjfb 2159931af54Sjfb rf = rcs_open(rcspath, RCS_READ); 2169931af54Sjfb if (rf == NULL) 2179931af54Sjfb return (-1); 2189931af54Sjfb 2199931af54Sjfb cvs_printf("\nRCS file: %s\nWorking file: %s\n", rcspath, cf->cf_name); 2209931af54Sjfb cvs_printf("head: %s\n", 2219931af54Sjfb rcsnum_tostr(rcs_head_get(rf), numbuf, sizeof(numbuf))); 2229931af54Sjfb cvs_printf("branch: %s\n", 2239931af54Sjfb rcsnum_tostr(rcs_branch_get(rf), numbuf, sizeof(numbuf))); 224874e0b9fSjfb cvs_printf("locks: %s\n", (rf->rf_flags & RCS_SLOCK) ? "strict" : ""); 2259931af54Sjfb 226874e0b9fSjfb cvs_printf("access list:\n"); 227874e0b9fSjfb TAILQ_FOREACH(acp, &(rf->rf_access), ra_list) 228874e0b9fSjfb cvs_printf("\t%s\n", acp->ra_name); 229874e0b9fSjfb 230874e0b9fSjfb if (!log_notags) { 2319931af54Sjfb cvs_printf("symbolic names:\n"); 232874e0b9fSjfb TAILQ_FOREACH(sym, &(rf->rf_symbols), rs_list) 2339931af54Sjfb cvs_printf("\t%s: %s\n", sym->rs_name, 2349931af54Sjfb rcsnum_tostr(sym->rs_num, numbuf, sizeof(numbuf))); 2359931af54Sjfb } 236874e0b9fSjfb 2379931af54Sjfb cvs_printf("keyword substitution: %s\n", ""); 238874e0b9fSjfb 239874e0b9fSjfb if (log_honly) 240874e0b9fSjfb cvs_printf("total revisions: %u;\n", rf->rf_ndelta); 241874e0b9fSjfb else { 2429931af54Sjfb cvs_printf("total revisions: %u;\tselected revisions: %u\n", 2439931af54Sjfb rf->rf_ndelta, nrev); 244874e0b9fSjfb cvs_printf("description:\n%s", rf->rf_desc); 2459931af54Sjfb TAILQ_FOREACH(rdp, &(rf->rf_delta), rd_list) { 246df745765Sjfb rcsnum_tostr(rdp->rd_num, numbuf, sizeof(numbuf)); 2479931af54Sjfb cvs_printf(CVS_GETLOG_REVSEP "\nrevision %s\n", numbuf); 248874e0b9fSjfb cvs_printf("date: %d/%02d/%02d %02d:%02d:%02d;" 249874e0b9fSjfb " author: %s; state: %s;\n", 250874e0b9fSjfb rdp->rd_date.tm_year + 1900, 251874e0b9fSjfb rdp->rd_date.tm_mon + 1, 2526c121f58Sjfb rdp->rd_date.tm_mday, rdp->rd_date.tm_hour, 2536c121f58Sjfb rdp->rd_date.tm_min, rdp->rd_date.tm_sec, 2546c121f58Sjfb rdp->rd_author, rdp->rd_state); 2559931af54Sjfb cvs_printf("%s", rdp->rd_log); 2566c121f58Sjfb } 257874e0b9fSjfb } 2586c121f58Sjfb 259a96bf98bSjfb cvs_printf(CVS_GETLOG_REVEND "\n"); 2609931af54Sjfb 2619931af54Sjfb rcs_close(rf); 2629931af54Sjfb 2639931af54Sjfb return (0); 2646c121f58Sjfb } 265