Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gix-command passes -- to become $0 in sh -c #1842

Open
EliahKagan opened this issue Feb 15, 2025 · 0 comments
Open

gix-command passes -- to become $0 in sh -c #1842

EliahKagan opened this issue Feb 15, 2025 · 0 comments
Labels
acknowledged an issue is accepted as shortcoming to be fixed help wanted Extra attention is needed

Comments

@EliahKagan
Copy link
Member

As detailed below and detailed further in the linked #1840 discussion thread, we are doing something like /bin/sh -c 'command "$@"' -- args... when running commands with a shell, but -- does not have its usual meaning of causing arguments to be interpreted as non-options (or otherwise to be interpreted less specially).

Instead, the subsequent arguments are already passed through as the positional parameters, and the argument we are currently passing as -- becomes the special $0 parameter that appears when the shell produces messages. More informative alternatives are available. It is not obvious what approach is best, but I think we should use the name the shell uses to invoke itself, which will usually look something like:

/bin/sh: the body of the error message

Or, because some shells sometimes add further context information to their own messages, like:

/bin/sh: line 1: the body of the error message

This makes clear that the message comes from a shell, rather than the less informative approach of using -- as we currently are (or using _, which may be more common than -- here but still not very informative). It distinguishes it from messages that come from an external command the shell runs, which is useful even when the operand to -c is just a path, or quoted path, of an external command for the shell to run. This is because a shell may sometimes fail to run such a command.

When it is important, such error messages will usually show the name of the command, so the alternative of using the code operand to -c or something derived from it risks duplicating information unnecessary.


Discussed in #1840

Originally posted by EliahKagan February 12, 2025
When use_shell is true and no optimization keeps a shell from actually being used, the impl From<Prepare> for Command returns a std::process::Command instance that, roughly speaking, will run something like /bin/sh -c 'command "$@"' -- args....

The argument after -c and its operand is --. This has been the case since functionality for passing arguments was added in d8e8b54 (#496).

Because the arguments before -- run a command with a shell, the arguments after -- are arbitrary arguments that are passed to the command or script rather than being treated specially by the shell, and -- is often used to prevent subsequent arguments from being treated as options or otherwise specially, it may look at first glance like -- does that here. Perhaps that was even its intent.

But this -- argument does not do that. Instead, to simplify from the standard, this way of invoking sh is:

sh -c command_string [command_name [argument...]]

Where, as the standard documents for -c:

Read commands from the command_string operand. Set the value of special parameter 0 (see 2.5.2 Special Parameters) from the value of the command_name operand and the positional parameters ($1, $2, and so on) in sequence from the remaining argument operands. No commands shall be read from the standard input.

This is to say that the effect of our passing -- here is to tell the script whose code is passed as the operand to -c that it should consider its own name, i.e. the value of $0, to be --. One consequence of this is that errors produced in the shell itself are prefixed --:. For example, in #1839, the error message is:

--: /Users/runner/work/gitoxide/gitoxide/target/debug/examples/arrow: No such file or directory

It seems to me that giving the script the name of -- may be confusing to people examining stderr of a process run with gix-command, unless they are familiar with implementation details of gix-command (as well as with the syntax of sh -c).

If the goal of using -- rather than some other string was to prevent subsequent commands from being interpreted as shell options, then nothing special has to be done to avoid that, at least for POSIX-compatible shells. Arguments that come after the command string are never interpreted this way, instead always becoming positional parameters like $1, $2, $3.

However, we do have to pass something where we are currently passing --, if arguments meant to become $1, $2, $3, ..., are passed. Otherwise the argument meant to be $1 (and thus the first word expanded from "$@") would become $0, and the other positional parameters would, in effect, be shifted.

I'm not sure what would be better. In one-liners and causal use, I think _ is common. That is probably not better here. We should not use the value of the command field (which becomes the command string, sometimes with "$@" appended), or at least we should not use it unmodified. This is because the command field is sometimes just a path, and having it be the value of $0 for the script would make it hard to distinguish messages produced by the shell from those produced by an external command the shell runs. The ability to distinguish this has already been useful in #1839.

@Byron Byron added acknowledged an issue is accepted as shortcoming to be fixed help wanted Extra attention is needed labels Feb 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
acknowledged an issue is accepted as shortcoming to be fixed help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants