Annotation of src/usr.bin/cvs/import.c, Revision 1.43
1.43 ! deraadt 1: /* $OpenBSD: import.c,v 1.42 2006/04/05 01:38:55 ray Exp $ */
1.1 krapht 2: /*
1.5 joris 3: * Copyright (c) 2004 Joris Vink <joris@openbsd.org>
1.1 krapht 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:
1.35 xsa 27: #include "includes.h"
1.1 krapht 28:
1.23 xsa 29: #include "cvs.h"
1.1 krapht 30: #include "log.h"
31: #include "proto.h"
32:
1.3 jfb 33:
1.25 xsa 34: #define CVS_IMPORT_DEFBRANCH "1.1.1"
1.3 jfb 35:
1.19 jfb 36:
1.25 xsa 37: static int cvs_import_init(struct cvs_cmd *, int, char **, int *);
38: static int cvs_import_pre_exec(struct cvsroot *);
39: static int cvs_import_pre_exec(struct cvsroot *);
40: static int cvs_import_post_exec(struct cvsroot *);
41: static int cvs_import_remote(CVSFILE *, void *);
42: static int cvs_import_local(CVSFILE *, void *);
43: static int cvs_import_cleanup(void);
1.3 jfb 44:
1.18 jfb 45: static int dflag = 0;
1.19 jfb 46: static int conflicts = 0;
47: static RCSNUM *imp_brnum;
48:
49: static char *module, *vendor, *release;
1.3 jfb 50:
1.15 jfb 51: struct cvs_cmd cvs_cmd_import = {
52: CVS_OP_IMPORT, CVS_REQ_IMPORT, "import",
53: { "im", "imp" },
54: "Import sources into CVS, using vendor branches",
1.26 xsa 55: "[-d] [-b branch] [-I ign] [-k mode] [-m msg] [-W spec] module "
56: "vendortag releasetag ...",
57: "b:dI:k:m:W:",
1.15 jfb 58: NULL,
1.7 joris 59: CF_RECURSE | CF_IGNORE | CF_NOSYMS,
1.15 jfb 60: cvs_import_init,
61: cvs_import_pre_exec,
62: cvs_import_remote,
63: cvs_import_local,
1.19 jfb 64: cvs_import_post_exec,
65: cvs_import_cleanup,
1.7 joris 66: CVS_CMD_SENDDIR
67: };
1.1 krapht 68:
1.15 jfb 69: static int
70: cvs_import_init(struct cvs_cmd *cmd, int argc, char **argv, int *arg)
1.1 krapht 71: {
1.7 joris 72: int ch;
1.1 krapht 73:
1.15 jfb 74: while ((ch = getopt(argc, argv, cmd->cmd_opts)) != -1) {
1.1 krapht 75: switch (ch) {
76: case 'b':
1.19 jfb 77: if ((imp_brnum = rcsnum_parse(optarg)) == NULL) {
1.3 jfb 78: cvs_log(LP_ERR, "%s is not a numeric branch",
1.19 jfb 79: optarg);
1.11 joris 80: return (CVS_EX_USAGE);
1.3 jfb 81: }
82: break;
1.1 krapht 83: case 'd':
1.18 jfb 84: dflag = 1;
1.1 krapht 85: break;
86: case 'I':
87: if (cvs_file_ignore(optarg) < 0) {
88: cvs_log(LP_ERR, "failed to add `%s' to list "
89: "of ignore patterns", optarg);
1.11 joris 90: return (CVS_EX_USAGE);
1.1 krapht 91: }
92: break;
93: case 'k':
94: break;
95: case 'm':
1.31 joris 96: cvs_msg = xstrdup(optarg);
1.1 krapht 97: break;
98: default:
1.11 joris 99: return (CVS_EX_USAGE);
1.1 krapht 100: }
101: }
102:
103: argc -= optind;
104: argv += optind;
1.15 jfb 105: if (argc != 3)
1.11 joris 106: return (CVS_EX_USAGE);
1.1 krapht 107:
1.43 ! deraadt 108: if (imp_brnum == NULL &&
! 109: (imp_brnum = rcsnum_parse(CVS_IMPORT_DEFBRANCH)) == NULL)
1.37 xsa 110: fatal("cvs_import_init: rcsnum_parse failed");
1.19 jfb 111:
1.7 joris 112: module = argv[0];
113: vendor = argv[1];
114: release = argv[2];
1.1 krapht 115:
1.15 jfb 116: *arg = optind + 3;
117:
1.33 xsa 118: if (cvs_msg == NULL)
119: cvs_msg = cvs_logmsg_get(NULL, NULL, NULL, NULL);
1.1 krapht 120:
1.7 joris 121: return (0);
122: }
1.1 krapht 123:
1.15 jfb 124: static int
125: cvs_import_pre_exec(struct cvsroot *root)
1.7 joris 126: {
1.19 jfb 127: char numbuf[64], repodir[MAXPATHLEN];
1.15 jfb 128:
129: if (root->cr_method == CVS_METHOD_LOCAL) {
1.37 xsa 130: if (cvs_path_cat(root->cr_dir, module, repodir,
131: sizeof(repodir)) >= sizeof(repodir))
132: fatal("cvs_import_pre_exec: cvs_path_cat overflow");
133:
1.41 joris 134: if (mkdir(repodir, 0775) == -1)
1.37 xsa 135: fatal("cvs_import_pre_exec: mkdir `%s': %s",
136: repodir, strerror(errno));
1.15 jfb 137: } else {
1.19 jfb 138: rcsnum_tostr(imp_brnum, numbuf, sizeof(numbuf));
139:
1.34 joris 140: cvs_sendarg(root, "-b", 0);
141: cvs_sendarg(root, numbuf, 0);
142: cvs_logmsg_send(root, cvs_msg);
143: cvs_sendarg(root, module, 0);
144: cvs_sendarg(root, vendor, 0);
145: cvs_sendarg(root, release, 0);
1.15 jfb 146: }
1.1 krapht 147:
148: return (0);
149: }
150:
1.19 jfb 151: static int
152: cvs_import_post_exec(struct cvsroot *root)
153: {
154: char buf[8];
155:
156: if (root->cr_method == CVS_METHOD_LOCAL) {
157: if (conflicts > 0)
158: snprintf(buf, sizeof(buf), "%d", conflicts);
159:
1.24 xsa 160: if (verbosity > 0)
161: cvs_printf("\n%s conflicts created by this import\n\n",
162: conflicts == 0 ? "No" : buf);
1.19 jfb 163: }
164:
165: return (CVS_EX_OK);
166: }
167:
1.3 jfb 168: /*
1.15 jfb 169: * cvs_import_remote()
1.3 jfb 170: *
171: * Perform the import of a single file or directory.
172: */
1.15 jfb 173: static int
174: cvs_import_remote(CVSFILE *cf, void *arg)
1.1 krapht 175: {
1.37 xsa 176: size_t sz;
1.3 jfb 177: struct cvsroot *root;
178: char fpath[MAXPATHLEN], repodir[MAXPATHLEN];
1.21 jfb 179: char repo[MAXPATHLEN], date[32];
1.1 krapht 180:
1.15 jfb 181: root = CVS_DIR_ROOT(cf);
1.24 xsa 182:
1.37 xsa 183: if (cvs_path_cat(root->cr_dir, module, repo, sizeof(repo)) >=
184: sizeof(repo))
185: fatal("cvs_import_remove: cvs_path_cat overflow");
1.1 krapht 186:
1.15 jfb 187: cvs_file_getpath(cf, fpath, sizeof(fpath));
1.1 krapht 188:
1.15 jfb 189: if (cf->cf_type == DT_DIR) {
190: if (!strcmp(cf->cf_name, "."))
1.3 jfb 191: strlcpy(repodir, repo, sizeof(repodir));
1.12 xsa 192: else {
1.37 xsa 193: if(cvs_path_cat(repo, fpath, repodir,
194: sizeof(repodir)) >= sizeof(repodir))
195: fatal("cvs_import_remove: cvs_path_cat overflow");
1.12 xsa 196: }
1.15 jfb 197:
1.34 joris 198: cvs_sendreq(root, CVS_REQ_DIRECTORY, fpath);
199: cvs_sendln(root, repodir);
1.15 jfb 200: return (0);
201: }
202:
1.28 xsa 203: if (dflag == 1) {
1.21 jfb 204: ctime_r(&(cf->cf_mtime), date);
1.22 jfb 205: sz = strlen(date);
1.43 ! deraadt 206: if (sz > 0 && date[sz - 1] == '\n')
1.22 jfb 207: date[--sz] = '\0';
1.34 joris 208: cvs_sendreq(root, CVS_REQ_CHECKINTIME, date);
1.21 jfb 209: }
1.34 joris 210:
211: cvs_sendreq(root, CVS_REQ_MODIFIED, cf->cf_name);
212: cvs_sendfile(root, fpath);
1.15 jfb 213:
214: return (0);
215: }
216:
217: static int
218: cvs_import_local(CVSFILE *cf, void *arg)
219: {
1.18 jfb 220: time_t stamp;
1.30 joris 221: char *fcont;
1.15 jfb 222: char fpath[MAXPATHLEN], rpath[MAXPATHLEN], repo[MAXPATHLEN];
1.17 jfb 223: const char *comment;
1.18 jfb 224: struct stat fst;
225: struct timeval ts[2];
226: struct cvsroot *root;
1.41 joris 227: struct rcs_delta *rdp;
228: struct rcs_branch *brp;
1.15 jfb 229: RCSFILE *rf;
1.41 joris 230: RCSNUM *rev, *brev;
1.30 joris 231: BUF *bp;
1.15 jfb 232:
233: root = CVS_DIR_ROOT(cf);
1.24 xsa 234:
1.37 xsa 235: if (cvs_path_cat(root->cr_dir, module, repo, sizeof(repo)) >=
236: sizeof(repo))
237: fatal("cvs_import_local: cvs_path_cat overflow");
1.15 jfb 238:
239: cvs_file_getpath(cf, fpath, sizeof(fpath));
240:
241: if (cf->cf_type == DT_DIR) {
242: if (!strcmp(cf->cf_name, "."))
243: strlcpy(rpath, repo, sizeof(rpath));
244: else {
1.37 xsa 245: if (cvs_path_cat(repo, fpath, rpath,
246: sizeof(rpath)) >= sizeof(rpath))
247: fatal("cvs_import_local: cvs_path_cat overflow");
1.15 jfb 248:
249: cvs_printf("Importing %s\n", rpath);
1.41 joris 250: if (mkdir(rpath, 0755) == -1) {
1.15 jfb 251: cvs_log(LP_ERRNO, "failed to create %s",
252: rpath);
253: }
1.3 jfb 254: }
1.1 krapht 255:
1.3 jfb 256: return (0);
1.1 krapht 257: }
258:
1.18 jfb 259: /*
260: * If -d was given, use the file's last modification time as the
261: * timestamps for the initial revisions.
262: */
1.28 xsa 263: if (dflag == 1) {
1.37 xsa 264: if (stat(fpath, &fst) == -1)
265: fatal("cvs_import_local: stat failed on `%s': %s",
266: fpath, strerror(errno));
267:
1.18 jfb 268: stamp = (time_t)fst.st_mtime;
269:
270: ts[0].tv_sec = stamp;
271: ts[0].tv_usec = 0;
272: ts[1].tv_sec = stamp;
273: ts[1].tv_usec = 0;
274: } else
275: stamp = -1;
276:
1.36 xsa 277: if (strlcpy(rpath, repo, sizeof(rpath)) >= sizeof(rpath) ||
278: strlcat(rpath, "/", sizeof(rpath)) >= sizeof(rpath) ||
279: strlcat(rpath, fpath, sizeof(rpath)) >= sizeof(rpath) ||
280: strlcat(rpath, RCS_FILE_EXT, sizeof(rpath)) >= sizeof(rpath))
281: fatal("cvs_import_local: path truncation");
1.15 jfb 282:
283: cvs_printf("N %s\n", fpath);
284:
1.41 joris 285: if ((rf = rcs_open(rpath, RCS_RDWR|RCS_CREATE, 0444)) == NULL)
1.37 xsa 286: fatal("cvs_import_local: rcs_open: `%s': %s", rpath,
1.38 xsa 287: rcs_errstr(rcs_errno));
1.17 jfb 288:
289: comment = rcs_comment_lookup(cf->cf_name);
1.40 xsa 290: if (comment != NULL)
291: rcs_comment_set(rf, comment);
1.17 jfb 292:
1.41 joris 293: brev = rcsnum_brtorev(imp_brnum);
294: if (rcs_rev_add(rf, brev, cvs_msg, stamp, NULL) < 0) {
1.37 xsa 295: (void)unlink(rpath);
296: fatal("cvs_import_local: rcs_rev_add failed: %s",
1.17 jfb 297: rcs_errstr(rcs_errno));
298: }
1.18 jfb 299:
1.41 joris 300: if (rcs_sym_add(rf, release, brev) < 0) {
1.37 xsa 301: (void)unlink(rpath);
302: fatal("cvs_import_local: rcs_sym_add failed: %s",
1.38 xsa 303: rcs_errstr(rcs_errno));
1.18 jfb 304: }
305:
1.41 joris 306: rev = rcsnum_alloc();
1.20 jfb 307: rcsnum_cpy(imp_brnum, rev, 2);
1.27 niallo 308: if (rcs_rev_add(rf, rev, cvs_msg, stamp, NULL) < 0) {
1.37 xsa 309: (void)unlink(rpath);
310: fatal("cvs_import_local: rcs_rev_add failed: %s",
1.17 jfb 311: rcs_errstr(rcs_errno));
312: }
313:
314: if (rcs_head_set(rf, rev) < 0) {
1.37 xsa 315: (void)unlink(rpath);
316: fatal("cvs_import_local: rcs_head_set failed: %s",
1.17 jfb 317: rcs_errstr(rcs_errno));
1.1 krapht 318: }
319:
1.19 jfb 320: if (rcs_branch_set(rf, imp_brnum) < 0) {
1.37 xsa 321: (void)unlink(rpath);
322: fatal("cvs_import_local: rcs_branch_set failed: %s",
1.38 xsa 323: rcs_errstr(rcs_errno));
1.20 jfb 324: }
325:
326: if (rcs_sym_add(rf, vendor, imp_brnum) < 0) {
1.37 xsa 327: (void)unlink(rpath);
328: fatal("cvs_import_local: rcs_sym_add failed: %s",
1.38 xsa 329: rcs_errstr(rcs_errno));
1.30 joris 330: }
1.41 joris 331:
332: /*
333: * Put the branch revision on the branches list for the first revision.
334: */
335: rdp = rcs_findrev(rf, rev);
1.42 ray 336: brp = xmalloc(sizeof(*brp));
1.41 joris 337: brp->rb_num = rcsnum_alloc();
338: rcsnum_cpy(brev, brp->rb_num, 0);
339: TAILQ_INSERT_TAIL(&(rdp->rd_branches), brp, rb_list);
1.30 joris 340:
341: if ((bp = cvs_buf_load(fpath, BUF_AUTOEXT)) == NULL) {
342: (void)unlink(rpath);
1.37 xsa 343: fatal("cvs_import_local: cvs_buf_load failed");
1.30 joris 344: }
345:
1.32 xsa 346: cvs_buf_putc(bp, '\0');
1.30 joris 347:
348: fcont = cvs_buf_release(bp);
349:
350: if (rcs_deltatext_set(rf, rev, fcont) < 0) {
1.20 jfb 351: (void)unlink(rpath);
1.37 xsa 352: fatal("cvs_import_local: rcs_deltatext_set failed");
1.18 jfb 353: }
354:
355: /* add the vendor tag and release tag as symbols */
1.15 jfb 356: rcs_close(rf);
1.18 jfb 357:
1.43 ! deraadt 358: if (dflag ==1 && utimes(rpath, ts) == -1)
1.18 jfb 359: cvs_log(LP_ERRNO, "failed to timestamp RCS file");
1.15 jfb 360:
1.37 xsa 361: return (0);
1.19 jfb 362: }
363:
364: static int
365: cvs_import_cleanup(void)
366: {
367: if (imp_brnum != NULL)
368: rcsnum_free(imp_brnum);
369: return (0);
1.1 krapht 370: }