From 93fb7cccca622cc15d2f33f3c567a6a26b25f4b0 Mon Sep 17 00:00:00 2001 From: Brandon Maier Date: Fri, 28 Jul 2023 21:32:18 +0000 Subject: [PATCH] utils/docker-run: fix support for git-worktrees The docker-run script attempts to support git-new-workdirs and git-worktrees by resolving the symlink at '$GIT_DIR/config' to get the true $GIT_DIR. However this does not work for git-worktrees as they do not use symlinks, instead they change the $GIT_DIR into a regular file that contains the path to the real $GIT_DIR. To complicate things further, we actually want the $GIT_COMMON_DIR which is the superset of a worktree's $GIT_DIR. git-rev-parse supports the '--git-common-dir' which will resolve the $GIT_COMMON_DIR for us. However it does not work for git-new-workdirs, so we still need to detect and handle them. '--git-common-dir' also appeared only with git 2.10.0, released in 2016, so it will not be available in older "enterprise-grade" distributions. In that case, 'git rev-parse --git-common-dir' would return the option flag '--git-common-dir' as-is, which is incorrect. So, we instruct it to never return flags. '--git-common-dir' also returns just '.git' for the main working copy, but 'docker run' want an absolute path, so we canonicalise it. Signed-off-by: Brandon Maier [yann.morin.1998@free.fr: - support git versions before --git-common-dir was introduced - don't mount GIT_DIR if unknown (i.e. not needed) - fix expanding MAIN_DIR ] Signed-off-by: Yann E. MORIN (cherry picked from commit 90790790925c5d456ce7585afdf6e42aa25fd9ea) Signed-off-by: Peter Korsgaard --- utils/docker-run | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/utils/docker-run b/utils/docker-run index 17c587a484..b201d28289 100755 --- a/utils/docker-run +++ b/utils/docker-run @@ -2,8 +2,13 @@ set -o errexit -o pipefail DIR=$(dirname "${0}") MAIN_DIR=$(readlink -f "${DIR}/..") -# GIT_DIR to support workdirs/worktrees -GIT_DIR="$(dirname "$(realpath "${MAIN_DIR}/.git/config")")" +if [ -L "${MAIN_DIR}/.git/config" ]; then + # Support git-new-workdir + GIT_DIR="$(dirname "$(realpath "${MAIN_DIR}/.git/config")")" +else + # Support git-worktree + GIT_DIR="$(cd "${MAIN_DIR}" && git rev-parse --no-flags --git-common-dir)" +fi # shellcheck disable=SC2016 IMAGE=$(grep ^image: "${MAIN_DIR}/.gitlab-ci.yml" | \ sed -e 's,^image: ,,g' | sed -e 's,\$CI_REGISTRY,registry.gitlab.com,g') @@ -13,9 +18,21 @@ declare -a docker_opts=( --rm --user "$(id -u):$(id -g)" --mount "type=bind,src=${MAIN_DIR},dst=${MAIN_DIR}" - --mount "type=bind,src=${GIT_DIR},dst=${GIT_DIR}" --workdir "${MAIN_DIR}" ) + +# Empty GIT_DIR means that we are not in a workdir, *and* git is too old +# to know about worktrees, so we're not in a worktree either. So it means +# we're in the main git working copy, and thus we don't need to mount the +# .git directory. +if [ "${GIT_DIR}" ]; then + # GIT_DIR in the main working copy (when git supports worktrees) will + # be just '.git', but 'docker run' needs an absolute path. If it's an + # absolute path already (in a wordir), then that's a noop. + GIT_DIR="$(readlink -e "${GIT_DIR}")" + docker_opts+=( --mount "type=bind,src=${GIT_DIR},dst=${GIT_DIR}" ) +fi + if tty -s; then docker_opts+=( -t ) fi