g |  104 ++++++++++++++++++++++++++--------------------------------------------
 1 file changed, 39 insertions(+), 65 deletions(-)

New commits:
commit 781d0cc285077b7a197357ed102db2e93534b8a9
Author:     Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
AuthorDate: Thu Nov 28 14:49:08 2024 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Mon Dec 2 18:27:13 2024 +0100

    fix refreshing git-hooks when using git-bash
    
    real symlinks require admin-rights or developer mode, and the other
    fallback mechanisms won't work for the version of git that comes with
    git-bash. Either spawning the process failes or worse it silently fails
    and basically ignores the hook.
    MSYS uses regular file copy when using "ln -s" which means to make sure
    the current version of a hook is used the hooks need to replaced
    everytime or the file contents need to be compared. When using hardlinks
    instead it is enough to check whether the source and target share the
    same inode.
    
    Change-Id: Ib2e325048779828313afc7fc9d120661d55fc3a5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177498
    Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
    Tested-by: Jenkins
    (cherry picked from commit caf0071d604eca7fc7b89e9ecfa7a686157ca797)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177527
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/g b/g
index 377890a3396a..cf9b8d59be19 100755
--- a/g
+++ b/g
@@ -29,9 +29,23 @@ usage()
     echo " -z restore the git hooks and do other sanity checks"
 }
 
+refresh_create_link()
+{
+    local hook_name=$1
+    local hook=$2
+    local lnarg=$3
+
+    # if it doesn't exist or is neither a symlink nor sharing the same inode 
(hardlink)
+    if [ ! -e "${hook?}" ] || [ ! \( -L "${hook?}" -o "${hook_name}" -ef 
"${hook?}" \) ] ; then
+        rm -f "${hook?}"
+        ln -f $lnarg "${hook_name}" "${hook?}"
+    fi
+}
+
 refresh_submodule_hooks()
 {
     local repo=$1
+    local lnarg=$2
     local hook
     local hook_name
 
@@ -42,10 +56,7 @@ refresh_submodule_hooks()
                 continue
             fi
             hook="${repo?}/.git/hooks/${hook_name##*/}"
-            if [ ! -e "${hook?}" ] || [ ! -L "${hook?}" ] ; then
-                rm -f "${hook?}"
-                ln -sf "${hook_name}" "${hook?}"
-            fi
+            refresh_create_link "${hook_name}" "${hook?}" "$lnarg"
         done
         # override if need be by the submodules' own hooks
         for hook_name in "${COREDIR?}/${repo?}/.git-hooks"/* ; do
@@ -53,10 +64,7 @@ refresh_submodule_hooks()
                 continue
             fi
             hook="${repo?}/.git/hooks/${hook_name##*/}"
-            if [ ! -e "${hook?}" ] || [ ! -L "${hook?}" ] ; then
-                rm -f "${hook?}"
-                ln -sf "${hook_name}" "${hook?}"
-            fi
+            refresh_create_link "${hook_name}" "${hook?}" "$lnarg"
         done
     elif [ -d .git/modules/"${repo}"/hooks ] ; then
         for hook_name in "${COREDIR?}/.git-hooks"/* ; do
@@ -64,10 +72,7 @@ refresh_submodule_hooks()
                 continue
             fi
             hook=".git/modules/${repo?}/hooks/${hook_name##*/}"
-            if [ ! -e "${hook?}" ] || [ ! -L "${hook?}" ] ; then
-                rm -f "${hook?}"
-                ln -sf "${hook_name}" "${hook?}"
-            fi
+            refresh_create_link "${hook_name}" "${hook?}" "$lnarg"
         done
         # override if need be by the submodules' own hooks
         for hook_name in "${COREDIR?}/${repo?}/.git-hooks"/* ; do
@@ -75,10 +80,7 @@ refresh_submodule_hooks()
                 continue
             fi
             hook=".git/modules/${repo?}/hooks/${hook_name##*/}"
-            if [ ! -e "${hook?}" ] || [ ! -L "${hook?}" ] ; then
-                rm -f "${hook?}"
-                ln -sf "${hook_name}" "${hook?}"
-            fi
+            refresh_create_link "${hook_name}" "${hook?}" "$lnarg"
         done
     fi
 
@@ -89,63 +91,35 @@ refresh_all_hooks()
     local repo
     local hook_name
     local hook
-    local winlnk
-    local wingit
     local gitbash
-    local lnkfile=".git/hooks/pre-commit"
+    local lnarg
 
     pushd "${COREDIR?}" > /dev/null
 
     # it is 'GIT for Windows'
-    wingit=$(git --version | grep -ic windows)
     gitbash=$(echo $OSTYPE | grep -ic msys)
 
-    # In the win-git-bash, do not make links, it makes only copies
-    if [ $gitbash -eq 1 ]; then
-        if [ -d ".git" ]; then
-            if [ ! -e "${lnkfile}" ] || [ ! -L "${lnkfile}" ] ; then
-                # here when wrong link then the file not exist
-                echo "Your hooks not right, solve this in cygwin with"
-                echo "   ./g -z"
-            fi
-        fi
-    else
-        if [ $wingit -eq 1 ]; then
-            # There's no ".git" e.g. in a secondary worktree
-            if [ -d ".git" ]; then
-                winlnk=0
-                if [ -e "${lnkfile}" ] && [ -L "${lnkfile}" ] ; then
-                    # if linux-links or windows-links?
-                    # dos dir output windows link:
-                    #   04.09.2020  10:54    <SYMLINK>      pre-commit 
[..\..\.git-hooks\pre-commit]
-                    # dos dir output linux link:
-                    #   file not found
-                    winlnk=$(cmd /C "DIR ${lnkfile//'/'/'\'}" 2>&1)
-                    winlnk=$(echo "$winlnk" | grep -icE 
"<SYMLINK>.*${lnkfile##*/} \[")
-                fi
-
-                if [ $winlnk -eq 0 ]; then
-                    echo "You using GIT for Windows, but the hook-links not 
right, change with mklink"
-                    cat .git-hooks/README
-                fi
-            fi
-        else
-            # There's no ".git" e.g. in a secondary worktree
-            if [ -d ".git" ]; then
-                for hook_name in "${COREDIR?}/.git-hooks"/* ; do
-                    hook=".git/hooks/${hook_name##*/}"
-                    if [ ! -e "${hook?}" ] || [ ! -L "${hook?}" ] ; then
-                        rm -f "${hook?}"
-                        ln -sf "${hook_name}" "${hook?}"
-                    fi
-                done
-            fi
-
-            for repo in ${SUBMODULES_ALL?} ; do
-                refresh_submodule_hooks "$repo"
-            done
-        fi
+    # git-bash/MSYS doesn't create symlinks by default, and "real" symlinks 
are restricted to
+    # Admin-mode or when devmode is activated, junction points as fallback 
would work for bash/
+    # regular use but not when git tries to spawn them, similar for plain 
windows shortcuts (worse
+    # because running the hooks will fail silently/they'd be inactive)
+    # ln -s without setting MSYS to contain 
winsymlinks:{lnk,native,nativestrict,sys} to force one
+    # of the other modes described above will do plain copies.
+    # So in case of git-bash use hardlinks since those work just fine, 
everywhere else use symlinks
+    if [ $gitbash -ne 1 ]; then
+        lnarg="--symbolic"
     fi
+    # There's no ".git" e.g. in a secondary worktree
+    if [ -d ".git" ]; then
+        for hook_name in "${COREDIR?}/.git-hooks"/* ; do
+            hook=".git/hooks/${hook_name##*/}"
+            refresh_create_link "${hook_name}" "${hook?}" "$lnarg"
+        done
+    fi
+
+    for repo in ${SUBMODULES_ALL?} ; do
+        refresh_submodule_hooks "$repo" "$lnarg"
+    done
 
     popd > /dev/null
 

Reply via email to