[BACK]Return to commit.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cvs

Annotation of src/usr.bin/cvs/commit.c, Revision 1.43

1.43    ! joris       1: /*     $OpenBSD: commit.c,v 1.42 2005/07/22 16:27:29 joris Exp $       */
1.1       jfb         2: /*
                      3:  * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
1.9       tedu        4:  * All rights reserved.
1.1       jfb         5:  *
1.9       tedu        6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
1.1       jfb         9:  *
1.9       tedu       10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
1.1       jfb        12:  * 2. The name of the author may not be used to endorse or promote products
1.9       tedu       13:  *    derived from this software without specific prior written permission.
1.1       jfb        14:  *
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                     16:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                     17:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
                     18:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     19:  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     20:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     21:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     22:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     23:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
1.9       tedu       24:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.1       jfb        25:  */
                     26:
                     27: #include <sys/types.h>
1.6       jfb        28: #include <sys/queue.h>
1.1       jfb        29: #include <sys/stat.h>
                     30:
                     31: #include <errno.h>
1.37      xsa        32: #include <fcntl.h>
1.1       jfb        33: #include <stdio.h>
                     34: #include <stdlib.h>
1.37      xsa        35: #include <string.h>
1.1       jfb        36: #include <unistd.h>
                     37:
1.37      xsa        38: #include "buf.h"
1.1       jfb        39: #include "cvs.h"
                     40: #include "log.h"
1.2       jfb        41: #include "proto.h"
1.1       jfb        42:
                     43:
1.34      jfb        44: static int cvs_commit_init    (struct cvs_cmd *, int, char **, int *);
                     45: static int cvs_commit_prepare (CVSFILE *, void *);
1.39      xsa        46: static int cvs_commit_remote  (CVSFILE *, void *);
                     47: static int cvs_commit_local   (CVSFILE *, void *);
1.34      jfb        48: static int cvs_commit_pre_exec(struct cvsroot *);
                     49:
                     50: struct cvs_cmd cvs_cmd_commit = {
                     51:        CVS_OP_COMMIT, CVS_REQ_CI, "commit",
                     52:        { "ci",  "com" },
                     53:        "Check files into the repository",
                     54:        "[-flR] [-F logfile | -m msg] [-r rev] ...",
                     55:        "F:flm:Rr:",
1.18      joris      56:        NULL,
1.34      jfb        57:        CF_RECURSE | CF_IGNORE | CF_SORT,
                     58:        cvs_commit_init,
                     59:        cvs_commit_pre_exec,
1.39      xsa        60:        cvs_commit_remote,
                     61:        cvs_commit_local,
1.34      jfb        62:        NULL,
                     63:        NULL,
1.41      joris      64:        CVS_CMD_SENDDIR | CVS_CMD_ALLOWSPEC | CVS_CMD_SENDARGS2
1.18      joris      65: };
1.1       jfb        66:
1.18      joris      67: static char *mfile = NULL;
1.35      xsa        68: static char *rev = NULL;
1.32      joris      69: static char **commit_files = NULL;
                     70: static int commit_fcount = 0;
1.43    ! joris      71: static int wantedstatus = 0;
1.6       jfb        72:
1.34      jfb        73: static int
                     74: cvs_commit_init(struct cvs_cmd *cmd, int argc, char **argv, int *arg)
1.1       jfb        75: {
1.18      joris      76:        int ch;
1.3       krapht     77:
1.34      jfb        78:        while ((ch = getopt(argc, argv, cmd->cmd_opts)) != -1) {
1.1       jfb        79:                switch (ch) {
                     80:                case 'F':
                     81:                        mfile = optarg;
                     82:                        break;
                     83:                case 'f':
1.10      jfb        84:                        /* XXX half-implemented */
1.34      jfb        85:                        cmd->file_flags &= ~CF_RECURSE;
1.1       jfb        86:                        break;
                     87:                case 'l':
1.34      jfb        88:                        cmd->file_flags &= ~CF_RECURSE;
1.1       jfb        89:                        break;
                     90:                case 'm':
1.14      jfb        91:                        cvs_msg = strdup(optarg);
                     92:                        if (cvs_msg == NULL) {
                     93:                                cvs_log(LP_ERRNO, "failed to copy message");
1.23      joris      94:                                return (CVS_EX_USAGE);
1.14      jfb        95:                        }
1.1       jfb        96:                        break;
                     97:                case 'R':
1.34      jfb        98:                        cmd->file_flags |= CF_RECURSE;
1.1       jfb        99:                        break;
1.35      xsa       100:                case 'r':
                    101:                        rev = optarg;
                    102:                        break;
1.1       jfb       103:                default:
1.23      joris     104:                        return (CVS_EX_USAGE);
1.1       jfb       105:                }
                    106:        }
                    107:
1.14      jfb       108:        if ((cvs_msg != NULL) && (mfile != NULL)) {
1.1       jfb       109:                cvs_log(LP_ERR, "the -F and -m flags are mutually exclusive");
1.23      joris     110:                return (CVS_EX_USAGE);
1.1       jfb       111:        }
                    112:
1.14      jfb       113:        if ((mfile != NULL) && (cvs_msg = cvs_logmsg_open(mfile)) == NULL)
1.23      joris     114:                return (CVS_EX_DATA);
1.1       jfb       115:
1.18      joris     116:        *arg = optind;
1.32      joris     117:
                    118:        commit_files = (argv + optind);
                    119:        commit_fcount = (argc - optind);
                    120:
1.18      joris     121:        return (0);
                    122: }
1.1       jfb       123:
1.18      joris     124: int
1.34      jfb       125: cvs_commit_pre_exec(struct cvsroot *root)
1.18      joris     126: {
                    127:        CVSFILE *cfp;
1.32      joris     128:        CVSFILE *tmp;
1.43    ! joris     129:        int i, flags = CF_RECURSE | CF_IGNORE | CF_SORT;
        !           130:        struct cvs_flist added, modified, removed, *cl[3];
        !           131:        int stattype[] = { CVS_FST_ADDED, CVS_FST_MODIFIED, CVS_FST_REMOVED };
        !           132:
        !           133:        SIMPLEQ_INIT(&added);
        !           134:        SIMPLEQ_INIT(&modified);
        !           135:        SIMPLEQ_INIT(&removed);
        !           136:
        !           137:        cl[0] = &added;
        !           138:        cl[1] = &modified;
        !           139:        cl[2] = &removed;
        !           140:
        !           141:        /*
        !           142:         * Obtain the file lists for the logmessage.
        !           143:         */
        !           144:        tmp = NULL;
        !           145:        for (i = 0; i < 3; i++) {
        !           146:                if (tmp != NULL)
        !           147:                        cvs_file_free(tmp);
        !           148:
        !           149:                wantedstatus = stattype[i];
        !           150:
        !           151:                if (commit_fcount != 0) {
        !           152:                        tmp = cvs_file_getspec(commit_files, commit_fcount,
        !           153:                            flags, cvs_commit_prepare, cl[i]);
        !           154:                } else {
        !           155:                        tmp = cvs_file_get(".", flags, cvs_commit_prepare,
        !           156:                            cl[i]);
        !           157:                }
1.32      joris     158:
1.43    ! joris     159:                if (tmp == NULL)
        !           160:                        return (CVS_EX_DATA);
1.32      joris     161:        }
1.1       jfb       162:
1.43    ! joris     163:        /*
        !           164:         * If we didn't catch any file, don't call the editor.
        !           165:         */
        !           166:        if (SIMPLEQ_EMPTY(&added) && SIMPLEQ_EMPTY(&modified) &&
        !           167:            SIMPLEQ_EMPTY(&removed)) {
1.32      joris     168:                cvs_file_free(tmp);
1.11      jfb       169:                return (0);
1.32      joris     170:        }
1.7       jfb       171:
1.43    ! joris     172:        /*
        !           173:         * Fetch the log message for real, with all the files.
        !           174:         */
1.17      joris     175:        if (cvs_msg == NULL)
1.43    ! joris     176:                cvs_msg = cvs_logmsg_get(tmp->cf_name, &added, &modified,
        !           177:                    &removed);
1.32      joris     178:
                    179:        cvs_file_free(tmp);
1.17      joris     180:
1.43    ! joris     181:        /* free the file lists */
        !           182:        for (i = 0; i < 3; i++) {
        !           183:                while (!SIMPLEQ_EMPTY(cl[i])) {
        !           184:                        cfp = SIMPLEQ_FIRST(cl[i]);
        !           185:                        SIMPLEQ_REMOVE_HEAD(cl[i], cf_list);
        !           186:                        cvs_file_free(cfp);
        !           187:                }
1.7       jfb       188:        }
1.17      joris     189:
                    190:        if (cvs_msg == NULL)
1.23      joris     191:                return (CVS_EX_DATA);
1.35      xsa       192:
                    193:        if (root->cr_method != CVS_METHOD_LOCAL) {
1.36      joris     194:                if (cvs_logmsg_send(root, cvs_msg) < 0)
                    195:                        return (CVS_EX_PROTO);
                    196:
1.35      xsa       197:                if (rev != NULL) {
                    198:                        if ((cvs_sendarg(root, "-r", 0) < 0) ||
                    199:                            (cvs_sendarg(root, rev, 0) < 0))
                    200:                                return (CVS_EX_PROTO);
                    201:                }
                    202:        }
1.7       jfb       203:
                    204:        return (0);
                    205: }
                    206:
                    207: /*
                    208:  * cvs_commit_prepare()
                    209:  *
                    210:  * Examine the file <cf> to see if it will be part of the commit, in which
                    211:  * case it gets added to the list passed as second argument.
                    212:  */
                    213: int
                    214: cvs_commit_prepare(CVSFILE *cf, void *arg)
                    215: {
                    216:        CVSFILE *copy;
                    217:        struct cvs_flist *clp = (struct cvs_flist *)arg;
                    218:
1.43    ! joris     219:        if ((cf->cf_type == DT_REG) && (cf->cf_cvstat == wantedstatus)) {
1.7       jfb       220:                copy = cvs_file_copy(cf);
                    221:                if (copy == NULL)
1.23      joris     222:                        return (CVS_EX_DATA);
1.7       jfb       223:
1.26      jfb       224:                SIMPLEQ_INSERT_TAIL(clp, copy, cf_list);
1.7       jfb       225:        }
1.3       krapht    226:
1.6       jfb       227:        return (0);
1.3       krapht    228: }
                    229:
                    230:
                    231: /*
1.39      xsa       232:  * cvs_commit_remote()
1.3       krapht    233:  *
1.6       jfb       234:  * Commit a single file.
1.3       krapht    235:  */
1.6       jfb       236: int
1.39      xsa       237: cvs_commit_remote(CVSFILE *cf, void *arg)
1.3       krapht    238: {
1.39      xsa       239:        int ret;
                    240:        char *repo, fpath[MAXPATHLEN];
1.6       jfb       241:        RCSFILE *rf;
                    242:        struct cvsroot *root;
                    243:
1.13      jfb       244:        ret = 0;
1.7       jfb       245:        rf = NULL;
                    246:        repo = NULL;
1.12      jfb       247:        root = CVS_DIR_ROOT(cf);
1.6       jfb       248:
                    249:        if (cf->cf_type == DT_DIR) {
1.39      xsa       250:                if (cf->cf_cvstat != CVS_FST_UNKNOWN) {
                    251:                        if (cvs_senddir(root, cf) < 0)
                    252:                                return (CVS_EX_PROTO);
1.6       jfb       253:                }
1.33      joris     254:                return (0);
1.3       krapht    255:        }
                    256:
1.7       jfb       257:        cvs_file_getpath(cf, fpath, sizeof(fpath));
                    258:
                    259:        if (cf->cf_parent != NULL)
1.26      jfb       260:                repo = cf->cf_parent->cf_repo;
1.3       krapht    261:
1.6       jfb       262:        if ((cf->cf_cvstat == CVS_FST_ADDED) ||
1.29      jfb       263:            (cf->cf_cvstat == CVS_FST_MODIFIED) ||
                    264:            (cf->cf_cvstat == CVS_FST_REMOVED)) {
1.39      xsa       265:                if (cvs_sendentry(root, cf) < 0) {
                    266:                        return (CVS_EX_PROTO);
                    267:                }
1.31      joris     268:
1.39      xsa       269:                /* if it's removed, don't bother sending a
                    270:                 * Modified request together with the file its
                    271:                 * contents.
                    272:                 */
                    273:                if (cf->cf_cvstat == CVS_FST_REMOVED)
                    274:                        return (0);
1.16      joris     275:
1.42      joris     276:                if (cvs_sendreq(root, CVS_REQ_MODIFIED, cf->cf_name) < 0)
1.39      xsa       277:                        return (CVS_EX_PROTO);
1.16      joris     278:
1.39      xsa       279:                if (cvs_sendfile(root, fpath) < 0) {
                    280:                        return (CVS_EX_PROTO);
1.5       krapht    281:                }
                    282:        }
1.3       krapht    283:
1.39      xsa       284:        return (0);
                    285: }
                    286:
                    287: static int
                    288: cvs_commit_local(CVSFILE *cf, void *arg)
                    289: {
                    290:        char fpath[MAXPATHLEN], rcspath[MAXPATHLEN];
                    291:
                    292:        if (cf->cf_type == DT_DIR) {
                    293:                if (verbosity > 1)
                    294:                        cvs_log(LP_INFO, "Examining %s", cf->cf_name);
                    295:                return (0);
                    296:        }
                    297:
                    298:        cvs_file_getpath(cf, fpath, sizeof(fpath));
                    299:
1.40      xsa       300:        if (cvs_rcs_getpath(cf, rcspath, sizeof(rcspath)) == NULL)
1.33      joris     301:                return (CVS_EX_DATA);
1.3       krapht    302:
1.6       jfb       303:        return (0);
1.1       jfb       304: }