* [PATCH] git: handle aliases defined in $GIT_DIR/config
@ 2006-06-04 18:47 Johannes Schindelin
2006-06-04 20:24 ` Junio C Hamano
0 siblings, 1 reply; 5+ messages in thread
From: Johannes Schindelin @ 2006-06-04 18:47 UTC (permalink / raw)
To: git, junkio
If you have a config containing something like this:
[alias]
l = "log --stat -M ORIG_HEAD.."
you can call
git l
and it will do the same as
git log --stat -M ORIG_HEAD..
This also works with hard links.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
For me, short cuts have to be easy to type, so they never
include digits, and they are never case sensitive, so I do not
need any fancy config stuff...
git.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/git.c b/git.c
index bc463c9..846062f 100644
--- a/git.c
+++ b/git.c
@@ -10,6 +10,7 @@ #include <limits.h>
#include <stdarg.h>
#include "git-compat-util.h"
#include "exec_cmd.h"
+#include "cache.h"
#include "builtin.h"
@@ -32,6 +33,60 @@ static void prepend_to_path(const char *
setenv("PATH", path, 1);
}
+static const char *alias_command;
+static char *alias_string = NULL;
+
+static int git_alias_config(const char *var, const char *value)
+{
+ if (!strncmp(var, "alias.", 6) && !strcmp(var + 6, alias_command)) {
+ alias_string = strdup(value);
+ }
+ return 0;
+}
+
+#define MAX_ALIAS_ARGS 32
+
+static int handle_alias(int *argcp, const char **argv, char **envp)
+{
+ int i, i2, j = 0;
+ char *new_argv[MAX_ALIAS_ARGS];
+
+ alias_command = argv[0];
+ git_config(git_alias_config);
+ if (!alias_string)
+ return 0;
+
+ /* split alias_string */
+ new_argv[j++] = alias_string;
+ for (i = i2 = 0; alias_string[i]; i++, i2++) {
+ if (isspace(alias_string[i])) {
+ alias_string[i2] = 0;
+ while (alias_string[++i] && isspace(alias_string[i]));
+ new_argv[j++] = alias_string + i;
+ i2 = i;
+ if (j >= MAX_ALIAS_ARGS)
+ die("too many args in alias %s",
+ alias_command);
+ } else {
+ if (alias_string[i] == '\\')
+ i++;
+ if (i != i2)
+ alias_string[i2] = alias_string[i];
+ }
+ }
+
+ if (j < 1)
+ die("empty alias: %s", alias_command);
+
+ /* insert after command name */
+ if (j > 1)
+ memmove(argv + j, argv + 1, (*argcp - 1) * sizeof(char*));
+ memcpy(argv, new_argv, j * sizeof(char*));
+ *argcp += j - 1;
+
+ return 1;
+}
+
const char git_version_string[] = GIT_VERSION;
static void handle_internal_command(int argc, const char **argv, char **envp)
@@ -121,6 +176,7 @@ int main(int argc, const char **argv, ch
if (!strncmp(cmd, "git-", 4)) {
cmd += 4;
argv[0] = cmd;
+ handle_alias(&argc, argv, envp);
handle_internal_command(argc, argv, envp);
die("cannot handle %s internally", cmd);
}
@@ -178,6 +234,8 @@ int main(int argc, const char **argv, ch
exec_path = git_exec_path();
prepend_to_path(exec_path, strlen(exec_path));
+ handle_alias(&argc, argv, envp);
+
/* See if it's an internal command */
handle_internal_command(argc, argv, envp);
--
1.3.3.ga182-dirty
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH] git: handle aliases defined in $GIT_DIR/config
2006-06-04 18:47 [PATCH] git: handle aliases defined in $GIT_DIR/config Johannes Schindelin
@ 2006-06-04 20:24 ` Junio C Hamano
2006-06-05 16:51 ` Johannes Schindelin
0 siblings, 1 reply; 5+ messages in thread
From: Junio C Hamano @ 2006-06-04 20:24 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> For me, short cuts have to be easy to type, so they never
> include digits, and they are never case sensitive, so I do not
> need any fancy config stuff...
Fair enough, and the spirit is the same as what Pasky suggested
earlier, I think.
However, I am not sure about some parts of the code. I started
mucking with it myself, but realized it is far easier for me to
just let the original submitter, especially the capable one like
you, do a bit more work ;-).
> +#define MAX_ALIAS_ARGS 32
> +
> +static int handle_alias(int *argcp, const char **argv, char **envp)
> +{
> + int i, i2, j = 0;
Please name them src, dst and cnt.
> + char *new_argv[MAX_ALIAS_ARGS];
> +
> + alias_command = argv[0];
> + git_config(git_alias_config);
> + if (!alias_string)
> + return 0;
> +
> + /* split alias_string */
> + new_argv[j++] = alias_string;
> + for (i = i2 = 0; alias_string[i]; i++, i2++) {
> + if (isspace(alias_string[i])) {
> + alias_string[i2] = 0;
> + while (alias_string[++i] && isspace(alias_string[i]));
Please make empty loops easier to read by saying:
while (alias_string[++src] && isspace(alias_string[src]))
; /* skip */
> + new_argv[j++] = alias_string + i;
> + i2 = i;
Do we need to reset dst here? I suspect starting the next
parsed string immediately after the terminating NUL might be
cleaner.
> + if (j >= MAX_ALIAS_ARGS)
> + die("too many args in alias %s",
> + alias_command);
> + } else {
> + if (alias_string[i] == '\\')
> + i++;
Barf when the config line ends with a lone backslash, perhaps?
Since the configuration file parser uses backslash for quoting
itself, the user would need to have double backslashes, I
suspect. We might want to support single/double quote pairs in
this parser as well. I would further suggest separating this
"split single string into a pair of (argc, argv)" into a helper
function, so we can reuse it in other parts of the system later.
> + if (i != i2)
> + alias_string[i2] = alias_string[i];
Doing this unconditionally is probably more readable (i.e. lose
the if condition) -- this is not performance critical part of
the system.
> + }
> + }
> +
> + if (j < 1)
> + die("empty alias: %s", alias_command);
> +
> + /* insert after command name */
> + if (j > 1)
> + memmove(argv + j, argv + 1, (*argcp - 1) * sizeof(char*));
> + memcpy(argv, new_argv, j * sizeof(char*));
Who guarantees the original argv array main() received is big
enough to hold (j-1) additional pointers, I wonder? I think you
would need to allocate a new array, and muck with both argc and
argv of the caller by passing the pointers to them, not just
argc.
> @@ -121,6 +176,7 @@ int main(int argc, const char **argv, ch
> if (!strncmp(cmd, "git-", 4)) {
> cmd += 4;
> argv[0] = cmd;
> + handle_alias(&argc, argv, envp);
Hence probably "handle_alias(&argc, &argv, envp)" is needed here.
> handle_internal_command(argc, argv, envp);
> die("cannot handle %s internally", cmd);
> }
> @@ -178,6 +234,8 @@ int main(int argc, const char **argv, ch
> exec_path = git_exec_path();
> prepend_to_path(exec_path, strlen(exec_path));
>
> + handle_alias(&argc, argv, envp);
> +
... and here.
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] git: handle aliases defined in $GIT_DIR/config
2006-06-04 20:24 ` Junio C Hamano
@ 2006-06-05 16:51 ` Johannes Schindelin
2006-06-05 17:02 ` Johannes Schindelin
0 siblings, 1 reply; 5+ messages in thread
From: Johannes Schindelin @ 2006-06-05 16:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi,
On Sun, 4 Jun 2006, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > For me, short cuts have to be easy to type, so they never
> > include digits, and they are never case sensitive, so I do not
> > need any fancy config stuff...
>
> Fair enough, and the spirit is the same as what Pasky suggested
> earlier, I think.
>
> However, I am not sure about some parts of the code. I started
> mucking with it myself, but realized it is far easier for me to
> just let the original submitter, especially the capable one like
> you, do a bit more work ;-).
Are you trying to butter me up? If so, it's working ;-)
Here is a revised patch which addresses all of your comments (and Pasky's
implicit ones) except the move of split_cmdline to somewhere central (I
am not sure if that function is really needed elsewhere...):
---
git.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 113 insertions(+), 0 deletions(-)
diff --git a/git.c b/git.c
index bc463c9..db6ac61 100644
--- a/git.c
+++ b/git.c
@@ -10,6 +10,7 @@ #include <limits.h>
#include <stdarg.h>
#include "git-compat-util.h"
#include "exec_cmd.h"
+#include "cache.h"
#include "builtin.h"
@@ -32,6 +33,115 @@ static void prepend_to_path(const char *
setenv("PATH", path, 1);
}
+static const char *alias_command;
+static char *alias_string = NULL;
+
+static int git_alias_config(const char *var, const char *value)
+{
+ if (!strncmp(var, "alias.", 6) && !strcmp(var + 6, alias_command)) {
+ alias_string = strdup(value);
+ }
+ return 0;
+}
+
+static int split_cmdline(char *cmdline, const char ***argv)
+{
+ int src, dst, count = 0, size = 16;
+ char quoted = 0;
+
+ *argv = malloc(sizeof(char*) * size);
+
+ /* split alias_string */
+ (*argv)[count++] = cmdline;
+ for (src = dst = 0; cmdline[src];) {
+ char c = cmdline[src];
+ if (!quoted && isspace(c)) {
+ cmdline[dst++] = 0;
+ while (cmdline[++src]
+ && isspace(cmdline[src]))
+ ; /* skip */
+ if (count >= size) {
+ size += 16;
+ *argv = realloc(*argv, sizeof(char*) * size);
+ }
+ (*argv)[count++] = cmdline + dst;
+ } else if(!quoted && (c == '\'' || c == '"')) {
+ quoted = c;
+ src++;
+ } else if (c == quoted) {
+ quoted = 0;
+ src++;
+ } else {
+ if (c == '\\' && quoted != '\'') {
+ src++;
+ c = cmdline[src];
+ if (!c) {
+ free(*argv);
+ *argv = NULL;
+ return error("cmdline ends with \\");
+ }
+ }
+ cmdline[dst++] = c;
+ src++;
+ }
+ }
+
+ cmdline[dst] = 0;
+
+ if (quoted) {
+ free(*argv);
+ *argv = NULL;
+ return error("unclosed quote");
+ }
+
+ return count;
+}
+
+static int handle_alias(int *argcp, const char ***argv)
+{
+ int nongit = 0;
+ const char *subdir;
+
+ subdir = setup_git_directory_gently(&nongit);
+ if (!nongit) {
+ int count;
+ const char** new_argv;
+
+ alias_command = (*argv)[0];
+ git_config(git_alias_config);
+ if (!alias_string)
+ return 0;
+
+ count = split_cmdline(alias_string, &new_argv);
+
+ if (count < 1)
+ die("empty alias for %s", alias_command);
+
+ if (!strcmp(alias_command, new_argv[0]))
+ die("recursive alias: %s", alias_command);
+
+ /* insert after command name */
+ if (*argcp > 1) {
+ new_argv = realloc(new_argv,
+ sizeof(char*) * (count + *argcp - 1));
+ memcpy(new_argv + count, *argv, sizeof(char*) * (*argcp - 1));
+ }
+
+ *argv = new_argv;
+ *argcp += count - 1;
+
+ if (subdir)
+ chdir(subdir);
+
+ return 1;
+ }
+
+ if (subdir)
+ chdir(subdir);
+
+ return 0;
+}
+
const char git_version_string[] = GIT_VERSION;
static void handle_internal_command(int argc, const char **argv, char **envp)
@@ -121,6 +231,7 @@ int main(int argc, const char **argv, ch
if (!strncmp(cmd, "git-", 4)) {
cmd += 4;
argv[0] = cmd;
+ handle_alias(&argc, &argv);
handle_internal_command(argc, argv, envp);
die("cannot handle %s internally", cmd);
}
@@ -178,6 +289,8 @@ int main(int argc, const char **argv, ch
exec_path = git_exec_path();
prepend_to_path(exec_path, strlen(exec_path));
+ handle_alias(&argc, &argv);
+
/* See if it's an internal command */
handle_internal_command(argc, argv, envp);
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH] git: handle aliases defined in $GIT_DIR/config
2006-06-05 16:51 ` Johannes Schindelin
@ 2006-06-05 17:02 ` Johannes Schindelin
2006-06-05 17:43 ` Johannes Schindelin
0 siblings, 1 reply; 5+ messages in thread
From: Johannes Schindelin @ 2006-06-05 17:02 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi,
sorry, I did not test with the subdir=... stuff I copied from Pasky's
patch. It breaks things for me. Looking into it...
Ciao,
Dscho
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] git: handle aliases defined in $GIT_DIR/config
2006-06-05 17:02 ` Johannes Schindelin
@ 2006-06-05 17:43 ` Johannes Schindelin
0 siblings, 0 replies; 5+ messages in thread
From: Johannes Schindelin @ 2006-06-05 17:43 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi,
On Mon, 5 Jun 2006, Johannes Schindelin wrote:
> Hi,
>
> sorry, I did not test with the subdir=... stuff I copied from Pasky's
> patch. It breaks things for me. Looking into it...
There were actually two bugs: I did not change the subdir back in all
cases, and git_setup_directory_gently had a bug (will send patch
separately). The updated patch:
---
git.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/git.c b/git.c
index bc463c9..8854472 100644
--- a/git.c
+++ b/git.c
@@ -10,6 +10,7 @@ #include <limits.h>
#include <stdarg.h>
#include "git-compat-util.h"
#include "exec_cmd.h"
+#include "cache.h"
#include "builtin.h"
@@ -32,6 +33,113 @@ static void prepend_to_path(const char *
setenv("PATH", path, 1);
}
+static const char *alias_command;
+static char *alias_string = NULL;
+
+static int git_alias_config(const char *var, const char *value)
+{
+ if (!strncmp(var, "alias.", 6) && !strcmp(var + 6, alias_command)) {
+ alias_string = strdup(value);
+ }
+ return 0;
+}
+
+static int split_cmdline(char *cmdline, const char ***argv)
+{
+ int src, dst, count = 0, size = 16;
+ char quoted = 0;
+
+ *argv = malloc(sizeof(char*) * size);
+
+ /* split alias_string */
+ (*argv)[count++] = cmdline;
+ for (src = dst = 0; cmdline[src];) {
+ char c = cmdline[src];
+ if (!quoted && isspace(c)) {
+ cmdline[dst++] = 0;
+ while (cmdline[++src]
+ && isspace(cmdline[src]))
+ ; /* skip */
+ if (count >= size) {
+ size += 16;
+ *argv = realloc(*argv, sizeof(char*) * size);
+ }
+ (*argv)[count++] = cmdline + dst;
+ } else if(!quoted && (c == '\'' || c == '"')) {
+ quoted = c;
+ src++;
+ } else if (c == quoted) {
+ quoted = 0;
+ src++;
+ } else {
+ if (c == '\\' && quoted != '\'') {
+ src++;
+ c = cmdline[src];
+ if (!c) {
+ free(*argv);
+ *argv = NULL;
+ return error("cmdline ends with \\");
+ }
+ }
+ cmdline[dst++] = c;
+ src++;
+ }
+ }
+
+ cmdline[dst] = 0;
+
+ if (quoted) {
+ free(*argv);
+ *argv = NULL;
+ return error("unclosed quote");
+ }
+
+ return count;
+}
+
+static int handle_alias(int *argcp, const char ***argv)
+{
+ int nongit = 0, ret = 0;
+ const char *subdir;
+
+ subdir = setup_git_directory_gently(&nongit);
+ if (!nongit) {
+ int count;
+ const char** new_argv;
+
+ alias_command = (*argv)[0];
+ git_config(git_alias_config);
+ if (alias_string) {
+
+ count = split_cmdline(alias_string, &new_argv);
+
+ if (count < 1)
+ die("empty alias for %s", alias_command);
+
+ if (!strcmp(alias_command, new_argv[0]))
+ die("recursive alias: %s", alias_command);
+
+ /* insert after command name */
+ if (*argcp > 1) {
+ new_argv = realloc(new_argv, sizeof(char*) *
+ (count + *argcp - 1));
+ memcpy(new_argv + count, *argv, sizeof(char*) *
+ (*argcp - 1));
+ }
+
+ *argv = new_argv;
+ *argcp += count - 1;
+
+ ret = 1;
+ }
+ }
+
+ if (subdir)
+ chdir(subdir);
+
+ return ret;
+}
+
const char git_version_string[] = GIT_VERSION;
static void handle_internal_command(int argc, const char **argv, char **envp)
@@ -121,6 +229,7 @@ int main(int argc, const char **argv, ch
if (!strncmp(cmd, "git-", 4)) {
cmd += 4;
argv[0] = cmd;
+ handle_alias(&argc, &argv);
handle_internal_command(argc, argv, envp);
die("cannot handle %s internally", cmd);
}
@@ -178,6 +287,8 @@ int main(int argc, const char **argv, ch
exec_path = git_exec_path();
prepend_to_path(exec_path, strlen(exec_path));
+ handle_alias(&argc, &argv);
+
/* See if it's an internal command */
handle_internal_command(argc, argv, envp);
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2006-06-05 17:43 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-04 18:47 [PATCH] git: handle aliases defined in $GIT_DIR/config Johannes Schindelin
2006-06-04 20:24 ` Junio C Hamano
2006-06-05 16:51 ` Johannes Schindelin
2006-06-05 17:02 ` Johannes Schindelin
2006-06-05 17:43 ` Johannes Schindelin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox