* Re: problems with importing from cvs archive
From: Jakub Narebski @ 2007-12-02 9:39 UTC (permalink / raw)
To: Ed S. Peschko; +Cc: git
In-Reply-To: <20071202064613.GB25351@venus>
"Ed S. Peschko" <esp5@pge.com> writes:
> I'm trying to use git-cvsimport to import from a CVS archive, using:
>
> git-cvsimport -d $CVSROOT
>
> and am getting the following error:
>
> fatal: refs/heads/origin: not a valid SHA1
> fatal: master: not a valid SHA1
> warning: You appear to be on a branch yet to be born
> warning: Forcing checkout of HEAD
> fatal: just how do you expect me to merge 0 trees?
> checkout failed: 256
[...]
> Or is this just a plain vanilla bug?
I guess that you might have been bitten by (just corrected, but not in
any released version yet) the bug in git-cvsimport (which is quite
old, and not very well maintained) when branches are packed.
You can either try last patch to cvsimport (it is in 'master'),
or unpack refs using "git reset --soft HEAD" when on given packed
branch,
--
Jakub Narebski
^ permalink raw reply
* Re: [PATCH 1/3] git-help: add -i|--info option to display info page.
From: Junio C Hamano @ 2007-12-02 9:25 UTC (permalink / raw)
To: Pascal Obry
Cc: Christian Couder, git, Theodore Tso, Jakub Narebski, Alex Riesen,
Andreas Ericsson, Matthieu Moy, Eric Wong
In-Reply-To: <475272CF.40602@obry.net>
Pascal Obry <pascal@obry.net> writes:
> Christian Couder a écrit :
>> "git help --info XXX" will now call "info git-XXX".
>
> If would be nice if this could be more generic. For example I'd like to
> use Emacs woman mode instead of info. Can't we have something like
>
> $ git help --ext XXX
>
> "ext" standing for external and calling whatever command recorded into
> .gitconfig for example ?
There is a bit of conflict here. We could do that and make the
implementation of "ext" command responsible to transform "commit" in
$ git help --ext commit
to the location of manual page (or formatted HTML page, or node in the
info documentation). git itself does not need to know much about where
the help material is in such an implementation.
But Christian's series is about making such "ext" thing easier to write.
No matter what kind of web browser is used, it needs to be told where
the preformatted HTML page for git-commit command is (and it does not
care where git-commit.1 manpage is found or what the node is called in
git.info document). It makes it a bit too limiting by defining -w (web)
and -i (info) upfront without offering -x (ext), but we need to start
somewhere.
Having said that, I think this is a post 1.5.4 material. Please keep
the discussion going, so that we can have something people can agree on
early after 1.5.4.
^ permalink raw reply
* Re: [PATCH 1/3] Prepare execv_git_cmd() for removal of builtins from the filesystem
From: Christian Couder @ 2007-12-02 8:48 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <1196579005-5662-1-git-send-email-gitster@pobox.com>
Le dimanche 2 décembre 2007, Junio C Hamano a écrit :
> + for (argc = 0; argv[argc]; argc++)
> + ; /* just counting */
> + nargv = xmalloc(sizeof(*nargv) * (argc + 2));
>
> - trace_argv_printf(argv, -1, "trace: exec:");
> + nargv[0] = "git";
> + for (argc = 0; argv[argc]; argc++)
> + nargv[argc + 1] = argv[argc];
> + nargv[argc + 1] = NULL;
> + trace_argv_printf(nargv, -1, "trace: exec:");
Minor nit: now that the number of arguments is known, we could perhaps use
the argument count instead of -1 in trace_argv_printf, so that it is not
computed again in quote.c:sq_quote_argv, like this:
trace_argv_printf(nargv, argc + 1, "trace: exec:");
Christian.
^ permalink raw reply
* [PATCH 2/2] Consolidate command list to one.
From: Junio C Hamano @ 2007-12-02 7:45 UTC (permalink / raw)
To: git
In-Reply-To: <1196581559-1614-1-git-send-email-gitster@pobox.com>
The categorized list of commands in git(7) and the list of common
commands in "git help" output were maintained separately, which was
insane. This consolidates them to a single command-list.txt file.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Documentation/Makefile | 4 +-
Documentation/cmd-list.perl | 138 +-----------------------------------------
Makefile | 8 +-
command-list.txt | 128 +++++++++++++++++++++++++++++++++++++++
generate-cmdlist.sh | 25 +-------
5 files changed, 140 insertions(+), 163 deletions(-)
create mode 100644 command-list.txt
diff --git a/Documentation/Makefile b/Documentation/Makefile
index d886641..de11ee0 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -122,9 +122,9 @@ cmds_txt = cmds-ancillaryinterrogators.txt \
$(cmds_txt): cmd-list.made
-cmd-list.made: cmd-list.perl $(MAN1_TXT)
+cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
$(RM) $@
- perl ./cmd-list.perl
+ perl ./cmd-list.perl ../command-list.txt
date >$@
git.7 git.html: git.txt
diff --git a/Documentation/cmd-list.perl b/Documentation/cmd-list.perl
index b709551..93b84b1 100755
--- a/Documentation/cmd-list.perl
+++ b/Documentation/cmd-list.perl
@@ -28,8 +28,8 @@ sub format_one {
}
if (my ($verify_name, $text) = ($description =~ /^($name) - (.*)/)) {
print $out "gitlink:$name\[1\]::\n\t";
- if ($attr) {
- print $out "($attr) ";
+ if ($attr =~ / deprecated /) {
+ print $out "(deprecated) ";
}
print $out "$text.\n\n";
}
@@ -39,12 +39,12 @@ sub format_one {
}
my %cmds = ();
-while (<DATA>) {
+for (sort <>) {
next if /^#/;
chomp;
my ($name, $cat, $attr) = /^(\S+)\s+(.*?)(?:\s+(.*))?$/;
- push @{$cmds{$cat}}, [$name, $attr];
+ push @{$cmds{$cat}}, [$name, " $attr "];
}
for my $cat (qw(ancillaryinterrogators
@@ -71,133 +71,3 @@ for my $cat (qw(ancillaryinterrogators
rename "$out+", "$out";
}
}
-
-# The following list is sorted with "sort -d" to make it easier
-# to find entry in the resulting git.html manual page.
-__DATA__
-git-add mainporcelain
-git-am mainporcelain
-git-annotate ancillaryinterrogators
-git-apply plumbingmanipulators
-git-archimport foreignscminterface
-git-archive mainporcelain
-git-bisect mainporcelain
-git-blame ancillaryinterrogators
-git-branch mainporcelain
-git-bundle mainporcelain
-git-cat-file plumbinginterrogators
-git-check-attr purehelpers
-git-checkout mainporcelain
-git-checkout-index plumbingmanipulators
-git-check-ref-format purehelpers
-git-cherry ancillaryinterrogators
-git-cherry-pick mainporcelain
-git-citool mainporcelain
-git-clean mainporcelain
-git-clone mainporcelain
-git-commit mainporcelain
-git-commit-tree plumbingmanipulators
-git-config ancillarymanipulators
-git-count-objects ancillaryinterrogators
-git-cvsexportcommit foreignscminterface
-git-cvsimport foreignscminterface
-git-cvsserver foreignscminterface
-git-daemon synchingrepositories
-git-describe mainporcelain
-git-diff mainporcelain
-git-diff-files plumbinginterrogators
-git-diff-index plumbinginterrogators
-git-diff-tree plumbinginterrogators
-git-fast-import ancillarymanipulators
-git-fetch mainporcelain
-git-fetch-pack synchingrepositories
-git-filter-branch ancillarymanipulators
-git-fmt-merge-msg purehelpers
-git-for-each-ref plumbinginterrogators
-git-format-patch mainporcelain
-git-fsck ancillaryinterrogators
-git-gc mainporcelain
-git-get-tar-commit-id ancillaryinterrogators
-git-grep mainporcelain
-git-gui mainporcelain
-git-hash-object plumbingmanipulators
-git-http-fetch synchelpers
-git-http-push synchelpers
-git-imap-send foreignscminterface
-git-index-pack plumbingmanipulators
-git-init mainporcelain
-git-instaweb ancillaryinterrogators
-gitk mainporcelain
-git-log mainporcelain
-git-lost-found ancillarymanipulators deprecated
-git-ls-files plumbinginterrogators
-git-ls-remote plumbinginterrogators
-git-ls-tree plumbinginterrogators
-git-mailinfo purehelpers
-git-mailsplit purehelpers
-git-merge mainporcelain
-git-merge-base plumbinginterrogators
-git-merge-file plumbingmanipulators
-git-merge-index plumbingmanipulators
-git-merge-one-file purehelpers
-git-mergetool ancillarymanipulators
-git-merge-tree ancillaryinterrogators
-git-mktag plumbingmanipulators
-git-mktree plumbingmanipulators
-git-mv mainporcelain
-git-name-rev plumbinginterrogators
-git-pack-objects plumbingmanipulators
-git-pack-redundant plumbinginterrogators
-git-pack-refs ancillarymanipulators
-git-parse-remote synchelpers
-git-patch-id purehelpers
-git-peek-remote purehelpers deprecated
-git-prune ancillarymanipulators
-git-prune-packed plumbingmanipulators
-git-pull mainporcelain
-git-push mainporcelain
-git-quiltimport foreignscminterface
-git-read-tree plumbingmanipulators
-git-rebase mainporcelain
-git-receive-pack synchelpers
-git-reflog ancillarymanipulators
-git-relink ancillarymanipulators
-git-remote ancillarymanipulators
-git-repack ancillarymanipulators
-git-request-pull foreignscminterface
-git-rerere ancillaryinterrogators
-git-reset mainporcelain
-git-revert mainporcelain
-git-rev-list plumbinginterrogators
-git-rev-parse ancillaryinterrogators
-git-rm mainporcelain
-git-runstatus ancillaryinterrogators
-git-send-email foreignscminterface
-git-send-pack synchingrepositories
-git-shell synchelpers
-git-shortlog mainporcelain
-git-show mainporcelain
-git-show-branch ancillaryinterrogators
-git-show-index plumbinginterrogators
-git-show-ref plumbinginterrogators
-git-sh-setup purehelpers
-git-stash mainporcelain
-git-status mainporcelain
-git-stripspace purehelpers
-git-submodule mainporcelain
-git-svn foreignscminterface
-git-symbolic-ref plumbingmanipulators
-git-tag mainporcelain
-git-tar-tree plumbinginterrogators deprecated
-git-unpack-file plumbinginterrogators
-git-unpack-objects plumbingmanipulators
-git-update-index plumbingmanipulators
-git-update-ref plumbingmanipulators
-git-update-server-info synchingrepositories
-git-upload-archive synchelpers
-git-upload-pack synchelpers
-git-var plumbinginterrogators
-git-verify-pack plumbinginterrogators
-git-verify-tag ancillaryinterrogators
-git-whatchanged ancillaryinterrogators
-git-write-tree plumbingmanipulators
diff --git a/Makefile b/Makefile
index c35c870..d5d2c7c 100644
--- a/Makefile
+++ b/Makefile
@@ -796,7 +796,7 @@ git-merge-subtree$X: git-merge-recursive$X
$(BUILT_INS): git$X
$(QUIET_BUILT_IN)$(RM) $@ && ln git$X $@
-common-cmds.h: ./generate-cmdlist.sh
+common-cmds.h: ./generate-cmdlist.sh command-list.txt
common-cmds.h: $(wildcard Documentation/git-*.txt)
$(QUIET_GEN)./generate-cmdlist.sh > $@+ && mv $@+ $@
@@ -1138,7 +1138,7 @@ check-docs::
esac ; \
test -f "Documentation/$$v.txt" || \
echo "no doc: $$v"; \
- sed -e '1,/^__DATA__/d' Documentation/cmd-list.perl | \
+ sed -e '/^#/d' command-list.txt | \
grep -q "^$$v[ ]" || \
case "$$v" in \
git) ;; \
@@ -1146,9 +1146,9 @@ check-docs::
esac ; \
done; \
( \
- sed -e '1,/^__DATA__/d' \
+ sed -e '/^#/d' \
-e 's/[ ].*//' \
- -e 's/^/listed /' Documentation/cmd-list.perl; \
+ -e 's/^/listed /' command-list.txt; \
ls -1 Documentation/git*txt | \
sed -e 's|Documentation/|documented |' \
-e 's/\.txt//'; \
diff --git a/command-list.txt b/command-list.txt
new file mode 100644
index 0000000..d30e869
--- /dev/null
+++ b/command-list.txt
@@ -0,0 +1,128 @@
+# List of known git commands.
+# command name category [deprecated] [common]
+git-add mainporcelain common
+git-am mainporcelain
+git-annotate ancillaryinterrogators
+git-apply plumbingmanipulators
+git-archimport foreignscminterface
+git-archive mainporcelain
+git-bisect mainporcelain common
+git-blame ancillaryinterrogators
+git-branch mainporcelain common
+git-bundle mainporcelain
+git-cat-file plumbinginterrogators
+git-check-attr purehelpers
+git-checkout mainporcelain common
+git-checkout-index plumbingmanipulators
+git-check-ref-format purehelpers
+git-cherry ancillaryinterrogators
+git-cherry-pick mainporcelain
+git-citool mainporcelain
+git-clean mainporcelain
+git-clone mainporcelain common
+git-commit mainporcelain common
+git-commit-tree plumbingmanipulators
+git-config ancillarymanipulators
+git-count-objects ancillaryinterrogators
+git-cvsexportcommit foreignscminterface
+git-cvsimport foreignscminterface
+git-cvsserver foreignscminterface
+git-daemon synchingrepositories
+git-describe mainporcelain
+git-diff mainporcelain common
+git-diff-files plumbinginterrogators
+git-diff-index plumbinginterrogators
+git-diff-tree plumbinginterrogators
+git-fast-import ancillarymanipulators
+git-fetch mainporcelain common
+git-fetch-pack synchingrepositories
+git-filter-branch ancillarymanipulators
+git-fmt-merge-msg purehelpers
+git-for-each-ref plumbinginterrogators
+git-format-patch mainporcelain
+git-fsck ancillaryinterrogators
+git-gc mainporcelain
+git-get-tar-commit-id ancillaryinterrogators
+git-grep mainporcelain common
+git-gui mainporcelain
+git-hash-object plumbingmanipulators
+git-http-fetch synchelpers
+git-http-push synchelpers
+git-imap-send foreignscminterface
+git-index-pack plumbingmanipulators
+git-init mainporcelain common
+git-instaweb ancillaryinterrogators
+gitk mainporcelain
+git-log mainporcelain common
+git-lost-found ancillarymanipulators deprecated
+git-ls-files plumbinginterrogators
+git-ls-remote plumbinginterrogators
+git-ls-tree plumbinginterrogators
+git-mailinfo purehelpers
+git-mailsplit purehelpers
+git-merge mainporcelain common
+git-merge-base plumbinginterrogators
+git-merge-file plumbingmanipulators
+git-merge-index plumbingmanipulators
+git-merge-one-file purehelpers
+git-mergetool ancillarymanipulators
+git-merge-tree ancillaryinterrogators
+git-mktag plumbingmanipulators
+git-mktree plumbingmanipulators
+git-mv mainporcelain common
+git-name-rev plumbinginterrogators
+git-pack-objects plumbingmanipulators
+git-pack-redundant plumbinginterrogators
+git-pack-refs ancillarymanipulators
+git-parse-remote synchelpers
+git-patch-id purehelpers
+git-peek-remote purehelpers deprecated
+git-prune ancillarymanipulators
+git-prune-packed plumbingmanipulators
+git-pull mainporcelain common
+git-push mainporcelain common
+git-quiltimport foreignscminterface
+git-read-tree plumbingmanipulators
+git-rebase mainporcelain common
+git-receive-pack synchelpers
+git-reflog ancillarymanipulators
+git-relink ancillarymanipulators
+git-remote ancillarymanipulators
+git-repack ancillarymanipulators
+git-request-pull foreignscminterface
+git-rerere ancillaryinterrogators
+git-reset mainporcelain common
+git-revert mainporcelain
+git-rev-list plumbinginterrogators
+git-rev-parse ancillaryinterrogators
+git-rm mainporcelain common
+git-runstatus ancillaryinterrogators
+git-send-email foreignscminterface
+git-send-pack synchingrepositories
+git-shell synchelpers
+git-shortlog mainporcelain
+git-show mainporcelain common
+git-show-branch ancillaryinterrogators
+git-show-index plumbinginterrogators
+git-show-ref plumbinginterrogators
+git-sh-setup purehelpers
+git-stash mainporcelain
+git-status mainporcelain common
+git-stripspace purehelpers
+git-submodule mainporcelain
+git-svn foreignscminterface
+git-symbolic-ref plumbingmanipulators
+git-tag mainporcelain common
+git-tar-tree plumbinginterrogators deprecated
+git-unpack-file plumbinginterrogators
+git-unpack-objects plumbingmanipulators
+git-update-index plumbingmanipulators
+git-update-ref plumbingmanipulators
+git-update-server-info synchingrepositories
+git-upload-archive synchelpers
+git-upload-pack synchelpers
+git-var plumbinginterrogators
+git-verify-pack plumbinginterrogators
+git-verify-tag ancillaryinterrogators
+git-whatchanged ancillaryinterrogators
+git-write-tree plumbingmanipulators
diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh
index 1ba27ec..a2913c2 100755
--- a/generate-cmdlist.sh
+++ b/generate-cmdlist.sh
@@ -9,29 +9,8 @@ struct cmdname_help
static struct cmdname_help common_cmds[] = {"
-sort <<\EOF |
-add
-bisect
-branch
-checkout
-clone
-commit
-diff
-fetch
-grep
-init
-log
-merge
-mv
-pull
-push
-rebase
-reset
-rm
-show
-status
-tag
-EOF
+sed -n -e 's/^git-\([^ ]*\)[ ].* common.*/\1/p' command-list.txt |
+sort |
while read cmd
do
sed -n '
--
1.5.3.6.2090.g4ece0
^ permalink raw reply related
* [PATCH 1/2] Resurrect peek-remote
From: Junio C Hamano @ 2007-12-02 7:45 UTC (permalink / raw)
To: git
8951d7c1f1ae38f34617b6c2490bf65e73e371f7 (Build in ls-remote) made
peek-remote as a synonym to ls-remote by enhancing the latter, but
at the same time actually _removed_ it, before we officially gave
removal notice. This was bad.
Resurrect it for v1.5.4.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Makefile | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/Makefile b/Makefile
index a7e44a3..c35c870 100644
--- a/Makefile
+++ b/Makefile
@@ -259,7 +259,7 @@ EXTRA_PROGRAMS =
BUILT_INS = \
git-format-patch$X git-show$X git-whatchanged$X git-cherry$X \
git-get-tar-commit-id$X git-init$X git-repo-config$X \
- git-fsck-objects$X git-cherry-pick$X \
+ git-fsck-objects$X git-cherry-pick$X git-peek-remote$X \
$(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))
# what 'all' will build and 'install' will install, in gitexecdir
--
1.5.3.6.2090.g4ece0
^ permalink raw reply related
* problems with importing from cvs archive
From: Ed S. Peschko @ 2007-12-02 6:46 UTC (permalink / raw)
To: git
All,
I'm trying to use git-cvsimport to import from a CVS archive, using:
git-cvsimport -d $CVSROOT
and am getting the following error:
fatal: refs/heads/origin: not a valid SHA1
fatal: master: not a valid SHA1
warning: You appear to be on a branch yet to be born
warning: Forcing checkout of HEAD
fatal: just how do you expect me to merge 0 trees?
checkout failed: 256
Is git-cvsimport meant to be universal - ie: work on any given CVS worktree - or do
you need to prep the CVS worktree in any way in order for it to be used?
Or is this just a plain vanilla bug?
Thanks,
Ed
^ permalink raw reply
* [PATCH 3/3] git-shell: accept "git foo" form
From: Junio C Hamano @ 2007-12-02 7:03 UTC (permalink / raw)
To: git
In-Reply-To: <1196579005-5662-2-git-send-email-gitster@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
shell.c | 26 +++++++++++++++-----------
1 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/shell.c b/shell.c
index 9826109..729797c 100644
--- a/shell.c
+++ b/shell.c
@@ -19,17 +19,13 @@ static int do_generic_cmd(const char *me, char *arg)
return execv_git_cmd(my_argv);
}
-static int do_cvs_cmd(const char *me, char *arg)
+static int do_cvs_cmd(void)
{
const char *cvsserver_argv[3] = {
"cvsserver", "server", NULL
};
- if (!arg || strcmp(arg, "server"))
- die("git-cvsserver only handles server: %s", arg);
-
setup_path(NULL);
-
return execv_git_cmd(cvsserver_argv);
}
@@ -40,7 +36,6 @@ static struct commands {
} cmd_list[] = {
{ "git-receive-pack", do_generic_cmd },
{ "git-upload-pack", do_generic_cmd },
- { "cvs", do_cvs_cmd },
{ NULL },
};
@@ -49,15 +44,24 @@ int main(int argc, char **argv)
char *prog;
struct commands *cmd;
+ /*
+ * Special hack to pretend to be a CVS server
+ */
if (argc == 2 && !strcmp(argv[1], "cvs server"))
- argv--;
- /* We want to see "-c cmd args", and nothing else */
- else if (argc != 3 || strcmp(argv[1], "-c"))
+ exit(do_cvs_cmd());
+
+ /*
+ * We do not accept anything but "-c" followed by "cmd arg",
+ * where "cmd" is a very limited subset of git commands.
+ */
+ if (argc != 3 || strcmp(argv[1], "-c"))
die("What do you think I am? A shell?");
prog = argv[2];
- argv += 2;
- argc -= 2;
+ if (!strncmp(prog, "git", 3) && isspace(prog[3]))
+ /* Accept "git foo" as if the caller said "git-foo". */
+ prog[3] = '-';
+
for (cmd = cmd_list ; cmd->name ; cmd++) {
int len = strlen(cmd->name);
char *arg;
--
1.5.3.6.2090.g4ece0
^ permalink raw reply related
* [PATCH 2/3] Avoid double exec() in execv_git_cmd()
From: Junio C Hamano @ 2007-12-02 7:03 UTC (permalink / raw)
To: git
In-Reply-To: <1196579005-5662-1-git-send-email-gitster@pobox.com>
This avoids double exec() when execv_git_cmd() is used to spawn an
external git command.
For this, execv_git_cmd() needs to be able to tell what's built-in.
This is done by introducing a new function git_builtin_command() that
checks the list of built-in commands and returns a pointer to the
cmd_struct if found. The same function is used from the git potty.
This unfortunately pulls all built-in functions to libgit.a, so any
external command that happens to link with exec_cmd.o will need to pull
them in. I am not sure if that is worth it.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Makefile | 7 +-
exec_cmd.c | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
exec_cmd.h | 8 ++
git.c | 155 +-------------------------------------------
4 files changed, 210 insertions(+), 168 deletions(-)
diff --git a/Makefile b/Makefile
index a7e44a3..6907954 100644
--- a/Makefile
+++ b/Makefile
@@ -893,7 +893,8 @@ git.o git.spec \
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
exec_cmd.o: exec_cmd.c GIT-CFLAGS
- $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' $<
+ $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) \
+ -DGIT_VERSION='"$(GIT_VERSION)"' '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' $<
builtin-init-db.o: builtin-init-db.c GIT-CFLAGS
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
@@ -923,8 +924,8 @@ $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
$(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
builtin-revert.o builtin-runstatus.o wt-status.o: wt-status.h
-$(LIB_FILE): $(LIB_OBJS)
- $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
+$(LIB_FILE): $(LIB_OBJS) $(BUILTIN_OBJS)
+ $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS) $(BUILTIN_OBJS)
XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
xdiff/xmerge.o
diff --git a/exec_cmd.c b/exec_cmd.c
index 10b2908..db61540 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -1,3 +1,4 @@
+#include "builtin.h"
#include "cache.h"
#include "exec_cmd.h"
#include "quote.h"
@@ -63,27 +64,206 @@ void setup_path(const char *cmd_path)
strbuf_release(&new_path);
}
+#define RUN_SETUP (1<<0)
+#define USE_PAGER (1<<1)
+/*
+ * require working tree to be present -- anything uses this needs
+ * RUN_SETUP for reading from the configuration file.
+ */
+#define NEED_WORK_TREE (1<<2)
+
+const char git_version_string[] = GIT_VERSION;
+const char git_usage_string[] =
+ "git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
+
+int run_builtin_command(struct cmd_struct *p, int argc, const char **argv)
+{
+ int status;
+ struct stat st;
+ const char *prefix;
+
+ prefix = NULL;
+ if (p->option & RUN_SETUP)
+ prefix = setup_git_directory();
+ if (p->option & USE_PAGER)
+ setup_pager();
+ if (p->option & NEED_WORK_TREE)
+ setup_work_tree();
+
+ trace_argv_printf(argv, argc, "trace: built-in: git");
+
+ status = p->fn(argc, argv, prefix);
+ if (status)
+ return status & 0xff;
+
+ /* Somebody closed stdout? */
+ if (fstat(fileno(stdout), &st))
+ return 0;
+ /* Ignore write errors for pipes and sockets.. */
+ if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
+ return 0;
+
+ /* Check for ENOSPC and EIO errors.. */
+ if (fflush(stdout))
+ die("write failure on standard output: %s", strerror(errno));
+ if (ferror(stdout))
+ die("unknown write failure on standard output");
+ if (fclose(stdout))
+ die("close failed on standard output: %s", strerror(errno));
+ return 0;
+}
+
+static struct cmd_struct builtin_command[] = {
+ { "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
+ { "annotate", cmd_annotate, RUN_SETUP },
+ { "apply", cmd_apply },
+ { "archive", cmd_archive },
+ { "blame", cmd_blame, RUN_SETUP },
+ { "branch", cmd_branch, RUN_SETUP },
+ { "bundle", cmd_bundle },
+ { "cat-file", cmd_cat_file, RUN_SETUP },
+ { "check-attr", cmd_check_attr, RUN_SETUP | NEED_WORK_TREE },
+ { "check-ref-format", cmd_check_ref_format },
+ { "checkout-index", cmd_checkout_index, RUN_SETUP | NEED_WORK_TREE},
+ { "cherry", cmd_cherry, RUN_SETUP },
+ { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
+ { "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE },
+ { "commit-tree", cmd_commit_tree, RUN_SETUP },
+ { "config", cmd_config },
+ { "count-objects", cmd_count_objects, RUN_SETUP },
+ { "describe", cmd_describe, RUN_SETUP },
+ { "diff", cmd_diff },
+ { "diff-files", cmd_diff_files },
+ { "diff-index", cmd_diff_index, RUN_SETUP },
+ { "diff-tree", cmd_diff_tree, RUN_SETUP },
+ { "fetch", cmd_fetch, RUN_SETUP },
+ { "fetch--tool", cmd_fetch__tool, RUN_SETUP },
+ { "fetch-pack", cmd_fetch_pack, RUN_SETUP },
+ { "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
+ { "for-each-ref", cmd_for_each_ref, RUN_SETUP },
+ { "format-patch", cmd_format_patch, RUN_SETUP },
+ { "fsck", cmd_fsck, RUN_SETUP },
+ { "fsck-objects", cmd_fsck, RUN_SETUP },
+ { "gc", cmd_gc, RUN_SETUP },
+ { "get-tar-commit-id", cmd_get_tar_commit_id },
+ { "grep", cmd_grep, RUN_SETUP | USE_PAGER },
+ { "help", cmd_help },
+#ifndef NO_CURL
+ { "http-fetch", cmd_http_fetch, RUN_SETUP },
+#endif
+ { "init", cmd_init_db },
+ { "init-db", cmd_init_db },
+ { "log", cmd_log, RUN_SETUP | USE_PAGER },
+ { "ls-files", cmd_ls_files, RUN_SETUP },
+ { "ls-remote", cmd_ls_remote },
+ { "ls-tree", cmd_ls_tree, RUN_SETUP },
+ { "mailinfo", cmd_mailinfo },
+ { "mailsplit", cmd_mailsplit },
+ { "merge-base", cmd_merge_base, RUN_SETUP },
+ { "merge-file", cmd_merge_file },
+ { "merge-ours", cmd_merge_ours, RUN_SETUP },
+ { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
+ { "name-rev", cmd_name_rev, RUN_SETUP },
+ { "pack-objects", cmd_pack_objects, RUN_SETUP },
+ { "pack-refs", cmd_pack_refs, RUN_SETUP },
+ { "peek-remote", cmd_ls_remote },
+ { "pickaxe", cmd_blame, RUN_SETUP },
+ { "prune", cmd_prune, RUN_SETUP },
+ { "prune-packed", cmd_prune_packed, RUN_SETUP },
+ { "push", cmd_push, RUN_SETUP },
+ { "read-tree", cmd_read_tree, RUN_SETUP },
+ { "reflog", cmd_reflog, RUN_SETUP },
+ { "repo-config", cmd_config },
+ { "rerere", cmd_rerere, RUN_SETUP },
+ { "reset", cmd_reset, RUN_SETUP },
+ { "rev-list", cmd_rev_list, RUN_SETUP },
+ { "rev-parse", cmd_rev_parse },
+ { "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
+ { "rm", cmd_rm, RUN_SETUP },
+ { "runstatus", cmd_runstatus, RUN_SETUP | NEED_WORK_TREE },
+ { "send-pack", cmd_send_pack, RUN_SETUP },
+ { "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER },
+ { "show", cmd_show, RUN_SETUP | USE_PAGER },
+ { "show-branch", cmd_show_branch, RUN_SETUP },
+ { "show-ref", cmd_show_ref, RUN_SETUP },
+ { "stripspace", cmd_stripspace },
+ { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
+ { "tag", cmd_tag, RUN_SETUP },
+ { "tar-tree", cmd_tar_tree },
+ { "unpack-objects", cmd_unpack_objects, RUN_SETUP },
+ { "update-index", cmd_update_index, RUN_SETUP },
+ { "update-ref", cmd_update_ref, RUN_SETUP },
+ { "upload-archive", cmd_upload_archive },
+ { "verify-pack", cmd_verify_pack },
+ { "verify-tag", cmd_verify_tag, RUN_SETUP },
+ { "version", cmd_version },
+ { "whatchanged", cmd_whatchanged, RUN_SETUP | USE_PAGER },
+ { "write-tree", cmd_write_tree, RUN_SETUP },
+};
+
+struct cmd_struct *git_builtin_command(const char *name)
+{
+ unsigned int hi, lo;
+ lo = 0;
+ hi = ARRAY_SIZE(builtin_command);
+ do {
+ unsigned mi = (lo + hi) / 2;
+ int cmp = strcmp(builtin_command[mi].cmd, name);
+ if (!cmp)
+ return &builtin_command[mi];
+ if (cmp > 0)
+ hi = mi;
+ else
+ lo = mi + 1;
+ } while (lo < hi);
+ return NULL;
+}
+
int execv_git_cmd(const char **argv)
{
- int argc;
- const char **nargv;
+ /*
+ * We exec "git foo" for builtin commands, but exec "git-foo"
+ * if "foo" is not a built-in, to avoid double exec overhead.
+ */
+ if (!git_builtin_command(argv[0])) {
+ struct strbuf cmd;
+ const char *save;
+
+ strbuf_init(&cmd, 0);
+ strbuf_addf(&cmd, "git-%s", argv[0]);
- for (argc = 0; argv[argc]; argc++)
- ; /* just counting */
- nargv = xmalloc(sizeof(*nargv) * (argc + 2));
+ save = argv[0];
+ argv[0] = cmd.buf;
+ trace_argv_printf(argv, -1, "trace: exec:");
- nargv[0] = "git";
- for (argc = 0; argv[argc]; argc++)
- nargv[argc + 1] = argv[argc];
- nargv[argc + 1] = NULL;
- trace_argv_printf(nargv, -1, "trace: exec:");
+ execvp(argv[0], (char **)argv);
- /* execvp() can only ever return if it fails */
- execvp("git", (char **)nargv);
+ trace_printf("trace: exec failed: %s\n", strerror(errno));
+ strbuf_release(&cmd);
+ argv[0] = save;
+ }
+ else {
+ int argc;
+ const char **nargv;
- trace_printf("trace: exec failed: %s\n", strerror(errno));
+ for (argc = 0; argv[argc]; argc++)
+ ; /* just counting */
+ nargv = xmalloc(sizeof(*nargv) * (argc + 2));
- free(nargv);
+ nargv[0] = "git";
+ for (argc = 0; argv[argc]; argc++)
+ nargv[argc + 1] = argv[argc];
+ nargv[argc + 1] = NULL;
+
+ trace_argv_printf(nargv, -1, "trace: exec:");
+
+ /* execvp() can only ever return if it fails */
+ execvp("git", (char **)nargv);
+
+ trace_printf("trace: exec failed: %s\n", strerror(errno));
+
+ free(nargv);
+ }
return -1;
}
diff --git a/exec_cmd.h b/exec_cmd.h
index a892355..184bc1d 100644
--- a/exec_cmd.h
+++ b/exec_cmd.h
@@ -7,5 +7,13 @@ extern void setup_path(const char *);
extern int execv_git_cmd(const char **argv); /* NULL terminated */
extern int execl_git_cmd(const char *cmd, ...);
+struct cmd_struct {
+ const char *cmd;
+ int (*fn)(int, const char **, const char *);
+ int option;
+};
+
+extern struct cmd_struct *git_builtin_command(const char *);
+extern int run_builtin_command(struct cmd_struct *p, int argc, const char **argv);
#endif /* GIT_EXEC_CMD_H */
diff --git a/git.c b/git.c
index d690426..9d86f5c 100644
--- a/git.c
+++ b/git.c
@@ -3,9 +3,6 @@
#include "cache.h"
#include "quote.h"
-const char git_usage_string[] =
- "git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
-
static int handle_options(const char*** argv, int* argc, int* envchanged)
{
int handled = 0;
@@ -222,151 +219,10 @@ static int handle_alias(int *argcp, const char ***argv)
return ret;
}
-const char git_version_string[] = GIT_VERSION;
-
-#define RUN_SETUP (1<<0)
-#define USE_PAGER (1<<1)
-/*
- * require working tree to be present -- anything uses this needs
- * RUN_SETUP for reading from the configuration file.
- */
-#define NEED_WORK_TREE (1<<2)
-
-struct cmd_struct {
- const char *cmd;
- int (*fn)(int, const char **, const char *);
- int option;
-};
-
-static int run_command(struct cmd_struct *p, int argc, const char **argv)
-{
- int status;
- struct stat st;
- const char *prefix;
-
- prefix = NULL;
- if (p->option & RUN_SETUP)
- prefix = setup_git_directory();
- if (p->option & USE_PAGER)
- setup_pager();
- if (p->option & NEED_WORK_TREE)
- setup_work_tree();
-
- trace_argv_printf(argv, argc, "trace: built-in: git");
-
- status = p->fn(argc, argv, prefix);
- if (status)
- return status & 0xff;
-
- /* Somebody closed stdout? */
- if (fstat(fileno(stdout), &st))
- return 0;
- /* Ignore write errors for pipes and sockets.. */
- if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
- return 0;
-
- /* Check for ENOSPC and EIO errors.. */
- if (fflush(stdout))
- die("write failure on standard output: %s", strerror(errno));
- if (ferror(stdout))
- die("unknown write failure on standard output");
- if (fclose(stdout))
- die("close failed on standard output: %s", strerror(errno));
- return 0;
-}
-
static void handle_internal_command(int argc, const char **argv)
{
const char *cmd = argv[0];
- static struct cmd_struct commands[] = {
- { "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
- { "annotate", cmd_annotate, RUN_SETUP },
- { "apply", cmd_apply },
- { "archive", cmd_archive },
- { "blame", cmd_blame, RUN_SETUP },
- { "branch", cmd_branch, RUN_SETUP },
- { "bundle", cmd_bundle },
- { "cat-file", cmd_cat_file, RUN_SETUP },
- { "checkout-index", cmd_checkout_index,
- RUN_SETUP | NEED_WORK_TREE},
- { "check-ref-format", cmd_check_ref_format },
- { "check-attr", cmd_check_attr, RUN_SETUP | NEED_WORK_TREE },
- { "cherry", cmd_cherry, RUN_SETUP },
- { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
- { "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE },
- { "commit-tree", cmd_commit_tree, RUN_SETUP },
- { "config", cmd_config },
- { "count-objects", cmd_count_objects, RUN_SETUP },
- { "describe", cmd_describe, RUN_SETUP },
- { "diff", cmd_diff },
- { "diff-files", cmd_diff_files },
- { "diff-index", cmd_diff_index, RUN_SETUP },
- { "diff-tree", cmd_diff_tree, RUN_SETUP },
- { "fetch", cmd_fetch, RUN_SETUP },
- { "fetch-pack", cmd_fetch_pack, RUN_SETUP },
- { "fetch--tool", cmd_fetch__tool, RUN_SETUP },
- { "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
- { "for-each-ref", cmd_for_each_ref, RUN_SETUP },
- { "format-patch", cmd_format_patch, RUN_SETUP },
- { "fsck", cmd_fsck, RUN_SETUP },
- { "fsck-objects", cmd_fsck, RUN_SETUP },
- { "gc", cmd_gc, RUN_SETUP },
- { "get-tar-commit-id", cmd_get_tar_commit_id },
- { "grep", cmd_grep, RUN_SETUP | USE_PAGER },
- { "help", cmd_help },
-#ifndef NO_CURL
- { "http-fetch", cmd_http_fetch, RUN_SETUP },
-#endif
- { "init", cmd_init_db },
- { "init-db", cmd_init_db },
- { "log", cmd_log, RUN_SETUP | USE_PAGER },
- { "ls-files", cmd_ls_files, RUN_SETUP },
- { "ls-tree", cmd_ls_tree, RUN_SETUP },
- { "ls-remote", cmd_ls_remote },
- { "mailinfo", cmd_mailinfo },
- { "mailsplit", cmd_mailsplit },
- { "merge-base", cmd_merge_base, RUN_SETUP },
- { "merge-file", cmd_merge_file },
- { "merge-ours", cmd_merge_ours, RUN_SETUP },
- { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
- { "name-rev", cmd_name_rev, RUN_SETUP },
- { "pack-objects", cmd_pack_objects, RUN_SETUP },
- { "peek-remote", cmd_ls_remote },
- { "pickaxe", cmd_blame, RUN_SETUP },
- { "prune", cmd_prune, RUN_SETUP },
- { "prune-packed", cmd_prune_packed, RUN_SETUP },
- { "push", cmd_push, RUN_SETUP },
- { "read-tree", cmd_read_tree, RUN_SETUP },
- { "reflog", cmd_reflog, RUN_SETUP },
- { "repo-config", cmd_config },
- { "rerere", cmd_rerere, RUN_SETUP },
- { "reset", cmd_reset, RUN_SETUP },
- { "rev-list", cmd_rev_list, RUN_SETUP },
- { "rev-parse", cmd_rev_parse },
- { "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
- { "rm", cmd_rm, RUN_SETUP },
- { "runstatus", cmd_runstatus, RUN_SETUP | NEED_WORK_TREE },
- { "send-pack", cmd_send_pack, RUN_SETUP },
- { "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER },
- { "show-branch", cmd_show_branch, RUN_SETUP },
- { "show", cmd_show, RUN_SETUP | USE_PAGER },
- { "stripspace", cmd_stripspace },
- { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
- { "tag", cmd_tag, RUN_SETUP },
- { "tar-tree", cmd_tar_tree },
- { "unpack-objects", cmd_unpack_objects, RUN_SETUP },
- { "update-index", cmd_update_index, RUN_SETUP },
- { "update-ref", cmd_update_ref, RUN_SETUP },
- { "upload-archive", cmd_upload_archive },
- { "verify-tag", cmd_verify_tag, RUN_SETUP },
- { "version", cmd_version },
- { "whatchanged", cmd_whatchanged, RUN_SETUP | USE_PAGER },
- { "write-tree", cmd_write_tree, RUN_SETUP },
- { "verify-pack", cmd_verify_pack },
- { "show-ref", cmd_show_ref, RUN_SETUP },
- { "pack-refs", cmd_pack_refs, RUN_SETUP },
- };
- int i;
+ struct cmd_struct *builtin;
/* Turn "git cmd --help" into "git help cmd" */
if (argc > 1 && !strcmp(argv[1], "--help")) {
@@ -374,12 +230,9 @@ static void handle_internal_command(int argc, const char **argv)
argv[0] = cmd = "help";
}
- for (i = 0; i < ARRAY_SIZE(commands); i++) {
- struct cmd_struct *p = commands+i;
- if (strcmp(p->cmd, cmd))
- continue;
- exit(run_command(p, argc, argv));
- }
+ builtin = git_builtin_command(cmd);
+ if (builtin)
+ exit(run_builtin_command(builtin, argc, argv));
}
static void execv_dashed_external(const char **argv)
--
1.5.3.6.2090.g4ece0
^ permalink raw reply related
* [PATCH 1/3] Prepare execv_git_cmd() for removal of builtins from the filesystem
From: Junio C Hamano @ 2007-12-02 7:03 UTC (permalink / raw)
To: git
Currently, execv_git_cmd() always try running the dashed form, which
means we cannot easily remove the git-foo hardlinks for built-in
commands. This updates the function to always exec "git foo" form, and
makes sure "git" potty does not infinitely recurse to itself.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
exec_cmd.c | 31 ++++++++++++-------------------
git.c | 32 +++++++++++++++++++++++++++++++-
2 files changed, 43 insertions(+), 20 deletions(-)
diff --git a/exec_cmd.c b/exec_cmd.c
index 2d0a758..10b2908 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -65,32 +65,25 @@ void setup_path(const char *cmd_path)
int execv_git_cmd(const char **argv)
{
- struct strbuf cmd;
- const char *tmp;
-
- strbuf_init(&cmd, 0);
- strbuf_addf(&cmd, "git-%s", argv[0]);
+ int argc;
+ const char **nargv;
- /*
- * argv[0] must be the git command, but the argv array
- * belongs to the caller, and may be reused in
- * subsequent loop iterations. Save argv[0] and
- * restore it on error.
- */
- tmp = argv[0];
- argv[0] = cmd.buf;
+ for (argc = 0; argv[argc]; argc++)
+ ; /* just counting */
+ nargv = xmalloc(sizeof(*nargv) * (argc + 2));
- trace_argv_printf(argv, -1, "trace: exec:");
+ nargv[0] = "git";
+ for (argc = 0; argv[argc]; argc++)
+ nargv[argc + 1] = argv[argc];
+ nargv[argc + 1] = NULL;
+ trace_argv_printf(nargv, -1, "trace: exec:");
/* execvp() can only ever return if it fails */
- execvp(cmd.buf, (char **)argv);
+ execvp("git", (char **)nargv);
trace_printf("trace: exec failed: %s\n", strerror(errno));
- argv[0] = tmp;
-
- strbuf_release(&cmd);
-
+ free(nargv);
return -1;
}
diff --git a/git.c b/git.c
index 01bbbc7..d690426 100644
--- a/git.c
+++ b/git.c
@@ -382,6 +382,36 @@ static void handle_internal_command(int argc, const char **argv)
}
}
+static void execv_dashed_external(const char **argv)
+{
+ struct strbuf cmd;
+ const char *tmp;
+
+ strbuf_init(&cmd, 0);
+ strbuf_addf(&cmd, "git-%s", argv[0]);
+
+ /*
+ * argv[0] must be the git command, but the argv array
+ * belongs to the caller, and may be reused in
+ * subsequent loop iterations. Save argv[0] and
+ * restore it on error.
+ */
+ tmp = argv[0];
+ argv[0] = cmd.buf;
+
+ trace_argv_printf(argv, -1, "trace: exec:");
+
+ /* execvp() can only ever return if it fails */
+ execvp(cmd.buf, (char **)argv);
+
+ trace_printf("trace: exec failed: %s\n", strerror(errno));
+
+ argv[0] = tmp;
+
+ strbuf_release(&cmd);
+}
+
+
int main(int argc, const char **argv)
{
const char *cmd = argv[0] ? argv[0] : "git-help";
@@ -445,7 +475,7 @@ int main(int argc, const char **argv)
handle_internal_command(argc, argv);
/* .. then try the external ones */
- execv_git_cmd(argv);
+ execv_dashed_external(argv);
/* It could be an alias -- this works around the insanity
* of overriding "git log" with "git show" by having
--
1.5.3.6.2090.g4ece0
^ permalink raw reply related
* [PATCH resend] git-commit: clean up die messages
From: Jeff King @ 2007-12-02 6:07 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Kristian Høgsberg
These are three types of cleanups here:
1. remove newline from die message (die/report adds it
already)
2. typo: s/merger/merge/
3. the old "* no commit message? aborting commit." is now
prepended with "fatal: ", making the asterisk look a
little funny. Let's just remove it.
Signed-off-by: Jeff King <peff@peff.net>
---
[sorry for the resend, I totally munged Kristian's address in the first
one].
I actually noticed number 3, and while fixing it, saw the others. The
wording in number 3 is a bit awkward, IMHO. I wonder if it might be
better as something like:
fatal: aborting commit with empty message
builtin-commit.c | 19 +++++++++----------
1 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/builtin-commit.c b/builtin-commit.c
index 0f1ae17..f6e8e44 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -336,7 +336,7 @@ static int prepare_log_message(const char *index_file, const char *prefix)
fp = fopen(git_path(commit_editmsg), "w");
if (fp == NULL)
- die("could not open %s\n", git_path(commit_editmsg));
+ die("could not open %s", git_path(commit_editmsg));
stripspace(&sb, 0);
@@ -362,8 +362,7 @@ static int prepare_log_message(const char *index_file, const char *prefix)
}
if (fwrite(sb.buf, 1, sb.len, fp) < sb.len)
- die("could not write commit template: %s\n",
- strerror(errno));
+ die("could not write commit template: %s", strerror(errno));
strbuf_release(&sb);
@@ -470,13 +469,13 @@ static void determine_author_info(struct strbuf *sb)
a = strstr(use_message_buffer, "\nauthor ");
if (!a)
- die("invalid commit: %s\n", use_message);
+ die("invalid commit: %s", use_message);
lb = strstr(a + 8, " <");
rb = strstr(a + 8, "> ");
eol = strchr(a + 8, '\n');
if (!lb || !rb || !eol)
- die("invalid commit: %s\n", use_message);
+ die("invalid commit: %s", use_message);
name = xstrndup(a + 8, lb - (a + 8));
email = xstrndup(lb + 2, rb - (lb + 2));
@@ -488,7 +487,7 @@ static void determine_author_info(struct strbuf *sb)
const char *rb = strchr(force_author, '>');
if (!lb || !rb)
- die("malformed --author parameter\n");
+ die("malformed --author parameter");
name = xstrndup(force_author, lb - force_author);
email = xstrndup(lb + 2, rb - (lb + 2));
}
@@ -518,7 +517,7 @@ static int parse_and_validate_options(int argc, const char *argv[])
if (amend && initial_commit)
die("You have nothing to amend.");
if (amend && in_merge)
- die("You are in the middle of a merger -- cannot amend.");
+ die("You are in the middle of a merge -- cannot amend.");
if (use_message)
f++;
@@ -641,7 +640,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
commit = lookup_commit(sha1);
if (!commit)
- die("couldn't look up newly created commit\n");
+ die("couldn't look up newly created commit");
if (!commit || parse_commit(commit))
die("could not parse newly created commit");
@@ -777,7 +776,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
launch_editor(git_path(commit_editmsg), &sb, env);
} else if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {
rollback_index_files();
- die("could not read commit message\n");
+ die("could not read commit message");
}
if (run_hook(index_file, "commit-msg", git_path(commit_editmsg))) {
rollback_index_files();
@@ -792,7 +791,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
stripspace(&sb, 1);
if (sb.len < header_len || message_is_empty(&sb, header_len)) {
rollback_index_files();
- die("* no commit message? aborting commit.");
+ die("no commit message? aborting commit.");
}
strbuf_addch(&sb, '\0');
if (is_encoding_utf8(git_commit_encoding) && !is_utf8(sb.buf))
--
1.5.3.6.2092.gf4c21-dirty
^ permalink raw reply related
* [PATCH] git-commit: clean up die messages
From: Jeff King @ 2007-12-02 6:05 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, krh
These are three types of cleanups here:
1. remove newline from die message (die/report adds it
already)
2. typo: s/merger/merge/
3. the old "* no commit message? aborting commit." is now
prepended with "fatal: ", making the asterisk look a
little funny. Let's just remove it.
Signed-off-by: Jeff King <peff@peff.net>
---
I actually noticed number 3, and while fixing it, saw the others. The
wording in number 3 is a bit awkward, IMHO. I wonder if it might be
better as something like:
fatal: aborting commit with empty message
builtin-commit.c | 19 +++++++++----------
1 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/builtin-commit.c b/builtin-commit.c
index 0f1ae17..f6e8e44 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -336,7 +336,7 @@ static int prepare_log_message(const char *index_file, const char *prefix)
fp = fopen(git_path(commit_editmsg), "w");
if (fp == NULL)
- die("could not open %s\n", git_path(commit_editmsg));
+ die("could not open %s", git_path(commit_editmsg));
stripspace(&sb, 0);
@@ -362,8 +362,7 @@ static int prepare_log_message(const char *index_file, const char *prefix)
}
if (fwrite(sb.buf, 1, sb.len, fp) < sb.len)
- die("could not write commit template: %s\n",
- strerror(errno));
+ die("could not write commit template: %s", strerror(errno));
strbuf_release(&sb);
@@ -470,13 +469,13 @@ static void determine_author_info(struct strbuf *sb)
a = strstr(use_message_buffer, "\nauthor ");
if (!a)
- die("invalid commit: %s\n", use_message);
+ die("invalid commit: %s", use_message);
lb = strstr(a + 8, " <");
rb = strstr(a + 8, "> ");
eol = strchr(a + 8, '\n');
if (!lb || !rb || !eol)
- die("invalid commit: %s\n", use_message);
+ die("invalid commit: %s", use_message);
name = xstrndup(a + 8, lb - (a + 8));
email = xstrndup(lb + 2, rb - (lb + 2));
@@ -488,7 +487,7 @@ static void determine_author_info(struct strbuf *sb)
const char *rb = strchr(force_author, '>');
if (!lb || !rb)
- die("malformed --author parameter\n");
+ die("malformed --author parameter");
name = xstrndup(force_author, lb - force_author);
email = xstrndup(lb + 2, rb - (lb + 2));
}
@@ -518,7 +517,7 @@ static int parse_and_validate_options(int argc, const char *argv[])
if (amend && initial_commit)
die("You have nothing to amend.");
if (amend && in_merge)
- die("You are in the middle of a merger -- cannot amend.");
+ die("You are in the middle of a merge -- cannot amend.");
if (use_message)
f++;
@@ -641,7 +640,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
commit = lookup_commit(sha1);
if (!commit)
- die("couldn't look up newly created commit\n");
+ die("couldn't look up newly created commit");
if (!commit || parse_commit(commit))
die("could not parse newly created commit");
@@ -777,7 +776,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
launch_editor(git_path(commit_editmsg), &sb, env);
} else if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {
rollback_index_files();
- die("could not read commit message\n");
+ die("could not read commit message");
}
if (run_hook(index_file, "commit-msg", git_path(commit_editmsg))) {
rollback_index_files();
@@ -792,7 +791,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
stripspace(&sb, 1);
if (sb.len < header_len || message_is_empty(&sb, header_len)) {
rollback_index_files();
- die("* no commit message? aborting commit.");
+ die("no commit message? aborting commit.");
}
strbuf_addch(&sb, '\0');
if (is_encoding_utf8(git_commit_encoding) && !is_utf8(sb.buf))
--
1.5.3.6.2092.gf4c21-dirty
^ permalink raw reply related
* Re: [PATCH] Move all dashed form git commands to libexecdir
From: Nguyen Thai Ngoc Duy @ 2007-12-02 5:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: Linus Torvalds, Jeff King, Santi B?jar, Steffen Prohaska,
Johannes Schindelin, Jan Hudec, git
In-Reply-To: <7vve7i43ec.fsf@gitster.siamese.dyndns.org>
On Dec 2, 2007 2:32 AM, Junio C Hamano <gitster@pobox.com> wrote:
> "Nguyen Thai Ngoc Duy" <pclouds@gmail.com> writes:
>
> > On Nov 30, 2007 10:50 PM, Linus Torvalds <torvalds@linux-foundation.org> wrote:
> >
> >> Well, different people will want different viewers *anyway* (ie some will
> >> prefer qgit etc), so how about making "git view" be something that
> >> literally acts as a built-in alias that just defaults to running gitk (if
> >> for no other reason than the fact that gitk is the one that ships with
> >> git, and simply has most users).
> >
> > We already have "git show", now we gonna get "git view", git trainers
> > may have hard time explaining this one shows you a particular object
> > while the other one shows you history. How about "git lshistory" (from
> > clearcase land) or git show --history?
>
> Heh, we have "bisect visualize". How about "git visualize"?
>
"git visualize"++
--
Duy
^ permalink raw reply
* Re: [PATCH 6/6] builtin-commit: Add newline when showing which commit was created
From: Jeff King @ 2007-12-02 5:40 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git, krh, gitster
In-Reply-To: <Pine.LNX.4.64.0712012238510.27959@racer.site>
On Sat, Dec 01, 2007 at 10:41:47PM +0000, Johannes Schindelin wrote:
> Basically, I ran a test case in which the shell script was different from
> the builtin version, and this was the patch that fixed it for me.
>
> Maybe it should have been
>
> if (log_tree_commit(&rev, commit))
> printf("\n");
>
> at the end of print_summary() instead. Can you try if that fixes it for
> you?
No, it doesn't, unless you meant "if (!log_tree_commit(...". Of course,
I can't get log_tree_commit to return anything but true anyway (either
log_tree_diff shows something, or since we have set always_show_header,
we end up calling show_log).
It would be helpful if you could remember the test case, but perhaps
that is not an option at this point.
-Peff
^ permalink raw reply
* Re: [PATCH 0/3] Call builtin functions directly, was Re: [PATCH] transport.c: call dash-less form of receive-pack and upload-pack on remote
From: Junio C Hamano @ 2007-12-02 5:19 UTC (permalink / raw)
To: Johannes Schindelin
Cc: Eyvind Bernhardsen, Nicolas Pitre, Nguyen Thai Ngoc Duy,
Jan Hudec, git
In-Reply-To: <Pine.LNX.4.64.0712020146240.27959@racer.site>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> Okay, I bit the apple and tried to move the builtins into the library, and
> rename handle_internal_command into execv_git_builtin(), moving it into
> exec-cmd.c.
>
> Big mistake.
I really feel this should not go in. Anything called exec _should_
assure the callers that the new command will start from a clean slate,
and the way to give that assurance is by actually doing exec(), not
introducing "clean-up" functions for random things we can think of (like
cached objects) and risking of forgetting some others. I do not think
the complexity is worth it.
The first step we have decided to take is to move git-foo form out of
users' PATH. This would reduce the cluttered PATH problem, and it means
not all of external commands have to become built-ins on a single flag
day. I also think it has always been a nice touch that we allowed users
to drop their own custom git-foo script to their path and call "git foo"
as if it is part of the official git suite, so spawning commands in
git-foo form needs to be supported via GIT_EXEC_PATH even if everything
eventually becomes built-in.
So I would prefer doing something like this instead for v1.5.5 (see
the top of updated release notes for 1.5.4 for deprecation notice).
* execv_git_cmd() function will exec "git" with the given subcommand
and its arguments;
* The command dispatcher of git potty itself will first try the
built-ins, and then try externals in dash form (which cannot be done
with execv_git_cmd() anymore), and then aliases.
* Just to be nice, we allow git-shell to treat "git foo arg" as if
"git-foo arg" was given, but it continues to use execv_git_cmd(), and
starts from a clean slate.
---
exec_cmd.c | 31 ++++++++++++-------------------
git.c | 32 +++++++++++++++++++++++++++++++-
shell.c | 26 +++++++++++++++-----------
3 files changed, 58 insertions(+), 31 deletions(-)
diff --git a/exec_cmd.c b/exec_cmd.c
index 2d0a758..10b2908 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -65,32 +65,25 @@ void setup_path(const char *cmd_path)
int execv_git_cmd(const char **argv)
{
- struct strbuf cmd;
- const char *tmp;
-
- strbuf_init(&cmd, 0);
- strbuf_addf(&cmd, "git-%s", argv[0]);
+ int argc;
+ const char **nargv;
- /*
- * argv[0] must be the git command, but the argv array
- * belongs to the caller, and may be reused in
- * subsequent loop iterations. Save argv[0] and
- * restore it on error.
- */
- tmp = argv[0];
- argv[0] = cmd.buf;
+ for (argc = 0; argv[argc]; argc++)
+ ; /* just counting */
+ nargv = xmalloc(sizeof(*nargv) * (argc + 2));
- trace_argv_printf(argv, -1, "trace: exec:");
+ nargv[0] = "git";
+ for (argc = 0; argv[argc]; argc++)
+ nargv[argc + 1] = argv[argc];
+ nargv[argc + 1] = NULL;
+ trace_argv_printf(nargv, -1, "trace: exec:");
/* execvp() can only ever return if it fails */
- execvp(cmd.buf, (char **)argv);
+ execvp("git", (char **)nargv);
trace_printf("trace: exec failed: %s\n", strerror(errno));
- argv[0] = tmp;
-
- strbuf_release(&cmd);
-
+ free(nargv);
return -1;
}
diff --git a/git.c b/git.c
index 01bbbc7..d690426 100644
--- a/git.c
+++ b/git.c
@@ -382,6 +382,36 @@ static void handle_internal_command(int argc, const char **argv)
}
}
+static void execv_dashed_external(const char **argv)
+{
+ struct strbuf cmd;
+ const char *tmp;
+
+ strbuf_init(&cmd, 0);
+ strbuf_addf(&cmd, "git-%s", argv[0]);
+
+ /*
+ * argv[0] must be the git command, but the argv array
+ * belongs to the caller, and may be reused in
+ * subsequent loop iterations. Save argv[0] and
+ * restore it on error.
+ */
+ tmp = argv[0];
+ argv[0] = cmd.buf;
+
+ trace_argv_printf(argv, -1, "trace: exec:");
+
+ /* execvp() can only ever return if it fails */
+ execvp(cmd.buf, (char **)argv);
+
+ trace_printf("trace: exec failed: %s\n", strerror(errno));
+
+ argv[0] = tmp;
+
+ strbuf_release(&cmd);
+}
+
+
int main(int argc, const char **argv)
{
const char *cmd = argv[0] ? argv[0] : "git-help";
@@ -445,7 +475,7 @@ int main(int argc, const char **argv)
handle_internal_command(argc, argv);
/* .. then try the external ones */
- execv_git_cmd(argv);
+ execv_dashed_external(argv);
/* It could be an alias -- this works around the insanity
* of overriding "git log" with "git show" by having
diff --git a/shell.c b/shell.c
index 9826109..729797c 100644
--- a/shell.c
+++ b/shell.c
@@ -19,17 +19,13 @@ static int do_generic_cmd(const char *me, char *arg)
return execv_git_cmd(my_argv);
}
-static int do_cvs_cmd(const char *me, char *arg)
+static int do_cvs_cmd(void)
{
const char *cvsserver_argv[3] = {
"cvsserver", "server", NULL
};
- if (!arg || strcmp(arg, "server"))
- die("git-cvsserver only handles server: %s", arg);
-
setup_path(NULL);
-
return execv_git_cmd(cvsserver_argv);
}
@@ -40,7 +36,6 @@ static struct commands {
} cmd_list[] = {
{ "git-receive-pack", do_generic_cmd },
{ "git-upload-pack", do_generic_cmd },
- { "cvs", do_cvs_cmd },
{ NULL },
};
@@ -49,15 +44,24 @@ int main(int argc, char **argv)
char *prog;
struct commands *cmd;
+ /*
+ * Special hack to pretend to be a CVS server
+ */
if (argc == 2 && !strcmp(argv[1], "cvs server"))
- argv--;
- /* We want to see "-c cmd args", and nothing else */
- else if (argc != 3 || strcmp(argv[1], "-c"))
+ exit(do_cvs_cmd());
+
+ /*
+ * We do not accept anything but "-c" followed by "cmd arg",
+ * where "cmd" is a very limited subset of git commands.
+ */
+ if (argc != 3 || strcmp(argv[1], "-c"))
die("What do you think I am? A shell?");
prog = argv[2];
- argv += 2;
- argc -= 2;
+ if (!strncmp(prog, "git", 3) && isspace(prog[3]))
+ /* Accept "git foo" as if the caller said "git-foo". */
+ prog[3] = '-';
+
for (cmd = cmd_list ; cmd->name ; cmd++) {
int len = strlen(cmd->name);
char *arg;
^ permalink raw reply related
* [PATCH 3/3] Use {web,instaweb,help}.browser config options.
From: Christian Couder @ 2007-12-02 5:08 UTC (permalink / raw)
To: Junio Hamano
Cc: git, Theodore Tso, Jakub Narebski, Alex Riesen, Andreas Ericsson,
Matthieu Moy, Eric Wong
Now "git-instaweb" will try to use the browser configured as
"web.browser", if "instaweb.browser" is not set.
"git-browse-help" will check first "help.browser" and then
"web.browser".
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
git-browse-help.sh | 8 ++++++--
git-instaweb.sh | 1 +
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/git-browse-help.sh b/git-browse-help.sh
index 11f8bfa..de52365 100755
--- a/git-browse-help.sh
+++ b/git-browse-help.sh
@@ -80,9 +80,13 @@ do
done
if test -z "$browser"; then
- browser=`git config web.browser`
+ for opt in "help.browser" "web.browser"
+ do
+ browser="`git config $opt`"
+ test -z "$browser" || break
+ done
if test -n "$browser" && ! valid_tool "$browser"; then
- echo >&2 "git config option web.browser set to unknown browser: $browser"
+ echo >&2 "git config option $opt set to unknown browser: $browser"
echo >&2 "Resetting to default..."
unset browser
fi
diff --git a/git-instaweb.sh b/git-instaweb.sh
index 8503ae4..42d8d7f 100755
--- a/git-instaweb.sh
+++ b/git-instaweb.sh
@@ -24,6 +24,7 @@ fqgitdir="$GIT_DIR"
local="`git config --bool --get instaweb.local`"
httpd="`git config --get instaweb.httpd`"
browser="`git config --get instaweb.browser`"
+test -z "$browser" && browser="`git config --get web.browser`"
port=`git config --get instaweb.port`
module_path="`git config --get instaweb.modulepath`"
--
1.5.3.6.1993.g154f-dirty
^ permalink raw reply related
* [PATCH 2/3] git-help: add -w|--web option to display html man page in a browser.
From: Christian Couder @ 2007-12-02 5:07 UTC (permalink / raw)
To: Junio Hamano
Cc: git, Theodore Tso, Jakub Narebski, Alex Riesen, Andreas Ericsson,
Matthieu Moy, Eric Wong
Now when using "git help -w XXX", we will try to show the HTML man
page "git-XXX.html" in your prefered web browser.
To do that "help.c" code will call a new shell script
"git-browse-help".
This currently works only if the HTML versions of the man page
have been installed in "PREFIX/share/doc/git-doc", so new target
to do that is added to "Documentation/Makefile".
The browser to use can be configured using the "web.browser"
config variable.
We try to open a new tab in an existing web browser, if possible.
The code in "git-browse-help" is heavily stolen from "git-mergetool"
by Theodore Y. Ts'o. Thanks.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
Documentation/Makefile | 4 +
Makefile | 4 +-
git-browse-help.sh | 154 ++++++++++++++++++++++++++++++++++++++++++++++++
help.c | 15 ++++-
4 files changed, 175 insertions(+), 2 deletions(-)
create mode 100755 git-browse-help.sh
diff --git a/Documentation/Makefile b/Documentation/Makefile
index d886641..3e01718 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -29,6 +29,7 @@ DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT))
prefix?=$(HOME)
bindir?=$(prefix)/bin
+htmldir?=$(prefix)/share/doc/git-doc
mandir?=$(prefix)/share/man
man1dir=$(mandir)/man1
man5dir=$(mandir)/man5
@@ -95,6 +96,9 @@ install-info: info
echo "No directory found in $(DESTDIR)$(infodir)" >&2 ; \
fi
+install-html: html
+ sh ./install-webdoc.sh $(htmldir)
+
../GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
$(MAKE) -C ../ GIT-VERSION-FILE
diff --git a/Makefile b/Makefile
index a5a40ce..9204bfe 100644
--- a/Makefile
+++ b/Makefile
@@ -223,7 +223,8 @@ SCRIPT_SH = \
git-merge-resolve.sh \
git-lost-found.sh git-quiltimport.sh git-submodule.sh \
git-filter-branch.sh \
- git-stash.sh
+ git-stash.sh \
+ git-browse-help.sh
SCRIPT_PERL = \
git-add--interactive.perl \
@@ -807,6 +808,7 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
-e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
-e 's/@@NO_CURL@@/$(NO_CURL)/g' \
+ -e 's|@@PREFIX@@|$(prefix_SQ)|g' \
$@.sh >$@+ && \
chmod +x $@+ && \
mv $@+ $@
diff --git a/git-browse-help.sh b/git-browse-help.sh
new file mode 100755
index 0000000..11f8bfa
--- /dev/null
+++ b/git-browse-help.sh
@@ -0,0 +1,154 @@
+#!/bin/sh
+#
+# This program launch a web browser on the html page
+# describing a git command.
+#
+# Copyright (c) 2007 Christian Couder
+# Copyright (c) 2006 Theodore Y. Ts'o
+#
+# This file is heavily stolen from git-mergetool.sh, by
+# Theodore Y. Ts'o (thanks) that is:
+#
+# Copyright (c) 2006 Theodore Y. Ts'o
+#
+# This file is licensed under the GPL v2, or a later version
+# at the discretion of Junio C Hamano or any other official
+# git maintainer.
+#
+
+USAGE='[--browser=browser|--tool=browser] [cmd to display] ...'
+SUBDIRECTORY_OK=Yes
+OPTIONS_SPEC=
+. git-sh-setup
+
+PREFIX="@@PREFIX@@"
+GIT_VERSION="@@GIT_VERSION@@"
+
+# Directories that may contain html documentation:
+install_html_dir="$PREFIX/share/doc/git-doc"
+rpm_dir="$PREFIX/share/doc/git-core-$GIT_VERSION"
+
+# Look for the directory that really contains html documentation.
+html_dir=''
+for dir in "$install_html_dir" "$rpm_dir"
+do
+ test -d "$dir" && { html_dir="$dir" ; break ; }
+done
+test -n "$html_dir" || die "No documentation directory found."
+
+valid_tool() {
+ case "$1" in
+ firefox | iceweasel | konqueror | w3m | links | lynx | dillo)
+ ;; # happy
+ *)
+ return 1
+ ;;
+ esac
+}
+
+init_browser_path() {
+ browser_path=`git config browser.$1.path`
+ test -z "$browser_path" && browser_path=$1
+}
+
+while test $# != 0
+do
+ case "$1" in
+ -b|--browser*|-t|--tool*)
+ case "$#,$1" in
+ *,*=*)
+ browser=`expr "z$1" : 'z-[^=]*=\(.*\)'`
+ ;;
+ 1,*)
+ usage ;;
+ *)
+ browser="$2"
+ shift ;;
+ esac
+ ;;
+ --)
+ break
+ ;;
+ -*)
+ usage
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+done
+
+if test -z "$browser"; then
+ browser=`git config web.browser`
+ if test -n "$browser" && ! valid_tool "$browser"; then
+ echo >&2 "git config option web.browser set to unknown browser: $browser"
+ echo >&2 "Resetting to default..."
+ unset browser
+ fi
+fi
+
+if test -z "$browser" ; then
+ if test -n "$DISPLAY"; then
+ browser_candidates="firefox iceweasel konqueror w3m links lynx dillo"
+ if test "$KDE_FULL_SESSION" = "true"; then
+ browser_candidates="konqueror $browser_candidates"
+ fi
+ else
+ browser_candidates="w3m links lynx"
+ fi
+ echo "browser candidates: $browser_candidates"
+ for i in $browser_candidates; do
+ init_browser_path $i
+ if type "$browser_path" > /dev/null 2>&1; then
+ browser=$i
+ break
+ fi
+ done
+ test -z "$browser" && die "No known browser available."
+else
+ valid_tool "$browser" || die "Unknown browser '$browser'."
+
+ init_browser_path "$browser"
+
+ if ! type "$browser_path" > /dev/null 2>&1; then
+ die "The browser $browser is not available as '$browser_path'."
+ fi
+fi
+
+pages=$(for p in "$@"; do echo "$html_dir/$p.html" ; done)
+test -z "$pages" && pages="$html_dir/git.html"
+
+case "$browser" in
+ firefox|iceweasel)
+ # Check version because firefox < 2.0 does not support "-new-tab".
+ vers=$(expr "$($browser_path -version)" : '.* \([0-9][0-9]*\)\..*')
+ NEWTAB='-new-tab'
+ test "$vers" -lt 2 && NEWTAB=''
+ nohup "$browser_path" $NEWTAB $pages &
+ ;;
+ konqueror)
+ case "$(basename "$browser_path")" in
+ konqueror)
+ # It's simpler to use kfmclient to open a new tab in konqueror.
+ browser_path="$(echo "$browser_path" | sed -e 's/konqueror$/kfmclient/')"
+ type "$browser_path" > /dev/null 2>&1 || die "No '$browser_path' found."
+ eval "$browser_path" newTab $pages
+ ;;
+ kfmclient)
+ eval "$browser_path" newTab $pages
+ ;;
+ *)
+ nohup "$browser_path" $pages &
+ ;;
+ esac
+ ;;
+ w3m|links|lynx)
+ eval "$browser_path" $pages
+ ;;
+ dillo)
+ nohup "$browser_path" $pages &
+ ;;
+esac
+
+
diff --git a/help.c b/help.c
index 0f1cb71..ecc8c66 100644
--- a/help.c
+++ b/help.c
@@ -265,6 +265,12 @@ static void show_info_page(const char *git_cmd)
execlp("info", "info", page, NULL);
}
+static void show_html_page(const char *git_cmd)
+{
+ const char *page = cmd_to_page(git_cmd);
+ execlp("git-browse-help", "git-browse-help", page, NULL);
+}
+
void help_unknown_cmd(const char *cmd)
{
fprintf(stderr, "git: '%s' is not a git-command. See 'git --help'.\n", cmd);
@@ -297,7 +303,14 @@ int cmd_help(int argc, const char **argv, const char *prefix)
const char *help_cmd = argc > 1 ? argv[1] : NULL;
check_help_cmd(help_cmd);
- if (!strcmp(help_cmd, "--info") || !strcmp(help_cmd, "-i")) {
+ if (!strcmp(help_cmd, "--web") || !strcmp(help_cmd, "-w")) {
+ help_cmd = argc > 2 ? argv[2] : NULL;
+ check_help_cmd(help_cmd);
+
+ show_html_page(help_cmd);
+ }
+
+ else if (!strcmp(help_cmd, "--info") || !strcmp(help_cmd, "-i")) {
help_cmd = argc > 2 ? argv[2] : NULL;
check_help_cmd(help_cmd);
--
1.5.3.6.1993.g154f-dirty
^ permalink raw reply related
* [PATCH 1/3] git-help: add -i|--info option to display info page.
From: Christian Couder @ 2007-12-02 5:07 UTC (permalink / raw)
To: Junio Hamano
Cc: git, Theodore Tso, Jakub Narebski, Alex Riesen, Andreas Ericsson,
Matthieu Moy, Eric Wong
"git help --info XXX" will now call "info git-XXX".
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
help.c | 35 +++++++++++++++++++++++++++--------
1 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/help.c b/help.c
index 37a9c25..0f1cb71 100644
--- a/help.c
+++ b/help.c
@@ -239,24 +239,32 @@ void list_common_cmds_help(void)
}
}
-static void show_man_page(const char *git_cmd)
+static const char *cmd_to_page(const char *git_cmd)
{
- const char *page;
-
if (!prefixcmp(git_cmd, "git"))
- page = git_cmd;
+ return git_cmd;
else {
int page_len = strlen(git_cmd) + 4;
char *p = xmalloc(page_len + 1);
strcpy(p, "git-");
strcpy(p + 4, git_cmd);
p[page_len] = 0;
- page = p;
+ return p;
}
+}
+static void show_man_page(const char *git_cmd)
+{
+ const char *page = cmd_to_page(git_cmd);
execlp("man", "man", page, NULL);
}
+static void show_info_page(const char *git_cmd)
+{
+ const char *page = cmd_to_page(git_cmd);
+ execlp("info", "info", page, NULL);
+}
+
void help_unknown_cmd(const char *cmd)
{
fprintf(stderr, "git: '%s' is not a git-command. See 'git --help'.\n", cmd);
@@ -269,10 +277,8 @@ int cmd_version(int argc, const char **argv, const char *prefix)
return 0;
}
-int cmd_help(int argc, const char **argv, const char *prefix)
+static void check_help_cmd(const char *help_cmd)
{
- const char *help_cmd = argc > 1 ? argv[1] : NULL;
-
if (!help_cmd) {
printf("usage: %s\n\n", git_usage_string);
list_common_cmds_help();
@@ -284,6 +290,19 @@ int cmd_help(int argc, const char **argv, const char *prefix)
list_commands();
exit(0);
}
+}
+
+int cmd_help(int argc, const char **argv, const char *prefix)
+{
+ const char *help_cmd = argc > 1 ? argv[1] : NULL;
+ check_help_cmd(help_cmd);
+
+ if (!strcmp(help_cmd, "--info") || !strcmp(help_cmd, "-i")) {
+ help_cmd = argc > 2 ? argv[2] : NULL;
+ check_help_cmd(help_cmd);
+
+ show_info_page(help_cmd);
+ }
else
show_man_page(help_cmd);
--
1.5.3.6.1993.g154f-dirty
^ permalink raw reply related
* [PATCH 0/3] git-help: add new options -w (for web) and -i (for info)
From: Christian Couder @ 2007-12-02 5:03 UTC (permalink / raw)
To: Junio Hamano
Cc: git, Theodore Tso, Jakub Narebski, Alex Riesen, Andreas Ericsson,
Matthieu Moy, Eric Wong
Hi,
Here are the changes since my last RFC/PATCH:
[PATCH 1/3] git-help: add -i|--info option to display info page:
- info is now in a separate patch
[PATCH 2/3] git-help: add -w|--web option to display html man page in a browser.
- git-html-help.sh has been renamed git-browse-help.sh
- use web.browser config option instead of web.tool
- look up for the following documentation directories:
"$PREFIX/share/doc/git-doc"
"$PREFIX/share/doc/git-core-$GIT_VERSION"
not only the first one
- add links, lynx and dillo has possible browsers
- git-browse-help.sh accept both -b|--browser and -t|--tool to specify
a browser (to be consistent with both git-mergetool and git-instaweb)
- improved launching of firefox|iceweasel and konqueror
[PATCH 3/3] Use {web,instaweb,help}.browser config options.
- improve consistent use of config options between git-browse-help and
git-instaweb
Thanks for your reviews,
Christian.
^ permalink raw reply
* [REPLACEMENT PATCH 3/3] Introduce execv_git_builtin() and use it
From: Johannes Schindelin @ 2007-12-02 3:16 UTC (permalink / raw)
To: Junio C Hamano
Cc: Eyvind Bernhardsen, Nicolas Pitre, Nguyen Thai Ngoc Duy,
Jan Hudec, git
In-Reply-To: <Pine.LNX.4.64.0712020303190.27959@racer.site>
You can call execv_git_builtin() to execute a builtin command. This
function is a reborn handle_internal_command() from git.c, and has the
semantics of execv_git_cmd(), i.e. it exits with the exit code of the
builtin if there is a matching builtin, but it avoids the real execvp()
call.
This function calls release_all_objects() and discard_cache() to start
from a clean slate (this, along with the calculation of argc, is the only
difference from a straight code move).
The test suite passes, which at least does not contradict the hypothesis
that this is good enough. However, it might be necessary to de-initialize
more global variables.
The function execv_git_cmd() and git.c's main() function were changed to
take advantage of execv_git_builtin().
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
On Sun, 2 Dec 2007, Johannes Schindelin wrote:
> Hi,
>
> On Sun, 2 Dec 2007, Johannes Schindelin wrote:
>
> > + { "fmt", cmd_fmt },
>
> Ah, well. This slipped in by mistake. Will resend in a few
> minutes.
Here we go.
exec_cmd.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
exec_cmd.h | 1 +
git.c | 170 +---------------------------------------------------------
3 files changed, 178 insertions(+), 169 deletions(-)
diff --git a/exec_cmd.c b/exec_cmd.c
index 2d0a758..745b951 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -1,6 +1,8 @@
#include "cache.h"
#include "exec_cmd.h"
#include "quote.h"
+#include "builtin.h"
+#include "object.h"
#define MAX_ARGS 32
extern char **environ;
@@ -63,11 +65,185 @@ void setup_path(const char *cmd_path)
strbuf_release(&new_path);
}
+const char git_usage_string[] =
+ "git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
+
+const char git_version_string[] = GIT_VERSION;
+
+#define RUN_SETUP (1<<0)
+#define USE_PAGER (1<<1)
+/*
+ * require working tree to be present -- anything uses this needs
+ * RUN_SETUP for reading from the configuration file.
+ */
+#define NEED_WORK_TREE (1<<2)
+
+struct cmd_struct {
+ const char *cmd;
+ int (*fn)(int, const char **, const char *);
+ int option;
+};
+
+static int run_command(struct cmd_struct *p, int argc, const char **argv)
+{
+ int status;
+ struct stat st;
+ const char *prefix;
+
+ prefix = NULL;
+ if (p->option & RUN_SETUP)
+ prefix = setup_git_directory();
+ if (p->option & USE_PAGER)
+ setup_pager();
+ if (p->option & NEED_WORK_TREE)
+ setup_work_tree();
+
+ trace_argv_printf(argv, argc, "trace: built-in: git");
+
+ status = p->fn(argc, argv, prefix);
+ if (status)
+ return status & 0xff;
+
+ /* Somebody closed stdout? */
+ if (fstat(fileno(stdout), &st))
+ return 0;
+ /* Ignore write errors for pipes and sockets.. */
+ if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
+ return 0;
+
+ /* Check for ENOSPC and EIO errors.. */
+ if (fflush(stdout))
+ die("write failure on standard output: %s", strerror(errno));
+ if (ferror(stdout))
+ die("unknown write failure on standard output");
+ if (fclose(stdout))
+ die("close failed on standard output: %s", strerror(errno));
+ return 0;
+}
+
+int execv_git_builtin(const char **argv)
+{
+ const char *cmd = argv[0];
+ static struct cmd_struct commands[] = {
+ { "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
+ { "annotate", cmd_annotate, RUN_SETUP },
+ { "apply", cmd_apply },
+ { "archive", cmd_archive },
+ { "blame", cmd_blame, RUN_SETUP },
+ { "branch", cmd_branch, RUN_SETUP },
+ { "bundle", cmd_bundle },
+ { "cat-file", cmd_cat_file, RUN_SETUP },
+ { "checkout-index", cmd_checkout_index,
+ RUN_SETUP | NEED_WORK_TREE},
+ { "check-ref-format", cmd_check_ref_format },
+ { "check-attr", cmd_check_attr, RUN_SETUP | NEED_WORK_TREE },
+ { "cherry", cmd_cherry, RUN_SETUP },
+ { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
+ { "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE },
+ { "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
+ { "commit-tree", cmd_commit_tree, RUN_SETUP },
+ { "config", cmd_config },
+ { "count-objects", cmd_count_objects, RUN_SETUP },
+ { "describe", cmd_describe, RUN_SETUP },
+ { "diff", cmd_diff },
+ { "diff-files", cmd_diff_files },
+ { "diff-index", cmd_diff_index, RUN_SETUP },
+ { "diff-tree", cmd_diff_tree, RUN_SETUP },
+ { "fetch", cmd_fetch, RUN_SETUP },
+ { "fetch-pack", cmd_fetch_pack, RUN_SETUP },
+ { "fetch--tool", cmd_fetch__tool, RUN_SETUP },
+ { "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
+ { "for-each-ref", cmd_for_each_ref, RUN_SETUP },
+ { "format-patch", cmd_format_patch, RUN_SETUP },
+ { "fsck", cmd_fsck, RUN_SETUP },
+ { "fsck-objects", cmd_fsck, RUN_SETUP },
+ { "gc", cmd_gc, RUN_SETUP },
+ { "get-tar-commit-id", cmd_get_tar_commit_id },
+ { "grep", cmd_grep, RUN_SETUP | USE_PAGER },
+ { "help", cmd_help },
+#ifndef NO_CURL
+ { "http-fetch", cmd_http_fetch, RUN_SETUP },
+#endif
+ { "init", cmd_init_db },
+ { "init-db", cmd_init_db },
+ { "log", cmd_log, RUN_SETUP | USE_PAGER },
+ { "ls-files", cmd_ls_files, RUN_SETUP },
+ { "ls-tree", cmd_ls_tree, RUN_SETUP },
+ { "ls-remote", cmd_ls_remote },
+ { "mailinfo", cmd_mailinfo },
+ { "mailsplit", cmd_mailsplit },
+ { "merge-base", cmd_merge_base, RUN_SETUP },
+ { "merge-file", cmd_merge_file },
+ { "merge-ours", cmd_merge_ours, RUN_SETUP },
+ { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
+ { "name-rev", cmd_name_rev, RUN_SETUP },
+ { "pack-objects", cmd_pack_objects, RUN_SETUP },
+ { "peek-remote", cmd_ls_remote },
+ { "pickaxe", cmd_blame, RUN_SETUP },
+ { "prune", cmd_prune, RUN_SETUP },
+ { "prune-packed", cmd_prune_packed, RUN_SETUP },
+ { "push", cmd_push, RUN_SETUP },
+ { "read-tree", cmd_read_tree, RUN_SETUP },
+ { "reflog", cmd_reflog, RUN_SETUP },
+ { "repo-config", cmd_config },
+ { "rerere", cmd_rerere, RUN_SETUP },
+ { "reset", cmd_reset, RUN_SETUP },
+ { "rev-list", cmd_rev_list, RUN_SETUP },
+ { "rev-parse", cmd_rev_parse },
+ { "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
+ { "rm", cmd_rm, RUN_SETUP },
+ { "send-pack", cmd_send_pack, RUN_SETUP },
+ { "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER },
+ { "show-branch", cmd_show_branch, RUN_SETUP },
+ { "show", cmd_show, RUN_SETUP | USE_PAGER },
+ { "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
+ { "stripspace", cmd_stripspace },
+ { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
+ { "tag", cmd_tag, RUN_SETUP },
+ { "tar-tree", cmd_tar_tree },
+ { "unpack-objects", cmd_unpack_objects, RUN_SETUP },
+ { "update-index", cmd_update_index, RUN_SETUP },
+ { "update-ref", cmd_update_ref, RUN_SETUP },
+ { "upload-archive", cmd_upload_archive },
+ { "verify-tag", cmd_verify_tag, RUN_SETUP },
+ { "version", cmd_version },
+ { "whatchanged", cmd_whatchanged, RUN_SETUP | USE_PAGER },
+ { "write-tree", cmd_write_tree, RUN_SETUP },
+ { "verify-pack", cmd_verify_pack },
+ { "show-ref", cmd_show_ref, RUN_SETUP },
+ { "pack-refs", cmd_pack_refs, RUN_SETUP },
+ };
+ int i;
+
+ /* Turn "git cmd --help" into "git help cmd" */
+ if (argv[0] && argv[1] && !strcmp(argv[1], "--help")) {
+ argv[1] = argv[0];
+ argv[0] = cmd = "help";
+ }
+
+ for (i = 0; i < ARRAY_SIZE(commands); i++) {
+ int argc;
+ struct cmd_struct *p = commands+i;
+ if (strcmp(p->cmd, cmd))
+ continue;
+ release_all_objects();
+ discard_cache();
+ for (argc = 0; argv[argc]; argc++)
+ ; /* do nothing */
+ exit(run_command(p, argc, argv));
+ }
+ return -1;
+}
+
int execv_git_cmd(const char **argv)
{
struct strbuf cmd;
const char *tmp;
+ /* Try builtin first... */
+ execv_git_builtin(argv);
+
+ /* ... and then external commands */
strbuf_init(&cmd, 0);
strbuf_addf(&cmd, "git-%s", argv[0]);
diff --git a/exec_cmd.h b/exec_cmd.h
index a892355..bb15425 100644
--- a/exec_cmd.h
+++ b/exec_cmd.h
@@ -4,6 +4,7 @@
extern void git_set_argv_exec_path(const char *exec_path);
extern const char* git_exec_path(void);
extern void setup_path(const char *);
+extern int execv_git_builtin(const char **argv); /* NULL terminated */
extern int execv_git_cmd(const char **argv); /* NULL terminated */
extern int execl_git_cmd(const char *cmd, ...);
diff --git a/git.c b/git.c
index 95296aa..1523c4a 100644
--- a/git.c
+++ b/git.c
@@ -3,9 +3,6 @@
#include "cache.h"
#include "quote.h"
-const char git_usage_string[] =
- "git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
-
static int handle_options(const char*** argv, int* argc, int* envchanged)
{
int handled = 0;
@@ -231,167 +228,6 @@ static int handle_alias(int *argcp, const char ***argv)
return ret;
}
-const char git_version_string[] = GIT_VERSION;
-
-#define RUN_SETUP (1<<0)
-#define USE_PAGER (1<<1)
-/*
- * require working tree to be present -- anything uses this needs
- * RUN_SETUP for reading from the configuration file.
- */
-#define NEED_WORK_TREE (1<<2)
-
-struct cmd_struct {
- const char *cmd;
- int (*fn)(int, const char **, const char *);
- int option;
-};
-
-static int run_command(struct cmd_struct *p, int argc, const char **argv)
-{
- int status;
- struct stat st;
- const char *prefix;
-
- prefix = NULL;
- if (p->option & RUN_SETUP)
- prefix = setup_git_directory();
- if (p->option & USE_PAGER)
- setup_pager();
- if (p->option & NEED_WORK_TREE)
- setup_work_tree();
-
- trace_argv_printf(argv, argc, "trace: built-in: git");
-
- status = p->fn(argc, argv, prefix);
- if (status)
- return status & 0xff;
-
- /* Somebody closed stdout? */
- if (fstat(fileno(stdout), &st))
- return 0;
- /* Ignore write errors for pipes and sockets.. */
- if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
- return 0;
-
- /* Check for ENOSPC and EIO errors.. */
- if (fflush(stdout))
- die("write failure on standard output: %s", strerror(errno));
- if (ferror(stdout))
- die("unknown write failure on standard output");
- if (fclose(stdout))
- die("close failed on standard output: %s", strerror(errno));
- return 0;
-}
-
-static void handle_internal_command(int argc, const char **argv)
-{
- const char *cmd = argv[0];
- static struct cmd_struct commands[] = {
- { "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
- { "annotate", cmd_annotate, RUN_SETUP },
- { "apply", cmd_apply },
- { "archive", cmd_archive },
- { "blame", cmd_blame, RUN_SETUP },
- { "branch", cmd_branch, RUN_SETUP },
- { "bundle", cmd_bundle },
- { "cat-file", cmd_cat_file, RUN_SETUP },
- { "checkout-index", cmd_checkout_index,
- RUN_SETUP | NEED_WORK_TREE},
- { "check-ref-format", cmd_check_ref_format },
- { "check-attr", cmd_check_attr, RUN_SETUP | NEED_WORK_TREE },
- { "cherry", cmd_cherry, RUN_SETUP },
- { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
- { "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE },
- { "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
- { "commit-tree", cmd_commit_tree, RUN_SETUP },
- { "config", cmd_config },
- { "count-objects", cmd_count_objects, RUN_SETUP },
- { "describe", cmd_describe, RUN_SETUP },
- { "diff", cmd_diff },
- { "diff-files", cmd_diff_files },
- { "diff-index", cmd_diff_index, RUN_SETUP },
- { "diff-tree", cmd_diff_tree, RUN_SETUP },
- { "fetch", cmd_fetch, RUN_SETUP },
- { "fetch-pack", cmd_fetch_pack, RUN_SETUP },
- { "fetch--tool", cmd_fetch__tool, RUN_SETUP },
- { "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
- { "for-each-ref", cmd_for_each_ref, RUN_SETUP },
- { "format-patch", cmd_format_patch, RUN_SETUP },
- { "fsck", cmd_fsck, RUN_SETUP },
- { "fsck-objects", cmd_fsck, RUN_SETUP },
- { "gc", cmd_gc, RUN_SETUP },
- { "get-tar-commit-id", cmd_get_tar_commit_id },
- { "grep", cmd_grep, RUN_SETUP | USE_PAGER },
- { "help", cmd_help },
-#ifndef NO_CURL
- { "http-fetch", cmd_http_fetch, RUN_SETUP },
-#endif
- { "init", cmd_init_db },
- { "init-db", cmd_init_db },
- { "log", cmd_log, RUN_SETUP | USE_PAGER },
- { "ls-files", cmd_ls_files, RUN_SETUP },
- { "ls-tree", cmd_ls_tree, RUN_SETUP },
- { "ls-remote", cmd_ls_remote },
- { "mailinfo", cmd_mailinfo },
- { "mailsplit", cmd_mailsplit },
- { "merge-base", cmd_merge_base, RUN_SETUP },
- { "merge-file", cmd_merge_file },
- { "merge-ours", cmd_merge_ours, RUN_SETUP },
- { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
- { "name-rev", cmd_name_rev, RUN_SETUP },
- { "pack-objects", cmd_pack_objects, RUN_SETUP },
- { "peek-remote", cmd_ls_remote },
- { "pickaxe", cmd_blame, RUN_SETUP },
- { "prune", cmd_prune, RUN_SETUP },
- { "prune-packed", cmd_prune_packed, RUN_SETUP },
- { "push", cmd_push, RUN_SETUP },
- { "read-tree", cmd_read_tree, RUN_SETUP },
- { "reflog", cmd_reflog, RUN_SETUP },
- { "repo-config", cmd_config },
- { "rerere", cmd_rerere, RUN_SETUP },
- { "reset", cmd_reset, RUN_SETUP },
- { "rev-list", cmd_rev_list, RUN_SETUP },
- { "rev-parse", cmd_rev_parse },
- { "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
- { "rm", cmd_rm, RUN_SETUP },
- { "send-pack", cmd_send_pack, RUN_SETUP },
- { "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER },
- { "show-branch", cmd_show_branch, RUN_SETUP },
- { "show", cmd_show, RUN_SETUP | USE_PAGER },
- { "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
- { "stripspace", cmd_stripspace },
- { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
- { "tag", cmd_tag, RUN_SETUP },
- { "tar-tree", cmd_tar_tree },
- { "unpack-objects", cmd_unpack_objects, RUN_SETUP },
- { "update-index", cmd_update_index, RUN_SETUP },
- { "update-ref", cmd_update_ref, RUN_SETUP },
- { "upload-archive", cmd_upload_archive },
- { "verify-tag", cmd_verify_tag, RUN_SETUP },
- { "version", cmd_version },
- { "whatchanged", cmd_whatchanged, RUN_SETUP | USE_PAGER },
- { "write-tree", cmd_write_tree, RUN_SETUP },
- { "verify-pack", cmd_verify_pack },
- { "show-ref", cmd_show_ref, RUN_SETUP },
- { "pack-refs", cmd_pack_refs, RUN_SETUP },
- };
- int i;
-
- /* Turn "git cmd --help" into "git help cmd" */
- if (argc > 1 && !strcmp(argv[1], "--help")) {
- argv[1] = argv[0];
- argv[0] = cmd = "help";
- }
-
- for (i = 0; i < ARRAY_SIZE(commands); i++) {
- struct cmd_struct *p = commands+i;
- if (strcmp(p->cmd, cmd))
- continue;
- exit(run_command(p, argc, argv));
- }
-}
-
int main(int argc, const char **argv)
{
const char *cmd = argv[0] ? argv[0] : "git-help";
@@ -423,7 +259,7 @@ int main(int argc, const char **argv)
if (!prefixcmp(cmd, "git-")) {
cmd += 4;
argv[0] = cmd;
- handle_internal_command(argc, argv);
+ execv_git_builtin(argv);
die("cannot handle %s internally", cmd);
}
@@ -451,10 +287,6 @@ int main(int argc, const char **argv)
setup_path(cmd_path);
while (1) {
- /* See if it's an internal command */
- handle_internal_command(argc, argv);
-
- /* .. then try the external ones */
execv_git_cmd(argv);
/* It could be an alias -- this works around the insanity
--
1.5.3.6.2112.ge2263
^ permalink raw reply related
* Re: [PATCH 3/3] Introduce execv_git_builtin() and use it
From: Johannes Schindelin @ 2007-12-02 3:04 UTC (permalink / raw)
To: Junio C Hamano
Cc: Eyvind Bernhardsen, Nicolas Pitre, Nguyen Thai Ngoc Duy,
Jan Hudec, git
In-Reply-To: <Pine.LNX.4.64.0712020254540.27959@racer.site>
Hi,
On Sun, 2 Dec 2007, Johannes Schindelin wrote:
> + { "fmt", cmd_fmt },
Ah, well. This slipped in by mistake. Will resend in a few minutes.
Ciao,
Dscho
^ permalink raw reply
* [PATCH 3/3] Introduce execv_git_builtin() and use it
From: Johannes Schindelin @ 2007-12-02 2:55 UTC (permalink / raw)
To: Junio C Hamano
Cc: Eyvind Bernhardsen, Nicolas Pitre, Nguyen Thai Ngoc Duy,
Jan Hudec, git
In-Reply-To: <Pine.LNX.4.64.0712020146240.27959@racer.site>
You can call execv_git_builtin() to execute a builtin command. This
function is a reborn handle_internal_command() from git.c, and has the
semantics of execv_git_cmd(), i.e. it exits with the exit code of the
builtin if there is a matching builtin, but it avoids the real
execvp() call.
This function calls release_all_objects() and discard_cache() to start
from a clean slate (this, along with the calculation of argc, is the
only difference from a straight code move).
The test suite passes, which at least does not contradict the
hypothesis that this is good enough. However, it might be
necessary to de-initialize more global variables.
The function execv_git_cmd() and git.c's main() function were changed
to take advantage of execv_git_builtin().
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
exec_cmd.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
exec_cmd.h | 1 +
git.c | 172 +---------------------------------------------------------
3 files changed, 180 insertions(+), 171 deletions(-)
diff --git a/exec_cmd.c b/exec_cmd.c
index 2d0a758..ac21181 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -1,6 +1,8 @@
#include "cache.h"
#include "exec_cmd.h"
#include "quote.h"
+#include "builtin.h"
+#include "object.h"
#define MAX_ARGS 32
extern char **environ;
@@ -63,11 +65,187 @@ void setup_path(const char *cmd_path)
strbuf_release(&new_path);
}
+const char git_usage_string[] =
+ "git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
+
+const char git_version_string[] = GIT_VERSION;
+
+#define RUN_SETUP (1<<0)
+#define USE_PAGER (1<<1)
+/*
+ * require working tree to be present -- anything uses this needs
+ * RUN_SETUP for reading from the configuration file.
+ */
+#define NEED_WORK_TREE (1<<2)
+
+struct cmd_struct {
+ const char *cmd;
+ int (*fn)(int, const char **, const char *);
+ int option;
+};
+
+static int run_command(struct cmd_struct *p, int argc, const char **argv)
+{
+ int status;
+ struct stat st;
+ const char *prefix;
+
+ prefix = NULL;
+ if (p->option & RUN_SETUP)
+ prefix = setup_git_directory();
+ if (p->option & USE_PAGER)
+ setup_pager();
+ if (p->option & NEED_WORK_TREE)
+ setup_work_tree();
+
+ trace_argv_printf(argv, argc, "trace: built-in: git");
+
+ status = p->fn(argc, argv, prefix);
+ if (status)
+ return status & 0xff;
+
+ /* Somebody closed stdout? */
+ if (fstat(fileno(stdout), &st))
+ return 0;
+ /* Ignore write errors for pipes and sockets.. */
+ if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
+ return 0;
+
+ /* Check for ENOSPC and EIO errors.. */
+ if (fflush(stdout))
+ die("write failure on standard output: %s", strerror(errno));
+ if (ferror(stdout))
+ die("unknown write failure on standard output");
+ if (fclose(stdout))
+ die("close failed on standard output: %s", strerror(errno));
+ return 0;
+}
+
+int execv_git_builtin(const char **argv)
+{
+ const char *cmd = argv[0];
+ static struct cmd_struct commands[] = {
+ { "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
+ { "annotate", cmd_annotate, RUN_SETUP },
+ { "apply", cmd_apply },
+ { "archive", cmd_archive },
+ { "blame", cmd_blame, RUN_SETUP },
+ { "branch", cmd_branch, RUN_SETUP },
+ { "bundle", cmd_bundle },
+ { "cat-file", cmd_cat_file, RUN_SETUP },
+ { "checkout-index", cmd_checkout_index,
+ RUN_SETUP | NEED_WORK_TREE},
+ { "check-ref-format", cmd_check_ref_format },
+ { "check-attr", cmd_check_attr, RUN_SETUP | NEED_WORK_TREE },
+ { "cherry", cmd_cherry, RUN_SETUP },
+ { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
+ { "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE },
+ { "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
+ { "commit-tree", cmd_commit_tree, RUN_SETUP },
+ { "config", cmd_config },
+ { "count-objects", cmd_count_objects, RUN_SETUP },
+ { "describe", cmd_describe, RUN_SETUP },
+ { "diff", cmd_diff },
+ { "diff-files", cmd_diff_files },
+ { "diff-index", cmd_diff_index, RUN_SETUP },
+ { "diff-tree", cmd_diff_tree, RUN_SETUP },
+ { "fast-export", cmd_fast_export, RUN_SETUP },
+ { "fetch", cmd_fetch, RUN_SETUP },
+ { "fetch-pack", cmd_fetch_pack, RUN_SETUP },
+ { "fetch--tool", cmd_fetch__tool, RUN_SETUP },
+ { "fmt", cmd_fmt },
+ { "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
+ { "for-each-ref", cmd_for_each_ref, RUN_SETUP },
+ { "format-patch", cmd_format_patch, RUN_SETUP },
+ { "fsck", cmd_fsck, RUN_SETUP },
+ { "fsck-objects", cmd_fsck, RUN_SETUP },
+ { "gc", cmd_gc, RUN_SETUP },
+ { "get-tar-commit-id", cmd_get_tar_commit_id },
+ { "grep", cmd_grep, RUN_SETUP | USE_PAGER },
+ { "help", cmd_help },
+#ifndef NO_CURL
+ { "http-fetch", cmd_http_fetch, RUN_SETUP },
+#endif
+ { "init", cmd_init_db },
+ { "init-db", cmd_init_db },
+ { "log", cmd_log, RUN_SETUP | USE_PAGER },
+ { "ls-files", cmd_ls_files, RUN_SETUP },
+ { "ls-tree", cmd_ls_tree, RUN_SETUP },
+ { "ls-remote", cmd_ls_remote },
+ { "mailinfo", cmd_mailinfo },
+ { "mailsplit", cmd_mailsplit },
+ { "merge-base", cmd_merge_base, RUN_SETUP },
+ { "merge-file", cmd_merge_file },
+ { "merge-ours", cmd_merge_ours, RUN_SETUP },
+ { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
+ { "name-rev", cmd_name_rev, RUN_SETUP },
+ { "pack-objects", cmd_pack_objects, RUN_SETUP },
+ { "peek-remote", cmd_ls_remote },
+ { "pickaxe", cmd_blame, RUN_SETUP },
+ { "prune", cmd_prune, RUN_SETUP },
+ { "prune-packed", cmd_prune_packed, RUN_SETUP },
+ { "push", cmd_push, RUN_SETUP },
+ { "read-tree", cmd_read_tree, RUN_SETUP },
+ { "reflog", cmd_reflog, RUN_SETUP },
+ { "repo-config", cmd_config },
+ { "rerere", cmd_rerere, RUN_SETUP },
+ { "reset", cmd_reset, RUN_SETUP },
+ { "rev-list", cmd_rev_list, RUN_SETUP },
+ { "rev-parse", cmd_rev_parse },
+ { "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
+ { "rm", cmd_rm, RUN_SETUP },
+ { "send-pack", cmd_send_pack, RUN_SETUP },
+ { "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER },
+ { "show-branch", cmd_show_branch, RUN_SETUP },
+ { "show", cmd_show, RUN_SETUP | USE_PAGER },
+ { "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
+ { "stripspace", cmd_stripspace },
+ { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
+ { "tag", cmd_tag, RUN_SETUP },
+ { "tar-tree", cmd_tar_tree },
+ { "unpack-objects", cmd_unpack_objects, RUN_SETUP },
+ { "update-index", cmd_update_index, RUN_SETUP },
+ { "update-ref", cmd_update_ref, RUN_SETUP },
+ { "upload-archive", cmd_upload_archive },
+ { "verify-tag", cmd_verify_tag, RUN_SETUP },
+ { "version", cmd_version },
+ { "whatchanged", cmd_whatchanged, RUN_SETUP | USE_PAGER },
+ { "write-tree", cmd_write_tree, RUN_SETUP },
+ { "verify-pack", cmd_verify_pack },
+ { "show-ref", cmd_show_ref, RUN_SETUP },
+ { "pack-refs", cmd_pack_refs, RUN_SETUP },
+ };
+ int i;
+
+ /* Turn "git cmd --help" into "git help cmd" */
+ if (argv[0] && argv[1] && !strcmp(argv[1], "--help")) {
+ argv[1] = argv[0];
+ argv[0] = cmd = "help";
+ }
+
+ for (i = 0; i < ARRAY_SIZE(commands); i++) {
+ int argc;
+ struct cmd_struct *p = commands+i;
+ if (strcmp(p->cmd, cmd))
+ continue;
+ release_all_objects();
+ discard_cache();
+ for (argc = 0; argv[argc]; argc++)
+ ; /* do nothing */
+ exit(run_command(p, argc, argv));
+ }
+ return -1;
+}
+
int execv_git_cmd(const char **argv)
{
struct strbuf cmd;
const char *tmp;
+ /* Try builtin first... */
+ execv_git_builtin(argv);
+
+ /* ... and then external commands */
strbuf_init(&cmd, 0);
strbuf_addf(&cmd, "git-%s", argv[0]);
diff --git a/exec_cmd.h b/exec_cmd.h
index a892355..bb15425 100644
--- a/exec_cmd.h
+++ b/exec_cmd.h
@@ -4,6 +4,7 @@
extern void git_set_argv_exec_path(const char *exec_path);
extern const char* git_exec_path(void);
extern void setup_path(const char *);
+extern int execv_git_builtin(const char **argv); /* NULL terminated */
extern int execv_git_cmd(const char **argv); /* NULL terminated */
extern int execl_git_cmd(const char *cmd, ...);
diff --git a/git.c b/git.c
index 38b01ca..1523c4a 100644
--- a/git.c
+++ b/git.c
@@ -3,9 +3,6 @@
#include "cache.h"
#include "quote.h"
-const char git_usage_string[] =
- "git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
-
static int handle_options(const char*** argv, int* argc, int* envchanged)
{
int handled = 0;
@@ -231,169 +228,6 @@ static int handle_alias(int *argcp, const char ***argv)
return ret;
}
-const char git_version_string[] = GIT_VERSION;
-
-#define RUN_SETUP (1<<0)
-#define USE_PAGER (1<<1)
-/*
- * require working tree to be present -- anything uses this needs
- * RUN_SETUP for reading from the configuration file.
- */
-#define NEED_WORK_TREE (1<<2)
-
-struct cmd_struct {
- const char *cmd;
- int (*fn)(int, const char **, const char *);
- int option;
-};
-
-static int run_command(struct cmd_struct *p, int argc, const char **argv)
-{
- int status;
- struct stat st;
- const char *prefix;
-
- prefix = NULL;
- if (p->option & RUN_SETUP)
- prefix = setup_git_directory();
- if (p->option & USE_PAGER)
- setup_pager();
- if (p->option & NEED_WORK_TREE)
- setup_work_tree();
-
- trace_argv_printf(argv, argc, "trace: built-in: git");
-
- status = p->fn(argc, argv, prefix);
- if (status)
- return status & 0xff;
-
- /* Somebody closed stdout? */
- if (fstat(fileno(stdout), &st))
- return 0;
- /* Ignore write errors for pipes and sockets.. */
- if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))
- return 0;
-
- /* Check for ENOSPC and EIO errors.. */
- if (fflush(stdout))
- die("write failure on standard output: %s", strerror(errno));
- if (ferror(stdout))
- die("unknown write failure on standard output");
- if (fclose(stdout))
- die("close failed on standard output: %s", strerror(errno));
- return 0;
-}
-
-static void handle_internal_command(int argc, const char **argv)
-{
- const char *cmd = argv[0];
- static struct cmd_struct commands[] = {
- { "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
- { "annotate", cmd_annotate, RUN_SETUP },
- { "apply", cmd_apply },
- { "archive", cmd_archive },
- { "blame", cmd_blame, RUN_SETUP },
- { "branch", cmd_branch, RUN_SETUP },
- { "bundle", cmd_bundle },
- { "cat-file", cmd_cat_file, RUN_SETUP },
- { "checkout-index", cmd_checkout_index,
- RUN_SETUP | NEED_WORK_TREE},
- { "check-ref-format", cmd_check_ref_format },
- { "check-attr", cmd_check_attr, RUN_SETUP | NEED_WORK_TREE },
- { "cherry", cmd_cherry, RUN_SETUP },
- { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
- { "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE },
- { "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
- { "commit-tree", cmd_commit_tree, RUN_SETUP },
- { "config", cmd_config },
- { "count-objects", cmd_count_objects, RUN_SETUP },
- { "describe", cmd_describe, RUN_SETUP },
- { "diff", cmd_diff },
- { "diff-files", cmd_diff_files },
- { "diff-index", cmd_diff_index, RUN_SETUP },
- { "diff-tree", cmd_diff_tree, RUN_SETUP },
- { "fast-export", cmd_fast_export, RUN_SETUP },
- { "fetch", cmd_fetch, RUN_SETUP },
- { "fetch-pack", cmd_fetch_pack, RUN_SETUP },
- { "fetch--tool", cmd_fetch__tool, RUN_SETUP },
- { "fmt", cmd_fmt },
- { "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
- { "for-each-ref", cmd_for_each_ref, RUN_SETUP },
- { "format-patch", cmd_format_patch, RUN_SETUP },
- { "fsck", cmd_fsck, RUN_SETUP },
- { "fsck-objects", cmd_fsck, RUN_SETUP },
- { "gc", cmd_gc, RUN_SETUP },
- { "get-tar-commit-id", cmd_get_tar_commit_id },
- { "grep", cmd_grep, RUN_SETUP | USE_PAGER },
- { "help", cmd_help },
-#ifndef NO_CURL
- { "http-fetch", cmd_http_fetch, RUN_SETUP },
-#endif
- { "init", cmd_init_db },
- { "init-db", cmd_init_db },
- { "log", cmd_log, RUN_SETUP | USE_PAGER },
- { "ls-files", cmd_ls_files, RUN_SETUP },
- { "ls-tree", cmd_ls_tree, RUN_SETUP },
- { "ls-remote", cmd_ls_remote },
- { "mailinfo", cmd_mailinfo },
- { "mailsplit", cmd_mailsplit },
- { "merge-base", cmd_merge_base, RUN_SETUP },
- { "merge-file", cmd_merge_file },
- { "merge-ours", cmd_merge_ours, RUN_SETUP },
- { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
- { "name-rev", cmd_name_rev, RUN_SETUP },
- { "pack-objects", cmd_pack_objects, RUN_SETUP },
- { "peek-remote", cmd_ls_remote },
- { "pickaxe", cmd_blame, RUN_SETUP },
- { "prune", cmd_prune, RUN_SETUP },
- { "prune-packed", cmd_prune_packed, RUN_SETUP },
- { "push", cmd_push, RUN_SETUP },
- { "read-tree", cmd_read_tree, RUN_SETUP },
- { "reflog", cmd_reflog, RUN_SETUP },
- { "repo-config", cmd_config },
- { "rerere", cmd_rerere, RUN_SETUP },
- { "reset", cmd_reset, RUN_SETUP },
- { "rev-list", cmd_rev_list, RUN_SETUP },
- { "rev-parse", cmd_rev_parse },
- { "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
- { "rm", cmd_rm, RUN_SETUP },
- { "send-pack", cmd_send_pack, RUN_SETUP },
- { "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER },
- { "show-branch", cmd_show_branch, RUN_SETUP },
- { "show", cmd_show, RUN_SETUP | USE_PAGER },
- { "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
- { "stripspace", cmd_stripspace },
- { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
- { "tag", cmd_tag, RUN_SETUP },
- { "tar-tree", cmd_tar_tree },
- { "unpack-objects", cmd_unpack_objects, RUN_SETUP },
- { "update-index", cmd_update_index, RUN_SETUP },
- { "update-ref", cmd_update_ref, RUN_SETUP },
- { "upload-archive", cmd_upload_archive },
- { "verify-tag", cmd_verify_tag, RUN_SETUP },
- { "version", cmd_version },
- { "whatchanged", cmd_whatchanged, RUN_SETUP | USE_PAGER },
- { "write-tree", cmd_write_tree, RUN_SETUP },
- { "verify-pack", cmd_verify_pack },
- { "show-ref", cmd_show_ref, RUN_SETUP },
- { "pack-refs", cmd_pack_refs, RUN_SETUP },
- };
- int i;
-
- /* Turn "git cmd --help" into "git help cmd" */
- if (argc > 1 && !strcmp(argv[1], "--help")) {
- argv[1] = argv[0];
- argv[0] = cmd = "help";
- }
-
- for (i = 0; i < ARRAY_SIZE(commands); i++) {
- struct cmd_struct *p = commands+i;
- if (strcmp(p->cmd, cmd))
- continue;
- exit(run_command(p, argc, argv));
- }
-}
-
int main(int argc, const char **argv)
{
const char *cmd = argv[0] ? argv[0] : "git-help";
@@ -425,7 +259,7 @@ int main(int argc, const char **argv)
if (!prefixcmp(cmd, "git-")) {
cmd += 4;
argv[0] = cmd;
- handle_internal_command(argc, argv);
+ execv_git_builtin(argv);
die("cannot handle %s internally", cmd);
}
@@ -453,10 +287,6 @@ int main(int argc, const char **argv)
setup_path(cmd_path);
while (1) {
- /* See if it's an internal command */
- handle_internal_command(argc, argv);
-
- /* .. then try the external ones */
execv_git_cmd(argv);
/* It could be an alias -- this works around the insanity
--
1.5.3.6.2112.ge2263
^ permalink raw reply related
* [PATCH 2/3] Include the objects needed for the builtin functions into libgit.a
From: Johannes Schindelin @ 2007-12-02 2:54 UTC (permalink / raw)
To: Junio C Hamano
Cc: Eyvind Bernhardsen, Nicolas Pitre, Nguyen Thai Ngoc Duy,
Jan Hudec, git
In-Reply-To: <Pine.LNX.4.64.0712020146240.27959@racer.site>
For the upcoming change in execv_git_cmd() to call builtin functions
directly, it is necessary to be able to access the builtins, so
move the corresponding objects into libgit.a.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
Makefile | 14 +++++++++-----
1 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/Makefile b/Makefile
index f000a5e..f9a62eb 100644
--- a/Makefile
+++ b/Makefile
@@ -314,7 +314,8 @@ LIB_OBJS = \
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
- transport.o bundle.o walker.o parse-options.o
+ transport.o bundle.o walker.o parse-options.o \
+ $(BUILTIN_OBJS)
BUILTIN_OBJS = \
builtin-add.o \
@@ -785,12 +786,12 @@ strip: $(PROGRAMS) git$X
$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
git.o: git.c common-cmds.h GIT-CFLAGS
- $(QUIET_CC)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
+ $(QUIET_CC)$(CC) \
$(ALL_CFLAGS) -c $(filter %.c,$^)
git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \
- $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
+ $(ALL_LDFLAGS) $(LIBS)
help.o: common-cmds.h
@@ -894,7 +895,10 @@ git.o git.spec \
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
exec_cmd.o: exec_cmd.c GIT-CFLAGS
- $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' $<
+ $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) \
+ -DGIT_EXEC_PATH='"$(gitexecdir_SQ)"' \
+ -DGIT_VERSION='"$(GIT_VERSION)"' \
+ $<
builtin-init-db.o: builtin-init-db.c GIT-CFLAGS
$(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
@@ -920,7 +924,7 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
-$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
+$(LIB_OBJS): $(LIB_H)
$(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
builtin-revert.o builtin-runstatus.o wt-status.o: wt-status.h
--
1.5.3.6.2112.ge2263
^ permalink raw reply related
* [PATCH 1/3] Introduce release_all_objects()
From: Johannes Schindelin @ 2007-12-02 2:54 UTC (permalink / raw)
To: Junio C Hamano
Cc: Eyvind Bernhardsen, Nicolas Pitre, Nguyen Thai Ngoc Duy,
Jan Hudec, git
In-Reply-To: <Pine.LNX.4.64.0712020146240.27959@racer.site>
The new function release_all_objects() can be used to flush the object
cache. This will be needed for the upcoming change in execv_git_cmd(),
which should call the builtin functions directly instead of calling
execvp().
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
Guess how surprised I was when "free(commit);" would work the
first time, but not the second...
ATM I use an ugly way to cope with the static "nr" variables
in alloc.c: I just do not free() the last block.
It might be a better idea to refactor the (quite ugly) code in
alloc.c to have global structures a la
#define BLOCKING 1024
struct object_block {
size_t struct_size;
int nr;
/* first (uint32_t *) is pointer to previous block */
void *block;
};
static void *alloc_node(struct object_block *block)
{
if (!block || block->nr >= BLOCKING) {
void *next = xmalloc(sizeof(void *)
+ BLOCKING * block->struct_size);
*(void **)next = block->block;
block->block = next;
block->nr = 0;
}
return block->block + sizeof(void *)
+ block->struct_size * block->nr++;
}
static void release_nodes(struct object_block *block)
{
while (block->block) {
void *previous = *(void **)block->block;
free(block->block);
block->block = previous;
}
block->nr = 0; /* not strictly necessary */
}
#define DEFINE_ALLOCATOR(type) \
static object_block type##s = { sizeof(struct type) }; \
struct type *alloc_##type##_node(void) \
{ \
return alloc_node(&type##s); \
}
DEFINE_ALLOCATOR(object)
DEFINE_ALLOCATOR(blob)
DEFINE_ALLOCATOR(tree)
DEFINE_ALLOCATOR(commit)
DEFINE_ALLOCATOR(tag)
but I am waaay too tired to brush this up, test it and submit it
(hint, hint).
alloc.c | 31 ++++++++++++++++++++++++++++++-
blob.c | 3 +++
blob.h | 1 +
cache.h | 6 ++++++
commit.c | 8 ++++++++
commit.h | 2 ++
object.c | 24 ++++++++++++++++++++++++
object.h | 2 ++
tag.c | 8 ++++++++
tag.h | 2 ++
tree.c | 6 ++++++
tree.h | 1 +
12 files changed, 93 insertions(+), 1 deletions(-)
diff --git a/alloc.c b/alloc.c
index 216c23a..8c5e5e0 100644
--- a/alloc.c
+++ b/alloc.c
@@ -20,6 +20,7 @@
#define DEFINE_ALLOCATOR(name, type) \
static unsigned int name##_allocs; \
+static void *last_alloced_##name; \
void *alloc_##name##_node(void) \
{ \
static int nr; \
@@ -28,13 +29,32 @@ void *alloc_##name##_node(void) \
\
if (!nr) { \
nr = BLOCKING; \
- block = xmalloc(BLOCKING * sizeof(type)); \
+ struct { \
+ void *previous; \
+ type block[BLOCKING]; \
+ } *buf = xmalloc(sizeof(*buf)); \
+ buf->previous = last_alloced_##name; \
+ last_alloced_##name = buf; \
+ block = buf->block; \
} \
nr--; \
name##_allocs++; \
ret = block++; \
memset(ret, 0, sizeof(type)); \
return ret; \
+} \
+ \
+void release_all_##name##_nodes(void) \
+{ \
+ void *buf = last_alloced_##name; \
+ if (!buf) \
+ return; \
+ buf = *(void **)buf; \
+ while (buf) { \
+ void *next = *(void **)buf; \
+ free(buf); \
+ buf = next; \
+ } \
}
union any_object {
@@ -74,3 +94,12 @@ void alloc_report(void)
REPORT(commit);
REPORT(tag);
}
+
+void release_all_nodes(void)
+{
+ release_all_blob_nodes();
+ release_all_tree_nodes();
+ release_all_commit_nodes();
+ release_all_tag_nodes();
+ release_all_object_nodes();
+}
diff --git a/blob.c b/blob.c
index bd7d078..63756e6 100644
--- a/blob.c
+++ b/blob.c
@@ -18,6 +18,9 @@ struct blob *lookup_blob(const unsigned char *sha1)
return (struct blob *) obj;
}
+void release_blob(struct blob *blob) {
+}
+
int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size)
{
item->object.parsed = 1;
diff --git a/blob.h b/blob.h
index ea5d9e9..7560671 100644
--- a/blob.h
+++ b/blob.h
@@ -10,6 +10,7 @@ struct blob {
};
struct blob *lookup_blob(const unsigned char *sha1);
+void release_blob(struct blob *blob);
int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size);
diff --git a/cache.h b/cache.h
index 4e59646..cc50f1c 100644
--- a/cache.h
+++ b/cache.h
@@ -613,6 +613,12 @@ extern void *alloc_tree_node(void);
extern void *alloc_commit_node(void);
extern void *alloc_tag_node(void);
extern void *alloc_object_node(void);
+extern void release_all_blob_nodes(void);
+extern void release_all_tree_nodes(void);
+extern void release_all_commit_nodes(void);
+extern void release_all_tag_nodes(void);
+extern void release_all_object_nodes(void);
+extern void release_all_nodes(void);
extern void alloc_report(void);
/* trace.c */
diff --git a/commit.c b/commit.c
index f074811..59c2236 100644
--- a/commit.c
+++ b/commit.c
@@ -48,6 +48,14 @@ struct commit *lookup_commit(const unsigned char *sha1)
return check_commit(obj, sha1, 0);
}
+void release_commit(struct commit *commit)
+{
+ if (commit->parents)
+ free_commit_list(commit->parents);
+ if (commit->buffer)
+ free(commit->buffer);
+}
+
static unsigned long parse_commit_date(const char *buf)
{
unsigned long date;
diff --git a/commit.h b/commit.h
index 10e2b5d..363b9fb 100644
--- a/commit.h
+++ b/commit.h
@@ -21,6 +21,7 @@ struct commit {
char *buffer;
};
+
extern int save_commit_buffer;
extern const char *commit_type;
@@ -35,6 +36,7 @@ struct commit *lookup_commit(const unsigned char *sha1);
struct commit *lookup_commit_reference(const unsigned char *sha1);
struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
int quiet);
+void release_commit(struct commit *commit);
int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size);
diff --git a/object.c b/object.c
index 16793d9..f217122 100644
--- a/object.c
+++ b/object.c
@@ -192,6 +192,30 @@ struct object *parse_object(const unsigned char *sha1)
return NULL;
}
+void release_all_objects(void)
+{
+ int i;
+ for (i = 0; i < obj_hash_size; i++)
+ if (obj_hash[i]) {
+ switch (obj_hash[i]->type) {
+ case OBJ_BLOB:
+ release_blob((struct blob *)obj_hash[i]);
+ break;
+ case OBJ_COMMIT:
+ release_commit((struct commit *)obj_hash[i]);
+ break;
+ /*case OBJ_TREE:
+ release_tree((struct tree *)obj_hash[i]);
+ break;
+ case OBJ_TAG:
+ release_tag((struct tag *)obj_hash[i]);
+ break;*/
+ }
+ obj_hash[i] = NULL;
+ }
+ release_all_nodes();
+}
+
struct object_list *object_list_insert(struct object *item,
struct object_list **list_p)
{
diff --git a/object.h b/object.h
index 397bbfa..ad6184c 100644
--- a/object.h
+++ b/object.h
@@ -44,6 +44,8 @@ extern unsigned int get_max_object_index(void);
extern struct object *get_indexed_object(unsigned int);
extern struct object_refs *lookup_object_refs(struct object *);
+extern void release_all_objects(void);
+
/** Internal only **/
struct object *lookup_object(const unsigned char *sha1);
diff --git a/tag.c b/tag.c
index f62bcdd..8bc6840 100644
--- a/tag.c
+++ b/tag.c
@@ -33,6 +33,14 @@ struct tag *lookup_tag(const unsigned char *sha1)
return (struct tag *) obj;
}
+void release_tag(struct tag *tag)
+{
+ if (tag->tag)
+ free(tag->tag);
+ if (tag->signature)
+ free(tag->signature);
+}
+
int parse_tag_buffer(struct tag *item, void *data, unsigned long size)
{
int typelen, taglen;
diff --git a/tag.h b/tag.h
index 7a0cb00..fbc6048 100644
--- a/tag.h
+++ b/tag.h
@@ -12,6 +12,8 @@ struct tag {
char *signature; /* not actually implemented */
};
+void release_tag(struct tag *tag);
+
extern struct tag *lookup_tag(const unsigned char *sha1);
extern int parse_tag_buffer(struct tag *item, void *data, unsigned long size);
extern int parse_tag(struct tag *item);
diff --git a/tree.c b/tree.c
index 8c0819f..ee99bc6 100644
--- a/tree.c
+++ b/tree.c
@@ -202,6 +202,12 @@ struct tree *lookup_tree(const unsigned char *sha1)
return (struct tree *) obj;
}
+void release_tree(struct tree *tree)
+{
+ if (tree->buffer)
+ free(tree->buffer);
+}
+
/*
* NOTE! Tree refs to external git repositories
* (ie gitlinks) do not count as real references.
diff --git a/tree.h b/tree.h
index dd25c53..f8372a2 100644
--- a/tree.h
+++ b/tree.h
@@ -12,6 +12,7 @@ struct tree {
};
struct tree *lookup_tree(const unsigned char *sha1);
+void release_tree(struct tree *tree);
int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size);
--
1.5.3.6.2112.ge2263
^ permalink raw reply related
* [PATCH 0/3] Call builtin functions directly, was Re: [PATCH] transport.c: call dash-less form of receive-pack and upload-pack on remote
From: Johannes Schindelin @ 2007-12-02 2:52 UTC (permalink / raw)
To: Junio C Hamano
Cc: Eyvind Bernhardsen, Nicolas Pitre, Nguyen Thai Ngoc Duy,
Jan Hudec, git
In-Reply-To: <Pine.LNX.4.64.0712012314190.27959@racer.site>
Hi,
On Sat, 1 Dec 2007, Johannes Schindelin wrote:
> On Sat, 1 Dec 2007, Johannes Schindelin wrote:
>
> > Will investigate right now,
>
> The problem is that "git <command>" will call execv_git_cmd() for
> non-builtins, which in turn will execute "git <command>", ... ad
> infinitum.
Okay, I bit the apple and tried to move the builtins into the library, and
rename handle_internal_command into execv_git_builtin(), moving it into
exec-cmd.c.
Big mistake.
Why? Because there is at least one caller, git-bundle, which relies on
execv_git_cmd() _not_ reusing all those "nice" one-shot static variables,
like for example the object hashmap and the objects themselves.
Now, it seems that we can get away for the moment with just introducing an
object release mechanism and calling that in execv_git_builtin() before
calling a builtin function, because the existing callers do not rely on
more than a cleanup of the objects.
But it is hairy, since it is such an essential part of git. And since I
was utterly tired while preparing this patch series. So I suggest maybe
putting this into pu, but no further for the moment. I will use the
patched git in the next days, though, to catch breakages (hopefully).
Ciao,
Dscho
^ permalink raw reply
* Re: git pack-objects input list
From: Nicolas Pitre @ 2007-12-02 2:23 UTC (permalink / raw)
To: Mike Hommey; +Cc: Linus Torvalds, git
In-Reply-To: <20071201223849.GA15110@glandium.org>
On Sat, 1 Dec 2007, Mike Hommey wrote:
> On Sat, Dec 01, 2007 at 09:49:00AM -0800, Linus Torvalds wrote:
> > Hope that clarified something.
>
> Thanks, that helped me understand my observations when trying to pack
> with and without file names in pack-objects input on different kind of
> datasets, where some would be best packed with and others would be without.
>
> I'll try to add some words about the pack-objects input format in the
> documentation. I don't know if it's worth adding information about the
> packing process itself in the manual page. Or maybe that should be added
> to a more technical document about git (a bit like "git for computer
> scientists")
Look at Documentation/technical/ for existing technically oriented
documents. The pack format and packing heuristics have documents of
their own already. If you feel like adding more documentation there
please just go ahead.
Nicolas
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox