diff options
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/cvs/rcs.c | 107 | ||||
-rw-r--r-- | usr.bin/cvs/rcs.h | 6 | ||||
-rw-r--r-- | usr.bin/rcs/rcsprog.c | 110 |
3 files changed, 205 insertions, 18 deletions
diff --git a/usr.bin/cvs/rcs.c b/usr.bin/cvs/rcs.c index ed6398691a5..5fdca83a071 100644 --- a/usr.bin/cvs/rcs.c +++ b/usr.bin/cvs/rcs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rcs.c,v 1.165 2006/04/13 19:16:15 joris Exp $ */ +/* $OpenBSD: rcs.c,v 1.166 2006/04/13 19:55:41 joris Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -1383,26 +1383,113 @@ rcs_rev_add(RCSFILE *rf, RCSNUM *rev, const char *msg, time_t date, int rcs_rev_remove(RCSFILE *rf, RCSNUM *rev) { - int ret; - struct rcs_delta *rdp; + size_t len; + char *tmpdir; + char *newdeltatext, path_tmp1[MAXPATHLEN], path_tmp2[MAXPATHLEN]; + struct rcs_delta *rdp, *prevrdp, *nextrdp; + BUF *nextbuf, *prevbuf, *newdiff; + +#if defined(RCSPROG) + tmpdir = rcs_tmpdir; +#else + tmpdir = cvs_tmpdir; +#endif - ret = 0; if (rev == RCS_HEAD_REV) rev = rf->rf_head; /* do we actually have that revision? */ if ((rdp = rcs_findrev(rf, rev)) == NULL) { rcs_errno = RCS_ERR_NOENT; - ret = -1; + return (-1); + } + + /* + * This is confusing, the previous delta is next in the TAILQ list. + * the next delta is the previous one in the TAILQ list. + * + * When the HEAD revision got specified, nextrdp will be NULL. + * When the first revision got specified, prevrdp will be NULL. + */ + prevrdp = (struct rcs_delta *)TAILQ_NEXT(rdp, rd_list); + nextrdp = (struct rcs_delta *)TAILQ_PREV(rdp, cvs_tqh, rd_list); + + newdeltatext = NULL; + prevbuf = nextbuf = NULL; + + if (prevrdp != NULL) { + if ((prevbuf = rcs_getrev(rf, prevrdp->rd_num)) == NULL) + fatal("error getting revision"); + } + + if ((prevrdp != NULL) && (nextrdp != NULL)) { + if ((nextbuf = rcs_getrev(rf, nextrdp->rd_num)) == NULL) + fatal("error getting revision"); + + newdiff = cvs_buf_alloc(64, BUF_AUTOEXT); + + /* calculate new diff */ + len = strlcpy(path_tmp1, tmpdir, sizeof(path_tmp1)); + if (len >= sizeof(path_tmp1)) + fatal("path truncation in rcs_rev_remove"); + + len = strlcat(path_tmp1, "/diff1.XXXXXXXXXX", + sizeof(path_tmp1)); + if (len >= sizeof(path_tmp1)) + fatal("path truncation in rcs_rev_remove"); + + cvs_buf_write_stmp(nextbuf, path_tmp1, 0600); + cvs_buf_free(nextbuf); + + len = strlcpy(path_tmp2, tmpdir, sizeof(path_tmp2)); + if (len >= sizeof(path_tmp2)) + fatal("path truncation in rcs_rev_remove"); + + len = strlcat(path_tmp2, "/diff2.XXXXXXXXXX", + sizeof(path_tmp2)); + if (len >= sizeof(path_tmp2)) + fatal("path truncation in rcs_rev_remove"); + + cvs_buf_write_stmp(prevbuf, path_tmp2, 0600); + cvs_buf_free(prevbuf); + + diff_format = D_RCSDIFF; + cvs_diffreg(path_tmp1, path_tmp2, newdiff); + + newdeltatext = cvs_buf_release(newdiff); + } else if ((nextrdp == NULL) && (prevrdp != NULL)) { + newdeltatext = cvs_buf_release(prevbuf); + } + + if (newdeltatext != NULL) { + if (rcs_deltatext_set(rf, prevrdp->rd_num, newdeltatext) < 0) + fatal("error setting new deltatext"); + } + + TAILQ_REMOVE(&(rf->rf_delta), rdp, rd_list); + + /* update pointers */ + if ((prevrdp != NULL) && (nextrdp != NULL)) { + rcsnum_cpy(prevrdp->rd_num, nextrdp->rd_next, 0); + } else if (prevrdp != NULL) { + rcs_head_set(rf, prevrdp->rd_num); + } else if (nextrdp != NULL) { + rcsnum_free(nextrdp->rd_next); + nextrdp->rd_next = rcsnum_alloc(); } else { - /* XXX assumes it's not a sub node */ - TAILQ_REMOVE(&(rf->rf_delta), rdp, rd_list); - rf->rf_ndelta--; - rf->rf_flags &= ~RCS_SYNCED; + rcsnum_free(rf->rf_head); + rf->rf_head = NULL; } - return (ret); + rf->rf_ndelta--; + rf->rf_flags &= ~RCS_SYNCED; + + rcs_freedelta(rdp); + if (newdeltatext != NULL) + xfree(newdeltatext); + + return (0); } /* diff --git a/usr.bin/cvs/rcs.h b/usr.bin/cvs/rcs.h index f544c73092b..4e4f226e39c 100644 --- a/usr.bin/cvs/rcs.h +++ b/usr.bin/cvs/rcs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rcs.h,v 1.59 2006/04/13 19:16:15 joris Exp $ */ +/* $OpenBSD: rcs.h,v 1.60 2006/04/13 19:55:41 joris Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -274,4 +274,8 @@ void rcs_set_tz(char *, struct rcs_delta *, struct tm *); extern char *timezone_flag; +#if defined(RCSPROG) +extern char *rcs_tmpdir; +#endif + #endif /* RCS_H */ diff --git a/usr.bin/rcs/rcsprog.c b/usr.bin/rcs/rcsprog.c index 4dec4f791f6..37d4b05a9e7 100644 --- a/usr.bin/rcs/rcsprog.c +++ b/usr.bin/rcs/rcsprog.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rcsprog.c,v 1.100 2006/04/13 16:10:29 joris Exp $ */ +/* $OpenBSD: rcsprog.c,v 1.101 2006/04/13 19:55:41 joris Exp $ */ /* * Copyright (c) 2005 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -29,7 +29,7 @@ #include "rcsprog.h" #define RCS_CMD_MAXARG 128 -#define RCSPROG_OPTSTRING "A:a:b::c:e::hik:Ll::m:Mn:N:qt::TUu::Vx::z::" +#define RCSPROG_OPTSTRING "A:a:b::c:e::hik:Ll::m:Mn:N:o:qt::TUu::Vx::z::" #define DESC_PROMPT "enter description, terminated with single '.' " \ "or end of file:\nNOTE: This is NOT the log message!" \ @@ -64,8 +64,9 @@ struct rcs_prog { struct cvs_wklhead rcs_temp_files; void sighdlr(int); -static void rcs_set_description(RCSFILE *, const char *); -static void rcs_attach_symbol(RCSFILE *, const char *); +static void rcs_set_description(RCSFILE *, const char *); +static void rcs_attach_symbol(RCSFILE *, const char *); +static u_int rcs_rev_select(RCSFILE *, char *); /* ARGSUSED */ void @@ -466,7 +467,7 @@ rcs_usage(void) fprintf(stderr, "usage: rcs [-ehIiLMqTUV] [-Aoldfile] [-ausers] [-b[rev]]\n" " [-cstring] [-e[users]] [-kmode] [-l[rev]] [-mrev:msg]\n" - " [-orev] [-sstate[:rev]] [-tfile|str] [-u[rev]]\n" + " [-orange] [-sstate[:rev]] [-tfile|str] [-u[rev]]\n" " [-xsuffixes] file ...\n"); } @@ -482,7 +483,7 @@ rcs_main(int argc, char **argv) int i, j, ch, kflag, lkmode; char fpath[MAXPATHLEN], ofpath[MAXPATHLEN]; char *logstr, *logmsg, *nflag, *descfile; - char *alist, *comment, *elist, *lrev, *urev; + char *alist, *comment, *elist, *lrev, *urev, *orange; mode_t fmode; RCSFILE *file, *oldfile; RCSNUM *logrev; @@ -494,7 +495,7 @@ rcs_main(int argc, char **argv) fmode = S_IRUSR|S_IRGRP|S_IROTH; flags = RCS_RDWR|RCS_PARSE_FULLY; lrev = urev = descfile = nflag = NULL; - logstr = alist = comment = elist = NULL; + logstr = alist = comment = elist = orange = NULL; while ((ch = rcs_getopt(argc, argv, RCSPROG_OPTSTRING)) != -1) { switch (ch) { @@ -552,6 +553,9 @@ rcs_main(int argc, char **argv) nflag = xstrdup(rcs_optarg); rcsflags |= RCSPROG_NFLAG; break; + case 'o': + orange = xstrdup(rcs_optarg); + break; case 'q': verbose = 0; break; @@ -754,6 +758,23 @@ rcs_main(int argc, char **argv) rcsnum_free(rev); } + if (orange != NULL) { + struct rcs_delta *rdp; + char b[16]; + + rcs_rev_select(file, orange); + TAILQ_FOREACH(rdp, &(file->rf_delta), rd_list) { + /* + * Delete selected revisions. + */ + if (rdp->rd_flags & RCS_RD_SELECT) { + rcsnum_tostr(rdp->rd_num, b, sizeof(b)); + printf("deleting revision %s\n", b); + (void)rcs_rev_remove(file, rdp->rd_num); + } + } + } + rcs_close(file); if (rcsflags & PRESERVETIME) @@ -873,3 +894,78 @@ rcs_set_description(RCSFILE *file, const char *in) rcs_desc_set(file, content); xfree(content); } + +static u_int +rcs_rev_select(RCSFILE *file, char *range) +{ + int i; + u_int nrev; + char *ep; + char *lstr, *rstr; + struct rcs_delta *rdp; + struct cvs_argvector *revargv, *revrange; + RCSNUM lnum, rnum; + + nrev = 0; + (void)memset(&lnum, 0, sizeof(lnum)); + (void)memset(&rnum, 0, sizeof(rnum)); + + if (range == NULL) { + TAILQ_FOREACH(rdp, &file->rf_delta, rd_list) + if (rcsnum_cmp(rdp->rd_num, file->rf_head, 0) == 0) { + rdp->rd_flags |= RCS_RD_SELECT; + return (1); + } + return (0); + } + + revargv = cvs_strsplit(range, ","); + for (i = 0; revargv->argv[i] != NULL; i++) { + revrange = cvs_strsplit(revargv->argv[i], ":"); + if (revrange->argv[0] == NULL) + /* should not happen */ + fatal("invalid revision range: %s", revargv->argv[i]); + else if (revrange->argv[1] == NULL) + lstr = rstr = revrange->argv[0]; + else { + if (revrange->argv[2] != NULL) + fatal("invalid revision range: %s", + revargv->argv[i]); + lstr = revrange->argv[0]; + rstr = revrange->argv[1]; + if (strcmp(lstr, "") == 0) + lstr = NULL; + if (strcmp(rstr, "") == 0) + rstr = NULL; + } + + if (lstr == NULL) + lstr = RCS_HEAD_INIT; + if (rcsnum_aton(lstr, &ep, &lnum) == 0 || (*ep != '\0')) + fatal("invalid revision: %s", lstr); + + if (rstr != NULL) { + if (rcsnum_aton(rstr, &ep, &rnum) == 0 || (*ep != '\0')) + fatal("invalid revision: %s", rstr); + } else + rcsnum_cpy(file->rf_head, &rnum, 0); + + cvs_argv_destroy(revrange); + + TAILQ_FOREACH(rdp, &file->rf_delta, rd_list) + if ((rcsnum_cmp(rdp->rd_num, &lnum, 0) <= 0) && + (rcsnum_cmp(rdp->rd_num, &rnum, 0) >= 0) && + !(rdp->rd_flags & RCS_RD_SELECT)) { + rdp->rd_flags |= RCS_RD_SELECT; + nrev++; + } + } + cvs_argv_destroy(revargv); + + if (lnum.rn_id != NULL) + xfree(lnum.rn_id); + if (rnum.rn_id != NULL) + xfree(rnum.rn_id); + + return (nrev); +} |