1*c1fe09b4Sjoris /* $OpenBSD: commit.c,v 1.59 2006/05/27 15:17:42 joris Exp $ */ 208f90673Sjfb /* 33ad3fb45Sjoris * Copyright (c) 2006 Joris Vink <joris@openbsd.org> 408f90673Sjfb * 53ad3fb45Sjoris * Permission to use, copy, modify, and distribute this software for any 63ad3fb45Sjoris * purpose with or without fee is hereby granted, provided that the above 73ad3fb45Sjoris * copyright notice and this permission notice appear in all copies. 808f90673Sjfb * 93ad3fb45Sjoris * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 103ad3fb45Sjoris * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 113ad3fb45Sjoris * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 123ad3fb45Sjoris * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 133ad3fb45Sjoris * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 143ad3fb45Sjoris * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 153ad3fb45Sjoris * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1608f90673Sjfb */ 1708f90673Sjfb 18ac41f80cSxsa #include "includes.h" 1908f90673Sjfb 2008f90673Sjfb #include "cvs.h" 213ad3fb45Sjoris #include "diff.h" 2208f90673Sjfb #include "log.h" 23dc6a6879Sjfb #include "proto.h" 2408f90673Sjfb 253ad3fb45Sjoris int cvs_commit(int, char **); 263ad3fb45Sjoris void cvs_commit_local(struct cvs_file *); 273ad3fb45Sjoris void cvs_commit_check_conflicts(struct cvs_file *); 2808f90673Sjfb 293ad3fb45Sjoris static char *commit_diff_file(struct cvs_file *); 303ad3fb45Sjoris 313ad3fb45Sjoris struct cvs_flisthead files_affected; 323ad3fb45Sjoris int conflicts_found; 333ad3fb45Sjoris char *logmsg; 3408f90673Sjfb 35e4276007Sjfb struct cvs_cmd cvs_cmd_commit = { 36e4276007Sjfb CVS_OP_COMMIT, CVS_REQ_CI, "commit", 37e4276007Sjfb { "ci", "com" }, 38e4276007Sjfb "Check files into the repository", 39e4276007Sjfb "[-flR] [-F logfile | -m msg] [-r rev] ...", 40e4276007Sjfb "F:flm:Rr:", 4116cfc147Sjoris NULL, 423ad3fb45Sjoris cvs_commit 4316cfc147Sjoris }; 4408f90673Sjfb 453ad3fb45Sjoris int 463ad3fb45Sjoris cvs_commit(int argc, char **argv) 4708f90673Sjfb { 4816cfc147Sjoris int ch; 493ad3fb45Sjoris char *arg = "."; 501890abdaSjoris int flags; 513ad3fb45Sjoris struct cvs_recursion cr; 5208f90673Sjfb 531890abdaSjoris flags = CR_RECURSE_DIRS; 541890abdaSjoris 553ad3fb45Sjoris while ((ch = getopt(argc, argv, cvs_cmd_commit.cmd_opts)) != -1) { 5608f90673Sjfb switch (ch) { 5708f90673Sjfb case 'f': 583ad3fb45Sjoris break; 593ad3fb45Sjoris case 'F': 6008f90673Sjfb break; 6108f90673Sjfb case 'l': 621890abdaSjoris flags &= ~CR_RECURSE_DIRS; 6308f90673Sjfb break; 6408f90673Sjfb case 'm': 653ad3fb45Sjoris logmsg = xstrdup(optarg); 6608f90673Sjfb break; 678d550b2eSxsa case 'r': 683ad3fb45Sjoris break; 693ad3fb45Sjoris case 'R': 708d550b2eSxsa break; 7108f90673Sjfb default: 723ad3fb45Sjoris fatal("%s", cvs_cmd_commit.cmd_synopsis); 7308f90673Sjfb } 7408f90673Sjfb } 7508f90673Sjfb 763ad3fb45Sjoris argc -= optind; 773ad3fb45Sjoris argv += optind; 7808f90673Sjfb 793ad3fb45Sjoris if (logmsg == NULL) 803ad3fb45Sjoris fatal("please use -m to specify a log message for now"); 8108f90673Sjfb 823ad3fb45Sjoris TAILQ_INIT(&files_affected); 833ad3fb45Sjoris conflicts_found = 0; 84ef6e385cSjoris 853ad3fb45Sjoris cr.enterdir = NULL; 863ad3fb45Sjoris cr.leavedir = NULL; 873ad3fb45Sjoris cr.local = cvs_commit_check_conflicts; 883ad3fb45Sjoris cr.remote = NULL; 891890abdaSjoris cr.flags = flags; 903ad3fb45Sjoris 913ad3fb45Sjoris if (argc > 0) 923ad3fb45Sjoris cvs_file_run(argc, argv, &cr); 933ad3fb45Sjoris else 943ad3fb45Sjoris cvs_file_run(1, &arg, &cr); 953ad3fb45Sjoris 963ad3fb45Sjoris if (conflicts_found != 0) 973ad3fb45Sjoris fatal("%d conflicts found, please correct these first", 983ad3fb45Sjoris conflicts_found); 993ad3fb45Sjoris 1003ad3fb45Sjoris cr.local = cvs_commit_local; 1013ad3fb45Sjoris cvs_file_walklist(&files_affected, &cr); 1023ad3fb45Sjoris cvs_file_freelist(&files_affected); 103ef6e385cSjoris 10416cfc147Sjoris return (0); 105c710bc5aSjfb } 106c710bc5aSjfb 1073ad3fb45Sjoris void 1083ad3fb45Sjoris cvs_commit_check_conflicts(struct cvs_file *cf) 10916cfc147Sjoris { 1103ad3fb45Sjoris cvs_log(LP_TRACE, "cvs_commit_check_conflicts(%s)", cf->file_path); 1115805c4b0Sjoris 112a4c69cc6Sjoris /* 1133ad3fb45Sjoris * cvs_file_classify makes the noise for us 1143ad3fb45Sjoris * XXX - we want that? 115a4c69cc6Sjoris */ 1163ad3fb45Sjoris cvs_file_classify(cf); 1173ad3fb45Sjoris 118*c1fe09b4Sjoris if (cf->file_type == CVS_DIR) { 119*c1fe09b4Sjoris if (verbosity > 1) 120*c1fe09b4Sjoris cvs_log(LP_NOTICE, "Examining %s", cf->file_path); 121*c1fe09b4Sjoris return; 122*c1fe09b4Sjoris } 123*c1fe09b4Sjoris 1243ad3fb45Sjoris if (cf->file_status == FILE_CONFLICT || 1253ad3fb45Sjoris cf->file_status == FILE_LOST || 1263ad3fb45Sjoris cf->file_status == FILE_UNLINK) 1273ad3fb45Sjoris conflicts_found++; 1283ad3fb45Sjoris 1292a132f99Sjoris if (cf->file_status == FILE_MERGE || 1302a132f99Sjoris cf->file_status == FILE_PATCH) { 1312a132f99Sjoris cvs_log(LP_ERR, "conflict: %s is not up-to-date", 1322a132f99Sjoris cf->file_path); 1332a132f99Sjoris conflicts_found++; 1342a132f99Sjoris } 1352a132f99Sjoris 1363ad3fb45Sjoris if (cf->file_status == FILE_ADDED || 1373ad3fb45Sjoris cf->file_status == FILE_REMOVED || 1383ad3fb45Sjoris cf->file_status == FILE_MODIFIED) 1393ad3fb45Sjoris cvs_file_get(cf->file_path, &files_affected); 140ef6e385cSjoris } 141ef6e385cSjoris 1423ad3fb45Sjoris void 1433ad3fb45Sjoris cvs_commit_local(struct cvs_file *cf) 144213afef1Sjfb { 1453ad3fb45Sjoris BUF *b; 1463ad3fb45Sjoris char *d, *f, rbuf[16]; 147d77e7b73Sjoris CVSENTRIES *entlist; 148213afef1Sjfb 1493ad3fb45Sjoris cvs_log(LP_TRACE, "cvs_commit_local(%s)", cf->file_path); 1503ad3fb45Sjoris cvs_file_classify(cf); 151213afef1Sjfb 152d77e7b73Sjoris if (cf->file_status == FILE_MODIFIED || 153d77e7b73Sjoris cf->file_status == FILE_REMOVED) 1543ad3fb45Sjoris rcsnum_tostr(cf->file_rcs->rf_head, rbuf, sizeof(rbuf)); 1553ad3fb45Sjoris 1563ad3fb45Sjoris cvs_printf("Checking in %s:\n", cf->file_path); 1573ad3fb45Sjoris cvs_printf("%s <- %s\n", cf->file_rpath, cf->file_path); 1583ad3fb45Sjoris cvs_printf("old revision: %s; ", rbuf); 1593ad3fb45Sjoris 1603ad3fb45Sjoris d = commit_diff_file(cf); 1613ad3fb45Sjoris 162d77e7b73Sjoris if (cf->file_status == FILE_REMOVED) { 163d77e7b73Sjoris b = rcs_getrev(cf->file_rcs, cf->file_rcs->rf_head); 164d77e7b73Sjoris if (b == NULL) 165d77e7b73Sjoris fatal("cvs_commit_local: failed to get HEAD"); 166d77e7b73Sjoris } else if (cf->file_status == FILE_MODIFIED) { 1673ad3fb45Sjoris if ((b = cvs_buf_load(cf->file_path, BUF_AUTOEXT)) == NULL) 1683ad3fb45Sjoris fatal("cvs_commit_local: failed to load file"); 169d77e7b73Sjoris } 1703ad3fb45Sjoris 1713ad3fb45Sjoris cvs_buf_putc(b, '\0'); 1723ad3fb45Sjoris f = cvs_buf_release(b); 1733ad3fb45Sjoris 1743ad3fb45Sjoris if (rcs_deltatext_set(cf->file_rcs, cf->file_rcs->rf_head, d) == -1) 1753ad3fb45Sjoris fatal("cvs_commit_local: failed to set delta"); 1763ad3fb45Sjoris 1773ad3fb45Sjoris if (rcs_rev_add(cf->file_rcs, RCS_HEAD_REV, logmsg, -1, NULL) == -1) 1783ad3fb45Sjoris fatal("cvs_commit_local: failed to add new revision"); 1793ad3fb45Sjoris 1803ad3fb45Sjoris if (rcs_deltatext_set(cf->file_rcs, cf->file_rcs->rf_head, f) == -1) 1813ad3fb45Sjoris fatal("cvs_commit_local: failed to set new HEAD delta"); 1823ad3fb45Sjoris 1833ad3fb45Sjoris xfree(f); 1843ad3fb45Sjoris xfree(d); 1853ad3fb45Sjoris 186d77e7b73Sjoris if (cf->file_status == FILE_REMOVED) { 187d77e7b73Sjoris if (rcs_state_set(cf->file_rcs, 188d77e7b73Sjoris cf->file_rcs->rf_head, RCS_STATE_DEAD) == -1) 189d77e7b73Sjoris fatal("cvs_commit_local: failed to set state"); 190d77e7b73Sjoris } 191d77e7b73Sjoris 1923ad3fb45Sjoris rcs_write(cf->file_rcs); 1933ad3fb45Sjoris 194d77e7b73Sjoris if (cf->file_status == FILE_REMOVED) { 195d77e7b73Sjoris strlcpy(rbuf, "Removed", sizeof(rbuf)); 196d77e7b73Sjoris } else if (cf->file_status == FILE_MODIFIED) { 1973ad3fb45Sjoris rcsnum_tostr(cf->file_rcs->rf_head, rbuf, sizeof(rbuf)); 198d77e7b73Sjoris } 199d77e7b73Sjoris 2003ad3fb45Sjoris cvs_printf("new revision: %s\n", rbuf); 2013ad3fb45Sjoris 2023ad3fb45Sjoris (void)unlink(cf->file_path); 2033ad3fb45Sjoris (void)close(cf->fd); 2043ad3fb45Sjoris cf->fd = -1; 205d77e7b73Sjoris 206d77e7b73Sjoris if (cf->file_status != FILE_REMOVED) { 2073ad3fb45Sjoris cvs_checkout_file(cf, cf->file_rcs->rf_head, 0); 208d77e7b73Sjoris } else { 209d77e7b73Sjoris entlist = cvs_ent_open(cf->file_wd); 210d77e7b73Sjoris cvs_ent_remove(entlist, cf->file_name); 211d77e7b73Sjoris cvs_ent_close(entlist, ENT_SYNC); 212d77e7b73Sjoris } 2133ad3fb45Sjoris 2143ad3fb45Sjoris cvs_printf("done\n"); 2153ad3fb45Sjoris 216213afef1Sjfb } 217c710bc5aSjfb 2183ad3fb45Sjoris static char * 2193ad3fb45Sjoris commit_diff_file(struct cvs_file *cf) 22008f90673Sjfb { 2213ad3fb45Sjoris char*delta, *p1, *p2; 2223ad3fb45Sjoris BUF *b1, *b2, *b3; 22308f90673Sjfb 224d77e7b73Sjoris if (cf->file_status == FILE_MODIFIED) { 2253ad3fb45Sjoris if ((b1 = cvs_buf_load(cf->file_path, BUF_AUTOEXT)) == NULL) 226d77e7b73Sjoris fatal("commit_diff_file: failed to load '%s'", 227d77e7b73Sjoris cf->file_path); 228d77e7b73Sjoris } else if (cf->file_status == FILE_REMOVED) { 229d77e7b73Sjoris b1 = rcs_getrev(cf->file_rcs, cf->file_rcs->rf_head); 230d77e7b73Sjoris if (b1 == NULL) 231d77e7b73Sjoris fatal("commit_diff_file: failed to load HEAD"); 232d77e7b73Sjoris b1 = rcs_kwexp_buf(b1, cf->file_rcs, cf->file_rcs->rf_head); 233d77e7b73Sjoris } 234c710bc5aSjfb 2353ad3fb45Sjoris if ((b2 = rcs_getrev(cf->file_rcs, cf->file_rcs->rf_head)) == NULL) 2363ad3fb45Sjoris fatal("commit_diff_file: failed to load HEAD for '%s'", 2373ad3fb45Sjoris cf->file_path); 238c710bc5aSjfb 2393ad3fb45Sjoris if ((b3 = cvs_buf_alloc(128, BUF_AUTOEXT)) == NULL) 2403ad3fb45Sjoris fatal("commit_diff_file: failed to create diff buf"); 241213afef1Sjfb 2423ad3fb45Sjoris (void)xasprintf(&p1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir); 2433ad3fb45Sjoris cvs_buf_write_stmp(b1, p1, 0600, NULL); 2443ad3fb45Sjoris cvs_buf_free(b1); 2456169aed9Skrapht 2463ad3fb45Sjoris (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir); 2473ad3fb45Sjoris cvs_buf_write_stmp(b2, p2, 0600, NULL); 2483ad3fb45Sjoris cvs_buf_free(b2); 24938c61fc2Sjoris 2503ad3fb45Sjoris diff_format = D_RCSDIFF; 2513ad3fb45Sjoris if (cvs_diffreg(p1, p2, b3) == D_ERROR) 2523ad3fb45Sjoris fatal("commit_diff_file: failed to get RCS patch"); 253740595fcSxsa 2543ad3fb45Sjoris cvs_buf_putc(b3, '\0'); 2553ad3fb45Sjoris delta = cvs_buf_release(b3); 2563ad3fb45Sjoris return (delta); 2576169aed9Skrapht } 258