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
next prev parent 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 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 NNTP newsgroup(s).