[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.37

1.37    ! xsa         1: /*     $OpenBSD: commit.c,v 1.36 2005/05/30 09:52:55 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 *);
                     46: static int cvs_commit_file    (CVSFILE *, void *);
                     47: static int cvs_commit_pre_exec(struct cvsroot *);
                     48:
                     49: struct cvs_cmd cvs_cmd_commit = {
                     50:        CVS_OP_COMMIT, CVS_REQ_CI, "commit",
                     51:        { "ci",  "com" },
                     52:        "Check files into the repository",
                     53:        "[-flR] [-F logfile | -m msg] [-r rev] ...",
                     54:        "F:flm:Rr:",
1.18      joris      55:        NULL,
1.34      jfb        56:        CF_RECURSE | CF_IGNORE | CF_SORT,
                     57:        cvs_commit_init,
                     58:        cvs_commit_pre_exec,
1.18      joris      59:        cvs_commit_file,
                     60:        NULL,
1.34      jfb        61:        NULL,
                     62:        NULL,
                     63:        CVS_CMD_ALLOWSPEC | CVS_CMD_SENDARGS2
1.18      joris      64: };
1.1       jfb        65:
1.18      joris      66: static char *mfile = NULL;
1.35      xsa        67: static char *rev = NULL;
1.32      joris      68: static char **commit_files = NULL;
                     69: static int commit_fcount = 0;
1.6       jfb        70:
1.34      jfb        71: static int
                     72: cvs_commit_init(struct cvs_cmd *cmd, int argc, char **argv, int *arg)
1.1       jfb        73: {
1.18      joris      74:        int ch;
1.3       krapht     75:
1.34      jfb        76:        while ((ch = getopt(argc, argv, cmd->cmd_opts)) != -1) {
1.1       jfb        77:                switch (ch) {
                     78:                case 'F':
                     79:                        mfile = optarg;
                     80:                        break;
                     81:                case 'f':
1.10      jfb        82:                        /* XXX half-implemented */
1.34      jfb        83:                        cmd->file_flags &= ~CF_RECURSE;
1.1       jfb        84:                        break;
                     85:                case 'l':
1.34      jfb        86:                        cmd->file_flags &= ~CF_RECURSE;
1.1       jfb        87:                        break;
                     88:                case 'm':
1.14      jfb        89:                        cvs_msg = strdup(optarg);
                     90:                        if (cvs_msg == NULL) {
                     91:                                cvs_log(LP_ERRNO, "failed to copy message");
1.23      joris      92:                                return (CVS_EX_USAGE);
1.14      jfb        93:                        }
1.1       jfb        94:                        break;
                     95:                case 'R':
1.34      jfb        96:                        cmd->file_flags |= CF_RECURSE;
1.1       jfb        97:                        break;
1.35      xsa        98:                case 'r':
                     99:                        rev = optarg;
                    100:                        break;
1.1       jfb       101:                default:
1.23      joris     102:                        return (CVS_EX_USAGE);
1.1       jfb       103:                }
                    104:        }
                    105:
1.14      jfb       106:        if ((cvs_msg != NULL) && (mfile != NULL)) {
1.1       jfb       107:                cvs_log(LP_ERR, "the -F and -m flags are mutually exclusive");
1.23      joris     108:                return (CVS_EX_USAGE);
1.1       jfb       109:        }
                    110:
1.14      jfb       111:        if ((mfile != NULL) && (cvs_msg = cvs_logmsg_open(mfile)) == NULL)
1.23      joris     112:                return (CVS_EX_DATA);
1.1       jfb       113:
1.18      joris     114:        *arg = optind;
1.32      joris     115:
                    116:        commit_files = (argv + optind);
                    117:        commit_fcount = (argc - optind);
                    118:
1.18      joris     119:        return (0);
                    120: }
1.1       jfb       121:
1.18      joris     122: int
1.34      jfb       123: cvs_commit_pre_exec(struct cvsroot *root)
1.18      joris     124: {
                    125:        struct cvs_flist cl;
                    126:        CVSFILE *cfp;
1.32      joris     127:        CVSFILE *tmp;
                    128:        int flags = CF_RECURSE | CF_IGNORE | CF_SORT;
                    129:
                    130:        SIMPLEQ_INIT(&cl);
                    131:
                    132:        if (commit_fcount != 0) {
                    133:                tmp = cvs_file_getspec(commit_files, commit_fcount,
                    134:                    flags, cvs_commit_prepare, &cl);
                    135:        } else {
                    136:                tmp = cvs_file_get(".", flags, cvs_commit_prepare, &cl);
                    137:        }
1.1       jfb       138:
1.32      joris     139:        if (tmp == NULL)
                    140:                return (CVS_EX_DATA);
                    141:
                    142:        if (SIMPLEQ_EMPTY(&cl)) {
                    143:                cvs_file_free(tmp);
1.11      jfb       144:                return (0);
1.32      joris     145:        }
1.7       jfb       146:
1.17      joris     147:        if (cvs_msg == NULL)
1.32      joris     148:                cvs_msg = cvs_logmsg_get(CVS_FILE_NAME(tmp),
1.14      jfb       149:                    NULL, &cl, NULL);
1.32      joris     150:
                    151:        cvs_file_free(tmp);
1.17      joris     152:
1.26      jfb       153:        while (!SIMPLEQ_EMPTY(&cl)) {
                    154:                cfp = SIMPLEQ_FIRST(&cl);
                    155:                SIMPLEQ_REMOVE_HEAD(&cl, cf_list);
1.17      joris     156:                cvs_file_free(cfp);
1.7       jfb       157:        }
1.17      joris     158:
                    159:        if (cvs_msg == NULL)
1.23      joris     160:                return (CVS_EX_DATA);
1.35      xsa       161:
                    162:        if (root->cr_method != CVS_METHOD_LOCAL) {
1.36      joris     163:                if (cvs_logmsg_send(root, cvs_msg) < 0)
                    164:                        return (CVS_EX_PROTO);
                    165:
1.35      xsa       166:                if (rev != NULL) {
                    167:                        if ((cvs_sendarg(root, "-r", 0) < 0) ||
                    168:                            (cvs_sendarg(root, rev, 0) < 0))
                    169:                                return (CVS_EX_PROTO);
                    170:                }
                    171:        }
1.7       jfb       172:
                    173:        return (0);
                    174: }
                    175:
                    176: /*
                    177:  * cvs_commit_prepare()
                    178:  *
                    179:  * Examine the file <cf> to see if it will be part of the commit, in which
                    180:  * case it gets added to the list passed as second argument.
                    181:  */
                    182: int
                    183: cvs_commit_prepare(CVSFILE *cf, void *arg)
                    184: {
                    185:        CVSFILE *copy;
                    186:        struct cvs_flist *clp = (struct cvs_flist *)arg;
                    187:
1.27      joris     188:        if ((cf->cf_type == DT_REG) && ((cf->cf_cvstat == CVS_FST_MODIFIED) ||
1.29      jfb       189:            (cf->cf_cvstat == CVS_FST_ADDED) ||
                    190:            (cf->cf_cvstat == CVS_FST_REMOVED))) {
1.7       jfb       191:                copy = cvs_file_copy(cf);
                    192:                if (copy == NULL)
1.23      joris     193:                        return (CVS_EX_DATA);
1.7       jfb       194:
1.26      jfb       195:                SIMPLEQ_INSERT_TAIL(clp, copy, cf_list);
1.7       jfb       196:        }
1.3       krapht    197:
1.6       jfb       198:        return (0);
1.3       krapht    199: }
                    200:
                    201:
                    202: /*
1.6       jfb       203:  * cvs_commit_file()
1.3       krapht    204:  *
1.6       jfb       205:  * Commit a single file.
1.3       krapht    206:  */
1.6       jfb       207: int
                    208: cvs_commit_file(CVSFILE *cf, void *arg)
1.3       krapht    209: {
1.24      xsa       210:        int ret, l;
1.6       jfb       211:        char *repo, rcspath[MAXPATHLEN], fpath[MAXPATHLEN];
                    212:        RCSFILE *rf;
                    213:        struct cvsroot *root;
                    214:
1.13      jfb       215:        ret = 0;
1.7       jfb       216:        rf = NULL;
                    217:        repo = NULL;
1.12      jfb       218:        root = CVS_DIR_ROOT(cf);
1.6       jfb       219:
                    220:        if (cf->cf_type == DT_DIR) {
1.13      jfb       221:                if (root->cr_method != CVS_METHOD_LOCAL) {
1.33      joris     222:                        if (cf->cf_cvstat != CVS_FST_UNKNOWN) {
                    223:                                if (cvs_senddir(root, cf) < 0)
                    224:                                        return (CVS_EX_PROTO);
                    225:                        }
1.6       jfb       226:                }
1.3       krapht    227:
1.33      joris     228:                return (0);
1.3       krapht    229:        }
                    230:
1.7       jfb       231:        cvs_file_getpath(cf, fpath, sizeof(fpath));
                    232:
                    233:        if (cf->cf_parent != NULL)
1.26      jfb       234:                repo = cf->cf_parent->cf_repo;
1.3       krapht    235:
1.6       jfb       236:        if ((cf->cf_cvstat == CVS_FST_ADDED) ||
1.29      jfb       237:            (cf->cf_cvstat == CVS_FST_MODIFIED) ||
                    238:            (cf->cf_cvstat == CVS_FST_REMOVED)) {
1.16      joris     239:                if (root->cr_method != CVS_METHOD_LOCAL) {
1.26      jfb       240:                        if (cvs_sendentry(root, cf) < 0) {
1.23      joris     241:                                return (CVS_EX_PROTO);
1.16      joris     242:                        }
1.31      joris     243:
                    244:                        /* if it's removed, don't bother sending a
                    245:                         * Modified request together with the file its
                    246:                         * contents.
                    247:                         */
                    248:                        if (cf->cf_cvstat == CVS_FST_REMOVED)
                    249:                                return (0);
1.16      joris     250:
                    251:                        if (cvs_sendreq(root, CVS_REQ_MODIFIED,
                    252:                            CVS_FILE_NAME(cf)) < 0) {
1.23      joris     253:                                return (CVS_EX_PROTO);
1.16      joris     254:                        }
                    255:
                    256:                        if (cvs_sendfile(root, fpath) < 0) {
1.23      joris     257:                                return (CVS_EX_PROTO);
1.16      joris     258:                        }
1.5       krapht    259:                }
                    260:        }
1.3       krapht    261:
1.24      xsa       262:        l = snprintf(rcspath, sizeof(rcspath), "%s/%s/%s%s",
1.6       jfb       263:            root->cr_dir, repo, fpath, RCS_FILE_EXT);
1.24      xsa       264:        if (l == -1 || l >= (int)sizeof(rcspath)) {
                    265:                errno = ENAMETOOLONG;
                    266:                cvs_log(LP_ERRNO, "%s", rcspath);
1.33      joris     267:                return (CVS_EX_DATA);
1.24      xsa       268:        }
1.3       krapht    269:
1.6       jfb       270:        return (0);
1.1       jfb       271: }