Annotation of src/usr.bin/cvs/update.c, Revision 1.172
1.172 ! fcambus 1: /* $OpenBSD: update.c,v 1.171 2015/11/05 09:48:21 nicm 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.156 joris 483: if (reset_tag != 1 && reset_option != 1)
1.130 joris 484: break;
485:
1.156 joris 486: if (cf->file_ent != NULL && cf->file_ent->ce_tag == NULL)
1.130 joris 487: break;
488:
489: if (cf->file_rcs->rf_dead != 1 &&
490: (cf->file_flags & FILE_HAS_TAG))
1.112 joris 491: cvs_checkout_file(cf, cf->file_rcsrev,
492: tag, CO_SETSTICKY);
1.45 joris 493: break;
494: default:
495: break;
496: }
1.136 joris 497:
498: if (cvs_join_rev1 != NULL)
499: update_join_file(cf);
1.65 joris 500: }
501:
502: static void
503: update_clear_conflict(struct cvs_file *cf)
504: {
505: CVSENTRIES *entlist;
1.148 tobias 506: char *entry, revbuf[CVS_REV_BUFSZ];
1.136 joris 507: char sticky[CVS_ENT_MAXLINELEN], opt[4];
1.65 joris 508:
509: cvs_log(LP_TRACE, "update_clear_conflict(%s)", cf->file_path);
510:
1.134 joris 511: rcsnum_tostr(cf->file_rcsrev, revbuf, sizeof(revbuf));
1.65 joris 512:
1.121 tobias 513: sticky[0] = '\0';
1.136 joris 514: if (cf->file_ent != NULL && cf->file_ent->ce_tag != NULL)
1.121 tobias 515: (void)xsnprintf(sticky, sizeof(sticky), "T%s",
516: cf->file_ent->ce_tag);
517:
1.136 joris 518: opt[0] = '\0';
519: if (cf->file_ent != NULL && cf->file_ent->ce_opts != NULL)
520: strlcpy(opt, cf->file_ent->ce_opts, sizeof(opt));
521:
1.65 joris 522: entry = xmalloc(CVS_ENT_MAXLINELEN);
1.148 tobias 523: cvs_ent_line_str(cf->file_name, revbuf, "Result of merge",
1.136 joris 524: opt[0] != '\0' ? opt : "", sticky, 0, 0,
1.129 xsa 525: entry, CVS_ENT_MAXLINELEN);
1.65 joris 526:
527: entlist = cvs_ent_open(cf->file_wd);
528: cvs_ent_add(entlist, entry);
1.171 nicm 529: free(entry);
1.65 joris 530: }
531:
532: /*
533: * XXX - this is the way GNU cvs checks for outstanding conflicts
534: * in a file after a merge. It is a very very bad approach and
535: * should be looked at once opencvs is working decently.
536: */
537: int
538: update_has_conflict_markers(struct cvs_file *cf)
539: {
540: BUF *bp;
541: int conflict;
542: char *content;
1.162 ray 543: struct rcs_line *lp;
544: struct rcs_lines *lines;
1.83 niallo 545: size_t len;
1.65 joris 546:
547: cvs_log(LP_TRACE, "update_has_conflict_markers(%s)", cf->file_path);
1.78 joris 548:
1.157 joris 549: if (!(cf->file_flags & FILE_ON_DISK) || cf->file_ent == NULL)
1.78 joris 550: return (0);
1.65 joris 551:
1.162 ray 552: bp = buf_load_fd(cf->fd);
1.65 joris 553:
1.162 ray 554: buf_putc(bp, '\0');
555: len = buf_len(bp);
556: content = buf_release(bp);
1.83 niallo 557: if ((lines = cvs_splitlines(content, len)) == NULL)
1.65 joris 558: fatal("update_has_conflict_markers: failed to split lines");
559:
560: conflict = 0;
561: TAILQ_FOREACH(lp, &(lines->l_lines), l_list) {
562: if (lp->l_line == NULL)
563: continue;
564:
565: if (!strncmp(lp->l_line, RCS_CONFLICT_MARKER1,
1.107 tobias 566: sizeof(RCS_CONFLICT_MARKER1) - 1) ||
1.65 joris 567: !strncmp(lp->l_line, RCS_CONFLICT_MARKER2,
1.107 tobias 568: sizeof(RCS_CONFLICT_MARKER2) - 1) ||
1.65 joris 569: !strncmp(lp->l_line, RCS_CONFLICT_MARKER3,
1.107 tobias 570: sizeof(RCS_CONFLICT_MARKER3) - 1)) {
1.65 joris 571: conflict = 1;
572: break;
573: }
574: }
575:
576: cvs_freelines(lines);
1.171 nicm 577: free(content);
1.65 joris 578: return (conflict);
1.136 joris 579: }
580:
581: void
582: update_join_file(struct cvs_file *cf)
583: {
584: time_t told;
585: RCSNUM *rev1, *rev2;
586: const char *state1, *state2;
587: char rbuf[CVS_REV_BUFSZ], *jrev1, *jrev2, *p;
588:
589: rev1 = rev2 = NULL;
590: jrev1 = jrev2 = NULL;
591:
592: jrev1 = xstrdup(cvs_join_rev1);
593: if (cvs_join_rev2 != NULL)
594: jrev2 = xstrdup(cvs_join_rev2);
595:
596: if (jrev2 == NULL) {
597: jrev2 = jrev1;
598: jrev1 = NULL;
599: }
600:
601: told = cvs_specified_date;
602:
1.142 joris 603: if ((p = strchr(jrev2, ':')) != NULL) {
1.136 joris 604: (*p++) = '\0';
1.163 ray 605: if ((cvs_specified_date = date_parse(p)) == -1) {
606: cvs_printf("invalid date: %s", p);
607: goto out;
608: }
1.136 joris 609: }
610:
611: rev2 = rcs_translate_tag(jrev2, cf->file_rcs);
612: cvs_specified_date = told;
613:
614: if (jrev1 != NULL) {
1.142 joris 615: if ((p = strchr(jrev1, ':')) != NULL) {
1.136 joris 616: (*p++) = '\0';
1.163 ray 617: if ((cvs_specified_date = date_parse(p)) == -1) {
618: cvs_printf("invalid date: %s", p);
619: goto out;
620: }
1.136 joris 621: }
622:
623: rev1 = rcs_translate_tag(jrev1, cf->file_rcs);
624: cvs_specified_date = told;
625: } else {
626: if (rev2 == NULL)
627: goto out;
628:
629: rev1 = rcsnum_alloc();
630: rcsnum_cpy(cf->file_rcsrev, rev1, 0);
631: }
632:
633: state1 = state2 = RCS_STATE_DEAD;
634:
635: if (rev1 != NULL)
636: state1 = rcs_state_get(cf->file_rcs, rev1);
637: if (rev2 != NULL)
638: state2 = rcs_state_get(cf->file_rcs, rev2);
639:
640: if (rev2 == NULL || !strcmp(state2, RCS_STATE_DEAD)) {
641: if (rev1 == NULL || !strcmp(state1, RCS_STATE_DEAD))
642: goto out;
643:
644: if (cf->file_status == FILE_REMOVED ||
645: cf->file_rcs->rf_dead == 1)
646: goto out;
647:
648: if (cf->file_status == FILE_MODIFIED ||
649: cf->file_status == FILE_ADDED)
650: goto out;
651:
652: (void)unlink(cf->file_path);
653: (void)close(cf->fd);
654: cf->fd = -1;
655: cvs_remove_local(cf);
656: goto out;
657: }
658:
659: if (cf->file_ent != NULL) {
660: if (!rcsnum_cmp(cf->file_ent->ce_rev, rev2, 0))
661: goto out;
1.154 tobias 662: }
663:
664: if (cf->file_rcsrev == NULL) {
665: cvs_printf("non-mergable file: %s has no head revision!\n",
666: cf->file_path);
667: goto out;
1.136 joris 668: }
669:
670: if (rev1 == NULL || !strcmp(state1, RCS_STATE_DEAD)) {
1.157 joris 671: if (cf->file_flags & FILE_ON_DISK) {
1.136 joris 672: cvs_printf("%s exists but has been added in %s\n",
1.137 joris 673: cf->file_path, jrev2);
1.136 joris 674: } else {
1.137 joris 675: cvs_printf("A %s\n", cf->file_path);
1.136 joris 676: cvs_checkout_file(cf, cf->file_rcsrev, NULL, 0);
677: cvs_add_local(cf);
678: }
679: goto out;
680: }
681:
1.137 joris 682: if (!rcsnum_cmp(rev1, rev2, 0))
683: goto out;
684:
1.157 joris 685: if (!(cf->file_flags & FILE_ON_DISK)) {
1.137 joris 686: cvs_printf("%s does not exist but is present in %s\n",
687: cf->file_path, jrev2);
1.136 joris 688: goto out;
1.137 joris 689: }
1.136 joris 690:
1.165 tobias 691: if (rcs_kwexp_get(cf->file_rcs) & RCS_KWEXP_NONE) {
1.136 joris 692: cvs_printf("non-mergable file: %s needs merge!\n",
693: cf->file_path);
694: goto out;
695: }
696:
697: cvs_printf("joining ");
698: rcsnum_tostr(rev1, rbuf, sizeof(rbuf));
699: cvs_printf("%s ", rbuf);
700:
701: rcsnum_tostr(rev2, rbuf, sizeof(rbuf));
702: cvs_printf("%s ", rbuf);
703:
704: rcsnum_tostr(cf->file_rcsrev, rbuf, sizeof(rbuf));
705: cvs_printf("into %s (%s)\n", cf->file_path, rbuf);
706:
707: d3rev1 = rev1;
708: d3rev2 = rev2;
709: cvs_checkout_file(cf, cf->file_rcsrev, NULL, CO_MERGE);
710:
1.138 joris 711: if (diff3_conflicts == 0)
1.136 joris 712: update_clear_conflict(cf);
713:
714: out:
1.172 ! fcambus 715: free(rev1);
! 716: free(rev2);
1.171 nicm 717: free(jrev1);
718: free(jrev2);
1.164 nicm 719: }
720:
721: void
722: cvs_backup_file(struct cvs_file *cf)
723: {
1.169 deraadt 724: char backup_name[PATH_MAX];
1.167 tedu 725: char revstr[RCSNUM_MAXSTR];
1.164 nicm 726:
727: if (cf->file_status == FILE_ADDED)
1.167 tedu 728: (void)xsnprintf(revstr, sizeof(revstr), "0");
1.164 nicm 729: else
1.167 tedu 730: rcsnum_tostr(cf->file_ent->ce_rev, revstr, sizeof(revstr));
1.164 nicm 731:
1.169 deraadt 732: (void)xsnprintf(backup_name, PATH_MAX, "%s/.#%s.%s",
1.164 nicm 733: cf->file_wd, cf->file_name, revstr);
734:
735: cvs_file_copy(cf->file_path, backup_name);
736:
1.169 deraadt 737: (void)xsnprintf(backup_name, PATH_MAX, ".#%s.%s",
1.164 nicm 738: cf->file_name, revstr);
739: cvs_printf("(Locally modified %s moved to %s)\n",
740: cf->file_name, backup_name);
1.1 jfb 741: }