Here is a patch for log.c (cvs 1.11). It improves cvs log -rrev1:rev2 when rev1 and rev2 are not one the same branch in particular if rev1 is on the main trunc and rev2 on a branch. for example cvs log -r1.30:1.32.2.2 will output mesages for 1.30,1.31.1.32,1.32.2.1,1.32.2.2 It's particularly useful when doing a cvs log on a directory giving symbolic tag for the revision range Hope this helps
*** log.c Tue Nov 14 10:36:07 2000 --- log.c.org Thu Nov 9 15:16:21 2000 *************** *** 129,135 **** static void log_version PROTO ((struct log_data *, struct revlist *, RCSNode *, RCSVers *, int)); static int log_branch PROTO ((Node *, void *)); ! static int version_compare PROTO ((const char *, const char *)); static const char *const log_usage[] = { --- 129,135 ---- static void log_version PROTO ((struct log_data *, struct revlist *, RCSNode *, RCSVers *, int)); static int log_branch PROTO ((Node *, void *)); ! static int version_compare PROTO ((const char *, const char *, int)); static const char *const log_usage[] = { *************** *** 893,899 **** { error (0, 0, "warning: no revision `%s' in `%s'", r->first, rcs->path); ! nr->first = xstrdup (r->first); } nr->last = xstrdup (nr->first); nr->fields = numdots (nr->first) + 1; --- 893,900 ---- { error (0, 0, "warning: no revision `%s' in `%s'", r->first, rcs->path); ! free (nr); ! continue; } nr->last = xstrdup (nr->first); nr->fields = numdots (nr->first) + 1; *************** *** 912,922 **** { error (0, 0, "warning: no revision `%s' in `%s'", r->first, rcs->path); ! nr->first = ""; } } ! if (r->last == NULL || isdigit ((unsigned char) r->last[0])) nr->last = xstrdup (r->last); else { --- 913,926 ---- { error (0, 0, "warning: no revision `%s' in `%s'", r->first, rcs->path); ! free (nr); ! continue; } } ! if (r->last == r->first) ! nr->last = xstrdup (nr->first); ! else if (r->last == NULL || isdigit ((unsigned char) r->last[0])) nr->last = xstrdup (r->last); else { *************** *** 928,971 **** { error (0, 0, "warning: no revision `%s' in `%s'", r->last, rcs->path); ! nr->last = ""; } } ! } ! ! if (*(nr->first)!='\0' && numdots(nr->first)%2==0) { ! char *cp; ! /* it's a branch */ ! cp=xmalloc(strlen(nr->first)+2); ! strcpy(cp,nr->first); ! strcat(cp,".0"); ! nr->first=cp; ! } ! ! if (*(nr->last)!='\0' && numdots(nr->last)%2==0) { char *cp; - /* it's a branch */ - cp=xmalloc(strlen(nr->last)+2); - strcpy(cp,nr->last); - strcat(cp,".*"); - nr->last=cp; - } ! if (*(nr->last)=='\0') { char *cp; - nr->last = xstrdup (nr->first); cp = strrchr (nr->last, '.'); ! cp[1] = '*'; ! cp[2] = '\0'; } ! ! if (*(nr->first)!='\0' && *(nr->last)!='\0' && version_compare (nr->first, nr->last) >0) { char *tmp; tmp = nr->first; --- 932,994 ---- { error (0, 0, "warning: no revision `%s' in `%s'", r->last, rcs->path); ! if (nr->first != NULL) ! free (nr->first); ! free (nr); ! continue; } } ! /* Process the revision numbers the same way that rlog ! does. This code is a bit cryptic for my tastes, but ! keeping the same implementation as rlog ensures a ! certain degree of compatibility. */ ! if (r->first == NULL) { ! nr->fields = numdots (nr->last) + 1; ! if (nr->fields < 2) ! nr->first = xstrdup (".0"); ! else { char *cp; ! nr->first = xstrdup (nr->last); ! cp = strrchr (nr->first, '.'); ! strcpy (cp, ".0"); ! } ! } ! else if (r->last == NULL) { + nr->fields = numdots (nr->first) + 1; + nr->last = xstrdup (nr->first); + if (nr->fields < 2) + nr->last[0] = '\0'; + else + { char *cp; cp = strrchr (nr->last, '.'); ! *cp = '\0'; } ! } ! else { + nr->fields = numdots (nr->first) + 1; + if (nr->fields != numdots (nr->last) + 1 + || (nr->fields > 2 + && version_compare (nr->first, nr->last, + nr->fields - 1) != 0)) + { + error (0, 0, + "invalid branch or revision pair %s:%s in `%s'", + r->first, r->last, rcs->path); + free (nr->first); + free (nr->last); + free (nr); + continue; + } + if (version_compare (nr->first, nr->last, nr->fields) > 0) + { char *tmp; tmp = nr->first; *************** *** 972,983 **** nr->first = nr->last; nr->last = tmp; } - - if(version_compare (nr->first, nr->last) ==-2) { - error (0, 0, - "warning : revision pair %s:%s in `%s' are not on the same branch", - nr->first, nr->last, rcs->path); } nr->next = NULL; *pr = nr; --- 995,1002 ---- nr->first = nr->last; nr->last = tmp; } } + } nr->next = NULL; *pr = nr; *************** *** 993,1011 **** nr = (struct revlist *) xmalloc (sizeof *nr); if (rcs->branch != NULL) - { nr->first = xstrdup (rcs->branch); - nr->last = ""; - } else { char *cp; - nr->last = xstrdup (rcs->head); nr->first = xstrdup (rcs->head); cp = strrchr (nr->first, '.'); *cp = '\0'; } nr->fields = numdots (nr->first) + 1; nr->next = NULL; --- 1012,1027 ---- nr = (struct revlist *) xmalloc (sizeof *nr); if (rcs->branch != NULL) nr->first = xstrdup (rcs->branch); else { char *cp; nr->first = xstrdup (rcs->head); cp = strrchr (nr->first, '.'); *cp = '\0'; } + nr->last = xstrdup (nr->first); nr->fields = numdots (nr->first) + 1; nr->next = NULL; *************** *** 1113,1129 **** if (revlist != NULL) { char *v; struct revlist *r; v = vnode->version; for (r = revlist; r != NULL; r = r->next) { ! int vf,vl; ! ! vf=version_compare (v, r->first); ! vl=version_compare (v, r->last); ! ! if ( vf>=0 && (vl<=0 && vl!=-2 )) { return 1; } --- 1129,1145 ---- if (revlist != NULL) { char *v; + int vfields; struct revlist *r; + /* This code is taken from rlog. */ v = vnode->version; + vfields = numdots (v) + 1; for (r = revlist; r != NULL; r = r->next) { ! if (vfields == r->fields + (r->fields & 1) ! && version_compare (v, r->first, r->fields) >= 0 ! && version_compare (v, r->last, r->fields) <= 0) { return 1; } *************** *** 1135,1140 **** --- 1151,1157 ---- return 0; } + /* By default, we print all revisions. */ return 1; } *************** *** 1460,1508 **** } /* ! * Compare versions. ! * return : ! * 0 if v1=v2 ! * 1 if v1 < v2 and on the same path ! * 2 if v1 < v2 and not on the same path ! * -1 if v2 < v1 and on the same path ! * -2 if v2 < v1 and not on the same path */ static int ! version_compare (v1, v2) const char *v1; const char *v2; { while (1) { int d1, d2, r; ! if (*v1 == '\0' && *v2 == '\0') return 0; ! if (*v1 == '\0' ) return -1; ! if (*v2 == '\0') return 1; while (*v1 == '0') ++v1; ! for (d1 = 0; v1[d1]!='.' && v1[d1]!='\0'; ++d1) ; while (*v2 == '0') ++v2; ! for (d2 = 0; v2[d2]!='.' && v2[d2]!='\0'; ++d2) ; ! if(v2[0]=='*') ! r=-1; ! else ! if (d1!=d2) ! r=d1<d2?-1:1; ! else r = memcmp (v1, v2, d1); ! if (r > 0 && v2[d2]=='\0') return 1; ! if (r > 0 && v2[d2]!='\0') return 2; ! if (r < 0 && v1[d1]=='\0') return -1; ! if (r < 0 && v1[d1]!='\0') return -2; v1 += d1; v2 += d1; --- 1477,1519 ---- } /* ! * Compare versions. This is taken from RCS compartial. */ static int ! version_compare (v1, v2, len) const char *v1; const char *v2; + int len; { while (1) { int d1, d2, r; ! if (*v1 == '\0') ! return 1; ! if (*v2 == '\0') ! return -1; while (*v1 == '0') ++v1; ! for (d1 = 0; isdigit ((unsigned char) v1[d1]); ++d1) ; while (*v2 == '0') ++v2; ! for (d2 = 0; isdigit ((unsigned char) v2[d2]); ++d2) ; ! if (d1 != d2) ! return d1 < d2 ? -1 : 1; ! r = memcmp (v1, v2, d1); + if (r != 0) + return r; ! --len; ! if (len == 0) ! return 0; v1 += d1; v2 += d1;