0

Is there any reliable way to check if Git literal pathspecs are enabled in a shell script?

This option can be set either by assigning a boolean value to the variable GIT_LITERAL_PATHSPECS or by passing a flag --literal-pathspecs to git, which also seems to set this variable.

However, parsing the variable seems pretty hard. This is what the documentation says about it:

The environment variables marked as "Boolean" take their values the same way as Boolean valued configuration variables, i.e., "true", "yes", "on" and positive numbers are taken as "yes", while "false", "no", "off", and "0" are taken as "no".

This seems to be enough information to implement it but I'm afraid that the documentation may be outdated or incomplete. There may be more valid keywords like "yeah" and "nah" (or they may be added in the future).

I tried to write a script that checks those values, but I don't know how reliable it would be:

if printf '%s' "$GIT_LITERAL_PATHSPECS" | grep -Eqxi 'true|yes|on' || [ "$GIT_LITERAL_PATHSPECS" -ge 1 ] 2>/dev/null
then
    echo 'literal pathspecs are ON'
else
    echo 'literal pathspecs are OFF'
fi

Even if it is reliable, I would prefer for some simpler method that won't require me to reimplement the whole boolean parser.

Is there some Git built-in method to check either this specific value, or at least to parse a boolean environment variable?

2
  • My documentation says that --literal-pathspecs will set GIT_LITERAL_PATHSPECS to 1. Commented May 24 at 12:13
  • @Guildenstern That seems likely but the user can set it to whatever value they please and I want my script to interpret it the same as Git would. Commented May 24 at 12:16

2 Answers 2

2

This isn't very specific, having phrases like "i.e." in it.

But it is exactly that: very specific. Id est is latin for "that is", as in "to be specific".

And the code bears it out; the quoted paragraph is an accurate and complete description:

int git_parse_maybe_bool_text(const char *value)
{
    if (!value)
        return 1;
    if (!*value)
        return 0;
    if (!strcasecmp(value, "true")
        || !strcasecmp(value, "yes")
        || !strcasecmp(value, "on"))
        return 1;
    if (!strcasecmp(value, "false")
        || !strcasecmp(value, "no")
        || !strcasecmp(value, "off"))
        return 0;
    return -1;
}

int git_parse_maybe_bool(const char *value)
{
    int v = git_parse_maybe_bool_text(value);
    if (0 <= v)
        return v;
    if (git_parse_int(value, &v))
        return !!v;
    return -1;
}

/*
 * Parse environment variable 'k' as a boolean (in various
 * possible spellings); if missing, use the default value 'def'.
 */
int git_env_bool(const char *k, int def)
{
    const char *v = getenv(k);
    int val;
    if (!v)
        return def;
    val = git_parse_maybe_bool(v);
    if (val < 0)
        die(_("bad boolean environment value '%s' for '%s'"),
            v, k);
    return val;
}

Sign up to request clarification or add additional context in comments.

4 Comments

You're right. I've managed to misconstrue "i.e." as "e.g.". I'm going to edit this part out of the question to make it less misleading for future readers. (I'll try to do it in a way that doesn't make this answer irrelevant.)
I think that abusing the git config to parse booleans is still more reliable. That method seems to be more future-proof in case the list supported strings is extended. But I think the implementation from the question would actually work correctly if I didn't miss anything?
For correct values yes, I think that'll work. Configure a bad value and Git will barf, but I also think trying to make identical error handling would likely be a bad idea so yeah.
>5min edit: I much prefer the version in your answer, I think that's the right way to do it.
1

This is the same concept as the other answer but I fixed it, simplified it and made sure it actually follows POSIX.

parse_git_bool() {
     test "$(git -c 'foo.bar'="$1" config --get --type=bool 'foo.bar' 2>/dev/null)" = 'true'
}

if parse_git_bool "$GIT_LITERAL_PATHSPECS"
then
    echo 'literal pathspecs are ON'
else
    echo 'literal pathspecs are OFF'
fi

Explanation:

We run git with the option -c which sets a temporary configuration value. From docs:

Pass a configuration parameter to the command. The value given will override values from configuration files. The is expected in the same format as listed by git config (subkeys separated by dots).

Note that omitting the = in git -c foo.bar ... is allowed and sets foo.bar to the boolean true value (just like [foo]bar would in a config file). Including the equals but with an empty value (like git -c foo.bar= ...) sets foo.bar to the empty string which git config --type=bool will convert to false.

Then we call config --get --type=bool which returns this value back but converted to boolean. (Only 2 values are possible true and false.) We use test to check if the returned value is true.

In case the input value was illegal, git config will silently fail (2>/dev/null) and the function will still return 1 just as if the parsed value was a correct false value. If you interested in having a different value for a failed parsing, you would need to check the exit code of git config.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.