From: Dave Chinner Date: Thu, 30 Jul 2015 23:07:58 +0000 (+1000) Subject: libxfs-apply: allow commit range specification X-Git-Tag: v4.2.0-rc1~3^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8fa16d696568c72734522f9925a0785a60f24c67;p=thirdparty%2Fxfsprogs-dev.git libxfs-apply: allow commit range specification Rather than having to manully run the script for every commit in a series that needs to be applied, allow the commit ID to specify a range of commits in the form or a git refspec. Change the internal code to pull a commit at a time from the source repository and applying it to the current repository. If guilt is in use, this will result in a patch per commit, if guilt is not in use it will aggregate all the changes into a single commit. Also, fix the xfsprogs libxfs file filter match to exclude files from the fs/xfs directory correctly. Note: this pulls in a function from guilt to handle commit ids in a sane manner. Signed-off-by: Dave Chinner --- diff --git a/tools/libxfs-apply b/tools/libxfs-apply index e6538c806..3b57298c6 100755 --- a/tools/libxfs-apply +++ b/tools/libxfs-apply @@ -17,7 +17,7 @@ usage() cleanup() { - rm -f $PATCH $LIBXFS_FILES $NEWPATCH + rm -f $PATCH } fail() @@ -55,7 +55,7 @@ done if [ -n "$PATCH" ]; then if [ -n "$REPO" -o -n "$COMMIT_ID" ]; then - usage "Need to specify either patch or source epo/commit" + usage "Need to specify either patch or source repo/commit" fi elif [ -z "$REPO" -o -z "$COMMIT_ID" ]; then usage "Need to specify both source repo and commit id" @@ -63,81 +63,170 @@ fi check_repo Destination -LIBXFS_FILES=`mktemp` -NEWPATCH=`mktemp` - -# switch to source repo and pull the commit into the patch file -if [ -n "$COMMIT_ID" ]; then - pushd $REPO > /dev/null - check_repo Source - PATCH=`mktemp` - git show $2 > $PATCH || usage "Bad source commit ID!" - popd > /dev/null -fi - # Are we using guilt? This works even if no patch is applied. guilt top &> /dev/null if [ $? -eq 0 ]; then GUILT=1 fi +#this is pulled from the guilt code to handle commit ids sanely. +# usage: munge_hash_range +# +# this means: +# - one commit +# .. - hash until head (excludes hash, includes head) +# .. - until hash (includes hash) +# .. - from hash to hash (inclusive) +# +# The output of this function is suitable to be passed to "git rev-list" +munge_hash_range() +{ + case "$1" in + *..*..*|*\ *) + # double .. or space is illegal + return 1;; + ..*) + # e.g., "..v0.10" + echo ${1#..};; + *..) + # e.g., "v0.19.." + echo ${1%..}..HEAD;; + *..*) + # e.g., "v0.19-rc1..v0.19" + echo ${1%%..*}..${1#*..};; + ?*) + # e.g., "v0.19" + echo $1^..$1;; + *) # empty + return 1;; + esac + return 0 +} + # Filter the patch into the right format & files for the other tree +filter_kernel_patch() +{ + local _patch=$1 + local _libxfs_files="" -if [ -d "fs/xfs/libxfs" ]; then # We are applying a progs patch to the kernel tree - lsdiff $PATCH | grep -q "a/libxfs/" + lsdiff $_patch | grep -q "a/libxfs/" if [ $? -ne 0 ]; then fail "Doesn't look like an xfsprogs patch with libxfs changes" fi # The files we will try to apply to - ls -1 fs/xfs/libxfs/*.[ch] | sed -e "s%.*/\(.*\)%*\1%" > $LIBXFS_FILES + _libxfs_files=`mktemp` + ls -1 fs/xfs/libxfs/*.[ch] | sed -e "s%.*/\(.*\)%*\1%" > $_libxfs_files # Create the new patch filterdiff \ - -I $LIBXFS_FILES \ + -I $_libxfs_files \ --strip=1 \ --addoldprefix=a/fs/xfs/ \ --addnewprefix=b/fs/xfs/ \ - $PATCH > $NEWPATCH + $_patch + + rm -f $_libxfs_files +} + +filter_xfsprogs_patch() +{ + local _patch=$1 + local _libxfs_files="" -elif [ -d "libxfs" -a -d "libxlog" ]; then # We are applying a kernel patch to the xfsprogs tree - lsdiff $PATCH | grep -q "a/fs/xfs/libxfs/" + lsdiff $_patch | grep -q "a/fs/xfs/libxfs/" if [ $? -ne 0 ]; then fail "Doesn't look like a kernel patch with libxfs changes" fi # The files we will try to apply to - ls -1 libxfs/*.[ch] | sed -e "s%.*/\(.*\)%*\1%" > $LIBXFS_FILES + _libxfs_files=`mktemp` + ls -1 libxfs/*.[ch] | sed -e "s%.*/\(.*\)%*libxfs/\1%" > $_libxfs_files # Create the new patch filterdiff \ - -I $LIBXFS_FILES \ + -I $_libxfs_files \ --strip=3 \ --addoldprefix=a/ \ --addnewprefix=b/ \ - $PATCH > $NEWPATCH -fi + $_patch -echo "Filtered patch for $REPO contains:" -lsdiff $NEWPATCH + rm -f $_libxfs_files +} + +apply_patch() +{ + local _patch=$1 + local _new_patch=`mktemp` + if [ -d "fs/xfs/libxfs" ]; then + filter_kernel_patch $_patch > $_new_patch + elif [ -d "libxfs" -a -d "libxlog" ]; then + filter_xfsprogs_patch $_patch > $_new_patch + fi -# Ok, now apply with guilt or patch; either may fail and require a force -# and/or a manual reject fixup -if [ $GUILT -eq 1 ]; then - echo "$REPO looks like a guilt directory." - PATCHES=`guilt applied | wc -l` - if [ $PATCHES -gt 0 ]; then - echo -n "Top patch is: " - guilt top + echo "Filtered patch for $REPO contains:" + lsdiff $_new_patch + + # Ok, now apply with guilt or patch; either may fail and require a force + # and/or a manual reject fixup + if [ $GUILT -eq 1 ]; then + echo "$REPO looks like a guilt directory." + PATCHES=`guilt applied | wc -l` + if [ $PATCHES -gt 0 ]; then + echo -n "Top patch is: " + guilt top + fi + read -r -p "Create new Guilt patch? (Enter patch name or return to skip) " response + if [ -n "$response" ]; then + guilt refresh; + guilt import -P $response $_new_patch + guilt push + fi + else + echo "Applying with patch utility:" + patch -p1 < $_new_patch fi - read -r -p "Create new Guilt patch? (Enter patch name or return to skip) " response - [ -z "$response" ] && guilt refresh; guilt import -P $response $NEWPATCH; guilt push -else - echo "Applying with patch utility:" - patch -p1 < $NEWPATCH + + rm -f $_new_patch + echo "Patch was applied in $REPO; check for rejects, guilt push -f, etc" +} + +# single patch is easy. +if [ -z "$COMMIT_ID" ]; then + apply_patch $PATCH + cleanup + exit 0 fi -echo "Patch was applied in $REPO; check for rejects, guilt push -f, etc" +# switch to source repo and get individual commit IDs +# +# git rev-list gives us a list in reverse chronological order, so we need to +# reverse that to give us the order we require. +pushd $REPO > /dev/null +check_repo Source +hashr=`munge_hash_range $COMMIT_ID` +echo "Commits to apply:" +commit_list=`git rev-list $hashr | tac` + +# echo the list of commits for confirmation +git log --oneline $hashr |tac +read -r -p "Proceed [y|N]? " response +if [ -z "$response" -o "$response" != "y" ]; then + fail "Aborted!" +fi +popd > /dev/null + +PATCH=`mktemp` +for commit in $commit_list; do + + # switch to source repo and pull commit into a patch file + pushd $REPO > /dev/null + git show $commit > $PATCH || usage "Bad source commit ID!" + popd > /dev/null + + apply_patch $PATCH +done + cleanup