Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Portage and automatic patching
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Portage & Programming
View previous topic :: View next topic  
Author Message
Dolda2000
n00b
n00b


Joined: 05 Mar 2004
Posts: 37
Location: Täby, Sweden

PostPosted: Thu May 19, 2005 1:36 am    Post subject: Portage and automatic patching Reply with quote

I have a few packages that I always patch when I emerge them. They include Xorg (for the IsolateDevice patch), gaim and screen, but there are some others as well.

Thie thing is, right now I always have to keep a look out for these packages whenever I run `emerge -Duva world', cancel, emerge them manually, stop emerge with Ctrl+S, go into /var/tmp/portage/..., apply the patch manually and then resume emerge with Ctrl+Q.

This is quite a procedure that I feel that I'd manage better without. Is there a way to make portage apply these patches automatically (like /etc/portage/package.patches or something like that)?
Back to top
View user's profile Send private message
platojones
Veteran
Veteran


Joined: 23 Oct 2002
Posts: 1554
Location: Just over the horizon

PostPosted: Thu May 19, 2005 1:53 am    Post subject: Reply with quote

I'm afraid not :cry:
Back to top
View user's profile Send private message
TrueDFX
Retired Dev
Retired Dev


Joined: 02 Jun 2004
Posts: 1348

PostPosted: Thu May 19, 2005 6:39 am    Post subject: Reply with quote

Keep in mind that this is in no way supported by anyone, not even by myself.

This is what I use:
Code:
if [[ " ${FEATURES} " == *" autopatch "* ]]; then
   case "$1" in
   unpack)
      if [[ -f "${BUILDDIR}/.autopatched" ]]; then
         /usr/bin/rm "${BUILDDIR}/.autopatched"
      fi
      ;;
   compile)
      if [[ ! -f "${BUILDDIR}/.autopatched" ]]; then
         if [[ -d "/etc/portage/autopatch/${CATEGORY}/${PN}" ]]; then
            IFS=$'\n'
            for patch in $(/usr/bin/find "/etc/portage/autopatch/${CATEGORY}/${PN}/." ! -name . -prune ! -type d); do
               for strip in 0 1 2 3 4; do
                  PATCHOPTS=(-N -d "${S}" -f -g 0 -i "${patch}" -p "${strip}" '--no-backup-if-mismatch')
                  if /usr/bin/patch --dry-run --quiet "${PATCHOPTS[@]}" >/dev/null; then
                     echo " * Applying ${patch##*/}"
                     /usr/bin/patch "${PATCHOPTS[@]}" || die "wtf?"
                     unset PATCHOPTS
                     continue 2
                  fi
               done
               echo " * Couldn't apply patch ${patch}"
               die "autopatch failed"
            done
            IFS=$' \t\n'
         fi
         /bin/touch "${BUILDDIR}/.autopatched"
      fi
   esac
fi
Stick that in your /etc/portage/bashrc, create /etc/portage/autopatch/x11-base/xorg-x11/ etc., put your patches in there, edit your /etc/make.conf, put "autopatch" in your FEATURES, and just emerge.

I can't find who originally came up with the idea of using bashrc for this, by the way, so I apologise in advance for not giving proper credit for that.

Again, keep in mind that this is in no way supported by anyone, not even by myself.


Last edited by TrueDFX on Sat May 21, 2005 3:36 pm; edited 1 time in total
Back to top
View user's profile Send private message
elvisthedj
Guru
Guru


Joined: 21 Jun 2004
Posts: 483
Location: Nampa, ID

PostPosted: Thu May 19, 2005 6:49 am    Post subject: Reply with quote

Thx TrueDFX :D I'll email you if I have any questions ;) (..kidding). Thx to whomever wrote that too!

Dolda2000: If you try that out, let me know how that works for you. The only thing I really apply a lot of patches to are various pieces of Asterisk which I typically leave out of my world file for that very reason.
_________________
Kris Edwards
kris edwards at g mail dot c0m
PGP
WWW
Back to top
View user's profile Send private message
rhill
Developer
Developer


Joined: 22 Oct 2004
Posts: 1629
Location: sk.ca

PostPosted: Thu May 19, 2005 7:32 am    Post subject: Reply with quote

TrueDFX wrote:
I can't find who originally came up with the idea of using bashrc for this, by the way, so I apologise in advance for not giving proper credit for that.


methinks it was solar, but i might be mistaken. that's the first i ever saw of it anyways.

http://dev.gentoo.org/~solar/portage_misc/bashrc.autopatch
_________________
by design, by neglect
for a fact or just for effect
Back to top
View user's profile Send private message
TrueDFX
Retired Dev
Retired Dev


Joined: 02 Jun 2004
Posts: 1348

PostPosted: Thu May 19, 2005 7:37 am    Post subject: Reply with quote

Thanks, yeah, that's the one.
Back to top
View user's profile Send private message
Dolda2000
n00b
n00b


Joined: 05 Mar 2004
Posts: 37
Location: Täby, Sweden

PostPosted: Thu May 19, 2005 2:49 pm    Post subject: Reply with quote

That's really interesting, TrueDFX. I was planning to start modifying emerge itself (and make it patch itself on future reemerges), but I had no idea it sourced external definitions like that.

That's certainly better, not to say more modular. I'll try it out at once.
Back to top
View user's profile Send private message
UncleOwen
Veteran
Veteran


Joined: 27 Feb 2003
Posts: 1493
Location: Germany, Hamburg

PostPosted: Thu May 19, 2005 3:34 pm    Post subject: Reply with quote

TrueDFX wrote:
Code:
if [[ " ${FEATURES} " == *" autopatch "* ]]; then


Does this work if autopatch is the first or last entry in ${FEATURES}?
Back to top
View user's profile Send private message
TrueDFX
Retired Dev
Retired Dev


Joined: 02 Jun 2004
Posts: 1348

PostPosted: Thu May 19, 2005 3:46 pm    Post subject: Reply with quote

UncleOwen wrote:
TrueDFX wrote:
Code:
if [[ " ${FEATURES} " == *" autopatch "* ]]; then


Does this work if autopatch is the first or last entry in ${FEATURES}?
Yes, it does. It checks " ${FEATURES} " instead of "${FEATURES}" for this. * matches even an empty string, so if your FEATURES is "autopatch notitles", " ${FEATURES} " can be split into "", " autopatch ", and "notitles ", where * and * match the first and third string.
Back to top
View user's profile Send private message
UncleOwen
Veteran
Veteran


Joined: 27 Feb 2003
Posts: 1493
Location: Germany, Hamburg

PostPosted: Thu May 19, 2005 3:52 pm    Post subject: Reply with quote

TrueDFX wrote:
UncleOwen wrote:
TrueDFX wrote:
Code:
if [[ " ${FEATURES} " == *" autopatch "* ]]; then


Does this work if autopatch is the first or last entry in ${FEATURES}?
Yes, it does. It checks " ${FEATURES} " instead of "${FEATURES}" for this.


Thanks, that's exactly what I missed.
Back to top
View user's profile Send private message
Dolda2000
n00b
n00b


Joined: 05 Mar 2004
Posts: 37
Location: Täby, Sweden

PostPosted: Fri May 20, 2005 12:11 am    Post subject: Reply with quote

I wrote my own version (not that anything was really wrong with yours, of course, but this just matches my thinking better), and it seems to be working just fine so far.

Code:
if [ "$EBUILD_PHASE" = unpack ]; then
    /bin/rm -f "${BUILDDIR}/.autopatched"
elif [ "$EBUILD_PHASE" = compile ]; then
    if [ ! -e "${BUILDDIR}/.autopatched" ]; then
        for patch in /etc/portage/package.patches/${CATEGORY}/${PN}/*.patch.[0-9]; do
            if [ -r "$patch" ]; then
                strip="${patch##*.}"
                einfo "Applying autopatch ${patch##*/}"
                /usr/bin/patch "-d${S}" "-p${strip}" -N -f <"${patch}" >/dev/null
                retcode=$?
                eend "${retcode}"
                if [ "${retcode}" -ne 0 ]; then
                    die "Autopatch application failed"
                fi
            fi
        done
        >"${BUILDDIR}/.autopatched"
    fi
fi

Thanks for your help!
Back to top
View user's profile Send private message
Erlend
Guru
Guru


Joined: 26 Dec 2004
Posts: 484

PostPosted: Mon Mar 27, 2006 4:57 pm    Post subject: Reply with quote

I just get:
Code:
ACCESS DENIED  unlink:    /.autopatched


probably something to do with sandbox?[/profile]
Back to top
View user's profile Send private message
Erlend
Guru
Guru


Joined: 26 Dec 2004
Posts: 484

PostPosted: Mon Mar 27, 2006 6:50 pm    Post subject: Reply with quote

I've tried to change it a bit:

Code:
if [ "$EBUILD_PHASE" = unpack ]; then
    /bin/rm -f "/tmp/portage/${CATEGORY}/${PN}/.autopatched"
    if [ ! -e "/tmp/portage/${CATEGORY}/${PN}/.autopatched" ]; then
        for patch in /etc/portage/package.patches/${CATEGORY}/${PN}/*.patch; do
            if [ -r "$patch" ]; then
                strip="${patch##*.}"
                ewarn "Unsupported patch: this is not guaranteed to work. Do not post bugs!"
                #einfo "Applying autopatch ${patch##*/}"
                #/usr/bin/patch "-d${S}" "-p${strip}" -N -f <"${patch}" >/dev/null
                #echo $patch
                epatch $patch
                retcode=$?
                eend "${retcode}"
                if [ "${retcode}" -ne 0 ]; then
                    die "Autopatch application failed"
                fi
            fi
        done
        >"/tmp/portage/${CATEGORY}/${PN}/.autopatched"
    fi
fi


so that it uses epatch. Can anybody tell me please why I get errors:

Code:
***** gtk+-2-smoothscroll-r6.patch *****

========================================

PATCH COMMAND:  patch -p0 -g0 -E --no-backup-if-mismatch < /etc/portage/package.
patches/x11-libs/gtk+/gtk+-2-smoothscroll-r6.patch

========================================
/var/tmp/portage/gtk+-2.8.12/temp/environment: line 2273: cat: command not found
/var/tmp/portage/gtk+-2.8.12/temp/environment: line 2273: patch: command not fou
nd
Back to top
View user's profile Send private message
millimille
n00b
n00b


Joined: 30 Apr 2006
Posts: 6

PostPosted: Mon May 22, 2006 1:42 pm    Post subject: Reply with quote

The bashrc version didn't seem to be working for me so I wrote my own, using epatch. There's a nasty hack to avoid some error messages though. This one patches ebuild.sh directly. Anyway, here it is:

Code:

--- bin/ebuild.sh.orig  2006-05-10 15:28:12.000000000 +1000
+++ bin/ebuild.sh       2006-05-22 23:28:15.512177750 +1000
@@ -661,6 +661,22 @@
        [ "$(type -t post_pkg_setup)" == "function" ] && post_pkg_setup
 }
 
+dyn_unpack_autopatch() {
+       vecho ">>> Applying custom patches"
+
+       OVERLAY='/etc/portage/patches'
+       PATCH_DIR="${OVERLAY}/${CATEGORY}"
+
+       if [ -d $PATCH_DIR ]; then
+               files=`ls -1 ${PATCH_DIR}/${PN}-*.patch 2>/dev/null`
+               cd ${S}
+
+               for file in ${files}; do
+                       epatch ${file}
+               done
+       fi
+}
+
 dyn_unpack() {
        trap "abort_unpack" SIGINT SIGQUIT
        [ "$(type -t pre_src_unpack)" == "function" ] && pre_src_unpack
@@ -702,6 +718,7 @@
        vecho ">>> Unpacking source..."
        src_unpack
        touch "${PORTAGE_BUILDDIR}/.unpacked" || die "IO Failure -- Failed 'touch .unpacked' in ${PORTAGE_BUILDDIR}"
+       dyn_unpack_autopatch    # DW: Patch Dir
        vecho ">>> Source unpacked."
        cd "${PORTAGE_BUILDDIR}"
 
@@ -1438,6 +1455,12 @@
        unset PORTAGE_RESTRICT
 fi
 
+# DW: UGLY hack
+if ! hasq "eutils" $INHERITED; then
+       INHERITED="$INHERITED eutils multilib portability"
+       inherit eutils
+fi
+
 # Expand KEYWORDS
 # We need to turn off pathname expansion for -* in KEYWORDS and
 # we need to escape ~ to avoid tilde expansion


Patches go into /etc/portage/patches/CATEGORY/NAME-desc.patch (ie, just inside the category directory).

Tested on portage-2.1_rc1-r4 (just then)[/code].
Back to top
View user's profile Send private message
ecatmur
Advocate
Advocate


Joined: 20 Oct 2003
Posts: 3595
Location: Edinburgh

PostPosted: Wed May 24, 2006 6:03 am    Post subject: Reply with quote

This is what I use:
Code:
function edautoreconf() {
        aclocal $(for x in m4 macros; do [[ -d $x ]] && echo "-I $x"; done) || die "aclocal failed"
        autoconf || die "autoconf failed"
        autoheader || die "autoheader failed"
        libtoolize --copy --force || die "libtoolize failed"
}

function edpatch_maybe_autotool() {
        ran_automake_at=()
        for am in $makefile_ams; do
                am="${path#$WORKDIR/}$(echo $am | sed 's:^\([^/]*/\+\)\{'$j'\}::')"
                ewarn "$am changed, trying to run automake"
                acpath="${am%/*}"; amade=""
                while true; do
                        acfull="$WORKDIR/$acpath/"
                        ewarn "trying: ${acfull}configure.{in,ac}"
                        if [[ -f "$acfull"configure.in || -f "$acfull"configure.ac ]]; then
                                if has "$acpath" "${ran_automake_at[@]}"; then
                                        echo -n "already run here, skipping"
                                        eend 0; amade="yes"; break
                                fi
                                ebegin "running automake in $acfull"
                                if ! (cd "$acfull"; automake --no-force); then
                                        eend $?; die "automake failed"
                                fi
                                ran_automake_at=("${ran_automake_at[@]}" "$acpath")
                                eend 0; amade="yes"; break
                        fi
                        [[ "$acpath" == */* ]] || break
                        acpath="${acpath%/*}"
                done
                if ! [[ "$amade" ]]; then
                        eerror "could not run automake"
                        die "patch failed"
                fi
        done
        for ac in $configure_acs; do
                ac="${path#$WORKDIR/}$(echo $ac | sed 's:^\([^/]*/\+\)\{'$j'\}::')"
                ebegin "$ac changed, running autoreconf"
                if ! (cd $WORKDIR/${ac%/configure.*}; edautoreconf); then
                        eend $?; die "autoreconf failed"
                fi
                eend 0
        done
}

function edpatch_apply() {
        local patch="$1" target=() tname="" path="" applied=""
        if grep "^RCS file: " "$patch"; then
                targets=("$(sed -e 's/^RCS file: \(.*\),v/\1/;ta;d;:a;q' "$patch")")
        else
                targets[0]="$(sed -e 's/--- \([^[:space:]]*\).*/\1/;ta;d;:a;q' "$patch")"
                targets[0]="${targets[0]%.orig}"
                targets[1]="$(sed -e 's/+++ \([^[:space:]]*\).*/\1/;ta;d;:a;q' "$patch")"
                targets[1]="${targets[1]%.orig}"
                [[ "${targets[0]}" == "${targets[1]}" ]] && targets=("$targets")
        fi
        makefile_ams=$(sed -e 's:^\(---\|+++\) \(\(.*/\)\?Makefile\.am\)\t.*:\2:;t;d' "$patch" | sort -u)
        configure_acs=$(sed -e 's:^\(---\|+++\) \(\(.*/\)\?configure\.\(ac\|in\)\)\t.*:\2:;t;d' "$patch" | sort -u)
        for target in "${targets[@]}"; do
                tname="$(basename "$target")"
                ewarn "Trying to apply $patch to $tname"
                i=0
                while true; do
                        ewarn "target $target"
                        for path in $(find "$WORKDIR" -name "$tname"); do
                                [[ "$path" == */"$target" ]] || continue
                                ewarn "trying: $path"
                                path="${path%$target}"
                                for j in $(seq 0 $i); do
                                        patch --dry-run -p$j -d "$path" <"$patch" \
                                                || continue
                                        ebegin "applying in $path"
                                        if ! patch -p$j -d "$path" <"$patch"; then
                                                eend $?
                                                die "patch failed, argh"
                                        fi
                                        eend 0
                                        edpatch_maybe_autotool
                                        applied="yes"; break
                                done; [[ "$applied" ]] && break
                        done; [[ "$applied" ]] && break
                        [[ "$target" == */* ]] || break
                        target="${target#*/}"
                        (( ++i ))
                done
                [[ "$applied" ]] && break
        done
        if ! [[ "$applied" ]]; then
                eerror "could not apply $patch"
                die "patch failed"
        fi
}

function edpatch() {
        for d in /etc/portage/patches/$CATEGORY/$PN*; do
                dn="${d##*/}"
                [[ "$dn" == "$PN" || "$dn" == "$P" || "$dn" == "$P-$PR" || "$dn" == "$PN[$SLOT]" || "$PVR" == ${dn#$PN-} ]] || continue
                for x in "$d"/*; do
                        [[ -f "$x" ]] && edpatch_apply "$x"
                done
        done
}

if [[ ! -f "${PORTAGE_BUILDDIR}/.patched" ]]; then
        echo ">>> Not marked as patched; patching..."
        edpatch
        touch "${PORTAGE_BUILDDIR}/.patched"
elif [[ "${PORTAGE_BUILDDIR}/.unpacked" -nt "${PORTAGE_BUILDDIR}/.patched" ]]; then
        echo ">>> WORKDIR has been re-unpacked; patching..."
        edpatch
        touch "${PORTAGE_BUILDDIR}/.patched"
else
        echo ">>> WORKDIR is up-to-date and patched, keeping..."
fi


The important thing it does is to check whether configure.{ac,in} or Makefile.am has been patched, and run autoconf/automake accordingly.
_________________
No more cruft
dep: Revdeps that work
Using command-line ACCEPT_KEYWORDS?
Back to top
View user's profile Send private message
Dolda2000
n00b
n00b


Joined: 05 Mar 2004
Posts: 37
Location: Täby, Sweden

PostPosted: Wed Jul 12, 2006 1:00 am    Post subject: Reply with quote

Portage changed the name of a couple of env variables in the some recent upgrades, so the version I posted before doesn't work anymore; in case anyone wants it, here's the new version:
Code:
if [ -n "$BUILDDIR" ]; then
    builddir="$BUILDDIR"
elif [ -n "$PORTAGE_BUILDDIR" ]; then
    builddir="$PORTAGE_BUILDDIR"
else
    dir "cannot find build dir"
fi
if [ "$EBUILD_PHASE" = unpack ]; then
    /bin/rm -f "${builddir}/.autopatched"
elif [ "$EBUILD_PHASE" = compile ]; then
    if [ ! -e "${builddir}/.autopatched" ]; then
        for patch in /etc/portage/package.patches/${CATEGORY}/${PN}/*.patch.[0-9]; do
            if [ -r "$patch" ]; then
                strip="${patch##*.}"
                einfo "Applying autopatch ${patch##*/}"
                /usr/bin/patch "-d${S}" "-p${strip}" -N -f <"${patch}" >/dev/null
                retcode=$?
                eend "${retcode}"
                if [ "${retcode}" -ne 0 ]; then
                    die "Autopatch application failed (S=${S}, strip=${strip})"
                fi
            fi
        done
        if [ -e "/etc/portage/package.patches/${CATEGORY}/${PN}/bashrc" ]; then
            einfo "Running bashrc for ${CATEGORY}/${PN}"
            . "/etc/portage/package.patches/${CATEGORY}/${PN}/bashrc"
        fi
        >"${builddir}/.autopatched"
    fi
fi
Back to top
View user's profile Send private message
wdsci
Tux's lil' helper
Tux's lil' helper


Joined: 02 Oct 2007
Posts: 122
Location: China

PostPosted: Fri Oct 26, 2007 2:48 am    Post subject: Reply with quote

I apologize in advance if it's against the rules to rekindle old threads like this, or if you've all had enough of custom patching and consider this post inane and irrelevant . . .

Anyway, I just wrote my own custom-patch patch (much like millimille's patch to ebuild.sh above). I thought it might be useful to be able to separate patches out by version, i.e. to have a patch apply only to Portage 2.1.3 but not to 2.1.4, and I figured I'd share my ebuild.sh patch, if anyone's interested:
Code:
*** portage-2.1.3/bin/ebuild.sh   2007-07-27 14:34:58.000000000 -0400
--- portage-2.1.3/bin/ebuild.sh   2007-10-25 21:12:52.000000000 -0400
***************
*** 766,771 ****
--- 766,788 ----
     cd "${WORKDIR}" || die "Directory change failed: \`cd '${WORKDIR}'\`"
     vecho ">>> Unpacking source..."
     qa_call src_unpack
+    if [ -n "${PORTAGE_PATCHDIR}" -a -d "${PORTAGE_PATCHDIR}/${CATEGORY}/${PN}" ]; then
+       vecho ">>> Applying custom patches..."
+       _runcustompatches() {
+          [ "$(type -t epatch)" == "function" ] || qa_source ${PORTDIR}/eclass/eutils.eclass
+          PATCHDIR=${PORTAGE_PATCHDIR}/${CATEGORY}/${PN}/${PV//.//}
+          PATCHLIST=
+          [ -d $PATCHDIR ] && PATCHLIST=" $PATCHDIR/* $PATCHLIST"
+          while [[ $PATCHDIR != ${PORTAGE_PATCHDIR}/${CATEGORY}/${PN} ]]; do
+             PATCHDIR=${PATCHDIR%/*}
+             [ -d $PATCHDIR ] && PATCHLIST="$PATCHDIR/* $PATCHLIST"
+          done
+          for x in $PATCHLIST; do
+             if [ -f $x ]; then epatch $x || die "Failed to apply patch $x"; fi
+          done
+       }
+       (_runcustompatches)
+    fi
     touch "${PORTAGE_BUILDDIR}/.unpacked" || die "IO Failure -- Failed 'touch .unpacked' in ${PORTAGE_BUILDDIR}"
     vecho ">>> Source unpacked."
     cd "${PORTAGE_BUILDDIR}"

This also requires adding a PORTAGE_PATCHDIR variable to make.conf. When emerging, say, Portage 2.1.3.9, it will apply all patches in ${PORTAGE_PATCHDIR}/sys-apps/portage, ${PORTAGE_PATCHDIR}/sys-apps/portage/2, ${PORTAGE_PATCHDIR}/sys-apps/portage/2/1, ${PORTAGE_PATCHDIR}/sys-apps/portage/2/1/3, and ${PORTAGE_PATCHDIR}/sys-apps/portage/2/1/3/9.

:) David
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Portage & Programming All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum