Annotation of src/usr.bin/cvs/update.c, Revision 1.174
1.174 ! millert 1: /* $OpenBSD: update.c,v 1.173 2016/10/14 20:37:07 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:
1.174 ! millert 262: if ((uintmax_t)st.st_size > SIZE_MAX)
1.151 joris 263: fatal("cvs_update_leavedir: %s: file size too big",
264: cf->file_name);
1.174 ! millert 265:
! 266: bufsize = (st.st_size > st.st_blksize) ? st.st_size : st.st_blksize;
1.60 joris 267:
268: isempty = 1;
269: buf = xmalloc(bufsize);
270:
1.73 joris 271: if (lseek(cf->fd, 0, SEEK_SET) == -1)
1.60 joris 272: fatal("cvs_update_leavedir: %s", strerror(errno));
273:
1.168 zhuk 274: while ((nbytes = getdents(cf->fd, buf, bufsize)) > 0) {
1.60 joris 275: ebuf = buf + nbytes;
276: cp = buf;
277:
278: while (cp < ebuf) {
279: dp = (struct dirent *)cp;
280: if (!strcmp(dp->d_name, ".") ||
281: !strcmp(dp->d_name, "..") ||
1.95 joris 282: dp->d_fileno == 0) {
1.60 joris 283: cp += dp->d_reclen;
284: continue;
285: }
286:
1.158 joris 287: if (strcmp(dp->d_name, CVS_PATH_CVSDIR))
1.60 joris 288: isempty = 0;
289:
290: if (isempty == 0)
291: break;
292:
293: cp += dp->d_reclen;
294: }
295: }
296:
297: if (nbytes == -1)
298: fatal("cvs_update_leavedir: %s", strerror(errno));
299:
1.171 nicm 300: free(buf);
1.60 joris 301:
1.158 joris 302: prune_it:
1.151 joris 303: if ((isempty == 1 && prune_dirs == 1) ||
304: (cvs_server_active == 1 && cvs_cmdop == CVS_OP_CHECKOUT)) {
1.69 joris 305: /* XXX */
1.60 joris 306: cvs_rmdir(cf->file_path);
307:
1.114 tobias 308: if (cvs_server_active == 0 && cvs_cmdop != CVS_OP_EXPORT) {
1.88 joris 309: entlist = cvs_ent_open(cf->file_wd);
310: cvs_ent_remove(entlist, cf->file_name);
311: }
1.2 jfb 312: }
313: }
314:
1.59 joris 315: void
316: cvs_update_local(struct cvs_file *cf)
1.2 jfb 317: {
1.136 joris 318: CVSENTRIES *entlist;
1.133 tobias 319: int ent_kflag, rcs_kflag, ret, flags;
1.136 joris 320: char *tag, rbuf[CVS_REV_BUFSZ];
1.59 joris 321:
322: cvs_log(LP_TRACE, "cvs_update_local(%s)", cf->file_path);
1.37 joris 323:
1.59 joris 324: if (cf->file_type == CVS_DIR) {
1.114 tobias 325: if (cf->file_status == FILE_SKIP) {
326: if (cvs_cmdop == CVS_OP_EXPORT && verbosity > 0)
327: cvs_printf("? %s\n", cf->file_path);
1.63 joris 328: return;
1.114 tobias 329: }
1.63 joris 330:
1.59 joris 331: if (cf->file_status != FILE_UNKNOWN &&
332: verbosity > 1)
1.159 joris 333: cvs_log(LP_ERR, "Updating %s", cf->file_path);
1.59 joris 334: return;
1.26 jfb 335: }
336:
1.70 joris 337: flags = 0;
1.112 joris 338: if (cvs_specified_tag != NULL)
339: tag = cvs_specified_tag;
1.122 joris 340: else if (cf->file_ent != NULL && cf->file_ent->ce_tag != NULL)
341: tag = cf->file_ent->ce_tag;
1.112 joris 342: else
343: tag = cvs_directory_tag;
344:
345: cvs_file_classify(cf, tag);
346:
1.146 tobias 347: if (kflag && cf->file_rcs != NULL)
1.119 tobias 348: rcs_kwexp_set(cf->file_rcs, kflag);
1.70 joris 349:
1.91 joris 350: if ((cf->file_status == FILE_UPTODATE ||
351: cf->file_status == FILE_MODIFIED) && cf->file_ent != NULL &&
1.124 tobias 352: cf->file_ent->ce_tag != NULL && reset_tag) {
1.91 joris 353: if (cf->file_status == FILE_MODIFIED)
354: cf->file_status = FILE_MERGE;
355: else
356: cf->file_status = FILE_CHECKOUT;
1.110 joris 357:
1.154 tobias 358: if ((cf->file_rcsrev = rcs_head_get(cf->file_rcs)) == NULL)
359: fatal("no head revision in RCS file for %s",
360: cf->file_path);
1.104 joris 361:
362: /* might be a bit overkill */
363: if (cvs_server_active == 1)
364: cvs_server_clear_sticky(cf->file_wd);
1.76 reyk 365: }
366:
1.154 tobias 367: if (print_stdout) {
368: if (cf->file_status != FILE_UNKNOWN && cf->file_rcs != NULL &&
1.155 tobias 369: cf->file_rcsrev != NULL && !cf->file_rcs->rf_dead &&
370: (cf->file_flags & FILE_HAS_TAG)) {
1.154 tobias 371: rcsnum_tostr(cf->file_rcsrev, rbuf, sizeof(rbuf));
372: if (verbosity > 1) {
373: cvs_log(LP_RCS, RCS_DIFF_DIV);
374: cvs_log(LP_RCS, "Checking out %s",
375: cf->file_path);
376: cvs_log(LP_RCS, "RCS: %s", cf->file_rpath);
377: cvs_log(LP_RCS, "VERS: %s", rbuf);
378: cvs_log(LP_RCS, "***************");
379: }
380: cvs_checkout_file(cf, cf->file_rcsrev, tag, CO_DUMP);
1.109 tobias 381: }
1.76 reyk 382: return;
1.70 joris 383: }
1.45 joris 384:
1.119 tobias 385: if (cf->file_ent != NULL) {
386: if (cf->file_ent->ce_opts == NULL) {
387: if (kflag)
388: cf->file_status = FILE_CHECKOUT;
1.154 tobias 389: } else if (cf->file_rcs != NULL) {
1.133 tobias 390: if (strlen(cf->file_ent->ce_opts) < 3)
391: fatal("malformed option for file %s",
392: cf->file_path);
393:
394: ent_kflag = rcs_kflag_get(cf->file_ent->ce_opts + 2);
395: rcs_kflag = rcs_kwexp_get(cf->file_rcs);
396:
397: if ((kflag && (kflag != ent_kflag)) ||
398: (reset_option && (ent_kflag != rcs_kflag)))
1.119 tobias 399: cf->file_status = FILE_CHECKOUT;
400: }
401: }
402:
1.59 joris 403: switch (cf->file_status) {
404: case FILE_UNKNOWN:
405: cvs_printf("? %s\n", cf->file_path);
1.45 joris 406: break;
1.59 joris 407: case FILE_MODIFIED:
1.164 nicm 408: if (backup_local_changes) {
409: cvs_backup_file(cf);
410:
411: cvs_checkout_file(cf, cf->file_rcsrev, NULL, flags);
412: cvs_printf("U %s\n", cf->file_path);
1.65 joris 413: } else {
1.164 nicm 414: ret = update_has_conflict_markers(cf);
415: if (cf->file_ent->ce_conflict != NULL && ret == 1)
416: cvs_printf("C %s\n", cf->file_path);
417: else {
418: if (cf->file_ent->ce_conflict != NULL && ret == 0)
419: update_clear_conflict(cf);
420: cvs_printf("M %s\n", cf->file_path);
421: }
1.65 joris 422: }
1.45 joris 423: break;
1.59 joris 424: case FILE_ADDED:
425: cvs_printf("A %s\n", cf->file_path);
1.45 joris 426: break;
1.59 joris 427: case FILE_REMOVED:
428: cvs_printf("R %s\n", cf->file_path);
1.45 joris 429: break;
1.59 joris 430: case FILE_CONFLICT:
431: cvs_printf("C %s\n", cf->file_path);
432: break;
433: case FILE_LOST:
434: case FILE_CHECKOUT:
435: case FILE_PATCH:
1.153 tobias 436: if (!reset_tag && (tag != NULL || cvs_specified_date != -1 ||
437: cvs_directory_date != -1 || (cf->file_ent != NULL &&
438: cf->file_ent->ce_tag != NULL)))
1.70 joris 439: flags = CO_SETSTICKY;
440:
1.161 nicm 441: if (cf->file_flags & FILE_ON_DISK && (cf->file_ent == NULL ||
442: cf->file_ent->ce_type == CVS_ENT_NONE)) {
443: cvs_log(LP_ERR, "move away %s; it is in the way",
444: cf->file_path);
445: cvs_printf("C %s\n", cf->file_path);
446: } else {
447: cvs_checkout_file(cf, cf->file_rcsrev, tag, flags);
448: cvs_printf("U %s\n", cf->file_path);
449: cvs_history_add(CVS_HISTORY_UPDATE_CO, cf, NULL);
450: }
1.59 joris 451: break;
452: case FILE_MERGE:
1.136 joris 453: d3rev1 = cf->file_ent->ce_rev;
454: d3rev2 = cf->file_rcsrev;
1.112 joris 455: cvs_checkout_file(cf, cf->file_rcsrev, tag, CO_MERGE);
1.65 joris 456:
457: if (diff3_conflicts != 0) {
458: cvs_printf("C %s\n", cf->file_path);
1.100 joris 459: cvs_history_add(CVS_HISTORY_UPDATE_MERGED_ERR,
460: cf, NULL);
1.65 joris 461: } else {
462: update_clear_conflict(cf);
463: cvs_printf("M %s\n", cf->file_path);
1.100 joris 464: cvs_history_add(CVS_HISTORY_UPDATE_MERGED, cf, NULL);
1.65 joris 465: }
1.59 joris 466: break;
467: case FILE_UNLINK:
468: (void)unlink(cf->file_path);
469: case FILE_REMOVE_ENTRY:
470: entlist = cvs_ent_open(cf->file_wd);
471: cvs_ent_remove(entlist, cf->file_name);
1.100 joris 472: cvs_history_add(CVS_HISTORY_UPDATE_REMOVE, cf, NULL);
1.160 joris 473:
474: if (cvs_server_active == 1)
475: cvs_checkout_file(cf, cf->file_rcsrev, tag, CO_REMOVE);
1.110 joris 476: break;
477: case FILE_UPTODATE:
478: if (cvs_cmdop != CVS_OP_UPDATE)
479: break;
480:
1.173 fcambus 481: if (reset_tag != 1 && reset_option != 1 &&
482: cvs_specified_tag == NULL && cvs_specified_date == -1)
1.130 joris 483: break;
484:
485: if (cf->file_rcs->rf_dead != 1 &&
486: (cf->file_flags & FILE_HAS_TAG))
1.112 joris 487: cvs_checkout_file(cf, cf->file_rcsrev,
488: tag, CO_SETSTICKY);
1.45 joris 489: break;
490: default:
491: break;
492: }
1.136 joris 493:
494: if (cvs_join_rev1 != NULL)
495: update_join_file(cf);
1.65 joris 496: }
497:
498: static void
499: update_clear_conflict(struct cvs_file *cf)
500: {
501: CVSENTRIES *entlist;
1.148 tobias 502: char *entry, revbuf[CVS_REV_BUFSZ];
1.136 joris 503: char sticky[CVS_ENT_MAXLINELEN], opt[4];
1.65 joris 504:
505: cvs_log(LP_TRACE, "update_clear_conflict(%s)", cf->file_path);
506:
1.134 joris 507: rcsnum_tostr(cf->file_rcsrev, revbuf, sizeof(revbuf));
1.65 joris 508:
1.121 tobias 509: sticky[0] = '\0';
1.136 joris 510: if (cf->file_ent != NULL && cf->file_ent->ce_tag != NULL)
1.121 tobias 511: (void)xsnprintf(sticky, sizeof(sticky), "T%s",
512: cf->file_ent->ce_tag);
513:
1.136 joris 514: opt[0] = '\0';
515: if (cf->file_ent != NULL && cf->file_ent->ce_opts != NULL)
516: strlcpy(opt, cf->file_ent->ce_opts, sizeof(opt));
517:
1.65 joris 518: entry = xmalloc(CVS_ENT_MAXLINELEN);
1.148 tobias 519: cvs_ent_line_str(cf->file_name, revbuf, "Result of merge",
1.136 joris 520: opt[0] != '\0' ? opt : "", sticky, 0, 0,
1.129 xsa 521: entry, CVS_ENT_MAXLINELEN);
1.65 joris 522:
523: entlist = cvs_ent_open(cf->file_wd);
524: cvs_ent_add(entlist, entry);
1.171 nicm 525: free(entry);
1.65 joris 526: }
527:
528: /*
529: * XXX - this is the way GNU cvs checks for outstanding conflicts
530: * in a file after a merge. It is a very very bad approach and
531: * should be looked at once opencvs is working decently.
532: */
533: int
534: update_has_conflict_markers(struct cvs_file *cf)
535: {
536: BUF *bp;
537: int conflict;
538: char *content;
1.162 ray 539: struct rcs_line *lp;
540: struct rcs_lines *lines;
1.83 niallo 541: size_t len;
1.65 joris 542:
543: cvs_log(LP_TRACE, "update_has_conflict_markers(%s)", cf->file_path);
1.78 joris 544:
1.157 joris 545: if (!(cf->file_flags & FILE_ON_DISK) || cf->file_ent == NULL)
1.78 joris 546: return (0);
1.65 joris 547:
1.162 ray 548: bp = buf_load_fd(cf->fd);
1.65 joris 549:
1.162 ray 550: buf_putc(bp, '\0');
551: len = buf_len(bp);
552: content = buf_release(bp);
1.83 niallo 553: if ((lines = cvs_splitlines(content, len)) == NULL)
1.65 joris 554: fatal("update_has_conflict_markers: failed to split lines");
555:
556: conflict = 0;
557: TAILQ_FOREACH(lp, &(lines->l_lines), l_list) {
558: if (lp->l_line == NULL)
559: continue;
560:
561: if (!strncmp(lp->l_line, RCS_CONFLICT_MARKER1,
1.107 tobias 562: sizeof(RCS_CONFLICT_MARKER1) - 1) ||
1.65 joris 563: !strncmp(lp->l_line, RCS_CONFLICT_MARKER2,
1.107 tobias 564: sizeof(RCS_CONFLICT_MARKER2) - 1) ||
1.65 joris 565: !strncmp(lp->l_line, RCS_CONFLICT_MARKER3,
1.107 tobias 566: sizeof(RCS_CONFLICT_MARKER3) - 1)) {
1.65 joris 567: conflict = 1;
568: break;
569: }
570: }
571:
572: cvs_freelines(lines);
1.171 nicm 573: free(content);
1.65 joris 574: return (conflict);
1.136 joris 575: }
576:
577: void
578: update_join_file(struct cvs_file *cf)
579: {
580: time_t told;
581: RCSNUM *rev1, *rev2;
582: const char *state1, *state2;
583: char rbuf[CVS_REV_BUFSZ], *jrev1, *jrev2, *p;
584:
585: rev1 = rev2 = NULL;
586: jrev1 = jrev2 = NULL;
587:
588: jrev1 = xstrdup(cvs_join_rev1);
589: if (cvs_join_rev2 != NULL)
590: jrev2 = xstrdup(cvs_join_rev2);
591:
592: if (jrev2 == NULL) {
593: jrev2 = jrev1;
594: jrev1 = NULL;
595: }
596:
597: told = cvs_specified_date;
598:
1.142 joris 599: if ((p = strchr(jrev2, ':')) != NULL) {
1.136 joris 600: (*p++) = '\0';
1.163 ray 601: if ((cvs_specified_date = date_parse(p)) == -1) {
602: cvs_printf("invalid date: %s", p);
603: goto out;
604: }
1.136 joris 605: }
606:
607: rev2 = rcs_translate_tag(jrev2, cf->file_rcs);
608: cvs_specified_date = told;
609:
610: if (jrev1 != NULL) {
1.142 joris 611: if ((p = strchr(jrev1, ':')) != NULL) {
1.136 joris 612: (*p++) = '\0';
1.163 ray 613: if ((cvs_specified_date = date_parse(p)) == -1) {
614: cvs_printf("invalid date: %s", p);
615: goto out;
616: }
1.136 joris 617: }
618:
619: rev1 = rcs_translate_tag(jrev1, cf->file_rcs);
620: cvs_specified_date = told;
621: } else {
622: if (rev2 == NULL)
623: goto out;
624:
625: rev1 = rcsnum_alloc();
626: rcsnum_cpy(cf->file_rcsrev, rev1, 0);
627: }
628:
629: state1 = state2 = RCS_STATE_DEAD;
630:
631: if (rev1 != NULL)
632: state1 = rcs_state_get(cf->file_rcs, rev1);
633: if (rev2 != NULL)
634: state2 = rcs_state_get(cf->file_rcs, rev2);
635:
636: if (rev2 == NULL || !strcmp(state2, RCS_STATE_DEAD)) {
637: if (rev1 == NULL || !strcmp(state1, RCS_STATE_DEAD))
638: goto out;
639:
640: if (cf->file_status == FILE_REMOVED ||
641: cf->file_rcs->rf_dead == 1)
642: goto out;
643:
644: if (cf->file_status == FILE_MODIFIED ||
645: cf->file_status == FILE_ADDED)
646: goto out;
647:
648: (void)unlink(cf->file_path);
649: (void)close(cf->fd);
650: cf->fd = -1;
651: cvs_remove_local(cf);
652: goto out;
653: }
654:
655: if (cf->file_ent != NULL) {
656: if (!rcsnum_cmp(cf->file_ent->ce_rev, rev2, 0))
657: goto out;
1.154 tobias 658: }
659:
660: if (cf->file_rcsrev == NULL) {
661: cvs_printf("non-mergable file: %s has no head revision!\n",
662: cf->file_path);
663: goto out;
1.136 joris 664: }
665:
666: if (rev1 == NULL || !strcmp(state1, RCS_STATE_DEAD)) {
1.157 joris 667: if (cf->file_flags & FILE_ON_DISK) {
1.136 joris 668: cvs_printf("%s exists but has been added in %s\n",
1.137 joris 669: cf->file_path, jrev2);
1.136 joris 670: } else {
1.137 joris 671: cvs_printf("A %s\n", cf->file_path);
1.136 joris 672: cvs_checkout_file(cf, cf->file_rcsrev, NULL, 0);
673: cvs_add_local(cf);
674: }
675: goto out;
676: }
677:
1.137 joris 678: if (!rcsnum_cmp(rev1, rev2, 0))
679: goto out;
680:
1.157 joris 681: if (!(cf->file_flags & FILE_ON_DISK)) {
1.137 joris 682: cvs_printf("%s does not exist but is present in %s\n",
683: cf->file_path, jrev2);
1.136 joris 684: goto out;
1.137 joris 685: }
1.136 joris 686:
1.165 tobias 687: if (rcs_kwexp_get(cf->file_rcs) & RCS_KWEXP_NONE) {
1.136 joris 688: cvs_printf("non-mergable file: %s needs merge!\n",
689: cf->file_path);
690: goto out;
691: }
692:
693: cvs_printf("joining ");
694: rcsnum_tostr(rev1, rbuf, sizeof(rbuf));
695: cvs_printf("%s ", rbuf);
696:
697: rcsnum_tostr(rev2, rbuf, sizeof(rbuf));
698: cvs_printf("%s ", rbuf);
699:
700: rcsnum_tostr(cf->file_rcsrev, rbuf, sizeof(rbuf));
701: cvs_printf("into %s (%s)\n", cf->file_path, rbuf);
702:
703: d3rev1 = rev1;
704: d3rev2 = rev2;
705: cvs_checkout_file(cf, cf->file_rcsrev, NULL, CO_MERGE);
706:
1.138 joris 707: if (diff3_conflicts == 0)
1.136 joris 708: update_clear_conflict(cf);
709:
710: out:
1.172 fcambus 711: free(rev1);
712: free(rev2);
1.171 nicm 713: free(jrev1);
714: free(jrev2);
1.164 nicm 715: }
716:
717: void
718: cvs_backup_file(struct cvs_file *cf)
719: {
1.169 deraadt 720: char backup_name[PATH_MAX];
1.167 tedu 721: char revstr[RCSNUM_MAXSTR];
1.164 nicm 722:
723: if (cf->file_status == FILE_ADDED)
1.167 tedu 724: (void)xsnprintf(revstr, sizeof(revstr), "0");
1.164 nicm 725: else
1.167 tedu 726: rcsnum_tostr(cf->file_ent->ce_rev, revstr, sizeof(revstr));
1.164 nicm 727:
1.169 deraadt 728: (void)xsnprintf(backup_name, PATH_MAX, "%s/.#%s.%s",
1.164 nicm 729: cf->file_wd, cf->file_name, revstr);
730:
731: cvs_file_copy(cf->file_path, backup_name);
732:
1.169 deraadt 733: (void)xsnprintf(backup_name, PATH_MAX, ".#%s.%s",
1.164 nicm 734: cf->file_name, revstr);
735: cvs_printf("(Locally modified %s moved to %s)\n",
736: cf->file_name, backup_name);
1.1 jfb 737: }