diff-pr.sh 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #!/bin/bash
  2. set -eo pipefail
  3. shopt -s dotglob
  4. # make sure we can GTFO
  5. trap 'echo >&2 Ctrl+C captured, exiting; exit 1' SIGINT
  6. usage() {
  7. cat <<-EOUSAGE
  8. usage: $0 [PR number] [repo[:tag]]
  9. ie: $0 1024
  10. $0 9001 debian php django
  11. EOUSAGE
  12. }
  13. # TODO flags parsing
  14. allFiles=
  15. listTarballContents=1
  16. findCopies='20%'
  17. if [ "$#" -eq 0 ]; then
  18. usage >&2
  19. exit 1
  20. fi
  21. pull="$1" # PR number
  22. shift
  23. #dir="$(dirname "$(readlink -f "$BASH_SOURCE")")"
  24. tempDir="$(mktemp -d)"
  25. trap "rm -rf '$tempDir'" EXIT
  26. cd "$tempDir"
  27. git clone --quiet --depth 1 \
  28. https://github.com/docker-library/official-images.git \
  29. oi
  30. git -C oi fetch --quiet --depth 1 \
  31. origin "pull/$pull/merge":pull
  32. images=( "$@" )
  33. if [ "${#images[@]}" -eq 0 ]; then
  34. images=( $(git -C oi/library diff --name-only master...pull -- . | xargs -n1 basename) )
  35. fi
  36. export BASHBREW_CACHE="${BASHBREW_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/bashbrew}"
  37. export BASHBREW_LIBRARY="$PWD/oi/library"
  38. # TODO something less hacky than "git archive" hackery, like a "bashbrew archive" or "bashbrew context" or something
  39. template='
  40. {{- range $.Entries -}}
  41. {{- $from := $.DockerFrom . -}}
  42. git -C "$BASHBREW_CACHE/git" archive --format=tar
  43. {{- " " -}}
  44. {{- "--prefix=" -}}
  45. {{- $.RepoName -}}
  46. _
  47. {{- .Tags | last -}}
  48. {{- "/" -}}
  49. {{- " " -}}
  50. {{- .GitCommit -}}
  51. {{- ":" -}}
  52. {{- (eq .Directory ".") | ternary "" .Directory -}}
  53. {{- "\n" -}}
  54. {{- end -}}
  55. '
  56. copy-tar() {
  57. local src="$1"; shift
  58. local dst="$1"; shift
  59. if [ "$allFiles" ]; then
  60. mkdir -p "$dst"
  61. cp -al "$src"/*/ "$dst/"
  62. return
  63. fi
  64. # "Dockerfile*" at the end here ensures we capture "Dockerfile.builder" style repos in a useful way too (busybox, hello-world)
  65. for d in "$src"/*/Dockerfile*; do
  66. dDir="$(dirname "$d")"
  67. dDirName="$(basename "$dDir")"
  68. IFS=$'\n'
  69. files=(
  70. "$(basename "$d")"
  71. $(awk '
  72. toupper($1) == "COPY" || toupper($1) == "ADD" {
  73. for (i = 2; i < NF; i++) {
  74. print $i
  75. }
  76. }
  77. ' "$d")
  78. # some extra files which are likely interesting if they exist, but no big loss if they do not
  79. ' *.manifest' # debian/ubuntu "package versions" list
  80. ' *.ks' # fedora "kickstart" (rootfs build script)
  81. ' build*.txt' # ubuntu "build-info.txt", debian "build-command.txt"
  82. # usefulness yet to be proven:
  83. #' *.log'
  84. #' {MD5,SHA1,SHA256}SUMS'
  85. #' *.{md5,sha1,sha256}'
  86. # (the space prefix is removed below and is used to ignore non-matching globs so that bad "Dockerfile" entries appropriately lead to failure)
  87. )
  88. unset IFS
  89. mkdir -p "$dst/$dDirName"
  90. for origF in "${files[@]}"; do
  91. f="${origF# }" # trim off leading space (indicates we don't care about failure)
  92. [ "$f" = "$origF" ] && failureMatters=1 || failureMatters=
  93. globbed=( $(cd "$dDir" && eval "echo $f") )
  94. for g in "${globbed[@]}"; do
  95. if [ -z "$failureMatters" ] && [ ! -e "$dDir/$g" ]; then
  96. continue
  97. fi
  98. mkdir -p "$(dirname "$dst/$dDirName/$g")"
  99. cp -alT "$dDir/$g" "$dst/$dDirName/$g"
  100. if [ "$listTarballContents" ]; then
  101. case "$g" in
  102. *.tar.*|*.tgz)
  103. tar -tf "$dst/$dDirName/$g" | sort > "$dst/$dDirName/$g 'tar -t'"
  104. ;;
  105. esac
  106. fi
  107. done
  108. done
  109. done
  110. }
  111. mkdir temp
  112. git -C temp init --quiet
  113. for image in "${images[@]}"; do
  114. if script="$(bashbrew cat -f "$template" "$image")"; then
  115. mkdir tar
  116. ( eval "$script" | tar -xiC tar )
  117. copy-tar tar temp
  118. rm -rf tar
  119. fi
  120. done
  121. git -C temp add . || :
  122. git -C temp commit --quiet --allow-empty -m 'initial' || :
  123. git -C oi checkout --quiet pull
  124. git -C temp rm --quiet -rf . || :
  125. script="$(bashbrew cat -f "$template" "${images[@]}")"
  126. mkdir tar
  127. ( eval "$script" | tar -xiC tar )
  128. copy-tar tar temp
  129. rm -rf tar
  130. git -C temp add .
  131. git -C temp diff --minimal --find-copies="$findCopies" --find-copies-harder --irreversible-delete --staged