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

Annotation of src/usr.bin/cvs/tag.c, Revision 1.61

1.61    ! tobias      1: /*     $OpenBSD: tag.c,v 1.60 2008/01/10 11:20:29 tobias Exp $ */
1.1       jfb         2: /*
1.45      xsa         3:  * Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org>
1.1       jfb         4:  *
1.45      xsa         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.45      xsa         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.60      tobias     18: #include <errno.h>
                     19: #include <string.h>
1.55      otto       20: #include <unistd.h>
1.1       jfb        21:
                     22: #include "cvs.h"
1.50      xsa        23: #include "remote.h"
1.1       jfb        24:
1.52      xsa        25: #define T_CHECK_UPTODATE       0x01
                     26: #define T_DELETE               0x02
                     27: #define T_FORCE_MOVE           0x04
1.59      tobias     28: #define T_BRANCH               0x08
1.52      xsa        29:
1.45      xsa        30: void   cvs_tag_local(struct cvs_file *);
                     31:
                     32: static int tag_del(struct cvs_file *);
                     33: static int tag_add(struct cvs_file *);
                     34:
1.52      xsa        35: static int      runflags = 0;
1.45      xsa        36: static char    *tag = NULL;
                     37: static char    *tag_date = NULL;
                     38: static char    *tag_name = NULL;
                     39: static char    *tag_oldname = NULL;
1.7       joris      40:
1.60      tobias     41: struct cvs_cmd cvs_cmd_rtag = {
                     42:        CVS_OP_RTAG, 0, "rtag",
                     43:        { "rt", "rfreeze" },
                     44:        "Add a symbolic tag to a module",
                     45:        "[-bcdFflR] [-D date | -r rev] tag modules ...",
                     46:        "bcD:dFflRr:",
                     47:        NULL,
                     48:        cvs_tag
                     49: };
                     50:
1.17      jfb        51: struct cvs_cmd cvs_cmd_tag = {
1.47      joris      52:        CVS_OP_TAG, 0, "tag",
1.17      jfb        53:        { "ta", "freeze" },
                     54:        "Add a symbolic tag to checked out version of files",
1.40      xsa        55:        "[-bcdFflR] [-D date | -r rev] tag [file ...]",
1.17      jfb        56:        "bcD:dFflRr:",
                     57:        NULL,
1.45      xsa        58:        cvs_tag
1.17      jfb        59: };
                     60:
1.45      xsa        61: int
                     62: cvs_tag(int argc, char **argv)
1.1       jfb        63: {
1.60      tobias     64:        int ch, flags, i;
1.49      reyk       65:        char *arg = ".";
1.45      xsa        66:        struct cvs_recursion cr;
1.1       jfb        67:
1.45      xsa        68:        flags = CR_RECURSE_DIRS;
1.1       jfb        69:
1.45      xsa        70:        while ((ch = getopt(argc, argv, cvs_cmd_tag.cmd_opts)) != -1) {
1.1       jfb        71:                switch (ch) {
1.59      tobias     72:                case 'b':
                     73:                        runflags |= T_BRANCH;
                     74:                        break;
1.52      xsa        75:                case 'c':
                     76:                        runflags |= T_CHECK_UPTODATE;
                     77:                        break;
1.45      xsa        78:                case 'D':
                     79:                        tag_date = optarg;
1.1       jfb        80:                        break;
                     81:                case 'd':
1.52      xsa        82:                        runflags |= T_DELETE;
1.3       jfb        83:                        break;
1.46      xsa        84:                case 'F':
1.52      xsa        85:                        runflags |= T_FORCE_MOVE;
1.46      xsa        86:                        break;
1.1       jfb        87:                case 'l':
1.45      xsa        88:                        flags &= ~CR_RECURSE_DIRS;
1.17      jfb        89:                        break;
                     90:                case 'R':
1.1       jfb        91:                        break;
                     92:                case 'r':
1.14      jfb        93:                        tag_oldname = optarg;
1.1       jfb        94:                        break;
                     95:                default:
1.45      xsa        96:                        fatal("%s", cvs_cmd_tag.cmd_synopsis);
1.1       jfb        97:                }
                     98:        }
                     99:
                    100:        argc -= optind;
                    101:        argv += optind;
                    102:
1.60      tobias    103:        if (cvs_cmdop == CVS_OP_RTAG) {
                    104:                if (argc < 2)
                    105:                        fatal("%s", cvs_cmd_rtag.cmd_synopsis);
                    106:
                    107:                 for (i = 1; i < argc; i++)
                    108:                         if (argv[i][0] == '/')
                    109:                                 fatal("Absolute path name is invalid: %s",
                    110:                                     argv[i]);
                    111:         } else if (cvs_cmdop == CVS_OP_TAG && argc == 0)
1.45      xsa       112:                fatal("%s", cvs_cmd_tag.cmd_synopsis);
                    113:
                    114:        tag_name = argv[0];
                    115:        argc--;
                    116:        argv++;
1.15      jfb       117:
1.38      xsa       118:        if (!rcs_sym_check(tag_name))
                    119:                fatal("tag `%s' must not contain the characters `%s'",
1.15      jfb       120:                    tag_name, RCS_SYM_INVALCHAR);
1.1       jfb       121:
1.45      xsa       122:        if (tag_oldname != NULL) {
1.52      xsa       123:                if (runflags & T_DELETE)
1.45      xsa       124:                        tag_oldname = NULL;
                    125:                else
                    126:                        tag = tag_oldname;
                    127:        }
                    128:
                    129:        if (tag_date != NULL) {
1.52      xsa       130:                if (runflags & T_DELETE)
1.45      xsa       131:                        tag_date = NULL;
                    132:                else
                    133:                        tag = tag_date;
                    134:        }
                    135:
                    136:        if (tag_oldname != NULL && tag_date != NULL)
                    137:                fatal("-r and -D options are mutually exclusive");
                    138:
                    139:        cr.enterdir = NULL;
                    140:        cr.leavedir = NULL;
1.50      xsa       141:
                    142:        if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
1.53      joris     143:                cvs_client_connect_to_server();
1.50      xsa       144:                cr.fileproc = cvs_client_sendfile;
                    145:
1.59      tobias    146:                if (runflags & T_BRANCH)
                    147:                        cvs_client_send_request("Argument -b");
                    148:
1.52      xsa       149:                if (runflags & T_CHECK_UPTODATE)
                    150:                        cvs_client_send_request("Argument -c");
                    151:
                    152:                if (runflags & T_DELETE)
1.50      xsa       153:                        cvs_client_send_request("Argument -d");
                    154:
1.52      xsa       155:                if (runflags & T_FORCE_MOVE)
1.50      xsa       156:                        cvs_client_send_request("Argument -F");
                    157:
                    158:                if (!(flags & CR_RECURSE_DIRS))
                    159:                        cvs_client_send_request("Argument -l");
                    160:
                    161:                if (tag_oldname != NULL)
                    162:                        cvs_client_send_request("Argument -r%s", tag_oldname);
                    163:
                    164:                cvs_client_send_request("Argument %s", tag_name);
                    165:        } else {
1.60      tobias    166:                if (cvs_cmdop == CVS_OP_RTAG &&
                    167:                    chdir(current_cvsroot->cr_dir) == -1)
                    168:                        fatal("cvs_tag: %s", strerror(errno));
                    169:
1.50      xsa       170:                cr.fileproc = cvs_tag_local;
                    171:        }
                    172:
1.45      xsa       173:        cr.flags = flags;
1.1       jfb       174:
1.60      tobias    175:        if (cvs_cmdop == CVS_OP_TAG ||
1.61    ! tobias    176:            current_cvsroot->cr_method == CVS_METHOD_LOCAL) {
1.60      tobias    177:                if (argc > 0)
                    178:                        cvs_file_run(argc, argv, &cr);
                    179:                else
                    180:                        cvs_file_run(1, &arg, &cr);
                    181:        }
1.50      xsa       182:
                    183:        if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
                    184:                cvs_client_send_files(argv, argc);
                    185:                cvs_client_senddir(".");
1.60      tobias    186:
                    187:                cvs_client_send_request((cvs_cmdop == CVS_OP_RTAG) ?
                    188:                    "rtag" : "tag");
                    189:
1.50      xsa       190:                cvs_client_get_responses();
                    191:        }
1.3       jfb       192:
1.7       joris     193:        return (0);
                    194: }
                    195:
1.45      xsa       196: void
                    197: cvs_tag_local(struct cvs_file *cf)
1.7       joris     198: {
1.45      xsa       199:        cvs_log(LP_TRACE, "cvs_tag_local(%s)", cf->file_path);
1.17      jfb       200:
1.60      tobias    201:        cvs_file_classify(cf, tag);
                    202:
1.45      xsa       203:        if (cf->file_type == CVS_DIR) {
                    204:                if (verbosity > 1) {
                    205:                        cvs_log(LP_NOTICE, "%s %s",
1.52      xsa       206:                            (runflags & T_DELETE) ? "Untagging" : "Tagging",
1.45      xsa       207:                            cf->file_path);
                    208:                }
                    209:                return;
                    210:        }
1.40      xsa       211:
1.52      xsa       212:        if (runflags & T_CHECK_UPTODATE) {
                    213:                if (cf->file_status != FILE_UPTODATE &&
                    214:                    cf->file_status != FILE_CHECKOUT &&
                    215:                    cf->file_status != FILE_PATCH) {
                    216:                        cvs_log(LP_NOTICE,
                    217:                            "%s is locally modified", cf->file_path);
                    218:                        return;
                    219:                }
                    220:        }
                    221:
                    222:        if (runflags & T_DELETE) {
1.45      xsa       223:                if (tag_del(cf) == 0) {
                    224:                        if (verbosity > 0)
                    225:                                cvs_printf("D %s\n", cf->file_path);
1.21      xsa       226:
1.45      xsa       227:                        rcs_write(cf->file_rcs);
                    228:                }
                    229:                return;
                    230:        }
1.21      xsa       231:
1.45      xsa       232:        switch(cf->file_status) {
                    233:        case FILE_ADDED:
                    234:                if (verbosity > 1) {
                    235:                        cvs_log(LP_NOTICE,
                    236:                            "couldn't tag added but un-commited file `%s'",
                    237:                            cf->file_path);
1.35      joris     238:                }
1.45      xsa       239:                return;
                    240:        case FILE_REMOVED:
                    241:                if (verbosity > 1) {
                    242:                        cvs_log(LP_NOTICE,
                    243:                            "skipping removed but un-commited file `%s'",
                    244:                            cf->file_path);
                    245:                }
                    246:                return;
                    247:        case FILE_CHECKOUT:
                    248:        case FILE_MODIFIED:
1.60      tobias    249:        case FILE_PATCH:
1.45      xsa       250:        case FILE_UPTODATE:
                    251:                if (tag_add(cf) == 0) {
                    252:                        if (verbosity > 0)
                    253:                                cvs_printf("T %s\n", cf->file_path);
1.1       jfb       254:
1.45      xsa       255:                        rcs_write(cf->file_rcs);
1.56      joris     256:                        cvs_history_add(CVS_HISTORY_TAG, cf, tag_name);
1.35      joris     257:                }
1.45      xsa       258:                break;
                    259:        default:
                    260:                break;
1.1       jfb       261:        }
                    262: }
                    263:
1.14      jfb       264: static int
1.45      xsa       265: tag_del(struct cvs_file *cf)
1.1       jfb       266: {
1.45      xsa       267:        if (cf->file_rcs == NULL)
                    268:                return (-1);
1.1       jfb       269:
1.45      xsa       270:        if (cvs_noexec == 1)
1.35      joris     271:                return (0);
1.1       jfb       272:
1.45      xsa       273:        return (rcs_sym_remove(cf->file_rcs, tag_name));
1.14      jfb       274: }
                    275:
                    276: static int
1.45      xsa       277: tag_add(struct cvs_file *cf)
1.14      jfb       278: {
1.57      xsa       279:        char revbuf[CVS_REV_BUFSZ], trevbuf[CVS_REV_BUFSZ];
1.60      tobias    280:        RCSNUM *srev, *trev;
1.46      xsa       281:        struct rcs_sym *sym;
1.14      jfb       282:
1.45      xsa       283:        if (cf->file_rcs == NULL) {
1.23      xsa       284:                if (verbosity > 1)
1.45      xsa       285:                        cvs_log(LP_NOTICE, "cannot find revision "
                    286:                            "control file for `%s'", cf->file_name);
                    287:                return (-1);
1.14      jfb       288:        }
1.1       jfb       289:
1.60      tobias    290:        if (cvs_cmdop == CVS_OP_TAG) {
                    291:                if (cf->file_ent == NULL)
                    292:                        return (-1);
                    293:                srev = cf->file_ent->ce_rev;
                    294:        } else
                    295:                srev = cf->file_rcsrev;
                    296:
1.45      xsa       297:        if (cvs_noexec == 1)
1.32      xsa       298:                return (0);
1.1       jfb       299:
1.60      tobias    300:        (void)rcsnum_tostr(srev, revbuf, sizeof(revbuf));
1.58      tobias    301:
1.46      xsa       302:        trev = rcs_sym_getrev(cf->file_rcs, tag_name);
                    303:        if (trev != NULL) {
1.60      tobias    304:                if (rcsnum_cmp(srev, trev, 0) == 0) {
1.46      xsa       305:                        rcsnum_free(trev);
                    306:                        return (-1);
                    307:                }
                    308:                (void)rcsnum_tostr(trev, trevbuf, sizeof(trevbuf));
                    309:
1.52      xsa       310:                if (!(runflags & T_FORCE_MOVE)) {
1.46      xsa       311:                        cvs_printf("W %s : %s ", cf->file_path, tag_name);
                    312:                        cvs_printf("already exists on version %s", trevbuf);
                    313:                        cvs_printf(" : NOT MOVING tag to version %s\n", revbuf);
                    314:
                    315:                        return (-1);
1.52      xsa       316:                } else if (runflags & T_FORCE_MOVE) {
1.46      xsa       317:                        sym = rcs_sym_get(cf->file_rcs, tag_name);
1.60      tobias    318:                        rcsnum_cpy(srev, sym->rs_num, 0);
1.46      xsa       319:                        cf->file_rcs->rf_flags &= ~RCS_SYNCED;
                    320:
                    321:                        return (0);
                    322:                }
                    323:        }
                    324:
1.59      tobias    325:        if (runflags & T_BRANCH) {
1.60      tobias    326:                if ((trev = rcsnum_new_branch(srev)) == NULL)
1.59      tobias    327:                        fatal("Cannot create a new branch");
                    328:
                    329:                for (;;) {
                    330:                        TAILQ_FOREACH(sym, &(cf->file_rcs->rf_symbols), rs_list)
                    331:                                if (!rcsnum_cmp(sym->rs_num, trev, 0))
                    332:                                        break;
                    333:
                    334:                        if (sym != NULL) {
                    335:                                if (rcsnum_inc(trev) == NULL)
                    336:                                        fatal("New revision too high");
                    337:                                if (rcsnum_inc(trev) == NULL)
                    338:                                        fatal("New revision too high");
                    339:                        } else
                    340:                                break;
                    341:                }
                    342:        } else {
                    343:                trev = rcsnum_alloc();
1.60      tobias    344:                rcsnum_cpy(srev, trev, 0);
1.59      tobias    345:        }
                    346:
                    347:        if (rcs_sym_add(cf->file_rcs, tag_name, trev) == -1) {
1.45      xsa       348:                if (rcs_errno != RCS_ERR_DUPENT) {
                    349:                        cvs_log(LP_NOTICE,
                    350:                            "failed to set tag %s to revision %s in %s",
                    351:                            tag_name, revbuf, cf->file_rcs->rf_path);
1.39      xsa       352:                }
1.59      tobias    353:                rcsnum_free(trev);
1.45      xsa       354:                return (-1);
1.1       jfb       355:        }
1.17      jfb       356:
1.59      tobias    357:        rcsnum_free(trev);
1.14      jfb       358:        return (0);
1.1       jfb       359: }