helpers 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. # Generate a reproducible archive from the content of a directory
  2. #
  3. # $1 : input directory
  4. # $2 : leading component in archive
  5. # $3 : ISO8601 date: YYYY-MM-DDThh:mm:ssZZ
  6. # $4 : output file
  7. # $5... : globs of filenames to exclude from the archive, suitable for
  8. # find's -path option, and relative to the input directory $1
  9. #
  10. # Notes :
  11. # - must not be called with CWD as, or below, the input directory
  12. # - some temporary files are created in CWD, and removed at the end
  13. #
  14. # Example:
  15. # $ find /path/to/temp/dir
  16. # /path/to/temp/dir/
  17. # /path/to/temp/dir/some-file
  18. # /path/to/temp/dir/some-dir/
  19. # /path/to/temp/dir/some-dir/some-other-file
  20. #
  21. # $ mk_tar_gz /path/to/some/dir \
  22. # foo_bar-1.2.3 \
  23. # 1970-01-01T00:00:00Z \
  24. # /path/to/foo.tar.gz \
  25. # '.git/*' '.svn/*'
  26. #
  27. # $ tar tzf /path/to/foo.tar.gz
  28. # foo_bar-1.2.3/some-file
  29. # foo_bar-1.2.3/some-dir/some-other-file
  30. #
  31. mk_tar_gz() {
  32. local in_dir="${1}"
  33. local base_dir="${2}"
  34. local date="${3}"
  35. local out="${4}"
  36. shift 4
  37. local glob tmp pax_options
  38. local -a find_opts
  39. for glob; do
  40. find_opts+=( -or -path "./${glob#./}" )
  41. done
  42. pax_options="delete=atime,delete=ctime,delete=mtime"
  43. pax_options+=",exthdr.name=%d/PaxHeaders/%f,exthdr.mtime={${date}}"
  44. tmp="$(mktemp --tmpdir="$(pwd)")"
  45. pushd "${in_dir}" >/dev/null
  46. # Establish list
  47. find . -not -type d -and -not \( -false "${find_opts[@]}" \) >"${tmp}.list"
  48. # Sort list for reproducibility
  49. LC_ALL=C sort <"${tmp}.list" >"${tmp}.sorted"
  50. # Create POSIX tarballs, since that's the format the most reproducible
  51. tar cf - --transform="s#^\./#${base_dir}/#" \
  52. --numeric-owner --owner=0 --group=0 --mtime="${date}" \
  53. --format=posix --pax-option="${pax_options}" \
  54. -T "${tmp}.sorted" >"${tmp}.tar"
  55. # Compress the archive
  56. gzip -6 -n <"${tmp}.tar" >"${out}"
  57. rm -f "${tmp}"{.list,.sorted,.tar}
  58. popd >/dev/null
  59. }
  60. # Keep this line and the following as last lines in this file.
  61. # vim: ft=bash