From acafa1af798b2ba2debe082310a5ebeb68e19f12 Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Sat, 12 Sep 2020 23:50:37 -0700 Subject: [PATCH] update.sh: create a fetch "quarantine" area Prepare a "quarantine" directory for incoming fetches that will allow all changes that result from an abandoned fetch to be easily discarded. Arrange for it to be automatically removed when update.sh exits. Future changes will actually redirect fetches into this quarantine area. Signed-off-by: Kyle J. McKay --- jobd/update.sh | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/jobd/update.sh b/jobd/update.sh index e2d1dce..ea21e07 100755 --- a/jobd/update.sh +++ b/jobd/update.sh @@ -106,7 +106,8 @@ git_bzr_fetch() ( [ -n "$cfg_mirror" ] || { echo "Mirroring is disabled" >&2; exit 0; } umask 002 -[ "$cfg_permission_control" != "Hooks" ] || umask 000 +dperms=2775 +[ "$cfg_permission_control" != "Hooks" ] || { umask 000; dperms=2777; } clean_git_env proj="${1%.git}" @@ -121,11 +122,15 @@ cd "$cfg_reporoot/$proj.git" check_and_set_needsgc bang_log= +incoming_fetch= +incoming_objs= cleanup_exit() { ec=$? if [ $ec != 0 ]; then echo "update failed dir: $PWD" >&2 fi + [ -z "$incoming_fetch" ] || rm -rf "$incoming_fetch" + [ -z "$incoming_objs" ] || rm -rf "$incoming_objs" [ -z "$bang_log" ] || rm -f "$bang_log" } trap 'cleanup_exit' EXIT @@ -153,6 +158,13 @@ rm -f FETCH_HEAD # Remove any stale ref locks clear_stale_ref_locks +# Remove any stale incoming-* object quarantine directories that are +# more than 12 hours old. These are new with Git >= 2.11.0. +# But we also create our own during the fetch process as Git's quarantine +# only applies to incoming receive-pack which we imitate for our fetch. +find -L . objects -maxdepth 1 -type d -name 'incoming-?*' -mmin +720 \ + -exec rm -rf '{}' + || : + # A previous failed update attempt can leave a huge tmp_pack_XXXXXX file behind. # Since no pushes are allowed to mirrors, we know that any such files that exist # at this point in time are garbage and can be safely deleted, we do not even @@ -166,6 +178,33 @@ find -L objects/pack -maxdepth 1 -type f -name "tmp_idx_?*" -exec rm -f '{}' + | [ -d reflogs ] || mkdir -p reflogs >/dev/null 2>&1 || : [ -d reflogs ] +# Create a "quarantine" area to fetch into +# This is set up similarly to the way the "repack" directory is set +# up for gc in that it's a subdirectory that's a whole "git" directory +# but it uses the existing objects directory as an alternate and its +# own objects subdirectory is a symlink to a subdirectory of the real +# objects directory (to guarantee that packs/objects can be moved rather +# than copied). It starts out with a copy of all of the project's refs. +# A successful fetch will "unquarantine" fetched objects/packs + ref changes +incoming_objs="$(mktemp -d "$PWD/objects/incoming-XXXXXX")" +incoming_objs="$(cd "$incoming_objs" && pwd -P)" +chmod "$dperms" "$incoming_objs" +mkdir "$incoming_objs/pack" +mkdir "$incoming_objs/info" +printf '%s\n' "$PWD/objects" >"$incoming_objs/info/alternates" +incoming_fetch="$(mktemp -d "$PWD/incoming-XXXXXX")" +incoming_fetch="$(cd "$incoming_fetch" && pwd -P)" +chmod "$dperms" "$incoming_fetch" +ln -s "$incoming_objs" "$incoming_fetch/objects" +mkdir "$incoming_fetch/refs" +ln -s "$PWD/config" "$incoming_fetch/config" +git for-each-ref --format='%(objectname) %(refname)' >"$incoming_fetch/packed-refs" +cat HEAD >"$incoming_fetch/HEAD" +# Make sure the incoming packed-refs file is properly peeled +git --git-dir="$incoming_fetch" pack-refs --all --prune +# link to svn if it exists +[ ! -d svn ] || ln -s "$PWD/svn" "$incoming_fetch/svn" + keep_bang_log= do_check_after_refs=1 bang_setup -- 2.11.4.GIT