1*37fdff3fStobias /* $OpenBSD: commit.c,v 1.126 2008/02/04 15:07:33 tobias Exp $ */ 208f90673Sjfb /* 33ad3fb45Sjoris * Copyright (c) 2006 Joris Vink <joris@openbsd.org> 42ec286b3Sxsa * Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org> 508f90673Sjfb * 63ad3fb45Sjoris * Permission to use, copy, modify, and distribute this software for any 73ad3fb45Sjoris * purpose with or without fee is hereby granted, provided that the above 83ad3fb45Sjoris * copyright notice and this permission notice appear in all copies. 908f90673Sjfb * 103ad3fb45Sjoris * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 113ad3fb45Sjoris * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 123ad3fb45Sjoris * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 133ad3fb45Sjoris * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 143ad3fb45Sjoris * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 153ad3fb45Sjoris * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 163ad3fb45Sjoris * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1708f90673Sjfb */ 1808f90673Sjfb 191f8531bdSotto #include <sys/stat.h> 201f8531bdSotto 211f8531bdSotto #include <errno.h> 221f8531bdSotto #include <fcntl.h> 231f8531bdSotto #include <string.h> 241f8531bdSotto #include <unistd.h> 2508f90673Sjfb 2608f90673Sjfb #include "cvs.h" 273ad3fb45Sjoris #include "diff.h" 289fac60a5Sjoris #include "remote.h" 2908f90673Sjfb 303ad3fb45Sjoris void cvs_commit_local(struct cvs_file *); 31db758d52Sjoris void cvs_commit_check_files(struct cvs_file *); 3208f90673Sjfb 3318cf7829Sjoris static BUF *commit_diff(struct cvs_file *, RCSNUM *, int); 342ec286b3Sxsa static void commit_desc_set(struct cvs_file *); 353ad3fb45Sjoris 363ad3fb45Sjoris struct cvs_flisthead files_affected; 37db758d52Sjoris struct cvs_flisthead files_added; 38db758d52Sjoris struct cvs_flisthead files_removed; 39db758d52Sjoris struct cvs_flisthead files_modified; 40db758d52Sjoris 413ad3fb45Sjoris int conflicts_found; 42db758d52Sjoris char *logmsg = NULL; 4308f90673Sjfb 44e4276007Sjfb struct cvs_cmd cvs_cmd_commit = { 45f331ff59Stobias CVS_OP_COMMIT, CVS_USE_WDIR, "commit", 46e4276007Sjfb { "ci", "com" }, 47e4276007Sjfb "Check files into the repository", 48e4276007Sjfb "[-flR] [-F logfile | -m msg] [-r rev] ...", 49e4276007Sjfb "F:flm:Rr:", 5016cfc147Sjoris NULL, 513ad3fb45Sjoris cvs_commit 5216cfc147Sjoris }; 5308f90673Sjfb 543ad3fb45Sjoris int 553ad3fb45Sjoris cvs_commit(int argc, char **argv) 5608f90673Sjfb { 57f4d74cd1Stobias int ch, Fflag, mflag; 583ad3fb45Sjoris char *arg = "."; 591890abdaSjoris int flags; 603ad3fb45Sjoris struct cvs_recursion cr; 6108f90673Sjfb 621890abdaSjoris flags = CR_RECURSE_DIRS; 63f4d74cd1Stobias Fflag = mflag = 0; 641890abdaSjoris 653ad3fb45Sjoris while ((ch = getopt(argc, argv, cvs_cmd_commit.cmd_opts)) != -1) { 6608f90673Sjfb switch (ch) { 673ad3fb45Sjoris case 'F': 68f4d74cd1Stobias /* free previously assigned value */ 69f4d74cd1Stobias if (logmsg != NULL) 70f4d74cd1Stobias xfree(logmsg); 7116190807Sjoris logmsg = cvs_logmsg_read(optarg); 72f4d74cd1Stobias Fflag = 1; 7308f90673Sjfb break; 746f8f2f56Sxsa case 'f': 756f8f2f56Sxsa break; 7608f90673Sjfb case 'l': 771890abdaSjoris flags &= ~CR_RECURSE_DIRS; 7808f90673Sjfb break; 7908f90673Sjfb case 'm': 80f4d74cd1Stobias /* free previously assigned value */ 81f4d74cd1Stobias if (logmsg != NULL) 82f4d74cd1Stobias xfree(logmsg); 833ad3fb45Sjoris logmsg = xstrdup(optarg); 84f4d74cd1Stobias mflag = 1; 8508f90673Sjfb break; 863ad3fb45Sjoris case 'R': 87bcf22459Stobias flags |= CR_RECURSE_DIRS; 888d550b2eSxsa break; 896f8f2f56Sxsa case 'r': 906f8f2f56Sxsa break; 9108f90673Sjfb default: 923ad3fb45Sjoris fatal("%s", cvs_cmd_commit.cmd_synopsis); 9308f90673Sjfb } 9408f90673Sjfb } 9508f90673Sjfb 963ad3fb45Sjoris argc -= optind; 973ad3fb45Sjoris argv += optind; 9808f90673Sjfb 99f4d74cd1Stobias /* -F and -m are mutually exclusive */ 100f4d74cd1Stobias if (Fflag && mflag) 101f4d74cd1Stobias fatal("cannot specify both a log file and a message"); 102f4d74cd1Stobias 103db758d52Sjoris TAILQ_INIT(&files_affected); 104db758d52Sjoris TAILQ_INIT(&files_added); 105db758d52Sjoris TAILQ_INIT(&files_removed); 106db758d52Sjoris TAILQ_INIT(&files_modified); 107db758d52Sjoris conflicts_found = 0; 10808f90673Sjfb 1099fac60a5Sjoris cr.enterdir = NULL; 1109fac60a5Sjoris cr.leavedir = NULL; 111db758d52Sjoris cr.fileproc = cvs_commit_check_files; 1129fac60a5Sjoris cr.flags = flags; 1139fac60a5Sjoris 1149fac60a5Sjoris if (argc > 0) 1159fac60a5Sjoris cvs_file_run(argc, argv, &cr); 1169fac60a5Sjoris else 1179fac60a5Sjoris cvs_file_run(1, &arg, &cr); 1189fac60a5Sjoris 119db758d52Sjoris if (conflicts_found != 0) 120db758d52Sjoris fatal("%d conflicts found, please correct these first", 121db758d52Sjoris conflicts_found); 122db758d52Sjoris 123a066adb3Sjoris if (TAILQ_EMPTY(&files_affected)) 124a066adb3Sjoris return (0); 125a066adb3Sjoris 126db758d52Sjoris if (logmsg == NULL && cvs_server_active == 0) { 127db758d52Sjoris logmsg = cvs_logmsg_create(&files_added, &files_removed, 128db758d52Sjoris &files_modified); 129db758d52Sjoris } 130db758d52Sjoris 131db758d52Sjoris if (logmsg == NULL) 132db758d52Sjoris fatal("This shouldnt happen, honestly!"); 133db758d52Sjoris 1344c65ce21Sjoris cvs_file_freelist(&files_modified); 1354c65ce21Sjoris cvs_file_freelist(&files_removed); 1364c65ce21Sjoris cvs_file_freelist(&files_added); 1374c65ce21Sjoris 138db758d52Sjoris if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) { 13980f6ca9bSjoris cvs_client_connect_to_server(); 140db758d52Sjoris cr.fileproc = cvs_client_sendfile; 141db758d52Sjoris 142db758d52Sjoris if (argc > 0) 143db758d52Sjoris cvs_file_run(argc, argv, &cr); 144db758d52Sjoris else 145db758d52Sjoris cvs_file_run(1, &arg, &cr); 146db758d52Sjoris 147585a1783Sxsa if (!(flags & CR_RECURSE_DIRS)) 148585a1783Sxsa cvs_client_send_request("Argument -l"); 149585a1783Sxsa 150f76ce13cSjoris cvs_client_send_logmsg(logmsg); 1519fac60a5Sjoris cvs_client_send_files(argv, argc); 1529fac60a5Sjoris cvs_client_senddir("."); 1539fac60a5Sjoris cvs_client_send_request("ci"); 1549fac60a5Sjoris cvs_client_get_responses(); 155db758d52Sjoris } else { 156bc5d89feSjoris cr.fileproc = cvs_commit_local; 1573ad3fb45Sjoris cvs_file_walklist(&files_affected, &cr); 1583ad3fb45Sjoris cvs_file_freelist(&files_affected); 159db758d52Sjoris } 160ef6e385cSjoris 16154de3f21Stobias xfree(logmsg); 16216cfc147Sjoris return (0); 163c710bc5aSjfb } 164c710bc5aSjfb 1653ad3fb45Sjoris void 166db758d52Sjoris cvs_commit_check_files(struct cvs_file *cf) 16716cfc147Sjoris { 16818cf7829Sjoris char *tag; 16918cf7829Sjoris RCSNUM *branch, *brev; 17018cf7829Sjoris char rev[CVS_REV_BUFSZ]; 17118cf7829Sjoris 17254de3f21Stobias branch = brev = NULL; 17354de3f21Stobias 174db758d52Sjoris cvs_log(LP_TRACE, "cvs_commit_check_files(%s)", cf->file_path); 1755805c4b0Sjoris 1767cffd7e4Sjoris if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) 1777cffd7e4Sjoris cvs_remote_classify_file(cf); 1787cffd7e4Sjoris else 17951ef6581Sjoris cvs_file_classify(cf, cvs_directory_tag); 1803ad3fb45Sjoris 181c1fe09b4Sjoris if (cf->file_type == CVS_DIR) { 182c1fe09b4Sjoris if (verbosity > 1) 183c1fe09b4Sjoris cvs_log(LP_NOTICE, "Examining %s", cf->file_path); 184c1fe09b4Sjoris return; 185c1fe09b4Sjoris } 186c1fe09b4Sjoris 1873ad3fb45Sjoris if (cf->file_status == FILE_CONFLICT || 188846e2b74Sjoris cf->file_status == FILE_UNLINK) { 1893ad3fb45Sjoris conflicts_found++; 190846e2b74Sjoris return; 191846e2b74Sjoris } 1923ad3fb45Sjoris 19319615a73Sjoris if (cf->file_status != FILE_REMOVED && 19419615a73Sjoris update_has_conflict_markers(cf)) { 195f9872b43Sjoris cvs_log(LP_ERR, "conflict: unresolved conflicts in %s from " 196f9872b43Sjoris "merging, please fix these first", cf->file_path); 197f9872b43Sjoris conflicts_found++; 198846e2b74Sjoris return; 199f9872b43Sjoris } 200f9872b43Sjoris 2012a132f99Sjoris if (cf->file_status == FILE_MERGE || 202d1eec7e9Sjoris cf->file_status == FILE_PATCH || 203846e2b74Sjoris cf->file_status == FILE_CHECKOUT || 204846e2b74Sjoris cf->file_status == FILE_LOST) { 2052a132f99Sjoris cvs_log(LP_ERR, "conflict: %s is not up-to-date", 2062a132f99Sjoris cf->file_path); 2072a132f99Sjoris conflicts_found++; 208846e2b74Sjoris return; 2092a132f99Sjoris } 2102a132f99Sjoris 21118cf7829Sjoris if (current_cvsroot->cr_method == CVS_METHOD_LOCAL) { 21218cf7829Sjoris tag = cvs_directory_tag; 21318cf7829Sjoris if (cf->file_ent != NULL) 21418cf7829Sjoris tag = cf->file_ent->ce_tag; 21518cf7829Sjoris 21618cf7829Sjoris if (tag != NULL && cf->file_rcs != NULL) { 21718cf7829Sjoris brev = rcs_sym_getrev(cf->file_rcs, tag); 21818cf7829Sjoris if (brev != NULL) { 21918cf7829Sjoris if (RCSNUM_ISBRANCH(brev)) 22018cf7829Sjoris goto next; 2214649b416Sjoris rcsnum_free(brev); 22218cf7829Sjoris } 22318cf7829Sjoris 22418cf7829Sjoris brev = rcs_translate_tag(tag, cf->file_rcs); 22518cf7829Sjoris 22618cf7829Sjoris if (brev == NULL) { 22718cf7829Sjoris fatal("failed to resolve tag: %s", 22818cf7829Sjoris cf->file_ent->ce_tag); 22918cf7829Sjoris } 23018cf7829Sjoris 23118cf7829Sjoris rcsnum_tostr(brev, rev, sizeof(rev)); 23218cf7829Sjoris if ((branch = rcsnum_revtobr(brev)) == NULL) { 23318cf7829Sjoris cvs_log(LP_ERR, "%s is not a branch revision", 23418cf7829Sjoris rev); 23518cf7829Sjoris conflicts_found++; 23654de3f21Stobias rcsnum_free(brev); 23718cf7829Sjoris return; 23818cf7829Sjoris } 23918cf7829Sjoris 24018cf7829Sjoris if (!RCSNUM_ISBRANCHREV(brev)) { 24118cf7829Sjoris cvs_log(LP_ERR, "%s is not a branch revision", 24218cf7829Sjoris rev); 24318cf7829Sjoris conflicts_found++; 24454de3f21Stobias rcsnum_free(branch); 24554de3f21Stobias rcsnum_free(brev); 24618cf7829Sjoris return; 24718cf7829Sjoris } 24818cf7829Sjoris 24918cf7829Sjoris rcsnum_tostr(branch, rev, sizeof(rev)); 25018cf7829Sjoris if (!RCSNUM_ISBRANCH(branch)) { 25118cf7829Sjoris cvs_log(LP_ERR, "%s (%s) is not a branch", 25218cf7829Sjoris cf->file_ent->ce_tag, rev); 25318cf7829Sjoris conflicts_found++; 25454de3f21Stobias rcsnum_free(branch); 25554de3f21Stobias rcsnum_free(brev); 25618cf7829Sjoris return; 25718cf7829Sjoris } 25818cf7829Sjoris } 25918cf7829Sjoris } 26018cf7829Sjoris 26118cf7829Sjoris next: 26254de3f21Stobias if (branch != NULL) 26354de3f21Stobias rcsnum_free(branch); 26454de3f21Stobias if (brev != NULL) 26554de3f21Stobias rcsnum_free(brev); 26654de3f21Stobias 2673ad3fb45Sjoris if (cf->file_status == FILE_ADDED || 2683ad3fb45Sjoris cf->file_status == FILE_REMOVED || 2693ad3fb45Sjoris cf->file_status == FILE_MODIFIED) 27051ef6581Sjoris cvs_file_get(cf->file_path, 0, &files_affected); 271db758d52Sjoris 272db758d52Sjoris switch (cf->file_status) { 273db758d52Sjoris case FILE_ADDED: 27451ef6581Sjoris cvs_file_get(cf->file_path, 0, &files_added); 275db758d52Sjoris break; 276db758d52Sjoris case FILE_REMOVED: 27751ef6581Sjoris cvs_file_get(cf->file_path, 0, &files_removed); 278db758d52Sjoris break; 279db758d52Sjoris case FILE_MODIFIED: 28051ef6581Sjoris cvs_file_get(cf->file_path, 0, &files_modified); 281db758d52Sjoris break; 282db758d52Sjoris } 283ef6e385cSjoris } 284ef6e385cSjoris 2853ad3fb45Sjoris void 2863ad3fb45Sjoris cvs_commit_local(struct cvs_file *cf) 287213afef1Sjfb { 28818cf7829Sjoris char *tag; 2894d33f394Sjoris BUF *b, *d; 29018cf7829Sjoris int onbranch, isnew, histtype; 29118cf7829Sjoris RCSNUM *nrev, *crev, *rrev, *brev; 292c486465dSxsa int openflags, rcsflags; 2937fa064caStobias char rbuf[CVS_REV_BUFSZ], nbuf[CVS_REV_BUFSZ]; 294d77e7b73Sjoris CVSENTRIES *entlist; 295ba7b4b60Sotto char attic[MAXPATHLEN], repo[MAXPATHLEN], rcsfile[MAXPATHLEN]; 296213afef1Sjfb 2973ad3fb45Sjoris cvs_log(LP_TRACE, "cvs_commit_local(%s)", cf->file_path); 29851ef6581Sjoris cvs_file_classify(cf, cvs_directory_tag); 299213afef1Sjfb 3007938e528Sjoris if (cvs_noexec == 1) 3017938e528Sjoris return; 3027938e528Sjoris 3037fcaca70Sjoris if (cf->file_type != CVS_FILE) 3047fcaca70Sjoris fatal("cvs_commit_local: '%s' is not a file", cf->file_path); 3057fcaca70Sjoris 3063901dfa5Sjoris if (cf->file_status != FILE_MODIFIED && 3073901dfa5Sjoris cf->file_status != FILE_ADDED && 3083901dfa5Sjoris cf->file_status != FILE_REMOVED) { 3093901dfa5Sjoris cvs_log(LP_ERR, "skipping bogus file `%s'", cf->file_path); 3103901dfa5Sjoris return; 3113901dfa5Sjoris } 3123901dfa5Sjoris 31318cf7829Sjoris onbranch = 0; 31418cf7829Sjoris nrev = RCS_HEAD_REV; 31518cf7829Sjoris crev = NULL; 31618cf7829Sjoris rrev = NULL; 31718cf7829Sjoris 318eb6d38a6Sjoris if (cf->file_rcs != NULL && cf->file_rcs->rf_branch != NULL) { 319b6bee913Sjoris rcsnum_free(cf->file_rcs->rf_branch); 320b6bee913Sjoris cf->file_rcs->rf_branch = NULL; 321b6bee913Sjoris } 322b6bee913Sjoris 323d77e7b73Sjoris if (cf->file_status == FILE_MODIFIED || 32461e51155Sjoris cf->file_status == FILE_REMOVED || (cf->file_status == FILE_ADDED 325570941ffSjoris && cf->file_rcs != NULL && cf->file_rcs->rf_dead == 1)) { 32618cf7829Sjoris rrev = rcs_head_get(cf->file_rcs); 32718cf7829Sjoris crev = rcs_head_get(cf->file_rcs); 3289af0ab72Stobias if (crev == NULL || rrev == NULL) 3299af0ab72Stobias fatal("RCS head empty or missing in %s\n", 3309af0ab72Stobias cf->file_rcs->rf_path); 33118cf7829Sjoris 33218cf7829Sjoris tag = cvs_directory_tag; 33318cf7829Sjoris if (cf->file_ent != NULL && cf->file_ent->ce_tag != NULL) 33418cf7829Sjoris tag = cf->file_ent->ce_tag; 33518cf7829Sjoris 33618cf7829Sjoris if (tag != NULL) { 33718cf7829Sjoris rcsnum_free(crev); 33818cf7829Sjoris crev = rcs_translate_tag(tag, cf->file_rcs); 33918cf7829Sjoris if (crev == NULL) { 34018cf7829Sjoris fatal("failed to resolve existing tag: %s", 34118cf7829Sjoris tag); 34218cf7829Sjoris } 34318cf7829Sjoris 34418cf7829Sjoris if (RCSNUM_ISBRANCHREV(crev)) { 34518cf7829Sjoris nrev = rcsnum_alloc(); 34618cf7829Sjoris rcsnum_cpy(crev, nrev, 0); 34718cf7829Sjoris rcsnum_inc(nrev); 34818cf7829Sjoris } else if (!RCSNUM_ISBRANCH(crev)) { 34918cf7829Sjoris brev = rcs_sym_getrev(cf->file_rcs, tag); 35018cf7829Sjoris if (brev == NULL) 35118cf7829Sjoris fatal("no more tag?"); 35218cf7829Sjoris nrev = rcsnum_brtorev(brev); 35318cf7829Sjoris if (nrev == NULL) 35418cf7829Sjoris fatal("failed to create branch rev"); 35554de3f21Stobias rcsnum_free(brev); 35618cf7829Sjoris } else { 35718cf7829Sjoris fatal("this isnt suppose to happen, honestly"); 35818cf7829Sjoris } 35918cf7829Sjoris 36018cf7829Sjoris rcsnum_free(rrev); 36118cf7829Sjoris rrev = rcsnum_branch_root(nrev); 36218cf7829Sjoris 36318cf7829Sjoris /* branch stuff was checked in cvs_commit_check_files */ 36418cf7829Sjoris onbranch = 1; 36518cf7829Sjoris } 36618cf7829Sjoris 36718cf7829Sjoris rcsnum_tostr(crev, rbuf, sizeof(rbuf)); 368570941ffSjoris } else { 3696bbad201Sjoris strlcpy(rbuf, "Non-existent", sizeof(rbuf)); 370570941ffSjoris } 3716bbad201Sjoris 37254de3f21Stobias if (rrev != NULL) 37354de3f21Stobias rcsnum_free(rrev); 37443c5228fSjoris isnew = 0; 37561e51155Sjoris if (cf->file_status == FILE_ADDED) { 37643c5228fSjoris isnew = 1; 37761e51155Sjoris rcsflags = RCS_CREATE; 37861e51155Sjoris openflags = O_CREAT | O_TRUNC | O_WRONLY; 37961e51155Sjoris if (cf->file_rcs != NULL) { 380ca2dc546Sniallo if (cf->in_attic == 0) 38161e51155Sjoris cvs_log(LP_ERR, "warning: expected %s " 38261e51155Sjoris "to be in the Attic", cf->file_path); 38361e51155Sjoris 38461e51155Sjoris if (cf->file_rcs->rf_dead == 0) 38561e51155Sjoris cvs_log(LP_ERR, "warning: expected %s " 38661e51155Sjoris "to be dead", cf->file_path); 38761e51155Sjoris 38861e51155Sjoris cvs_get_repository_path(cf->file_wd, repo, MAXPATHLEN); 389c486465dSxsa (void)xsnprintf(rcsfile, MAXPATHLEN, "%s/%s%s", 39061e51155Sjoris repo, cf->file_name, RCS_FILE_EXT); 39161e51155Sjoris 39261e51155Sjoris if (rename(cf->file_rpath, rcsfile) == -1) 39361e51155Sjoris fatal("cvs_commit_local: failed to move %s " 39461e51155Sjoris "outside the Attic: %s", cf->file_path, 39561e51155Sjoris strerror(errno)); 39661e51155Sjoris 39761e51155Sjoris xfree(cf->file_rpath); 39861e51155Sjoris cf->file_rpath = xstrdup(rcsfile); 39961e51155Sjoris 40061e51155Sjoris rcsflags = RCS_READ | RCS_PARSE_FULLY; 40161e51155Sjoris openflags = O_RDONLY; 40261e51155Sjoris rcs_close(cf->file_rcs); 40343c5228fSjoris isnew = 0; 40461e51155Sjoris } 40561e51155Sjoris 40661e51155Sjoris cf->repo_fd = open(cf->file_rpath, openflags); 4076bbad201Sjoris if (cf->repo_fd < 0) 4086bbad201Sjoris fatal("cvs_commit_local: %s", strerror(errno)); 4096bbad201Sjoris 4106bbad201Sjoris cf->file_rcs = rcs_open(cf->file_rpath, cf->repo_fd, 411998f3c00Sotto rcsflags, 0444); 4126bbad201Sjoris if (cf->file_rcs == NULL) 4136bbad201Sjoris fatal("cvs_commit_local: failed to create RCS file " 4146bbad201Sjoris "for %s", cf->file_path); 4152ec286b3Sxsa 4162ec286b3Sxsa commit_desc_set(cf); 4176bbad201Sjoris } 4183ad3fb45Sjoris 4192868ee63Sreyk if (verbosity > 1) { 4203ad3fb45Sjoris cvs_printf("Checking in %s:\n", cf->file_path); 4213ad3fb45Sjoris cvs_printf("%s <- %s\n", cf->file_rpath, cf->file_path); 4223ad3fb45Sjoris cvs_printf("old revision: %s; ", rbuf); 4232868ee63Sreyk } 4243ad3fb45Sjoris 42518cf7829Sjoris if (isnew == 0 && onbranch == 0) 42618cf7829Sjoris d = commit_diff(cf, cf->file_rcs->rf_head, 0); 4273ad3fb45Sjoris 428d77e7b73Sjoris if (cf->file_status == FILE_REMOVED) { 42918cf7829Sjoris b = rcs_rev_getbuf(cf->file_rcs, crev, 0); 430d77e7b73Sjoris if (b == NULL) 43118cf7829Sjoris fatal("cvs_commit_local: failed to get crev"); 43218cf7829Sjoris } else if (onbranch == 1) { 43318cf7829Sjoris b = commit_diff(cf, crev, 1); 4346bbad201Sjoris } else { 435f2a4882aSjoris if ((b = cvs_buf_load_fd(cf->fd, BUF_AUTOEXT)) == NULL) 4363ad3fb45Sjoris fatal("cvs_commit_local: failed to load file"); 437d77e7b73Sjoris } 4383ad3fb45Sjoris 43918cf7829Sjoris if (isnew == 0 && onbranch == 0) { 44018cf7829Sjoris if (rcs_deltatext_set(cf->file_rcs, crev, d) == -1) 4413ad3fb45Sjoris fatal("cvs_commit_local: failed to set delta"); 4426bbad201Sjoris } 4433ad3fb45Sjoris 44418cf7829Sjoris if (rcs_rev_add(cf->file_rcs, nrev, logmsg, -1, NULL) == -1) 4453ad3fb45Sjoris fatal("cvs_commit_local: failed to add new revision"); 4463ad3fb45Sjoris 44718cf7829Sjoris if (nrev == RCS_HEAD_REV) 44818cf7829Sjoris nrev = cf->file_rcs->rf_head; 44918cf7829Sjoris 45018cf7829Sjoris if (rcs_deltatext_set(cf->file_rcs, nrev, b) == -1) 4513ad3fb45Sjoris fatal("cvs_commit_local: failed to set new HEAD delta"); 4523ad3fb45Sjoris 453d77e7b73Sjoris if (cf->file_status == FILE_REMOVED) { 45418cf7829Sjoris if (rcs_state_set(cf->file_rcs, nrev, RCS_STATE_DEAD) == -1) 455d77e7b73Sjoris fatal("cvs_commit_local: failed to set state"); 456d77e7b73Sjoris } 457d77e7b73Sjoris 45856f996a2Sxsa if (cf->file_status == FILE_ADDED && cf->file_ent->ce_opts != NULL) { 459*37fdff3fStobias int cf_kflag; 46056f996a2Sxsa 461*37fdff3fStobias cf_kflag = rcs_kflag_get(cf->file_ent->ce_opts + 2); 462*37fdff3fStobias rcs_kwexp_set(cf->file_rcs, cf_kflag); 46356f996a2Sxsa } 46456f996a2Sxsa 4653ad3fb45Sjoris rcs_write(cf->file_rcs); 4663ad3fb45Sjoris 467d77e7b73Sjoris if (cf->file_status == FILE_REMOVED) { 4682868ee63Sreyk strlcpy(nbuf, "Removed", sizeof(nbuf)); 4696bbad201Sjoris } else if (cf->file_status == FILE_ADDED) { 47061e51155Sjoris if (cf->file_rcs->rf_dead == 1) 4712868ee63Sreyk strlcpy(nbuf, "Initial Revision", sizeof(nbuf)); 47219615a73Sjoris else 47318cf7829Sjoris rcsnum_tostr(nrev, nbuf, sizeof(nbuf)); 474d77e7b73Sjoris } else if (cf->file_status == FILE_MODIFIED) { 47518cf7829Sjoris rcsnum_tostr(nrev, nbuf, sizeof(nbuf)); 476d77e7b73Sjoris } 477d77e7b73Sjoris 4782868ee63Sreyk if (verbosity > 1) 4792868ee63Sreyk cvs_printf("new revision: %s\n", nbuf); 4803ad3fb45Sjoris 4813ad3fb45Sjoris (void)unlink(cf->file_path); 4823ad3fb45Sjoris (void)close(cf->fd); 4833ad3fb45Sjoris cf->fd = -1; 484d77e7b73Sjoris 485d77e7b73Sjoris if (cf->file_status != FILE_REMOVED) { 48618cf7829Sjoris cvs_checkout_file(cf, nrev, NULL, CO_COMMIT); 487d77e7b73Sjoris } else { 488d77e7b73Sjoris entlist = cvs_ent_open(cf->file_wd); 489d77e7b73Sjoris cvs_ent_remove(entlist, cf->file_name); 490d77e7b73Sjoris cvs_ent_close(entlist, ENT_SYNC); 4917fcaca70Sjoris 4927fcaca70Sjoris cvs_get_repository_path(cf->file_wd, repo, MAXPATHLEN); 4937fcaca70Sjoris 494c486465dSxsa (void)xsnprintf(attic, MAXPATHLEN, "%s/%s", 495c486465dSxsa repo, CVS_PATH_ATTIC); 4967fcaca70Sjoris 4977fcaca70Sjoris if (mkdir(attic, 0755) == -1 && errno != EEXIST) 4987fcaca70Sjoris fatal("cvs_commit_local: failed to create Attic"); 4997fcaca70Sjoris 500c486465dSxsa (void)xsnprintf(attic, MAXPATHLEN, "%s/%s/%s%s", repo, 5017fcaca70Sjoris CVS_PATH_ATTIC, cf->file_name, RCS_FILE_EXT); 5027fcaca70Sjoris 5037fcaca70Sjoris if (rename(cf->file_rpath, attic) == -1) 5047fcaca70Sjoris fatal("cvs_commit_local: failed to move %s to Attic", 5057fcaca70Sjoris cf->file_path); 5067fcaca70Sjoris 507408908afSjoris if (cvs_server_active == 1) 508408908afSjoris cvs_server_update_entry("Remove-entry", cf); 509d77e7b73Sjoris } 5103ad3fb45Sjoris 5112868ee63Sreyk if (verbosity > 1) 5123ad3fb45Sjoris cvs_printf("done\n"); 5132868ee63Sreyk else { 5142868ee63Sreyk cvs_log(LP_NOTICE, "checking in '%s'; revision %s -> %s", 5152868ee63Sreyk cf->file_path, rbuf, nbuf); 5162868ee63Sreyk } 5173901dfa5Sjoris 5183901dfa5Sjoris switch (cf->file_status) { 5193901dfa5Sjoris case FILE_MODIFIED: 5203901dfa5Sjoris histtype = CVS_HISTORY_COMMIT_MODIFIED; 5213901dfa5Sjoris break; 5223901dfa5Sjoris case FILE_ADDED: 5233901dfa5Sjoris histtype = CVS_HISTORY_COMMIT_ADDED; 5243901dfa5Sjoris break; 5253901dfa5Sjoris case FILE_REMOVED: 5263901dfa5Sjoris histtype = CVS_HISTORY_COMMIT_REMOVED; 5273901dfa5Sjoris break; 5283901dfa5Sjoris } 5293901dfa5Sjoris 5304649b416Sjoris if (crev != NULL) 5314649b416Sjoris rcsnum_free(crev); 5324649b416Sjoris 5333901dfa5Sjoris cvs_history_add(histtype, cf, NULL); 534213afef1Sjfb } 535c710bc5aSjfb 5364d33f394Sjoris static BUF * 53718cf7829Sjoris commit_diff(struct cvs_file *cf, RCSNUM *rev, int reverse) 53808f90673Sjfb { 53918cf7829Sjoris char *p1, *p2, *p; 540b794e5f5Stobias BUF *b; 541924e91c6Sjoris 542924e91c6Sjoris (void)xasprintf(&p1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir); 54308f90673Sjfb 54419615a73Sjoris if (cf->file_status == FILE_MODIFIED || 54519615a73Sjoris cf->file_status == FILE_ADDED) { 546b794e5f5Stobias if ((b = cvs_buf_load_fd(cf->fd, BUF_AUTOEXT)) == NULL) 54717b2872aStobias fatal("commit_diff: failed to load '%s'", 548d77e7b73Sjoris cf->file_path); 549b794e5f5Stobias cvs_buf_write_stmp(b, p1, NULL); 550b794e5f5Stobias cvs_buf_free(b); 551924e91c6Sjoris } else { 55218cf7829Sjoris rcs_rev_write_stmp(cf->file_rcs, rev, p1, 0); 553924e91c6Sjoris } 5546169aed9Skrapht 5553ad3fb45Sjoris (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir); 55687d368dcStobias rcs_rev_write_stmp(cf->file_rcs, rev, p2, RCS_KWEXP_NONE); 557924e91c6Sjoris 558b794e5f5Stobias if ((b = cvs_buf_alloc(128, BUF_AUTOEXT)) == NULL) 55918cf7829Sjoris fatal("commit_diff: failed to create diff buf"); 56038c61fc2Sjoris 5613ad3fb45Sjoris diff_format = D_RCSDIFF; 56218cf7829Sjoris 56318cf7829Sjoris if (reverse == 1) { 56418cf7829Sjoris p = p1; 56518cf7829Sjoris p1 = p2; 56618cf7829Sjoris p2 = p; 56718cf7829Sjoris } 56818cf7829Sjoris 569b794e5f5Stobias if (cvs_diffreg(p1, p2, b) == D_ERROR) 57018cf7829Sjoris fatal("commit_diff: failed to get RCS patch"); 571740595fcSxsa 5728787a230Sjoris xfree(p1); 5738787a230Sjoris xfree(p2); 5748787a230Sjoris 575b794e5f5Stobias return (b); 5766169aed9Skrapht } 5772ec286b3Sxsa 5782ec286b3Sxsa static void 5792ec286b3Sxsa commit_desc_set(struct cvs_file *cf) 5802ec286b3Sxsa { 5812ec286b3Sxsa BUF *bp; 582c486465dSxsa int fd; 583ba7b4b60Sotto char desc_path[MAXPATHLEN], *desc; 5842ec286b3Sxsa 585c486465dSxsa (void)xsnprintf(desc_path, MAXPATHLEN, "%s/%s%s", 5862ec286b3Sxsa CVS_PATH_CVSDIR, cf->file_name, CVS_DESCR_FILE_EXT); 5872ec286b3Sxsa 588ba7b4b60Sotto if ((fd = open(desc_path, O_RDONLY)) == -1) 5892ec286b3Sxsa return; 5902ec286b3Sxsa 591fe6c66d1Sjoris bp = cvs_buf_load_fd(fd, BUF_AUTOEXT); 5922ec286b3Sxsa cvs_buf_putc(bp, '\0'); 5932ec286b3Sxsa desc = cvs_buf_release(bp); 5942ec286b3Sxsa 5952ec286b3Sxsa rcs_desc_set(cf->file_rcs, desc); 5962ec286b3Sxsa 5972d02866cSjoris (void)close(fd); 5982ec286b3Sxsa (void)cvs_unlink(desc_path); 5992ec286b3Sxsa 6002ec286b3Sxsa xfree(desc); 6012ec286b3Sxsa } 602