naughty-commits.sh 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #!/usr/bin/env bash
  2. set -Eeuo pipefail
  3. fileSizeThresholdMB='2'
  4. : "${BASHBREW_CACHE:=$HOME/.cache/bashbrew}"
  5. export BASHBREW_CACHE BASHBREW_ARCH=
  6. if [ ! -d "$BASHBREW_CACHE/git" ]; then
  7. # initialize the "bashbrew cache"
  8. bashbrew --arch amd64 from --uniq --apply-constraints hello-world:linux > /dev/null
  9. fi
  10. _git() {
  11. git -C "$BASHBREW_CACHE/git" "$@"
  12. }
  13. if [ "$#" -eq 0 ]; then
  14. set -- '--all'
  15. fi
  16. imgs="$(bashbrew list --repos "$@" | sort -u)"
  17. for img in $imgs; do
  18. IFS=$'\n'
  19. commits=( $(
  20. bashbrew cat --format '
  21. {{- range $e := .Entries -}}
  22. {{- range $a := .Architectures -}}
  23. {{- /* force `git fetch` */ -}}
  24. {{- $froms := $.ArchDockerFroms $a $e -}}
  25. {{- $e.ArchGitCommit $a -}}
  26. {{- "\n" -}}
  27. {{- end -}}
  28. {{- end -}}
  29. ' "$img" | sort -u
  30. ) )
  31. unset IFS
  32. declare -A naughtyCommits=() naughtyTopCommits=() seenCommits=()
  33. for topCommit in "${commits[@]}"; do
  34. IFS=$'\n'
  35. potentiallyNaughtyGlobs=( '**.tar**' )
  36. potentiallyNaughtyCommits=( $(_git log --diff-filter=DMT --format='format:%H' "$topCommit" -- "${potentiallyNaughtyGlobs[@]}") )
  37. unset IFS
  38. # bash 4.3 sucks (https://stackoverflow.com/a/7577209/433558)
  39. [ "${#potentiallyNaughtyCommits[@]}" -gt 0 ] || continue
  40. for commit in "${potentiallyNaughtyCommits[@]}"; do
  41. [ -z "${seenCommits[$commit]:-}" ] || break
  42. seenCommits[$commit]=1
  43. IFS=$'\n'
  44. binaryFiles=( $(
  45. _git diff-tree --no-commit-id -r --numstat --diff-filter=DMT "$commit" -- "${potentiallyNaughtyGlobs[@]}" \
  46. | grep '^-' \
  47. | cut -d$'\t' -f3- \
  48. || :
  49. ) )
  50. unset IFS
  51. # bash 4.3 sucks (https://stackoverflow.com/a/7577209/433558)
  52. [ "${#binaryFiles[@]}" -gt 0 ] || continue
  53. naughtyReasons=()
  54. for file in "${binaryFiles[@]}"; do
  55. fileSize="$(_git ls-tree -r --long "$commit" -- "$file" | awk '{ print $4 }')"
  56. fileSizeMB="$(( fileSize / 1024 / 1024 ))"
  57. if [ "$fileSizeMB" -gt "$fileSizeThresholdMB" ]; then
  58. naughtyReasons+=( "modified binary file (larger than ${fileSizeThresholdMB}MB): $file (${fileSizeMB}MB)" )
  59. fi
  60. done
  61. if [ "${#naughtyReasons[@]}" -gt 0 ]; then
  62. IFS=$'\n'
  63. naughtyCommits[$commit]="${naughtyReasons[*]}"
  64. unset IFS
  65. naughtyTopCommits[$commit]="$topCommit"
  66. fi
  67. done
  68. done
  69. if [ "${#naughtyCommits[@]}" -gt 0 ]; then
  70. echo " - $img:"
  71. for naughtyCommit in "${!naughtyCommits[@]}"; do
  72. naughtyReasons="${naughtyCommits[$naughtyCommit]}"
  73. naughtyTopCommit="${naughtyTopCommits[$naughtyCommit]}"
  74. if [ "$naughtyTopCommit" != "$naughtyCommit" ]; then
  75. #commitsBetween="$(_git rev-list --count "$naughtyCommit...$naughtyTopCommit")"
  76. naughtyCommit+=" (in history of $naughtyTopCommit)"
  77. fi
  78. echo " - commit $naughtyCommit:"
  79. sed -e 's/^/ - /' <<<"$naughtyReasons"
  80. done
  81. echo
  82. fi
  83. done