/ maint / rust-maint-common / update-shell-includes
update-shell-includes
  1  #!/usr/bin/env bash
  2  #
  3  # Arrange for all shell scripts to obtain the common libraries
  4  # not via the current working directory, but rather realpath $0, by:
  5  #
  6  #  1. Checking that no shell scripts have ad hoc `.` or `source`'s
  7  #  2. Updating/checking the standard bash-utils.sh include stanza.
  8  #   
  9  # Usage;
 10  #   update-shell-includes [--check] --all | [--] FILE...
 11  #
 12  # To edit the standard shell script stanza, edit it here in this script!
 13  
 14  set -euo pipefail
 15  
 16  # this include stanza is automatically maintained by update-shell-includes
 17  common_dir=$(realpath "$0")
 18  common_dir=$(dirname "$common_dir")
 19  # shellcheck source=maint/common/bash-utils.sh
 20  . "$common_dir"/bash-utils.sh
 21  
 22  install=true
 23  all=false
 24  
 25  while [ $# != 0 ]; do
 26      case "$1" in
 27  	--) shift; break ;;
 28  	--check) install=false ;;
 29  	--all) all=true ;;
 30  	-*) fail "unknown option $1";;
 31  	*) break ;;
 32      esac
 33      shift
 34  done
 35  
 36  case "$all.$#" in
 37      false.0) fail "need --all or one or more script filenames" ;;
 38      false.*) ;;
 39      true.0)
 40  	wanted=$(
 41              git_grep_for_shell_script_shebangs | grep -vF "${0##*/}"
 42  	)
 43          # shellcheck disable=SC2086
 44  	set -- $wanted
 45  	;;
 46      true.*) fail "script filenames not allowed with --all " ;;
 47  esac
 48  
 49  # create the .new files here, with cp, to preserve the permissions
 50  for f in "$@"; do
 51      cp -- "$f" "$f.new"
 52  done
 53  
 54  errors=$(perl -we '
 55      use strict;
 56      use POSIX;
 57  
 58      my $msg_re = qr{this include stanza is automatically maintained};
 59      my $stanza_re = qr{
 60        ^ \s* \n                     # blank line
 61          \# \s* $msg_re .* \n
 62          (?: .* \S .* \n )+         # some non-blank lines
 63      }xm;
 64  
 65      my $bad_re = qr{
 66          ^ [\ \t]* (?: \. | source ) [ \t] [^\$\n] * (?: maint/ | bash-utils\.sh ) .*
 67      }xm;
 68  
 69      undef $/;
 70      sub slurp ($) {
 71          open F, "<", "$_[0]" or die "$_[0]: $!";
 72          $_ = <F>;
 73          F->error and die $!;
 74      }
 75  
 76      slurp(shift @ARGV);
 77      m{$stanza_re} or die "missing stanza in self!";
 78  
 79      my $stanza = $&;
 80  
 81      foreach my $f (@ARGV) {
 82          slurp($f);
 83          if (s{$stanza_re}{$stanza}) {
 84          } elsif (m{$bad_re}) {
 85              print "$f: bad include line, \`$&`\n";
 86          }
 87          open O, ">", "$f.new" or die "$f.new: $!";
 88          print O or die $!;
 89          close O or die $!;
 90      }
 91  ' "$0" "$@")
 92  
 93  ok=true
 94  
 95  if [ "$errors" != "" ]; then
 96      cat <<END >&2
 97  errors searching/checking scripts for include stanzas:
 98  $errors
 99  END
100      ok=false
101  fi
102  
103  for f in "$@"; do
104      if $ok && $install; then
105  	mv -f -- "$f.new" "$f"
106      else
107  	set +e
108  	diff -u -- "$f" "$f.new"
109  	rc=$?
110  	set -e
111  	case "$rc" in
112  	    0) rm -- "$f.new" ;;
113  	    1) ok=false;;
114  	    *) fail 'diff failed';;
115  	esac
116      fi
117  done
118  
119  if ! $ok; then
120      fail "$0 check/update failed"
121  fi