git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] add a diff-files command (revised and cleaned up)

From
Nicolas Pitre <nico@cam.org>
Date
Apr 28, 2005, 17:35 UTC
Message-ID
<Pine.LNX.4.62.0504281327520.14033@localhost.localdomain>
In-Reply-To
<Pine.LNX.4.58.0504280950340.18901@ppc970.osdl.org>
On Thu, 28 Apr 2005, Linus Torvalds wrote:
> HOWEVER, there clearly is a separate problem, which is what "show-files"  
> currently does very badly (and not at all in some cases), which is the 
> "ok, what about the _other_ files?"
Right.  And that's the problem I'm trying to solve.
What about this patch then?
=====
Give show-files the ability to process exclusion pattern.

This can be used with the famous dontdiff file as follows to find out about uncommitted files just like dontdiff is used with the diff command:

    show-files --others --exclude-from=dontdiff
and the exclude list can be reversed with the --ignore switch.
Signed-off-by: Nicolas Pitre <nico@cam.org>
--- a/show-files.c
+++ b/show-files.c
@@ -6,6 +6,7 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include <dirent.h>
+#include <fnmatch.h>
 
 #include "cache.h"
 
@@ -17,6 +18,70 @@ static int show_stage = 0;
 static int show_unmerged = 0;
 static int line_terminator = '\n';
 
+static int nr_excludes;
+static const char **excludes;
+static int excludes_alloc;
+
+static void add_exclude(const char *string)
+{
+	if (nr_excludes == excludes_alloc) {
+		excludes_alloc = alloc_nr(excludes_alloc);
+		excludes = realloc(excludes, excludes_alloc*sizeof(char *));
+	}
+	excludes[nr_excludes++] = string;
+}
+
+static void add_excludes_from_file(const char *fname)
+{
+	int fd, i;
+	long size;
+	char *buf, *entry;
+
+	fd = open(fname, O_RDONLY);
+	if (fd < 0)
+		goto err;
+	size = lseek(fd, 0, SEEK_END);
+	if (size < 0)
+		goto err;
+	lseek(fd, 0, SEEK_SET);
+	if (size == 0) {
+		close(fd);
+		return;
+	}
+	buf = xmalloc(size);
+	if (read(fd, buf, size) != size)
+		goto err;
+	close(fd);
+
+	entry = buf;
+	for (i = 0; i < size; i++) {
+		if (buf[i] == '\n') {
+			if (entry != buf + i) {
+				buf[i] = 0;
+				add_exclude(entry);
+			}
+			entry = buf + i + 1;
+		}
+	}
+	return;
+
+err:	perror(fname);
+	exit(1);
+}
+
+static int excluded(const char *pathname)
+{
+	int i;
+	if (nr_excludes) {
+		const char *basename = strrchr(pathname, '/');
+		basename = (basename) ? basename+1 : pathname;
+		for (i = 0; i < nr_excludes; i++)
+			if (fnmatch(excludes[i], basename, 0) == 0)
+				return 1;
+	}
+	return 0;
+}
+
 static const char **dir;
 static int nr_dir;
 static int dir_alloc;
@@ -59,6 +124,8 @@ static void read_directory(const char *p
 
 			if (de->d_name[0] == '.')
 				continue;
+			if (excluded(de->d_name) != show_ignored)
+				continue;
 			len = strlen(de->d_name);
 			memcpy(fullname + baselen, de->d_name, len+1);
 
@@ -101,17 +168,17 @@ static void show_files(void)
 	int i;
 
 	/* For cached/deleted files we don't need to even do the readdir */
-	if (show_others | show_ignored) {
+	if (show_others) {
 		read_directory(".", "", 0);
 		qsort(dir, nr_dir, sizeof(char *), cmp_name);
-	}
-	if (show_others) {
 		for (i = 0; i < nr_dir; i++)
 			printf("%s%c", dir[i], line_terminator);
 	}
 	if (show_cached | show_stage) {
 		for (i = 0; i < active_nr; i++) {
 			struct cache_entry *ce = active_cache[i];
+			if (excluded(ce->name) != show_ignored)
+				continue;
 			if (show_unmerged && !ce_stage(ce))
 				continue;
 			if (!show_stage)
@@ -130,14 +197,13 @@ static void show_files(void)
 		for (i = 0; i < active_nr; i++) {
 			struct cache_entry *ce = active_cache[i];
 			struct stat st;
+			if (excluded(ce->name) != show_ignored)
+				continue;
 			if (!stat(ce->name, &st))
 				continue;
 			printf("%s%c", ce->name, line_terminator);
 		}
 	}
-	if (show_ignored) {
-		/* We don't have any "ignore" list yet */
-	}
 }
 
 int main(int argc, char **argv)
@@ -179,11 +245,34 @@ int main(int argc, char **argv)
 			continue;
 		}
 
-		usage("show-files [-z] (--[cached|deleted|others|ignored|stage])*");
+		if (!strcmp(arg, "-x") && i+1 < argc) {
+			add_exclude(argv[++i]);
+			continue;
+		}
+		if (!strncmp(arg, "--exclude=", 10)) {
+			add_exclude(arg+10);
+			continue;
+		}
+		if (!strcmp(arg, "-X") && i+1 < argc) {
+			add_excludes_from_file(argv[++i]);
+			continue;
+		}
+		if (!strncmp(arg, "--exclude-from=", 15)) {
+			add_excludes_from_file(arg+15);
+			continue;
+		}
+
+		usage("show-files [-z] (--[cached|deleted|others|stage])* "
+		      "[ --ignored [--exclude=<pattern>] [--exclude-from=<file>) ]");
+	}
+
+	if (show_ignored && !nr_excludes) {
+		fprintf(stderr, "%s: --ignored needs some exclude pattern\n", argv[0]);
+		exit(1);
 	}
 
 	/* With no flags, we default to showing the cached files */
-	if (!(show_stage | show_deleted | show_others | show_ignored | show_unmerged))
+	if (!(show_stage | show_deleted | show_others | show_unmerged))
 		show_cached = 1;
 
 	read_cache();
Previous: Linus TorvaldsNext: Junio C Hamano
Message 3 of 4 in “add a diff-files command (revised and cleaned up)”
  1. add a diff-files command (revised and cleaned up)Nicolas Pitre, Apr 28, 2005
  2. Linus TorvaldsApr 28, 2005
  3. Nicolas PitreApr 28, 2005
  4. Junio C HamanoApr 28, 2005

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.