diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2004-06-20 18:47:46 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2004-06-20 18:47:46 +0000 |
commit | 8908ae08ec12426bf0c946b2bb67e4b6a8825518 (patch) | |
tree | 8bc32c7daf63de0bcb851ad6fd382c2b3aea622f /usr.bin/diff | |
parent | 27aab8e947ae47e5ef251b626c74f07b90c6d431 (diff) |
Implement -I option: ignore changes matching a set of regexes. From
Jared Yanovich, with twists from millert@ and me. Testing by brad@,
sturm@ and pval@. ok millert@
Diffstat (limited to 'usr.bin/diff')
-rw-r--r-- | usr.bin/diff/diff.1 | 49 | ||||
-rw-r--r-- | usr.bin/diff/diff.c | 60 | ||||
-rw-r--r-- | usr.bin/diff/diff.h | 8 | ||||
-rw-r--r-- | usr.bin/diff/diffreg.c | 55 |
4 files changed, 144 insertions, 28 deletions
diff --git a/usr.bin/diff/diff.1 b/usr.bin/diff/diff.1 index 633c2f435c0..48668dfd229 100644 --- a/usr.bin/diff/diff.1 +++ b/usr.bin/diff/diff.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: diff.1,v 1.25 2004/03/16 00:40:34 millert Exp $ +.\" $OpenBSD: diff.1,v 1.26 2004/06/20 18:47:45 otto Exp $ .\" .\" Copyright (c) 1980, 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -38,31 +38,36 @@ .Sh SYNOPSIS .Nm diff .Op Fl abdilpqtTw +.Op Fl I Ar pattern .Oo -.Fl c | Fl e | Fl f | -.Fl n | Fl u +.Fl c | e | f | +.Fl n | u .Oc .Op Fl L Ar label .Ar file1 file2 .Nm diff .Op Fl abdilpqtTw +.Op Fl I Ar pattern .Op Fl L Ar label .Fl C Ar number .Ar file1 file2 .Nm diff .Op Fl abdilqtw +.Op Fl I Ar pattern .Fl D Ar string .Ar file1 file2 .Nm diff .Op Fl abdilpqtTw +.Op Fl I Ar pattern .Op Fl L Ar label .Fl U Ar number .Ar file1 file2 .Nm diff .Op Fl abdilNPpqtTw +.Op Fl I Ar pattern .Oo -.Fl c | Fl e | Fl f | -.Fl n | Fl u +.Fl c | e | f | +.Fl n | u .Oc .Bk -words .Op Fl L Ar label @@ -93,11 +98,12 @@ With the output format is modified slightly: the output begins with identification of the files involved and their creation dates and then each change is separated -by a line with fifteen *'s. +by a line with fifteen +.Li * Ns 's . The lines removed from .Ar file1 are marked with -.Sq \-\ \& ; +.Sq \&-\ \& ; those added to .Ar file2 are marked @@ -179,7 +185,8 @@ lines of context. Comparison options: .Bl -tag -width Ds .It Fl a -Treat all files as ASCII. +Treat all files as +.Tn ASCII . .It Fl b Causes trailing blanks (spaces and tabs) to be ignored, and other strings of blanks to compare equal. @@ -187,6 +194,18 @@ strings of blanks to compare equal. Try very hard to produce a diff as small as possible. This may consume a lot of processing power and memory when processing large files with many changes. +.It Fl I Ar pattern +Ignores changes, insertions, and deletions whose lines match the +extended regular expression +.Ar pattern . +Multiple +.Fl I +patterns may be specified. +All lines in the change must match some pattern for the change to be +ignored. +See +.Xr re_format 7 +for more information on regular expression patterns. .It Fl i Ignores the case of letters. E.g., @@ -285,8 +304,9 @@ Binary files which differ, common subdirectories, and files which appear in only one directory are described as such. In directory mode only regular files and directories are compared. -If a non-regular file such as a device special file or FIFO is -encountered, a diagnostic message is printed. +If a non-regular file such as a device special file or +.Tn FIFO +is encountered, a diagnostic message is printed. .Pp If only one of .Ar file1 @@ -372,11 +392,11 @@ Replace the range of specified lines with the line .Va ZZ . .It Li XX,YY Ns Ic c Ns Li ZZ,QQ Replace the range -.Va XX , Ns YY +.Va XX , Ns Va YY from .Ar file1 with the range -.Va ZZ , Ns QQ +.Va ZZ , Ns Va QQ from .Ar file2 . .El @@ -418,7 +438,7 @@ as the temporary directory. .El .Sh FILES .Bl -tag -width /tmp/diff.XXXXXXXX -compact -.It Pa /tmp/diff.XXXXXXXX +.It Pa /tmp/diff. Ns Ar XXXXXXXX Temporary file used when comparing a device or the standard input. Note that the temporary file is unlinked as soon as it is created so it will not show up in a directory listing. @@ -442,7 +462,8 @@ An error occurred. .Xr diff3 1 , .Xr ed 1 , .Xr pr 1 , -.Xr fnmatch 3 +.Xr fnmatch 3 , +.Xr re_format 7 .Sh STANDARDS The .Nm diff --git a/usr.bin/diff/diff.c b/usr.bin/diff/diff.c index 134cb37c0f3..b32ee897861 100644 --- a/usr.bin/diff/diff.c +++ b/usr.bin/diff/diff.c @@ -1,4 +1,4 @@ -/* $OpenBSD: diff.c,v 1.45 2004/03/16 00:40:34 millert Exp $ */ +/* $OpenBSD: diff.c,v 1.46 2004/06/20 18:47:45 otto Exp $ */ /* * Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com> @@ -21,7 +21,7 @@ */ #ifndef lint -static const char rcsid[] = "$OpenBSD: diff.c,v 1.45 2004/03/16 00:40:34 millert Exp $"; +static const char rcsid[] = "$OpenBSD: diff.c,v 1.46 2004/06/20 18:47:45 otto Exp $"; #endif /* not lint */ #include <sys/param.h> @@ -43,11 +43,12 @@ static const char rcsid[] = "$OpenBSD: diff.c,v 1.45 2004/03/16 00:40:34 millert int aflag, bflag, dflag, iflag, lflag, Nflag, Pflag, pflag, rflag; int sflag, tflag, Tflag, wflag; int format, context, status; -char *start, *ifdefname, *diffargs, *label; +char *start, *ifdefname, *diffargs, *label, *ignore_pats; struct stat stb1, stb2; struct excludes *excludes_list; +regex_t ignore_re; -#define OPTIONS "0123456789abC:cdD:efhiL:lnNPpqrS:sTtU:uwX:x:" +#define OPTIONS "0123456789abC:cdD:efhI:iL:lnNPpqrS:sTtU:uwX:x:" static struct option longopts[] = { { "text", no_argument, 0, 'a' }, { "ignore-space-change", no_argument, 0, 'b' }, @@ -56,6 +57,7 @@ static struct option longopts[] = { { "minimal", no_argument, 0, 'd' }, { "ed", no_argument, 0, 'e' }, { "forward-ed", no_argument, 0, 'f' }, + { "ignore-matching-lines", required_argument, 0, 'I' }, { "ignore-case", no_argument, 0, 'i' }, { "paginate", no_argument, 0, 'l' }, { "label", required_argument, 0, 'L' }, @@ -78,6 +80,7 @@ static struct option longopts[] = { __dead void usage(void); void push_excludes(char *); +void push_ignore_pats(char *); void read_excludes_file(char *file); void set_argstr(char **, char **); @@ -139,6 +142,9 @@ main(int argc, char **argv) case 'h': /* silently ignore for backwards compatibility */ break; + case 'I': + push_ignore_pats(optarg); + break; case 'i': iflag = 1; break; @@ -216,6 +222,19 @@ main(int argc, char **argv) */ if (argc != 2) usage(); + if (ignore_pats != NULL) { + char buf[BUFSIZ]; + int error; + + if ((error = regcomp(&ignore_re, ignore_pats, + REG_NEWLINE | REG_EXTENDED)) != 0) { + regerror(error, &ignore_re, buf, sizeof(buf)); + if (*ignore_pats != '\0') + errx(2, "%s: %s", ignore_pats, buf); + else + errx(2, "%s", buf); + } + } if (strcmp(argv[0], "-") == 0) { fstat(STDIN_FILENO, &stb1); gotstdin = 1; @@ -343,6 +362,25 @@ push_excludes(char *pattern) } void +push_ignore_pats(char *pattern) +{ + size_t len; + + if (ignore_pats == NULL) { + /* XXX: estrdup */ + len = strlen(pattern) + 1; + ignore_pats = emalloc(len); + strlcpy(ignore_pats, pattern, len); + } else { + /* old + "|" + new + NUL */ + len = strlen(ignore_pats) + strlen(pattern) + 2; + ignore_pats = erealloc(ignore_pats, len); + strlcat(ignore_pats, "|", len); + strlcat(ignore_pats, pattern, len); + } +} + +void print_only(const char *path, size_t dirlen, const char *entry) { if (dirlen > 1) @@ -400,12 +438,14 @@ __dead void usage(void) { (void)fprintf(stderr, - "usage: diff [-abdilpqtTw] [-c | -e | -f | -n | -u] [-L label] file1 file2\n" - " diff [-abdilpqtTw] [-L label] -C number file1 file2\n" - " diff [-abdilqtw] -D string file1 file2\n" - " diff [-abdilpqtTw] [-L label] -U number file1 file2\n" - " diff [-abdilNPpqtTw] [-c | -e | -f | -n | -u ] [-L label] [-r] [-s]\n" - " [-S name] [-X file] [-x pattern] dir1 dir2\n"); + "usage: diff [-abdilpqtTw] [-I pattern] [-c | -e | -f | -n | -u]\n" + " [-L label] file1 file2\n" + " diff [-abdilpqtTw] [-I pattern] [-L label] -C number file1 file2\n" + " diff [-abdilqtw] [-I pattern] -D string file1 file2\n" + " diff [-abdilpqtTw] [-I pattern] [-L label] -U number file1 file2\n" + " diff [-abdilNPpqtTw] [-I pattern] [-c | -e | -f | -n | -u]\n" + " [-L label] [-r] [-s] [-S name] [-X file] [-x pattern] dir1\n" + " dir2\n"); exit(2); } diff --git a/usr.bin/diff/diff.h b/usr.bin/diff/diff.h index d9af1a94c0e..8d5e70813dd 100644 --- a/usr.bin/diff/diff.h +++ b/usr.bin/diff/diff.h @@ -1,4 +1,4 @@ -/* $OpenBSD: diff.h,v 1.27 2004/03/16 00:40:34 millert Exp $ */ +/* $OpenBSD: diff.h,v 1.28 2004/06/20 18:47:45 otto Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -31,6 +31,9 @@ * @(#)diff.h 8.1 (Berkeley) 6/6/93 */ +#include <sys/types.h> +#include <regex.h> + /* * Output format options */ @@ -73,9 +76,10 @@ struct excludes { extern int aflag, bflag, dflag, iflag, lflag, Nflag, Pflag, pflag, rflag, sflag, tflag, Tflag, wflag; extern int format, context, status; -extern char *start, *ifdefname, *diffargs, *label; +extern char *start, *ifdefname, *diffargs, *label, *ignore_pats; extern struct stat stb1, stb2; extern struct excludes *excludes_list; +extern regex_t ignore_re; char *splice(char *, char *); int diffreg(char *, char *, int); diff --git a/usr.bin/diff/diffreg.c b/usr.bin/diff/diffreg.c index 6c5b36ce3ae..cccd4305353 100644 --- a/usr.bin/diff/diffreg.c +++ b/usr.bin/diff/diffreg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: diffreg.c,v 1.56 2004/06/18 07:23:50 otto Exp $ */ +/* $OpenBSD: diffreg.c,v 1.57 2004/06/20 18:47:45 otto Exp $ */ /* * Copyright (C) Caldera International Inc. 2001-2002. @@ -65,7 +65,7 @@ */ #ifndef lint -static const char rcsid[] = "$OpenBSD: diffreg.c,v 1.56 2004/06/18 07:23:50 otto Exp $"; +static const char rcsid[] = "$OpenBSD: diffreg.c,v 1.57 2004/06/20 18:47:45 otto Exp $"; #endif /* not lint */ #include <sys/param.h> @@ -214,6 +214,7 @@ static void unravel(int); static void unsort(struct line *, int, int *); static void change(char *, FILE *, char *, FILE *, int, int, int, int); static void sort(struct line *, int); +static int ignoreline(char *); static int asciifile(FILE *); static int fetch(long *, int, int, FILE *, int, int); static int newcand(int, int, int); @@ -226,6 +227,7 @@ static int files_differ(FILE *, FILE *, int); static __inline int min(int, int); static __inline int max(int, int); static char *match_function(const long *, int, FILE *); +static char *preadline(int, size_t, off_t); /* @@ -965,6 +967,29 @@ uni_range(int a, int b) printf("%d,0", b); } +static char * +preadline(int fd, size_t len, off_t off) +{ + char *line; + ssize_t nr; + + line = emalloc(len + 1); + if ((nr = pread(fd, line, len, off)) < 0) + err(1, "preadline"); + line[nr] = '\0'; + return (line); +} + +static int +ignoreline(char *line) +{ + int ret; + + ret = regexec(&ignore_re, line, 0, NULL, 0); + free(line); + return (ret == 0); /* if it matched, it should be ignored. */ +} + /* * Indicate that there is a difference between lines a and b of the from file * to get to lines c to d of the to file. If a is greater then b then there @@ -981,6 +1006,32 @@ change(char *file1, FILE *f1, char *file2, FILE *f2, int a, int b, int c, int d) restart: if (format != D_IFDEF && a > b && c > d) return; + if (ignore_pats != NULL) { + char *line; + /* + * All lines in the change, insert, or delete must + * match an ignore pattern for the change to be + * ignored. + */ + if (a <= b) { /* Changes and deletes. */ + for (i = a; i <= b; i++) { + line = preadline(fileno(f1), + ixold[i] - ixold[i - 1], ixold[i - 1]); + if (!ignoreline(line)) + goto proceed; + } + } + if (a > b || c <= d) { /* Changes and inserts. */ + for (i = c; i <= d; i++) { + line = preadline(fileno(f2), + ixnew[i] - ixnew[i - 1], ixnew[i - 1]); + if (!ignoreline(line)) + goto proceed; + } + } + return; + } +proceed: if (format == D_CONTEXT || format == D_UNIFIED) { /* * Allocate change records as needed. |