* [PATCH 7/7] shell should call the new setup_path() to setup $PATH
2007-10-27 8:36 ` [PATCH 6/7] walk $PATH to generate list of commands for "help -a" Scott R Parish
@ 2007-10-27 8:36 ` Scott R Parish
2007-10-28 6:18 ` [PATCH 6/7] walk $PATH to generate list of commands for "help -a" Junio C Hamano
` (3 subsequent siblings)
4 siblings, 0 replies; 25+ messages in thread
From: Scott R Parish @ 2007-10-27 8:36 UTC (permalink / raw)
To: git; +Cc: Scott R Parish
Shell currently does its own manual thing for setting up the $PATH;
it can now call setup_path().
Signed-off-by: Scott R Parish <srp@srparish.net>
---
shell.c | 8 +-------
1 files changed, 1 insertions(+), 7 deletions(-)
diff --git a/shell.c b/shell.c
index cfe372b..9826109 100644
--- a/shell.c
+++ b/shell.c
@@ -24,17 +24,11 @@ static int do_cvs_cmd(const char *me, char *arg)
const char *cvsserver_argv[3] = {
"cvsserver", "server", NULL
};
- const char *oldpath = getenv("PATH");
- struct strbuf newpath = STRBUF_INIT;
if (!arg || strcmp(arg, "server"))
die("git-cvsserver only handles server: %s", arg);
- strbuf_addstr(&newpath, git_exec_path());
- strbuf_addch(&newpath, ':');
- strbuf_addstr(&newpath, oldpath);
-
- setenv("PATH", strbuf_detach(&newpath, NULL), 1);
+ setup_path(NULL);
return execv_git_cmd(cvsserver_argv);
}
--
gitgui.0.8.4.11178.g9a1bf-dirty
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH 6/7] walk $PATH to generate list of commands for "help -a"
2007-10-27 8:36 ` [PATCH 6/7] walk $PATH to generate list of commands for "help -a" Scott R Parish
2007-10-27 8:36 ` [PATCH 7/7] shell should call the new setup_path() to setup $PATH Scott R Parish
@ 2007-10-28 6:18 ` Junio C Hamano
2007-10-28 9:45 ` Scott Parish
2007-10-28 11:18 ` [PATCH 6/7] include $PATH in generating " Scott R Parish
` (2 subsequent siblings)
4 siblings, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2007-10-28 6:18 UTC (permalink / raw)
To: Scott R Parish; +Cc: git
Scott R Parish <srp@srparish.net> writes:
> Git had previously been using the $PATH for scripts--a previous
> patch moved exec'ed commands to also use the $PATH. For consistancy
> "help -a" should also use the $PATH.
s/consistancy/consistency/
> We walk all the paths in $PATH collecting the names of "git-*"
> commands. To help distinguish between the main git commands
> and commands picked up elsewhere (probably extensions) we
> print them seperately. The main commands are the ones that
> are found in the first directory in $PATH that contains the
> "git" binary.
This is not right. $(gitexecdir) in Makefile is designed to
allow distros to move git-* commands out of the primary user
$PATH directories and install only "git" wrapper in /usr/bin.
"Use the directory 'git' is in" rule breaks this.
The "main commands" should be the first of argv_exec_path,
EXEC_PATH_ENVIRONMENT or builtin_exec_path.
> diff --git a/help.c b/help.c
> index ce3d795..ee4fce0 100644
> --- a/help.c
> +++ b/help.c
> @@ -64,7 +69,42 @@ static int cmdname_compare(const void *a_, const void *b_)
> ...
> +static void subtract_cmds(struct cmdnames *a, struct cmdnames *b) {
> + int ai, aj, bi;
> +
> + ai = aj = bi = 0;
> + while (ai < a->cnt && bi < b->cnt) {
> + if (0 > strcmp(a->names[ai]->name, b->names[bi]->name))
> + a->names[aj++] = a->names[ai++];
> + else if (0 > strcmp(a->names[ai]->name, b->names[bi]->name))
> + bi++;
> + else
> + ai++, bi++;
In general, xxxcmp(a, b) is designed to return the same sign as
"a - b" (subtract b from a, using an appropriate definition of
"subtract" in the domain of a and b). It is a good habit to
write:
strcmp(a, b) < 0 strcmp(a, b) > 0
because these give the same sign as
a < b a > b
and makes your program easier to read.
> @@ -122,18 +168,66 @@ static void list_commands(const char *exec_path)
> if (has_extension(de->d_name, ".exe"))
> entlen -= 4;
>
> + if (has_extension(de->d_name, ".perl") ||
> + has_extension(de->d_name, ".sh"))
> + continue;
> +
This needs a good justification.
If you have "." on PATH, and you run ./git in a freshly built
source directory, "git relink.perl" would try to run
./git-relink.perl.
I do not think excluding these is necessary nor is a good idea.
> +static void list_commands()
> +{
ANSI. "static void list_commands(void)".
> + path = paths = xstrdup(env_path);
> + while ((char *)1 != path) {
> + if ((colon = strchr(path, ':')))
> + *colon = 0;
> +
> + len = list_commands_in_dir(path);
> + longest = MAX(longest, len);
> +
> + path = colon + 1;
> + }
I know that on modern architectures bit representation of
(char*) NULL is the same as integer 0 of the same size as a
pointer, and adding 1 to it would yield (char *)1, but the above
feels _dirty_.
while (1) {
...
if (!colon)
break;
path = colon + 1;
}
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 6/7] walk $PATH to generate list of commands for "help -a"
2007-10-28 6:18 ` [PATCH 6/7] walk $PATH to generate list of commands for "help -a" Junio C Hamano
@ 2007-10-28 9:45 ` Scott Parish
2007-10-28 10:07 ` Junio C Hamano
0 siblings, 1 reply; 25+ messages in thread
From: Scott Parish @ 2007-10-28 9:45 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Sat, Oct 27, 2007 at 11:18:02PM -0700, Junio C Hamano wrote:
> > We walk all the paths in $PATH collecting the names of "git-*"
> > commands. To help distinguish between the main git commands
> > and commands picked up elsewhere (probably extensions) we
> > print them seperately. The main commands are the ones that
> > are found in the first directory in $PATH that contains the
> > "git" binary.
>
> This is not right. $(gitexecdir) in Makefile is designed to
> allow distros to move git-* commands out of the primary user
> $PATH directories and install only "git" wrapper in /usr/bin.
> "Use the directory 'git' is in" rule breaks this.
>
> The "main commands" should be the first of argv_exec_path,
> EXEC_PATH_ENVIRONMENT or builtin_exec_path.
This is after we've already prepended the above three paths (if
they're specified) to $PATH, so yes, generally they should be in
one of those directories, but more generally, it will be in one of
the directories in $PATH.
Its not clear to me what exactly you're looking for me to change,
just the wording i'm using in my comment? Or are you refering to
the approach?
When i email the changes, should i keep emailing the whole
patch series, or just the few patches that have changed?
Thanks
sRp
--
Scott Parish
http://srparish.net/
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 6/7] walk $PATH to generate list of commands for "help -a"
2007-10-28 9:45 ` Scott Parish
@ 2007-10-28 10:07 ` Junio C Hamano
2007-10-28 11:15 ` Scott Parish
0 siblings, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2007-10-28 10:07 UTC (permalink / raw)
To: Scott Parish; +Cc: git
Scott Parish <sRp@srparish.net> writes:
> On Sat, Oct 27, 2007 at 11:18:02PM -0700, Junio C Hamano wrote:
>
>> > We walk all the paths in $PATH collecting the names of "git-*"
>> > commands. To help distinguish between the main git commands
>> > and commands picked up elsewhere (probably extensions) we
>> > print them seperately. The main commands are the ones that
>> > are found in the first directory in $PATH that contains the
>> > "git" binary.
>> ...
> Its not clear to me what exactly you're looking for me to change,
> just the wording i'm using in my comment? Or are you refering to
> the approach?
"git" binary will be found as /usr/bin/git while git-foo will be
found as /usr/libexec/git/git-foo in such an installation that
takes advantage of $(gitexecdir). And /usr/libexec/git/git will
not exist. Using existence of /usr/bin/git (I am referring to
your 'first directory on $PATH that contains the "git" binary'
above) as the cue for the location of "main commands" is wrong.
> When i email the changes, should i keep emailing the whole
> patch series, or just the few patches that have changed?
It's up to you. Obviously, if you are replacing 2 patches out
of 100-patch series, you would not want to resend the whole
thing, though ;-)
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 6/7] walk $PATH to generate list of commands for "help -a"
2007-10-28 10:07 ` Junio C Hamano
@ 2007-10-28 11:15 ` Scott Parish
0 siblings, 0 replies; 25+ messages in thread
From: Scott Parish @ 2007-10-28 11:15 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Sun, Oct 28, 2007 at 03:07:14AM -0700, Junio C Hamano wrote:
> Scott Parish <sRp@srparish.net> writes:
>
> > On Sat, Oct 27, 2007 at 11:18:02PM -0700, Junio C Hamano wrote:
> >
> >> > We walk all the paths in $PATH collecting the names of "git-*"
> >> > commands. To help distinguish between the main git commands
> >> > and commands picked up elsewhere (probably extensions) we
> >> > print them seperately. The main commands are the ones that
> >> > are found in the first directory in $PATH that contains the
> >> > "git" binary.
> >> ...
> > Its not clear to me what exactly you're looking for me to change,
> > just the wording i'm using in my comment? Or are you refering to
> > the approach?
>
> "git" binary will be found as /usr/bin/git while git-foo will be
> found as /usr/libexec/git/git-foo in such an installation that
> takes advantage of $(gitexecdir). And /usr/libexec/git/git will
> not exist. Using existence of /usr/bin/git (I am referring to
> your 'first directory on $PATH that contains the "git" binary'
> above) as the cue for the location of "main commands" is wrong.
Thanks for the clarification, that would be a problem. I've modified
the patch to list the main commands from git_exec_path(); i have
mixed feelings, but curious what you think.
sRp
--
Scott Parish
http://srparish.net/
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 6/7] include $PATH in generating list of commands for "help -a"
2007-10-27 8:36 ` [PATCH 6/7] walk $PATH to generate list of commands for "help -a" Scott R Parish
2007-10-27 8:36 ` [PATCH 7/7] shell should call the new setup_path() to setup $PATH Scott R Parish
2007-10-28 6:18 ` [PATCH 6/7] walk $PATH to generate list of commands for "help -a" Junio C Hamano
@ 2007-10-28 11:18 ` Scott R Parish
2007-10-28 11:32 ` Junio C Hamano
2007-10-28 14:44 ` Scott R Parish
2007-10-29 3:30 ` Scott R Parish
4 siblings, 1 reply; 25+ messages in thread
From: Scott R Parish @ 2007-10-28 11:18 UTC (permalink / raw)
To: git; +Cc: Scott R Parish
Git had previously been using the $PATH for scripts--a previous
patch moved exec'ed commands to also use the $PATH. For consistency
"help -a" should also list commands in the $PATH.
The main commands are still listed from the git_exec_path(), but
the $PATH is walked and other git commands (probably extensions) are
listed.
Signed-off-by: Scott R Parish <srp@srparish.net>
---
help.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 124 insertions(+), 38 deletions(-)
diff --git a/help.c b/help.c
index 34ac5db..2534bf0 100644
--- a/help.c
+++ b/help.c
@@ -37,24 +37,28 @@ static inline void mput_char(char c, unsigned int num)
putchar(c);
}
-static struct cmdname {
- size_t len;
- char name[1];
-} **cmdname;
-static int cmdname_alloc, cmdname_cnt;
-
-static void add_cmdname(const char *name, int len)
+static struct cmdnames {
+ int alloc;
+ int cnt;
+ struct cmdname {
+ size_t len;
+ char name[1];
+ } **names;
+} main_cmds, other_cmds;
+
+static void add_cmdname(struct cmdnames *cmds, const char *name, int len)
{
struct cmdname *ent;
- if (cmdname_alloc <= cmdname_cnt) {
- cmdname_alloc = cmdname_alloc + 200;
- cmdname = xrealloc(cmdname, cmdname_alloc * sizeof(*cmdname));
+ if (cmds->alloc <= cmds->cnt) {
+ cmds->alloc = cmds->alloc + 200;
+ cmds->names = xrealloc(cmds->names,
+ cmds->alloc * sizeof(*cmds->names));
}
ent = xmalloc(sizeof(*ent) + len);
ent->len = len;
memcpy(ent->name, name, len);
ent->name[len] = 0;
- cmdname[cmdname_cnt++] = ent;
+ cmds->names[cmds->cnt++] = ent;
}
static int cmdname_compare(const void *a_, const void *b_)
@@ -64,7 +68,44 @@ static int cmdname_compare(const void *a_, const void *b_)
return strcmp(a->name, b->name);
}
-static void pretty_print_string_list(struct cmdname **cmdname, int longest)
+static void uniq(struct cmdnames *cmds)
+{
+ int i, j;
+
+ if (!cmds->cnt)
+ return;
+
+ for (i = j = 1; i < cmds->cnt; i++) {
+ if (strcmp(cmds->names[i]->name, cmds->names[i-1]->name)) {
+ cmds->names[j++] = cmds->names[i];
+ }
+ }
+
+ cmds->cnt = j;
+}
+
+static void subtract_cmds(struct cmdnames *a, struct cmdnames *b) {
+ int ai, aj, bi;
+ int cmp;
+
+ ai = aj = bi = 0;
+ while (ai < a->cnt && bi < b->cnt) {
+ cmp = strcmp(a->names[ai]->name, b->names[bi]->name);
+ if (cmp < 0)
+ a->names[aj++] = a->names[ai++];
+ else if (cmp == 0)
+ ai++, bi++;
+ else if (cmp > 0)
+ bi++;
+ }
+
+ while (ai < a->cnt)
+ a->names[aj++] = a->names[ai++];
+
+ a->cnt = aj;
+}
+
+static void pretty_print_string_list(struct cmdnames *cmds, int longest)
{
int cols = 1, rows;
int space = longest + 1; /* min 1 SP between words */
@@ -73,9 +114,7 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest)
if (space < max_cols)
cols = max_cols / space;
- rows = (cmdname_cnt + cols - 1) / cols;
-
- qsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare);
+ rows = (cmds->cnt + cols - 1) / cols;
for (i = 0; i < rows; i++) {
printf(" ");
@@ -83,31 +122,29 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest)
for (j = 0; j < cols; j++) {
int n = j * rows + i;
int size = space;
- if (n >= cmdname_cnt)
+ if (n >= cmds->cnt)
break;
- if (j == cols-1 || n + rows >= cmdname_cnt)
+ if (j == cols-1 || n + rows >= cmds->cnt)
size = 1;
- printf("%-*s", size, cmdname[n]->name);
+ printf("%-*s", size, cmds->names[n]->name);
}
putchar('\n');
}
}
-static void list_commands(const char *exec_path)
+static unsigned int list_commands_in_dir(struct cmdnames *cmds, const char *dir)
{
unsigned int longest = 0;
const char *prefix = "git-";
int prefix_len = strlen(prefix);
- DIR *dir = opendir(exec_path);
+ DIR *dirp = opendir(dir);
struct dirent *de;
+ struct stat st;
- if (!dir || chdir(exec_path)) {
- fprintf(stderr, "git: '%s': %s\n", exec_path, strerror(errno));
- exit(1);
- }
+ if (!dirp || chdir(dir))
+ return 0;
- while ((de = readdir(dir)) != NULL) {
- struct stat st;
+ while ((de = readdir(dirp)) != NULL) {
int entlen;
if (prefixcmp(de->d_name, prefix))
@@ -125,16 +162,67 @@ static void list_commands(const char *exec_path)
if (longest < entlen)
longest = entlen;
- add_cmdname(de->d_name + prefix_len, entlen);
+ add_cmdname(cmds, de->d_name + prefix_len, entlen);
+ }
+ closedir(dirp);
+
+ return longest;
+}
+
+static void list_commands(void)
+{
+ unsigned int longest = 0;
+ unsigned int len;
+ const char *env_path = getenv("PATH");
+ char *paths, *path, *colon;
+ const char *exec_path = git_exec_path();
+
+ if (exec_path)
+ longest = list_commands_in_dir(&main_cmds, exec_path);
+
+ if (!env_path) {
+ fprintf(stderr, "PATH not set\n");
+ exit(1);
+ }
+
+ path = paths = xstrdup(env_path);
+ while (1) {
+ if ((colon = strchr(path, ':')))
+ *colon = 0;
+
+ len = list_commands_in_dir(&other_cmds, path);
+ longest = MAX(longest, len);
+
+ if (!colon)
+ break;
+ path = colon + 1;
+ }
+ free(paths);
+
+ qsort(main_cmds.names, main_cmds.cnt,
+ sizeof(*main_cmds.names), cmdname_compare);
+ uniq(&main_cmds);
+
+ qsort(other_cmds.names, other_cmds.cnt,
+ sizeof(*other_cmds.names), cmdname_compare);
+ uniq(&other_cmds);
+ subtract_cmds(&other_cmds, &main_cmds);
+
+ if (main_cmds.cnt) {
+ printf("available git commands in '%s'\n", exec_path);
+ printf("----------------------------");
+ mput_char('-', strlen(exec_path));
+ putchar('\n');
+ pretty_print_string_list(&main_cmds, longest);
+ putchar('\n');
+ }
+
+ if (other_cmds.cnt) {
+ printf("git commands available from elsewhere on your $PATH\n");
+ printf("---------------------------------------------------\n");
+ pretty_print_string_list(&other_cmds, longest);
+ putchar('\n');
}
- closedir(dir);
-
- printf("git commands available in '%s'\n", exec_path);
- printf("----------------------------");
- mput_char('-', strlen(exec_path));
- putchar('\n');
- pretty_print_string_list(cmdname, longest);
- putchar('\n');
}
void list_common_cmds_help(void)
@@ -188,7 +276,6 @@ int cmd_version(int argc, const char **argv, const char *prefix)
int cmd_help(int argc, const char **argv, const char *prefix)
{
const char *help_cmd = argc > 1 ? argv[1] : NULL;
- const char *exec_path = git_exec_path();
if (!help_cmd) {
printf("usage: %s\n\n", git_usage_string);
@@ -198,8 +285,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)
else if (!strcmp(help_cmd, "--all") || !strcmp(help_cmd, "-a")) {
printf("usage: %s\n\n", git_usage_string);
- if(exec_path)
- list_commands(exec_path);
+ list_commands();
exit(0);
}
--
1.5.3.4.401.g19778-dirty
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH 6/7] include $PATH in generating list of commands for "help -a"
2007-10-28 11:18 ` [PATCH 6/7] include $PATH in generating " Scott R Parish
@ 2007-10-28 11:32 ` Junio C Hamano
2007-10-28 14:39 ` Scott Parish
0 siblings, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2007-10-28 11:32 UTC (permalink / raw)
To: Scott R Parish; +Cc: git
Scott R Parish <srp@srparish.net> writes:
> + while (1) {
> + if ((colon = strchr(path, ':')))
> + *colon = 0;
> +
> + len = list_commands_in_dir(&other_cmds, path);
> + longest = MAX(longest, len);
Where do we borrow this MAX() macro?
On Linux with glibc, /usr/include/sys/param.h which is included
by git-compat-util.h (meaning, for everybody) is where we find
it, but that somehow does not sound portable assumption.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 6/7] include $PATH in generating list of commands for "help -a"
2007-10-28 11:32 ` Junio C Hamano
@ 2007-10-28 14:39 ` Scott Parish
0 siblings, 0 replies; 25+ messages in thread
From: Scott Parish @ 2007-10-28 14:39 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Sun, Oct 28, 2007 at 04:32:12AM -0700, Junio C Hamano wrote:
> Scott R Parish <srp@srparish.net> writes:
>
> > + while (1) {
> > + if ((colon = strchr(path, ':')))
> > + *colon = 0;
> > +
> > + len = list_commands_in_dir(&other_cmds, path);
> > + longest = MAX(longest, len);
>
> Where do we borrow this MAX() macro?
>
> On Linux with glibc, /usr/include/sys/param.h which is included
> by git-compat-util.h (meaning, for everybody) is where we find
> it, but that somehow does not sound portable assumption.
Awesome catch
sRp
--
Scott Parish
http://srparish.net/
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 6/7] include $PATH in generating list of commands for "help -a"
2007-10-27 8:36 ` [PATCH 6/7] walk $PATH to generate list of commands for "help -a" Scott R Parish
` (2 preceding siblings ...)
2007-10-28 11:18 ` [PATCH 6/7] include $PATH in generating " Scott R Parish
@ 2007-10-28 14:44 ` Scott R Parish
2007-10-28 16:51 ` Johannes Schindelin
2007-10-29 3:30 ` Scott R Parish
4 siblings, 1 reply; 25+ messages in thread
From: Scott R Parish @ 2007-10-28 14:44 UTC (permalink / raw)
To: git; +Cc: Scott R Parish
Git had previously been using the $PATH for scripts--a previous
patch moved exec'ed commands to also use the $PATH. For consistency
"help -a" should also list commands in the $PATH.
The main commands are still listed from the git_exec_path(), but
the $PATH is walked and other git commands (probably extensions) are
listed.
Signed-off-by: Scott R Parish <srp@srparish.net>
---
help.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 125 insertions(+), 38 deletions(-)
diff --git a/help.c b/help.c
index 34ac5db..07cf67a 100644
--- a/help.c
+++ b/help.c
@@ -37,24 +37,28 @@ static inline void mput_char(char c, unsigned int num)
putchar(c);
}
-static struct cmdname {
- size_t len;
- char name[1];
-} **cmdname;
-static int cmdname_alloc, cmdname_cnt;
-
-static void add_cmdname(const char *name, int len)
+static struct cmdnames {
+ int alloc;
+ int cnt;
+ struct cmdname {
+ size_t len;
+ char name[1];
+ } **names;
+} main_cmds, other_cmds;
+
+static void add_cmdname(struct cmdnames *cmds, const char *name, int len)
{
struct cmdname *ent;
- if (cmdname_alloc <= cmdname_cnt) {
- cmdname_alloc = cmdname_alloc + 200;
- cmdname = xrealloc(cmdname, cmdname_alloc * sizeof(*cmdname));
+ if (cmds->alloc <= cmds->cnt) {
+ cmds->alloc = cmds->alloc + 200;
+ cmds->names = xrealloc(cmds->names,
+ cmds->alloc * sizeof(*cmds->names));
}
ent = xmalloc(sizeof(*ent) + len);
ent->len = len;
memcpy(ent->name, name, len);
ent->name[len] = 0;
- cmdname[cmdname_cnt++] = ent;
+ cmds->names[cmds->cnt++] = ent;
}
static int cmdname_compare(const void *a_, const void *b_)
@@ -64,7 +68,44 @@ static int cmdname_compare(const void *a_, const void *b_)
return strcmp(a->name, b->name);
}
-static void pretty_print_string_list(struct cmdname **cmdname, int longest)
+static void uniq(struct cmdnames *cmds)
+{
+ int i, j;
+
+ if (!cmds->cnt)
+ return;
+
+ for (i = j = 1; i < cmds->cnt; i++) {
+ if (strcmp(cmds->names[i]->name, cmds->names[i-1]->name)) {
+ cmds->names[j++] = cmds->names[i];
+ }
+ }
+
+ cmds->cnt = j;
+}
+
+static void subtract_cmds(struct cmdnames *a, struct cmdnames *b) {
+ int ai, aj, bi;
+ int cmp;
+
+ ai = aj = bi = 0;
+ while (ai < a->cnt && bi < b->cnt) {
+ cmp = strcmp(a->names[ai]->name, b->names[bi]->name);
+ if (cmp < 0)
+ a->names[aj++] = a->names[ai++];
+ else if (cmp == 0)
+ ai++, bi++;
+ else if (cmp > 0)
+ bi++;
+ }
+
+ while (ai < a->cnt)
+ a->names[aj++] = a->names[ai++];
+
+ a->cnt = aj;
+}
+
+static void pretty_print_string_list(struct cmdnames *cmds, int longest)
{
int cols = 1, rows;
int space = longest + 1; /* min 1 SP between words */
@@ -73,9 +114,7 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest)
if (space < max_cols)
cols = max_cols / space;
- rows = (cmdname_cnt + cols - 1) / cols;
-
- qsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare);
+ rows = (cmds->cnt + cols - 1) / cols;
for (i = 0; i < rows; i++) {
printf(" ");
@@ -83,31 +122,29 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest)
for (j = 0; j < cols; j++) {
int n = j * rows + i;
int size = space;
- if (n >= cmdname_cnt)
+ if (n >= cmds->cnt)
break;
- if (j == cols-1 || n + rows >= cmdname_cnt)
+ if (j == cols-1 || n + rows >= cmds->cnt)
size = 1;
- printf("%-*s", size, cmdname[n]->name);
+ printf("%-*s", size, cmds->names[n]->name);
}
putchar('\n');
}
}
-static void list_commands(const char *exec_path)
+static unsigned int list_commands_in_dir(struct cmdnames *cmds, const char *dir)
{
unsigned int longest = 0;
const char *prefix = "git-";
int prefix_len = strlen(prefix);
- DIR *dir = opendir(exec_path);
+ DIR *dirp = opendir(dir);
struct dirent *de;
+ struct stat st;
- if (!dir || chdir(exec_path)) {
- fprintf(stderr, "git: '%s': %s\n", exec_path, strerror(errno));
- exit(1);
- }
+ if (!dirp || chdir(dir))
+ return 0;
- while ((de = readdir(dir)) != NULL) {
- struct stat st;
+ while ((de = readdir(dirp)) != NULL) {
int entlen;
if (prefixcmp(de->d_name, prefix))
@@ -125,16 +162,68 @@ static void list_commands(const char *exec_path)
if (longest < entlen)
longest = entlen;
- add_cmdname(de->d_name + prefix_len, entlen);
+ add_cmdname(cmds, de->d_name + prefix_len, entlen);
+ }
+ closedir(dirp);
+
+ return longest;
+}
+
+static void list_commands(void)
+{
+ unsigned int longest = 0;
+ unsigned int len;
+ const char *env_path = getenv("PATH");
+ char *paths, *path, *colon;
+ const char *exec_path = git_exec_path();
+
+ if (exec_path)
+ longest = list_commands_in_dir(&main_cmds, exec_path);
+
+ if (!env_path) {
+ fprintf(stderr, "PATH not set\n");
+ exit(1);
+ }
+
+ path = paths = xstrdup(env_path);
+ while (1) {
+ if ((colon = strchr(path, ':')))
+ *colon = 0;
+
+ len = list_commands_in_dir(&other_cmds, path);
+ if (len > longest)
+ longest = len;
+
+ if (!colon)
+ break;
+ path = colon + 1;
+ }
+ free(paths);
+
+ qsort(main_cmds.names, main_cmds.cnt,
+ sizeof(*main_cmds.names), cmdname_compare);
+ uniq(&main_cmds);
+
+ qsort(other_cmds.names, other_cmds.cnt,
+ sizeof(*other_cmds.names), cmdname_compare);
+ uniq(&other_cmds);
+ subtract_cmds(&other_cmds, &main_cmds);
+
+ if (main_cmds.cnt) {
+ printf("available git commands in '%s'\n", exec_path);
+ printf("----------------------------");
+ mput_char('-', strlen(exec_path));
+ putchar('\n');
+ pretty_print_string_list(&main_cmds, longest);
+ putchar('\n');
+ }
+
+ if (other_cmds.cnt) {
+ printf("git commands available from elsewhere on your $PATH\n");
+ printf("---------------------------------------------------\n");
+ pretty_print_string_list(&other_cmds, longest);
+ putchar('\n');
}
- closedir(dir);
-
- printf("git commands available in '%s'\n", exec_path);
- printf("----------------------------");
- mput_char('-', strlen(exec_path));
- putchar('\n');
- pretty_print_string_list(cmdname, longest);
- putchar('\n');
}
void list_common_cmds_help(void)
@@ -188,7 +277,6 @@ int cmd_version(int argc, const char **argv, const char *prefix)
int cmd_help(int argc, const char **argv, const char *prefix)
{
const char *help_cmd = argc > 1 ? argv[1] : NULL;
- const char *exec_path = git_exec_path();
if (!help_cmd) {
printf("usage: %s\n\n", git_usage_string);
@@ -198,8 +286,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)
else if (!strcmp(help_cmd, "--all") || !strcmp(help_cmd, "-a")) {
printf("usage: %s\n\n", git_usage_string);
- if(exec_path)
- list_commands(exec_path);
+ list_commands();
exit(0);
}
--
1.5.3.4.401.g19778-dirty
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH 6/7] include $PATH in generating list of commands for "help -a"
2007-10-28 14:44 ` Scott R Parish
@ 2007-10-28 16:51 ` Johannes Schindelin
2007-10-29 2:44 ` Scott Parish
0 siblings, 1 reply; 25+ messages in thread
From: Johannes Schindelin @ 2007-10-28 16:51 UTC (permalink / raw)
To: Scott R Parish; +Cc: git
Hi,
On Sun, 28 Oct 2007, Scott R Parish wrote:
> diff --git a/help.c b/help.c
> index 34ac5db..07cf67a 100644
> --- a/help.c
> +++ b/help.c
> @@ -37,24 +37,28 @@ static inline void mput_char(char c, unsigned int num)
> putchar(c);
> }
>
> -static struct cmdname {
> - size_t len;
> - char name[1];
> -} **cmdname;
> -static int cmdname_alloc, cmdname_cnt;
> -
> -static void add_cmdname(const char *name, int len)
> +static struct cmdnames {
> + int alloc;
> + int cnt;
> + struct cmdname {
> + size_t len;
> + char name[1];
> + } **names;
> +} main_cmds, other_cmds;
> +
> +static void add_cmdname(struct cmdnames *cmds, const char *name, int len)
> {
> struct cmdname *ent;
> - if (cmdname_alloc <= cmdname_cnt) {
> - cmdname_alloc = cmdname_alloc + 200;
> - cmdname = xrealloc(cmdname, cmdname_alloc * sizeof(*cmdname));
> + if (cmds->alloc <= cmds->cnt) {
> + cmds->alloc = cmds->alloc + 200;
> + cmds->names = xrealloc(cmds->names,
> + cmds->alloc * sizeof(*cmds->names));
Looks like a candidate for ALLOC_GROW() ...
> @@ -64,7 +68,44 @@ static int cmdname_compare(const void *a_, const void *b_)
> return strcmp(a->name, b->name);
> }
>
> -static void pretty_print_string_list(struct cmdname **cmdname, int longest)
> +static void uniq(struct cmdnames *cmds)
> +{
> + int i, j;
> +
> + if (!cmds->cnt)
> + return;
> +
> + for (i = j = 1; i < cmds->cnt; i++) {
> + if (strcmp(cmds->names[i]->name, cmds->names[i-1]->name)) {
> + cmds->names[j++] = cmds->names[i];
> + }
> + }
Losing the curly brackets would make this look much nicer.
> +
> + cmds->cnt = j;
> +}
> +
> +static void subtract_cmds(struct cmdnames *a, struct cmdnames *b) {
Maybe "exclude_cmds()", and choose more suggestive names for the
parameters?
> - DIR *dir = opendir(exec_path);
> + DIR *dirp = opendir(dir);
I am not sure that a rename from "dir" to "dirp" is needed here. It
distracts a little from the real content of your patch.
Thanks,
Dscho
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 6/7] include $PATH in generating list of commands for "help -a"
2007-10-28 16:51 ` Johannes Schindelin
@ 2007-10-29 2:44 ` Scott Parish
2007-10-29 11:30 ` Johannes Schindelin
0 siblings, 1 reply; 25+ messages in thread
From: Scott Parish @ 2007-10-29 2:44 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
On Sun, Oct 28, 2007 at 04:51:00PM +0000, Johannes Schindelin wrote:
> > +static void subtract_cmds(struct cmdnames *a, struct cmdnames *b) {
>
> Maybe "exclude_cmds()", and choose more suggestive names for the
> parameters?
I was thinking set operations when i named this (hense "a" and "b"),
but i'll try this out.
sRp
--
Scott Parish
http://srparish.net/
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 6/7] include $PATH in generating list of commands for "help -a"
2007-10-29 2:44 ` Scott Parish
@ 2007-10-29 11:30 ` Johannes Schindelin
2007-10-29 11:45 ` David Symonds
0 siblings, 1 reply; 25+ messages in thread
From: Johannes Schindelin @ 2007-10-29 11:30 UTC (permalink / raw)
To: Scott Parish; +Cc: git
Hi,
On Sun, 28 Oct 2007, Scott Parish wrote:
> On Sun, Oct 28, 2007 at 04:51:00PM +0000, Johannes Schindelin wrote:
>
> > > +static void subtract_cmds(struct cmdnames *a, struct cmdnames *b) {
> >
> > Maybe "exclude_cmds()", and choose more suggestive names for the
> > parameters?
>
> I was thinking set operations when i named this (hense "a" and "b"),
> but i'll try this out.
Yes, I guessed that. But in that case, "subtract" is actively wrong,
since you cannot guarantee (and indeed do not want to assume) that one is
the subset of the other.
Ciao,
Dscho
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 6/7] include $PATH in generating list of commands for "help -a"
2007-10-29 11:30 ` Johannes Schindelin
@ 2007-10-29 11:45 ` David Symonds
0 siblings, 0 replies; 25+ messages in thread
From: David Symonds @ 2007-10-29 11:45 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Scott Parish, git
On 10/29/07, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> Hi,
>
> On Sun, 28 Oct 2007, Scott Parish wrote:
>
> > I was thinking set operations when i named this (hense "a" and "b"),
> > but i'll try this out.
>
> Yes, I guessed that. But in that case, "subtract" is actively wrong,
> since you cannot guarantee (and indeed do not want to assume) that one is
> the subset of the other.
The nearest set theory operation would be "difference" (or
"complement"); that does not require that the subtrahend is a subset
of the minuend.
Dave.
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 6/7] include $PATH in generating list of commands for "help -a"
2007-10-27 8:36 ` [PATCH 6/7] walk $PATH to generate list of commands for "help -a" Scott R Parish
` (3 preceding siblings ...)
2007-10-28 14:44 ` Scott R Parish
@ 2007-10-29 3:30 ` Scott R Parish
2007-10-29 21:17 ` Junio C Hamano
4 siblings, 1 reply; 25+ messages in thread
From: Scott R Parish @ 2007-10-29 3:30 UTC (permalink / raw)
To: git; +Cc: Scott R Parish
Git had previously been using the $PATH for scripts--a previous
patch moved exec'ed commands to also use the $PATH. For consistency
"help -a" should also list commands in the $PATH.
The main commands are still listed from the git_exec_path(), but
the $PATH is walked and other git commands (probably extensions) are
listed.
Signed-off-by: Scott R Parish <srp@srparish.net>
---
help.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 120 insertions(+), 37 deletions(-)
diff --git a/help.c b/help.c
index 34ac5db..855aeef 100644
--- a/help.c
+++ b/help.c
@@ -37,24 +37,25 @@ static inline void mput_char(char c, unsigned int num)
putchar(c);
}
-static struct cmdname {
- size_t len;
- char name[1];
-} **cmdname;
-static int cmdname_alloc, cmdname_cnt;
-
-static void add_cmdname(const char *name, int len)
+static struct cmdnames {
+ int alloc;
+ int cnt;
+ struct cmdname {
+ size_t len;
+ char name[1];
+ } **names;
+} main_cmds, other_cmds;
+
+static void add_cmdname(struct cmdnames *cmds, const char *name, int len)
{
- struct cmdname *ent;
- if (cmdname_alloc <= cmdname_cnt) {
- cmdname_alloc = cmdname_alloc + 200;
- cmdname = xrealloc(cmdname, cmdname_alloc * sizeof(*cmdname));
- }
- ent = xmalloc(sizeof(*ent) + len);
+ struct cmdname *ent = xmalloc(sizeof(*ent) + len);
+
ent->len = len;
memcpy(ent->name, name, len);
ent->name[len] = 0;
- cmdname[cmdname_cnt++] = ent;
+
+ ALLOC_GROW(cmds->names, cmds->cnt + 1, cmds->alloc);
+ cmds->names[cmds->cnt++] = ent;
}
static int cmdname_compare(const void *a_, const void *b_)
@@ -64,7 +65,42 @@ static int cmdname_compare(const void *a_, const void *b_)
return strcmp(a->name, b->name);
}
-static void pretty_print_string_list(struct cmdname **cmdname, int longest)
+static void uniq(struct cmdnames *cmds)
+{
+ int i, j;
+
+ if (!cmds->cnt)
+ return;
+
+ for (i = j = 1; i < cmds->cnt; i++)
+ if (strcmp(cmds->names[i]->name, cmds->names[i-1]->name))
+ cmds->names[j++] = cmds->names[i];
+
+ cmds->cnt = j;
+}
+
+static void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) {
+ int ci, cj, ei;
+ int cmp;
+
+ ci = cj = ei = 0;
+ while (ci < cmds->cnt && ei < excludes->cnt) {
+ cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name);
+ if (cmp < 0)
+ cmds->names[cj++] = cmds->names[ci++];
+ else if (cmp == 0)
+ ci++, ei++;
+ else if (cmp > 0)
+ ei++;
+ }
+
+ while (ci < cmds->cnt)
+ cmds->names[cj++] = cmds->names[ci++];
+
+ cmds->cnt = cj;
+}
+
+static void pretty_print_string_list(struct cmdnames *cmds, int longest)
{
int cols = 1, rows;
int space = longest + 1; /* min 1 SP between words */
@@ -73,9 +109,7 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest)
if (space < max_cols)
cols = max_cols / space;
- rows = (cmdname_cnt + cols - 1) / cols;
-
- qsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare);
+ rows = (cmds->cnt + cols - 1) / cols;
for (i = 0; i < rows; i++) {
printf(" ");
@@ -83,28 +117,27 @@ static void pretty_print_string_list(struct cmdname **cmdname, int longest)
for (j = 0; j < cols; j++) {
int n = j * rows + i;
int size = space;
- if (n >= cmdname_cnt)
+ if (n >= cmds->cnt)
break;
- if (j == cols-1 || n + rows >= cmdname_cnt)
+ if (j == cols-1 || n + rows >= cmds->cnt)
size = 1;
- printf("%-*s", size, cmdname[n]->name);
+ printf("%-*s", size, cmds->names[n]->name);
}
putchar('\n');
}
}
-static void list_commands(const char *exec_path)
+static unsigned int list_commands_in_dir(struct cmdnames *cmds,
+ const char *path)
{
unsigned int longest = 0;
const char *prefix = "git-";
int prefix_len = strlen(prefix);
- DIR *dir = opendir(exec_path);
+ DIR *dir = opendir(path);
struct dirent *de;
- if (!dir || chdir(exec_path)) {
- fprintf(stderr, "git: '%s': %s\n", exec_path, strerror(errno));
- exit(1);
- }
+ if (!dir || chdir(path))
+ return 0;
while ((de = readdir(dir)) != NULL) {
struct stat st;
@@ -125,16 +158,68 @@ static void list_commands(const char *exec_path)
if (longest < entlen)
longest = entlen;
- add_cmdname(de->d_name + prefix_len, entlen);
+ add_cmdname(cmds, de->d_name + prefix_len, entlen);
}
closedir(dir);
- printf("git commands available in '%s'\n", exec_path);
- printf("----------------------------");
- mput_char('-', strlen(exec_path));
- putchar('\n');
- pretty_print_string_list(cmdname, longest);
- putchar('\n');
+ return longest;
+}
+
+static void list_commands(void)
+{
+ unsigned int longest = 0;
+ unsigned int len;
+ const char *env_path = getenv("PATH");
+ char *paths, *path, *colon;
+ const char *exec_path = git_exec_path();
+
+ if (exec_path)
+ longest = list_commands_in_dir(&main_cmds, exec_path);
+
+ if (!env_path) {
+ fprintf(stderr, "PATH not set\n");
+ exit(1);
+ }
+
+ path = paths = xstrdup(env_path);
+ while (1) {
+ if ((colon = strchr(path, ':')))
+ *colon = 0;
+
+ len = list_commands_in_dir(&other_cmds, path);
+ if (len > longest)
+ longest = len;
+
+ if (!colon)
+ break;
+ path = colon + 1;
+ }
+ free(paths);
+
+ qsort(main_cmds.names, main_cmds.cnt,
+ sizeof(*main_cmds.names), cmdname_compare);
+ uniq(&main_cmds);
+
+ qsort(other_cmds.names, other_cmds.cnt,
+ sizeof(*other_cmds.names), cmdname_compare);
+ uniq(&other_cmds);
+ exclude_cmds(&other_cmds, &main_cmds);
+
+ if (main_cmds.cnt) {
+ printf("available git commands in '%s'\n", exec_path);
+ printf("----------------------------");
+ mput_char('-', strlen(exec_path));
+ putchar('\n');
+ pretty_print_string_list(&main_cmds, longest);
+ putchar('\n');
+ }
+
+ if (other_cmds.cnt) {
+ printf("git commands available from elsewhere on your $PATH\n");
+ printf("---------------------------------------------------\n");
+ pretty_print_string_list(&other_cmds, longest);
+ putchar('\n');
+ }
}
void list_common_cmds_help(void)
@@ -188,7 +273,6 @@ int cmd_version(int argc, const char **argv, const char *prefix)
int cmd_help(int argc, const char **argv, const char *prefix)
{
const char *help_cmd = argc > 1 ? argv[1] : NULL;
- const char *exec_path = git_exec_path();
if (!help_cmd) {
printf("usage: %s\n\n", git_usage_string);
@@ -198,8 +282,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)
else if (!strcmp(help_cmd, "--all") || !strcmp(help_cmd, "-a")) {
printf("usage: %s\n\n", git_usage_string);
- if(exec_path)
- list_commands(exec_path);
+ list_commands();
exit(0);
}
--
1.5.3.4.401.g19778-dirty
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH 6/7] include $PATH in generating list of commands for "help -a"
2007-10-29 3:30 ` Scott R Parish
@ 2007-10-29 21:17 ` Junio C Hamano
2007-10-30 3:00 ` Scott Parish
0 siblings, 1 reply; 25+ messages in thread
From: Junio C Hamano @ 2007-10-29 21:17 UTC (permalink / raw)
To: Scott R Parish; +Cc: git
Scott R Parish <srp@srparish.net> writes:
> Git had previously been using the $PATH for scripts--a previous
> patch moved exec'ed commands to also use the $PATH. For consistency
> "help -a" should also list commands in the $PATH.
>
> The main commands are still listed from the git_exec_path(), but
> the $PATH is walked and other git commands (probably extensions) are
> listed.
>
> Signed-off-by: Scott R Parish <srp@srparish.net>
> ---
> help.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++---------------
> 1 files changed, 120 insertions(+), 37 deletions(-)
Thanks.
It's easier to read if you briefly describe the differences
between the replacement patch and the previous version of the
patch below the three-dash lines. See for example Lars Knoll's
patch from today <200710290959.32538.lars@trolltech.com>.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 6/7] include $PATH in generating list of commands for "help -a"
2007-10-29 21:17 ` Junio C Hamano
@ 2007-10-30 3:00 ` Scott Parish
0 siblings, 0 replies; 25+ messages in thread
From: Scott Parish @ 2007-10-30 3:00 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Mon, Oct 29, 2007 at 02:17:26PM -0700, Junio C Hamano wrote:
> It's easier to read if you briefly describe the differences
> between the replacement patch and the previous version of the
> patch below the three-dash lines. See for example Lars Knoll's
> patch from today <200710290959.32538.lars@trolltech.com>.
Oh, that's useful information!
For the above patch, were basically what Johannes Schindelin suggested:
+ add_cmdname() now uses ALLOC_GROW and has its lines reordered to be
somewhat cleanre
+ uniq() has lost the curly brackets
+ s/subtract_cmds/exclude_cmds/
+ exclude_cmds() uses an arg name of "path" instead of "dir"
+ exclude_cmd() no longer renames "dir" to "dirp"
+ exclude_cmds() an earlier patch moved the "struct stat" declaration
for no-longer relevant reasons. change removed.
sRp
--
Scott Parish
http://srparish.net/
^ permalink raw reply [flat|nested] 25+ messages in thread