update-patches 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #!/usr/bin/env mksh
  2. #-
  3. # Copyright (c) 2014
  4. # Thorsten Glaser <tg@mirbsd.org>
  5. # Copyright (c) 2006
  6. # Thorsten Glaser <tg@freewrt.org>
  7. #
  8. # Derived from the MirPorts Framework "update-patches" script:
  9. #
  10. # Copyright (c) 2003, 2004, 2005
  11. # Thorsten "mirabile" Glaser <tg@MirBSD.de>
  12. # Based upon code and idea (c) 2000
  13. # Marc Espie for the OpenBSD project. All rights reserved.
  14. #
  15. # Provided that these terms and disclaimer and all copyright notices
  16. # are retained or reproduced in an accompanying document, permission
  17. # is granted to deal in this work without restriction, including un-
  18. # limited rights to use, publicly perform, distribute, sell, modify,
  19. # merge, give away, or sublicence.
  20. #
  21. # This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
  22. # the utmost extent permitted by applicable law, neither express nor
  23. # implied; without malicious intent or gross negligence. In no event
  24. # may a licensor, author or contributor be held liable for indirect,
  25. # direct, other damage, loss, or other issues arising in any way out
  26. # of dealing in the work, even if advised of the possibility of such
  27. # damage or existence of a defect, except proven that it results out
  28. # of said person's immediate fault when using the work as intended.
  29. do_diff() {
  30. local f1=$2/$1
  31. local f2=$3/$1
  32. if [[ ! -e $f1 ]]; then
  33. [[ -d ${f1%/*}/. ]] || mkdir -p "${f1%/*}"
  34. if [[ ! -s $f2 ]]; then
  35. cat <<EOF
  36. --- $f1 (non-existant)
  37. +++ $f2 (empty)
  38. @@ -0,0 +0,0 @@
  39. EOF
  40. return 0
  41. fi
  42. touch -t 197001010000.00 "$f1"
  43. fi
  44. diff -adup "$f1" "$f2"
  45. return $?
  46. }
  47. set -A accounted
  48. set -A edit
  49. TRANSFORM='sed s/[.+]/\\\\&/g'
  50. PATCHDIR=$CURDIR/patches
  51. EXTRADIR=$CURDIR/extra
  52. mkdir -p "$PATCHDIR"
  53. SUBDIST=${WRKDIST##${WRKDIR1}?(/)}
  54. if [[ -n $SUBDIST ]]; then
  55. mv "${WRKDIR1}.orig/${SUBDIST}" "${WRKDIR1}/${SUBDIST}.orig"
  56. D_BASE=${WRKDIR1}
  57. D_SUB=${SUBDIST}
  58. # D_SUBP=$D_SUB
  59. D_SUBP='[^/]*'
  60. D_CMP=$D_SUBP
  61. else
  62. # WRKSRC == WRKDIR
  63. D_BASE=$(dirname "${WRKDIR1}")
  64. D_SUB=$(basename "${WRKDIR1}")
  65. D_SUBP=$D_SUB
  66. D_CMP=
  67. fi
  68. ORGDIST=${D_BASE}/${D_SUB}.orig
  69. if [[ -e $WRKDIST/.patched-newfiles ]]; then
  70. touch "$ORGDIST/.patched-newfiles"
  71. patch_newfiles=1
  72. else
  73. patch_newfiles=0
  74. fi
  75. if [[ -e $WRKDIST/../.autoreconf_done ]]; then
  76. touch "$ORGDIST/.autoreconf_done"
  77. ignore_autoconf=1
  78. else
  79. ignore_autoconf=0
  80. fi
  81. DIFF_FLAGS="-adu -I \"^--- $(print -r -- "$D_SUBP.orig/" | $TRANSFORM)@@ .*\""
  82. DIFF_FLAGS="$DIFF_FLAGS -I \"^\+\+\+ $(print -r -- "$D_SUBP/" | $TRANSFORM)@@ .*\""
  83. for file in $(cd ${WRKDIST}; find . -type f | sed 's#^\./##'); do
  84. #print -r -- "DEBUG: <$file>" >>/tmp/debug
  85. [[ ! -e $ORGDIST/$file && $patch_newfiles = 0 ]] && continue
  86. [[ $file = configure && $ignore_autoconf = 1 ]] && continue
  87. [[ $file = missing && $ignore_autoconf = 1 ]] && continue
  88. [[ $file = depcomp && $ignore_autoconf = 1 ]] && continue
  89. [[ $file = install-sh && $ignore_autoconf = 1 ]] && continue
  90. [[ $file = aclocal.m4 && $ignore_autoconf = 1 ]] && continue
  91. [[ $file = INSTALL && $ignore_autoconf = 1 ]] && continue
  92. [[ $file = config.h.in && $ignore_autoconf = 1 ]] && continue
  93. [[ $(basename $file) = Makefile.in && $ignore_autoconf = 1 ]] && continue
  94. cmp -s "$ORGDIST/$file" "$WRKDIST/$file" && continue
  95. print -ru2 -- "Processing ${file}..."
  96. # look in patchdir for an existing patchfile matching this
  97. cd "$PATCHDIR"
  98. for i in $PATCH_LIST; do
  99. # Ignore non-files, or old backup
  100. [[ ! -f $i || $i = *@(.orig|.rej|~) ]] && continue
  101. # Patch found. Is this the one?
  102. if grep "^[+-][+-][+-] $D_CMP[^/]*/$file " "$i" >/dev/null; then
  103. # Multiple files in the diff?
  104. if [[ $(grep -c "^--- $D_CMP" "$i") -gt 1 || \
  105. $(grep -c "^+++ $D_CMP" "$i") -gt 1 ]]; then
  106. print -ru2 -- "Cannot process, $i contains patches"
  107. print -ru2 -- "to multiple files! Aborting."
  108. print -n 'FAIL\0'
  109. [[ -n $SUBDIST ]] && mv \
  110. "${WRKDIR1}/${SUBDIST}.orig" \
  111. "${WRKDIR1}.orig/${SUBDIST}"
  112. exit 0
  113. fi
  114. # Multiple diffs with this file?
  115. let n=0
  116. pflst=
  117. for j in $PATCH_LIST; do
  118. [[ ! -f $j || $j = *@(.orig|.rej|~) ]] && \
  119. continue
  120. grep "^[+-][+-][+-] $D_CMP[^/]*/$file " \
  121. "$j" >/dev/null || continue
  122. let n++
  123. pflst="$pflst '$j'"
  124. done
  125. if (( n != 1 )); then
  126. print -ru2 -- "Cannot process, file $file"
  127. print -ru2 -- "is contained in multiple patches:"
  128. print -ru2 -- "$pflst"
  129. print -n 'FAIL\0'
  130. [[ -n $SUBDIST ]] && mv \
  131. "${WRKDIR1}/${SUBDIST}.orig" \
  132. "${WRKDIR1}.orig/${SUBDIST}"
  133. exit 0
  134. fi
  135. # No, process this patch
  136. accounted+=("$i")
  137. # found it, copy preamble before comparision
  138. ( sed -e "/^--- /,\$d" <"$i"; \
  139. cd "$D_BASE" && do_diff "$file" "$D_SUB.orig" "$D_SUB" \
  140. ) >"$i.new"
  141. # did it change? mark it as changed
  142. tfile=$(print -r -- "$file" | $TRANSFORM)
  143. if eval diff "$(print -r -- "${DIFF_FLAGS}" | sed \
  144. "s#@@#${tfile}#g")" "$i" "$i.new" 1>&2; then
  145. rm "$i.new"
  146. else
  147. print -ru2 -- "Patch $i for $file updated"
  148. mv "$i" "$i.orig"
  149. mv "$i.new" "$i"
  150. edit+=("$i")
  151. fi
  152. continue 2
  153. fi
  154. done
  155. # Build a sensible name for the new patch file
  156. patchname=patch-$(print -r -- "$file" | sed -e 's#[/.- ]#_#g')
  157. print -ru2 -- "No patch-* found for $file, creating $patchname"
  158. ( cd "$D_BASE" && do_diff "$file" "$D_SUB.orig" "$D_SUB" ) >"$patchname"
  159. edit+=("$patchname")
  160. accounted+=("$patchname")
  161. done
  162. # Verify all patches accounted for
  163. cd "$PATCHDIR"
  164. for i in *; do
  165. [[ ! -f $i || $i = *@(.orig|.rej|~) ]] && continue
  166. grep '^\\ No newline at end of file' $i >/dev/null && \
  167. print -ru2 -- "*** Patch $i needs manual intervention"
  168. found=0
  169. for j in "${accounted[@]}"; do
  170. [[ $i = "$j" ]] || continue
  171. found=1
  172. break
  173. done
  174. (( found )) || print -ru2 -- "*** Patch $i not accounted for"
  175. done
  176. for i in "${edit[@]}"; do
  177. print -nr -- "$i"
  178. print -n '\0'
  179. done
  180. [[ -n $SUBDIST ]] && mv "${WRKDIR1}/${SUBDIST}.orig" "${WRKDIR1}.orig/${SUBDIST}"
  181. exit 0