summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/cvs/rcs.c107
-rw-r--r--usr.bin/cvs/rcs.h6
-rw-r--r--usr.bin/rcs/rcsprog.c110
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);
+}