Annotation of src/usr.bin/cvs/update.c, Revision 1.173
1.173 ! fcambus 1: /* $OpenBSD: update.c,v 1.172 2016/10/13 20:51:25 fcambus Exp $ */
1.1 jfb 2: /*
1.59 joris 3: * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
1.1 jfb 4: *
1.59 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 jfb 8: *
1.59 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 jfb 16: */
17:
1.97 otto 18: #include <sys/stat.h>
19:
1.168 zhuk 20: #include <dirent.h>
1.97 otto 21: #include <errno.h>
22: #include <fcntl.h>
1.170 millert 23: #include <stdint.h>
1.171 nicm 24: #include <stdlib.h>
1.97 otto 25: #include <string.h>
26: #include <unistd.h>
1.1 jfb 27:
28: #include "cvs.h"
1.59 joris 29: #include "diff.h"
1.80 joris 30: #include "remote.h"
1.1 jfb 31:
1.60 joris 32: int prune_dirs = 0;
1.108 joris 33: int print_stdout = 0;
1.63 joris 34: int build_dirs = 0;
1.124 tobias 35: int reset_option = 0;
36: int reset_tag = 0;
1.164 nicm 37: int backup_local_changes = 0;
1.104 joris 38: char *cvs_specified_tag = NULL;
1.136 joris 39: char *cvs_join_rev1 = NULL;
40: char *cvs_join_rev2 = NULL;
1.63 joris 41:
1.119 tobias 42: static char *koptstr;
1.125 joris 43: static char *dateflag = NULL;
1.124 tobias 44: static int Aflag = 0;
1.119 tobias 45:
1.65 joris 46: static void update_clear_conflict(struct cvs_file *);
1.136 joris 47: static void update_join_file(struct cvs_file *);
1.65 joris 48:
1.152 joris 49: extern CVSENTRIES *current_list;
50:
1.29 jfb 51: struct cvs_cmd cvs_cmd_update = {
1.116 tobias 52: CVS_OP_UPDATE, CVS_USE_WDIR, "update",
1.29 jfb 53: { "up", "upd" },
54: "Bring work tree in sync with repository",
55: "[-ACdflPpR] [-D date | -r rev] [-I ign] [-j rev] [-k mode] "
56: "[-t id] ...",
1.106 joris 57: "ACD:dfI:j:k:lPpQqRr:t:u",
1.29 jfb 58: NULL,
1.59 joris 59: cvs_update
1.18 joris 60: };
1.2 jfb 61:
1.59 joris 62: int
63: cvs_update(int argc, char **argv)
1.1 jfb 64: {
1.18 joris 65: int ch;
1.59 joris 66: char *arg = ".";
1.61 joris 67: int flags;
1.59 joris 68: struct cvs_recursion cr;
1.2 jfb 69:
1.80 joris 70: flags = CR_RECURSE_DIRS;
1.61 joris 71:
1.59 joris 72: while ((ch = getopt(argc, argv, cvs_cmd_update.cmd_opts)) != -1) {
1.1 jfb 73: switch (ch) {
74: case 'A':
1.124 tobias 75: Aflag = 1;
76: if (koptstr == NULL)
77: reset_option = 1;
78: if (cvs_specified_tag == NULL)
79: reset_tag = 1;
1.24 joris 80: break;
1.1 jfb 81: case 'C':
1.164 nicm 82: backup_local_changes = 1;
1.126 joris 83: break;
1.1 jfb 84: case 'D':
1.125 joris 85: dateflag = optarg;
1.163 ray 86: if ((cvs_specified_date = date_parse(dateflag)) == -1)
87: fatal("invalid date: %s", dateflag);
1.153 tobias 88: reset_tag = 0;
1.32 xsa 89: break;
1.1 jfb 90: case 'd':
1.63 joris 91: build_dirs = 1;
1.24 joris 92: break;
1.1 jfb 93: case 'f':
1.2 jfb 94: break;
1.35 xsa 95: case 'I':
96: break;
97: case 'j':
1.136 joris 98: if (cvs_join_rev1 == NULL)
99: cvs_join_rev1 = optarg;
100: else if (cvs_join_rev2 == NULL)
101: cvs_join_rev2 = optarg;
102: else
103: fatal("too many -j options");
1.35 xsa 104: break;
105: case 'k':
1.124 tobias 106: reset_option = 0;
1.119 tobias 107: koptstr = optarg;
108: kflag = rcs_kflag_get(koptstr);
109: if (RCS_KWEXP_INVAL(kflag)) {
110: cvs_log(LP_ERR,
1.143 tobias 111: "invalid RCS keyword expansion mode");
1.135 tobias 112: fatal("%s", cvs_cmd_update.cmd_synopsis);
1.119 tobias 113: }
1.35 xsa 114: break;
1.1 jfb 115: case 'l':
1.61 joris 116: flags &= ~CR_RECURSE_DIRS;
1.2 jfb 117: break;
1.1 jfb 118: case 'P':
1.60 joris 119: prune_dirs = 1;
1.24 joris 120: break;
1.1 jfb 121: case 'p':
1.108 joris 122: print_stdout = 1;
1.79 xsa 123: cvs_noexec = 1;
1.27 xsa 124: break;
1.1 jfb 125: case 'Q':
126: case 'q':
1.2 jfb 127: break;
1.1 jfb 128: case 'R':
1.115 tobias 129: flags |= CR_RECURSE_DIRS;
1.2 jfb 130: break;
1.1 jfb 131: case 'r':
1.124 tobias 132: reset_tag = 0;
1.104 joris 133: cvs_specified_tag = optarg;
1.106 joris 134: break;
135: case 'u':
1.1 jfb 136: break;
137: default:
1.59 joris 138: fatal("%s", cvs_cmd_update.cmd_synopsis);
1.1 jfb 139: }
1.32 xsa 140: }
141:
1.59 joris 142: argc -= optind;
143: argv += optind;
1.2 jfb 144:
1.80 joris 145: if (current_cvsroot->cr_method == CVS_METHOD_LOCAL) {
146: cr.enterdir = cvs_update_enterdir;
1.118 tobias 147: cr.leavedir = prune_dirs ? cvs_update_leavedir : NULL;
1.80 joris 148: cr.fileproc = cvs_update_local;
149: flags |= CR_REPO;
150: } else {
1.82 joris 151: cvs_client_connect_to_server();
1.124 tobias 152: if (Aflag)
1.80 joris 153: cvs_client_send_request("Argument -A");
1.125 joris 154: if (dateflag != NULL)
155: cvs_client_send_request("Argument -D%s", dateflag);
1.80 joris 156: if (build_dirs)
157: cvs_client_send_request("Argument -d");
1.119 tobias 158: if (kflag)
159: cvs_client_send_request("Argument -k%s", koptstr);
1.80 joris 160: if (!(flags & CR_RECURSE_DIRS))
161: cvs_client_send_request("Argument -l");
162: if (prune_dirs)
163: cvs_client_send_request("Argument -P");
1.108 joris 164: if (print_stdout)
1.80 joris 165: cvs_client_send_request("Argument -p");
166:
1.110 joris 167: if (cvs_specified_tag != NULL)
168: cvs_client_send_request("Argument -r%s",
169: cvs_specified_tag);
170:
1.80 joris 171: cr.enterdir = NULL;
172: cr.leavedir = NULL;
173: cr.fileproc = cvs_client_sendfile;
174: }
175:
1.61 joris 176: cr.flags = flags;
1.49 joris 177:
1.59 joris 178: if (argc > 0)
179: cvs_file_run(argc, argv, &cr);
180: else
181: cvs_file_run(1, &arg, &cr);
1.80 joris 182:
183: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
184: cvs_client_send_files(argv, argc);
185: cvs_client_senddir(".");
186: cvs_client_send_request("update");
187: cvs_client_get_responses();
188: }
1.35 xsa 189:
1.24 joris 190: return (0);
191: }
1.2 jfb 192:
1.59 joris 193: void
194: cvs_update_enterdir(struct cvs_file *cf)
1.2 jfb 195: {
1.59 joris 196: CVSENTRIES *entlist;
1.169 deraadt 197: char *dirtag, *entry, fpath[PATH_MAX];
1.59 joris 198:
199: cvs_log(LP_TRACE, "cvs_update_enterdir(%s)", cf->file_path);
200:
1.145 tobias 201: cvs_file_classify(cf, NULL);
1.59 joris 202:
1.63 joris 203: if (cf->file_status == DIR_CREATE && build_dirs == 1) {
1.145 tobias 204: cvs_parse_tagfile(cf->file_wd, &dirtag, NULL, NULL);
205: cvs_mkpath(cf->file_path, cvs_specified_tag != NULL ?
206: cvs_specified_tag : dirtag);
1.171 nicm 207: free(dirtag);
1.145 tobias 208:
1.59 joris 209: if ((cf->fd = open(cf->file_path, O_RDONLY)) == -1)
1.87 xsa 210: fatal("cvs_update_enterdir: `%s': %s",
211: cf->file_path, strerror(errno));
1.140 joris 212:
213: if (cvs_server_active == 1 && cvs_cmdop != CVS_OP_CHECKOUT)
214: cvs_server_clear_sticky(cf->file_path);
1.59 joris 215:
1.114 tobias 216: if (cvs_cmdop != CVS_OP_EXPORT) {
217: (void)xasprintf(&entry, "D/%s////", cf->file_name);
1.59 joris 218:
1.114 tobias 219: entlist = cvs_ent_open(cf->file_wd);
220: cvs_ent_add(entlist, entry);
1.171 nicm 221: free(entry);
1.114 tobias 222: }
1.94 xsa 223: } else if ((cf->file_status == DIR_CREATE && build_dirs == 0) ||
224: cf->file_status == FILE_UNKNOWN) {
1.67 joris 225: cf->file_status = FILE_SKIP;
1.124 tobias 226: } else if (reset_tag) {
1.169 deraadt 227: (void)xsnprintf(fpath, PATH_MAX, "%s/%s",
1.104 joris 228: cf->file_path, CVS_PATH_TAG);
229: (void)unlink(fpath);
230: } else {
1.131 joris 231: if (cvs_specified_tag != NULL || cvs_specified_date != -1)
1.104 joris 232: cvs_write_tagfile(cf->file_path,
1.120 tobias 233: cvs_specified_tag, NULL);
1.60 joris 234: }
235: }
236:
237: void
238: cvs_update_leavedir(struct cvs_file *cf)
239: {
240: int nbytes;
1.81 xsa 241: int isempty;
1.60 joris 242: size_t bufsize;
243: struct stat st;
244: struct dirent *dp;
245: char *buf, *ebuf, *cp;
246: CVSENTRIES *entlist;
247:
1.67 joris 248: cvs_log(LP_TRACE, "cvs_update_leavedir(%s)", cf->file_path);
1.86 joris 249:
1.105 joris 250: if (cvs_server_active == 1 && !strcmp(cf->file_name, "."))
251: return;
1.69 joris 252:
1.158 joris 253: entlist = cvs_ent_open(cf->file_path);
254: if (!TAILQ_EMPTY(&(entlist->cef_ent))) {
255: isempty = 0;
256: goto prune_it;
257: }
258:
1.60 joris 259: if (fstat(cf->fd, &st) == -1)
260: fatal("cvs_update_leavedir: %s", strerror(errno));
261:
262: bufsize = st.st_size;
263: if (bufsize < st.st_blksize)
264: bufsize = st.st_blksize;
1.139 tobias 265:
266: if (st.st_size > SIZE_MAX)
1.151 joris 267: fatal("cvs_update_leavedir: %s: file size too big",
268: cf->file_name);
1.60 joris 269:
270: isempty = 1;
271: buf = xmalloc(bufsize);
272:
1.73 joris 273: if (lseek(cf->fd, 0, SEEK_SET) == -1)
1.60 joris 274: fatal("cvs_update_leavedir: %s", strerror(errno));
275:
1.168 zhuk 276: while ((nbytes = getdents(cf->fd, buf, bufsize)) > 0) {
1.60 joris 277: ebuf = buf + nbytes;
278: cp = buf;
279:
280: while (cp < ebuf) {
281: dp = (struct dirent *)cp;
282: if (!strcmp(dp->d_name, ".") ||
283: !strcmp(dp->d_name, "..") ||
1.95 joris 284: dp->d_fileno == 0) {
1.60 joris 285: cp += dp->d_reclen;
286: continue;
287: }
288:
1.158 joris 289: if (strcmp(dp->d_name, CVS_PATH_CVSDIR))
1.60 joris 290: isempty = 0;
291:
292: if (isempty == 0)
293: break;
294:
295: cp += dp->d_reclen;
296: }
297: }
298:
299: if (nbytes == -1)
300: fatal("cvs_update_leavedir: %s", strerror(errno));
301:
1.171 nicm 302: free(buf);
1.60 joris 303:
1.158 joris 304: prune_it:
1.151 joris 305: if ((isempty == 1 && prune_dirs == 1) ||
306: (cvs_server_active == 1 && cvs_cmdop == CVS_OP_CHECKOUT)) {
1.69 joris 307: /* XXX */
1.60 joris 308: cvs_rmdir(cf->file_path);
309:
1.114 tobias 310: if (cvs_server_active == 0 && cvs_cmdop != CVS_OP_EXPORT) {
1.88 joris 311: entlist = cvs_ent_open(cf->file_wd);
312: cvs_ent_remove(entlist, cf->file_name);
313: }
1.2 jfb 314: }
315: }
316:
1.59 joris 317: void
318: cvs_update_local(struct cvs_file *cf)
1.2 jfb 319: {
1.136 joris 320: CVSENTRIES *entlist;
1.133 tobias 321: int ent_kflag, rcs_kflag, ret, flags;
1.136 joris 322: char *tag, rbuf[CVS_REV_BUFSZ];
1.59 joris 323:
324: cvs_log(LP_TRACE, "cvs_update_local(%s)", cf->file_path);
1.37 joris 325:
1.59 joris 326: if (cf->file_type == CVS_DIR) {
1.114 tobias 327: if (cf->file_status == FILE_SKIP) {
328: if (cvs_cmdop == CVS_OP_EXPORT && verbosity > 0)
329: cvs_printf("? %s\n", cf->file_path);
1.63 joris 330: return;
1.114 tobias 331: }
1.63 joris 332:
1.59 joris 333: if (cf->file_status != FILE_UNKNOWN &&
334: verbosity > 1)
1.159 joris 335: cvs_log(LP_ERR, "Updating %s", cf->file_path);
1.59 joris 336: return;
1.26 jfb 337: }
338:
1.70 joris 339: flags = 0;
1.112 joris 340: if (cvs_specified_tag != NULL)
341: tag = cvs_specified_tag;
1.122 joris 342: else if (cf->file_ent != NULL && cf->file_ent->ce_tag != NULL)
343: tag = cf->file_ent->ce_tag;
1.112 joris 344: else
345: tag = cvs_directory_tag;
346:
347: cvs_file_classify(cf, tag);
348:
1.146 tobias 349: if (kflag && cf->file_rcs != NULL)
1.119 tobias 350: rcs_kwexp_set(cf->file_rcs, kflag);
1.70 joris 351:
1.91 joris 352: if ((cf->file_status == FILE_UPTODATE ||
353: cf->file_status == FILE_MODIFIED) && cf->file_ent != NULL &&
1.124 tobias 354: cf->file_ent->ce_tag != NULL && reset_tag) {
1.91 joris 355: if (cf->file_status == FILE_MODIFIED)
356: cf->file_status = FILE_MERGE;
357: else
358: cf->file_status = FILE_CHECKOUT;
1.110 joris 359:
1.154 tobias 360: if ((cf->file_rcsrev = rcs_head_get(cf->file_rcs)) == NULL)
361: fatal("no head revision in RCS file for %s",
362: cf->file_path);
1.104 joris 363:
364: /* might be a bit overkill */
365: if (cvs_server_active == 1)
366: cvs_server_clear_sticky(cf->file_wd);
1.76 reyk 367: }
368:
1.154 tobias 369: if (print_stdout) {
370: if (cf->file_status != FILE_UNKNOWN && cf->file_rcs != NULL &&
1.155 tobias 371: cf->file_rcsrev != NULL && !cf->file_rcs->rf_dead &&
372: (cf->file_flags & FILE_HAS_TAG)) {
1.154 tobias 373: rcsnum_tostr(cf->file_rcsrev, rbuf, sizeof(rbuf));
374: if (verbosity > 1) {
375: cvs_log(LP_RCS, RCS_DIFF_DIV);
376: cvs_log(LP_RCS, "Checking out %s",
377: cf->file_path);
378: cvs_log(LP_RCS, "RCS: %s", cf->file_rpath);
379: cvs_log(LP_RCS, "VERS: %s", rbuf);
380: cvs_log(LP_RCS, "***************");
381: }
382: cvs_checkout_file(cf, cf->file_rcsrev, tag, CO_DUMP);
1.109 tobias 383: }
1.76 reyk 384: return;
1.70 joris 385: }
1.45 joris 386:
1.119 tobias 387: if (cf->file_ent != NULL) {
388: if (cf->file_ent->ce_opts == NULL) {
389: if (kflag)
390: cf->file_status = FILE_CHECKOUT;
1.154 tobias 391: } else if (cf->file_rcs != NULL) {
1.133 tobias 392: if (strlen(cf->file_ent->ce_opts) < 3)
393: fatal("malformed option for file %s",
394: cf->file_path);
395:
396: ent_kflag = rcs_kflag_get(cf->file_ent->ce_opts + 2);
397: rcs_kflag = rcs_kwexp_get(cf->file_rcs);
398:
399: if ((kflag && (kflag != ent_kflag)) ||
400: (reset_option && (ent_kflag != rcs_kflag)))
1.119 tobias 401: cf->file_status = FILE_CHECKOUT;
402: }
403: }
404:
1.59 joris 405: switch (cf->file_status) {
406: case FILE_UNKNOWN:
407: cvs_printf("? %s\n", cf->file_path);
1.45 joris 408: break;
1.59 joris 409: case FILE_MODIFIED:
1.164 nicm 410: if (backup_local_changes) {
411: cvs_backup_file(cf);
412:
413: cvs_checkout_file(cf, cf->file_rcsrev, NULL, flags);
414: cvs_printf("U %s\n", cf->file_path);
1.65 joris 415: } else {
1.164 nicm 416: ret = update_has_conflict_markers(cf);
417: if (cf->file_ent->ce_conflict != NULL && ret == 1)
418: cvs_printf("C %s\n", cf->file_path);
419: else {
420: if (cf->file_ent->ce_conflict != NULL && ret == 0)
421: update_clear_conflict(cf);
422: cvs_printf("M %s\n", cf->file_path);
423: }
1.65 joris 424: }
1.45 joris 425: break;
1.59 joris 426: case FILE_ADDED:
427: cvs_printf("A %s\n", cf->file_path);
1.45 joris 428: break;
1.59 joris 429: case FILE_REMOVED:
430: cvs_printf("R %s\n", cf->file_path);
1.45 joris 431: break;
1.59 joris 432: case FILE_CONFLICT:
433: cvs_printf("C %s\n", cf->file_path);
434: break;
435: case FILE_LOST:
436: case FILE_CHECKOUT:
437: case FILE_PATCH:
1.153 tobias 438: if (!reset_tag && (tag != NULL || cvs_specified_date != -1 ||
439: cvs_directory_date != -1 || (cf->file_ent != NULL &&
440: cf->file_ent->ce_tag != NULL)))
1.70 joris 441: flags = CO_SETSTICKY;
442:
1.161 nicm 443: if (cf->file_flags & FILE_ON_DISK && (cf->file_ent == NULL ||
444: cf->file_ent->ce_type == CVS_ENT_NONE)) {
445: cvs_log(LP_ERR, "move away %s; it is in the way",
446: cf->file_path);
447: cvs_printf("C %s\n", cf->file_path);
448: } else {
449: cvs_checkout_file(cf, cf->file_rcsrev, tag, flags);
450: cvs_printf("U %s\n", cf->file_path);
451: cvs_history_add(CVS_HISTORY_UPDATE_CO, cf, NULL);
452: }
1.59 joris 453: break;
454: case FILE_MERGE:
1.136 joris 455: d3rev1 = cf->file_ent->ce_rev;
456: d3rev2 = cf->file_rcsrev;
1.112 joris 457: cvs_checkout_file(cf, cf->file_rcsrev, tag, CO_MERGE);
1.65 joris 458:
459: if (diff3_conflicts != 0) {
460: cvs_printf("C %s\n", cf->file_path);
1.100 joris 461: cvs_history_add(CVS_HISTORY_UPDATE_MERGED_ERR,
462: cf, NULL);
1.65 joris 463: } else {
464: update_clear_conflict(cf);
465: cvs_printf("M %s\n", cf->file_path);
1.100 joris 466: cvs_history_add(CVS_HISTORY_UPDATE_MERGED, cf, NULL);
1.65 joris 467: }
1.59 joris 468: break;
469: case FILE_UNLINK:
470: (void)unlink(cf->file_path);
471: case FILE_REMOVE_ENTRY:
472: entlist = cvs_ent_open(cf->file_wd);
473: cvs_ent_remove(entlist, cf->file_name);
1.100 joris 474: cvs_history_add(CVS_HISTORY_UPDATE_REMOVE, cf, NULL);
1.160 joris 475:
476: if (cvs_server_active == 1)
477: cvs_checkout_file(cf, cf->file_rcsrev, tag, CO_REMOVE);
1.110 joris 478: break;
479: case FILE_UPTODATE:
480: if (cvs_cmdop != CVS_OP_UPDATE)
481: break;
482:
1.173 ! fcambus 483: if (reset_tag != 1 && reset_option != 1 &&
! 484: cvs_specified_tag == NULL && cvs_specified_date == -1)
1.130 joris 485: break;
486:
487: if (cf->file_rcs->rf_dead != 1 &&
488: (cf->file_flags & FILE_HAS_TAG))
1.112 joris 489: cvs_checkout_file(cf, cf->file_rcsrev,
490: tag, CO_SETSTICKY);
1.45 joris 491: break;
492: default:
493: break;
494: }
1.136 joris 495:
496: if (cvs_join_rev1 != NULL)
497: update_join_file(cf);
1.65 joris 498: }
499:
500: static void
501: update_clear_conflict(struct cvs_file *cf)
502: {
503: CVSENTRIES *entlist;
1.148 tobias 504: char *entry, revbuf[CVS_REV_BUFSZ];
1.136 joris 505: char sticky[CVS_ENT_MAXLINELEN], opt[4];
1.65 joris 506:
507: cvs_log(LP_TRACE, "update_clear_conflict(%s)", cf->file_path);
508:
1.134 joris 509: rcsnum_tostr(cf->file_rcsrev, revbuf, sizeof(revbuf));
1.65 joris 510:
1.121 tobias 511: sticky[0] = '\0';
1.136 joris 512: if (cf->file_ent != NULL && cf->file_ent->ce_tag != NULL)
1.121 tobias 513: (void)xsnprintf(sticky, sizeof(sticky), "T%s",
514: cf->file_ent->ce_tag);
515:
1.136 joris 516: opt[0] = '\0';
517: if (cf->file_ent != NULL && cf->file_ent->ce_opts != NULL)
518: strlcpy(opt, cf->file_ent->ce_opts, sizeof(opt));
519:
1.65 joris 520: entry = xmalloc(CVS_ENT_MAXLINELEN);
1.148 tobias 521: cvs_ent_line_str(cf->file_name, revbuf, "Result of merge",
1.136 joris 522: opt[0] != '\0' ? opt : "", sticky, 0, 0,
1.129 xsa 523: entry, CVS_ENT_MAXLINELEN);
1.65 joris 524:
525: entlist = cvs_ent_open(cf->file_wd);
526: cvs_ent_add(entlist, entry);
1.171 nicm 527: free(entry);
1.65 joris 528: }
529:
530: /*
531: * XXX - this is the way GNU cvs checks for outstanding conflicts
532: * in a file after a merge. It is a very very bad approach and
533: * should be looked at once opencvs is working decently.
534: */
535: int
536: update_has_conflict_markers(struct cvs_file *cf)
537: {
538: BUF *bp;
539: int conflict;
540: char *content;
1.162 ray 541: struct rcs_line *lp;
542: struct rcs_lines *lines;
1.83 niallo 543: size_t len;
1.65 joris 544:
545: cvs_log(LP_TRACE, "update_has_conflict_markers(%s)", cf->file_path);
1.78 joris 546:
1.157 joris 547: if (!(cf->file_flags & FILE_ON_DISK) || cf->file_ent == NULL)
1.78 joris 548: return (0);
1.65 joris 549:
1.162 ray 550: bp = buf_load_fd(cf->fd);
1.65 joris 551:
1.162 ray 552: buf_putc(bp, '\0');
553: len = buf_len(bp);
554: content = buf_release(bp);
1.83 niallo 555: if ((lines = cvs_splitlines(content, len)) == NULL)
1.65 joris 556: fatal("update_has_conflict_markers: failed to split lines");
557:
558: conflict = 0;
559: TAILQ_FOREACH(lp, &(lines->l_lines), l_list) {
560: if (lp->l_line == NULL)
561: continue;
562:
563: if (!strncmp(lp->l_line, RCS_CONFLICT_MARKER1,
1.107 tobias 564: sizeof(RCS_CONFLICT_MARKER1) - 1) ||
1.65 joris 565: !strncmp(lp->l_line, RCS_CONFLICT_MARKER2,
1.107 tobias 566: sizeof(RCS_CONFLICT_MARKER2) - 1) ||
1.65 joris 567: !strncmp(lp->l_line, RCS_CONFLICT_MARKER3,
1.107 tobias 568: sizeof(RCS_CONFLICT_MARKER3) - 1)) {
1.65 joris 569: conflict = 1;
570: break;
571: }
572: }
573:
574: cvs_freelines(lines);
1.171 nicm 575: free(content);
1.65 joris 576: return (conflict);
1.136 joris 577: }
578:
579: void
580: update_join_file(struct cvs_file *cf)
581: {
582: time_t told;
583: RCSNUM *rev1, *rev2;
584: const char *state1, *state2;
585: char rbuf[CVS_REV_BUFSZ], *jrev1, *jrev2, *p;
586:
587: rev1 = rev2 = NULL;
588: jrev1 = jrev2 = NULL;
589:
590: jrev1 = xstrdup(cvs_join_rev1);
591: if (cvs_join_rev2 != NULL)
592: jrev2 = xstrdup(cvs_join_rev2);
593:
594: if (jrev2 == NULL) {
595: jrev2 = jrev1;
596: jrev1 = NULL;
597: }
598:
599: told = cvs_specified_date;
600:
1.142 joris 601: if ((p = strchr(jrev2, ':')) != NULL) {
1.136 joris 602: (*p++) = '\0';
1.163 ray 603: if ((cvs_specified_date = date_parse(p)) == -1) {
604: cvs_printf("invalid date: %s", p);
605: goto out;
606: }
1.136 joris 607: }
608:
609: rev2 = rcs_translate_tag(jrev2, cf->file_rcs);
610: cvs_specified_date = told;
611:
612: if (jrev1 != NULL) {
1.142 joris 613: if ((p = strchr(jrev1, ':')) != NULL) {
1.136 joris 614: (*p++) = '\0';
1.163 ray 615: if ((cvs_specified_date = date_parse(p)) == -1) {
616: cvs_printf("invalid date: %s", p);
617: goto out;
618: }
1.136 joris 619: }
620:
621: rev1 = rcs_translate_tag(jrev1, cf->file_rcs);
622: cvs_specified_date = told;
623: } else {
624: if (rev2 == NULL)
625: goto out;
626:
627: rev1 = rcsnum_alloc();
628: rcsnum_cpy(cf->file_rcsrev, rev1, 0);
629: }
630:
631: state1 = state2 = RCS_STATE_DEAD;
632:
633: if (rev1 != NULL)
634: state1 = rcs_state_get(cf->file_rcs, rev1);
635: if (rev2 != NULL)
636: state2 = rcs_state_get(cf->file_rcs, rev2);
637:
638: if (rev2 == NULL || !strcmp(state2, RCS_STATE_DEAD)) {
639: if (rev1 == NULL || !strcmp(state1, RCS_STATE_DEAD))
640: goto out;
641:
642: if (cf->file_status == FILE_REMOVED ||
643: cf->file_rcs->rf_dead == 1)
644: goto out;
645:
646: if (cf->file_status == FILE_MODIFIED ||
647: cf->file_status == FILE_ADDED)
648: goto out;
649:
650: (void)unlink(cf->file_path);
651: (void)close(cf->fd);
652: cf->fd = -1;
653: cvs_remove_local(cf);
654: goto out;
655: }
656:
657: if (cf->file_ent != NULL) {
658: if (!rcsnum_cmp(cf->file_ent->ce_rev, rev2, 0))
659: goto out;
1.154 tobias 660: }
661:
662: if (cf->file_rcsrev == NULL) {
663: cvs_printf("non-mergable file: %s has no head revision!\n",
664: cf->file_path);
665: goto out;
1.136 joris 666: }
667:
668: if (rev1 == NULL || !strcmp(state1, RCS_STATE_DEAD)) {
1.157 joris 669: if (cf->file_flags & FILE_ON_DISK) {
1.136 joris 670: cvs_printf("%s exists but has been added in %s\n",
1.137 joris 671: cf->file_path, jrev2);
1.136 joris 672: } else {
1.137 joris 673: cvs_printf("A %s\n", cf->file_path);
1.136 joris 674: cvs_checkout_file(cf, cf->file_rcsrev, NULL, 0);
675: cvs_add_local(cf);
676: }
677: goto out;
678: }
679:
1.137 joris 680: if (!rcsnum_cmp(rev1, rev2, 0))
681: goto out;
682:
1.157 joris 683: if (!(cf->file_flags & FILE_ON_DISK)) {
1.137 joris 684: cvs_printf("%s does not exist but is present in %s\n",
685: cf->file_path, jrev2);
1.136 joris 686: goto out;
1.137 joris 687: }
1.136 joris 688:
1.165 tobias 689: if (rcs_kwexp_get(cf->file_rcs) & RCS_KWEXP_NONE) {
1.136 joris 690: cvs_printf("non-mergable file: %s needs merge!\n",
691: cf->file_path);
692: goto out;
693: }
694:
695: cvs_printf("joining ");
696: rcsnum_tostr(rev1, rbuf, sizeof(rbuf));
697: cvs_printf("%s ", rbuf);
698:
699: rcsnum_tostr(rev2, rbuf, sizeof(rbuf));
700: cvs_printf("%s ", rbuf);
701:
702: rcsnum_tostr(cf->file_rcsrev, rbuf, sizeof(rbuf));
703: cvs_printf("into %s (%s)\n", cf->file_path, rbuf);
704:
705: d3rev1 = rev1;
706: d3rev2 = rev2;
707: cvs_checkout_file(cf, cf->file_rcsrev, NULL, CO_MERGE);
708:
1.138 joris 709: if (diff3_conflicts == 0)
1.136 joris 710: update_clear_conflict(cf);
711:
712: out:
1.172 fcambus 713: free(rev1);
714: free(rev2);
1.171 nicm 715: free(jrev1);
716: free(jrev2);
1.164 nicm 717: }
718:
719: void
720: cvs_backup_file(struct cvs_file *cf)
721: {
1.169 deraadt 722: char backup_name[PATH_MAX];
1.167 tedu 723: char revstr[RCSNUM_MAXSTR];
1.164 nicm 724:
725: if (cf->file_status == FILE_ADDED)
1.167 tedu 726: (void)xsnprintf(revstr, sizeof(revstr), "0");
1.164 nicm 727: else
1.167 tedu 728: rcsnum_tostr(cf->file_ent->ce_rev, revstr, sizeof(revstr));
1.164 nicm 729:
1.169 deraadt 730: (void)xsnprintf(backup_name, PATH_MAX, "%s/.#%s.%s",
1.164 nicm 731: cf->file_wd, cf->file_name, revstr);
732:
733: cvs_file_copy(cf->file_path, backup_name);
734:
1.169 deraadt 735: (void)xsnprintf(backup_name, PATH_MAX, ".#%s.%s",
1.164 nicm 736: cf->file_name, revstr);
737: cvs_printf("(Locally modified %s moved to %s)\n",
738: cf->file_name, backup_name);
1.1 jfb 739: }