Git development
 help / color / mirror / Atom feed
* Re: [StGit PATCH] Fixed default install location
From: Catalin Marinas @ 2008-07-25 21:46 UTC (permalink / raw)
  To: Daniel White; +Cc: git
In-Reply-To: <20080724202031.55dec8e8@whitehouse.id.au>

2008/7/24 Daniel White <daniel@whitehouse.id.au>:
> Originally broken by addition of Debian package support.
>
> Signed-off-by: Daniel White <daniel@whitehouse.id.au>
> ---
>
> The default installation direction is actually /usr at present despite
> what 'INSTALL' says.
>
> The 'debian/rules' makefile specifies the prefix as /usr so doesn't
> seem to depend on this. I've tested the resulting debian package and
> everything is still installed correctly under /usr.

I also use "python setup.py bdist_rpm" when releasing, I think it will
get confused by a different prefix.

-- 
Catalin

^ permalink raw reply

* Re: git-scm.com
From: Scott Chacon @ 2008-07-25 21:46 UTC (permalink / raw)
  To: git
In-Reply-To: <bd6139dc0807251420x32e65e73o8db5d77c8b841947@mail.gmail.com>

I mean to have the new documentation I'm beginning be the
'eye-catcher' on that page eventually.  Not because it's done by me,
but because it will be open and I want to encourage people to
contribute to it (we must make it perfect, after all) :)  However, the
big thing is that I couldn't think of a _single_ resource that I would
want to point people at.  I tried to split everything up
categorically, but I don't know what you're looking for being there
exactly.  Thanks for the feedback, though, I'll see what I can do.

As for my own plug, I feel kinda bad about that, but I have gotten a
lot of feedback that it's a useful resource and I thought by
separating it out into a 'books' section, I had cleanly distinguished
between the corporate sellouts and everyone else :)  I have Git Magic
in the Tutorials section, including a nice plug for it and a link to
it's source on Github - if it were an e-book (had a pdf version and a
cover) I would happily put it over there.  I would like, however, to
keep the downloadable resources seperate from the free online
resources (though now that I think about it, I should probably put
"Git from the Bottom Up" pdf up there somewhere...).  I want people to
know they have to shell out money for those greedy bastards projects,
though.  There will be an O'Reilly book soon, and I'll put that up,
too. If you have other resources that you think are really good, let
me know so I can add them.

Scott

On Fri, Jul 25, 2008 at 2:20 PM, Sverre Rabbelier <alturin@gmail.com> wrote:
> On Fri, Jul 25, 2008 at 19:35, Scott Chacon <schacon@gmail.com> wrote:
>> A followup on the post I did a few days ago about Git documentation.
>> I forked Petr's git.or.cz site and put up a version that I think is a
>> bit more accessible and newbie-friendly at git-scm.com.  I had meant
>> to discuss this with Petr before posting it to you all, but I
>> published a blog post that got a bit more attention than I expected,
>> and I didn't want you all to think I didn't care about your opinion,
>> as some have already accused me of.
>
> I had a looksie at the site and I think the documentation section [0]
> could use some TLC. It might be because it's getting late, but there's
> not really any 'eye catchers', no "CLICK ME!" link for someone
> browsing around looking for Documentation. In order to find what you
> want you have to read -a lot- of the page, which I think is a sign
> that the page would do well with some TLC ;).
> Now I'll admit that the git.or.cz version [1] is a lot worse, but with
> this being an attempt to make it a lot more newbie friendly...
>
> [0] http://git-scm.com/documentation
> [1] http://git.or.cz/gitwiki/GitDocumentation
>
> PS: I think you forgot the </shameless plug> when you did put up your
> own e-book in the books section but did not put "Git Magic" there ;).
>
> --
> Cheers,
>
> Sverre Rabbelier
>

^ permalink raw reply

* Re: [PATCH] git-reset: Let -q hush "locally modified" messages
From: Stephan Beyer @ 2008-07-25 21:38 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Carlos Rica, Johannes Schindelin, git
In-Reply-To: <7vwsj9r722.fsf@gitster.siamese.dyndns.org>

Hi,

Junio C Hamano wrote:
> Stephan Beyer <s-beyer@gmx.net> writes:
> 
> > git reset -q makes reset more quiet, but "locally modified" messages are
> > still shown.  This patch makes them disappear, too.
> 
> Files being "locally modified" is not and error, so I think it is in line
> with the spirit of what -q is meant to do.
> 
> It is an interface change, though.

Yes, as "needs update" -> "locally modified" was.

However, scripts, that rely on filenames when doing -q (whyever),
will break.

So should I stick to "git reset -q foo >/dev/null" if I want it quiet,
or is there some chance of inclusion?

Regards,
  Stephan

-- 
Stephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F

^ permalink raw reply

* Re: [StGit PATCH] Test that we can add a new file to a non-topmost patch with refresh -p
From: Catalin Marinas @ 2008-07-25 21:37 UTC (permalink / raw)
  To: Karl Hasselström; +Cc: git, Jon Smirl
In-Reply-To: <20080722071438.GA16807@diana.vm.bytemark.co.uk>

2008/7/22 Karl Hasselström <kha@treskal.com>:
> On 2008-07-21 23:01:17 +0100, Catalin Marinas wrote:
>
>> I don't think we should spend time on fixing the current code as you
>> already have a new implementation. Maybe we could add a simple test
>> and refuse refreshing other than the topmost patch in case of files
>> added to the index.
>
> Yes, I guess that's OK. Hmm, how do we check that cheaply?

In the stable branch, we already call git.check_status() in the
refresh implementation, so it's pretty cheap to test.

-- 
Catalin

^ permalink raw reply

* Re: git-scm.com
From: Johan Herland @ 2008-07-25 21:36 UTC (permalink / raw)
  To: Scott Chacon; +Cc: git
In-Reply-To: <d411cc4a0807251035i7aed2ec9wef7e8f1b3ae4c585@mail.gmail.com>

On Friday 25 July 2008, Scott Chacon wrote:
> Hey all,
>
> A followup on the post I did a few days ago about Git documentation.
> I forked Petr's git.or.cz site and put up a version that I think is a
> bit more accessible and newbie-friendly at git-scm.com.  I had meant
> to discuss this with Petr before posting it to you all, but I
> published a blog post that got a bit more attention than I expected,
> and I didn't want you all to think I didn't care about your opinion,
> as some have already accused me of.
>
> Anyhow, I'm discussing with Petr about where we want to go from here -
> what changes he'd like to make, etc, but I obviously value your
> opinion as well, so please let me know what you think.  The content
> has barely changed, it's really just a usability overhaul.  I want to
> make sure that whatever someone is looking for (especially someone
> new), they can find in a few clicks and a few seconds.

Thanks for the update. Looks good.

Minor niggle: On the download page, in the Binaries table, Cygwin is listed 
before msysGit. I'm under the impression that msysGit is what we really 
want to be pushing on Windows (it's faster, smaller, and less strange to 
Windows-people (i.e. less Unix-y)), so you might want to switch the order 
around.


Have fun!

...Johan

-- 
Johan Herland, <johan@herland.net>
www.herland.net

^ permalink raw reply

* Re: [PATCH] git-reset: Let -q hush "locally modified" messages
From: Junio C Hamano @ 2008-07-25 21:24 UTC (permalink / raw)
  To: Stephan Beyer; +Cc: Carlos Rica, Johannes Schindelin, git
In-Reply-To: <1217018948-32475-1-git-send-email-s-beyer@gmx.net>

Stephan Beyer <s-beyer@gmx.net> writes:

> git reset -q makes reset more quiet, but "locally modified" messages are
> still shown.  This patch makes them disappear, too.

Files being "locally modified" is not and error, so I think it is in line
with the spirit of what -q is meant to do.

It is an interface change, though.

^ permalink raw reply

* Re: git-scm.com
From: Sverre Rabbelier @ 2008-07-25 21:20 UTC (permalink / raw)
  To: Scott Chacon; +Cc: git
In-Reply-To: <d411cc4a0807251035i7aed2ec9wef7e8f1b3ae4c585@mail.gmail.com>

On Fri, Jul 25, 2008 at 19:35, Scott Chacon <schacon@gmail.com> wrote:
> A followup on the post I did a few days ago about Git documentation.
> I forked Petr's git.or.cz site and put up a version that I think is a
> bit more accessible and newbie-friendly at git-scm.com.  I had meant
> to discuss this with Petr before posting it to you all, but I
> published a blog post that got a bit more attention than I expected,
> and I didn't want you all to think I didn't care about your opinion,
> as some have already accused me of.

I had a looksie at the site and I think the documentation section [0]
could use some TLC. It might be because it's getting late, but there's
not really any 'eye catchers', no "CLICK ME!" link for someone
browsing around looking for Documentation. In order to find what you
want you have to read -a lot- of the page, which I think is a sign
that the page would do well with some TLC ;).
Now I'll admit that the git.or.cz version [1] is a lot worse, but with
this being an attempt to make it a lot more newbie friendly...

[0] http://git-scm.com/documentation
[1] http://git.or.cz/gitwiki/GitDocumentation

PS: I think you forgot the </shameless plug> when you did put up your
own e-book in the books section but did not put "Git Magic" there ;).

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: [PATCH] Respect crlf attribute even if core.autocrlf has not been set
From: Eyvind Bernhardsen @ 2008-07-25 21:05 UTC (permalink / raw)
  To: Dmitry Potapov
  Cc: Johannes Schindelin, Avery Pennarun, Joshua Jensen,
	Junio C Hamano, git
In-Reply-To: <20080725140142.GB2925@dpotapov.dyndns.org>

On 25. juli. 2008, at 16.01, Dmitry Potapov wrote:

> On Fri, Jul 25, 2008 at 02:30:16PM +0200, Eyvind Bernhardsen wrote:
>>
>> Fair enough.  Did you read the rest of my email to see when I think
>> Git should mess with content?  I've thought about it, and being able
>> to do stuff like this in .gitattributes would work for me:
>>
>> * eol=auto
>> *.bat eol=crlf
>> Makefile eol=lf
>> bin/magic-binary eol=none
>>
>> I.e. "detect line endings and do CRLF->LF conversion on all files
>> except *.bat (*->CRLF), Makefile (*->LF) and bin/magic-binary (do
>> nothing)".
>
> I suppose "* eol=auto" means to convert CRLF->LF on checkin and
> LF->native on checkout?

That's the idea, yes, with "native" being configurable.

> Also, perhaps, it should be also possible to explicitly specify:
> *.txt eol=native
> which is the same as 'auto' but without guessing whether it is text
> or not.

Yes!  Good catch, that needs to be possible.

>> ...but "core.autocrlf" is not versioned and applies to _all_
>> repositories, and anyone who doesn't have the correct setting can  
>> mess
>> the repository up.
>
> I think the real issue here is not as much about being or not being
> versioned, but about forcing and not forcing anything on users.

The reason I want versioning is to fix the problem of enforcing  
normalised line endings in repositories with checked-in CRLFs; I'm not  
sure how to solve it any other way, but I'm open to suggestions.

> If we had core.autocrlf=input as default then clueless users will not
> checkin files with the incorrect ending. But there is an objection to
> that -- you penalize those who always have good endings. And even the
> fact that is merely default value that you can easily change to false
> does not convince everyone.

That is an excellent argument for why setting "autocrlf=true" by  
default on Windows was a bad idea.  Thanks! :)

> The same can be said about your
> * eol=auto
> It forces conversion on everyone, even on those who do not need it.
> Of course, you can say those projects that do not have the problem  
> with
> clueless users putting text files with incorrect end-of-lines will not
> have lines like that in their .gitattribute. Yet, if I participate in
> that project, why do I have to pay the price for this conversion just
> because someone stupid can mess up line-endings?

It's about correctness: if the repository isn't supposed to have CRs  
in any text files, that needs to be enforced.  You might not be  
stupid, but that doesn't mean you won't ever take a file that was  
created on Windows and commit it to the repository on Linux.  If the  
tool used to create the file was CR-damaged, there goes the  
repository's LF-only policy.

As you say, the reason I want the setting to be per-repository is that  
I don't think the cost is worthwhile for every repository.  The case  
where it _is_ worthwhile is when the repository will be shared between  
Windows users and Linux users, and the Windows users want CRLFs in  
their working directories.  I think it's worthwhile to actually make  
Git work right in that case.

As a side note, there's a lot of complaining about the cost of  
enforcing LF-only input, but I can't remember seeing any actual  
numbers.  Is it really that bad?

>> There's also no way of saying "this file should
>> have LF line endings, even with autocrlf=true".
>
> Actually, there is
>
> *.sh crlf=input
>
> i.e. I want my shell files to have LF even I normally use CRLF for
> all other files (on Windows).

Won't they still be converted to CRLF on checkout when autocrlf=true  
on Windows?

>> One problem is that the autocrlf setting mixes "I want LF only in my
>> repositories" and "I like to have CRLFs in my working directory" into
>> one config variable.  Instead, I'd like to have a config setting that
>> specifies which line ending form I prefer: "when a text file is  
>> marked
>> eol=auto, convert LFs to CRLFs on checkout".
>
> Following your style above, I believe it should be defined as
> native-eol=crlf

Yes, that sounds right.

> but there are people who do not want to pay any price for conversion.
> Currently, "core.autocrlf=false" means to do nothing about end-of- 
> lines,
> and even to ignore setting in .gitattributes. Should it be possible to
> disable *any* conversion on checkin and checkout? Should this be that
> value be the default, which most users use?

Well, there's no reason why Git repositories used only on Windows  
machines shouldn't store CRLFs, so why should all msysgit users pay  
the cost on every checkin _and_ checkout?

This is the reason the setting needs to be a per-repository policy and  
not a user configuration; users should not be able to configure away  
correctness, but they shouldn't be penalised unnecessarily for it,  
either.
-- 
Eyvind Bernhardsen

^ permalink raw reply

* Re: [PATCH] bash completion: Add completion for 'git help'
From: Junio C Hamano @ 2008-07-25 21:02 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Lee Marlow, git
In-Reply-To: <20080725204051.GB23202@spearce.org>

Thanks for an Ack, but personally I do not think the completion of "all
commands" is worth it.

I've been busy with day-job for the past few days, and haven't had chance
to push things out today, but FYI here is what I already have on 'master'
privately, relative to what have already been pushed out.

  Documentation: clarify how to disable elements in core.whitespace (Junio C Hamano)
  Makefile: fix shell quoting (Junio C Hamano)
  tests: propagate $(TAR) down from the toplevel Makefile (Junio C Hamano)
  index-pack.c: correctly initialize appended objects (Björn Steinbrink)
  send-email: find body-encoding correctly (Peter Valdemar Mørch)
  document that git-tag can tag more than heads (Jonathan Nieder)
  perl/Makefile: update NO_PERL_MAKEMAKER section (Brandon Casey)
  bash: offer only paths after '--' for 'git checkout' (SZEDER Gábor)
  checkout: mention '--' in the docs (SZEDER Gábor)
  git-checkout: improve error messages, detect ambiguities. (Pierre Habouzit)
  update test case to protect am --skip behaviour (Olivier Marin)
  Teach fsck and prune about the new location of temporary objects (Brandon Casey)
  git-checkout: fix command line parsing. (Pierre Habouzit)

At this point immediately before -rc1, I am giving much higher precedence
to real fixes than clean-ups, "use parse-opt", or new features.  Please do
not get alarmed if your non-fix patches are left unresponded for a while.

BTW, has anybody taken a look at this one?

  Subject: BUG: fetch incorrect interpretation of globing patterns in refspecs
  Date: Thu, 24 Jul 2008 09:07:21 +0200
  Message-ID: <71295b5a0807240007k246973abj1897895d0d67bb6c@mail.gmail.com>

If not, I think I probably need to take a look at this, reproducing and
possibly fixing, before applying non-fix patches.

^ permalink raw reply

* [PATCH] git-reset: Let -q hush "locally modified" messages
From: Stephan Beyer @ 2008-07-25 20:49 UTC (permalink / raw)
  To: Carlos Rica, Johannes Schindelin; +Cc: git, Stephan Beyer

git reset -q makes reset more quiet, but "locally modified" messages are
still shown.  This patch makes them disappear, too.

Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---

Hi,

I don't know if this was actually a bug or a feature.
I considered this a bug, so here's a patch.

Regards,
  Stephan


 builtin-reset.c |   15 +++++++++------
 1 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/builtin-reset.c b/builtin-reset.c
index 4d246c3..c24c219 100644
--- a/builtin-reset.c
+++ b/builtin-reset.c
@@ -85,7 +85,7 @@ static void print_new_head_line(struct commit *commit)
 		printf("\n");
 }
 
-static int update_index_refresh(int fd, struct lock_file *index_lock)
+static int update_index_refresh(int fd, struct lock_file *index_lock, int flags)
 {
 	int result;
 
@@ -96,7 +96,8 @@ static int update_index_refresh(int fd, struct lock_file *index_lock)
 
 	if (read_cache() < 0)
 		return error("Could not read index");
-	result = refresh_cache(REFRESH_SAY_CHANGED) ? 1 : 0;
+
+	result = refresh_cache(flags) ? 1 : 0;
 	if (write_cache(fd, active_cache, active_nr) ||
 			commit_locked_index(index_lock))
 		return error ("Could not refresh index");
@@ -128,7 +129,7 @@ static void update_index_from_diff(struct diff_queue_struct *q,
 }
 
 static int read_from_tree(const char *prefix, const char **argv,
-		unsigned char *tree_sha1)
+		unsigned char *tree_sha1, int refresh_flags)
 {
 	struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
 	int index_fd, index_was_discarded = 0;
@@ -152,7 +153,7 @@ static int read_from_tree(const char *prefix, const char **argv,
 	if (!index_was_discarded)
 		/* The index is still clobbered from do_diff_cache() */
 		discard_cache();
-	return update_index_refresh(index_fd, lock);
+	return update_index_refresh(index_fd, lock, refresh_flags);
 }
 
 static void prepend_reflog_action(const char *action, char *buf, size_t size)
@@ -246,7 +247,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		else if (reset_type != NONE)
 			die("Cannot do %s reset with paths.",
 					reset_type_names[reset_type]);
-		return read_from_tree(prefix, argv + i, sha1);
+		return read_from_tree(prefix, argv + i, sha1,
+				quiet ? REFRESH_QUIET : REFRESH_SAY_CHANGED);
 	}
 	if (reset_type == NONE)
 		reset_type = MIXED; /* by default */
@@ -286,7 +288,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 	case SOFT: /* Nothing else to do. */
 		break;
 	case MIXED: /* Report what has not been updated. */
-		update_index_refresh(0, NULL);
+		update_index_refresh(0, NULL,
+				quiet ? REFRESH_QUIET : REFRESH_SAY_CHANGED);
 		break;
 	}
 
-- 
1.6.0.rc0.49.g3d2ce

^ permalink raw reply related

* Re: [PATCH] bash completion: Add completion for 'git help'
From: Shawn O. Pearce @ 2008-07-25 20:40 UTC (permalink / raw)
  To: Lee Marlow; +Cc: git
In-Reply-To: <1216858043-53646-1-git-send-email-lee.marlow@gmail.com>

Lee Marlow <lee.marlow@gmail.com> wrote:
> Renamed cached __git_commandlist to __git_porcelain_commandlist
> and added __git_all_commandlist that only filters out *--* helpers.
> Completions for 'git help' will use the __git_all_commandlist, while
> __git_porcelain_commandlist is used for git command completion.
> Users who actually read man pages may want to see help for plumbing
> commands.
> 
> Options added: --all --info --man --web
> 
> Signed-off-by: Lee Marlow <lee.marlow@gmail.com>

Acked-by: Shawn O. Pearce <spearce@spearce.org>

> This version fixes a small error in the __git_all_commands
...
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index 2edb341..f3bdea4 100755
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -349,10 +349,10 @@ __git_complete_revlist ()
>  	esac
>  }
>  
> -__git_commands ()
> +__git_all_commands ()
>  {
> -	if [ -n "$__git_commandlist" ]; then
> -		echo "$__git_commandlist"
> +	if [ -n "$__git_all_commandlist" ]; then
> +		echo "$__git_all_commandlist"
>  		return
>  	fi
>  	local i IFS=" "$'\n'
> @@ -360,6 +360,24 @@ __git_commands ()
>  	do
>  		case $i in
>  		*--*)             : helper pattern;;
> +		*) echo $i;;
> +		esac
> +	done
> +}
> +__git_all_commandlist=
> +__git_all_commandlist="$(__git_all_commands 2>/dev/null)"
> +
> +__git_porcelain_commands ()
> +{
> +	if [ -n "$__git_porcelain_commandlist" ]; then
> +		echo "$__git_porcelain_commandlist"
> +		return
> +	fi
> +	local i IFS=" "$'\n'
> +	for i in "help" $(__git_all_commands)
> +	do
> +		case $i in
> +		*--*)             : helper pattern;;
>  		applymbox)        : ask gittus;;
>  		applypatch)       : ask gittus;;
>  		archimport)       : import;;
> @@ -427,8 +445,8 @@ __git_commands ()
>  		esac
>  	done
>  }
> -__git_commandlist=
> -__git_commandlist="$(__git_commands 2>/dev/null)"
> +__git_porcelain_commandlist=
> +__git_porcelain_commandlist="$(__git_porcelain_commands 2>/dev/null)"
>  
>  __git_aliases ()
>  {
> @@ -767,6 +785,18 @@ _git_gc ()
>  	COMPREPLY=()
>  }
>  
> +_git_help ()
> +{
> +	local cur="${COMP_WORDS[COMP_CWORD]}"
> +	case "$cur" in
> +	--*)
> +		__gitcomp "--all --info --man --web"
> +		return
> +		;;
> +	esac
> +	__gitcomp "$(__git_all_commands)"
> +}
> +
>  _git_ls_remote ()
>  {
>  	__gitcomp "$(__git_remotes)"
> @@ -1369,7 +1399,8 @@ _git ()
>  		case "$i" in
>  		--git-dir=*) __git_dir="${i#--git-dir=}" ;;
>  		--bare)      __git_dir="." ;;
> -		--version|--help|-p|--paginate) ;;
> +		--version|-p|--paginate) ;;
> +		--help) command="help"; break ;;
>  		*) command="$i"; break ;;
>  		esac
>  		c=$((++c))
> @@ -1389,7 +1420,7 @@ _git ()
>  			--help
>  			"
>  			;;
> -		*)     __gitcomp "$(__git_commands) $(__git_aliases)" ;;
> +		*)     __gitcomp "$(__git_porcelain_commands) $(__git_aliases)" ;;
>  		esac
>  		return
>  	fi
> @@ -1414,6 +1445,7 @@ _git ()
>  	fetch)       _git_fetch ;;
>  	format-patch) _git_format_patch ;;
>  	gc)          _git_gc ;;
> +	help)        _git_help ;;
>  	log)         _git_log ;;
>  	ls-remote)   _git_ls_remote ;;
>  	ls-tree)     _git_ls_tree ;;

-- 
Shawn.

^ permalink raw reply

* Re: [PATCH] bash: offer only paths after '--' for 'git checkout'
From: Shawn O. Pearce @ 2008-07-25 20:34 UTC (permalink / raw)
  To: SZEDER GGGbor; +Cc: git, Pierre Habouzit, gitster
In-Reply-To: <1216813762-23511-2-git-send-email-szeder@ira.uka.de>

SZEDER GGGbor <szeder@ira.uka.de> wrote:
> Commit d773c631 (bash: offer only paths after '--', 2008-07-08) did the
> same for several other git commands, but 'git checkout' went unnoticed.
> 
> Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>

Acked-by: Shawn O. Pearce <spearce@spearce.org>

> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index 2edb341..9b51fda 100755
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -626,6 +626,8 @@ _git_bundle ()
>  
>  _git_checkout ()
>  {
> +	__git_has_doubledash && return
> +
>  	__gitcomp "$(__git_refs)"
>  }
>  

-- 
Shawn.

^ permalink raw reply

* Re: git rebase to move a batch of patches onto the current branch
From: Björn Steinbrink @ 2008-07-25 20:31 UTC (permalink / raw)
  To: Avery Pennarun; +Cc: Git Mailing List
In-Reply-To: <32541b130807241257j7820a591if8ca01c66bbcd6b2@mail.gmail.com>

On 2008.07.24 15:57:03 -0400, Avery Pennarun wrote:
> Hi,
> 
> I often find myself being on a branch and wanting to do the equivalent
> of a series of cherry-picks from another branch into the current one.
> Unfortunately, "git cherry-pick" only does one patch at a time (which
> is very tedious), and "git rebase", which is much less tedious to use,
> seems to specializing in applying your current branch on top of
> another branch, not the other way around.
> 
> Currently I do something like this:
> 
>       git checkout -b tmp branch_with_interesting_stuff~5
>       git rebase --onto mybranch branch_with_interesting_stuff~15
>       git branch -d mybranch
>       git branch -m tmp mybranch
> 
> But it seems a little complex when what I *really* want to type is
> something like:
> 
>       git cherry-pick
> branch_with_interesting_stuff~15..branch_with_interesting_stuff~5
> 
> and have it give me a rebase-style UI in case of conflicts, etc.  And
> of course, even more bonus points if I can get "rebase -i"
> functionality.

For "rebase -i", this should do:

git checkout mybranch
git reset --hard interesting_stuff~5
git rebase -i --onto ORIG_HEAD interesting_stuff~5

Not as nice as the format-patch thing but at least it doesn't drop your
braches' reflog like your version, and it provides "rebase -i"
functionality.

Note that the ORIG_HEAD thing might require a recent git version, IIRC
there were some patches to make rebase correctly handle that.

Björn

^ permalink raw reply

* [JGIT PATCH 5/9 v2] Create a catalog of CommandRefs for lookup and enumeration
From: Shawn O. Pearce @ 2008-07-25 20:02 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <1217015167-4680-6-git-send-email-spearce@spearce.org>

The command catalog supports enumerating commands registered through
a services list, converting each entry into a CommandRef and making
that available to callers on demand.  The CommandRef can be later used
to create a command instance or just to obtain documentation about it.

All current commands are listed in the service registration.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---

 All that was missing was the services file entry in the built JAR.
 With this replacement for 5/9 the series should be fine.

 make_jgit.sh                                       |    1 +
 .../services/org.spearce.jgit.pgm.TextBuiltin      |   12 ++
 .../src/org/spearce/jgit/pgm/CommandCatalog.java   |  188 ++++++++++++++++++++
 3 files changed, 201 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin
 create mode 100644 org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandCatalog.java

diff --git a/make_jgit.sh b/make_jgit.sh
index bcb2df0..89df80c 100755
--- a/make_jgit.sh
+++ b/make_jgit.sh
@@ -71,6 +71,7 @@ sed s/@@use_self@@/1/ jgit.sh >$O+ &&
 java org.spearce.jgit.pgm.build.JarLinkUtil \
 	`for p in $JARS   ; do printf %s " -include $p"     ;done` \
 	`for p in $PLUGINS; do printf %s " -include $p/bin2";done` \
+	-file META-INF/services/org.spearce.jgit.pgm.TextBuiltin=org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin \
 	-file META-INF/MANIFEST.MF=$T_MF \
 	>>$O+ &&
 chmod 555 $O+ &&
diff --git a/org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin b/org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin
new file mode 100644
index 0000000..69ef046
--- /dev/null
+++ b/org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin
@@ -0,0 +1,12 @@
+org.spearce.jgit.pgm.DiffTree
+org.spearce.jgit.pgm.Fetch
+org.spearce.jgit.pgm.Glog
+org.spearce.jgit.pgm.IndexPack
+org.spearce.jgit.pgm.Log
+org.spearce.jgit.pgm.LsRemote
+org.spearce.jgit.pgm.LsTree
+org.spearce.jgit.pgm.MergeBase
+org.spearce.jgit.pgm.Push
+org.spearce.jgit.pgm.RevList
+org.spearce.jgit.pgm.ShowRev
+org.spearce.jgit.pgm.Tag
diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandCatalog.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandCatalog.java
new file mode 100644
index 0000000..13c585c
--- /dev/null
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandCatalog.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Git Development Community nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.spearce.jgit.pgm;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+/**
+ * List of all commands known by jgit's command line tools.
+ * <p>
+ * Commands are implementations of {@link TextBuiltin}, with an optional
+ * {@link Command} class annotation to insert additional documentation or
+ * override the default command name (which is guessed from the class name).
+ * <p>
+ * Commands may be registered by adding them to a services file in the same JAR
+ * (or classes directory) as the command implementation. The service file name
+ * is <code>META-INF/services/org.spearce.jgit.pgm.TextBuiltin</code> and it
+ * contains one concrete implementation class name per line.
+ * <p>
+ * Command registration is identical to Java 6's services, however the catalog
+ * uses a lightweight wrapper to delay creating a command instance as much as
+ * possible. This avoids initializing the AWT or SWT GUI toolkits even if the
+ * command's constructor might require them.
+ */
+public class CommandCatalog {
+	private static final CommandCatalog INSTANCE = new CommandCatalog();
+
+	/**
+	 * Locate a single command by its user friendly name.
+	 *
+	 * @param name
+	 *            name of the command. Typically in dash-lower-case-form, which
+	 *            was derived from the DashLowerCaseForm class name.
+	 * @return the command instance; null if no command exists by that name.
+	 */
+	public static CommandRef get(final String name) {
+		return INSTANCE.commands.get(name);
+	}
+
+	/**
+	 * @return all known commands, sorted by command name.
+	 */
+	public static CommandRef[] all() {
+		return toSortedArray(INSTANCE.commands.values());
+	}
+
+	/**
+	 * @return all common commands, sorted by command name.
+	 */
+	public static CommandRef[] common() {
+		final ArrayList<CommandRef> common = new ArrayList<CommandRef>();
+		for (final CommandRef c : INSTANCE.commands.values())
+			if (c.isCommon())
+				common.add(c);
+		return toSortedArray(common);
+	}
+
+	private static CommandRef[] toSortedArray(final Collection<CommandRef> c) {
+		final CommandRef[] r = c.toArray(new CommandRef[c.size()]);
+		Arrays.sort(r, new Comparator<CommandRef>() {
+			public int compare(final CommandRef o1, final CommandRef o2) {
+				return o1.getName().compareTo(o2.getName());
+			}
+		});
+		return r;
+	}
+
+	private final ClassLoader ldr;
+
+	private final Map<String, CommandRef> commands;
+
+	private CommandCatalog() {
+		ldr = Thread.currentThread().getContextClassLoader();
+		commands = new HashMap<String, CommandRef>();
+
+		final Enumeration<URL> catalogs = catalogs();
+		while (catalogs.hasMoreElements())
+			scan(catalogs.nextElement());
+	}
+
+	private Enumeration<URL> catalogs() {
+		try {
+			final String pfx = "META-INF/services/";
+			return ldr.getResources(pfx + TextBuiltin.class.getName());
+		} catch (IOException err) {
+			return new Vector<URL>().elements();
+		}
+	}
+
+	private void scan(final URL cUrl) {
+		final BufferedReader cIn;
+		try {
+			final InputStream in = cUrl.openStream();
+			cIn = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+		} catch (IOException err) {
+			// If we cannot read from the service list, go to the next.
+			//
+			return;
+		}
+
+		try {
+			String line;
+			while ((line = cIn.readLine()) != null) {
+				if (line.length() > 0 && !line.startsWith("#"))
+					load(line);
+			}
+		} catch (IOException err) {
+			// If we failed during a read, ignore the error.
+			//
+		} finally {
+			try {
+				cIn.close();
+			} catch (IOException e) {
+				// Ignore the close error; we are only reading.
+			}
+		}
+	}
+
+	private void load(final String cn) {
+		final Class<? extends TextBuiltin> clazz;
+		try {
+			clazz = Class.forName(cn, false, ldr).asSubclass(TextBuiltin.class);
+		} catch (ClassNotFoundException notBuiltin) {
+			// Doesn't exist, even though the service entry is present.
+			//
+			return;
+		} catch (ClassCastException notBuiltin) {
+			// Isn't really a builtin, even though its listed as such.
+			//
+			return;
+		}
+
+		final CommandRef cr;
+		final Command a = clazz.getAnnotation(Command.class);
+		if (a != null)
+			cr = new CommandRef(clazz, a);
+		else
+			cr = new CommandRef(clazz);
+
+		commands.put(cr.getName(), cr);
+	}
+}
-- 
1.6.0.rc0.182.gb96c7

^ permalink raw reply related

* Re: git rebase to move a batch of patches onto the current branch
From: Alex Riesen @ 2008-07-25 20:00 UTC (permalink / raw)
  To: Stephan Beyer; +Cc: Daniel Barkalow, Avery Pennarun, Git Mailing List
In-Reply-To: <20080725192500.GB13539@leksak.fem-net>

Stephan Beyer, Fri, Jul 25, 2008 21:25:00 +0200:
> Daniel Barkalow wrote:
> > > On 7/24/08, Alex Riesen <raa.lkml@gmail.com> wrote:
> > > > Avery Pennarun, Thu, Jul 24, 2008 22:16:06 +0200:
> > > > > On 7/24/08, Alex Riesen <raa.lkml@gmail.com> wrote:
> > > >
> > > > > >     gcp3 ()
> > > >  > >     {
> > > >  > >         git format-patch -k --stdout --full-index "$@" | git am -k -3 --binary
> > > >  > >     }
> > > >  >
> > > >  > But that'll give up when there are conflicts, right?  git-rebase lets
> > > >  > me fix them in a nice way.
> > > >
> > > > No, it same as in rebase. You'll fix them and do "git am --resolved".
> > > >  See manpage of git am.
> > > 
> > > Hmm, cool.
> > > 
> > > So that command isn't too easy to come upon by accident.  If I wanted
> > > to submit a patch to make this process a bit more obvious, would it
> > > make sense to simply have git-cherry-pick call that sequence when you
> > > give it more than one commit?
> > 
> > Before terribly long, we'll have "git sequencer", which should be easy to 
> > get to do the "rebase -i" thing with cherry-pick-style usage (somebody 
> > would just need to write code to generate the correct series of pick 
> > statements).
> 
> For simple cases this code could be something like:
> git rev-list --reverse --cherry-pick --no-merges --first-parent <from>..<to> |
> 	sed 's/^/pick /' | git sequencer
> 
> (At least this is what I use relatively often.)
> 
> But as long as git sequencer is not in official git, this is not an
> option. :)

Besides, that's longer than format-patch + am for the same from..to
range.

^ permalink raw reply

* Re: [JGIT PATCH 0/9] List commonly used (or recognized) commands
From: Shawn O. Pearce @ 2008-07-25 19:52 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <1217015167-4680-1-git-send-email-spearce@spearce.org>

"Shawn O. Pearce" <spearce@spearce.org> wrote:
> This series adds support to jgit to list commonly used subcommands
> if the user just executes `jgit` with no subcommand requested:
> 
>   $ jgit
>   jgit --git-dir GIT_DIR --help (-h) --show-stack-trace command [ARG ...]
>   
>   The most commonly used commands are:
>    fetch  Update remote refs from another repository
>    log    View commit history
>    push   Update remote repository from local refs
>    tag    Create a tag

Scratch that.  This series is busted if you install jgit and actually
try to use it.  No subcommands get registered.  I suspect it is due
to the shell script+ZIP file we have in the CLASSPATH confusing the
JRE and making it impossible to read correctly.

-- 
Shawn.

^ permalink raw reply

* [PATCH 6/9 - v3] builtin-init-db.c: use parse_options()
From: Michele Ballabio @ 2008-07-25 19:53 UTC (permalink / raw)
  To: dkr+ml.git; +Cc: git, gitster
In-Reply-To: <4889EF45.1040603@free.fr>

Signed-off-by: Michele Ballabio <barra_cuda@katamail.com>
---
On Friday 25 July 2008, Olivier Marin wrote:
> Michele Ballabio a écrit :
> > 
> >>> +		  PARSE_OPT_OPTARG, parse_opt_shared_cb, PERM_GROUP },
> >> Are you sure the default value is really used here?
> > 
> > Yes. Perhaps I don't understand your question. Can you explain what you mean?
> 
> If I read the code correctly in parse-options.c, with OPTION_CALLBACK, the
> default value is not "automatically" used. You can use it in your callback
> if you want, but because you don't, I think it's never used.

Oh, you're right, but git_config_perm() handles NULL just fine, so I can
remove it. Done in this patch, thanks.

> what I suggested is more something like:
> 
> static int parse_opt_shared_cb(const struct option *opt, const char *arg,
> 			       int unset)
> {
> 	*(int *)(opt->value) = unset ? -1 : git_config_perm("arg", arg);
> 	return 0;
> }
> 
> int shared = -1;
> 
> { OPTION_CALLBACK, 0, "shared", &shared,
> 	"permissions", "setup as shared repository",
> 	PARSE_OPT_OPTARG, parse_perm_callback },
> 
> if (shared >= 0)
> 	shared_repository = shared;
> 
> This way we do not change shared_repository during parsing, so we do not
> loose the initial value.
> 
> But it seems nobody care about this kind of details, so perhaps, you can
> just ignore this suggestion.

I might be wrong, but shared_repository is initialized to PERM_UMASK and
does not change before parse_options() is called, so this is not much
useful.

 builtin-init-db.c |   57 +++++++++++++++++++++++++++++++++-------------------
 1 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/builtin-init-db.c b/builtin-init-db.c
index 38b4fcb..01b84a9 100644
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
@@ -6,6 +6,7 @@
 #include "cache.h"
 #include "builtin.h"
 #include "exec_cmd.h"
+#include "parse-options.h"
 
 #ifndef DEFAULT_GIT_TEMPLATE_DIR
 #define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates"
@@ -353,8 +354,18 @@ static int guess_repository_type(const char *git_dir)
 	return 1;
 }
 
-static const char init_db_usage[] =
-"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]";
+static const char * const init_db_usage[] = {
+	"git init [-q | --quiet] [--bare] [--template=<dir>] [--shared[=<type>]]",
+	NULL
+};
+
+static int parse_opt_shared_cb(const struct option *opt, const char *arg,
+			       int unset)
+{
+	*(int *)(opt->value) = unset ? PERM_UMASK :
+				       git_config_perm("arg", arg);
+	return 0;
+}
 
 /*
  * If you want to, you can share the DB area with any number of branches.
@@ -367,25 +378,29 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	const char *git_dir;
 	const char *template_dir = NULL;
 	unsigned int flags = 0;
-	int i;
-
-	for (i = 1; i < argc; i++, argv++) {
-		const char *arg = argv[1];
-		if (!prefixcmp(arg, "--template="))
-			template_dir = arg+11;
-		else if (!strcmp(arg, "--bare")) {
-			static char git_dir[PATH_MAX+1];
-			is_bare_repository_cfg = 1;
-			setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir,
-						sizeof(git_dir)), 0);
-		} else if (!strcmp(arg, "--shared"))
-			shared_repository = PERM_GROUP;
-		else if (!prefixcmp(arg, "--shared="))
-			shared_repository = git_config_perm("arg", arg+9);
-		else if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet"))
-			flags |= INIT_DB_QUIET;
-		else
-			usage(init_db_usage);
+	int bare = 0;
+
+	const struct option options[] = {
+		OPT_STRING(0, "template", &template_dir, "path",
+			   "path to the template directory"),
+		OPT_BOOLEAN(0, "bare", &bare, "set up a bare repository"),
+		{ OPTION_CALLBACK, 0, "shared", &shared_repository,
+		  "permissions", "set up a shared repository",
+		  PARSE_OPT_OPTARG, parse_opt_shared_cb },
+		OPT_BIT('q', "quiet", &flags, "be quiet", INIT_DB_QUIET),
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, options, init_db_usage, 0);
+
+	if (argc > 0)
+		usage_with_options(init_db_usage, options);
+
+	if (bare) {
+		static char git_dir[PATH_MAX+1];
+		is_bare_repository_cfg = 1;
+		setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir,
+					sizeof(git_dir)), 0);
 	}
 
 	/*
-- 
1.5.6.3

^ permalink raw reply related

* [JGIT PATCH 9/9] Add debug-show-commands to display the command table
From: Shawn O. Pearce @ 2008-07-25 19:46 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <1217015167-4680-9-git-send-email-spearce@spearce.org>

This can be useful to debug the command catalog.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../services/org.spearce.jgit.pgm.TextBuiltin      |    2 +
 .../src/org/spearce/jgit/pgm/CommandRef.java       |    7 ++
 .../org/spearce/jgit/pgm/debug/ShowCommands.java   |   78 ++++++++++++++++++++
 3 files changed, 87 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/debug/ShowCommands.java

diff --git a/org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin b/org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin
index 69ef046..1ff5a30 100644
--- a/org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin
+++ b/org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin
@@ -10,3 +10,5 @@ org.spearce.jgit.pgm.Push
 org.spearce.jgit.pgm.RevList
 org.spearce.jgit.pgm.ShowRev
 org.spearce.jgit.pgm.Tag
+
+org.spearce.jgit.pgm.debug.ShowCommands
diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandRef.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandRef.java
index 40400a7..8bf784b 100644
--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandRef.java
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandRef.java
@@ -120,6 +120,13 @@ public class CommandRef {
 	}
 
 	/**
+	 * @return loader for {@link #getImplementationClassName()}.
+	 */
+	public ClassLoader getImplementationClassLoader() {
+		return impl.getClassLoader();
+	}
+
+	/**
 	 * @return a new instance of the command implementation.
 	 */
 	public TextBuiltin create() {
diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/debug/ShowCommands.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/debug/ShowCommands.java
new file mode 100644
index 0000000..64ecf7f
--- /dev/null
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/debug/ShowCommands.java
@@ -0,0 +1,78 @@
+package org.spearce.jgit.pgm.debug;
+
+import java.net.URL;
+
+import org.kohsuke.args4j.Option;
+import org.spearce.jgit.pgm.Command;
+import org.spearce.jgit.pgm.CommandCatalog;
+import org.spearce.jgit.pgm.CommandRef;
+import org.spearce.jgit.pgm.TextBuiltin;
+
+@Command(usage = "Display a list of all registered jgit commands")
+class ShowCommands extends TextBuiltin {
+	@Option(name = "--pretty", usage = "alter the detail shown")
+	private Format pretty = Format.USAGE;
+
+	@Override
+	protected void run() throws Exception {
+		final CommandRef[] list = CommandCatalog.all();
+
+		int width = 0;
+		for (final CommandRef c : list)
+			width = Math.max(width, c.getName().length());
+		width += 2;
+
+		for (final CommandRef c : list) {
+			System.err.print(c.isCommon() ? '*' : ' ');
+			System.err.print(' ');
+
+			System.err.print(c.getName());
+			for (int i = c.getName().length(); i < width; i++)
+				System.err.print(' ');
+
+			pretty.print(c);
+			System.err.println();
+		}
+		System.err.println();
+	}
+
+	static enum Format {
+		/** */
+		USAGE {
+			void print(final CommandRef c) {
+				System.err.print(c.getUsage());
+			}
+		},
+
+		/** */
+		CLASSES {
+			void print(final CommandRef c) {
+				System.err.print(c.getImplementationClassName());
+			}
+		},
+
+		/** */
+		URLS {
+			void print(final CommandRef c) {
+				final ClassLoader ldr = c.getImplementationClassLoader();
+
+				String cn = c.getImplementationClassName();
+				cn = cn.replace('.', '/') + ".class";
+
+				final URL url = ldr.getResource(cn);
+				if (url == null) {
+					System.err.print("!! NOT FOUND !!");
+					return;
+				}
+
+				String rn = url.toExternalForm();
+				if (rn.endsWith(cn))
+					rn = rn.substring(0, rn.length() - cn.length());
+
+				System.err.print(rn);
+			}
+		};
+
+		abstract void print(CommandRef c);
+	}
+}
-- 
1.6.0.rc0.182.gb96c7

^ permalink raw reply related

* [JGIT PATCH 6/9] Document some common commands with the new Command annotation
From: Shawn O. Pearce @ 2008-07-25 19:46 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <1217015167-4680-6-git-send-email-spearce@spearce.org>

This way they are known to be common at runtime, by looking at
the annotation associated with the class instance.  Right now
we do not use these annotations but they will be useful soon.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../src/org/spearce/jgit/pgm/Fetch.java            |    1 +
 .../src/org/spearce/jgit/pgm/Log.java              |    1 +
 .../src/org/spearce/jgit/pgm/Push.java             |    1 +
 .../src/org/spearce/jgit/pgm/Tag.java              |    1 +
 4 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java
index 194f669..dcad972 100644
--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Fetch.java
@@ -47,6 +47,7 @@ import org.spearce.jgit.transport.RefSpec;
 import org.spearce.jgit.transport.TrackingRefUpdate;
 import org.spearce.jgit.transport.Transport;
 
+@Command(common = true, usage = "Update remote refs from another repository")
 class Fetch extends TextBuiltin {
 	@Argument(index = 0, metaVar = "uri-ish")
 	private String remote = "origin";
diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Log.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Log.java
index 780a63b..e16387b 100644
--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Log.java
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Log.java
@@ -45,6 +45,7 @@ import java.util.TimeZone;
 import org.spearce.jgit.lib.PersonIdent;
 import org.spearce.jgit.revwalk.RevCommit;
 
+@Command(common = true, usage = "View commit history")
 class Log extends RevWalkTextBuiltin {
 	private final TimeZone myTZ = TimeZone.getDefault();
 
diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Push.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Push.java
index df6c664..6b35ab8 100644
--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Push.java
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Push.java
@@ -51,6 +51,7 @@ import org.spearce.jgit.transport.RemoteRefUpdate;
 import org.spearce.jgit.transport.Transport;
 import org.spearce.jgit.transport.RemoteRefUpdate.Status;
 
+@Command(common = true, usage = "Update remote repository from local refs")
 class Push extends TextBuiltin {
 	@Argument(index = 0, metaVar = "uri-ish")
 	private String remote = "origin";
diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Tag.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Tag.java
index a7bd037..6c73552 100644
--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Tag.java
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Tag.java
@@ -45,6 +45,7 @@ import org.spearce.jgit.lib.ObjectId;
 import org.spearce.jgit.lib.ObjectLoader;
 import org.spearce.jgit.lib.PersonIdent;
 
+@Command(common = true, usage = "Create a tag")
 class Tag extends TextBuiltin {
 	@Option(name = "-f", usage = "force replacing an existing tag")
 	private boolean force;
-- 
1.6.0.rc0.182.gb96c7

^ permalink raw reply related

* [JGIT PATCH 8/9] Refactor SubcommandHandler to use CommandCatalog instead of reflection
From: Shawn O. Pearce @ 2008-07-25 19:46 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <1217015167-4680-8-git-send-email-spearce@spearce.org>

Now that all commands are known to the CommandCatalog we do not need
to perform direct reflection inside of the SubcommandHandler.  Instead
we can reuse the lookup table already known to the CommandCatalog.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../src/org/spearce/jgit/pgm/TextBuiltin.java      |    8 +--
 .../spearce/jgit/pgm/opt/SubcommandHandler.java    |   65 ++------------------
 2 files changed, 6 insertions(+), 67 deletions(-)

diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/TextBuiltin.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/TextBuiltin.java
index e2eef84..5c066cb 100644
--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/TextBuiltin.java
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/TextBuiltin.java
@@ -83,13 +83,7 @@ public abstract class TextBuiltin {
 	/** RevWalk used during command line parsing, if it was required. */
 	protected RevWalk argWalk;
 
-	/**
-	 * Set the name this command can be invoked as on the command line.
-	 *
-	 * @param name
-	 *            the name of the command.
-	 */
-	public void setCommandName(final String name) {
+	final void setCommandName(final String name) {
 		commandName = name;
 	}
 
diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/opt/SubcommandHandler.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/opt/SubcommandHandler.java
index c7e1bf6..86004bb 100644
--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/opt/SubcommandHandler.java
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/opt/SubcommandHandler.java
@@ -37,8 +37,6 @@
 
 package org.spearce.jgit.pgm.opt;
 
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 import java.text.MessageFormat;
 
 import org.kohsuke.args4j.CmdLineException;
@@ -47,7 +45,8 @@ import org.kohsuke.args4j.OptionDef;
 import org.kohsuke.args4j.spi.OptionHandler;
 import org.kohsuke.args4j.spi.Parameters;
 import org.kohsuke.args4j.spi.Setter;
-import org.spearce.jgit.pgm.Main;
+import org.spearce.jgit.pgm.CommandCatalog;
+import org.spearce.jgit.pgm.CommandRef;
 import org.spearce.jgit.pgm.TextBuiltin;
 
 /**
@@ -57,12 +56,6 @@ import org.spearce.jgit.pgm.TextBuiltin;
  * we can execute at runtime with the remaining arguments of the parser.
  */
 public class SubcommandHandler extends OptionHandler<TextBuiltin> {
-	private static String mypackage() {
-		final String p = Main.class.getName();
-		final int dot = p.lastIndexOf('.');
-		return p.substring(0, dot);
-	}
-
 	/**
 	 * Create a new handler for the command name.
 	 * <p>
@@ -80,65 +73,17 @@ public class SubcommandHandler extends OptionHandler<TextBuiltin> {
 	@Override
 	public int parseArguments(final Parameters params) throws CmdLineException {
 		final String name = params.getParameter(0);
-		final StringBuilder s = new StringBuilder();
-		s.append(mypackage());
-		s.append('.');
-		boolean upnext = true;
-		for (int i = 0; i < name.length(); i++) {
-			final char c = name.charAt(i);
-			if (c == '-') {
-				upnext = true;
-				continue;
-			}
-			if (upnext)
-				s.append(Character.toUpperCase(c));
-			else
-				s.append(c);
-			upnext = false;
-		}
-
-		final Class<?> clazz;
-		try {
-			clazz = Class.forName(s.toString());
-		} catch (ClassNotFoundException e) {
-			throw new CmdLineException(MessageFormat.format(
-					"{0} is not a jgit command", name));
-		}
-
-		if (!TextBuiltin.class.isAssignableFrom(clazz))
+		final CommandRef cr = CommandCatalog.get(name);
+		if (cr == null)
 			throw new CmdLineException(MessageFormat.format(
 					"{0} is not a jgit command", name));
 
-		final Constructor<?> cons;
-		try {
-			cons = clazz.getDeclaredConstructor();
-		} catch (SecurityException e) {
-			throw new CmdLineException("Cannot create " + name, e);
-		} catch (NoSuchMethodException e) {
-			throw new CmdLineException("Cannot create " + name, e);
-		}
-		cons.setAccessible(true);
-
-		final TextBuiltin cmd;
-		try {
-			cmd = (TextBuiltin) cons.newInstance();
-		} catch (InstantiationException e) {
-			throw new CmdLineException("Cannot create " + name, e);
-		} catch (IllegalAccessException e) {
-			throw new CmdLineException("Cannot create " + name, e);
-		} catch (InvocationTargetException e) {
-			throw new CmdLineException("Cannot create " + name, e);
-		}
-
-		cmd.setCommandName(name);
-		setter.addValue(cmd);
-
 		// Force option parsing to stop. Everything after us should
 		// be arguments known only to this command and must not be
 		// recognized by the current parser.
 		//
 		owner.stopOptionParsing();
-
+		setter.addValue(cr.create());
 		return 1;
 	}
 
-- 
1.6.0.rc0.182.gb96c7

^ permalink raw reply related

* [JGIT PATCH 7/9] Include commonly used commands in main help output
From: Shawn O. Pearce @ 2008-07-25 19:46 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <1217015167-4680-7-git-send-email-spearce@spearce.org>

If the main loop did not get a subcommand during parsing of the
command line then we should offer up a list of commonly used
commands and their one-line usage summary, to help the user make
a decision about which command they should try to execute.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../src/org/spearce/jgit/pgm/Main.java             |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Main.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Main.java
index c069989..c8bade8 100644
--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Main.java
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Main.java
@@ -121,6 +121,24 @@ public class Main {
 				System.err.println();
 				clp.printUsage(System.err);
 				System.err.println();
+			} else if (subcommand == null) {
+				System.err.println();
+				System.err.println("The most commonly used commands are:");
+				final CommandRef[] common = CommandCatalog.common();
+				int width = 0;
+				for (final CommandRef c : common)
+					width = Math.max(width, c.getName().length());
+				width += 2;
+
+				for (final CommandRef c : common) {
+					System.err.print(' ');
+					System.err.print(c.getName());
+					for (int i = c.getName().length(); i < width; i++)
+						System.err.print(' ');
+					System.err.print(c.getUsage());
+					System.err.println();
+				}
+				System.err.println();
 			}
 			System.exit(1);
 		}
-- 
1.6.0.rc0.182.gb96c7

^ permalink raw reply related

* [JGIT PATCH 5/9] Create a catalog of CommandRefs for lookup and enumeration
From: Shawn O. Pearce @ 2008-07-25 19:46 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <1217015167-4680-5-git-send-email-spearce@spearce.org>

The command catalog supports enumerating commands registered through
a services list, converting each entry into a CommandRef and making
that available to callers on demand.  The CommandRef can be later used
to create a command instance or just to obtain documentation about it.

All current commands are listed in the service registration.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../services/org.spearce.jgit.pgm.TextBuiltin      |   12 ++
 .../src/org/spearce/jgit/pgm/CommandCatalog.java   |  188 ++++++++++++++++++++
 2 files changed, 200 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin
 create mode 100644 org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandCatalog.java

diff --git a/org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin b/org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin
new file mode 100644
index 0000000..69ef046
--- /dev/null
+++ b/org.spearce.jgit.pgm/src/META-INF/services/org.spearce.jgit.pgm.TextBuiltin
@@ -0,0 +1,12 @@
+org.spearce.jgit.pgm.DiffTree
+org.spearce.jgit.pgm.Fetch
+org.spearce.jgit.pgm.Glog
+org.spearce.jgit.pgm.IndexPack
+org.spearce.jgit.pgm.Log
+org.spearce.jgit.pgm.LsRemote
+org.spearce.jgit.pgm.LsTree
+org.spearce.jgit.pgm.MergeBase
+org.spearce.jgit.pgm.Push
+org.spearce.jgit.pgm.RevList
+org.spearce.jgit.pgm.ShowRev
+org.spearce.jgit.pgm.Tag
diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandCatalog.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandCatalog.java
new file mode 100644
index 0000000..13c585c
--- /dev/null
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandCatalog.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Git Development Community nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.spearce.jgit.pgm;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+/**
+ * List of all commands known by jgit's command line tools.
+ * <p>
+ * Commands are implementations of {@link TextBuiltin}, with an optional
+ * {@link Command} class annotation to insert additional documentation or
+ * override the default command name (which is guessed from the class name).
+ * <p>
+ * Commands may be registered by adding them to a services file in the same JAR
+ * (or classes directory) as the command implementation. The service file name
+ * is <code>META-INF/services/org.spearce.jgit.pgm.TextBuiltin</code> and it
+ * contains one concrete implementation class name per line.
+ * <p>
+ * Command registration is identical to Java 6's services, however the catalog
+ * uses a lightweight wrapper to delay creating a command instance as much as
+ * possible. This avoids initializing the AWT or SWT GUI toolkits even if the
+ * command's constructor might require them.
+ */
+public class CommandCatalog {
+	private static final CommandCatalog INSTANCE = new CommandCatalog();
+
+	/**
+	 * Locate a single command by its user friendly name.
+	 *
+	 * @param name
+	 *            name of the command. Typically in dash-lower-case-form, which
+	 *            was derived from the DashLowerCaseForm class name.
+	 * @return the command instance; null if no command exists by that name.
+	 */
+	public static CommandRef get(final String name) {
+		return INSTANCE.commands.get(name);
+	}
+
+	/**
+	 * @return all known commands, sorted by command name.
+	 */
+	public static CommandRef[] all() {
+		return toSortedArray(INSTANCE.commands.values());
+	}
+
+	/**
+	 * @return all common commands, sorted by command name.
+	 */
+	public static CommandRef[] common() {
+		final ArrayList<CommandRef> common = new ArrayList<CommandRef>();
+		for (final CommandRef c : INSTANCE.commands.values())
+			if (c.isCommon())
+				common.add(c);
+		return toSortedArray(common);
+	}
+
+	private static CommandRef[] toSortedArray(final Collection<CommandRef> c) {
+		final CommandRef[] r = c.toArray(new CommandRef[c.size()]);
+		Arrays.sort(r, new Comparator<CommandRef>() {
+			public int compare(final CommandRef o1, final CommandRef o2) {
+				return o1.getName().compareTo(o2.getName());
+			}
+		});
+		return r;
+	}
+
+	private final ClassLoader ldr;
+
+	private final Map<String, CommandRef> commands;
+
+	private CommandCatalog() {
+		ldr = Thread.currentThread().getContextClassLoader();
+		commands = new HashMap<String, CommandRef>();
+
+		final Enumeration<URL> catalogs = catalogs();
+		while (catalogs.hasMoreElements())
+			scan(catalogs.nextElement());
+	}
+
+	private Enumeration<URL> catalogs() {
+		try {
+			final String pfx = "META-INF/services/";
+			return ldr.getResources(pfx + TextBuiltin.class.getName());
+		} catch (IOException err) {
+			return new Vector<URL>().elements();
+		}
+	}
+
+	private void scan(final URL cUrl) {
+		final BufferedReader cIn;
+		try {
+			final InputStream in = cUrl.openStream();
+			cIn = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+		} catch (IOException err) {
+			// If we cannot read from the service list, go to the next.
+			//
+			return;
+		}
+
+		try {
+			String line;
+			while ((line = cIn.readLine()) != null) {
+				if (line.length() > 0 && !line.startsWith("#"))
+					load(line);
+			}
+		} catch (IOException err) {
+			// If we failed during a read, ignore the error.
+			//
+		} finally {
+			try {
+				cIn.close();
+			} catch (IOException e) {
+				// Ignore the close error; we are only reading.
+			}
+		}
+	}
+
+	private void load(final String cn) {
+		final Class<? extends TextBuiltin> clazz;
+		try {
+			clazz = Class.forName(cn, false, ldr).asSubclass(TextBuiltin.class);
+		} catch (ClassNotFoundException notBuiltin) {
+			// Doesn't exist, even though the service entry is present.
+			//
+			return;
+		} catch (ClassCastException notBuiltin) {
+			// Isn't really a builtin, even though its listed as such.
+			//
+			return;
+		}
+
+		final CommandRef cr;
+		final Command a = clazz.getAnnotation(Command.class);
+		if (a != null)
+			cr = new CommandRef(clazz, a);
+		else
+			cr = new CommandRef(clazz);
+
+		commands.put(cr.getName(), cr);
+	}
+}
-- 
1.6.0.rc0.182.gb96c7

^ permalink raw reply related

* [JGIT PATCH 4/9] Create a lightweight registration wrapper for TextBuiltin
From: Shawn O. Pearce @ 2008-07-25 19:46 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <1217015167-4680-4-git-send-email-spearce@spearce.org>

Automatic command list generation requires knowing what commands
are available to this runtime, and what name those commands can be
called as by the end-user.  This lightweight wrappers carries the
data from the Command annotation, possibly filling in the name of
the command by generating it from the implementation class name.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../src/org/spearce/jgit/pgm/CommandRef.java       |  151 ++++++++++++++++++++
 1 files changed, 151 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandRef.java

diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandRef.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandRef.java
new file mode 100644
index 0000000..40400a7
--- /dev/null
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/CommandRef.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Git Development Community nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.spearce.jgit.pgm;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Description of a command (a {@link TextBuiltin} subclass.
+ * <p>
+ * These descriptions are lightweight compared to creating a command instance
+ * and are therefore suitable for catalogs of "known" commands without linking
+ * the command's implementation and creating a dummy instance of the command.
+ */
+public class CommandRef {
+	private final Class<? extends TextBuiltin> impl;
+
+	private final String name;
+
+	private String usage;
+
+	boolean common;
+
+	CommandRef(final Class<? extends TextBuiltin> clazz) {
+		this(clazz, guessName(clazz));
+	}
+
+	CommandRef(final Class<? extends TextBuiltin> clazz, final Command cmd) {
+		this(clazz, cmd.name().length() > 0 ? cmd.name() : guessName(clazz));
+		usage = cmd.usage();
+		common = cmd.common();
+	}
+
+	private CommandRef(final Class<? extends TextBuiltin> clazz, final String cn) {
+		impl = clazz;
+		name = cn;
+		usage = "";
+	}
+
+	private static String guessName(final Class<? extends TextBuiltin> clazz) {
+		final StringBuilder s = new StringBuilder();
+		if (clazz.getName().startsWith("org.spearce.jgit.pgm.debug."))
+			s.append("debug-");
+
+		boolean lastWasDash = true;
+		for (final char c : clazz.getSimpleName().toCharArray()) {
+			if (Character.isUpperCase(c)) {
+				if (!lastWasDash)
+					s.append('-');
+				lastWasDash = !lastWasDash;
+				s.append(Character.toLowerCase(c));
+			} else {
+				s.append(c);
+			}
+		}
+		return s.toString();
+	}
+
+	/**
+	 * @return name the command is invoked as from the command line.
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * @return one line description of the command's feature set.
+	 */
+	public String getUsage() {
+		return usage;
+	}
+
+	/**
+	 * @return true if this command is considered to be commonly used.
+	 */
+	public boolean isCommon() {
+		return common;
+	}
+
+	/**
+	 * @return name of the Java class which implements this command.
+	 */
+	public String getImplementationClassName() {
+		return impl.getName();
+	}
+
+	/**
+	 * @return a new instance of the command implementation.
+	 */
+	public TextBuiltin create() {
+		final Constructor<? extends TextBuiltin> c;
+		try {
+			c = impl.getDeclaredConstructor();
+		} catch (SecurityException e) {
+			throw new RuntimeException("Cannot create command " + getName(), e);
+		} catch (NoSuchMethodException e) {
+			throw new RuntimeException("Cannot create command " + getName(), e);
+		}
+		c.setAccessible(true);
+
+		final TextBuiltin r;
+		try {
+			r = c.newInstance();
+		} catch (InstantiationException e) {
+			throw new RuntimeException("Cannot create command " + getName(), e);
+		} catch (IllegalAccessException e) {
+			throw new RuntimeException("Cannot create command " + getName(), e);
+		} catch (IllegalArgumentException e) {
+			throw new RuntimeException("Cannot create command " + getName(), e);
+		} catch (InvocationTargetException e) {
+			throw new RuntimeException("Cannot create command " + getName(), e);
+		}
+		r.setCommandName(getName());
+		return r;
+	}
+}
-- 
1.6.0.rc0.182.gb96c7

^ permalink raw reply related

* [JGIT PATCH 3/9] Create an optional documentation annotation for TextBuiltin
From: Shawn O. Pearce @ 2008-07-25 19:46 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <1217015167-4680-3-git-send-email-spearce@spearce.org>

This new annotation can be used for automatic command list creation,
or additional help generation by the default help generator.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../src/org/spearce/jgit/pgm/Command.java          |   72 ++++++++++++++++++++
 1 files changed, 72 insertions(+), 0 deletions(-)
 create mode 100644 org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Command.java

diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Command.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Command.java
new file mode 100644
index 0000000..40be1f7
--- /dev/null
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/Command.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Git Development Community nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.spearce.jgit.pgm;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to document a {@link TextBuiltin}.
+ * <p>
+ * This is an optional annotation for TextBuiltin subclasses and it carries
+ * documentation forward into the runtime system describing what the command is
+ * and why users may want to invoke it.
+ */
+@Retention(RUNTIME)
+@Target( { TYPE })
+public @interface Command {
+	/**
+	 * @return name the command is invoked as from the command line. If the
+	 *         (default) empty string is supplied the name will be generated
+	 *         from the class name.
+	 */
+	public String name() default "";
+
+	/**
+	 * @return one line description of the command's feature set.
+	 */
+	public String usage() default "";
+
+	/**
+	 * @return true if this command is considered to be commonly used.
+	 */
+	public boolean common() default false;
+}
-- 
1.6.0.rc0.182.gb96c7

^ permalink raw reply related

* [JGIT PATCH 2/9] Remove unnecessary duplicate if (help) test inside TextBuiltin
From: Shawn O. Pearce @ 2008-07-25 19:46 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <1217015167-4680-2-git-send-email-spearce@spearce.org>

This was caused by a copy-and-paste error as I borrowed the
global argument handling code in Main to help start writing
the command specific argument handling in TextBuiltin.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../src/org/spearce/jgit/pgm/TextBuiltin.java      |    9 ++++-----
 1 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/TextBuiltin.java b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/TextBuiltin.java
index d02a0a2..e2eef84 100644
--- a/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/TextBuiltin.java
+++ b/org.spearce.jgit.pgm/src/org/spearce/jgit/pgm/TextBuiltin.java
@@ -145,11 +145,10 @@ public abstract class TextBuiltin {
 			clp.printSingleLineUsage(System.err);
 			System.err.println();
 
-			if (help) {
-				System.err.println();
-				clp.printUsage(System.err);
-				System.err.println();
-			}
+			System.err.println();
+			clp.printUsage(System.err);
+			System.err.println();
+
 			System.exit(1);
 		}
 
-- 
1.6.0.rc0.182.gb96c7

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox