fix(agents-repo-sync): refuse a .git that is not a valid gitdir
A half-removed AGENTS/.git passed the test -d guard, so git walked up and committed (and bundled) the enclosing repository. Require rev-parse --git-dir to report .git; agents-cleanup uses the same test.
This commit is contained in:
@@ -6,7 +6,9 @@
|
||||
#
|
||||
# DESCRIPTION
|
||||
# Stages everything in <dir> and commits it with <message>. Shared by
|
||||
# agents-init and agents-vault.
|
||||
# agents-init, agents-vault and agents-cleanup. <dir> must be the root of
|
||||
# its own repository: a .git directory that is not a valid gitdir is
|
||||
# refused, because git would otherwise commit the enclosing repository.
|
||||
#
|
||||
# It never touches the network, and that is the point rather than an
|
||||
# omission. Both callers run on every agent launch, synchronously, ahead
|
||||
@@ -36,7 +38,8 @@
|
||||
#
|
||||
# EXIT STATUS
|
||||
# 0 Committed, or nothing needed committing
|
||||
# 1 <dir> is not a git repository, arguments were missing, or the commit
|
||||
# 1 <dir> is not the root of its own git repository (a broken .git
|
||||
# directory inside another repository counts as not), arguments were missing, or the commit
|
||||
# itself failed (e.g. a pre-commit/commit-msg hook rejected it)
|
||||
# 2 A rebase is in progress; nothing committed, nothing touched
|
||||
#
|
||||
@@ -48,9 +51,12 @@
|
||||
# _agents_repo_sync /path/to/AGENTS "chore: sync AGENTS repository"
|
||||
function _agents_repo_sync --argument-names dir msg
|
||||
test -n "$dir" -a -n "$msg"; or return 1
|
||||
test -d "$dir/.git"; or return 1
|
||||
# Not `test -d "$dir/.git"`: a half-deleted .git directory passes that, and
|
||||
# git then walks up, finds the enclosing repository and commits *that*.
|
||||
# A valid repository rooted at <dir> reports its git dir as plain ".git".
|
||||
test "$(git -C "$dir" rev-parse --git-dir 2>/dev/null)" = .git; or return 1
|
||||
|
||||
# The guard above proved .git is a directory, so these are the same two
|
||||
# The guard above proved <dir> has its own .git, so these are the same two
|
||||
# paths `agents-vault --status` reports an unresolved rebase from.
|
||||
if test -d "$dir/.git/rebase-merge"; or test -d "$dir/.git/rebase-apply"
|
||||
echo "_agents_repo_sync: unresolved rebase in $dir; nothing committed" >&2
|
||||
|
||||
@@ -136,7 +136,9 @@ function agents-cleanup --description 'undo agents-init: restore real files, arc
|
||||
# Resolved, because link targets are compared after realpath, which
|
||||
# also resolves any symlinked parent of $root.
|
||||
set agents_dir (realpath -- "$agents_dir")
|
||||
test -d "$agents_dir/.git"; and set has_repo 1
|
||||
# A .git that is not a valid gitdir (half-removed) is "not a repository";
|
||||
# git would otherwise resolve to the enclosing project.
|
||||
test "$(git -C "$agents_dir" rev-parse --git-dir 2>/dev/null)" = .git; and set has_repo 1
|
||||
end
|
||||
|
||||
if test $has_repo -eq 1
|
||||
|
||||
@@ -379,5 +379,19 @@ end
|
||||
check "directive-only: deleted" false (test -e $v1/AGENTS.md -o -L $v1/AGENTS.md; and echo true; or echo false)
|
||||
check "no directive: content identical" "$v2before" (string collect <$v2/AGENTS.md)
|
||||
|
||||
section "agents-cleanup: invalid AGENTS/.git never commits the outer repo"
|
||||
fresh_state
|
||||
set -l i1 (scaffolded_repo)
|
||||
echo secret >$i1/untracked-secret.txt
|
||||
rm -rf $i1/AGENTS/.git/HEAD $i1/AGENTS/.git/objects
|
||||
set -l i1before (git -C $i1 rev-list --all | count)
|
||||
pushd $i1 >/dev/null
|
||||
set -l i1rc (agents-cleanup --silent 2>/dev/null; echo $status)
|
||||
popd >/dev/null
|
||||
check "invalid .git: exits 0" 0 "$i1rc"
|
||||
check "invalid .git: outer repo untouched" "$i1before" (git -C $i1 rev-list --all | count)
|
||||
check "invalid .git: no bundle" 0 (count $XDG_STATE_HOME/agents-cleanup/*.bundle 2>/dev/null)
|
||||
check "invalid .git: AGENTS/ removed" false (test -e $i1/AGENTS; and echo true; or echo false)
|
||||
|
||||
cleanup
|
||||
report
|
||||
|
||||
Reference in New Issue
Block a user