Re: [PATCH 1/2] add git-quote: shell and C quoting tool

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Junio C Hamano, Mon, Jul 24, 2006 07:49:53 +0200:
> > In case anyone asks why isn't it a standalone tool nor is it put into
> > git-stripspace: I don't know. Maybe it should be.
> 
> This organization is fine by me.
> 
>  * unquote?

Not done yet. I actually never expected it to be used for unquoting,
being naturally unquoted by bash. C-quoting was done just because it
was so simple to do. I have no idea where could that be used.

>  * doc?

Done. Sorry for missing that.

> > +enum {SHELL_QUOTE, C_QUOTE};
> > +static int style = SHELL_QUOTE,
> > +	   use_stdin = 0;
> 
> Shouldn't style be of type which is that unnamed enum?

It should. Done.

> > +static const char *separator = NULL; /* default is space */
> > +static unsigned sep_len = 0;
> 
> It is not clear if this is separator of input side or output
> side (after reading the code it becomes somewhat obvious that
> you are talking about output separator), and if the default is
> space wouldn't it make more sense to set that here?

Right. It is out_separator now.

> > +static const char builtin_quote_usage[] =
> > +"git-quote [--c] [--sep=<c-quoted> | -z] ( [--stdin] | [--] ... )";
> > +
> > +static void print_quoted(const char *text)
> > +{
> > +	switch (style)
> > +	{
> > +	case SHELL_QUOTE:
> > +		sq_quote_print(stdout, text);
> > +		break;
> > +	case C_QUOTE:
> > +		quote_c_style(text, NULL, stdout, 0);
> > +		break;
> > +	}
> 
> Not a big deal but aren't these going to write out things quoted
> when they do not need to?  To help scripts, it might be worth
> adding "check if this needs quoting" interface perhaps?

Not done yet. "--no-overquote"?

> > +		if (!strcmp(arg, "--c")) {
> 
> Perhaps "--c-style" with "-c" as a shorthand, (and
> "--shell-style" with "-s" to complement)?

Done. --sh-style.

> > +			style = C_QUOTE;
> > +			continue;
> > +		}
> > +		if (!strcmp(arg, "-z")) {
> > +			separator = "";
> > +			sep_len = 1;
> > +			continue;
> > +		}
> 
> Is it plausible that somebody might want to feed you NUL
> terminated sequence as input (iow you might want to give them
> choice of separator on the input side)?

Done. -z sets both separators to NUL, --in-separator=<c-style> defines
by its first character the input separator. I.e.:

$ find | git quote -z --in-separator='\n'
'a'\0'b'\0''

which is not all that useful...

> > +		if (!strncmp(arg, "--sep=", 6)) {
> 
> Perhaps "--separator" (or "--output-separator") with whatever
> shorthand is handy?

--out-separator. No idea of a shortcut, though

> > +			separator = unquote_c_style(tmp, &end);
> > +			sep_len = strlen(separator);
> 
> If the parameter is a malformed c-quoted string, you would dump
> core here.

Oops. Fixed.

> > +	if (!separator) {
> > +		sep_len = 1;
> > +		separator = "\x20";
> 
> Any reason you needed to spell it in hex?  Is this trying to
> be portable to EBCDIC (or trying to prevent the code to be
> ported there)?  I dunno.

Visibility. I have dificulty seeing spaces and tabs.
I changed it anyway, maybe that's just me.

> > +		while (EOF != (ch = fgetc(stdin))) {
> 
> Looks similar to strbuf.c::read_line() loop...
> 

Indeed. Replaced.

I attach the updated patch here, because it is obviously is not quite
finished yet and I probably wont have enough time over the week. So
maybe someone takes over. Or it'll be taken as is, that happens too.

Signed-off-by: Alex Riesen <raa.lkml@xxxxxxxxx>

---

diff --git a/Documentation/git-quote.txt b/Documentation/git-quote.txt
new file mode 100644
index 0000000..98b2859
--- /dev/null
+++ b/Documentation/git-quote.txt
@@ -0,0 +1,70 @@
+git-quote(1)
+============
+
+NAME
+----
+git-quote - Quote given text according to Shell or C rules
+
+
+SYNOPSIS
+--------
+'git-quote' [-c] [-s] [-s] [--out-separator=<c-quoted>] 
+	[--in-separator=<c-quoted>] [-z] [--] ...
+'git-quote' ... --stdin < <stream>
+
+DESCRIPTION
+-----------
+Quote the lines according to the given rules, which can be Shell backslash
+quoting (every line is enclosed in single ticks, backslash and single tick
+quoted specially) or a C quoting (use double ticks and backslash-prefixed
+symbols).
+
+The separator options are handled in the order they are given, so one
+can save some typing by giving "-z" first, and overriding input or
+output separator as needed.
+
+OPTIONS
+-------
+-c|--c-style::
+	Select C-style quoting
+
+-s|--sh-style::
+	Select Shell-style quoting. This is default.
+
+--out-separator=<c-quoted>::
+	Specify the separator between the output elements. If the separator
+	have to contain special characters, they must be quoted according
+	to C quoting rules (double ticks are not essential).
+	The ASCII space is default output separator.
+
+--in-separator=<c-quoted>::
+	Specify the separator between the input elements. Only the
+	first character of <c-quoted> is used.
+	Used only if --stdin is also given. The default is LF.
+
+-z::
+	Separate the elements on output and expect elements separated
+	on input with NUL character.
+	Used only if --stdin is also given.
+
+--stdin::
+	Specify that the elements have to be read from stdin.
+	This option ends command line parsing.
+	Also, if there were no output separator set by previous
+	--out-separator or -z, this option will set it to LF.
+
+<stream>::
+	Byte stream to act on.
+
+Author
+------
+Written by Alex Riesen <raa.lkml@xxxxxxxxx>
+
+Documentation
+--------------
+Documentation by Alex Riesen.
+
+GIT
+---
+Part of the gitlink:git[7] suite
+
diff --git a/Makefile b/Makefile
index 3e085df..4df2951 100644
--- a/Makefile
+++ b/Makefile
@@ -246,7 +246,8 @@ BUILTIN_OBJS = \
 	builtin-apply.o builtin-show-branch.o builtin-diff-files.o \
 	builtin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \
 	builtin-cat-file.o builtin-mailsplit.o builtin-stripspace.o \
-	builtin-update-ref.o builtin-fmt-merge-msg.o builtin-prune.o
+	builtin-update-ref.o builtin-fmt-merge-msg.o builtin-prune.o \
+	builtin-quote.o
 
 GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
 LIBS = $(GITLIBS) -lz
diff --git a/builtin-quote.c b/builtin-quote.c
new file mode 100644
index 0000000..d9d4b00
--- /dev/null
+++ b/builtin-quote.c
@@ -0,0 +1,123 @@
+/*
+ * "git quote" builtin command
+ *
+ * DOES NOT QUOTE \0 (truncates lines at it)
+ */
+#include "cache.h"
+#include "builtin.h"
+#include "strbuf.h"
+#include "quote.h"
+
+static enum {SHELL_QUOTE, C_QUOTE} style = SHELL_QUOTE;
+static int use_stdin = 0;
+static const char *out_separator = NULL; /* default is space */
+static unsigned out_separator_len = 0;
+
+static const char builtin_quote_usage[] =
+"git-quote [-c | -s] [--out-separator=<c-quoted> | -z] ( [--stdin] | [--] ... )";
+
+static void print_quoted(const char *text)
+{
+	switch (style)
+	{
+	case SHELL_QUOTE:
+		sq_quote_print(stdout, text);
+		break;
+	case C_QUOTE:
+		quote_c_style(text, NULL, stdout, 0);
+		break;
+	}
+	fwrite(out_separator, 1, out_separator_len, stdout);
+}
+
+static char *unquote_c_arg(const char *arg)
+{
+	const char *end;
+	char *tmp;
+	char *result;
+	if ('"' == *arg)
+		tmp = strdup(arg);
+	else {
+		size_t l = strlen(arg);
+		tmp = malloc(l + 3);
+		sprintf(tmp, "\"%s\"", arg);
+	}
+	result = unquote_c_style(tmp, &end);
+	free(tmp);
+	return result;
+}
+
+int cmd_quote(int argc, const char **argv, char **envp)
+{
+	int in_separator = '\n';
+	int i;
+	for (i = 1; i < argc; i++) {
+		const char *arg = argv[i];
+
+		if (arg[0] != '-')
+			break;
+		if (!strcmp(arg, "--")) {
+			i++;
+			break;
+		}
+		if (!strcmp(arg, "--stdin")) {
+			use_stdin = 1;
+			if ( !out_separator ) {
+				out_separator = "\n";
+				out_separator_len = 1;
+			}
+			break;
+		}
+		if (!strcmp(arg, "--c-style") || !strcmp(arg, "-c")) {
+			style = C_QUOTE;
+			continue;
+		}
+		if (!strcmp(arg, "--sh-style") || !strcmp(arg, "-s")) {
+			style = SHELL_QUOTE;
+			continue;
+		}
+		if (!strcmp(arg, "-z")) {
+			in_separator = 0;
+			out_separator = "";
+			out_separator_len = 1;
+			continue;
+		}
+		if (!strncmp(arg, "--out-separator=", 16)) {
+			arg += 16;
+			out_separator = unquote_c_arg(arg);
+			if (!out_separator)
+				die("malformed separator '%s'", arg);
+			out_separator_len = strlen(out_separator);
+			/* this will leak if multiple --sep= given */
+			continue;
+		}
+		if (!strncmp(arg, "--in-separator=", 15)) {
+			char *sep;
+			arg += 15;
+			sep = unquote_c_arg(arg);
+			if (!sep || !*sep)
+				die("malformed separator '%s'", arg);
+			in_separator = *sep;
+			free(sep);
+			continue;
+		}
+		die(builtin_quote_usage);
+	}
+	if (!out_separator) {
+		out_separator_len = 1;
+		out_separator = " ";
+	}
+	if (use_stdin) {
+		struct strbuf line;
+		strbuf_init(&line);
+
+		while (!line.eof) {
+			read_line(&line, stdin, in_separator);
+			if (line.len)
+				print_quoted(line.buf);
+		}
+	} else
+		for (; argv[i]; ++i)
+			print_quoted(argv[i]);
+	return 0;
+}
diff --git a/builtin.h b/builtin.h
index 5339d86..9bd522e 100644
--- a/builtin.h
+++ b/builtin.h
@@ -64,4 +64,6 @@ extern int mailinfo(FILE *in, FILE *out,
 
 extern int cmd_stripspace(int argc, const char **argv, char **envp);
 extern void stripspace(FILE *in, FILE *out);
+
+extern int cmd_quote(int argc, const char **argv, char **envp);
 #endif
diff --git a/git.c b/git.c
index ee5a0e8..f94d25a 100644
--- a/git.c
+++ b/git.c
@@ -202,6 +202,7 @@ static void handle_internal_command(int 
 		{ "update-ref", cmd_update_ref },
 		{ "fmt-merge-msg", cmd_fmt_merge_msg },
 		{ "prune", cmd_prune },
+		{ "quote", cmd_quote },
 	};
 	int i;
 
-
: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]