containers/apps/ci-os/packages/merge-diff/default.nix

144 lines
4 KiB
Nix
Raw Normal View History

{ 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 <path_pattern> [-o <output_file>]"
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" ];
};
}