All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: kevin@sb.org, "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH 1/5] alias: add functions to do param substitution and alias running
Date: Fri, 24 Dec 2010 21:07:45 +0700	[thread overview]
Message-ID: <1293199669-19016-2-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1293199669-19016-1-git-send-email-pclouds@gmail.com>

These functions help substitute %foo% in an alias command to real
values, then run the alias and return the first line from stdout.

The normal use case is:

    /* extract all %xxx% from cmd to params */
    extract_alias_params(cmd, params);
    param = lookup_alias_param(params, "%foo%");
    if (param)
        param->value = "value for %foo%";
    param = lookup_alias_param(params, "%bar%");
    if (param)
        param->value = "value for %bar%";
    /* substitute %foo% and %bar% */
    expand_alias_params(cmd, params);
    free_alias_params(params);
    if (!get_alias_oneline(alias, cmd, output))
        /* do something with output->buf here */

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 alias.c |  139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 cache.h |   11 +++++
 2 files changed, 150 insertions(+), 0 deletions(-)

diff --git a/alias.c b/alias.c
index eb9f08b..6626bb0 100644
--- a/alias.c
+++ b/alias.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "run-command.h"
 
 static const char *alias_key;
 static char *alias_val;
@@ -85,3 +86,141 @@ int split_cmdline(char *cmdline, const char ***argv)
 const char *split_cmdline_strerror(int split_cmdline_errno) {
 	return split_cmdline_errors[-split_cmdline_errno-1];
 }
+
+int extract_alias_params(const char *cmd, struct alias_param **params)
+{
+	const char *s = cmd;
+	int nr_param = 0;
+
+	*params = NULL;
+	while (s && (s = strchr(s, '%')) != NULL) {
+		int len = strcspn(s+1, "% ")+2;
+		if (len < 2 || s[len-1] != '%')
+			return error("malformed parameter at %s", s);
+		nr_param++;
+		*params = xrealloc(*params, sizeof(struct alias_param)*nr_param);
+		(*params)[nr_param-1].param = xstrndup(s, len);
+		(*params)[nr_param-1].pos = s - cmd;
+		(*params)[nr_param-1].value = NULL;
+		s += len;
+	}
+
+	nr_param++;
+	*params = xrealloc(*params, sizeof(struct alias_param)*nr_param);
+	(*params)[nr_param-1].param = NULL;
+	(*params)[nr_param-1].value = NULL;
+	return 0;
+}
+
+struct alias_param *lookup_alias_param(struct alias_param *params, const char *param)
+{
+	int i;
+	for (i = 0; params[i].param; i++)
+		if (!strcmp(params[i].param, param))
+			return params+i;
+	return NULL;
+}
+
+int expand_alias_params(struct strbuf *cmd, const struct alias_param *params)
+{
+	int i, offset = 0;
+
+	/* TODO: quote for '!' commands */
+	for (i = 0; params[i].param; i++) {
+		if (!params[i].value)
+			return error("param %s not substituted", params[i].param);
+		strbuf_splice(cmd,
+			      params[i].pos + offset, strlen(params[i].param),
+			      params[i].value, strlen(params[i].value));
+		offset += strlen(params[i].value) - strlen(params[i].param);
+	}
+
+	return 0;
+}
+
+void free_alias_params(struct alias_param *params)
+{
+	int i;
+	for (i = 0; params[i].param; i++) {
+		free(params[i].param);
+		free(params[i].value);
+	}
+	free(params);
+}
+
+static void *wait_and_finish(void *arg)
+{
+	struct child_process *cp = arg;
+	char buf[1024];
+	while (xread(cp->out, buf, 1024) > 0)
+		;
+	close(cp->out);
+	finish_command(cp);
+	free(cp->argv);
+	free(cp);
+	return (void *) (intptr_t) 0;
+}
+
+static int start_support_alias(const char *alias, char *cmd, struct child_process **cpp)
+{
+	struct child_process *cp;
+	const char **argv;
+	int count;
+
+	cp = xmalloc(sizeof(struct child_process));
+	memset(cp, 0, sizeof(struct child_process));
+	cp->in = 0;
+	cp->out = -1;
+
+	if (cmd[0] == '!') {
+		argv = xmalloc(sizeof(*argv)*4);
+		argv[0] = "/bin/sh";
+		argv[1] = "-c";
+		argv[2] = cmd+1;
+		argv[3] = NULL;
+	}
+	else {
+		count = split_cmdline(cmd, &argv);
+		if (count < 0) {
+			free(cp);
+			return error("Bad alias %s: %s", cmd, split_cmdline_strerror(count));
+		}
+		cp->git_cmd = 1;
+	}
+
+	cp->argv = argv;
+	if (start_command(cp)) {
+		error("Failed to run %s", cmd);
+		free(cp);
+		free(argv);
+		return -1;
+	}
+	*cpp = cp;
+	return 0;
+}
+
+int get_alias_oneline(const char *alias, char *cmd, struct strbuf *ref)
+{
+	struct child_process *cp;
+	FILE *fp;
+	int ret;
+
+	ret = start_support_alias(alias, cmd, &cp);
+	if (ret)
+		return ret;
+
+	fp = fdopen(cp->out, "r");
+	ret = strbuf_getline(ref, fp, '\n');
+	if (!ret) {
+		/* let it finish, if there's error, users should know */
+#ifdef NO_PTHREADS
+		wait_and_finish(cp);
+#else
+		pthread_t thread;
+		pthread_create(&thread, NULL, wait_and_finish, cp);
+#endif
+		return 0;
+	}
+	wait_and_finish(cp);
+	return -1;
+}
diff --git a/cache.h b/cache.h
index e83bc2d..20a37ff 100644
--- a/cache.h
+++ b/cache.h
@@ -1113,10 +1113,21 @@ extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
 int report_path_error(const char *ps_matched, const char **pathspec, int prefix_offset);
 void overlay_tree_on_cache(const char *tree_name, const char *prefix);
 
+struct alias_param {
+	char *param;
+	int pos;
+	char *value;
+};
+
 char *alias_lookup(const char *alias);
 int split_cmdline(char *cmdline, const char ***argv);
 /* Takes a negative value returned by split_cmdline */
 const char *split_cmdline_strerror(int cmdline_errno);
+int extract_alias_params(const char *cmd, struct alias_param **params);
+struct alias_param *lookup_alias_param(struct alias_param *params, const char *param);
+int expand_alias_params(struct strbuf *cmd, const struct alias_param *params);
+void free_alias_params(struct alias_param *params);
+int get_alias_oneline(const char *alias, char *cmd, struct strbuf *result);
 
 /* git.c */
 struct startup_info {
-- 
1.7.3.3.476.g10a82

  reply	other threads:[~2010-12-24 14:09 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-12-24 14:07 [PATCH 0/5] Custom extended SHA-1 syntax Nguyễn Thái Ngọc Duy
2010-12-24 14:07 ` Nguyễn Thái Ngọc Duy [this message]
2010-12-24 14:07 ` [PATCH 2/5] get_sha1: allow custom SHA-1 mapping with $SHA1^{~alias} syntax Nguyễn Thái Ngọc Duy
2010-12-24 14:07 ` [PATCH 3/5] sha1_name: move interpret_nth_prior_checkout closer to interpret_branch_name Nguyễn Thái Ngọc Duy
2010-12-24 14:07 ` [PATCH 4/5] interpret_branch_name: takes @{u} code out and reorder the function Nguyễn Thái Ngọc Duy
2010-12-24 14:07 ` [PATCH 5/5] get_sha1: allow custom ref mapping with $ref@{~alias} syntax Nguyễn Thái Ngọc Duy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1293199669-19016-2-git-send-email-pclouds@gmail.com \
    --to=pclouds@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=kevin@sb.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.