Diff options
| -rwxr-xr-x | custom/hooks/post-receive.commit-graph | 34 | |
| -rwxr-xr-x | tests/t0507-hooks.sh | 24 |
2 files changed, 57 insertions, 1 deletion
diff --git a/custom/hooks/post-receive.commit-graph b/custom/hooks/post-receive.commit-graph new file mode 100755 index 0000000..51d8c3c --- /dev/null +++ b/custom/hooks/post-receive.commit-graph @@ -0,0 +1,34 @@ +#!/bin/sh + +# Brings the repository's commit-graph up to date after a push. cgit's log, +# blame and graph pages then read commits from it instead of parsing each one +# out of the object store, and its changed path filters let a log or blame of +# one file skip the commits that never touched it. git gc writes a graph now +# and then, but starts the filters only when one is written with them, as this +# does, and keeps them from then on. +# +# --split writes each push's new commits as a small layer over the last, and +# git merges the layers as they pile up, so a push costs little. A git too old +# for these options leaves the graph as it was, and nothing here complains or +# exits nonzero, so the pusher is not shown an error over a missing speedup. +# +# To install the hook, copy or link it to hooks/post-receive in each +# repository. Git runs one post-receive per repository, so fold this together +# with the other hooks here to have more than one. + +set -eu + +# The pushing user's umask decides the mode of a new graph file in a +# repository git does not share, so force one that leaves it readable by the +# web server. git writes a shared repository's files group writable itself. +case "$(git config --get core.sharedRepository | tr '[:upper:]' '[:lower:]')" in +""|umask|0|false|no|off) + umask 022 + ;; +*) + umask 002 + ;; +esac + +git commit-graph write --reachable --split --changed-paths --no-progress \ + >/dev/null 2>&1 || : diff --git a/tests/t0507-hooks.sh b/tests/t0507-hooks.sh index 8802ccc..8a45f81 100755 --- a/tests/t0507-hooks.sh +++ b/tests/t0507-hooks.sh @@ -2,7 +2,7 @@ # Checks the post-receive hooks under custom/hooks. The cache hook runs from a # copy pointed at a cache and a scan path in the trash directory, since the -# shipped one names the system's own, and both hooks run inside bare +# shipped one names the system's own, and the hooks run inside bare # repositories the way git runs them after a push. test_description='Check the shipped post-receive hooks' @@ -125,4 +125,26 @@ test_expect_success SANITY 'the age hook keeps a shared directory group writable grep "^drwxrw[xs]" mode ' +test_expect_success 'the commit-graph hook writes a graph with path filters' ' + git init -q --bare graph.git && + git -C work push -q ../graph.git HEAD:refs/heads/main && + (cd graph.git && sh "$HOOK_DIRECTORY/post-receive.commit-graph" 2>../graph-err) && + test_must_be_empty graph-err && + test_path_is_file graph.git/objects/info/commit-graphs/commit-graph-chain && + grep -q BDAT graph.git/objects/info/commit-graphs/*.graph && + git -C graph.git commit-graph verify +' + +for shell in $shells +do + test_expect_success "a later push moves the graph on under $shell" " + cat graph.git/objects/info/commit-graphs/commit-graph-chain >chain-$shell && + test_commit -C work graph-$shell && + git -C work push -q ../graph.git HEAD:refs/heads/main && + (cd graph.git && $shell \"\$HOOK_DIRECTORY/post-receive.commit-graph\") && + ! test_cmp chain-$shell graph.git/objects/info/commit-graphs/commit-graph-chain && + git -C graph.git commit-graph verify + " +done + test_done |
