From 75703eb8d5bd0d8d9ef0a8abaf25b421ca668ab5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 10 Jul 2010 16:25:47 +0200 Subject: diff: make diff -r much less eager to recurse into directories function old new delta skip_dir 44 120 +76 diff_main 1175 1185 +10 Signed-off-by: Denys Vlasenko --- editors/diff.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/editors/diff.c b/editors/diff.c index 3e20483..a3ca2b6 100644 --- a/editors/diff.c +++ b/editors/diff.c @@ -121,6 +121,7 @@ typedef struct FILE_and_pos_t { struct globals { smallint exit_status; int opt_U_context; + const char *other_dir; char *label[2]; struct stat stb[2]; }; @@ -761,7 +762,7 @@ static int FAST_FUNC add_to_dirlist(const char *filename, { struct dlist *const l = userdata; const char *file = filename + l->len; - while(*file == '/') + while (*file == '/') file++; l->dl = xrealloc_vector(l->dl, 6, l->e); l->dl[l->e] = xstrdup(file); @@ -780,6 +781,25 @@ static int FAST_FUNC skip_dir(const char *filename, add_to_dirlist(filename, sb, userdata, depth); return SKIP; } + if (!(option_mask32 & FLAG(N))) { + /* -r without -N: no need to recurse into dirs + * which do not exist on the "other side". + * Testcase: diff -r /tmp / + * (it would recurse deep into /proc without this code) */ + struct dlist *const l = userdata; + filename += l->len; + if (filename[0]) { + struct stat osb; + char *othername = concat_path_file(G.other_dir, filename); + int r = stat(othername, &osb); + free(othername); + if (r != 0 || !S_ISDIR(osb.st_mode)) { + /* other dir doesn't have similarly named + * directory, don't recurse */ + return SKIP; + } + } + } return TRUE; } @@ -793,6 +813,7 @@ static void diffdir(char *p[2], const char *s_start) /*list[i].s = list[i].e = 0; - memset did it */ /*list[i].dl = NULL; */ + G.other_dir = p[1 - i]; /* We need to trim root directory prefix. * Using list.len to specify its length, * add_to_dirlist will remove it. */ -- cgit v1.1