#!/bin/bash # # Author: Dave Hansen # xpatch: a 'patch' replacement so you can turn .src.rpms # into git trees. # #################################################### # # Why? # # Why do I want to do this? I don't run RHEL, Fedora, # SLES, or openSUSE so I don't have rpm around all the # time. Novell and Redhat do not exactly make it easy # to find their enterprise kernels, and there are a # *LOT* of old versions. It isn't always easy to get # access to these, even though my company has copies # laying around in lots of places. # # I often get a customer bug report saying, "I'm running # XYZ distro kernel". I never have source handy for # those kernels. If there was a git tree for all of # them, I bet I could find and fix distro bugs much # faster. # #################################################### # # How? # # If this file is called xpatch, then doing this will # get it in your path: # # mkdir $HOME/bin # PATH=$HOME/bin:$PATH # cp xpatch ~/bin/patch # chmod 755 ~/bin/patch # # This is how I run this script after setting PATH: # # rpm -Uvh kernel-1.2.4.2.src.rpm # cd /usr/src/packages/SPEC # rpmbuild -bc kernel-default.spec # # After RPM finishes, I have a git tree with history. # # If the RPM is based off of 2.6.27.33, then the # resulting git tree will be based off of the -stable # git tree's v2.6.27.33. # # Each distro-applied patch gets entered as its own # commit. Most of them have nice author and SOB lines, # as well as dates. This means I can use git-blame to # find culprits who introduce distro bugs. set -e function ver { eval `cat Makefile | head -4 | perl -pe 's/ //g'` echo $VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION } function gitaddnew { git ls-files -o --exclude-standard | xargs --no-run-if-empty git add } VER=$(ver) if ! [ -d .git ]; then echo first patch run?? >&2 echo ver: $VER #git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-2.6-stable.git linux.git echo copying git dir... cp -r /home/dave/linux/.git/ ./ git describe echo adding... gitaddnew echo diffing... if ! git diff v$VER | head -100 | diffstat | grep '^ 0 files changed'; then echo unable to find starting git revision exit 1 fi git reset v$(ver) echo diffstat: git diff v$VER | head -100 | diffstat git describe echo sleeping... sleep 10 VER="" fi PATCHNEXT=false PATCH="$(readlink /proc/self/fd/0)" for arg in "$@"; do if $PATCHNEXT; then PATCH="$arg" break; fi if [ "$arg" == "-i" ]; then PATCHNEXT=true fi; done echo PATCH: "'$PATCH'" { echo my stdin is from \"`readlink /proc/self/fd/0`\" echo PATCH: "'$PATCH'" echo args: "$@" } >> ~/logs/patch.log /usr/bin/patch "$@" # This is magic. It assumes that any patch changing the # kernel version is taking us to a new mainline release, # and it triggers us to try and merge with that git # commit from Linus's (or the -stable) tree. # # This might be better done by comparing the patches # themselves with the kernel.org patches, but this seems # to work OK for now. RET=$? VER2=$(ver) if [ "$VER" == "$VER2" ]; then echo version did not change. What happened? exit 2 exit $RET fi echo changing ver from $VER to $VER2 VER=$VER2 git describe gitaddnew git diff v$(ver) | diffstat | grep '^ 0 files changed' && git reset v$(ver) git describe exit $RET