Annotation of src/usr.bin/cvs/checkout.c, Revision 1.155
1.155 ! tobias 1: /* $OpenBSD: checkout.c,v 1.154 2008/06/14 03:58:29 tobias Exp $ */
1.1 jfb 2: /*
1.53 joris 3: * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
1.1 jfb 4: *
1.53 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.53 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.92 otto 18: #include <sys/param.h>
19: #include <sys/dirent.h>
20: #include <sys/stat.h>
1.117 tobias 21: #include <sys/time.h>
1.92 otto 22:
23: #include <errno.h>
24: #include <fcntl.h>
1.100 tobias 25: #include <libgen.h>
1.130 xsa 26: #include <stdlib.h>
1.92 otto 27: #include <string.h>
1.149 tobias 28: #include <time.h>
1.92 otto 29: #include <unistd.h>
1.1 jfb 30:
31: #include "cvs.h"
1.53 joris 32: #include "diff.h"
1.66 joris 33: #include "remote.h"
1.72 joris 34:
1.61 xsa 35: static void checkout_check_repository(int, char **);
1.113 tobias 36: static int checkout_classify(const char *, const char *);
1.53 joris 37: static void checkout_repository(const char *, const char *);
1.14 joris 38:
1.101 joris 39: extern int print_stdout;
1.54 joris 40: extern int prune_dirs;
1.57 joris 41: extern int build_dirs;
1.54 joris 42:
1.78 xsa 43: static int flags = CR_REPO | CR_RECURSE_DIRS;
1.132 tobias 44: static int Aflag = 0;
1.120 joris 45: static char *dflag = NULL;
1.125 tobias 46: static char *koptstr = NULL;
1.133 joris 47: static char *dateflag = NULL;
1.78 xsa 48:
1.127 joris 49: static int nflag = 0;
50:
1.133 joris 51: char *checkout_target_dir = NULL;
1.151 joris 52:
1.136 joris 53: time_t cvs_specified_date = -1;
1.154 tobias 54: time_t cvs_directory_date = -1;
1.151 joris 55: int disable_fast_checkout = 0;
1.131 tobias 56:
1.22 jfb 57: struct cvs_cmd cvs_cmd_checkout = {
1.112 tobias 58: CVS_OP_CHECKOUT, CVS_USE_WDIR, "checkout",
1.22 jfb 59: { "co", "get" },
1.53 joris 60: "Checkout a working copy of a repository",
1.33 xsa 61: "[-AcflNnPpRs] [-D date | -r tag] [-d dir] [-j rev] [-k mode] "
1.22 jfb 62: "[-t id] module ...",
1.77 xsa 63: "AcD:d:fj:k:lNnPpRr:st:",
1.59 joris 64: NULL,
65: cvs_checkout
66: };
67:
68: struct cvs_cmd cvs_cmd_export = {
1.112 tobias 69: CVS_OP_EXPORT, CVS_USE_WDIR, "export",
1.59 joris 70: { "exp", "ex" },
71: "Export sources from CVS, similar to checkout",
1.61 xsa 72: "[-flNnR] [-d dir] [-k mode] -D date | -r rev module ...",
73: "D:d:k:flNnRr:",
1.22 jfb 74: NULL,
1.61 xsa 75: cvs_export
1.33 xsa 76: };
77:
1.53 joris 78: int
79: cvs_checkout(int argc, char **argv)
1.1 jfb 80: {
1.78 xsa 81: int ch;
1.13 jfb 82:
1.53 joris 83: while ((ch = getopt(argc, argv, cvs_cmd_checkout.cmd_opts)) != -1) {
1.1 jfb 84: switch (ch) {
1.76 xsa 85: case 'A':
1.132 tobias 86: Aflag = 1;
87: if (koptstr == NULL)
88: reset_option = 1;
89: if (cvs_specified_tag == NULL)
90: reset_tag = 1;
1.76 xsa 91: break;
1.129 joris 92: case 'c':
93: cvs_modules_list();
94: exit(0);
1.131 tobias 95: case 'D':
1.133 joris 96: dateflag = optarg;
97: cvs_specified_date = cvs_date_parse(dateflag);
1.154 tobias 98: reset_tag = 0;
1.131 tobias 99: break;
1.120 joris 100: case 'd':
101: if (dflag != NULL)
102: fatal("-d specified two or more times");
103: dflag = optarg;
1.133 joris 104: checkout_target_dir = dflag;
1.151 joris 105:
106: if (cvs_server_active == 1)
107: disable_fast_checkout = 1;
1.120 joris 108: break;
1.142 joris 109: case 'j':
110: if (cvs_join_rev1 == NULL)
111: cvs_join_rev1 = optarg;
112: else if (cvs_join_rev2 == NULL)
113: cvs_join_rev2 = optarg;
114: else
115: fatal("too many -j options");
116: break;
1.125 tobias 117: case 'k':
1.132 tobias 118: reset_option = 0;
1.125 tobias 119: koptstr = optarg;
120: kflag = rcs_kflag_get(koptstr);
121: if (RCS_KWEXP_INVAL(kflag)) {
122: cvs_log(LP_ERR,
1.144 tobias 123: "invalid RCS keyword expansion mode");
1.125 tobias 124: fatal("%s", cvs_cmd_add.cmd_synopsis);
125: }
126: break;
1.77 xsa 127: case 'l':
128: flags &= ~CR_RECURSE_DIRS;
129: break;
1.104 joris 130: case 'N':
131: break;
1.127 joris 132: case 'n':
133: nflag = 1;
134: break;
1.54 joris 135: case 'P':
136: prune_dirs = 1;
1.77 xsa 137: break;
1.101 joris 138: case 'p':
1.112 tobias 139: cmdp->cmd_flags &= ~CVS_USE_WDIR;
1.101 joris 140: print_stdout = 1;
141: cvs_noexec = 1;
1.127 joris 142: nflag = 1;
1.101 joris 143: break;
1.77 xsa 144: case 'R':
1.110 tobias 145: flags |= CR_RECURSE_DIRS;
1.54 joris 146: break;
1.93 niallo 147: case 'r':
1.132 tobias 148: reset_tag = 0;
1.97 joris 149: cvs_specified_tag = optarg;
1.93 niallo 150: break;
1.1 jfb 151: default:
1.53 joris 152: fatal("%s", cvs_cmd_checkout.cmd_synopsis);
1.1 jfb 153: }
154: }
155:
156: argc -= optind;
157: argv += optind;
158:
1.53 joris 159: if (argc == 0)
160: fatal("%s", cvs_cmd_checkout.cmd_synopsis);
1.22 jfb 161:
1.151 joris 162: if (cvs_server_active == 1 && disable_fast_checkout != 1) {
163: cmdp->cmd_flags &= ~CVS_USE_WDIR;
164: cvs_noexec = 1;
165: }
166:
1.61 xsa 167: checkout_check_repository(argc, argv);
168:
1.151 joris 169: if (cvs_server_active == 1 && disable_fast_checkout != 1)
170: cvs_noexec = 0;
171:
1.61 xsa 172: return (0);
173: }
174:
175: int
176: cvs_export(int argc, char **argv)
177: {
1.78 xsa 178: int ch;
1.61 xsa 179:
180: prune_dirs = 1;
181:
182: while ((ch = getopt(argc, argv, cvs_cmd_export.cmd_opts)) != -1) {
183: switch (ch) {
1.125 tobias 184: case 'k':
185: koptstr = optarg;
186: kflag = rcs_kflag_get(koptstr);
187: if (RCS_KWEXP_INVAL(kflag)) {
188: cvs_log(LP_ERR,
1.144 tobias 189: "invalid RCS keyword expansion mode");
1.125 tobias 190: fatal("%s", cvs_cmd_add.cmd_synopsis);
191: }
192: break;
1.61 xsa 193: case 'l':
194: flags &= ~CR_RECURSE_DIRS;
195: break;
196: case 'R':
1.110 tobias 197: flags |= CR_RECURSE_DIRS;
1.98 xsa 198: break;
199: case 'r':
200: cvs_specified_tag = optarg;
1.61 xsa 201: break;
202: default:
203: fatal("%s", cvs_cmd_export.cmd_synopsis);
204: }
205: }
206:
207: argc -= optind;
208: argv += optind;
209:
1.108 tobias 210: if (cvs_specified_tag == NULL)
211: fatal("must specify a tag or date");
212:
1.61 xsa 213: if (argc == 0)
214: fatal("%s", cvs_cmd_export.cmd_synopsis);
215:
216: checkout_check_repository(argc, argv);
217:
218: return (0);
219: }
220:
221: static void
222: checkout_check_repository(int argc, char **argv)
223: {
1.67 xsa 224: int i;
1.123 joris 225: char *wdir, *d;
1.79 joris 226: struct cvs_recursion cr;
1.119 joris 227: struct module_checkout *mc;
1.123 joris 228: struct cvs_ignpat *ip;
229: struct cvs_filelist *fl, *nxt;
230: char repo[MAXPATHLEN], fpath[MAXPATHLEN], *f[1];
1.79 joris 231:
1.102 tobias 232: build_dirs = print_stdout ? 0 : 1;
233:
1.79 joris 234: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
235: cvs_client_connect_to_server();
236:
1.97 joris 237: if (cvs_specified_tag != NULL)
238: cvs_client_send_request("Argument -r%s",
239: cvs_specified_tag);
1.132 tobias 240: if (Aflag)
1.79 joris 241: cvs_client_send_request("Argument -A");
1.133 joris 242:
243: if (dateflag != NULL)
244: cvs_client_send_request("Argument -D%s", dateflag);
1.122 joris 245:
1.125 tobias 246: if (kflag)
247: cvs_client_send_request("Argument -k%s", koptstr);
248:
1.122 joris 249: if (dflag != NULL)
250: cvs_client_send_request("Argument -d%s", dflag);
1.80 xsa 251:
252: if (!(flags & CR_RECURSE_DIRS))
253: cvs_client_send_request("Argument -l");
1.79 joris 254:
255: if (cvs_cmdop == CVS_OP_CHECKOUT && prune_dirs == 1)
256: cvs_client_send_request("Argument -P");
257:
1.101 joris 258: if (print_stdout == 1)
259: cvs_client_send_request("Argument -p");
260:
1.127 joris 261: if (nflag == 1)
262: cvs_client_send_request("Argument -n");
263:
1.79 joris 264: cr.enterdir = NULL;
265: cr.leavedir = NULL;
1.103 tobias 266: if (print_stdout)
267: cr.fileproc = NULL;
268: else
269: cr.fileproc = cvs_client_sendfile;
270:
271: flags &= ~CR_REPO;
1.79 joris 272: cr.flags = flags;
273:
1.108 tobias 274: if (cvs_cmdop != CVS_OP_EXPORT)
275: cvs_file_run(argc, argv, &cr);
1.79 joris 276:
277: cvs_client_send_files(argv, argc);
278: cvs_client_senddir(".");
279:
280: cvs_client_send_request("%s",
281: (cvs_cmdop == CVS_OP_CHECKOUT) ? "co" : "export");
282:
283: cvs_client_get_responses();
284:
285: return;
286: }
1.104 joris 287:
1.53 joris 288: for (i = 0; i < argc; i++) {
1.119 joris 289: mc = cvs_module_lookup(argv[i]);
290: current_module = mc;
1.116 joris 291:
1.123 joris 292: TAILQ_FOREACH(fl, &(mc->mc_ignores), flist)
293: cvs_file_ignore(fl->file_path, &checkout_ign_pats);
1.13 jfb 294:
1.123 joris 295: TAILQ_FOREACH(fl, &(mc->mc_modules), flist) {
1.139 tobias 296: module_repo_root = NULL;
297:
1.123 joris 298: (void)xsnprintf(repo, sizeof(repo), "%s/%s",
299: current_cvsroot->cr_dir, fl->file_path);
1.121 joris 300:
1.123 joris 301: if (!(mc->mc_flags & MODULE_ALIAS) || dflag != NULL)
1.139 tobias 302: module_repo_root = xstrdup(fl->file_path);
1.123 joris 303:
304: if (mc->mc_flags & MODULE_NORECURSE)
305: flags &= ~CR_RECURSE_DIRS;
306:
307: if (dflag != NULL)
308: wdir = dflag;
1.124 joris 309: else if (mc->mc_flags & MODULE_ALIAS)
310: wdir = fl->file_path;
1.123 joris 311: else
1.124 joris 312: wdir = mc->mc_name;
1.123 joris 313:
314: switch (checkout_classify(repo, fl->file_path)) {
315: case CVS_FILE:
316: cr.fileproc = cvs_update_local;
317: cr.flags = flags;
318:
319: if (!(mc->mc_flags & MODULE_ALIAS)) {
320: module_repo_root =
1.139 tobias 321: xstrdup(dirname(fl->file_path));
1.123 joris 322: d = wdir;
323: (void)xsnprintf(fpath, sizeof(fpath),
324: "%s/%s", d,
325: basename(fl->file_path));
326: } else {
327: d = dirname(wdir);
328: strlcpy(fpath, fl->file_path,
329: sizeof(fpath));
330: }
331:
332: if (build_dirs == 1)
333: cvs_mkpath(d, cvs_specified_tag);
334:
335: f[0] = fpath;
336: cvs_file_run(1, f, &cr);
337: break;
338: case CVS_DIR:
339: if (build_dirs == 1)
340: cvs_mkpath(wdir, cvs_specified_tag);
341: checkout_repository(repo, wdir);
342: break;
343: default:
344: break;
345: }
1.126 joris 346:
1.127 joris 347: if (nflag != 1 && mc->mc_prog != NULL &&
1.128 joris 348: mc->mc_flags & MODULE_RUN_ON_CHECKOUT)
1.147 joris 349: cvs_exec(mc->mc_prog, NULL, 0);
1.139 tobias 350:
351: if (module_repo_root != NULL)
352: xfree(module_repo_root);
1.123 joris 353: }
1.119 joris 354:
1.123 joris 355: if (mc->mc_canfree == 1) {
356: for (fl = TAILQ_FIRST(&(mc->mc_modules));
357: fl != TAILQ_END(&(mc->mc_modules)); fl = nxt) {
358: nxt = TAILQ_NEXT(fl, flist);
359: TAILQ_REMOVE(&(mc->mc_modules), fl, flist);
360: xfree(fl->file_path);
361: xfree(fl);
362: }
363: }
1.120 joris 364:
1.123 joris 365: while ((ip = TAILQ_FIRST(&checkout_ign_pats)) != NULL) {
366: TAILQ_REMOVE(&checkout_ign_pats, ip, ip_list);
367: xfree(ip);
1.113 tobias 368: }
1.119 joris 369:
370: xfree(mc);
1.113 tobias 371: }
372: }
1.100 tobias 373:
1.113 tobias 374: static int
375: checkout_classify(const char *repo, const char *arg)
376: {
377: char *d, *f, fpath[MAXPATHLEN];
378: struct stat sb;
379:
380: if (stat(repo, &sb) == 0) {
1.123 joris 381: if (S_ISDIR(sb.st_mode))
382: return CVS_DIR;
1.113 tobias 383: }
1.97 joris 384:
1.113 tobias 385: d = dirname(repo);
386: f = basename(repo);
387:
388: (void)xsnprintf(fpath, sizeof(fpath), "%s/%s%s", d, f, RCS_FILE_EXT);
389: if (stat(fpath, &sb) == 0) {
390: if (!S_ISREG(sb.st_mode)) {
391: cvs_log(LP_ERR, "ignoring %s: not a regular file", arg);
392: return 0;
393: }
394: return CVS_FILE;
1.33 xsa 395: }
1.113 tobias 396:
397: (void)xsnprintf(fpath, sizeof(fpath), "%s/%s/%s%s",
398: d, CVS_PATH_ATTIC, f, RCS_FILE_EXT);
399: if (stat(fpath, &sb) == 0) {
400: if (!S_ISREG(sb.st_mode)) {
401: cvs_log(LP_ERR, "ignoring %s: not a regular file", arg);
402: return 0;
403: }
404: return CVS_FILE;
405: }
406:
407: cvs_log(LP_ERR, "cannot find module `%s' - ignored", arg);
408: return 0;
1.14 joris 409: }
1.9 jfb 410:
1.53 joris 411: static void
412: checkout_repository(const char *repobase, const char *wdbase)
1.14 joris 413: {
1.53 joris 414: struct cvs_flisthead fl, dl;
415: struct cvs_recursion cr;
416:
417: TAILQ_INIT(&fl);
418: TAILQ_INIT(&dl);
1.94 joris 419:
1.99 xsa 420: cvs_history_add((cvs_cmdop == CVS_OP_CHECKOUT) ?
421: CVS_HISTORY_CHECKOUT : CVS_HISTORY_EXPORT, NULL, wdbase);
1.41 joris 422:
1.112 tobias 423: if (print_stdout) {
424: cr.enterdir = NULL;
425: cr.leavedir = NULL;
426: } else {
427: cr.enterdir = cvs_update_enterdir;
1.151 joris 428: if (cvs_server_active == 1) {
429: if (disable_fast_checkout != 1)
430: cr.leavedir = NULL;
431: else
432: cr.leavedir = cvs_update_leavedir;
433: } else {
434: cr.leavedir = prune_dirs ? cvs_update_leavedir : NULL;
435: }
1.112 tobias 436: }
1.64 joris 437: cr.fileproc = cvs_update_local;
1.78 xsa 438: cr.flags = flags;
1.41 joris 439:
1.143 joris 440: cvs_repository_lock(repobase, 0);
1.111 tobias 441: cvs_repository_getdir(repobase, wdbase, &fl, &dl,
442: flags & CR_RECURSE_DIRS ? 1 : 0);
1.1 jfb 443:
1.53 joris 444: cvs_file_walklist(&fl, &cr);
445: cvs_file_freelist(&fl);
1.23 joris 446:
1.53 joris 447: cvs_repository_unlock(repobase);
1.23 joris 448:
1.53 joris 449: cvs_file_walklist(&dl, &cr);
450: cvs_file_freelist(&dl);
451: }
1.23 joris 452:
1.58 joris 453: void
1.105 joris 454: cvs_checkout_file(struct cvs_file *cf, RCSNUM *rnum, char *tag, int co_flags)
1.53 joris 455: {
1.151 joris 456: BUF *bp;
1.148 joris 457: mode_t mode;
1.141 joris 458: int cf_kflag, exists, fd;
1.53 joris 459: time_t rcstime;
460: CVSENTRIES *ent;
461: struct timeval tv[2];
1.149 tobias 462: struct tm datetm;
1.151 joris 463: char *entry, *tosend;
1.115 xsa 464: char kbuf[8], sticky[CVS_REV_BUFSZ], rev[CVS_REV_BUFSZ];
1.96 xsa 465: char timebuf[CVS_TIME_BUFSZ], tbuf[CVS_TIME_BUFSZ];
1.22 jfb 466:
1.87 joris 467: exists = 0;
468: tosend = NULL;
1.104 joris 469:
470: if (!(co_flags & CO_REMOVE))
471: rcsnum_tostr(rnum, rev, sizeof(rev));
1.155 ! tobias 472: else
! 473: rev[0] = '\0';
1.41 joris 474:
1.66 joris 475: cvs_log(LP_TRACE, "cvs_checkout_file(%s, %s, %d) -> %s",
1.78 xsa 476: cf->file_path, rev, co_flags,
1.66 joris 477: (cvs_server_active) ? "to client" : "to disk");
1.42 joris 478:
1.78 xsa 479: if (co_flags & CO_DUMP) {
1.106 tobias 480: rcs_rev_write_fd(cf->file_rcs, rnum, STDOUT_FILENO, 0);
1.65 reyk 481: return;
482: }
1.87 joris 483:
1.66 joris 484: if (cvs_server_active == 0) {
1.141 joris 485: (void)unlink(cf->file_path);
486:
1.87 joris 487: if (!(co_flags & CO_MERGE)) {
488: if (cf->fd != -1) {
489: exists = 1;
490: (void)close(cf->fd);
491: }
492:
1.141 joris 493: cf->fd = open(cf->file_path,
1.142 joris 494: O_CREAT | O_RDWR | O_TRUNC);
1.87 joris 495: if (cf->fd == -1)
496: fatal("cvs_checkout_file: open: %s",
497: strerror(errno));
498:
1.106 tobias 499: rcs_rev_write_fd(cf->file_rcs, rnum, cf->fd, 0);
1.87 joris 500: } else {
1.142 joris 501: cvs_merge_file(cf, (cvs_join_rev1 == NULL));
1.66 joris 502: }
503:
1.148 joris 504: mode = cf->file_rcs->rf_mode;
505: mode |= S_IWUSR;
506:
507: if (fchmod(cf->fd, mode) == -1)
1.66 joris 508: fatal("cvs_checkout_file: fchmod: %s", strerror(errno));
509:
1.87 joris 510: if ((exists == 0) && (cf->file_ent == NULL) &&
511: !(co_flags & CO_MERGE))
1.66 joris 512: rcstime = rcs_rev_getdate(cf->file_rcs, rnum);
1.84 joris 513: else
1.66 joris 514: time(&rcstime);
515:
516: tv[0].tv_sec = rcstime;
517: tv[0].tv_usec = 0;
518: tv[1] = tv[0];
519: if (futimes(cf->fd, tv) == -1)
520: fatal("cvs_checkout_file: futimes: %s",
521: strerror(errno));
1.53 joris 522: } else {
523: time(&rcstime);
1.41 joris 524: }
525:
1.149 tobias 526: gmtime_r(&rcstime, &datetm);
527: asctime_r(&datetm, tbuf);
1.107 tobias 528: tbuf[strcspn(tbuf, "\n")] = '\0';
1.58 joris 529:
1.78 xsa 530: if (co_flags & CO_MERGE) {
1.89 xsa 531: (void)xsnprintf(timebuf, sizeof(timebuf), "Result of merge+%s",
1.58 joris 532: tbuf);
533: } else {
534: strlcpy(timebuf, tbuf, sizeof(timebuf));
535: }
1.41 joris 536:
1.154 tobias 537: if (reset_tag) {
538: sticky[0] = '\0';
539: } else if (co_flags & CO_SETSTICKY)
1.105 joris 540: if (tag != NULL)
1.114 xsa 541: (void)xsnprintf(sticky, sizeof(sticky), "T%s", tag);
1.136 joris 542: else if (cvs_specified_date != -1) {
1.149 tobias 543: gmtime_r(&cvs_specified_date, &datetm);
1.138 xsa 544: (void)strftime(sticky, sizeof(sticky),
1.149 tobias 545: "D"CVS_DATE_FMT, &datetm);
1.154 tobias 546: } else if (cvs_directory_date != -1) {
547: gmtime_r(&cvs_directory_date, &datetm);
548: (void)strftime(sticky, sizeof(sticky),
549: "D"CVS_DATE_FMT, &datetm);
1.134 tobias 550: } else
1.114 xsa 551: (void)xsnprintf(sticky, sizeof(sticky), "T%s", rev);
1.154 tobias 552: else if (cf->file_ent != NULL && cf->file_ent->ce_tag != NULL)
1.114 xsa 553: (void)xsnprintf(sticky, sizeof(sticky), "T%s",
1.109 tobias 554: cf->file_ent->ce_tag);
1.89 xsa 555: else
1.114 xsa 556: sticky[0] = '\0';
1.60 joris 557:
1.85 xsa 558: kbuf[0] = '\0';
1.125 tobias 559: if (cf->file_rcs->rf_expand != NULL) {
560: cf_kflag = rcs_kflag_get(cf->file_rcs->rf_expand);
561: if (kflag || cf_kflag != RCS_KWEXP_DEFAULT)
562: (void)xsnprintf(kbuf, sizeof(kbuf),
563: "-k%s", cf->file_rcs->rf_expand);
1.132 tobias 564: } else if (!reset_option && cf->file_ent != NULL) {
1.85 xsa 565: if (cf->file_ent->ce_opts != NULL)
566: strlcpy(kbuf, cf->file_ent->ce_opts, sizeof(kbuf));
567: }
568:
1.135 xsa 569: entry = xmalloc(CVS_ENT_MAXLINELEN);
570: cvs_ent_line_str(cf->file_name, rev, timebuf, kbuf, sticky, 0, 0,
571: entry, CVS_ENT_MAXLINELEN);
1.41 joris 572:
1.66 joris 573: if (cvs_server_active == 0) {
1.108 tobias 574: if (!(co_flags & CO_REMOVE) && cvs_cmdop != CVS_OP_EXPORT) {
1.95 joris 575: ent = cvs_ent_open(cf->file_wd);
576: cvs_ent_add(ent, entry);
1.142 joris 577: cf->file_ent = cvs_ent_parse(entry);
1.95 joris 578: }
1.66 joris 579: } else {
1.87 joris 580: if (co_flags & CO_MERGE) {
1.141 joris 581: (void)unlink(cf->file_path);
1.142 joris 582: cvs_merge_file(cf, (cvs_join_rev1 == NULL));
1.87 joris 583: tosend = cf->file_path;
1.140 joris 584: fd = cf->fd;
1.87 joris 585: }
586:
1.78 xsa 587: if (co_flags & CO_COMMIT)
1.137 tobias 588: cvs_server_update_entry("Updated", cf);
1.87 joris 589: else if (co_flags & CO_MERGE)
590: cvs_server_update_entry("Merged", cf);
1.95 joris 591: else if (co_flags & CO_REMOVE)
592: cvs_server_update_entry("Removed", cf);
1.69 joris 593: else
594: cvs_server_update_entry("Updated", cf);
1.68 joris 595:
1.135 xsa 596: if (!(co_flags & CO_REMOVE)) {
1.95 joris 597: cvs_remote_output(entry);
1.66 joris 598:
1.87 joris 599: if (!(co_flags & CO_MERGE)) {
1.148 joris 600: mode = cf->file_rcs->rf_mode;
601: mode |= S_IWUSR;
1.151 joris 602: bp = rcs_rev_getbuf(cf->file_rcs, rnum, 0);
603: cvs_remote_send_file_buf(cf->file_path,
604: bp, mode);
605: } else {
606: cvs_remote_send_file(tosend, fd);
1.87 joris 607: }
1.68 joris 608: }
1.66 joris 609: }
1.152 tobias 610:
611: xfree(entry);
1.1 jfb 612: }