{ pkgs, lib, gitSvPkg, ... }: with pkgs; writeShellApplication rec { name = "merge-diff"; runtimeInputs = [ gitFull jq coreutils gnugrep gawk gitSvPkg ]; # Define the shell script text = '' #!/usr/bin/env bash set -euo pipefail # Function to display usage usage() { echo "Usage: $0 -p [-o ]" echo " -p, --pattern Path pattern to filter changed files (can be specified multiple times)" echo " -o, --output Output file (defaults to stdout)" echo " -h, --help Display this help message" exit 1 } # Parse command-line arguments PATTERNS=() OUTPUT="" while [[ $# -gt 0 ]]; do case "$1" in -p|--pattern) PATTERNS+=("$2") shift 2 ;; -o|--output) OUTPUT="$2" shift 2 ;; -h|--help) usage ;; *) echo "Unknown option: $1" usage ;; esac done if [ ''${#PATTERNS[@]} -eq 0 ]; then echo "Error: At least one path pattern must be specified." usage fi # Get the current commit SHA CURRENT_SHA=$(git rev-parse HEAD) # Get parent commits PARENT_COUNT=$(git rev-list --parents -n 1 "$CURRENT_SHA" | wc -w) if [ "$PARENT_COUNT" -gt 2 ]; then echo "This is a merge commit with $((PARENT_COUNT - 1)) parents." # For simplicity, comparing with the first parent PARENT_SHA=$(git rev-parse HEAD^1) elif [ "$PARENT_COUNT" -eq 2 ]; then # Regular commit with one parent PARENT_SHA=$(git rev-parse HEAD^1) else echo "Single commit with no parents. Listing all changes." PARENT_SHA=HEAD~1 fi echo "Current Commit SHA: $CURRENT_SHA" echo "Parent Commit SHA: $PARENT_SHA" # List changed files between parent and current commit CHANGED_FILES=$(git diff --name-only "$PARENT_SHA" "$CURRENT_SHA") echo "Changed files:" echo "$CHANGED_FILES" # Initialize an empty array for filtered changes FILTERED_CHANGES=() # Iterate over each pattern and filter changed files for pattern in "''${PATTERNS[@]}"; do while IFS= read -r file; do if [[ "$file" == "$pattern" ]]; then FILTERED_CHANGES+=("$file") fi done <<< "$CHANGED_FILES" done # Remove duplicates UNIQUE_FILTERED_CHANGES=$(printf "%s\n" "''${FILTERED_CHANGES[@]}" | sort -u) echo "Filtered changed files:" echo "$UNIQUE_FILTERED_CHANGES" # Determine if changes exist if [ -n "$UNIQUE_FILTERED_CHANGES" ]; then CHANGES_EXIST=true else CHANGES_EXIST=false fi # Determine semantic version bump using git-sv # Ensure that git-sv is available if ! command -v git-sv &> /dev/null; then echo "Error: git-sv is not installed or not in PATH." exit 1 fi # Get the semantic version bump VERSION_BUMP=$(git-sv bump --from "$PARENT_SHA" --to "$CURRENT_SHA") # Validate the version bump if [[ "$VERSION_BUMP" =~ ^(patch|minor|major)$ ]]; then echo "Version bump: $VERSION_BUMP" else echo "Error: Unexpected version bump value: $VERSION_BUMP" exit 1 fi # Convert to JSON RESULTS=$(jq -n \ --argjson filteredChanges "$(printf '%s\n' "$UNIQUE_FILTERED_CHANGES" | jq -R -s -c 'split("\n") | map(select(length > 0))')" \ --arg changesExist "$CHANGES_EXIST" \ --arg versionBump "$VERSION_BUMP" \ '{filteredChanges: $filteredChanges, changesExist: ($changesExist == "true"), versionBump: $versionBump}') # Output results if [ -n "$OUTPUT" ]; then echo "$RESULTS" > "$OUTPUT" else echo "$RESULTS" fi ''; # Metadata for the package meta = with lib; { homepage = "https://code.252.no/tommy/containers"; description = "Identify Merge Commit and List Changed Files with Flexible Filtering and Semantic Versioning"; license = licenses.mit; maintainers = with maintainers; [ "tommy-skaug" ]; }; }