Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 30 additions & 16 deletions lib/bash/git/lib_git.sh
Original file line number Diff line number Diff line change
Expand Up @@ -164,28 +164,42 @@ __git_path_matches_allowed_path__() {

__git_only_path_dirty__() {
local allowed_path="$1"
local status_output line path source_path destination_path
local status_file status_record status_code path related_path

status_output="$(git status --porcelain --untracked-files=no --ignore-submodules=none)"
[[ -z "$status_output" ]] && return 1
std_make_temp_file status_file base-git-status || return 1
if ! git status --porcelain=v1 --untracked-files=no --ignore-submodules=none -z > "$status_file"; then
std_unregister_cleanup_path "$status_file"
rm -f -- "$status_file"
return 1
fi
if [[ ! -s "$status_file" ]]; then
std_unregister_cleanup_path "$status_file"
rm -f -- "$status_file"
return 1
fi

while IFS= read -r line; do
[[ -z "$line" ]] && continue
path="${line:3}"
if [[ "$path" == *" -> "* ]]; then
source_path="${path%% -> *}"
destination_path="${path#* -> }"
if ! __git_path_matches_allowed_path__ "$source_path" "$allowed_path" ||
! __git_path_matches_allowed_path__ "$destination_path" "$allowed_path"; then
return 1
fi
continue
fi
while IFS= read -r -d '' status_record; do
[[ -n "$status_record" ]] || continue
status_code="${status_record:0:2}"
path="${status_record:3}"
if ! __git_path_matches_allowed_path__ "$path" "$allowed_path"; then
std_unregister_cleanup_path "$status_file"
rm -f -- "$status_file"
return 1
fi
done <<< "$status_output"

if [[ "$status_code" == *R* || "$status_code" == *C* ]]; then
if ! IFS= read -r -d '' related_path ||
! __git_path_matches_allowed_path__ "$related_path" "$allowed_path"; then
std_unregister_cleanup_path "$status_file"
rm -f -- "$status_file"
return 1
fi
fi
done < "$status_file"

std_unregister_cleanup_path "$status_file"
rm -f -- "$status_file"
return 0
}

Expand Down
18 changes: 18 additions & 0 deletions lib/bash/git/tests/lib_git.bats
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,24 @@ EOF
[ "$rc" -eq 0 ]
}

@test "__git_only_path_dirty__ accepts tracked paths containing spaces" {
local repo="$TEST_TMPDIR/repo"
local rc

init_git_repo "$repo"
mkdir -p "$repo/shared"
printf 'one\n' > "$repo/shared/hello world.txt"
commit_all "$repo" "Initial commit"
printf 'local change\n' >> "$repo/shared/hello world.txt"

pushd "$repo" >/dev/null
__git_only_path_dirty__ "shared"
rc=$?
popd >/dev/null

[ "$rc" -eq 0 ]
}

@test "__git_only_path_dirty__ does not treat sibling path prefixes as allowed" {
local repo="$TEST_TMPDIR/repo"
local rc
Expand Down
Loading