summaryrefslogtreecommitdiffstats
path: root/scripts/git-resolve.sh
diff options
context:
space:
mode:
authorZeng Chi <zengchi@kylinos.cn>2026-09-21 18:24:42 +0800
committerSean Christopherson <seanjc@google.com>2026-09-22 08:36:16 -0700
commit119e9db233ad0f4cbd4cfb9f9385a7bca378b37d (patch)
tree660d50d4139cb750fbde1ae3432452c20726c99d /scripts/git-resolve.sh
downloadlinux-stable-119e9db233ad0f4cbd4cfb9f9385a7bca378b37d.tar.gz
linux-stable-119e9db233ad0f4cbd4cfb9f9385a7bca378b37d.zip
KVM: Don't pre-reserve xarray entries when storing empty/NULL attributesgrafted
Skip the xarray reservation loop when clearing all memory attributes, as storing NULL only erases the entry and never needs to allocate, so no reservation (and no cleanup of a failed one) is required in that case. Suggested-by: Sean Christopherson <seanjc@google.com> Cc: David Ballesteros <davimaba.v@proton.me> Signed-off-by: Zeng Chi <zengchi@kylinos.cn> Link: https://patch.msgid.link/20260921102442.1232375-1-zeng_chi911@163.com [sean: split to separate patch] Signed-off-by: Sean Christopherson <seanjc@google.com>
Diffstat (limited to 'scripts/git-resolve.sh')
-rwxr-xr-xscripts/git-resolve.sh201
1 files changed, 201 insertions, 0 deletions
diff --git a/scripts/git-resolve.sh b/scripts/git-resolve.sh
new file mode 100755
index 000000000..e9b5940c0
--- /dev/null
+++ b/scripts/git-resolve.sh
@@ -0,0 +1,201 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# (c) 2025, Sasha Levin <sashal@kernel.org>
+
+usage() {
+ echo "Usage: $(basename "$0") [--selftest] [--force] <commit-id> [commit-subject]"
+ echo "Resolves a short git commit ID to its full SHA-1 hash, particularly useful for fixing references in commit messages."
+ echo ""
+ echo "Arguments:"
+ echo " --selftest Run self-tests"
+ echo " --force Try to find commit by subject if ID lookup fails"
+ echo " commit-id Short git commit ID to resolve"
+ echo " commit-subject Optional commit subject to help resolve between multiple matches"
+ exit 1
+}
+
+# Convert subject with ellipsis to grep pattern
+convert_to_grep_pattern() {
+ local subject="$1"
+ # First escape ALL regex special characters
+ local escaped_subject
+ escaped_subject=$(printf '%s\n' "$subject" | sed 's/[[\.*^$()+?{}|]/\\&/g')
+ # Also escape colons, parentheses, and hyphens as they are special in our context
+ escaped_subject=$(echo "$escaped_subject" | sed 's/[:-]/\\&/g')
+ # Then convert escaped ... sequence to .*?
+ escaped_subject=$(echo "$escaped_subject" | sed 's/\\\.\\\.\\\./.*?/g')
+ echo "^${escaped_subject}$"
+}
+
+git_resolve_commit() {
+ local force=0
+ if [ "$1" = "--force" ]; then
+ force=1
+ shift
+ fi
+
+ # Split input into commit ID and subject
+ local input="$*"
+ local commit_id="${input%% *}"
+ local subject=""
+
+ # Extract subject if present (everything after the first space)
+ if [[ "$input" == *" "* ]]; then
+ subject="${input#* }"
+ # Strip the ("...") quotes if present
+ subject="${subject#*(\"}"
+ subject="${subject%\")*}"
+ fi
+
+ # Get all possible matching commit IDs
+ local matches
+ readarray -t matches < <(git rev-parse --disambiguate="$commit_id" 2>/dev/null)
+
+ # Return immediately if we have exactly one match
+ if [ ${#matches[@]} -eq 1 ]; then
+ echo "${matches[0]}"
+ return 0
+ fi
+
+ # If no matches and not in force mode, return failure
+ if [ ${#matches[@]} -eq 0 ] && [ $force -eq 0 ]; then
+ return 1
+ fi
+
+ # If we have a subject, try to find a match with that subject
+ if [ -n "$subject" ]; then
+ # Convert subject with possible ellipsis to grep pattern
+ local grep_pattern
+ grep_pattern=$(convert_to_grep_pattern "$subject")
+
+ # In force mode with no ID matches, use git log --grep directly
+ if [ ${#matches[@]} -eq 0 ] && [ $force -eq 1 ]; then
+ # Use git log to search, but filter to ensure subject matches exactly
+ local match
+ match=$(git log --format="%H %s" --grep="$grep_pattern" --perl-regexp -10 | \
+ while read -r hash subject; do
+ if echo "$subject" | grep -qP "$grep_pattern"; then
+ echo "$hash"
+ break
+ fi
+ done)
+ if [ -n "$match" ]; then
+ echo "$match"
+ return 0
+ fi
+ else
+ # Normal subject matching for existing matches
+ for match in "${matches[@]}"; do
+ if git log -1 --format="%s" "$match" | grep -qP "$grep_pattern"; then
+ echo "$match"
+ return 0
+ fi
+ done
+ fi
+ fi
+
+ # No match found
+ return 1
+}
+
+run_selftest() {
+ local test_cases=(
+ '00250b5 ("MAINTAINERS: add new Rockchip SoC list")'
+ '0037727 ("KVM: selftests: Convert xen_shinfo_test away from VCPU_ID")'
+ 'ffef737 ("net/tls: Fix skb memory leak when running kTLS traffic")'
+ 'd3d7 ("cifs: Improve guard for excluding $LXDEV xattr")'
+ 'dbef ("Rename .data.once to .data..once to fix resetting WARN*_ONCE")'
+ '12345678' # Non-existent commit
+ '12345 ("I'\''m a dummy commit")' # Valid prefix but wrong subject
+ '--force 99999999 ("net/tls: Fix skb memory leak when running kTLS traffic")' # Force mode with non-existent ID but valid subject
+ '83be ("firmware: ... auto-update: fix poll_complete() ... errors")' # Wildcard test
+ '--force 999999999999 ("firmware: ... auto-update: fix poll_complete() ... errors")' # Force mode wildcard test
+ )
+
+ local expected=(
+ "00250b529313d6262bb0ebbd6bdf0a88c809f6f0"
+ "0037727b3989c3fe1929c89a9a1dfe289ad86f58"
+ "ffef737fd0372ca462b5be3e7a592a8929a82752"
+ "d3d797e326533794c3f707ce1761da7a8895458c"
+ "dbefa1f31a91670c9e7dac9b559625336206466f"
+ "" # Expect empty output for non-existent commit
+ "" # Expect empty output for wrong subject
+ "ffef737fd0372ca462b5be3e7a592a8929a82752" # Should find commit by subject in force mode
+ "83beece5aff75879bdfc6df8ba84ea88fd93050e" # Wildcard test
+ "83beece5aff75879bdfc6df8ba84ea88fd93050e" # Force mode wildcard test
+ )
+
+ local expected_exit_codes=(
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1 # Expect failure for non-existent commit
+ 1 # Expect failure for wrong subject
+ 0 # Should succeed in force mode
+ 0 # Should succeed with wildcard
+ 0 # Should succeed with force mode and wildcard
+ )
+
+ local failed=0
+
+ echo "Running self-tests..."
+ for i in "${!test_cases[@]}"; do
+ # Capture both output and exit code
+ local result
+ result=$(git_resolve_commit ${test_cases[$i]}) # Removed quotes to allow --force to be parsed
+ local exit_code=$?
+
+ # Check both output and exit code
+ if [ "$result" != "${expected[$i]}" ] || [ $exit_code != ${expected_exit_codes[$i]} ]; then
+ echo "Test case $((i+1)) FAILED"
+ echo "Input: ${test_cases[$i]}"
+ echo "Expected output: '${expected[$i]}'"
+ echo "Got output: '$result'"
+ echo "Expected exit code: ${expected_exit_codes[$i]}"
+ echo "Got exit code: $exit_code"
+ failed=1
+ else
+ echo "Test case $((i+1)) PASSED"
+ fi
+ done
+
+ if [ $failed -eq 0 ]; then
+ echo "All tests passed!"
+ exit 0
+ else
+ echo "Some tests failed!"
+ exit 1
+ fi
+}
+
+# Check for selftest
+if [ "$1" = "--selftest" ]; then
+ run_selftest
+ exit $?
+fi
+
+# Handle --force flag
+force=""
+if [ "$1" = "--force" ]; then
+ force="--force"
+ shift
+fi
+
+# Verify arguments
+if [ $# -eq 0 ]; then
+ usage
+fi
+
+# Skip validation in force mode
+if [ -z "$force" ]; then
+ # Validate that the first argument matches at least one git commit
+ if [ "$(git rev-parse --disambiguate="$1" 2>/dev/null | wc -l)" -eq 0 ]; then
+ echo "Error: '$1' does not match any git commit"
+ exit 1
+ fi
+fi
+
+git_resolve_commit $force "$@"
+exit $?