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

Annotation of src/usr.bin/cvs/entries.c, Revision 1.57

1.57    ! joris       1: /*     $OpenBSD$       */
1.1       jfb         2: /*
1.57    ! joris       3:  * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
1.1       jfb         4:  *
1.57    ! joris       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.
        !             8:  *
        !             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.54      xsa        18: #include "includes.h"
1.1       jfb        19:
1.34      xsa        20: #include "cvs.h"
1.1       jfb        21: #include "log.h"
                     22:
1.42      xsa        23: #define CVS_ENTRIES_NFIELDS    6
                     24: #define CVS_ENTRIES_DELIM      '/'
1.1       jfb        25:
1.57    ! joris      26: static struct cvs_ent_line *ent_get_line(CVSENTRIES *, const char *);
1.1       jfb        27:
1.42      xsa        28: CVSENTRIES *
1.57    ! joris      29: cvs_ent_open(const char *dir)
1.1       jfb        30: {
1.57    ! joris      31:        FILE *fp;
1.1       jfb        32:        size_t len;
1.57    ! joris      33:        CVSENTRIES *ep;
        !            34:        char *p, buf[MAXPATHLEN];
1.1       jfb        35:        struct cvs_ent *ent;
1.57    ! joris      36:        struct cvs_ent_line *line;
1.36      xsa        37:
1.57    ! joris      38:        ep = (CVSENTRIES *)xmalloc(sizeof(*ep));
        !            39:        memset(ep, 0, sizeof(*ep));
1.52      joris      40:
1.57    ! joris      41:        cvs_path_cat(dir, CVS_PATH_ENTRIES, buf, sizeof(buf));
        !            42:        ep->cef_path = xstrdup(buf);
1.8       jfb        43:
1.57    ! joris      44:        cvs_path_cat(dir, CVS_PATH_BACKUPENTRIES, buf, sizeof(buf));
        !            45:        ep->cef_bpath = xstrdup(buf);
1.3       jfb        46:
1.57    ! joris      47:        cvs_path_cat(dir, CVS_PATH_LOGENTRIES, buf, sizeof(buf));
        !            48:        ep->cef_lpath = xstrdup(buf);
1.1       jfb        49:
1.4       jfb        50:        TAILQ_INIT(&(ep->cef_ent));
1.3       jfb        51:
1.57    ! joris      52:        if ((fp = fopen(ep->cef_path, "r")) != NULL) {
        !            53:                while (fgets(buf, sizeof(buf), fp)) {
        !            54:                        len = strlen(buf);
        !            55:                        if (len > 0 && buf[len - 1] == '\n')
        !            56:                                buf[len - 1] = '\0';
        !            57:
        !            58:                        if (buf[0] == 'D' && buf[1] == '\0')
        !            59:                                break;
        !            60:
        !            61:                        line = (struct cvs_ent_line *)xmalloc(sizeof(*line));
        !            62:                        line->buf = xstrdup(buf);
        !            63:                        TAILQ_INSERT_TAIL(&(ep->cef_ent), line, entries_list);
        !            64:                }
1.52      joris      65:
1.25      jfb        66:                (void)fclose(fp);
1.12      jfb        67:        }
1.1       jfb        68:
1.57    ! joris      69:        if ((fp = fopen(ep->cef_lpath, "r")) != NULL) {
        !            70:                while (fgets(buf, sizeof(buf), fp)) {
        !            71:                        len = strlen(buf);
        !            72:                        if (len > 0 && buf[strlen(buf) - 1] == '\n')
        !            73:                                buf[strlen(buf) - 1] = '\0';
        !            74:
        !            75:                        p = &buf[1];
        !            76:
        !            77:                        if (buf[0] == 'A') {
        !            78:                                line = xmalloc(sizeof(*line));
        !            79:                                line->buf = xstrdup(p);
        !            80:                                TAILQ_INSERT_TAIL(&(ep->cef_ent), line,
        !            81:                                    entries_list);
        !            82:                        } else if (buf[0] == 'R') {
        !            83:                                ent = cvs_ent_parse(p);
        !            84:                                line = ent_get_line(ep, ent->ce_name);
        !            85:                                if (line != NULL)
        !            86:                                        TAILQ_REMOVE(&(ep->cef_ent), line,
        !            87:                                            entries_list);
        !            88:                                cvs_ent_free(ent);
        !            89:                        }
        !            90:                }
1.4       jfb        91:
1.52      joris      92:                (void)fclose(fp);
                     93:        }
1.12      jfb        94:
1.1       jfb        95:        return (ep);
                     96: }
                     97:
1.57    ! joris      98: struct cvs_ent *
        !            99: cvs_ent_parse(const char *entry)
1.1       jfb       100: {
1.57    ! joris     101:        int i;
1.5       jfb       102:        struct cvs_ent *ent;
1.57    ! joris     103:        char *fields[CVS_ENTRIES_NFIELDS], *buf, *sp, *dp;
1.5       jfb       104:
1.57    ! joris     105:        buf = xstrdup(entry);
        !           106:        sp = buf;
        !           107:        i = 0;
        !           108:        do {
        !           109:                dp = strchr(sp, CVS_ENTRIES_DELIM);
        !           110:                if (dp != NULL)
        !           111:                        *(dp++) = '\0';
        !           112:                fields[i++] = sp;
        !           113:                sp = dp;
        !           114:        } while (dp != NULL && i < CVS_ENTRIES_NFIELDS);
1.8       jfb       115:
1.57    ! joris     116:        if (i < CVS_ENTRIES_NFIELDS)
        !           117:                fatal("missing fields in entry line '%s'", entry);
1.5       jfb       118:
1.57    ! joris     119:        ent = (struct cvs_ent *)xmalloc(sizeof(*ent));
        !           120:        ent->ce_buf = buf;
1.52      joris     121:
1.57    ! joris     122:        if (*fields[0] == '\0')
        !           123:                ent->ce_type = CVS_ENT_FILE;
        !           124:        else if (*fields[0] == 'D')
        !           125:                ent->ce_type = CVS_ENT_DIR;
        !           126:        else
        !           127:                ent->ce_type = CVS_ENT_NONE;
        !           128:
        !           129:        ent->ce_status = CVS_ENT_REG;
        !           130:        ent->ce_name = fields[1];
        !           131:        ent->ce_rev = NULL;
1.5       jfb       132:
1.57    ! joris     133:        if (ent->ce_type == CVS_ENT_FILE) {
        !           134:                if (*fields[2] == '-') {
        !           135:                        ent->ce_status = CVS_ENT_REMOVED;
        !           136:                        sp = fields[2] + 1;
        !           137:                } else {
        !           138:                        sp = fields[2];
        !           139:                        if (fields[2][0] == '0' && fields[2][1] == '\0')
        !           140:                                ent->ce_status = CVS_ENT_ADDED;
        !           141:                }
1.1       jfb       142:
1.57    ! joris     143:                if ((ent->ce_rev = rcsnum_parse(sp)) == NULL)
        !           144:                        fatal("failed to parse entry revision '%s'", entry);
1.1       jfb       145:
1.57    ! joris     146:                if (strcmp(fields[3], CVS_DATE_DUMMY) == 0 ||
        !           147:                    strncmp(fields[3], "Initial ", 8) == 0 ||
        !           148:                    strncmp(fields[3], "Result of merge", 15) == 0)
        !           149:                        ent->ce_mtime = CVS_DATE_DMSEC;
        !           150:                else
        !           151:                        ent->ce_mtime = cvs_date_parse(fields[3]);
1.3       jfb       152:        }
1.1       jfb       153:
1.57    ! joris     154:        ent->ce_conflict = fields[3];
        !           155:        if ((dp = strchr(ent->ce_conflict, '+')) != NULL)
        !           156:                *dp = '\0';
        !           157:        else
        !           158:                ent->ce_conflict = NULL;
1.1       jfb       159:
1.57    ! joris     160:        if (strcmp(fields[4], ""))
        !           161:                ent->ce_opts = fields[4];
        !           162:        else
        !           163:                ent->ce_opts = NULL;
1.8       jfb       164:
1.57    ! joris     165:        if (strcmp(fields[5], ""))
        !           166:                ent->ce_tag = fields[5];
        !           167:        else
        !           168:                ent->ce_tag = NULL;
1.3       jfb       169:
1.57    ! joris     170:        return (ent);
1.3       jfb       171: }
                    172:
1.57    ! joris     173: struct cvs_ent *
        !           174: cvs_ent_get(CVSENTRIES *ep, const char *name)
1.3       jfb       175: {
                    176:        struct cvs_ent *ent;
1.57    ! joris     177:        struct cvs_ent_line *l;
1.3       jfb       178:
1.57    ! joris     179:        l = ent_get_line(ep, name);
        !           180:        if (l == NULL)
        !           181:                return (NULL);
1.3       jfb       182:
1.57    ! joris     183:        ent = cvs_ent_parse(l->buf);
        !           184:        return (ent);
        !           185: }
1.3       jfb       186:
1.57    ! joris     187: int
        !           188: cvs_ent_exists(CVSENTRIES *ep, const char *name)
        !           189: {
        !           190:        struct cvs_ent_line *l;
1.1       jfb       191:
1.57    ! joris     192:        l = ent_get_line(ep, name);
        !           193:        if (l == NULL)
        !           194:                return (0);
1.8       jfb       195:
1.57    ! joris     196:        return (1);
1.1       jfb       197: }
                    198:
1.57    ! joris     199: void
        !           200: cvs_ent_close(CVSENTRIES *ep, int writefile)
1.9       jfb       201: {
1.57    ! joris     202:        FILE *fp;
        !           203:        struct cvs_ent_line *l;
1.44      xsa       204:
1.57    ! joris     205:        if (writefile) {
        !           206:                if ((fp = fopen(ep->cef_bpath, "w")) == NULL)
        !           207:                        fatal("cvs_ent_close: failed to write %s",
        !           208:                            ep->cef_path);
        !           209:        }
1.16      jfb       210:
1.57    ! joris     211:        while ((l = TAILQ_FIRST(&(ep->cef_ent))) != NULL) {
        !           212:                if (writefile) {
        !           213:                        fputs(l->buf, fp);
        !           214:                        fputc('\n', fp);
1.51      joris     215:                }
1.57    ! joris     216:
        !           217:                TAILQ_REMOVE(&(ep->cef_ent), l, entries_list);
        !           218:                xfree(l->buf);
        !           219:                xfree(l);
1.22      jfb       220:        }
1.9       jfb       221:
1.57    ! joris     222:        if (writefile) {
        !           223:                fputc('D', fp);
        !           224:                (void)fclose(fp);
        !           225:
        !           226:                if (rename(ep->cef_bpath, ep->cef_path) == -1)
        !           227:                        fatal("cvs_ent_close: %s: %s", ep->cef_path,
        !           228:                             strerror(errno));
        !           229:
        !           230:                (void)unlink(ep->cef_lpath);
        !           231:        }
1.9       jfb       232:
1.57    ! joris     233:        xfree(ep->cef_path);
        !           234:        xfree(ep->cef_bpath);
        !           235:        xfree(ep->cef_lpath);
        !           236:        xfree(ep);
1.9       jfb       237: }
                    238:
1.57    ! joris     239: void
        !           240: cvs_ent_add(CVSENTRIES *ep, const char *line)
1.1       jfb       241: {
1.57    ! joris     242:        FILE *fp;
        !           243:        struct cvs_ent_line *l;
1.39      xsa       244:        struct cvs_ent *ent;
1.1       jfb       245:
1.57    ! joris     246:        if ((ent = cvs_ent_parse(line)) == NULL)
        !           247:                fatal("cvs_ent_add: parsing failed '%s'", line);
1.1       jfb       248:
1.57    ! joris     249:        l = ent_get_line(ep, ent->ce_name);
        !           250:        if (l != NULL)
        !           251:                cvs_ent_remove(ep, ent->ce_name);
1.1       jfb       252:
1.57    ! joris     253:        cvs_ent_free(ent);
1.1       jfb       254:
1.57    ! joris     255:        cvs_log(LP_TRACE, "cvs_ent_add(%s, %s)", ep->cef_path, line);
1.1       jfb       256:
1.57    ! joris     257:        if ((fp = fopen(ep->cef_lpath, "a")) == NULL)
        !           258:                fatal("cvs_ent_add: failed to open '%s'", ep->cef_lpath);
1.1       jfb       259:
1.57    ! joris     260:        fputc('A', fp);
        !           261:        fputs(line, fp);
        !           262:        fputc('\n', fp);
1.1       jfb       263:
1.57    ! joris     264:        (void)fclose(fp);
1.10      jfb       265:
1.57    ! joris     266:        l = (struct cvs_ent_line *)xmalloc(sizeof(*l));
        !           267:        l->buf = xstrdup(line);
        !           268:        TAILQ_INSERT_TAIL(&(ep->cef_ent), l, entries_list);
        !           269: }
1.10      jfb       270:
1.57    ! joris     271: void
        !           272: cvs_ent_remove(CVSENTRIES *ep, const char *name)
        !           273: {
        !           274:        FILE *fp;
        !           275:        struct cvs_ent_line *l;
1.1       jfb       276:
1.57    ! joris     277:        cvs_log(LP_TRACE, "cvs_ent_remove(%s, %s)", ep->cef_path, name);
1.1       jfb       278:
1.57    ! joris     279:        l = ent_get_line(ep, name);
        !           280:        if (l == NULL)
        !           281:                return;
1.1       jfb       282:
1.57    ! joris     283:        if ((fp = fopen(ep->cef_lpath, "a")) == NULL)
        !           284:                fatal("cvs_ent_remove: failed to open '%s'",
        !           285:                    ep->cef_lpath);
1.38      joris     286:
1.57    ! joris     287:        fputc('R', fp);
        !           288:        fputs(l->buf, fp);
        !           289:        fputc('\n', fp);
1.24      jfb       290:
1.57    ! joris     291:        (void)fclose(fp);
1.24      jfb       292:
1.57    ! joris     293:        TAILQ_REMOVE(&(ep->cef_ent), l, entries_list);
        !           294:        xfree(l->buf);
        !           295:        xfree(l);
1.5       jfb       296: }
                    297:
                    298: void
                    299: cvs_ent_free(struct cvs_ent *ent)
                    300: {
                    301:        if (ent->ce_rev != NULL)
                    302:                rcsnum_free(ent->ce_rev);
1.57    ! joris     303:        xfree(ent->ce_buf);
1.53      joris     304:        xfree(ent);
1.5       jfb       305: }
1.8       jfb       306:
1.57    ! joris     307: static struct cvs_ent_line *
        !           308: ent_get_line(CVSENTRIES *ep, const char *name)
1.8       jfb       309: {
1.57    ! joris     310:        char *p, *s;
        !           311:        struct cvs_ent_line *l;
1.8       jfb       312:
1.57    ! joris     313:        TAILQ_FOREACH(l, &(ep->cef_ent), entries_list) {
        !           314:                if (l->buf[0] == 'D')
        !           315:                        p = &(l->buf[2]);
        !           316:                else
        !           317:                        p = &(l->buf[1]);
        !           318:
        !           319:                if ((s = strchr(p, '/')) == NULL)
        !           320:                        fatal("ent_get_line: bad entry line '%s'", l->buf);
        !           321:
        !           322:                *s = '\0';
        !           323:
        !           324:                if (!strcmp(p, name)) {
        !           325:                        *s = '/';
        !           326:                        return (l);
1.15      jfb       327:                }
1.8       jfb       328:
1.57    ! joris     329:                *s = '/';
1.8       jfb       330:        }
                    331:
1.57    ! joris     332:        return (NULL);
1.1       jfb       333: }