commit.c revision 1.9
1/* $OpenBSD: commit.c,v 1.9 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/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 46 47int cvs_commit_prepare (CVSFILE *, void *); 48int cvs_commit_file (CVSFILE *, void *); 49 50 51/* 52 * cvs_commit() 53 * 54 * Handler for the `cvs commit' command. 55 */ 56int 57cvs_commit(int argc, char **argv) 58{ 59 int i, ch, recurse, flags; 60 char *msg, *mfile; 61 struct cvs_flist cl; 62 struct cvsroot *root; 63 64 flags = CF_RECURSE|CF_IGNORE|CF_SORT; 65 recurse = 1; 66 mfile = NULL; 67 msg = NULL; 68 TAILQ_INIT(&cl); 69 70 while ((ch = getopt(argc, argv, "F:flm:R")) != -1) { 71 switch (ch) { 72 case 'F': 73 mfile = optarg; 74 break; 75 case 'f': 76 recurse = 0; 77 break; 78 case 'l': 79 recurse = 0; 80 break; 81 case 'm': 82 msg = optarg; 83 break; 84 case 'R': 85 recurse = 1; 86 break; 87 default: 88 return (EX_USAGE); 89 } 90 } 91 92 if ((msg != NULL) && (mfile != NULL)) { 93 cvs_log(LP_ERR, "the -F and -m flags are mutually exclusive"); 94 return (EX_USAGE); 95 } 96 97 if ((mfile != NULL) && (msg = cvs_logmsg_open(mfile)) == NULL) 98 return (EX_DATAERR); 99 100 argc -= optind; 101 argv += optind; 102 103 if (argc == 0) { 104 cvs_files = cvs_file_get(".", flags); 105 } else { 106 cvs_files = cvs_file_getspec(argv, argc, flags); 107 } 108 if (cvs_files == NULL) 109 return (EX_DATAERR); 110 111 cvs_file_examine(cvs_files, cvs_commit_prepare, &cl); 112 113 if (msg == NULL) { 114 msg = cvs_logmsg_get(CVS_FILE_NAME(cvs_files), &cl); 115 if (msg == NULL) 116 return (1); 117 } 118 119 root = CVS_DIR_ROOT(cvs_files); 120 cvs_connect(root); 121 cvs_logmsg_send(root, msg); 122 123 cvs_file_examine(cvs_files, cvs_commit_file, &cl); 124 125 if (root->cr_method != CVS_METHOD_LOCAL) { 126 cvs_senddir(root, cvs_files); 127 if (argc > 0) { 128 for (i = 0; i < argc; i++) 129 cvs_sendarg(root, argv[i], 0); 130 } 131 cvs_sendreq(root, CVS_REQ_CI, NULL); 132 } 133 134 return (0); 135} 136 137 138/* 139 * cvs_commit_prepare() 140 * 141 * Examine the file <cf> to see if it will be part of the commit, in which 142 * case it gets added to the list passed as second argument. 143 */ 144int 145cvs_commit_prepare(CVSFILE *cf, void *arg) 146{ 147 CVSFILE *copy; 148 struct cvs_flist *clp = (struct cvs_flist *)arg; 149 150 if ((cf->cf_type == DT_REG) && (cf->cf_cvstat == CVS_FST_MODIFIED)) { 151 copy = cvs_file_copy(cf); 152 if (copy == NULL) 153 return (-1); 154 155 TAILQ_INSERT_TAIL(clp, copy, cf_list); 156 } 157 158 return (0); 159} 160 161 162/* 163 * cvs_commit_file() 164 * 165 * Commit a single file. 166 */ 167int 168cvs_commit_file(CVSFILE *cf, void *arg) 169{ 170 char *repo, rcspath[MAXPATHLEN], fpath[MAXPATHLEN]; 171 RCSFILE *rf; 172 struct cvsroot *root; 173 struct cvs_ent *entp; 174 175 rf = NULL; 176 repo = NULL; 177 178 if (cf->cf_type == DT_DIR) { 179 if (cf->cf_cvstat != CVS_FST_UNKNOWN) { 180 root = CVS_DIR_ROOT(cf); 181 if ((cf->cf_parent != NULL) && 182 (root != cf->cf_parent->cf_ddat->cd_root)) { 183 cvs_connect(root); 184 } 185 186 cvs_senddir(root, cf); 187 } 188 189 return (0); 190 } 191 192 193 root = CVS_DIR_ROOT(cf); 194 cvs_file_getpath(cf, fpath, sizeof(fpath)); 195 196 if (cf->cf_parent != NULL) 197 repo = cf->cf_parent->cf_ddat->cd_repo; 198 199 entp = cvs_ent_getent(fpath); 200 if (entp == NULL) 201 return (-1); 202 203 if ((cf->cf_cvstat == CVS_FST_ADDED) || 204 (cf->cf_cvstat == CVS_FST_MODIFIED)) { 205 if ((root->cr_method != CVS_METHOD_LOCAL) && 206 (cvs_sendentry(root, entp) < 0)) { 207 cvs_ent_free(entp); 208 return (-1); 209 } 210 211 cvs_sendreq(root, CVS_REQ_MODIFIED, CVS_FILE_NAME(cf)); 212 cvs_sendfile(root, fpath); 213 } 214 215 snprintf(rcspath, sizeof(rcspath), "%s/%s/%s%s", 216 root->cr_dir, repo, fpath, RCS_FILE_EXT); 217 218 cvs_ent_free(entp); 219 220 return (0); 221} 222