dev
sh 222 lines 6.21 KB
Raw
1 #!/bin/bash
2
3 # usage:
4 # ./compare_overrides.sh GIT_HASH_A GIT_HASH_B
5
6 set -e
7 cd "$(dirname "$0")/.."
8
9 HASH_A=${1:?usage: ./compare_overrides.sh GIT_HASH_A GIT_HASH_B}
10 HASH_B=${2:?usage: ./compare_overrides.sh GIT_HASH_A GIT_HASH_B}
11
12 sdk_git_url=https://github.com/dart-lang/sdk
13
14 yq() {
15 go run github.com/mikefarah/yq/v4@latest "$@"
16 }
17
18 normalize_url() {
19 echo "$1" | sed 's|\.git$||'
20 }
21
22 repo_cache_dir() {
23 echo "scripts/.cache/repos/$(normalize_url "$1" | sed 's|https://github.com/||; s|/|_|g')"
24 }
25
26 ensure_repo_clone() {
27 local url=$1 cache_dir=$2
28 if [[ -d "${cache_dir}/.git" ]]; then
29 git -C "$cache_dir" fetch --quiet origin
30 else
31 mkdir -p "$(dirname "$cache_dir")"
32 if [[ "$(normalize_url "$url")" == "$sdk_git_url" ]]; then
33 git clone --quiet --filter=blob:none "$url" "$cache_dir" || return 1
34 else
35 git clone --quiet "$url" "$cache_dir" || return 1
36 fi
37 fi
38 }
39
40 normalize_repo_path() {
41 local path=$1
42 [[ -z "$path" || "$path" == "-" ]] && return 0
43 echo "${path#./}"
44 }
45
46 ensure_ref() {
47 local cache_dir=$1 ref=$2
48 git -C "$cache_dir" cat-file -e "${ref}^{commit}" 2>/dev/null && return 0
49 git -C "$cache_dir" fetch --quiet origin "$ref" 2>/dev/null || true
50 git -C "$cache_dir" cat-file -e "${ref}^{commit}" 2>/dev/null
51 }
52
53 count_lines_at_ref() {
54 local cache_dir=$1 ref=$2 path=$3
55 local repo_path file lines total=0
56
57 ensure_ref "$cache_dir" "$ref" || return 1
58 repo_path=$(normalize_repo_path "$path")
59
60 while IFS= read -r file; do
61 [[ -z "$file" ]] && continue
62 lines=$(git -C "$cache_dir" show "$ref:$file" 2>/dev/null | wc -l | tr -d ' ')
63 total=$((total + lines))
64 done < <(
65 if [[ -n "$repo_path" ]]; then
66 git -C "$cache_dir" ls-tree -r --name-only "$ref" -- "$repo_path" 2>/dev/null
67 else
68 git -C "$cache_dir" ls-tree -r --name-only "$ref" 2>/dev/null
69 fi
70 )
71
72 echo "$total"
73 }
74
75 print_ref_diff() {
76 local cache_dir=$1 old_ref=$2 new_ref=$3 old_path=$4 new_path=$5
77 local repo_path diff_paths=() path
78
79 ensure_ref "$cache_dir" "$old_ref" || {
80 echo " diff (old ref not found: $old_ref)"
81 return 1
82 }
83 ensure_ref "$cache_dir" "$new_ref" || {
84 echo " diff (new ref not found: $new_ref)"
85 return 1
86 }
87
88 for path in "$old_path" "$new_path"; do
89 repo_path=$(normalize_repo_path "$path")
90 [[ -z "$repo_path" ]] && continue
91 [[ " ${diff_paths[*]} " == *" $repo_path "* ]] && continue
92 diff_paths+=("$repo_path")
93 done
94
95 if [[ ${#diff_paths[@]} -eq 0 ]]; then
96 git -C "$cache_dir" diff --stat "$old_ref" "$new_ref" | sed 's/^/ /'
97 else
98 git -C "$cache_dir" diff --stat "$old_ref" "$new_ref" -- "${diff_paths[@]}" | sed 's/^/ /'
99 fi
100 }
101
102 overrides_json_git() {
103 git show "${1}:pubspec_overrides.yaml" | yq -o=json '.dependency_overrides // {}'
104 }
105
106 overrides_json_worktree() {
107 yq -o=json '.dependency_overrides // {}' pubspec_overrides.yaml
108 }
109
110 print_git_fields() {
111 local pkg=$1 old_url=$2 new_url=$3 old_ref=$4 new_ref=$5 old_path=$6 new_path=$7
112 echo " $pkg"
113 echo " url $old_url -> $new_url"
114 echo " ref $old_ref -> $new_ref"
115 echo " path $old_path -> $new_path"
116 }
117
118 print_new_repo_stats() {
119 local new_url=$1 new_ref=$2 new_path=$3 cache_dir loc
120
121 [[ "$new_url" == "-" || "$new_ref" == "-" ]] && return 0
122
123 cache_dir=$(repo_cache_dir "$new_url")
124 if ! ensure_repo_clone "$new_url" "$cache_dir"; then
125 echo " loc (clone failed)"
126 return 0
127 fi
128
129 if loc=$(count_lines_at_ref "$cache_dir" "$new_ref" "$new_path"); then
130 echo " loc $loc lines"
131 else
132 echo " loc (ref not found: $new_ref)"
133 fi
134 }
135
136 print_changed_ref_stats() {
137 local url=$1 old_ref=$2 new_ref=$3 old_path=$4 new_path=$5 cache_dir
138
139 [[ "$url" == "-" || "$old_ref" == "-" || "$new_ref" == "-" ]] && return 0
140
141 cache_dir=$(repo_cache_dir "$url")
142 if ! ensure_repo_clone "$url" "$cache_dir"; then
143 echo " diff (clone failed)"
144 return 0
145 fi
146
147 print_ref_diff "$cache_dir" "$old_ref" "$new_ref" "$old_path" "$new_path"
148 }
149
150 compare_overrides_jq='
151 def git($obj; $pkg): $obj[$pkg].git // null;
152 def fields($obj; $pkg):
153 git($obj; $pkg) as $g |
154 [($g.url // ""), ($g.ref // ""), ($g.path // "")];
155 def dash($v): if $v == "" then "-" else $v end;
156 '
157
158 resolved_a=$(git rev-parse "$HASH_A")
159 resolved_b=$(git rev-parse "$HASH_B")
160 resolved_head=$(git rev-parse HEAD)
161
162 if [[ "$resolved_a" == "$resolved_b" ]]; then
163 json_a=$(overrides_json_git "$HASH_A")
164 json_b=$(overrides_json_git "$HASH_B")
165 elif [[ "$resolved_b" == "$resolved_head" ]]; then
166 json_a=$(overrides_json_git "$HASH_A")
167 json_b=$(overrides_json_worktree)
168 else
169 json_a=$(overrides_json_git "$HASH_A")
170 json_b=$(overrides_json_git "$HASH_B")
171 fi
172
173 new_output=$(
174 jq -r -n --argjson a "$json_a" --argjson b "$json_b" "$compare_overrides_jq"'
175 ($b | keys[] | select(git($b; .))) as $pkg |
176 select((git($a; $pkg) | not) or git($a; $pkg).url != git($b; $pkg).url) |
177 (fields($a; $pkg)) as $old |
178 (fields($b; $pkg)) as $new |
179 [
180 $pkg,
181 dash($old[0]), dash($new[0]),
182 dash($old[1]), dash($new[1]),
183 dash($old[2]), dash($new[2])
184 ] | @tsv
185 ' | while IFS=$'\t' read -r pkg old_url new_url old_ref new_ref old_path new_path; do
186 print_git_fields "$pkg" "$old_url" "$new_url" "$old_ref" "$new_ref" "$old_path" "$new_path"
187 print_new_repo_stats "$new_url" "$new_ref" "$new_path"
188 done
189 )
190
191 changed_output=$(
192 jq -r -n --argjson a "$json_a" --argjson b "$json_b" "$compare_overrides_jq"'
193 ($b | keys[] | select(git($b; .) and git($a; .))) as $pkg |
194 select(git($a; $pkg).url == git($b; $pkg).url) |
195 select((git($a; $pkg).ref // "") != (git($b; $pkg).ref // "")) |
196 (fields($a; $pkg)) as $old |
197 (fields($b; $pkg)) as $new |
198 [
199 $pkg,
200 dash($old[0]), dash($new[0]),
201 dash($old[1]), dash($new[1]),
202 dash($old[2]), dash($new[2])
203 ] | @tsv
204 ' | while IFS=$'\t' read -r pkg old_url new_url old_ref new_ref old_path new_path; do
205 print_git_fields "$pkg" "$old_url" "$new_url" "$old_ref" "$new_ref" "$old_path" "$new_path"
206 print_changed_ref_stats "$new_url" "$old_ref" "$new_ref" "$old_path" "$new_path"
207 done
208 )
209
210 if [[ -n "$new_output" ]]; then
211 echo "new git repos:"
212 echo "$new_output"
213 fi
214
215 if [[ -n "$new_output" && -n "$changed_output" ]]; then
216 echo
217 fi
218
219 if [[ -n "$changed_output" ]]; then
220 echo "changed git refs:"
221 echo "$changed_output"
222 fi