summaryrefslogtreecommitdiffstats
path: root/src/triggers/partial-copy
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 14:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 14:17:27 +0000
commitaae1a14ea756102251351d96e2567b4986d30e2b (patch)
treea1af617672e26aee4c1031a3aa83e8ff08f6a0a5 /src/triggers/partial-copy
parentInitial commit. (diff)
downloadgitolite3-upstream.tar.xz
gitolite3-upstream.zip
Adding upstream version 3.6.12.upstream/3.6.12upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/triggers/partial-copy')
-rwxr-xr-xsrc/triggers/partial-copy69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/triggers/partial-copy b/src/triggers/partial-copy
new file mode 100755
index 0000000..79b4d48
--- /dev/null
+++ b/src/triggers/partial-copy
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+# this is a wee bit expensive in terms of forks etc., compared to doing it in
+# perl, but I wanted to show how *easy* it actually is now. And really,
+# you'll only notice if you access this repo like a hundred times a minute or
+# something so don't sweat it.
+
+# given a repo and a user, check if option('partialCopyOf') is set, and if so,
+# fetch all allowed branches from there.
+
+die() { echo "$@" >&2; exit 1; }
+
+# make sure we're being called from the pre_git trigger
+[ "$1" = "PRE_GIT" ] || die I must be called from PRE_GIT, not "$1"
+shift
+
+repo=$1
+user=$2
+main=`git config --file $GL_REPO_BASE/$repo.git/config --get gitolite.partialCopyOf`;
+[ -z "$main" ] && exit 0
+
+# "we", "our repo" => the partial copy
+# "main", "pco" => the one which we are a "partial copy of"
+
+cd $GL_REPO_BASE/$main.git
+
+for ref in `git for-each-ref refs/heads '--format=%(refname)'`
+do
+ cd $GL_REPO_BASE/$repo.git
+
+ gitolite access -q $repo $user R $ref &&
+ git fetch -f $GL_REPO_BASE/$main.git $ref:$ref
+done
+
+export GL_BYPASS_ACCESS_CHECKS=1
+
+# remove all refs not in main or accessible
+cd $GL_REPO_BASE/$repo.git
+
+for ref in `git for-each-ref refs/heads refs/tags '--format=%(refname)'`
+do
+ cd $GL_REPO_BASE/$main.git
+
+ if git show-ref --verify --quiet $ref &&
+ gitolite access -q $repo $user R $ref ; then
+ # ref is present in main and accessible in repo
+ continue
+ fi
+
+ git push -f $GL_REPO_BASE/$repo.git :$ref || die "FATAL: failed to delete $ref"
+done
+
+# remove all tags no longer reachable
+cd $GL_REPO_BASE/$repo.git
+
+for ref in `git for-each-ref refs/tags '--format=%(refname)'`
+do
+ SHA=`git rev-list -1 $ref`
+ for branch in `git for-each-ref refs/heads '--format=%(refname)'`
+ do
+ if [ "`git merge-base $SHA $branch`" = "$SHA" ]; then
+ # tag is reachable in current branch, continue higher loop
+ continue 2
+ fi
+ done
+ git push -f $GL_REPO_BASE/$repo.git :$ref || die "FATAL: failed to delete $ref"
+done
+
+exit 0