#!/usr/bin/env bash # sync-upstream.sh - Sync and compare upstream quickemu/quickget with qget templates # Downloads upstream quickget, parses OS functions, and compares with actions/ set -euo pipefail # Configuration UPSTREAM_URL="https://raw.githubusercontent.com/quickemu-project/quickemu/master/quickget" SCRIPT_DIR="$(dirname "$0")" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" ACTIONS_DIR="${PROJECT_DIR}/actions" UPSTREAM_CACHE="${TMPDIR:-/tmp}/quickget-upstream-$$" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Options SHOW_ALL=false SHOW_MISSING=false SHOW_EXTRA=false SHOW_DIFF=false FILTER_OS="" usage() { cat </dev/null; then log_error "Failed to download upstream quickget" exit 1 fi log_success "Downloaded upstream quickget ($(wc -l <"$UPSTREAM_CACHE") lines)" } # Extract OS names from upstream quickget extract_upstream_os() { # Extract from os_info case statement grep -oE '^\s+[a-z][a-z0-9_-]+\)' "$UPSTREAM_CACHE" 2>/dev/null | sed 's/)//;s/^[[:space:]]*//' | sort -u } # Extract function names (make_, releases_, get_) extract_upstream_functions() { local os_name="$1" # Find functions related to this OS grep -oE "^(function )?(make_|releases_|get_)${os_name}\(\)" "$UPSTREAM_CACHE" 2>/dev/null | sed 's/^function //;s/()$//' | sort -u } # Get local qget OS names from actions/ get_local_os() { if [[ -d "$ACTIONS_DIR" ]]; then ls -1 "$ACTIONS_DIR/" 2>/dev/null | sort -u fi } # Get function count for OS in upstream get_upstream_function_count() { local os_name="$1" extract_upstream_functions "$os_name" | wc -l } # Get function count for OS in local actions get_local_function_count() { local os_name="$1" local action_file="${ACTIONS_DIR}/${os_name}" if [[ -f "$action_file" ]]; then # Count function-like patterns: make_, releases_, get_ grep -cE '^(make_|releases_|get_)' "$action_file" 2>/dev/null || echo "0" else echo "0" fi } # Show diff for specific OS show_os_diff() { local os_name="$1" local local_file="${ACTIONS_DIR}/${os_name}" echo "" echo "=== Diff for: ${os_name} ===" echo "" # Get upstream functions echo "Upstream functions:" extract_upstream_functions "$os_name" | sed 's/^/ /' echo "" # Get local functions if [[ -f "$local_file" ]]; then echo "Local (qget) functions:" grep -oE '^(make_|releases_|get_)[a-z_]*' "$local_file" 2>/dev/null | sort -u | sed 's/^/ /' echo "" else echo "Local: (not found)" echo "" fi # Function count comparison local up_count=$(get_upstream_function_count "$os_name") local local_count=$(get_local_function_count "$os_name") echo "Function counts - Upstream: $up_count, Local: $local_count" } # Main comparison logic run_comparison() { log_info "Extracting OS from upstream quickget..." local upstream_os upstream_os=$(extract_upstream_os) local upstream_count upstream_count=$(echo "$upstream_os" | grep -c . || echo "0") log_success "Found $upstream_count OS in upstream" log_info "Extracting OS from local actions/..." local local_os local_os=$(get_local_os) local local_count local_count=$(echo "$local_os" | grep -c . || echo "0") log_success "Found $local_count OS in local actions/" echo "" echo "============================================" echo "Comparison Results" echo "============================================" echo "" # Calculate differences # OS only in upstream (missing from qget) local missing_os missing_os=$(comm -23 <(echo "$upstream_os") <(echo "$local_os") 2>/dev/null || echo "") # OS only in local qget (extra compared to upstream) local extra_os extra_os=$(comm -13 <(echo "$upstream_os") <(echo "$local_os") 2>/dev/null || echo "") # Common OS (for diff comparison) local common_os common_os=$(comm -12 <(echo "$upstream_os") <(echo "$local_os") 2>/dev/null || echo "") # Show results based on options if [[ "$SHOW_MISSING" == "true" || "$SHOW_ALL" == "true" ]]; then echo "----------------------------------------" echo "MISSING in qget (only in upstream):" echo "----------------------------------------" if [[ -n "$missing_os" ]]; then if [[ -n "$FILTER_OS" ]]; then echo "$missing_os" | grep "^${FILTER_OS}$" || echo " (none matching filter)" else echo "$missing_os" | sed 's/^/ /' fi else echo " (none)" fi echo "" fi if [[ "$SHOW_EXTRA" == "true" || "$SHOW_ALL" == "true" ]]; then echo "----------------------------------------" echo "EXTRA in qget (not in upstream):" echo "----------------------------------------" if [[ -n "$extra_os" ]]; then if [[ -n "$FILTER_OS" ]]; then echo "$extra_os" | grep "^${FILTER_OS}$" || echo " (none matching filter)" else echo "$extra_os" | sed 's/^/ /' fi else echo " (none)" fi echo "" fi if [[ "$SHOW_DIFF" == "true" || "$SHOW_ALL" == "true" ]]; then echo "----------------------------------------" echo "IMPLEMENTATION DIFF (common OS with differences):" echo "----------------------------------------" local has_diff=false # Check each common OS for differences while IFS= read -r os_name; do [[ -z "$os_name" ]] && continue [[ -n "$FILTER_OS" && "$os_name" != "$FILTER_OS" ]] && continue local up_count local_count up_count=$(get_upstream_function_count "$os_name") local_count=$(get_local_function_count "$os_name") if [[ "$up_count" != "$local_count" ]]; then has_diff=true if [[ "$SHOW_DIFF" == "true" ]]; then show_os_diff "$os_name" else echo " $os_name: upstream=$up_count functions, local=$local_count functions" fi fi done <<<"$common_os" if [[ "$has_diff" == "false" ]]; then echo " (no implementation differences found)" fi echo "" fi # Summary echo "============================================" echo "Summary:" echo "============================================" echo " Upstream OS: $upstream_count" echo " Local OS: $local_count" echo " Missing: $(echo "$missing_os" | grep -c . || echo "0")" echo " Extra: $(echo "$extra_os" | grep -c . || echo "0")" echo " Common: $(echo "$common_os" | grep -c . || echo "0")" } # Main execution main() { cd "$PROJECT_DIR" # Check if actions directory exists if [[ ! -d "$ACTIONS_DIR" ]]; then log_error "actions/ directory not found in $PROJECT_DIR" exit 1 fi # Download upstream download_upstream # Run comparison run_comparison log_success "Comparison complete!" } main "$@"