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

Annotation of src/usr.bin/cvs/status.c, Revision 1.55

1.55    ! xsa         1: /*     $OpenBSD: status.c,v 1.54 2006/01/30 17:58:47 xsa Exp $ */
1.1       jfb         2: /*
                      3:  * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
1.41      xsa         4:  * Copyright (c) 2005 Xavier Santolaria <xsa@openbsd.org>
1.4       tedu        5:  * All rights reserved.
1.1       jfb         6:  *
1.4       tedu        7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
1.1       jfb        10:  *
1.4       tedu       11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
1.1       jfb        13:  * 2. The name of the author may not be used to endorse or promote products
1.4       tedu       14:  *    derived from this software without specific prior written permission.
1.1       jfb        15:  *
                     16:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                     17:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                     18:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
                     19:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     20:  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     21:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     22:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     23:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     24:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
1.4       tedu       25:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.1       jfb        26:  */
                     27:
1.51      xsa        28: #include "includes.h"
1.1       jfb        29:
                     30: #include "cvs.h"
                     31: #include "log.h"
                     32: #include "proto.h"
                     33:
                     34:
1.15      jfb        35: #define CVS_STATUS_SEP \
                     36:  "==================================================================="
                     37:
1.31      xsa        38: /* Keep this sorted as it is now. See file.h for status values. */
1.1       jfb        39: const char *cvs_statstr[] = {
                     40:        "Unknown",
1.15      jfb        41:        "Up-to-date",
1.1       jfb        42:        "Locally Modified",
1.29      xsa        43:        "Locally Added",
                     44:        "Locally Removed",
                     45:        "Unresolved Conflict",
1.1       jfb        46:        "Patched",
1.16      jfb        47:        "Needs Checkout",
1.1       jfb        48: };
1.33      xsa        49:
1.1       jfb        50:
1.41      xsa        51: static int cvs_status_init     (struct cvs_cmd *, int, char **, int *);
                     52: static int cvs_status_remote   (CVSFILE *, void *);
                     53: static int cvs_status_local    (CVSFILE *, void *);
1.22      jfb        54: static int cvs_status_pre_exec (struct cvsroot *);
                     55:
                     56: struct cvs_cmd cvs_cmd_status = {
                     57:        CVS_OP_STATUS, CVS_REQ_STATUS, "status",
                     58:        { "st", "stat" },
                     59:        "Display status information on checked out files",
                     60:        "[-lRv]",
                     61:        "lRv",
                     62:        NULL,
                     63:        CF_SORT | CF_IGNORE | CF_RECURSE,
                     64:        cvs_status_init,
                     65:        cvs_status_pre_exec,
1.20      jfb        66:        cvs_status_remote,
1.22      jfb        67:        cvs_status_local,
                     68:        NULL,
                     69:        NULL,
1.10      joris      70:        CVS_CMD_ALLOWSPEC | CVS_CMD_SENDDIR | CVS_CMD_SENDARGS2
                     71: };
1.1       jfb        72:
1.10      joris      73: static int verbose = 0;
1.1       jfb        74:
1.22      jfb        75: static int
                     76: cvs_status_init(struct cvs_cmd *cmd, int argc, char **argv, int *arg)
1.1       jfb        77: {
1.10      joris      78:        int ch;
1.1       jfb        79:
1.22      jfb        80:        while ((ch = getopt(argc, argv, cmd->cmd_opts)) != -1) {
1.1       jfb        81:                switch (ch) {
1.7       jfb        82:                case 'l':
1.22      jfb        83:                        cmd->file_flags &= ~CF_RECURSE;
1.7       jfb        84:                        break;
                     85:                case 'R':
1.22      jfb        86:                        cmd->file_flags |= CF_RECURSE;
1.7       jfb        87:                        break;
                     88:                case 'v':
                     89:                        verbose = 1;
                     90:                        break;
1.1       jfb        91:                default:
1.14      joris      92:                        return (CVS_EX_USAGE);
1.1       jfb        93:                }
                     94:        }
                     95:
1.10      joris      96:        *arg = optind;
                     97:        return (0);
                     98: }
1.1       jfb        99:
1.22      jfb       100: static int
                    101: cvs_status_pre_exec(struct cvsroot *root)
1.10      joris     102: {
1.26      xsa       103:        if (root->cr_method != CVS_METHOD_LOCAL) {
1.50      joris     104:                if (verbose == 1)
                    105:                        cvs_sendarg(root, "-v", 0);
1.26      xsa       106:        }
                    107:
1.1       jfb       108:        return (0);
                    109: }
                    110:
                    111: /*
1.20      jfb       112:  * cvs_status_remote()
1.1       jfb       113:  *
                    114:  * Get the status of a single file.
                    115:  */
1.22      jfb       116: static int
1.20      jfb       117: cvs_status_remote(CVSFILE *cfp, void *arg)
1.1       jfb       118: {
1.44      xsa       119:        char fpath[MAXPATHLEN];
1.1       jfb       120:        struct cvsroot *root;
                    121:
1.5       jfb       122:        root = CVS_DIR_ROOT(cfp);
1.1       jfb       123:
1.6       jfb       124:        if (cfp->cf_type == DT_DIR) {
1.15      jfb       125:                if (cfp->cf_cvstat == CVS_FST_UNKNOWN)
1.50      joris     126:                        cvs_sendreq(root, CVS_REQ_QUESTIONABLE, cfp->cf_name);
1.15      jfb       127:                else
1.50      joris     128:                        cvs_senddir(root, cfp);
                    129:                return (0);
1.6       jfb       130:        }
1.1       jfb       131:
1.5       jfb       132:        cvs_file_getpath(cfp, fpath, sizeof(fpath));
1.1       jfb       133:
1.50      joris     134:        cvs_sendentry(root, cfp);
1.15      jfb       135:
                    136:        switch (cfp->cf_cvstat) {
                    137:        case CVS_FST_UNKNOWN:
1.50      joris     138:                cvs_sendreq(root, CVS_REQ_QUESTIONABLE, cfp->cf_name);
1.15      jfb       139:                break;
                    140:        case CVS_FST_UPTODATE:
1.50      joris     141:                cvs_sendreq(root, CVS_REQ_UNCHANGED, cfp->cf_name);
1.15      jfb       142:                break;
1.17      joris     143:        case CVS_FST_ADDED:
1.15      jfb       144:        case CVS_FST_MODIFIED:
1.50      joris     145:                cvs_sendreq(root, CVS_REQ_MODIFIED, cfp->cf_name);
                    146:                cvs_sendfile(root, fpath);
1.55    ! xsa       147:                break;
1.15      jfb       148:        default:
                    149:                break;
                    150:        }
                    151:
1.50      joris     152:        return (0);
1.15      jfb       153: }
                    154:
1.22      jfb       155: static int
                    156: cvs_status_local(CVSFILE *cf, void *arg)
1.15      jfb       157: {
1.35      xsa       158:        size_t n;
                    159:        char buf[MAXNAMLEN], fpath[MAXPATHLEN], rcspath[MAXPATHLEN];
                    160:        char numbuf[64], timebuf[32];
1.15      jfb       161:        RCSFILE *rf;
1.41      xsa       162:        struct rcs_sym *sym;
1.15      jfb       163:
1.33      xsa       164:        if (cf->cf_type == DT_DIR) {
                    165:                if (verbosity > 1)
1.43      xsa       166:                        cvs_log(LP_NOTICE, "Examining %s", cf->cf_name);
1.15      jfb       167:                return (0);
1.33      xsa       168:        }
1.15      jfb       169:
1.22      jfb       170:        cvs_file_getpath(cf, fpath, sizeof(fpath));
1.49      xsa       171:        cvs_rcs_getpath(cf, rcspath, sizeof(rcspath));
1.1       jfb       172:
1.46      joris     173:        rf = NULL;
1.37      xsa       174:        if (cf->cf_cvstat != CVS_FST_UNKNOWN &&
                    175:            cf->cf_cvstat != CVS_FST_ADDED) {
1.53      xsa       176:                if ((rf = rcs_open(rcspath, RCS_READ)) == NULL)
                    177:                        fatal("cvs_status_local: rcs_open `%s': %s", rcspath,
1.54      xsa       178:                            rcs_errstr(rcs_errno));
1.30      xsa       179:        }
1.5       jfb       180:
1.16      jfb       181:        buf[0] = '\0';
1.47      xsa       182:
                    183:        if (cf->cf_cvstat == CVS_FST_UNKNOWN)
                    184:                cvs_log(LP_WARN, "nothing known about %s", cf->cf_name);
                    185:
1.30      xsa       186:        if (cf->cf_cvstat == CVS_FST_LOST || cf->cf_cvstat == CVS_FST_UNKNOWN)
1.27      xsa       187:                strlcpy(buf, "no file ", sizeof(buf));
1.22      jfb       188:        strlcat(buf, cf->cf_name, sizeof(buf));
1.16      jfb       189:
1.28      xsa       190:        cvs_printf(CVS_STATUS_SEP "\nFile: %-17s\tStatus: %s\n\n",
1.22      jfb       191:            buf, cvs_statstr[cf->cf_cvstat]);
1.16      jfb       192:
1.22      jfb       193:        if (cf->cf_cvstat == CVS_FST_UNKNOWN) {
1.52      xsa       194:                strlcpy(buf, "No entry for ", sizeof(buf));
                    195:                strlcat(buf, cf->cf_name, sizeof(buf));
1.37      xsa       196:        } else if (cf->cf_cvstat == CVS_FST_ADDED) {
1.52      xsa       197:                strlcpy(buf, "New file!", sizeof(buf));
1.16      jfb       198:        } else {
1.37      xsa       199:                rcsnum_tostr(cf->cf_lrev, numbuf, sizeof(numbuf));
1.52      xsa       200:                strlcpy(buf, numbuf, sizeof(buf));
1.35      xsa       201:
                    202:                /* Display etime in local mode only. */
                    203:                if (cvs_cmdop != CVS_OP_SERVER) {
                    204:                        strlcat(buf, "\t", sizeof(buf));
                    205:
                    206:                        ctime_r(&(cf->cf_etime), timebuf);
                    207:                        n = strlen(timebuf);
                    208:                        if ((n > 0) && (timebuf[n - 1] == '\n'))
1.36      xsa       209:                                timebuf[--n] = '\0';
1.35      xsa       210:
                    211:                        strlcat(buf, timebuf, sizeof(buf));
                    212:                }
1.16      jfb       213:        }
1.32      joris     214:
1.28      xsa       215:        cvs_printf("   Working revision:\t%s\n", buf);
1.30      xsa       216:
1.37      xsa       217:        if (cf->cf_cvstat == CVS_FST_UNKNOWN ||
                    218:            cf->cf_cvstat == CVS_FST_ADDED) {
1.52      xsa       219:                strlcpy(buf, "No revision control file", sizeof(buf));
1.30      xsa       220:        } else {
1.52      xsa       221:                strlcpy(buf, rcsnum_tostr(rf->rf_head, numbuf, sizeof(numbuf)),
                    222:                    sizeof(buf));
                    223:                strlcat(buf, "\t", sizeof(buf));
                    224:                strlcat(buf, rcspath, sizeof(buf));
1.30      xsa       225:        }
                    226:
                    227:        cvs_printf("   Repository revision:\t%s\n", buf);
                    228:
                    229:        /* If the file is unknown, no other output is needed after this. */
1.37      xsa       230:        if (cf->cf_cvstat == CVS_FST_UNKNOWN) {
                    231:                cvs_printf("\n");
1.30      xsa       232:                return (0);
1.37      xsa       233:        }
1.30      xsa       234:
1.38      xsa       235:        if (cf->cf_tag != NULL)
                    236:                cvs_printf("   Sticky Tag:\t\t%s\n", cf->cf_tag);
                    237:        else if (verbosity > 0)
                    238:                cvs_printf("   Sticky Tag:\t\t(none)\n");
                    239:
                    240:        /* XXX */
                    241:        if (verbosity > 0)
                    242:                cvs_printf("   Sticky Date:\t\t%s\n", "(none)");
                    243:
                    244:        if (cf->cf_opts != NULL)
                    245:                cvs_printf("   Sticky Options:\t%s\n", cf->cf_opts);
                    246:        else if (verbosity > 0)
                    247:                cvs_printf("   Sticky Options:\t(none)\n");
1.41      xsa       248:
1.48      xsa       249:        if (verbose == 1) {
1.41      xsa       250:                cvs_printf("\n");
                    251:                cvs_printf("   Existing Tags:\n");
                    252:
                    253:                if (!TAILQ_EMPTY(&(rf->rf_symbols))) {
                    254:                        TAILQ_FOREACH(sym, &(rf->rf_symbols), rs_list) {
                    255:                                rcsnum_tostr(sym->rs_num, numbuf,
                    256:                                    sizeof(numbuf));
                    257:
                    258:                                cvs_printf("\t%-25s\t(%s: %s)\n",
1.45      xsa       259:                                    sym->rs_name,
1.41      xsa       260:                                    RCSNUM_ISBRANCH(sym->rs_num) ? "branch" :
                    261:                                    "revision", numbuf);
                    262:                        }
                    263:                } else {
                    264:                        cvs_printf("\tNo Tags Exist\n");
                    265:                }
                    266:        }
1.15      jfb       267:
1.25      xsa       268:        cvs_printf("\n");
1.46      joris     269:
                    270:        if (rf != NULL)
                    271:                rcs_close(rf);
1.15      jfb       272:
                    273:        return (0);
1.1       jfb       274: }