mgorny 14/06/19 08:08:10 Modified: ChangeLog python-r1.eclass python-utils-r1.eclass Log: Improve handling of corner cases in python_fix_shebang. Support --force and --quiet options, bug #505354. Add tests.
Revision Changes Path 1.1291 eclass/ChangeLog file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/eclass/ChangeLog?rev=1.1291&view=markup plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/eclass/ChangeLog?rev=1.1291&content-type=text/plain diff : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/eclass/ChangeLog?r1=1.1290&r2=1.1291 Index: ChangeLog =================================================================== RCS file: /var/cvsroot/gentoo-x86/eclass/ChangeLog,v retrieving revision 1.1290 retrieving revision 1.1291 diff -u -r1.1290 -r1.1291 --- ChangeLog 14 Jun 2014 18:33:59 -0000 1.1290 +++ ChangeLog 19 Jun 2014 08:08:10 -0000 1.1291 @@ -1,6 +1,11 @@ # ChangeLog for eclass directory # Copyright 1999-2014 Gentoo Foundation; Distributed under the GPL v2 -# $Header: /var/cvsroot/gentoo-x86/eclass/ChangeLog,v 1.1290 2014/06/14 18:33:59 kensington Exp $ +# $Header: /var/cvsroot/gentoo-x86/eclass/ChangeLog,v 1.1291 2014/06/19 08:08:10 mgorny Exp $ + + 19 Jun 2014; Michał Górny <[email protected]> python-r1.eclass, + python-utils-r1.eclass, tests/python-utils-r1.sh: + Improve handling of corner cases in python_fix_shebang. Support --force and + --quiet options, bug #505354. Add tests. 14 Jun 2014; Michael Palimaka <[email protected]> kde4-base.eclass, kde4-functions.eclass: Sync with KDE overlay. Adapt to live ebuild versioning change. Remove 1.74 eclass/python-r1.eclass file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/eclass/python-r1.eclass?rev=1.74&view=markup plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/eclass/python-r1.eclass?rev=1.74&content-type=text/plain diff : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/eclass/python-r1.eclass?r1=1.73&r2=1.74 Index: python-r1.eclass =================================================================== RCS file: /var/cvsroot/gentoo-x86/eclass/python-r1.eclass,v retrieving revision 1.73 retrieving revision 1.74 diff -u -r1.73 -r1.74 --- python-r1.eclass 26 May 2014 16:13:35 -0000 1.73 +++ python-r1.eclass 19 Jun 2014 08:08:10 -0000 1.74 @@ -1,6 +1,6 @@ # Copyright 1999-2014 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/eclass/python-r1.eclass,v 1.73 2014/05/26 16:13:35 mgorny Exp $ +# $Header: /var/cvsroot/gentoo-x86/eclass/python-r1.eclass,v 1.74 2014/06/19 08:08:10 mgorny Exp $ # @ECLASS: python-r1 # @MAINTAINER: @@ -794,7 +794,7 @@ doexe "${files[@]}" ) - python_fix_shebang \ + python_fix_shebang -q \ "${files[@]/*\//${D%/}/${PYTHON_SCRIPTDIR}/}" else local f @@ -802,7 +802,7 @@ cp -p "${f}" "${f}-${EPYTHON}" || die done - python_fix_shebang \ + python_fix_shebang -q \ "${files[@]/%/-${EPYTHON}}" fi } 1.57 eclass/python-utils-r1.eclass file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/eclass/python-utils-r1.eclass?rev=1.57&view=markup plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/eclass/python-utils-r1.eclass?rev=1.57&content-type=text/plain diff : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/eclass/python-utils-r1.eclass?r1=1.56&r2=1.57 Index: python-utils-r1.eclass =================================================================== RCS file: /var/cvsroot/gentoo-x86/eclass/python-utils-r1.eclass,v retrieving revision 1.56 retrieving revision 1.57 diff -u -r1.56 -r1.57 --- python-utils-r1.eclass 26 May 2014 16:13:35 -0000 1.56 +++ python-utils-r1.eclass 19 Jun 2014 08:08:10 -0000 1.57 @@ -1,6 +1,6 @@ # Copyright 1999-2014 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/eclass/python-utils-r1.eclass,v 1.56 2014/05/26 16:13:35 mgorny Exp $ +# $Header: /var/cvsroot/gentoo-x86/eclass/python-utils-r1.eclass,v 1.57 2014/06/19 08:08:10 mgorny Exp $ # @ECLASS: python-utils-r1 # @MAINTAINER: @@ -670,8 +670,7 @@ # don't use this at home, just call python_doscript() instead if [[ ${_PYTHON_REWRITE_SHEBANG} ]]; then - local _PYTHON_FIX_SHEBANG_QUIET=1 - python_fix_shebang "${ED%/}/${d}/${newfn}" + python_fix_shebang -q "${ED%/}/${d}/${newfn}" fi } @@ -935,7 +934,7 @@ } # @FUNCTION: python_fix_shebang -# @USAGE: <path>... +# @USAGE: [-f|--force] [-q|--quiet] <path>... # @DESCRIPTION: # Replace the shebang in Python scripts with the current Python # implementation (EPYTHON). If a directory is passed, works recursively @@ -947,13 +946,28 @@ # # Shebangs matching explicitly current Python version will be left # unmodified. Shebangs requesting another Python version will be treated -# as fatal error. +# as fatal error, unless --force is given. +# +# --force causes the function to replace even shebangs that require +# incompatible Python version. --quiet causes the function not to list +# modified files verbosely. python_fix_shebang() { debug-print-function ${FUNCNAME} "${@}" - [[ ${1} ]] || die "${FUNCNAME}: no paths given" [[ ${EPYTHON} ]] || die "${FUNCNAME}: EPYTHON unset (pkg_setup not called?)" + local force quiet + while [[ ${@} ]]; do + case "${1}" in + -f|--force) force=1; shift;; + -q|--quiet) quiet=1; shift;; + --) shift; break;; + *) break;; + esac + done + + [[ ${1} ]] || die "${FUNCNAME}: no paths given" + local path f for path; do local any_correct any_fixed is_recursive @@ -961,54 +975,88 @@ [[ -d ${path} ]] && is_recursive=1 while IFS= read -r -d '' f; do - local shebang=$(head -n 1 "${f}") - local error + local shebang i + local error from - case "${shebang} " in - '#!'*"${EPYTHON} "*) - debug-print "${FUNCNAME}: in file ${f#${D}}" - debug-print "${FUNCNAME}: shebang matches EPYTHON: ${shebang}" - - # Nothing to do, move along. - any_correct=1 - ;; - '#!'*python" "*|'#!'*python[23]" "*) - debug-print "${FUNCNAME}: in file ${f#${D}}" - debug-print "${FUNCNAME}: rewriting shebang: ${shebang}" - - # Note: for internal use. - if [[ ! ${_PYTHON_FIX_SHEBANG_QUIET} ]]; then - einfo "Fixing shebang in ${f#${D}}." - fi - - local from - if [[ "${shebang} " == *'python2 '* ]]; then - from=python2 - python_is_python3 "${EPYTHON}" && error=1 - elif [[ "${shebang} " == *'python3 '* ]]; then - from=python3 - python_is_python3 "${EPYTHON}" || error=1 - else - from=python - fi - - if [[ ! ${error} ]]; then - sed -i -e "1s:${from}:${EPYTHON}:" "${f}" || die - any_fixed=1 - fi - ;; - '#!'*python[23].[0123456789]" "*|'#!'*pypy" "*|'#!'*jython[23].[0123456789]" "*) - # Explicit mismatch. - error=1 - ;; - *) - # Non-Python shebang. Allowed in recursive mode, - # disallowed when specifying file explicitly. - [[ ${is_recursive} ]] || error=1 - ;; - esac + read shebang <"${f}" - if [[ ${error} ]]; then + # First, check if it's shebang at all... + if [[ ${shebang} == '#!'* ]]; then + # Match left-to-right in a loop, to avoid matching random + # repetitions like 'python2.7 python2'. + for i in ${shebang}; do + case "${i}" in + *"${EPYTHON}") + debug-print "${FUNCNAME}: in file ${f#${D}}" + debug-print "${FUNCNAME}: shebang matches EPYTHON: ${shebang}" + + # Nothing to do, move along. + any_correct=1 + from=${EPYTHON} + break + ;; + *python|*python[23]) + debug-print "${FUNCNAME}: in file ${f#${D}}" + debug-print "${FUNCNAME}: rewriting shebang: ${shebang}" + + if [[ ${i} == *python2 ]]; then + from=python2 + if [[ ! ${force} ]]; then + python_is_python3 "${EPYTHON}" && error=1 + fi + elif [[ ${i} == *python3 ]]; then + from=python3 + if [[ ! ${force} ]]; then + python_is_python3 "${EPYTHON}" || error=1 + fi + else + from=python + fi + break + ;; + *python[23].[0123456789]|*pypy|*jython[23].[0123456789]) + # Explicit mismatch. + if [[ ! ${force} ]]; then + error=1 + else + case "${i}" in + *python[23].[0123456789]) + from="python[23].[0123456789]";; + *pypy) + from="pypy";; + *jython[23].[0123456789]) + from="jython[23].[0123456789]";; + *) + die "${FUNCNAME}: internal error in 2nd pattern match";; + esac + fi + break + ;; + esac + done + fi + + if [[ ! ${error} && ! ${from} ]]; then + # Non-Python shebang. Allowed in recursive mode, + # disallowed when specifying file explicitly. + [[ ${is_recursive} ]] && continue + error=1 + fi + + if [[ ! ${quiet} ]]; then + einfo "Fixing shebang in ${f#${D}}." + fi + + if [[ ! ${error} ]]; then + # We either want to match ${from} followed by space + # or at end-of-string. + if [[ ${shebang} == *${from}" "* ]]; then + sed -i -e "1s:${from} :${EPYTHON} :" "${f}" || die + else + sed -i -e "1s:${from}$:${EPYTHON}:" "${f}" || die + fi + any_fixed=1 + else eerror "The file has incompatible shebang:" eerror " file: ${f#${D}}" eerror " current shebang: ${shebang}"
