diff options
Diffstat (limited to 'usr.bin/cvs/rcs.c')
-rw-r--r-- | usr.bin/cvs/rcs.c | 209 |
1 files changed, 153 insertions, 56 deletions
diff --git a/usr.bin/cvs/rcs.c b/usr.bin/cvs/rcs.c index 9a56fa3b5ea..b7a5eb25a82 100644 --- a/usr.bin/cvs/rcs.c +++ b/usr.bin/cvs/rcs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rcs.c,v 1.116 2005/12/24 04:10:51 joris Exp $ */ +/* $OpenBSD: rcs.c,v 1.117 2005/12/27 16:05:20 niallo Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -45,6 +45,7 @@ #define RCS_BUFSIZE 16384 #define RCS_BUFEXTSIZE 8192 +#define RCS_KWEXP_SIZE 1024 /* RCS token types */ @@ -269,10 +270,13 @@ int rcs_errno = RCS_ERR_NOERR; static int rcs_write(RCSFILE *); -static int rcs_parse(RCSFILE *); +static int rcs_parse_init(RCSFILE *); static int rcs_parse_admin(RCSFILE *); static int rcs_parse_delta(RCSFILE *); +static int rcs_parse_deltas(RCSFILE *, RCSNUM *); static int rcs_parse_deltatext(RCSFILE *); +static int rcs_parse_deltatexts(RCSFILE *, RCSNUM *); +static int rcs_parse_desc(RCSFILE *, RCSNUM *); static int rcs_parse_access(RCSFILE *); static int rcs_parse_symbols(RCSFILE *); @@ -345,7 +349,7 @@ rcs_open(const char *path, int flags, ...) TAILQ_INIT(&(rfp->rf_locks)); if (rfp->rf_flags & RCS_CREATE) { - } else if (rcs_parse(rfp) < 0) { + } else if (rcs_parse_init(rfp) < 0) { rcs_close(rfp); return (NULL); } @@ -426,6 +430,7 @@ rcs_close(RCSFILE *rfp) xfree(rfp->rf_expand); if (rfp->rf_desc != NULL) xfree(rfp->rf_desc); + rcs_freepdata(rfp->rf_pdata); xfree(rfp); } @@ -453,6 +458,9 @@ rcs_write(RCSFILE *rfp) from_fd = to_fd = fd = -1; + /* Write operations need the whole file parsed */ + rcs_parse_deltatexts(rfp, NULL); + if (rfp->rf_flags & RCS_SYNCED) return (0); @@ -660,7 +668,7 @@ rcs_head_get(RCSFILE *file) * <rev>, which must reference a valid revision within the file. */ int -rcs_head_set(RCSFILE *file, const RCSNUM *rev) +rcs_head_set(RCSFILE *file, RCSNUM *rev) { struct rcs_delta *rd; @@ -1233,12 +1241,16 @@ rcs_getrev(RCSFILE *rfp, RCSNUM *frev) return (NULL); } + /* No matter what, we're going to need up the the description parsed */ + rcs_parse_desc(rfp, NULL); + rdp = rcs_findrev(rfp, rfp->rf_head); if (rdp == NULL) { cvs_log(LP_ERR, "failed to get RCS HEAD revision"); return (NULL); } - + if (rdp->rd_tlen == 0) + rcs_parse_deltatexts(rfp, rfp->rf_head); len = rdp->rd_tlen; if (len == 0) { rbuf = cvs_buf_alloc(1, 0); @@ -1260,8 +1272,10 @@ rcs_getrev(RCSFILE *rfp, RCSNUM *frev) cvs_buf_free(rbuf); return (NULL); } - cvs_buf_putc(rbuf, '\0'); + /* check if we have parsed this rev's deltatext */ + if (rdp->rd_tlen == 0) + rcs_parse_deltatexts(rfp, rdp->rd_num); bp = cvs_buf_release(rbuf); rbuf = cvs_patchfile((char *)bp, (char *)rdp->rd_text, @@ -1434,13 +1448,23 @@ rcs_rev_remove(RCSFILE *rf, RCSNUM *rev) * Returns a pointer to the delta on success, or NULL on failure. */ struct rcs_delta * -rcs_findrev(RCSFILE *rfp, const RCSNUM *rev) +rcs_findrev(RCSFILE *rfp, RCSNUM *rev) { u_int cmplen; - struct rcs_delta *rdp; + struct rcs_delta *rdp, *enddelta; struct rcs_dlist *hp; int found; + /* + * We need to do more parsing if the last revision in the linked list + * is greater than the requested revision. + */ + enddelta = TAILQ_LAST(&(rfp->rf_delta), rcs_dlist); + if ((enddelta == NULL) + || (rcsnum_cmp(enddelta->rd_num, rev, -1) == -1)) { + rcs_parse_deltas(rfp, rev); + } + cmplen = 2; hp = &(rfp->rf_delta); @@ -1582,18 +1606,128 @@ rcs_kflag_usage(void) "\t-kb\tGenerate binary file unmodified (merges not allowed).\n"); } +/* rcs_parse_deltas() + * + * Parse deltas. If <rev> is not NULL, parse only as far as that + * revision. If <rev> is NULL, parse all deltas. + * + * Returns 0 on success, -1 on failure. + */ +static int +rcs_parse_deltas(RCSFILE *rfp, RCSNUM *rev) +{ + int ret; + struct rcs_delta *enddelta; + if ((rfp->rf_flags & PARSED_DELTAS) + || (rfp->rf_flags & RCS_CREATE)) + return (0); + for (;;) { + ret = rcs_parse_delta(rfp); + if (rev != NULL) { + enddelta = TAILQ_LAST(&(rfp->rf_delta), rcs_dlist); + if (rcsnum_cmp(enddelta->rd_num, rev, -1) == 0) + break; + } + if (ret == 0) { + rfp->rf_flags |= PARSED_DELTAS; + break; + } + else if (ret == -1) + fatal("error parsing deltas"); + } + return (0); +} + +/* rcs_parse_deltatexts() + * + * Parse deltatexts. If <rev> is not NULL, parse only as far as that + * revision. If <rev> is NULL, parse everything. + * + * Returns 0 on success, -1 on failure. + */ +static int +rcs_parse_deltatexts(RCSFILE *rfp, RCSNUM *rev) +{ + int ret; + struct rcs_delta *rdp; + if ((rfp->rf_flags & PARSED_DELTATEXTS) + || (rfp->rf_flags & RCS_CREATE)) + return (0); + if (!(rfp->rf_flags & PARSED_DESC)) + rcs_parse_desc(rfp, rev); + for (;;) { + if (rev != NULL) { + rdp = rcs_findrev(rfp, rev); + if (rdp->rd_text != NULL) + break; + else + ret = rcs_parse_deltatext(rfp); + } else + ret = rcs_parse_deltatext(rfp); + if (ret == 0) { + rfp->rf_flags |= PARSED_DELTATEXTS; + break; + } + else if (ret == -1) { + fatal("problem parsing deltatexts"); + } + } + + return (0); +} + +/* rcs_parse_desc() + * + * Parse RCS description. + * + * Returns 0 on success, -1 on failure. + */ +static int +rcs_parse_desc(RCSFILE *rfp, RCSNUM *rev) +{ + int ret = 0; + if ((rfp->rf_flags & PARSED_DESC) + || (rfp->rf_flags & RCS_CREATE)) + return (0); + if (!(rfp->rf_flags & PARSED_DELTAS)) + rcs_parse_deltas(rfp, rev); + /* do parsing */ + ret = rcs_gettok(rfp); + if (ret != RCS_TOK_DESC) { + rcs_errno = RCS_ERR_PARSE; + cvs_log(LP_ERR, "token `%s' found where RCS desc expected", + RCS_TOKSTR(rfp)); + fatal("problem parsing RCS desc"); + return (-1); + } + + ret = rcs_gettok(rfp); + if (ret != RCS_TOK_STRING) { + rcs_errno = RCS_ERR_PARSE; + cvs_log(LP_ERR, "token `%s' found where RCS desc expected", + RCS_TOKSTR(rfp)); + fatal("problem parsing RCS desc"); + } + + rfp->rf_desc = xstrdup(RCS_TOKSTR(rfp)); + rfp->rf_flags |= PARSED_DESC; + return (0); +} + /* - * rcs_parse() + * rcs_parse_init() * - * Parse the contents of file <path>, which are in the RCS format. + * Initial parsing of file <path>, which are in the RCS format. + * Just does admin section * Returns 0 on success, or -1 on failure. */ static int -rcs_parse(RCSFILE *rfp) +rcs_parse_init(RCSFILE *rfp) { - int ret; + int ret, count; struct rcs_pdata *pdp; + count = 0; if (rfp->rf_flags & RCS_PARSED) return (0); @@ -1616,53 +1750,13 @@ rcs_parse(RCSFILE *rfp) if ((ret = rcs_parse_admin(rfp)) < 0) { rcs_freepdata(pdp); - return (-1); - } else if (ret == RCS_TOK_NUM) { - for (;;) { - ret = rcs_parse_delta(rfp); - if (ret == 0) - break; - else if (ret == -1) { - rcs_freepdata(pdp); - return (-1); - } - } - } - - ret = rcs_gettok(rfp); - if (ret != RCS_TOK_DESC) { - rcs_errno = RCS_ERR_PARSE; - cvs_log(LP_ERR, "token `%s' found where RCS desc expected", - RCS_TOKSTR(rfp)); - rcs_freepdata(pdp); - return (-1); + fatal("could not parse admin data"); } - ret = rcs_gettok(rfp); - if (ret != RCS_TOK_STRING) { - rcs_errno = RCS_ERR_PARSE; - cvs_log(LP_ERR, "token `%s' found where RCS desc expected", - RCS_TOKSTR(rfp)); - rcs_freepdata(pdp); - return (-1); - } - - rfp->rf_desc = xstrdup(RCS_TOKSTR(rfp)); - for (;;) { - ret = rcs_parse_deltatext(rfp); - if (ret == 0) - break; - else if (ret == -1) { - rcs_freepdata(pdp); - return (-1); - } - } - - rcs_freepdata(pdp); - - rfp->rf_pdata = NULL; - rfp->rf_flags |= RCS_PARSED | RCS_SYNCED; + if (rfp->rf_flags & RCS_PARSE_FULLY) + rcs_parse_deltatexts(rfp, NULL); + rfp->rf_flags |= RCS_SYNCED; return (0); } @@ -2670,6 +2764,9 @@ rcs_deltatext_set(RCSFILE *rfp, RCSNUM *rev, const char *dtext) size_t len; struct rcs_delta *rdp; + /* Write operations require full parsing */ + rcs_parse_deltatexts(rfp, NULL); + if ((rdp = rcs_findrev(rfp, rev)) == NULL) return (-1); |