1 /* $OpenBSD: commit.c,v 1.6 2004/11/26 16:23:50 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/types.h> 28 #include <sys/queue.h> 29 #include <sys/stat.h> 30 31 #include <errno.h> 32 #include <stdio.h> 33 #include <fcntl.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <string.h> 37 #include <sysexits.h> 38 39 #include "cvs.h" 40 #include "log.h" 41 #include "buf.h" 42 #include "proto.h" 43 44 45 LIST_HEAD(ci_list, ci_file); 46 47 struct ci_file { 48 char *ci_path; 49 RCSNUM *ci_rev; 50 LIST_ENTRY(ci_file) ci_link; 51 }; 52 53 54 55 int cvs_commit_file (CVSFILE *, void *); 56 57 58 /* 59 * cvs_commit() 60 * 61 * Handler for the `cvs commit' command. 62 */ 63 64 int 65 cvs_commit(int argc, char **argv) 66 { 67 int ch, recurse, flags; 68 char *msg, *mfile; 69 struct ci_list cl; 70 71 flags = 0; 72 recurse = 1; 73 mfile = NULL; 74 msg = NULL; 75 LIST_INIT(&cl); 76 77 while ((ch = getopt(argc, argv, "F:flm:R")) != -1) { 78 switch (ch) { 79 case 'F': 80 mfile = optarg; 81 break; 82 case 'f': 83 recurse = 0; 84 break; 85 case 'l': 86 recurse = 0; 87 break; 88 case 'm': 89 msg = optarg; 90 break; 91 case 'R': 92 recurse = 1; 93 break; 94 default: 95 return (EX_USAGE); 96 } 97 } 98 99 if ((msg != NULL) && (mfile != NULL)) { 100 cvs_log(LP_ERR, "the -F and -m flags are mutually exclusive"); 101 return (EX_USAGE); 102 } 103 104 if ((mfile != NULL) && (msg = cvs_logmsg_open(mfile)) == NULL) 105 return (EX_DATAERR); 106 107 argc -= optind; 108 argv += optind; 109 110 if (argc == 0) 111 cvs_files = cvs_file_get(".", flags); 112 else { 113 cvs_files = cvs_file_getspec(argv, argc, flags); 114 } 115 if (cvs_files == NULL) 116 return (EX_DATAERR); 117 118 cvs_file_examine(cvs_files, cvs_commit_file, &cl); 119 120 cvs_senddir(cvs_files->cf_ddat->cd_root, cvs_files); 121 cvs_sendreq(cvs_files->cf_ddat->cd_root, CVS_REQ_CI, NULL); 122 123 return (0); 124 } 125 126 127 /* 128 * cvs_commit_file() 129 * 130 * Commit a single file. 131 */ 132 133 int 134 cvs_commit_file(CVSFILE *cf, void *arg) 135 { 136 char *repo, rcspath[MAXPATHLEN], fpath[MAXPATHLEN]; 137 RCSFILE *rf; 138 struct cvsroot *root; 139 struct cvs_ent *entp; 140 struct ci_list *cl; 141 142 cl = (struct ci_list *)arg; 143 144 if (cf->cf_type == DT_DIR) { 145 if (cf->cf_cvstat != CVS_FST_UNKNOWN) { 146 root = cf->cf_ddat->cd_root; 147 if ((cf->cf_parent == NULL) || 148 (root != cf->cf_parent->cf_ddat->cd_root)) { 149 cvs_connect(root); 150 } 151 152 cvs_senddir(root, cf); 153 } 154 155 return (0); 156 } 157 else 158 root = cf->cf_parent->cf_ddat->cd_root; 159 160 rf = NULL; 161 if (cf->cf_parent != NULL) { 162 repo = cf->cf_parent->cf_ddat->cd_repo; 163 } 164 else { 165 repo = NULL; 166 } 167 168 entp = cvs_ent_getent(fpath); 169 if (entp == NULL) 170 return (-1); 171 172 if ((cf->cf_cvstat == CVS_FST_ADDED) || 173 (cf->cf_cvstat == CVS_FST_MODIFIED)) { 174 if ((root->cr_method != CVS_METHOD_LOCAL) && 175 (cvs_sendentry(root, entp) < 0)) { 176 cvs_ent_free(entp); 177 return (-1); 178 } 179 180 cvs_sendreq(root, CVS_REQ_MODIFIED, CVS_FILE_NAME(cf)); 181 cvs_sendfile(root, fpath); 182 } 183 184 snprintf(rcspath, sizeof(rcspath), "%s/%s/%s%s", 185 root->cr_dir, repo, fpath, RCS_FILE_EXT); 186 187 cvs_ent_free(entp); 188 189 return (0); 190 } 191