git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeff King <peff@peff.net>
To: Junio C Hamano <gitster@pobox.com>
Cc: Erik Faye-Lund <kusmabite@gmail.com>,
	Dun Peal <dunpealer@gmail.com>,
	git@vger.kernel.org
Subject: Re: Weird behavior of shell variables in git aliases
Date: Tue, 22 Mar 2011 07:18:44 -0400	[thread overview]
Message-ID: <20110322111844.GA32446@sigill.intra.peff.net> (raw)
In-Reply-To: <7v4o6wnlxm.fsf@alter.siamese.dyndns.org>

On Mon, Mar 21, 2011 at 03:33:25PM -0700, Junio C Hamano wrote:

> >> But interestingly, that's _not_ the behavior as of Erik's 7f51f8b
> >> (alias: use run_command api to execute aliases, 2011-01-07), which is in
> >> master but not yet released. With that, we end up executing:
> >>
> >>   sh -c 'echo $1 && echo $1 "$@"' 'echo $1 && echo $1' 'foo'
> [...]
> >
> > Oh, I should have been paying a bit more attention.  I've been assuming
> > that we were turning "!anything" into { "sh", "-c", "anything", "-" }
> > followed by the user supplied arguments.

Yeah, I think that would be more useful in general, but...

> The attached quick hack gives
> 
>   $ git config alias.silly
>   !echo hello $1; echo $# args, bye!
>   $ GIT_TRACE=1 ./git silly world funny
>   trace: exec: 'git-silly' 'world' 'funny'
>   trace: run_command: 'git-silly' 'world' 'funny'
>   trace: run_command: 'sh' '-c' 'echo hello $1; echo $# args, bye'\!'' '-' 'world' 'funny'
>   trace: exec: 'sh' '-c' 'echo hello $1; echo $# args, bye'\!''
>   '-' 'world' 'funny'
>   hello world
>   2 args, bye!
> 
> but it would penalize a properly written alias that uses "sh -c <it> -"
> trick itself by double forking, which is not very nice and I am unhappy
> about.

Doesn't it also break a lot of other more garden-variety aliases that
rely on the automagic "$@", like:

  $ git config alias.log-nopager
  !git --no-pager log

  $ GIT_TRACE=1 git.v1.7.4 log-nopager --oneline
  trace: exec: 'git-log-nopager' '--oneline'
  trace: run_command: 'git-log-nopager' '--oneline'
  trace: alias to shell cmd: log-nopager => git --no-pager log '--oneline'
  trace: built-in: git 'log' '--oneline'
  93c7d44 foo

  $ GIT_TRACE=1 git.master log-nopager --oneline
  trace: exec: 'git-log-nopager' '--oneline'
  trace: run_command: 'git-log-nopager' '--oneline'
  trace: run_command: 'git --no-pager log' '--oneline'
  trace: exec: 'sh' '-c' 'git --no-pager log "$@"' 'git --no-pager log' '--oneline'
  trace: built-in: git 'log' '--oneline'
  93c7d44 foo

  $ GIT_TRACE=1 git.jch.shell-alias log-nopager --oneline
  trace: exec: 'git-log-nopager' '--oneline'
  trace: run_command: 'git-log-nopager' '--oneline'
  trace: run_command: 'sh' '-c' 'git --no-pager log' '-' '--oneline'
  trace: exec: 'sh' '-c' 'git --no-pager log' '-' '--oneline'
  trace: built-in: git 'log'
  commit 93c7d44635e8bb56a4fd864d024ce75a2ad4ffcf
  Author: Jeff King <peff@peff.net>
  Date:   Tue Mar 22 06:57:02 2011 -0400

      foo

I think the evolution of the alias code was something like:

 1. Let's have alias.foo, so that "git foo XXX" can be aliased to "git
    log --whatever XXX", just like shell aliases.

 2. Oops, git doesn't allow some things in (1) that we might want to do,
    like turning off the pager or choosing a new repo. For that we need
    to respawn git, so now we have "!git --whatever1 log --whatever2".
    It appends the arguments, just like the form in (1), so it is
    consistent.

 3. Oops, (2) doesn't allow complex mini-scripts that access the
    parameters in a non-sequential way. You have to do "!sh -c 'git
    --whatever $1 log --whatever2 $2'".

Knowing that step (3) exists, I think your solution is a better one. The
question is whether it is better enough to be worth breaking the people
who were helped by step (2).

Another way of looking at it is that types (1) and (2) are like shell
aliases. And they suck for complex things, just the way that shell
aliases do. The solution in the shell is to put your complex alias into
a shell function, or to push it into its own script. In git, you can
push things into their own script, but we have no equivalent to a shell
function. So one solution is:

  git config function.silly '!echo hello $1; echo $# args, bye!'

The name is of course terrible. But I think the idea is sound that there
are two different types of interface people may want. On the other hand,
this is getting kind of grossly complex. The separate script option is
always available.

-Peff

  parent reply	other threads:[~2011-03-22 11:18 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-03-21 16:39 Weird behavior of shell variables in git aliases Dun Peal
2011-03-21 21:53 ` Jeff King
2011-03-21 22:21   ` Junio C Hamano
2011-03-21 22:33     ` Junio C Hamano
2011-03-22 10:38       ` Lasse Makholm
2011-03-22 11:28         ` Jeff King
2011-03-22 12:59           ` Lasse Makholm
2011-03-22 10:52       ` Ævar Arnfjörð Bjarmason
2011-03-22 11:18       ` Jeff King [this message]
2011-03-22 13:28         ` Jeff King
2011-03-22 13:35           ` Lasse Makholm
2011-03-22 13:43             ` Jeff King
2011-03-22 13:53               ` Lasse Makholm
2011-03-22 15:06                 ` Dun Peal
2011-03-22 17:57               ` Junio C Hamano
2011-03-22 18:32                 ` Jeff King
2011-03-22 22:22                   ` Lasse Makholm
2011-03-23  3:01                     ` Junio C Hamano
2011-03-22 17:36           ` Junio C Hamano
2011-03-22 17:35         ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110322111844.GA32446@sigill.intra.peff.net \
    --to=peff@peff.net \
    --cc=dunpealer@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=kusmabite@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).