From 1d5d4f1203485827df0e6620776822acb54df4ec Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Mon, 20 Mar 2017 05:12:20 -0700 Subject: [PATCH] tg.sh: fallback to tmp dir outside .git If the .git directory is not writable by the user running "tg" then fall back to using the normal temporary location and if that fails fall back to plain "/tmp" before giving up. Do this for both the per-run-of-tg temporary directory and the supposed-to-be-persistent global temporary directcory. Create the per-run temporary directory first and if the global tg-cache directory can't be created just move it into the per-run temporary directory. As part of this change, limit writing in the repository-global "tg-cache" directory to a subdirectory based on the effective user id to avoid bizarre failures where a different user needs to update a cache entry originally written by someone else. With this change it's now always possible (presuming there is a writable temporary directory available somewhere on the system) to perform the "tg" read-only operations on any git repository, even ones for which the user running "tg" only has read-only access. Although if neither "$TMPDIR" (if non-empty) nor /tmp is writable then TMPDIR will have to be explicitly set to a writable temporary directory before running "tg" for it to work. Some operations may be a bit slower if the persistent cache is not available as it will have to be built as-needed on each run, but all the read-only operations will still work fine thanks to the previous change to write tree turds in an alternate temporary directory. Signed-off-by: Kyle J. McKay --- tg.sh | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/tg.sh b/tg.sh index 94d1af7..842aea5 100644 --- a/tg.sh +++ b/tg.sh @@ -1555,11 +1555,6 @@ initial_setup() root_dir="${root_dir%/}" - # make sure global cache directory exists inside GIT_DIR - - tg_cache_dir="$git_common_dir/tg-cache" - [ -d "$tg_cache_dir" ] || mkdir "$tg_cache_dir" - # create global temporary directories, inside GIT_DIR tg_tmp_dir= @@ -1569,8 +1564,29 @@ initial_setup() trap 'exit 131' QUIT trap 'exit 134' ABRT trap 'exit 143' TERM - tg_tmp_dir="$(mktemp -d "$git_dir/tg-tmp.XXXXXX")" + tg_tmp_dir="$(mktemp -d "$git_dir/tg-tmp.XXXXXX" 2>/dev/null)" || tg_tmp_dir= + [ -n "$tg_tmp_dir" ] || tg_tmp_dir="$(mktemp -d "${TMPDIR:-/tmp}/tg-tmp.XXXXXX" 2>/dev/null)" || tg_tmp_dir= + [ -n "$tg_tmp_dir" ] || [ -z "$TMPDIR" ] || tg_tmp_dir="$(mktemp -d "/tmp/tg-tmp.XXXXXX" 2>/dev/null)" || tg_tmp_dir= tg_ref_cache="$tg_tmp_dir/tg~ref-cache" + [ -n "$tg_tmp_dir" ] && [ -w "$tg_tmp_dir" ] && { >"$tg_ref_cache"; } >/dev/null 2>&1 || + die "could not create a writable temporary directory" + + # make sure global cache directory exists inside GIT_DIR or $tg_tmp_dir + + user_id_no="$(id -u)" || : + : "${user_id_no:=_99_}" + tg_cache_dir="$git_common_dir/tg-cache" + [ -d "$tg_cache_dir" ] || mkdir "$tg_cache_dir" >/dev/null 2>&1 || tg_cache_dir= + [ -z "$tg_cache_dir" ] || tg_cache_dir="$tg_cache_dir/$user_id_no" + [ -z "$tg_cache_dir" ] || [ -d "$tg_cache_dir" ] || mkdir "$tg_cache_dir" >/dev/null 2>&1 || tg_cache_dir= + [ -z "$tg_cache_dir" ] || { >"$tg_cache_dir/.tgcache"; } >/dev/null 2>&1 || tg_cache_dir= + if [ -z "$tg_cache_dir" ]; then + tg_cache_dir="$tg_tmp_dir/tg-cache" + [ -d "$tg_cache_dir" ] || mkdir "$tg_cache_dir" >/dev/null 2>&1 || tg_cache_dir= + [ -z "$tg_cache_dir" ] || { >"$tg_cache_dir/.tgcache"; } >/dev/null 2>&1 || tg_cache_dir= + fi + [ -n "$tg_cache_dir" ] || + die "could not create a writable tg-cache directory (even a temporary one)" # GIT_ALTERNATE_OBJECT_DIRECTORIES can contain double-quoted entries # since Git v2.11.1; however, we really don't want to deal with that -- 2.11.4.GIT