cowpatch.sh 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #!/bin/sh
  2. #
  3. # cowpatch.sh, by Rich Felker
  4. #
  5. # Permission to use, copy, modify, and/or distribute this software for
  6. # any purpose with or without fee is hereby granted.
  7. #
  8. # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  9. # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  10. # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  11. # AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. # DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
  13. # OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  14. # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15. # PERFORMANCE OF THIS SOFTWARE.
  16. #
  17. # Take the above disclaimer seriously! This is an experimental tool
  18. # still and does not yet take precautions against malformed/malicious
  19. # patch files like patch(1) does. It may act out-of-tree and clobber
  20. # stuff you didn't intend for it to clobber.
  21. #
  22. set -e
  23. echo () { printf "%s\n" "$*" ; }
  24. cow () {
  25. test -h "$1" || return 0
  26. if test -d "$1" ; then
  27. case "$1" in
  28. */*) set -- "${1%/*}/" "${1##*/}" ;;
  29. *) set -- "" "$1" ;;
  30. esac
  31. mkdir "$1$2.tmp.$$"
  32. mv "$1$2" "$1.$2.orig"
  33. mv "$1$2.tmp.$$" "$1$2"
  34. ( cd "$1$2" && ln -s ../".$2.orig"/* . )
  35. else
  36. cp "$1" "$1.tmp.$$"
  37. mv "$1.tmp.$$" "$1"
  38. fi
  39. }
  40. cowp () {
  41. while test "$1" ; do
  42. case "$1" in
  43. */*) set -- "${1#*/}" "$2${2:+/}${1%%/*}" ;;
  44. *) set -- "" "$2${2:+/}$1" ;;
  45. esac
  46. cow "$2"
  47. done
  48. }
  49. cowpatch () {
  50. plev=0
  51. OPTIND=1
  52. while getopts ":p:i:RNE" opt ; do
  53. test "$opt" = p && plev="$OPTARG"
  54. done
  55. while IFS= read -r l ; do
  56. case "$l" in
  57. +++*)
  58. IFS=" " read -r junk pfile junk <<EOF
  59. $l
  60. EOF
  61. i=0; while test "$i" -lt "$plev" ; do pfile=${pfile#*/}; i=$((i+1)) ; done
  62. cowp "$pfile"
  63. echo "$l"
  64. ;;
  65. @@*)
  66. echo "$l"
  67. IFS=" " read -r junk i j junk <<EOF
  68. $l
  69. EOF
  70. case "$i" in *,*) i=${i#*,} ;; *) i=1 ;; esac
  71. case "$j" in *,*) j=${j#*,} ;; *) j=1 ;; esac
  72. while test $i -gt 0 || test $j -gt 0 ; do
  73. IFS= read -r l
  74. echo "$l"
  75. case "$l" in
  76. +*) j=$((j-1)) ;;
  77. -*) i=$((i-1)) ;;
  78. *) i=$((i-1)) ; j=$((j-1)) ;;
  79. esac
  80. done ;;
  81. *) echo "$l" ;;
  82. esac
  83. done
  84. }
  85. gotcmd=0
  86. while getopts ":p:i:RNEI:S:" opt ; do
  87. case "$opt" in
  88. I) find "$OPTARG" -path "$OPTARG/*" -prune -exec sh -c 'ln -sf "$@" .' sh {} + ; gotcmd=1 ;;
  89. S) cowp "$OPTARG" ; gotcmd=1 ;;
  90. esac
  91. done
  92. test "$gotcmd" -eq 0 || exit 0
  93. cowpatch "$@" | patch "$@"