#!/bin/bash # update_copyright.sh # Updates copyright year ranges in a source file based on git history # # Usage: ./update_copyright.sh [--dry-run] # # Examples: # # Update a single file # ./update_copyright.sh src/main.cpp # # # Dry-run on a single file # ./update_copyright.sh --dry-run src/main.cpp # # # Update all C++ files using find -exec # find src \( -name "*.cpp" -o -name "*.hpp" \) -exec ./update_copyright.sh {} \; # # # Dry-run on all C++ files # find src \( -name "*.cpp" -o -name "*.hpp" \) -exec ./update_copyright.sh --dry-run {} \; set -e # Check for dry-run flag DRY_RUN=false FILE="" if [ "$1" = "--dry-run" ]; then DRY_RUN=true FILE="$2" elif [ "$1" = "--help" ] || [ "$1" = "-h" ]; then grep "^#" "$0" | sed 's/^# \?//' exit 0 else FILE="$1" fi # Check if file argument provided if [ -z "$FILE" ]; then echo "Error: No file specified" echo "Usage: $0 [--dry-run] " echo "Run '$0 --help' for more information" exit 1 fi # Check if file exists if [ ! -f "$FILE" ]; then echo "Error: File not found: $FILE" exit 1 fi # Get the repository root REPO_ROOT=$(git rev-parse --show-toplevel) cd "$REPO_ROOT" # Copyright holder name COPYRIGHT_HOLDER="Moritz Martinius" # Function to get first and last commit years for a file get_years_for_file() { local file="$1" # Get the year of the first commit that touched this file first_year=$(git log --follow --format=%ad --date=format:%Y --reverse "$file" 2>/dev/null | head -1) # Get the year of the last commit that touched this file last_year=$(git log --follow --format=%ad --date=format:%Y -1 "$file" 2>/dev/null) # If file is not in git, use current year if [ -z "$first_year" ]; then first_year=$(date +%Y) last_year=$(date +%Y) fi echo "$first_year $last_year" } # Get years from git history read -r first_year last_year <<< "$(get_years_for_file "$FILE")" # Determine the copyright year string if [ "$first_year" = "$last_year" ]; then year_string="$first_year" else year_string="$first_year-$last_year" fi # Check if file has a copyright notice if ! grep -q "Copyright (C)" "$FILE"; then echo "No copyright notice found in $FILE, skipping" exit 0 fi if [ "$DRY_RUN" = true ]; then # Just show what would be changed current_year=$(grep "Copyright (C)" "$FILE" | sed -n 's/.*Copyright (C) \([0-9]\{4\}\(-[0-9]\{4\}\)\?\).*/\1/p' | head -1) if [ "$current_year" != "$year_string" ]; then echo "Would update $FILE: $current_year → $year_string" else echo "No change needed for $FILE (already $year_string)" fi else # Update the copyright line # Matches patterns like "Copyright (C) 2023 Moritz Martinius" or "Copyright (C) 2023-2024 Moritz Martinius" # Handle variable whitespace between year and name # Get current year from file for comparison current_year=$(grep "Copyright (C)" "$FILE" | sed -n 's/.*Copyright (C) \([0-9]\{4\}\(-[0-9]\{4\}\)\?\).*/\1/p' | head -1) if [ "$current_year" = "$year_string" ]; then echo "No changes needed for $FILE (already $year_string)" else sed -i "s/Copyright (C) [0-9]\{4\}\(-[0-9]\{4\}\)\? \+$COPYRIGHT_HOLDER/Copyright (C) $year_string $COPYRIGHT_HOLDER/" "$FILE" echo "✓ Updated $FILE: $current_year → $year_string" fi fi