Implement a basic --changed-group-format
etcupdate(8) requires that option, while GNU diff supports many more variation of that options, their behaviour beside the simple verion implemented here are quite inconsistent as such I do not plan to implement those. The only special keyword supported by this implementation are: %< and %> %= is not implemented as the documentation of GNU diff says: common lines, but it actually when tested print the changes from the first file
This commit is contained in:
parent
be13fe9688
commit
e676ac4a5f
@ -30,7 +30,7 @@
|
|||||||
.\" @(#)diff.1 8.1 (Berkeley) 6/30/93
|
.\" @(#)diff.1 8.1 (Berkeley) 6/30/93
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd April 8, 2017
|
.Dd April 20, 2017
|
||||||
.Dt DIFF 1
|
.Dt DIFF 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -44,6 +44,7 @@
|
|||||||
.Fl n | q | u
|
.Fl n | q | u
|
||||||
.Oc
|
.Oc
|
||||||
.Op Fl -brief
|
.Op Fl -brief
|
||||||
|
.Op Fl -changed-group-format Ar GFMT
|
||||||
.Op Fl -ed
|
.Op Fl -ed
|
||||||
.Op Fl -expand-tabs
|
.Op Fl -expand-tabs
|
||||||
.Op Fl -forward-ed
|
.Op Fl -forward-ed
|
||||||
@ -70,6 +71,7 @@
|
|||||||
.Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern
|
.Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern
|
||||||
.Op Fl L Ar label | Fl -label Ar label
|
.Op Fl L Ar label | Fl -label Ar label
|
||||||
.Op Fl -brief
|
.Op Fl -brief
|
||||||
|
.Op Fl -changed-group-format Ar GFMT
|
||||||
.Op Fl -ed
|
.Op Fl -ed
|
||||||
.Op Fl -expand-tabs
|
.Op Fl -expand-tabs
|
||||||
.Op Fl -forward-ed
|
.Op Fl -forward-ed
|
||||||
@ -94,6 +96,7 @@
|
|||||||
.Op Fl abdiltw
|
.Op Fl abdiltw
|
||||||
.Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern
|
.Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern
|
||||||
.Op Fl -brief
|
.Op Fl -brief
|
||||||
|
.Op Fl -changed-group-format Ar GFMT
|
||||||
.Op Fl -ed
|
.Op Fl -ed
|
||||||
.Op Fl -expand-tabs
|
.Op Fl -expand-tabs
|
||||||
.Op Fl -forward-ed
|
.Op Fl -forward-ed
|
||||||
@ -119,6 +122,7 @@
|
|||||||
.Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern
|
.Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern
|
||||||
.Op Fl L Ar label | Fl -label Ar label
|
.Op Fl L Ar label | Fl -label Ar label
|
||||||
.Op Fl -brief
|
.Op Fl -brief
|
||||||
|
.Op Fl -changed-group-format Ar GFMT
|
||||||
.Op Fl -ed
|
.Op Fl -ed
|
||||||
.Op Fl -expand-tabs
|
.Op Fl -expand-tabs
|
||||||
.Op Fl -forward-ed
|
.Op Fl -forward-ed
|
||||||
@ -146,6 +150,7 @@
|
|||||||
.Fl n | q | u
|
.Fl n | q | u
|
||||||
.Oc
|
.Oc
|
||||||
.Op Fl -brief
|
.Op Fl -brief
|
||||||
|
.Op Fl -changed-group-format Ar GFMT
|
||||||
.Op Fl -context
|
.Op Fl -context
|
||||||
.Op Fl -ed
|
.Op Fl -ed
|
||||||
.Op Fl -expand-tabs
|
.Op Fl -expand-tabs
|
||||||
@ -355,6 +360,16 @@ E.g.,
|
|||||||
.Dq if (\ \&a == b \&)
|
.Dq if (\ \&a == b \&)
|
||||||
will compare equal to
|
will compare equal to
|
||||||
.Dq if(a==b) .
|
.Dq if(a==b) .
|
||||||
|
.It Fl -changed-group-format Ar GFMT
|
||||||
|
Format input groups in the provided
|
||||||
|
.Pp
|
||||||
|
the format is a string with special keywords:
|
||||||
|
.Bl -tag -width %<
|
||||||
|
.It %<
|
||||||
|
lines from FILE1
|
||||||
|
.It %<
|
||||||
|
lines from FILE2
|
||||||
|
.El
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
Directory comparison options:
|
Directory comparison options:
|
||||||
|
@ -41,6 +41,7 @@ int lflag, Nflag, Pflag, rflag, sflag, Tflag, cflag;
|
|||||||
int diff_format, diff_context, status, ignore_file_case;
|
int diff_format, diff_context, status, ignore_file_case;
|
||||||
int tabsize = 8;
|
int tabsize = 8;
|
||||||
char *start, *ifdefname, *diffargs, *label[2], *ignore_pats;
|
char *start, *ifdefname, *diffargs, *label[2], *ignore_pats;
|
||||||
|
char *group_format = NULL;
|
||||||
struct stat stb1, stb2;
|
struct stat stb1, stb2;
|
||||||
struct excludes *excludes_list;
|
struct excludes *excludes_list;
|
||||||
regex_t ignore_re;
|
regex_t ignore_re;
|
||||||
@ -54,6 +55,7 @@ enum {
|
|||||||
OPT_NORMAL,
|
OPT_NORMAL,
|
||||||
OPT_HORIZON_LINES,
|
OPT_HORIZON_LINES,
|
||||||
OPT_SPEED_LARGE_FILES,
|
OPT_SPEED_LARGE_FILES,
|
||||||
|
OPT_CHANGED_GROUP_FORMAT,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct option longopts[] = {
|
static struct option longopts[] = {
|
||||||
@ -89,6 +91,7 @@ static struct option longopts[] = {
|
|||||||
{ "speed-large-files", no_argument, NULL, OPT_SPEED_LARGE_FILES},
|
{ "speed-large-files", no_argument, NULL, OPT_SPEED_LARGE_FILES},
|
||||||
{ "strip-trailing-cr", no_argument, NULL, OPT_STRIPCR },
|
{ "strip-trailing-cr", no_argument, NULL, OPT_STRIPCR },
|
||||||
{ "tabsize", optional_argument, NULL, OPT_TSIZE },
|
{ "tabsize", optional_argument, NULL, OPT_TSIZE },
|
||||||
|
{ "changed-group-format", required_argument, NULL, OPT_CHANGED_GROUP_FORMAT},
|
||||||
{ NULL, 0, 0, '\0'}
|
{ NULL, 0, 0, '\0'}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -227,6 +230,10 @@ main(int argc, char **argv)
|
|||||||
case 'x':
|
case 'x':
|
||||||
push_excludes(optarg);
|
push_excludes(optarg);
|
||||||
break;
|
break;
|
||||||
|
case OPT_CHANGED_GROUP_FORMAT:
|
||||||
|
diff_format = D_GFORMAT;
|
||||||
|
group_format = optarg;
|
||||||
|
break;
|
||||||
case OPT_HORIZON_LINES:
|
case OPT_HORIZON_LINES:
|
||||||
break; /* XXX TODO for compatibility with GNU diff3 */
|
break; /* XXX TODO for compatibility with GNU diff3 */
|
||||||
case OPT_IGN_FN_CASE:
|
case OPT_IGN_FN_CASE:
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#define D_NREVERSE 5 /* Reverse ed script with numbered
|
#define D_NREVERSE 5 /* Reverse ed script with numbered
|
||||||
lines and no trailing . */
|
lines and no trailing . */
|
||||||
#define D_BRIEF 6 /* Say if the files differ */
|
#define D_BRIEF 6 /* Say if the files differ */
|
||||||
|
#define D_GFORMAT 7 /* Diff with defined changed group format */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Output flags
|
* Output flags
|
||||||
@ -87,6 +88,7 @@ extern int lflag, Nflag, Pflag, rflag, sflag, Tflag, cflag;
|
|||||||
extern int diff_format, diff_context, status, ignore_file_case;
|
extern int diff_format, diff_context, status, ignore_file_case;
|
||||||
extern int tabsize;
|
extern int tabsize;
|
||||||
extern char *start, *ifdefname, *diffargs, *label[2], *ignore_pats;
|
extern char *start, *ifdefname, *diffargs, *label[2], *ignore_pats;
|
||||||
|
extern char *group_format;
|
||||||
extern struct stat stb1, stb2;
|
extern struct stat stb1, stb2;
|
||||||
extern struct excludes *excludes_list;
|
extern struct excludes *excludes_list;
|
||||||
extern regex_t ignore_re;
|
extern regex_t ignore_re;
|
||||||
|
@ -1008,7 +1008,7 @@ output(char *file1, FILE *f1, char *file2, FILE *f2, int flags)
|
|||||||
}
|
}
|
||||||
if (m == 0)
|
if (m == 0)
|
||||||
change(file1, f1, file2, f2, 1, 0, 1, len[1], &flags);
|
change(file1, f1, file2, f2, 1, 0, 1, len[1], &flags);
|
||||||
if (diff_format == D_IFDEF) {
|
if (diff_format == D_IFDEF || diff_format == D_GFORMAT) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
#define c i0
|
#define c i0
|
||||||
if ((c = getc(f1)) == EOF)
|
if ((c = getc(f1)) == EOF)
|
||||||
@ -1081,10 +1081,13 @@ change(char *file1, FILE *f1, char *file2, FILE *f2, int a, int b, int c, int d,
|
|||||||
int *pflags)
|
int *pflags)
|
||||||
{
|
{
|
||||||
static size_t max_context = 64;
|
static size_t max_context = 64;
|
||||||
int i;
|
long curpos;
|
||||||
|
int i, nc;
|
||||||
|
const char *walk;
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
if (diff_format != D_IFDEF && a > b && c > d)
|
if ((diff_format != D_IFDEF || diff_format == D_GFORMAT) &&
|
||||||
|
a > b && c > d)
|
||||||
return;
|
return;
|
||||||
if (ignore_pats != NULL) {
|
if (ignore_pats != NULL) {
|
||||||
char *line;
|
char *line;
|
||||||
@ -1181,12 +1184,38 @@ proceed:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (diff_format == D_GFORMAT) {
|
||||||
|
curpos = ftell(f1);
|
||||||
|
/* print through if append (a>b), else to (nb: 0 vs 1 orig) */
|
||||||
|
nc = ixold[a > b ? b : a - 1] - curpos;
|
||||||
|
for (i = 0; i < nc; i++)
|
||||||
|
diff_output("%c", getc(f1));
|
||||||
|
for (walk = group_format; *walk != '\0'; walk++) {
|
||||||
|
if (*walk == '%') {
|
||||||
|
walk++;
|
||||||
|
switch (*walk) {
|
||||||
|
case '<':
|
||||||
|
fetch(ixold, a, b, f1, '<', 1, *pflags);
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
fetch(ixnew, c, d, f2, '>', 0, *pflags);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
diff_output("%%%c", *walk);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
diff_output("%c", *walk);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (diff_format == D_NORMAL || diff_format == D_IFDEF) {
|
if (diff_format == D_NORMAL || diff_format == D_IFDEF) {
|
||||||
fetch(ixold, a, b, f1, '<', 1, *pflags);
|
fetch(ixold, a, b, f1, '<', 1, *pflags);
|
||||||
if (a <= b && c <= d && diff_format == D_NORMAL)
|
if (a <= b && c <= d && diff_format == D_NORMAL)
|
||||||
diff_output("---\n");
|
diff_output("---\n");
|
||||||
}
|
}
|
||||||
i = fetch(ixnew, c, d, f2, diff_format == D_NORMAL ? '>' : '\0', 0, *pflags);
|
if (diff_format != D_GFORMAT)
|
||||||
|
i = fetch(ixnew, c, d, f2, diff_format == D_NORMAL ? '>' : '\0', 0, *pflags);
|
||||||
if (i != 0 && diff_format == D_EDIT) {
|
if (i != 0 && diff_format == D_EDIT) {
|
||||||
/*
|
/*
|
||||||
* A non-zero return value for D_EDIT indicates that the
|
* A non-zero return value for D_EDIT indicates that the
|
||||||
@ -1220,7 +1249,7 @@ fetch(long *f, int a, int b, FILE *lb, int ch, int oldfile, int flags)
|
|||||||
* When doing #ifdef's, copy down to current line
|
* When doing #ifdef's, copy down to current line
|
||||||
* if this is the first file, so that stuff makes it to output.
|
* if this is the first file, so that stuff makes it to output.
|
||||||
*/
|
*/
|
||||||
if (diff_format == D_IFDEF && oldfile) {
|
if ((diff_format == D_IFDEF) && oldfile) {
|
||||||
long curpos = ftell(lb);
|
long curpos = ftell(lb);
|
||||||
/* print through if append (a>b), else to (nb: 0 vs 1 orig) */
|
/* print through if append (a>b), else to (nb: 0 vs 1 orig) */
|
||||||
nc = f[a > b ? b : a - 1] - curpos;
|
nc = f[a > b ? b : a - 1] - curpos;
|
||||||
@ -1244,7 +1273,8 @@ fetch(long *f, int a, int b, FILE *lb, int ch, int oldfile, int flags)
|
|||||||
for (i = a; i <= b; i++) {
|
for (i = a; i <= b; i++) {
|
||||||
fseek(lb, f[i - 1], SEEK_SET);
|
fseek(lb, f[i - 1], SEEK_SET);
|
||||||
nc = f[i] - f[i - 1];
|
nc = f[i] - f[i - 1];
|
||||||
if (diff_format != D_IFDEF && ch != '\0') {
|
if ((diff_format != D_IFDEF && diff_format != D_GFORMAT) &&
|
||||||
|
ch != '\0') {
|
||||||
diff_output("%c", ch);
|
diff_output("%c", ch);
|
||||||
if (Tflag && (diff_format == D_NORMAL || diff_format == D_CONTEXT
|
if (Tflag && (diff_format == D_NORMAL || diff_format == D_CONTEXT
|
||||||
|| diff_format == D_UNIFIED))
|
|| diff_format == D_UNIFIED))
|
||||||
|
@ -22,7 +22,8 @@ ${PACKAGE}FILES+= \
|
|||||||
unified_9999.out \
|
unified_9999.out \
|
||||||
header.out \
|
header.out \
|
||||||
header_ns.out \
|
header_ns.out \
|
||||||
ifdef.out
|
ifdef.out \
|
||||||
|
group-format.out
|
||||||
|
|
||||||
NETBSD_ATF_TESTS_SH+= netbsd_diff_test
|
NETBSD_ATF_TESTS_SH+= netbsd_diff_test
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ atf_test_case unified
|
|||||||
atf_test_case header
|
atf_test_case header
|
||||||
atf_test_case header_ns
|
atf_test_case header_ns
|
||||||
atf_test_case ifdef
|
atf_test_case ifdef
|
||||||
|
atf_test_case group_format
|
||||||
|
|
||||||
simple_body()
|
simple_body()
|
||||||
{
|
{
|
||||||
@ -78,6 +79,15 @@ ifdef_body()
|
|||||||
"$(atf_get_srcdir)/input_c2.in"
|
"$(atf_get_srcdir)/input_c2.in"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group_format_body()
|
||||||
|
{
|
||||||
|
atf_check -o file:$(atf_get_srcdir)/group-format.out -s eq:1 \
|
||||||
|
diff --changed-group-format='<<<<<<< (local)
|
||||||
|
%<=======
|
||||||
|
%>>>>>>>> (stock)
|
||||||
|
' "$(atf_get_srcdir)/input_c1.in" "$(atf_get_srcdir)/input_c2.in"
|
||||||
|
}
|
||||||
|
|
||||||
atf_init_test_cases()
|
atf_init_test_cases()
|
||||||
{
|
{
|
||||||
atf_add_test_case simple
|
atf_add_test_case simple
|
||||||
@ -85,4 +95,5 @@ atf_init_test_cases()
|
|||||||
atf_add_test_case header
|
atf_add_test_case header
|
||||||
atf_add_test_case header_ns
|
atf_add_test_case header_ns
|
||||||
atf_add_test_case ifdef
|
atf_add_test_case ifdef
|
||||||
|
atf_add_test_case group_format
|
||||||
}
|
}
|
||||||
|
27
usr.bin/diff/tests/group-format.out
Normal file
27
usr.bin/diff/tests/group-format.out
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* A comment
|
||||||
|
*
|
||||||
|
<<<<<<< (local)
|
||||||
|
* And another bla
|
||||||
|
=======
|
||||||
|
* And another bla
|
||||||
|
>>>>>>> (stock)
|
||||||
|
*
|
||||||
|
<<<<<<< (local)
|
||||||
|
* And yet another
|
||||||
|
=======
|
||||||
|
* and yet another
|
||||||
|
>>>>>>> (stock)
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
<<<<<<< (local)
|
||||||
|
=======
|
||||||
|
|
||||||
|
>>>>>>> (stock)
|
||||||
|
printf("something");
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user