Annotation of src/usr.bin/cvs/import.c, Revision 1.82
1.82 ! tobias 1: /* $OpenBSD: import.c,v 1.81 2008/01/31 21:30:08 joris Exp $ */
1.1 krapht 2: /*
1.45 joris 3: * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
1.1 krapht 4: *
1.45 joris 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.
1.1 krapht 8: *
1.45 joris 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.
1.1 krapht 16: */
17:
1.72 otto 18: #include <sys/stat.h>
19:
20: #include <errno.h>
21: #include <fcntl.h>
22: #include <string.h>
23: #include <unistd.h>
1.1 krapht 24:
1.23 xsa 25: #include "cvs.h"
1.45 joris 26: #include "diff.h"
1.64 joris 27: #include "remote.h"
1.1 krapht 28:
1.45 joris 29: void cvs_import_local(struct cvs_file *);
1.3 jfb 30:
1.45 joris 31: static void import_new(struct cvs_file *);
32: static void import_update(struct cvs_file *);
1.47 joris 33: static void import_tag(struct cvs_file *, RCSNUM *, RCSNUM *);
1.62 joris 34: static BUF *import_get_rcsdiff(struct cvs_file *, RCSNUM *);
1.3 jfb 35:
1.45 joris 36: #define IMPORT_DEFAULT_BRANCH "1.1.1"
1.19 jfb 37:
1.45 joris 38: static char *import_branch = IMPORT_DEFAULT_BRANCH;
39: static char *logmsg = NULL;
40: static char *vendor_tag = NULL;
41: static char *release_tag = NULL;
1.68 xsa 42: static char *koptstr;
1.51 xsa 43: static int dflag = 0;
44:
1.45 joris 45: char *import_repository = NULL;
1.47 joris 46: int import_conflicts = 0;
1.3 jfb 47:
1.15 jfb 48: struct cvs_cmd cvs_cmd_import = {
1.80 tobias 49: CVS_OP_IMPORT, CVS_USE_WDIR, "import",
1.15 jfb 50: { "im", "imp" },
51: "Import sources into CVS, using vendor branches",
1.68 xsa 52: "[-b branch] [-d] [-k mode] [-m message] "
53: "repository vendor-tag release-tags",
54: "b:dk:m:",
1.15 jfb 55: NULL,
1.45 joris 56: cvs_import
1.7 joris 57: };
1.1 krapht 58:
1.45 joris 59: int
60: cvs_import(int argc, char **argv)
1.1 krapht 61: {
1.56 xsa 62: int ch;
1.45 joris 63: char repo[MAXPATHLEN], *arg = ".";
64: struct cvs_recursion cr;
1.1 krapht 65:
1.45 joris 66: while ((ch = getopt(argc, argv, cvs_cmd_import.cmd_opts)) != -1) {
1.1 krapht 67: switch (ch) {
68: case 'b':
1.45 joris 69: import_branch = optarg;
1.1 krapht 70: break;
1.51 xsa 71: case 'd':
72: dflag = 1;
73: break;
1.68 xsa 74: case 'k':
75: koptstr = optarg;
76: kflag = rcs_kflag_get(koptstr);
77: if (RCS_KWEXP_INVAL(kflag)) {
78: cvs_log(LP_ERR,
79: "invalid RCS keyword expension mode");
80: fatal("%s", cvs_cmd_import.cmd_synopsis);
81: }
82: break;
1.1 krapht 83: case 'm':
1.45 joris 84: logmsg = optarg;
1.1 krapht 85: break;
86: default:
1.45 joris 87: fatal("%s", cvs_cmd_import.cmd_synopsis);
88: break;
1.1 krapht 89: }
90: }
91:
92: argc -= optind;
93: argv += optind;
1.19 jfb 94:
1.45 joris 95: if (argc < 3)
96: fatal("%s", cvs_cmd_import.cmd_synopsis);
1.1 krapht 97:
1.45 joris 98: if (logmsg == NULL)
1.57 joris 99: logmsg = cvs_logmsg_create(NULL, NULL, NULL);
100:
101: if (logmsg == NULL)
102: fatal("This shouldnt happen, honestly!");
1.15 jfb 103:
1.45 joris 104: import_repository = argv[0];
105: vendor_tag = argv[1];
106: release_tag = argv[2];
107:
1.64 joris 108: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
109: cvs_client_connect_to_server();
110:
111: cvs_client_send_request("Argument -b%s", IMPORT_DEFAULT_BRANCH);
1.68 xsa 112:
1.82 ! tobias 113: if (kflag)
1.68 xsa 114: cvs_client_send_request("Argument -k%s", koptstr);
115:
1.75 joris 116: cvs_client_send_logmsg(logmsg);
1.64 joris 117: cvs_client_send_request("Argument %s", import_repository);
118: cvs_client_send_request("Argument %s", vendor_tag);
119: cvs_client_send_request("Argument %s", release_tag);
120:
121: cr.enterdir = NULL;
122: cr.leavedir = NULL;
123: cr.fileproc = cvs_client_sendfile;
124: cr.flags = CR_RECURSE_DIRS;
125:
126: cvs_file_run(1, &arg, &cr);
127: cvs_client_senddir(".");
128: cvs_client_send_request("import");
129:
130: cvs_client_get_responses();
131: return (0);
132: }
133:
1.70 xsa 134: (void)xsnprintf(repo, sizeof(repo), "%s/%s",
135: current_cvsroot->cr_dir, import_repository);
1.45 joris 136:
1.48 joris 137: if (cvs_noexec != 1) {
138: if (mkdir(repo, 0755) == -1 && errno != EEXIST)
139: fatal("cvs_import: %s: %s", repo, strerror(errno));
140: }
1.45 joris 141:
142: cr.enterdir = NULL;
143: cr.leavedir = NULL;
1.53 joris 144: cr.fileproc = cvs_import_local;
1.45 joris 145: cr.flags = CR_RECURSE_DIRS;
146: cvs_file_run(1, &arg, &cr);
1.1 krapht 147:
1.47 joris 148: if (import_conflicts != 0) {
149: cvs_printf("\n%d conflicts created by this import.\n\n",
150: import_conflicts);
151: cvs_printf("Use the following command to help the merge:\n");
152: cvs_printf("\topencvs checkout ");
153: cvs_printf("-j%s:yesterday -j%s %s\n\n", vendor_tag,
154: vendor_tag, import_repository);
155: } else {
156: cvs_printf("\nNo conflicts created by this import.\n\n");
157: }
158:
1.7 joris 159: return (0);
160: }
1.1 krapht 161:
1.45 joris 162: void
163: cvs_import_local(struct cvs_file *cf)
1.7 joris 164: {
1.45 joris 165: int isnew;
166: struct stat st;
167: char repo[MAXPATHLEN];
1.15 jfb 168:
1.45 joris 169: cvs_log(LP_TRACE, "cvs_import_local(%s)", cf->file_path);
1.1 krapht 170:
1.77 joris 171: cvs_file_classify(cf, cvs_directory_tag);
1.1 krapht 172:
1.45 joris 173: if (cf->file_type == CVS_DIR) {
174: if (!strcmp(cf->file_path, "."))
175: return;
1.19 jfb 176:
1.45 joris 177: if (verbosity > 1)
178: cvs_log(LP_NOTICE, "Importing %s", cf->file_path);
1.19 jfb 179:
1.48 joris 180: if (cvs_noexec == 1)
181: return;
1.19 jfb 182:
1.45 joris 183: if (mkdir(cf->file_rpath, 0755) == -1 && errno != EEXIST)
184: fatal("cvs_import_local: %s: %s", cf->file_rpath,
185: strerror(errno));
1.15 jfb 186:
1.45 joris 187: return;
1.15 jfb 188: }
189:
1.45 joris 190: isnew = 1;
1.67 xsa 191: (void)xsnprintf(repo, sizeof(repo), "%s/%s/%s/%s%s",
1.45 joris 192: current_cvsroot->cr_dir, cf->file_wd, CVS_PATH_ATTIC,
193: cf->file_name, RCS_FILE_EXT);
1.34 joris 194:
1.45 joris 195: if (cf->file_rcs != NULL || stat(repo, &st) != -1)
196: isnew = 0;
1.15 jfb 197:
1.45 joris 198: if (isnew == 1)
199: import_new(cf);
200: else
201: import_update(cf);
1.15 jfb 202: }
203:
1.45 joris 204: static void
205: import_new(struct cvs_file *cf)
1.15 jfb 206: {
1.45 joris 207: BUF *bp;
1.51 xsa 208: time_t tstamp;
209: struct stat st;
1.45 joris 210: struct rcs_branch *brp;
1.41 joris 211: struct rcs_delta *rdp;
1.45 joris 212: RCSNUM *branch, *brev;
213:
1.51 xsa 214: tstamp = -1;
215:
1.45 joris 216: cvs_log(LP_TRACE, "import_new(%s)", cf->file_name);
217:
1.48 joris 218: if (cvs_noexec == 1) {
219: cvs_printf("N %s/%s\n", import_repository, cf->file_path);
220: return;
221: }
222:
1.51 xsa 223: if (dflag == 1) {
224: if (fstat(cf->fd, &st) == -1)
225: fatal("import_new: %s", strerror(errno));
226:
227: tstamp = st.st_mtime;
228: }
229:
1.45 joris 230: if ((branch = rcsnum_parse(import_branch)) == NULL)
231: fatal("import_new: failed to parse branch");
232:
1.50 joris 233: if ((bp = cvs_buf_load_fd(cf->fd, BUF_AUTOEXT)) == NULL)
1.45 joris 234: fatal("import_new: failed to load %s", cf->file_path);
235:
236: if ((brev = rcsnum_brtorev(branch)) == NULL)
237: fatal("import_new: failed to get first branch revision");
1.24 xsa 238:
1.45 joris 239: cf->repo_fd = open(cf->file_rpath, O_CREAT|O_TRUNC|O_WRONLY);
240: if (cf->repo_fd < 0)
241: fatal("import_new: %s: %s", cf->file_rpath, strerror(errno));
1.1 krapht 242:
1.45 joris 243: cf->file_rcs = rcs_open(cf->file_rpath, cf->repo_fd, RCS_CREATE, 0444);
244: if (cf->file_rcs == NULL)
245: fatal("import_new: failed to create RCS file for %s",
246: cf->file_path);
1.1 krapht 247:
1.45 joris 248: rcs_branch_set(cf->file_rcs, branch);
1.18 jfb 249:
1.45 joris 250: if (rcs_sym_add(cf->file_rcs, vendor_tag, branch) == -1)
251: fatal("import_new: failed to add release tag");
1.18 jfb 252:
1.47 joris 253: if (rcs_sym_add(cf->file_rcs, release_tag, brev) == -1)
1.45 joris 254: fatal("import_new: failed to add vendor tag");
1.17 jfb 255:
1.51 xsa 256: if (rcs_rev_add(cf->file_rcs, brev, logmsg, tstamp, NULL) == -1)
1.45 joris 257: fatal("import_new: failed to create first branch revision");
1.1 krapht 258:
1.76 tobias 259: if (rcs_rev_add(cf->file_rcs, RCS_HEAD_REV, "Initial revision",
260: tstamp, NULL) == -1)
1.45 joris 261: fatal("import_new: failed to create first revision");
1.20 jfb 262:
1.45 joris 263: if ((rdp = rcs_findrev(cf->file_rcs, cf->file_rcs->rf_head)) == NULL)
264: fatal("import_new: cannot find newly added revision");
1.41 joris 265:
1.42 ray 266: brp = xmalloc(sizeof(*brp));
1.41 joris 267: brp->rb_num = rcsnum_alloc();
268: rcsnum_cpy(brev, brp->rb_num, 0);
269: TAILQ_INSERT_TAIL(&(rdp->rd_branches), brp, rb_list);
1.30 joris 270:
1.45 joris 271: if (rcs_deltatext_set(cf->file_rcs,
1.60 joris 272: cf->file_rcs->rf_head, bp) == -1)
1.45 joris 273: fatal("import_new: failed to set deltatext");
1.30 joris 274:
1.82 ! tobias 275: if (kflag)
1.68 xsa 276: rcs_kwexp_set(cf->file_rcs, kflag);
277:
1.45 joris 278: rcs_write(cf->file_rcs);
1.47 joris 279: cvs_printf("N %s/%s\n", import_repository, cf->file_path);
1.30 joris 280:
1.45 joris 281: rcsnum_free(branch);
282: rcsnum_free(brev);
1.19 jfb 283: }
284:
1.45 joris 285: static void
286: import_update(struct cvs_file *cf)
1.19 jfb 287: {
1.64 joris 288: int ret;
1.62 joris 289: BUF *b1, *b2, *d;
1.74 xsa 290: char branch[CVS_REV_BUFSZ];
1.81 joris 291: RCSNUM *newrev, *rev, *brev;
1.47 joris 292:
1.45 joris 293: cvs_log(LP_TRACE, "import_update(%s)", cf->file_path);
1.47 joris 294:
1.66 niallo 295: if ((rev = rcs_translate_tag(import_branch, cf->file_rcs)) == NULL)
296: fatal("import_update: could not translate tag `%s'", import_branch);
1.47 joris 297:
298: if ((brev = rcsnum_parse(import_branch)) == NULL)
299: fatal("import_update: rcsnum_parse failed");
300:
1.81 joris 301: if ((b1 = rcs_rev_getbuf(cf->file_rcs, rev, RCS_KWEXP_NONE)) == NULL)
302: fatal("import_update: failed to grab revision");
303:
304: if ((b2 = cvs_buf_load_fd(cf->fd, BUF_AUTOEXT)) == NULL)
305: fatal("import_update: failed to load %s", cf->file_path);
306:
307: ret = cvs_buf_differ(b1, b2);
308: cvs_buf_free(b1);
309: cvs_buf_free(b2);
310: if (ret == 0) {
311: import_tag(cf, brev, rev);
312: rcsnum_free(brev);
313: rcs_write(cf->file_rcs);
314: return;
1.47 joris 315: }
316:
317: if (cf->file_rcs->rf_branch != NULL)
318: rcsnum_tostr(cf->file_rcs->rf_branch, branch, sizeof(branch));
319:
1.81 joris 320: d = import_get_rcsdiff(cf, rev);
321: newrev = rcsnum_inc(rev);
1.47 joris 322:
323: if (rcs_rev_add(cf->file_rcs, newrev, logmsg, -1, NULL) == -1)
324: fatal("import_update: failed to add new revision");
325:
326: if (rcs_deltatext_set(cf->file_rcs, newrev, d) == -1)
327: fatal("import_update: failed to set deltatext");
1.48 joris 328:
1.47 joris 329: import_tag(cf, brev, newrev);
330:
1.73 niallo 331: if (cf->file_rcs->rf_branch == NULL || cf->in_attic == 1 ||
1.47 joris 332: strcmp(branch, import_branch)) {
333: import_conflicts++;
334: cvs_printf("C %s/%s\n", import_repository, cf->file_path);
335: } else {
336: cvs_printf("U %s/%s\n", import_repository, cf->file_path);
337: }
1.68 xsa 338:
1.82 ! tobias 339: if (kflag)
1.68 xsa 340: rcs_kwexp_set(cf->file_rcs, kflag);
1.47 joris 341:
342: rcsnum_free(brev);
343: rcs_write(cf->file_rcs);
344: }
345:
346: static void
347: import_tag(struct cvs_file *cf, RCSNUM *branch, RCSNUM *newrev)
348: {
1.74 xsa 349: char b[CVS_REV_BUFSZ];
1.47 joris 350:
1.48 joris 351: if (cvs_noexec != 1) {
352: rcsnum_tostr(branch, b, sizeof(b));
353: rcs_sym_add(cf->file_rcs, vendor_tag, branch);
1.47 joris 354:
1.48 joris 355: rcsnum_tostr(newrev, b, sizeof(b));
356: rcs_sym_add(cf->file_rcs, release_tag, newrev);
357: }
1.47 joris 358: }
359:
1.62 joris 360: static BUF *
1.47 joris 361: import_get_rcsdiff(struct cvs_file *cf, RCSNUM *rev)
362: {
1.62 joris 363: char *p1, *p2;
1.61 niallo 364: BUF *b1, *b2;
1.47 joris 365:
1.61 niallo 366: b2 = cvs_buf_alloc(128, BUF_AUTOEXT);
1.47 joris 367:
1.48 joris 368: if (cvs_noexec != 1) {
1.64 joris 369: if ((b1 = cvs_buf_load_fd(cf->fd, BUF_AUTOEXT)) == NULL)
370: fatal("import_get_rcsdiff: failed loading %s",
371: cf->file_path);
372:
1.48 joris 373: (void)xasprintf(&p1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir);
1.54 ray 374: cvs_buf_write_stmp(b1, p1, NULL);
1.48 joris 375: cvs_buf_free(b1);
376:
377: (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir);
1.79 tobias 378: rcs_rev_write_stmp(cf->file_rcs, rev, p2, RCS_KWEXP_NONE);
1.48 joris 379:
380: diff_format = D_RCSDIFF;
1.61 niallo 381: if (cvs_diffreg(p2, p1, b2) == D_ERROR)
1.48 joris 382: fatal("import_get_rcsdiff: failed to get RCS patch");
1.59 xsa 383:
384: (void)unlink(p1);
385: (void)unlink(p2);
1.55 xsa 386:
1.64 joris 387: xfree(p1);
388: xfree(p2);
1.48 joris 389: }
1.55 xsa 390:
1.62 joris 391: return (b2);
1.1 krapht 392: }