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

Re: check-attr doesn't respect recursive definitions

From
Jeff King <peff@peff.net>
Date
Apr 2, 2013, 17:15 UTC
Message-ID
<20130402171557.GA24698@sigill.intra.peff.net>
In-Reply-To
<20130402165128.GA19712@sigill.intra.peff.net>
On Tue, Apr 02, 2013 at 12:51:28PM -0400, Jeff King wrote:
Show 15 quoted lines
> But let's take a step back. I think Jan is trying to do a very
> reasonable thing: come up with the same set of paths that git-archive
> would. What's the best way to solve that? Recursive application of
> attributes is one way, but is there another way we could help with
> solving that?
> 
> Using:
> 
>   git ls-tree --name-only -zrt HEAD |
>   git check-attr --stdin -z export-ignore
> 
> means we can find out that "foo/" is ignored. But he would have to
> manually post-process the output to see that "foo/bar" is below "foo".
> Not impossible, but I just wonder if git can be more helpful in figuring
> this out.

One way to solve the problem is something like the patch below, which allows "git archive --format=lstree" to give an lstree-like listing, but with export-ignore attributes applied.

It feels weirdly specific, though, like there should be a more general solution.

---
 Makefile         |  1 +
 archive-lstree.c | 43 +++++++++++++++++++++++++++++++++++
 archive.c        |  1 +
 archive.h        |  1 +
 quote.c          |  4 ++--
 quote.h          |  1 +
 6 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index e9749ca..5e63d72 100644
--- a/Makefile
+++ b/Makefile
@@ -772,6 +772,7 @@ LIB_OBJS += archive.o
 LIB_OBJS += alias.o
 LIB_OBJS += alloc.o
 LIB_OBJS += archive.o
+LIB_OBJS += archive-lstree.o
 LIB_OBJS += archive-tar.o
 LIB_OBJS += archive-zip.o
 LIB_OBJS += argv-array.o
diff --git a/archive-lstree.c b/archive-lstree.c
new file mode 100644
index 0000000..5ca1bbc
--- /dev/null
+++ b/archive-lstree.c
@@ -0,0 +1,43 @@
+#include "cache.h"
+#include "archive.h"
+#include "quote.h"
+#include "commit.h"
+#include "blob.h"
+
+static int write_lstree_entry(struct archiver_args *args,
+			      const unsigned char *sha1,
+			      const char *path, size_t pathlen,
+			      unsigned int mode)
+{
+	const char *type;
+
+	if (S_ISDIR(mode))
+		return 0;
+	else if (S_ISGITLINK(mode))
+		type = commit_type;
+	else
+		type = blob_type;
+
+	printf("%06o %s %s\t", mode, type, sha1_to_hex(sha1));
+	quote_c_style_counted(path, pathlen, NULL, stdout, 0);
+	printf("\n");
+
+	return 0;
+}
+
+static int write_lstree_archive(const struct archiver *ar,
+				struct archiver_args *args)
+{
+	return write_archive_entries(args, write_lstree_entry);
+}
+
+static struct archiver lstree_archiver = {
+	"lstree",
+	write_lstree_archive,
+	ARCHIVER_REMOTE
+};
+
+void init_lstree_archiver(void)
+{
+	register_archiver(&lstree_archiver);
+}
diff --git a/archive.c b/archive.c
index 3f00da6..4966db7 100644
--- a/archive.c
+++ b/archive.c
@@ -420,6 +420,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
 	git_config(git_default_config, NULL);
 	init_tar_archiver();
 	init_zip_archiver();
+	init_lstree_archiver();
 
 	argc = parse_archive_args(argc, argv, &ar, &args, name_hint, remote);
 	if (nongit) {
diff --git a/archive.h b/archive.h
index 895afcd..1428fc4 100644
--- a/archive.h
+++ b/archive.h
@@ -27,6 +27,7 @@ extern void init_zip_archiver(void);
 
 extern void init_tar_archiver(void);
 extern void init_zip_archiver(void);
+extern void init_lstree_archiver(void);
 
 typedef int (*write_archive_entry_fn_t)(struct archiver_args *args,
 					const unsigned char *sha1,
diff --git a/quote.c b/quote.c
index 911229f..da6b7e4 100644
--- a/quote.c
+++ b/quote.c
@@ -206,8 +206,8 @@ static size_t next_quote_pos(const char *s, ssize_t maxlen)
  *     of name, enclosed with double quotes if asked and needed only.
  *     Return value is the same as in (1).
  */
-static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
-                                    struct strbuf *sb, FILE *fp, int no_dq)
+size_t quote_c_style_counted(const char *name, ssize_t maxlen,
+			     struct strbuf *sb, FILE *fp, int no_dq)
 {
 #undef EMIT
 #define EMIT(c)                                 \
diff --git a/quote.h b/quote.h
index 133155a..f2b8acb 100644
--- a/quote.h
+++ b/quote.h
@@ -55,6 +55,7 @@ extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq
 
 extern int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);
 extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq);
+extern size_t quote_c_style_counted(const char *name, ssize_t len, struct strbuf *, FILE *, int no_dq);
 extern void quote_two_c_style(struct strbuf *, const char *, const char *, int);
 
 extern void write_name_quoted(const char *name, FILE *, int terminator);
Previous: Jeff KingNext: Junio C Hamano
Message 8 of 13 in “check-attr doesn't respect recursive definitions”
  1. Jan LarresMar 30, 2013
  2. Jeff KingApr 2, 2013
  3. Jeff KingApr 2, 2013
  4. Junio C HamanoApr 2, 2013
  5. Jeff KingApr 2, 2013
  6. Junio C HamanoApr 2, 2013
  7. Jeff KingApr 2, 2013
  8. Jeff KingApr 2, 2013
  9. Junio C HamanoApr 2, 2013
  10. Jeff KingApr 2, 2013
  11. Jan LarresApr 3, 2013
  12. Duy NguyenApr 5, 2013
  13. Jan LarresApr 5, 2013

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.