Git Mailing List Archive mirror
 help / color / mirror / Atom feed
* [PATCH 2/2] git-show: use pathattr to run "display"
@ 2007-03-01  7:18 Junio C Hamano
  2007-03-01  9:04 ` Andy Parkins
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Junio C Hamano @ 2007-03-01  7:18 UTC (permalink / raw
  To: git

This is a bit of detour, to demonstrate a possible use of
pathattr infrastructure.  With this,

	$ git show v1.4.4:t/test4012.png

would hopefully do what you would expect.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

 * I was planning to write the config reader as a follow-up, but
   got sidetracked.  After all, doing something whose effect is
   visible is more fun.

 builtin-log.c |   31 ++++++++++++++++++++++++-------
 pathattr.c    |    8 ++++++++
 pathattr.h    |    3 +++
 3 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/builtin-log.c b/builtin-log.c
index 1c9f7d0..519fab2 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -12,6 +12,7 @@
 #include "builtin.h"
 #include "tag.h"
 #include "reflog-walk.h"
+#include "pathattr.h"
 
 static int default_show_root = 1;
 
@@ -86,26 +87,42 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix)
 	return cmd_log_walk(&rev);
 }
 
-static int show_object(const unsigned char *sha1, int suppress_header)
+static void to_stdout(const unsigned char *blobdata, unsigned long size)
+{
+	fwrite(blobdata, size, 1, stdout);
+}
+
+static int show_object(const unsigned char *sha1, const char *path, int nohead)
 {
 	unsigned long size;
 	enum object_type type;
-	char *buf = read_sha1_file(sha1, &type, &size);
+	unsigned char *buf = read_sha1_file(sha1, &type, &size);
 	int offset = 0;
+	pretty_fn pretty = to_stdout;
 
 	if (!buf)
 		return error("Could not read object %s", sha1_to_hex(sha1));
 
-	if (suppress_header)
+	if (nohead) {
 		while (offset < size && buf[offset++] != '\n') {
 			int new_offset = offset;
 			while (new_offset < size && buf[new_offset++] != '\n')
 				; /* do nothing */
 			offset = new_offset;
 		}
+	}
+
+	if (size <= offset)
+		goto finish;
+
+	if (path) {
+		const struct pathattr *a = pathattr_lookup(path);
+		if (a && a->pretty)
+			pretty = a->pretty;
+	}
 
-	if (offset < size)
-		fwrite(buf + offset, size - offset, 1, stdout);
+	pretty(buf + offset, size - offset);
+ finish:
 	free(buf);
 	return 0;
 }
@@ -142,7 +159,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
 		const char *name = objects[i].name;
 		switch (o->type) {
 		case OBJ_BLOB:
-			ret = show_object(o->sha1, 0);
+			ret = show_object(o->sha1, name, 0);
 			break;
 		case OBJ_TAG: {
 			struct tag *t = (struct tag *)o;
@@ -153,7 +170,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
 					t->tag,
 					diff_get_color(rev.diffopt.color_diff,
 						DIFF_RESET));
-			ret = show_object(o->sha1, 1);
+			ret = show_object(o->sha1, name, 1);
 			objects[i].item = (struct object *)t->tagged;
 			i--;
 			break;
diff --git a/pathattr.c b/pathattr.c
index 06bbb4e..c84be39 100644
--- a/pathattr.c
+++ b/pathattr.c
@@ -1,6 +1,13 @@
 #include "cache.h"
 #include "pathattr.h"
 
+static void show_display(const unsigned char *blobdata, unsigned long size)
+{
+	FILE *display = popen("display -", "w");
+	fwrite(blobdata, size, 1, display);
+	fclose(display);
+}
+
 /*
  * Path match specification
  */
@@ -93,6 +100,7 @@ static void init_stack(void)
 	a = locate(stk, "image/*");
 	a->conv_i = NULL;
 	a->conv_o = NULL;
+	a->pretty = show_display;
 	add_match(stk, a, "*.png");
 	add_match(stk, a, "*.jpg");
 	add_match(stk, a, "*.gif");
diff --git a/pathattr.h b/pathattr.h
index 4ca4e60..bfd9ff1 100644
--- a/pathattr.h
+++ b/pathattr.h
@@ -3,6 +3,8 @@
 
 #include "convert.h"
 
+typedef void (*pretty_fn)(const unsigned char *blobdata, unsigned long size);
+
 /*
  * Data in one section of [pathattr "name"], except
  * the path match specification.
@@ -11,6 +13,7 @@ struct pathattr {
 	char *name;
 	convi_fn conv_i;
 	convo_fn conv_o;
+	pretty_fn pretty;
 };
 
 const struct pathattr *pathattr_lookup(const char *);
-- 
1.5.0.2.809.g0f936

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/2] git-show: use pathattr to run "display"
  2007-03-01  7:18 [PATCH 2/2] git-show: use pathattr to run "display" Junio C Hamano
@ 2007-03-01  9:04 ` Andy Parkins
  2007-03-01  9:17   ` Andy Parkins
  2007-03-01  9:26 ` [PATCH 3/2] pathattr: read from git_config() Junio C Hamano
  2007-03-01  9:29 ` [PATCH 4/2] pathattr: allow piping to external program Junio C Hamano
  2 siblings, 1 reply; 6+ messages in thread
From: Andy Parkins @ 2007-03-01  9:04 UTC (permalink / raw
  To: git; +Cc: Junio C Hamano

On Thursday 2007 March 01 07:18, Junio C Hamano wrote:
> This is a bit of detour, to demonstrate a possible use of
> pathattr infrastructure.  With this,
>
> 	$ git show v1.4.4:t/test4012.png
>
> would hopefully do what you would expect.

Is this serious?  This doesn't belong inside git does it?

What if I don't want to run "display"?  What if I don't want to run anything, 
and just want png files dumped raw to the terminal?



Andy

-- 
Dr Andy Parkins, M Eng (hons), MIET
andyparkins@gmail.com

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/2] git-show: use pathattr to run "display"
  2007-03-01  9:04 ` Andy Parkins
@ 2007-03-01  9:17   ` Andy Parkins
  0 siblings, 0 replies; 6+ messages in thread
From: Andy Parkins @ 2007-03-01  9:17 UTC (permalink / raw
  To: git; +Cc: Junio C Hamano

On Thursday 2007 March 01 09:04, Andy Parkins wrote:
> Is this serious?  This doesn't belong inside git does it?

I see from the source that it's not.  It's just a demo.  Sorry Junio.


Andy
-- 
Dr Andy Parkins, M Eng (hons), MIET
andyparkins@gmail.com

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 3/2] pathattr: read from git_config().
  2007-03-01  7:18 [PATCH 2/2] git-show: use pathattr to run "display" Junio C Hamano
  2007-03-01  9:04 ` Andy Parkins
@ 2007-03-01  9:26 ` Junio C Hamano
  2007-03-01  9:29 ` [PATCH 4/2] pathattr: allow piping to external program Junio C Hamano
  2 siblings, 0 replies; 6+ messages in thread
From: Junio C Hamano @ 2007-03-01  9:26 UTC (permalink / raw
  To: git

Now we read the path traits from the usual configuration
mechanism.  No per-directory .gitattributes yet, though.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 * [3/2] (this one) and [4/2] are the follow-up to the pathattr
   series.

 pathattr.c |   63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 62 insertions(+), 1 deletions(-)

diff --git a/pathattr.c b/pathattr.c
index c84be39..2532c9a 100644
--- a/pathattr.c
+++ b/pathattr.c
@@ -85,6 +85,67 @@ static void add_match(struct pathattr_stack *s, struct pathattr *a, const char *
 	m->attr = a;
 }
 
+static convi_fn conv_i_trait(const char *value)
+{
+	if (!strcmp(value, "crlf"))
+		return convi_crlf;
+	return NULL;
+}
+
+static convo_fn conv_o_trait(const char *value)
+{
+	if (!strcmp(value, "crlf"))
+		return convo_crlf;
+	return NULL;
+}
+
+static pretty_fn pretty_trait(const char *value)
+{
+	if (!strcmp(value, "display"))
+		return show_display;
+	return NULL;
+}
+
+static int attr_config(const char *var, const char *value)
+{
+	struct pathattr *a;
+	static const char pa[] = "pathattr.";
+	const char *trait;
+	char group[256];
+	int group_len;
+
+	if (prefixcmp(var, pa))
+		return 0; /* we are not interested in other configs */
+	trait = strrchr(var, '.');
+	if (!trait)
+		return 0; /* huh? */
+	group_len = trait - var - (sizeof(pa) - 1);
+	if (group_len <= 0)
+		return 0; /* huh? */
+	trait++;
+	if (sizeof(group) < group_len)
+		die("'%.*s' is too long as a group name", group_len,
+		    var + sizeof(pa) - 1);
+	memcpy(group, var + sizeof(pa) - 1, group_len);
+	group[group_len] = 0;
+	a = locate(stk, group);
+
+	if (!strcmp(trait, "path"))
+		add_match(stk, a, value);
+	else if (!strcmp(trait, "conv_i"))
+		a->conv_i = conv_i_trait(value);
+	else if (!strcmp(trait, "conv_o"))
+		a->conv_i = conv_o_trait(value);
+	else if (!strcmp(trait, "pretty"))
+		a->pretty = pretty_trait(value);
+	/*
+	 * Do not barf if the configuration has unknown trait.
+	 * the user might be bisecting git and trying an older
+	 * version on the latest repository.
+	 */
+	return 0;
+}
+
 static void init_stack(void)
 {
 	struct pathattr *a;
@@ -105,7 +166,7 @@ static void init_stack(void)
 	add_match(stk, a, "*.jpg");
 	add_match(stk, a, "*.gif");
 
-	/* NEEDSWORK: read from config */
+	git_config(attr_config);
 }
 
 static void pop_stack(void)
-- 
1.5.0.2.809.g0f936

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/2] pathattr: allow piping to external program.
  2007-03-01  7:18 [PATCH 2/2] git-show: use pathattr to run "display" Junio C Hamano
  2007-03-01  9:04 ` Andy Parkins
  2007-03-01  9:26 ` [PATCH 3/2] pathattr: read from git_config() Junio C Hamano
@ 2007-03-01  9:29 ` Junio C Hamano
  2007-03-01  9:37   ` Junio C Hamano
  2 siblings, 1 reply; 6+ messages in thread
From: Junio C Hamano @ 2007-03-01  9:29 UTC (permalink / raw
  To: git

This sets up capability for various traits to be an external
process, accessed via pipe.  conv-i and conv-o need to spawn
bidirectional pipe, but I have not coded that part yet.

You can try running:

    $ git show HEAD:Documentation/*.txt

with:

    [pathattr "kludge"]
        path = Documentation/*.txt
        pretty = "pipe sed -e 's/^/>> /'"

to see what it does.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

 * I somehow suspect two Johannes'es would hate me for doing
   this.  I should instead resume coding the part to read
   .gitattributes from each directory, but spawning external
   stuff to borrow what other people already have done is much
   more fun than doing gruntwork in C.

 builtin-log.c |   18 ++++++++++---
 convert.c     |   16 ++++++------
 convert.h     |    3 --
 pathattr.c    |   77 ++++++++++++++++++++++++++++++++++++++++++++++----------
 pathattr.h    |    8 +++++-
 5 files changed, 92 insertions(+), 30 deletions(-)

diff --git a/builtin-log.c b/builtin-log.c
index 519fab2..86062d3 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -87,7 +87,7 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix)
 	return cmd_log_walk(&rev);
 }
 
-static void to_stdout(const unsigned char *blobdata, unsigned long size)
+static void to_stdout(const unsigned char *blobdata, unsigned long size, const char *unused)
 {
 	fwrite(blobdata, size, 1, stdout);
 }
@@ -99,6 +99,7 @@ static int show_object(const unsigned char *sha1, const char *path, int nohead)
 	unsigned char *buf = read_sha1_file(sha1, &type, &size);
 	int offset = 0;
 	pretty_fn pretty = to_stdout;
+	char *pretty_args = NULL;
 
 	if (!buf)
 		return error("Could not read object %s", sha1_to_hex(sha1));
@@ -117,11 +118,13 @@ static int show_object(const unsigned char *sha1, const char *path, int nohead)
 
 	if (path) {
 		const struct pathattr *a = pathattr_lookup(path);
-		if (a && a->pretty)
+		if (a && a->pretty) {
 			pretty = a->pretty;
+			pretty_args = a->pretty_args;
+		}
 	}
 
-	pretty(buf + offset, size - offset);
+	pretty(buf + offset, size - offset, pretty_args);
  finish:
 	free(buf);
 	return 0;
@@ -159,6 +162,13 @@ int cmd_show(int argc, const char **argv, const char *prefix)
 		const char *name = objects[i].name;
 		switch (o->type) {
 		case OBJ_BLOB:
+			/*
+			 * This is a hack to make v2.6.0:README
+			 * and friends to work.  Anybody have
+			 * better ideas?
+			 */
+			if (strchr(name, ':'))
+				name = strchr(name, ':') + 1;
 			ret = show_object(o->sha1, name, 0);
 			break;
 		case OBJ_TAG: {
@@ -170,7 +180,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
 					t->tag,
 					diff_get_color(rev.diffopt.color_diff,
 						DIFF_RESET));
-			ret = show_object(o->sha1, name, 1);
+			ret = show_object(o->sha1, NULL, 1);
 			objects[i].item = (struct object *)t->tagged;
 			i--;
 			break;
diff --git a/convert.c b/convert.c
index c39946d..504036e 100644
--- a/convert.c
+++ b/convert.c
@@ -253,11 +253,11 @@ static int convo_autocrlf(const char *path, char **bufp, unsigned long *sizep)
 int convert_to_git(const char *path, char **bufp, unsigned long *sizep)
 {
 	if (path) {
-		const struct pathattr *attr = pathattr_lookup(path);
-		if (attr) {
-			if (!attr->conv_i)
+		const struct pathattr *a = pathattr_lookup(path);
+		if (a) {
+			if (!a->conv_i)
 				return 0;
-			return attr->conv_i(path, bufp, sizep);
+			return a->conv_i(path, bufp, sizep, a->conv_i_args);
 		}
 	}
 	/* Fallback */
@@ -268,11 +268,11 @@ int convert_to_working_tree(const char *path, char **bufp,
 			    unsigned long *sizep)
 {
 	if (path) {
-		const struct pathattr *attr = pathattr_lookup(path);
-		if (attr) {
-			if (!attr->conv_o)
+		const struct pathattr *a = pathattr_lookup(path);
+		if (a) {
+			if (!a->conv_o)
 				return 0;
-			return attr->conv_o(path, bufp, sizep);
+			return a->conv_o(path, bufp, sizep, a->conv_o_args);
 		}
 	}
 	/* Fallback */
diff --git a/convert.h b/convert.h
index e54b3ef..ff6fb85 100644
--- a/convert.h
+++ b/convert.h
@@ -1,9 +1,6 @@
 #ifndef CONVERT_H
 #define CONVERT_H
 
-typedef int (*convi_fn)(const char *, char **, unsigned long *);
-typedef int (*convo_fn)(const char *, char **, unsigned long *);
-
 int convi_crlf(const char *path, char **bufp, unsigned long *sizep);
 int convo_crlf(const char *path, char **bufp, unsigned long *sizep);
 
diff --git a/pathattr.c b/pathattr.c
index 2532c9a..9362234 100644
--- a/pathattr.c
+++ b/pathattr.c
@@ -1,9 +1,30 @@
 #include "cache.h"
 #include "pathattr.h"
 
-static void show_display(const unsigned char *blobdata, unsigned long size)
+static int convi_pipe(const char *path, char **bufp, unsigned long *sizep,
+		      const char *args)
 {
-	FILE *display = popen("display -", "w");
+	/* NEEDSWORK: set up two-way pipe, spawn command specified
+	 * with args, and have it convert bufp & sizep
+	 */
+	return 0;
+}
+
+static int convo_pipe(const char *path, char **bufp, unsigned long *sizep,
+		      const char *args)
+{
+	/* NEEDSWORK: set up two-way pipe, spawn command specified
+	 * with args, and have it convert bufp & sizep
+	 */
+	return 0;
+}
+
+static void pretty_pipe(const unsigned char *blobdata, unsigned long size,
+			const char *args)
+{
+	FILE *display;
+
+	display = popen(args, "w");
 	fwrite(blobdata, size, 1, display);
 	fclose(display);
 }
@@ -67,6 +88,7 @@ static struct pathattr *locate(struct pathattr_stack *s, const char *name)
 		s->attr = xrealloc(s->attr, sizeof(*a) * s->attr_alloc);
 	}
 	a = &(s->attr[s->attr_nr++]);
+	memset(a, 0, sizeof(*a));
 	a->name = xstrdup(name);
 	return a;
 }
@@ -80,29 +102,57 @@ static void add_match(struct pathattr_stack *s, struct pathattr *a, const char *
 		s->match = xrealloc(s->match, sizeof(*m) * s->match_alloc);
 	}
 	m = &(s->match[s->match_nr++]);
+	memset(m, 0, sizeof(*m));
 	m->pattern = xstrdup(pattern);
 	m->type = strchr(pattern, '/') ? FNM_PATHNAME : 0;
 	m->attr = a;
 }
 
-static convi_fn conv_i_trait(const char *value)
+static int call_convi_crlf(const char *path, char **bufp, unsigned long *sizep,
+			   const char *args)
+{
+	return convi_crlf(path, bufp, sizep);
+}
+
+static int call_convo_crlf(const char *path, char **bufp, unsigned long *sizep,
+			   const char *args)
+{
+	return convo_crlf(path, bufp, sizep);
+}
+
+static int parse_pipe_trait(const char *value, char **args)
+{
+	if (strncmp(value, "pipe ", 5))
+		return 0;
+	free(*args);
+	*args = xstrdup(value + 5);
+	return 1;
+}
+
+static convi_fn conv_i_trait(const char *value, struct pathattr *a)
 {
 	if (!strcmp(value, "crlf"))
-		return convi_crlf;
+		return call_convi_crlf;
+	if (parse_pipe_trait(value, &a->conv_i_args))
+		return convi_pipe;
 	return NULL;
 }
 
-static convo_fn conv_o_trait(const char *value)
+static convo_fn conv_o_trait(const char *value, struct pathattr *a)
 {
 	if (!strcmp(value, "crlf"))
-		return convo_crlf;
+		return call_convo_crlf;
+	if (parse_pipe_trait(value, &a->conv_o_args))
+		return convo_pipe;
 	return NULL;
 }
 
-static pretty_fn pretty_trait(const char *value)
+static pretty_fn pretty_trait(const char *value, struct pathattr *a)
 {
 	if (!strcmp(value, "display"))
-		return show_display;
+		value = "pipe display -";
+	if (parse_pipe_trait(value, &a->pretty_args))
+		return pretty_pipe;
 	return NULL;
 }
 
@@ -133,11 +183,11 @@ static int attr_config(const char *var, const char *value)
 	if (!strcmp(trait, "path"))
 		add_match(stk, a, value);
 	else if (!strcmp(trait, "conv_i"))
-		a->conv_i = conv_i_trait(value);
+		a->conv_i = conv_i_trait(value, a);
 	else if (!strcmp(trait, "conv_o"))
-		a->conv_i = conv_o_trait(value);
+		a->conv_i = conv_o_trait(value, a);
 	else if (!strcmp(trait, "pretty"))
-		a->pretty = pretty_trait(value);
+		a->pretty = pretty_trait(value, a);
 	/*
 	 * Do not barf if the configuration has unknown trait.
 	 * the user might be bisecting git and trying an older
@@ -154,14 +204,13 @@ static void init_stack(void)
 
 	/* A couple of silly example as an illustration */
 	a = locate(stk, "silly");
-	a->conv_i = convi_crlf;
-	a->conv_o = convo_crlf;
+	a->conv_i = call_convi_crlf;
+	a->conv_o = call_convo_crlf;
 	add_match(stk, a, "*.dos-txt");
 
 	a = locate(stk, "image/*");
 	a->conv_i = NULL;
 	a->conv_o = NULL;
-	a->pretty = show_display;
 	add_match(stk, a, "*.png");
 	add_match(stk, a, "*.jpg");
 	add_match(stk, a, "*.gif");
diff --git a/pathattr.h b/pathattr.h
index bfd9ff1..34e8ce4 100644
--- a/pathattr.h
+++ b/pathattr.h
@@ -3,7 +3,9 @@
 
 #include "convert.h"
 
-typedef void (*pretty_fn)(const unsigned char *blobdata, unsigned long size);
+typedef int (*convi_fn)(const char *, char **, unsigned long *, const char *);
+typedef int (*convo_fn)(const char *, char **, unsigned long *, const char *);
+typedef void (*pretty_fn)(const unsigned char *, unsigned long, const char *);
 
 /*
  * Data in one section of [pathattr "name"], except
@@ -14,6 +16,10 @@ struct pathattr {
 	convi_fn conv_i;
 	convo_fn conv_o;
 	pretty_fn pretty;
+
+	char *conv_i_args;
+	char *conv_o_args;
+	char *pretty_args;
 };
 
 const struct pathattr *pathattr_lookup(const char *);
-- 
1.5.0.2.809.g0f936

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 4/2] pathattr: allow piping to external program.
  2007-03-01  9:29 ` [PATCH 4/2] pathattr: allow piping to external program Junio C Hamano
@ 2007-03-01  9:37   ` Junio C Hamano
  0 siblings, 0 replies; 6+ messages in thread
From: Junio C Hamano @ 2007-03-01  9:37 UTC (permalink / raw
  To: git

Junio C Hamano <junkio@cox.net> writes:

> This sets up capability for various traits to be an external
> process, accessed via pipe.  conv-i and conv-o need to spawn
> bidirectional pipe, but I have not coded that part yet.
>
> You can try running:
>
>     $ git show HEAD:Documentation/*.txt

... obviously I meant

	$ git show HEAD:Documentation/git.txt

or something a bit more concrete than '*' here.

>
> with:
>
>     [pathattr "kludge"]
>         path = Documentation/*.txt
>         pretty = "pipe sed -e 's/^/>> /'"
>
> to see what it does.
>
> Signed-off-by: Junio C Hamano <junkio@cox.net>

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2007-03-01  9:37 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-01  7:18 [PATCH 2/2] git-show: use pathattr to run "display" Junio C Hamano
2007-03-01  9:04 ` Andy Parkins
2007-03-01  9:17   ` Andy Parkins
2007-03-01  9:26 ` [PATCH 3/2] pathattr: read from git_config() Junio C Hamano
2007-03-01  9:29 ` [PATCH 4/2] pathattr: allow piping to external program Junio C Hamano
2007-03-01  9:37   ` Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).