[Buildroot] [PATCH 4/7 v4] download/git: try to recover from utterly-broken repositories

Ricardo Martincoski ricardo.martincoski at gmail.com
Sun Apr 29 18:49:48 UTC 2018


Hello,

Using the previous iteration I tested adding '&& false' after the git checkout
command and the trap worked as expected.

But since this patch is not easy to me to review (my bash scripts use a small
subset of bash features), I decided to do more extensive testing. I think I
found something to be changed. Could you double-check? See at the end.

On Sat, Apr 28, 2018 at 04:34 PM, Yann E. MORIN wrote:

> +++ b/support/download/git
> @@ -16,6 +16,33 @@ set -e
>  # Environment:
>  #   GIT      : the git command to call
>  
> +# Save out path and options in case we need to call ourselves again

s/out/our/ ?

> +myname="${0}"
> +declare -a OPTS=("${@}")

It looks OK to me.
Similar syntax is used in support/scripts/check-bin-arch and no one using old
bash versions complained so far.
I didn't checked the bash version available on RHEL6 neither the bash source
code.

> +
> +# This function is called when an error occurs. Its job is to attempt a
> +# clone from scratch (only once!) in case the git tree is borked, or in
> +# case an unexpected and unsupported situation arises with submodules
> +# or uncomitted stuff (e.g. if the user manually mucked around in the

s/uncomitted/uncommitted/ ?

> +# git cache).
> +_on_error() {
> +    local ret=${?}
> +
> +    printf "Detected a corrupted git cache.\n" >&2
> +    if ${BR_GIT_BACKEND_FIRST_FAULT:-false}; then
> +        printf "This is the second time in a row; bailing out\n" >&2
> +        exit ${ret}
> +    fi
> +    export BR_GIT_BACKEND_FIRST_FAULT=true
> +
> +    printf "Removing it and starting afresh.\n" >&2
> +
> +    popd >/dev/null
> +    rm -rf "${git_cache}"
> +
> +    exec "${myname}" "${OPTS[@]}" || exit ${ret}
> +}
> +
>  verbose=
>  recurse=0
>  while getopts "${BR_BACKEND_DL_GETOPTS}" OPT; do
> @@ -39,6 +66,9 @@ git_cache="${dl_dir}/git"
>  mkdir -p "${git_cache}"
>  pushd "${git_cache}" >/dev/null
>  
> +# Any error now should try to recover
> +trap _on_error ERR
> +
>  # Caller needs to single-quote its arguments to prevent them from
>  # being expanded a second time (in case there are spaces in them)
>  _git() {

It seems the trap is not executed when a git command fails.

I first created a git cache. I used squashfs because it is small, its server is
fast, and it has hash to check against.
I removed .git/index in the cache so the next git init will create a brand new
one leaving lots of untracked files to be overwritten. Since the -f is not yet
added to git checkout (it belongs to a later patch) it should trigger a
ditch+restart, but it didn't.
I recreated the cache from scratch and replaced .git/HEAD with a directory. This
way the cache is broken and git init does not recovers it, as expected, leading
'git remote' to fail. It also should trigger a ditch+restart, but it didn't.

With the help of [1] I found in the bash manual, not mentioned in the SHELL
BUILTIN COMMANDS/trap section, only in the FUNCTIONS section:
"FUNCTIONS" [...]
"All other aspects of the shell execution environment are identical between a
 function and its caller with these exceptions:" [...]
"the ERR trap is not inherited unless the -o errtrace shell option has been
 enabled."

As a dirty hack I repeated the trap inside _git:
  _git() {
 +    trap _on_error ERR
It fixes the 2 cases I mentioned above.

Maybe the proper fix is to enable errtrace, but I didn't tested it, neither I
know all the implications of using this for all the other cases.
>From the manual:
"-E      If set, any trap on ERR is inherited by shell functions, command
 substitutions, and commands executed in a subshell environment. The ERR trap is
 normally not inherited in such cases."

[1] https://unix.stackexchange.com/questions/419017/return-trap-in-bash-not-executing-for-function

Regards,
Ricardo


More information about the buildroot mailing list