diff options
author | Tobias Stoeckmann <tobias@cvs.openbsd.org> | 2007-09-13 13:10:58 +0000 |
---|---|---|
committer | Tobias Stoeckmann <tobias@cvs.openbsd.org> | 2007-09-13 13:10:58 +0000 |
commit | e149a4581854b359e674cd5b1a129eb8549b09b1 (patch) | |
tree | 3d8ba2761956633f4145b85b3bb978526add5baa | |
parent | 67529b284be16edf396f300e8e1f24219d36d2c3 (diff) |
Added annotate support for local and remote repositories. Behaves like
GNU cvs but is a little faster.
OK joris@, ray@, xsa@
-rw-r--r-- | usr.bin/cvs/annotate.c | 70 | ||||
-rw-r--r-- | usr.bin/cvs/rcs.c | 131 | ||||
-rw-r--r-- | usr.bin/cvs/rcs.h | 6 | ||||
-rw-r--r-- | usr.bin/cvs/util.h | 4 |
4 files changed, 187 insertions, 24 deletions
diff --git a/usr.bin/cvs/annotate.c b/usr.bin/cvs/annotate.c index df80a3f1da6..b112211c596 100644 --- a/usr.bin/cvs/annotate.c +++ b/usr.bin/cvs/annotate.c @@ -1,6 +1,7 @@ -/* $OpenBSD: annotate.c,v 1.37 2007/02/22 06:42:09 otto Exp $ */ +/* $OpenBSD: annotate.c,v 1.38 2007/09/13 13:10:57 tobias Exp $ */ /* * Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org> + * Copyright (c) 2007 Tobias Stoeckmann <tobias@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -17,6 +18,10 @@ #include <sys/param.h> #include <sys/dirent.h> + +#include <stdlib.h> +#include <string.h> +#include <time.h> #include <unistd.h> #include "cvs.h" @@ -108,15 +113,68 @@ cvs_annotate(int argc, char **argv) void cvs_annotate_local(struct cvs_file *cf) { + int i; + char date[10], rnum[13], *p; + RCSNUM *crev; + struct cvs_line **alines; + cvs_log(LP_TRACE, "cvs_annotate_local(%s)", cf->file_path); cvs_file_classify(cf, NULL); - if (cf->file_status == FILE_UNKNOWN || - cf->file_status == FILE_UNLINK) + if (cf->file_status == FILE_UNKNOWN || cf->file_status == FILE_UNLINK || + cf->file_type != CVS_FILE) return; - cvs_printf("Annotations for %s", cf->file_name); - cvs_printf("\n***************\n"); - cvs_printf("no code yet\n"); + if (rev == NULL) + rcs_rev_getlines(cf->file_rcs, cf->file_rcsrev, &alines); + else { + crev = rcsnum_parse(rev); + + if (rcsnum_cmp(crev, cf->file_rcsrev, 0) < 0) { + if (!force_head) { + /* Stick at weird GNU cvs, ignore error. */ + rcsnum_free(crev); + return; + } + rcsnum_cpy(cf->file_rcsrev, crev, 0); + } + rcs_rev_getlines(cf->file_rcs, crev, &alines); + rcsnum_free(crev); + } + + /* Stick at weird GNU cvs, ignore error. */ + if (alines == NULL) + return; + + cvs_log(LP_RCS, "Annotations for %s", cf->file_path); + cvs_log(LP_RCS, "***************"); + + for (i = 0; alines[i] != NULL; i++) { + rcsnum_tostr(alines[i]->l_delta->rd_num, rnum, sizeof(rnum)); + strftime(date, sizeof(date), "%d-%b-%y", + &(alines[i]->l_delta->rd_date)); + if (alines[i]->l_len && + alines[i]->l_line[alines[i]->l_len - 1] == '\n') + alines[i]->l_line[alines[i]->l_len - 1] = '\0'; + else { + p = xmalloc(alines[i]->l_len + 1); + memcpy(p, alines[i]->l_line, alines[i]->l_len); + p[alines[i]->l_len] = '\0'; + + if (alines[i]->l_needsfree) + xfree(alines[i]->l_line); + alines[i]->l_line = p; + alines[i]->l_len++; + alines[i]->l_needsfree = 1; + } + cvs_printf("%-12.12s (%-8.8s %s): %s\n", rnum, + alines[i]->l_delta->rd_author, date, alines[i]->l_line); + + if (alines[i]->l_needsfree) + xfree(alines[i]->l_line); + xfree(alines[i]); + } + + xfree(alines); } diff --git a/usr.bin/cvs/rcs.c b/usr.bin/cvs/rcs.c index 37a3bd1e6ce..0744daddcfc 100644 --- a/usr.bin/cvs/rcs.c +++ b/usr.bin/cvs/rcs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rcs.c,v 1.217 2007/09/07 23:05:04 joris Exp $ */ +/* $OpenBSD: rcs.c,v 1.218 2007/09/13 13:10:57 tobias Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -73,6 +73,10 @@ #define RCS_NOSCOL 0x01 /* no terminating semi-colon */ #define RCS_VOPT 0x02 /* value is optional */ +#define ANNOTATE_NEVER 0 +#define ANNOTATE_NOW 1 +#define ANNOTATE_LATER 2 + /* opaque parse data */ struct rcs_pdata { u_int rp_lines; @@ -219,7 +223,8 @@ static const char *rcs_errstrs[] = { int rcs_errno = RCS_ERR_NOERR; -int rcs_patch_lines(struct cvs_lines *, struct cvs_lines *); +int rcs_patch_lines(struct cvs_lines *, struct cvs_lines *, + struct cvs_line **, struct rcs_delta *); static void rcs_parse_init(RCSFILE *); static int rcs_parse_admin(RCSFILE *); static int rcs_parse_delta(RCSFILE *); @@ -1022,7 +1027,8 @@ rcs_tag_resolve(RCSFILE *file, const char *tag) } int -rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines) +rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines, + struct cvs_line **alines, struct rcs_delta *rdp) { u_char op; char *ep; @@ -1075,7 +1081,12 @@ rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines) for (i = 0; (i < nbln) && (dlp != NULL); i++) { ndlp = TAILQ_NEXT(dlp, l_list); TAILQ_REMOVE(&(dlines->l_lines), dlp, l_list); - xfree(dlp); + if (alines != NULL && dlp->l_line != NULL) { + dlp->l_delta = rdp; + alines[dlp->l_lineno_orig - 1] = + dlp; + } else + xfree(dlp); dlp = ndlp; /* last line is gone - reset dlp */ if (dlp == NULL) { @@ -1091,6 +1102,12 @@ rcs_patch_lines(struct cvs_lines *dlines, struct cvs_lines *plines) if (lp == NULL) fatal("truncated RCS patch"); TAILQ_REMOVE(&(plines->l_lines), lp, l_list); + if (alines != NULL) { + if (lp->l_needsfree == 1) + xfree(lp->l_line); + lp->l_line = NULL; + lp->l_needsfree = 0; + } TAILQ_INSERT_AFTER(&(dlines->l_lines), dlp, lp, l_list); dlp = lp; @@ -2623,14 +2640,15 @@ rcs_translate_tag(const char *revstr, RCSFILE *rfp) * return it as a pointer to a struct cvs_lines. */ struct cvs_lines * -rcs_rev_getlines(RCSFILE *rfp, RCSNUM *frev) +rcs_rev_getlines(RCSFILE *rfp, RCSNUM *frev, struct cvs_line ***alines) { size_t plen; - int i, done, nextroot; + int annotate, done, i, nextroot; RCSNUM *tnum, *bnum; struct rcs_branch *brp; - struct rcs_delta *hrdp, *trdp, *rdp; + struct rcs_delta *hrdp, *prdp, *rdp, *trdp; u_char *patch; + struct cvs_line *line, *nline; struct cvs_lines *dlines, *plines; if ((hrdp = rcs_findrev(rfp, rfp->rf_head)) == NULL) @@ -2648,14 +2666,43 @@ rcs_rev_getlines(RCSFILE *rfp, RCSNUM *frev) bnum = tnum; } + if (alines != NULL) { + /* start with annotate first at requested revision */ + annotate = ANNOTATE_LATER; + *alines = NULL; + } else + annotate = ANNOTATE_NEVER; + dlines = cvs_splitlines(hrdp->rd_text, hrdp->rd_tlen); done = 0; rdp = hrdp; - if (!rcsnum_differ(rdp->rd_num, bnum)) - goto next; + if (!rcsnum_differ(rdp->rd_num, bnum)) { + if (annotate == ANNOTATE_LATER) { + /* found requested revision for annotate */ + i = 0; + TAILQ_FOREACH(line, &(dlines->l_lines), l_list) { + line->l_lineno_orig = line->l_lineno; + i++; + } + + *alines = xcalloc(i + 1, sizeof(struct cvs_line *)); + (*alines)[i] = NULL; + annotate = ANNOTATE_NOW; + /* annotate down to 1.1 from where we are */ + if (bnum == tnum) + bnum = rcsnum_alloc(); + bnum = rcsnum_parse("1.1"); + if (!rcsnum_differ(rdp->rd_num, bnum)) { + goto next; + } + } else + goto next; + } + + prdp = hrdp; if ((rdp = rcs_findrev(rfp, hrdp->rd_next)) == NULL) goto done; @@ -2680,12 +2727,37 @@ again: plen = rdp->rd_tlen; patch = rdp->rd_text; plines = cvs_splitlines(patch, plen); - rcs_patch_lines(dlines, plines); + if (annotate == ANNOTATE_NOW) + rcs_patch_lines(dlines, plines, *alines, prdp); + else + rcs_patch_lines(dlines, plines, NULL, NULL); cvs_freelines(plines); - if (!rcsnum_differ(rdp->rd_num, bnum)) - break; + if (!rcsnum_differ(rdp->rd_num, bnum)) { + if (annotate != ANNOTATE_LATER) + break; + + /* found requested revision for annotate */ + i = 0; + TAILQ_FOREACH(line, &(dlines->l_lines), l_list) { + line->l_lineno_orig = line->l_lineno; + i++; + } + *alines = xcalloc(i + 1, sizeof(struct cvs_line *)); + (*alines)[i] = NULL; + annotate = ANNOTATE_NOW; + + /* annotate down to 1.1 from where we are */ + if (bnum == tnum) + bnum = rcsnum_alloc(); + bnum = rcsnum_parse("1.1"); + + if (!rcsnum_differ(rdp->rd_num, bnum)) + break; + } + + prdp = rdp; rdp = trdp; } @@ -2705,8 +2777,18 @@ next: break; } - if (brp == NULL) + if (brp == NULL) { + if (annotate != ANNOTATE_NEVER) { + if (*alines != NULL) + xfree(*alines); + *alines = NULL; + cvs_freelines(dlines); + if (bnum != tnum) + rcsnum_free(bnum); + return (NULL); + } fatal("expected branch not found on branch list"); + } if ((rdp = rcs_findrev(rfp, brp->rb_num)) == NULL) fatal("rcs_rev_getlines: failed to get delta for target rev"); @@ -2714,6 +2796,25 @@ next: goto again; } done: + /* put remaining lines of 1.1 into annotate buffer */ + if (annotate == ANNOTATE_NOW) { + for (line = TAILQ_FIRST(&(dlines->l_lines)); + line != NULL; line = nline) { + nline = TAILQ_NEXT(line, l_list); + TAILQ_REMOVE(&(dlines->l_lines), line, l_list); + if (line->l_line == NULL) { + xfree(line); + continue; + } + + line->l_delta = rdp; + (*alines)[line->l_lineno_orig - 1] = line; + } + + cvs_freelines(dlines); + dlines = NULL; + } + if (bnum != tnum) rcsnum_free(bnum); @@ -2738,7 +2839,7 @@ rcs_rev_getbuf(RCSFILE *rfp, RCSNUM *rev, int mode) BUF *bp; expand = 0; - lines = rcs_rev_getlines(rfp, rev); + lines = rcs_rev_getlines(rfp, rev, NULL); bp = cvs_buf_alloc(1024, BUF_AUTOEXT); if (!(mode & RCS_KWEXP_NONE)) { @@ -2785,7 +2886,7 @@ rcs_rev_write_fd(RCSFILE *rfp, RCSNUM *rev, int fd, int mode) extern int print_stdout; expand = 0; - lines = rcs_rev_getlines(rfp, rev); + lines = rcs_rev_getlines(rfp, rev, NULL); if (!(mode & RCS_KWEXP_NONE)) { if (rfp->rf_expand != NULL) diff --git a/usr.bin/cvs/rcs.h b/usr.bin/cvs/rcs.h index f3c2e763a5a..b4e294207cb 100644 --- a/usr.bin/cvs/rcs.h +++ b/usr.bin/cvs/rcs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rcs.h,v 1.77 2007/06/01 17:47:47 niallo Exp $ */ +/* $OpenBSD: rcs.h,v 1.78 2007/09/13 13:10:57 tobias Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -215,6 +215,7 @@ typedef struct rcs_file { } RCSFILE; extern int rcs_errno; +struct cvs_line; struct cvs_lines; RCSFILE *rcs_open(const char *, int, int, ...); @@ -260,7 +261,8 @@ const char *rcs_errstr(int); void rcs_write(RCSFILE *); void rcs_rev_write_stmp(RCSFILE *, RCSNUM *, char *, int); void rcs_rev_write_fd(RCSFILE *, RCSNUM *, int, int); -struct cvs_lines *rcs_rev_getlines(RCSFILE *, RCSNUM *); +struct cvs_lines *rcs_rev_getlines(RCSFILE *, RCSNUM *, + struct cvs_line ***); BUF *rcs_rev_getbuf(RCSFILE *, RCSNUM *, int); int rcs_kflag_get(const char *); diff --git a/usr.bin/cvs/util.h b/usr.bin/cvs/util.h index fb73a9e17d7..1e80fa00bff 100644 --- a/usr.bin/cvs/util.h +++ b/usr.bin/cvs/util.h @@ -1,4 +1,4 @@ -/* $OpenBSD: util.h,v 1.21 2007/09/04 19:07:04 tobias Exp $ */ +/* $OpenBSD: util.h,v 1.22 2007/09/13 13:10:57 tobias Exp $ */ /* * Copyright (c) 2006 Niall O'Higgins <niallo@openbsd.org> * All rights reserved. @@ -45,9 +45,11 @@ void cvs_freeargv(char **, int); u_int cvs_revision_select(RCSFILE *, char *); struct cvs_line { + struct rcs_delta *l_delta; u_char *l_line; size_t l_len; int l_lineno; + int l_lineno_orig; int l_needsfree; TAILQ_ENTRY(cvs_line) l_list; }; |