22
33# Required environment variables:
44# $INPUT_FILES: Pattern(s) to filter files by (e.g., "content/** data/**")
5- # $INPUT_PR: Pull request number (if running in PR context)
65# $INPUT_HEAD: Current branch or SHA for git diff
76# $INPUT_OUTPUT_FILE: Optional file to redirect output to.
8- # $GH_TOKEN: the access token
97
108# Default value for files parameter if not provided
119FILTER=${INPUT_FILES:- .}
@@ -14,63 +12,156 @@ FILTER=${INPUT_FILES:-.}
1412echo " __ using filter: __"
1513echo " $FILTER "
1614
17- # Find the file diff in the pull request or merge group
18- # If its a pull request, use the faster call to the GitHub API
19- # For push, workflow_dispatch, and merge_group, use git diff
20- if [ -n " $INPUT_PR " ]
21- then
22- echo " __ running gh pr diff __"
23- DIFF=$( gh pr diff $INPUT_PR --name-only)
24- if [ -z " $DIFF " ]; then
25- echo " __ gh pr diff failed, falling back to git diff __"
26- HEAD=$( gh pr view $INPUT_PR --json headRefName --jq .headRefName)
27- fi
28- fi
15+ # Ensure we have the latest from the remote
16+ echo " __ fetching latest changes __"
17+ git fetch --depth=1 origin main
18+ git fetch --depth=1 origin ${INPUT_HEAD:- HEAD}
2919
30- if [ -z " $DIFF " ]; then
31- # If HEAD was set from gh pr view but INPUT_HEAD is empty, use HEAD instead
32- if [ -z " $INPUT_HEAD " ] && [ -n " $HEAD " ]; then
33- INPUT_HEAD=$HEAD
34- fi
35- echo " __ using branch name $INPUT_HEAD __"
36- git fetch origin $INPUT_HEAD :refs/remotes/origin/$INPUT_HEAD
37- echo " __ running git diff __"
20+ # Get diff with status information
21+ echo " __ running git diff with status __"
22+ DIFF_OUTPUT=$( git diff --name-status origin/main origin/${INPUT_HEAD:- HEAD} )
3823
39- DIFF=$( git diff --name-only origin/main origin/$INPUT_HEAD )
40- fi
24+ # Function to extract files by pattern from diff output
25+ extract_files () {
26+ local pattern=$1
27+ local field=$2
28+ echo " $DIFF_OUTPUT " | grep -E " $pattern " | cut -f$field
29+ }
4130
42- # So we can inspect the output
43- echo " __ DIFF found __"
44- echo " $DIFF "
31+ # Extract files by status
32+ echo " __ extracting files by status __"
33+ MODIFIED_FILES=$( extract_files " ^[AM]" 2)
34+ DELETED_FILES=$( extract_files " ^D" 2)
35+ RENAMED_OLD_FILES=$( extract_files " ^R[0-9]+" 2)
36+ RENAMED_NEW_FILES=$( extract_files " ^R[0-9]+" 3)
37+
38+ # Create paired renames in format "oldname=>newname"
39+ create_rename_pairs () {
40+ local old_files=$1
41+ local new_files=$2
42+ local pairs=()
4543
46- # Filter the DIFF to just the directories specified in the input files
47- if [ " $FILTER " != " ." ]; then
48- echo " __ filtering DIFF to only include $FILTER __"
49- FILTERED_DIFF=" "
5044 IFS=$' \n '
51- for file in $DIFF ; do
45+ for i in $( seq 1 $( echo " $old_files " | wc -l) ) ; do
46+ OLD=$( echo " $old_files " | sed -n " ${i} p" )
47+ NEW=$( echo " $new_files " | sed -n " ${i} p" )
48+ pairs+=(" $OLD =>$NEW " )
49+ done
50+ unset IFS
51+
52+ printf " %s\n" " ${pairs[@]} "
53+ }
54+
55+ RENAMED_FILES_WITH_HISTORY=$( create_rename_pairs " $RENAMED_OLD_FILES " " $RENAMED_NEW_FILES " )
56+
57+ # Combine files for different outputs
58+ DIFF=$( echo -e " $MODIFIED_FILES \n$RENAMED_NEW_FILES " | sort | uniq)
59+ ALL_DIFF=$( echo -e " $MODIFIED_FILES \n$DELETED_FILES \n$RENAMED_NEW_FILES " | sort | uniq)
60+
61+ # Debug output
62+ echo " __ MODIFIED files found __"
63+ echo " $MODIFIED_FILES "
64+ echo " __ DELETED files found __"
65+ echo " $DELETED_FILES "
66+ echo " __ RENAMED files found (with history) __"
67+ echo " $RENAMED_FILES_WITH_HISTORY "
68+ echo " __ ALL changed files __"
69+ echo " $ALL_DIFF "
70+
71+ # Function to filter files by pattern
72+ filter_files () {
73+ local files=$1
74+ local result=" "
75+
76+ IFS=$' \n '
77+ for file in $files ; do
5278 while IFS= read -r pattern || [ -n " $pattern " ]; do
5379 clean_pattern=${pattern%/ }
5480 if [[ $file == $clean_pattern || $file == $clean_pattern /* ]]; then
55- FILTERED_DIFF=" $FILTERED_DIFF $file "
81+ result=" $result $file "
82+ break
83+ fi
84+ done <<< " $FILTER"
85+ done
86+ unset IFS
87+
88+ echo " $result "
89+ }
90+
91+ # Function to filter rename pairs
92+ filter_renames () {
93+ local new_files=$1
94+ local old_files=$2
95+ local result=" "
96+
97+ IFS=$' \n '
98+ for i in $( seq 1 $( echo " $new_files " | wc -l) ) ; do
99+ NEW=$( echo " $new_files " | sed -n " ${i} p" )
100+ OLD=$( echo " $old_files " | sed -n " ${i} p" )
101+
102+ while IFS= read -r pattern || [ -n " $pattern " ]; do
103+ clean_pattern=${pattern%/ }
104+ if [[ $NEW == $clean_pattern || $NEW == $clean_pattern /* ]]; then
105+ result=" $result $OLD =>$NEW "
56106 break
57107 fi
58108 done <<< " $FILTER"
59109 done
60110 unset IFS
111+
112+ echo " $result "
113+ }
114+
115+ # Filter the files to just the directories specified in the input files
116+ if [ " $FILTER " != " ." ]; then
117+ echo " __ filtering files to only include $FILTER __"
118+
119+ FILTERED_MODIFIED=$( filter_files " $MODIFIED_FILES " )
120+ FILTERED_DELETED=$( filter_files " $DELETED_FILES " )
121+ FILTERED_RENAMED=$( filter_renames " $RENAMED_NEW_FILES " " $RENAMED_OLD_FILES " )
122+
123+ # For filtered_changed_files (non-deleted files)
124+ FILTERED_DIFF=" $FILTERED_MODIFIED "
125+ for new_file in $( echo " $FILTERED_RENAMED " | grep -o " =>[^[:space:]]*" | sed ' s/=>//g' ) ; do
126+ FILTERED_DIFF=" $FILTERED_DIFF $new_file "
127+ done
128+
129+ MODIFIED_FILES=$FILTERED_MODIFIED
130+ DELETED_FILES=$FILTERED_DELETED
131+ RENAMED_FILES_WITH_HISTORY=$FILTERED_RENAMED
61132 DIFF=$FILTERED_DIFF
62- echo " __ filtered DIFF __"
63- echo " $DIFF "
133+
134+ echo " __ filtered MODIFIED files __"
135+ echo " $MODIFIED_FILES "
136+ echo " __ filtered DELETED files __"
137+ echo " $DELETED_FILES "
138+ echo " __ filtered RENAMED files (with history) __"
139+ echo " $RENAMED_FILES_WITH_HISTORY "
140+ echo " __ filtered changed files (non-deleted) __"
141+ echo " $FILTERED_DIFF "
64142fi
65143
144+ # Function to format output (standardize whitespace)
145+ format_output () {
146+ local input=$1
147+ echo " $input " | tr ' \n' ' ' | tr -s ' ' | sed ' s/^ *//' | sed ' s/ *$//'
148+ }
149+
66150echo " __ formatting output __"
67- FORMATTED_DIFF=$( echo " $DIFF " | tr ' \n' ' ' | tr -s ' ' | sed ' s/^ *//' | sed ' s/ *$//' )
68- echo " Formatted diff: '$FORMATTED_DIFF '"
151+ FORMATTED_MODIFIED=$( format_output " $MODIFIED_FILES " )
152+ FORMATTED_DELETED=$( format_output " $DELETED_FILES " )
153+ FORMATTED_DIFF=$( format_output " $DIFF " )
154+ FORMATTED_RENAMED=$( format_output " $RENAMED_FILES_WITH_HISTORY " )
155+ ALL_FORMATTED=$( format_output " $ALL_DIFF " )
156+
157+ echo " Formatted modified: '$FORMATTED_MODIFIED '"
158+ echo " Formatted deleted: '$FORMATTED_DELETED '"
159+ echo " Formatted renamed: '$FORMATTED_RENAMED '"
160+ echo " Formatted non-deleted changes: '$FORMATTED_DIFF '"
69161
70162# Set the output for GitHub Actions
71- ALL_FORMATTED=$( echo " $DIFF " | tr ' \n' ' ' | tr -s ' ' | sed ' s/^ *//' | sed ' s/ *$//' )
72163HAS_CHANGES=true
73- if [[ -z " $ALL_FORMATTED " ]]; then
164+ if [[ -z " $FORMATTED_DIFF " && -z " $FORMATTED_DELETED " ]]; then
74165 echo " No changed files detected"
75166 HAS_CHANGES=false
76167fi
@@ -83,6 +174,8 @@ set_outputs() {
83174 echo " Setting empty outputs to $target "
84175 echo " all_changed_files=" >> " $target "
85176 echo " filtered_changed_files=" >> " $target "
177+ echo " filtered_deleted_files=" >> " $target "
178+ echo " filtered_renamed_files=" >> " $target "
86179 else
87180 echo " Setting non-empty outputs to $target "
88181 echo " all_changed_files<<EOF" >> " $target "
@@ -92,6 +185,14 @@ set_outputs() {
92185 echo " filtered_changed_files<<EOF" >> " $target "
93186 echo " $FORMATTED_DIFF " >> " $target "
94187 echo " EOF" >> " $target "
188+
189+ echo " filtered_deleted_files<<EOF" >> " $target "
190+ echo " $FORMATTED_DELETED " >> " $target "
191+ echo " EOF" >> " $target "
192+
193+ echo " filtered_renamed_files<<EOF" >> " $target "
194+ echo " $FORMATTED_RENAMED " >> " $target "
195+ echo " EOF" >> " $target "
95196 fi
96197}
97198
0 commit comments