ubuntu-dev-tools/edit-patch
2010-12-02 23:36:32 +01:00

269 lines
7.1 KiB
Bash
Executable File

#!/bin/sh
#
# Copyright (C) 2009 Canonical
#
# Authors:
# Daniel Holbach
# Michael Vogt
# David Futcher
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; version 3.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
set -e
PATCHSYSTEM="unknown"
PATCHNAME="no-patch-name"
PREFIX="debian/patches"
PATCH_DESC=$(cat<<EOF
## Description: add some description\
\n## Origin/Author: add some origin or author\
\n## Bug: bug URL
EOF
)
fatal_error() {
echo "$@" >&2
exit 1
}
# check if the given binary is installed and give a error if not
# arg1: binary
# arg2: error message
require_installed() {
if ! which "$1" >/dev/null; then
fatal_error "$2"
fi
}
ensure_debian_dir() {
if [ ! -e debian/control ] || [ ! -e debian/rules ]; then
fatal_error "Can not find debian/rules or debian/control. Not in a debian dir?"
fi
}
detect_patchsystem() {
CDBS_PATCHSYS="^[^#]*simple-patchsys.mk"
if grep -q "$CDBS_PATCHSYS" debian/rules; then
PATCHSYSTEM="cdbs"
require_installed cdbs-edit-patch "no cdbs-edit-patch found, is 'cdbs' installed?"
elif [ -e debian/patches/00list ]; then
PATCHSYSTEM="dpatch"
require_installed dpatch-edit-patch "no dpatch-edit-patch found, is 'dpatch' installed?"
elif [ -e debian/patches/series -o \( \
-e debian/source/format -a "$(cat debian/source/format)" = "3.0 (quilt)" \) ]; then
PATCHSYSTEM="quilt"
require_installed quilt "no quilt found, is 'quilt' installed?"
else
PATCHSYSTEM="none"
PREFIX="debian/applied-patches"
fi
}
# remove full path if given
normalize_patch_path() {
PATCHNAME=${PATCHNAME##*/}
echo "Normalizing patch path to $PATCHNAME"
}
# ensure (for new patches) that:
# - dpatch ends with .dpatch
# - cdbs/quilt with .patch
normalize_patch_extension() {
# check if we have a patch already
if [ -e $PREFIX/$PATCHNAME ]; then
echo "Patch $PATCHNAME exists, not normalizing"
return
fi
# normalize name for new patches
PATCHNAME=${PATCHNAME%.*}
if [ "$PATCHSYSTEM" = "quilt" ]; then
PATCHNAME="${PATCHNAME}.patch"
elif [ "$PATCHSYSTEM" = "cdbs" ]; then
PATCHNAME="${PATCHNAME}.patch"
elif [ "$PATCHSYSTEM" = "dpatch" ]; then
PATCHNAME="${PATCHNAME}.dpatch"
elif [ "$PATCHSYSTEM" = "none" ]; then
PATCHNAME="${PATCHNAME}.patch"
fi
echo "Normalizing patch name to $PATCHNAME"
}
edit_patch_cdbs() {
cdbs-edit-patch $PATCHNAME
vcs_add debian/patches/$1
}
edit_patch_dpatch() {
dpatch-edit-patch $PATCHNAME
# add if needed
if ! grep -q $1 $PREFIX/00list; then
echo "$1" >> $PREFIX/00list
fi
vcs_add $PREFIX/00list $PREFIX/$1
}
edit_patch_quilt() {
export QUILT_PATCHES=debian/patches
if [ -e $PREFIX/$1 ]; then
# if its a existing patch and we are at the end of the stack,
# go back at the beginning
if ! quilt unapplied; then
quilt pop -a
fi
quilt push $1
else
# if its a new patch make sure we are at the end of the stack
if quilt unapplied >/dev/null; then
quilt push -a
fi
quilt new $1
fi
# use a sub-shell
quilt shell
quilt refresh
quilt pop -a
vcs_add $PREFIX/$1 $PREFIX/series
}
vcs_add() {
if [ -d .bzr ]; then
bzr add $@
elif [ -d .git ];then
git add $@
else
echo "Remember to add $@ to a VCS if you use one"
fi
}
vcs_commit() {
# check if debcommit is happy
if ! debcommit --noact 2>/dev/null; then
return
fi
# commit (if the user confirms)
debcommit --confirm
}
add_changelog() {
S="$PREFIX/$1: [DESCRIBE CHANGES HERE]"
if head -n1 debian/changelog|grep UNRELEASED; then
dch --append "$S"
else
dch --increment "$S"
fi
# let the user edit it
dch --edit
}
add_patch_tagging() {
# check if we have a descripton already
if grep "## Description:" $PREFIX/$1; then
return
fi
# if not, add one
RANGE=1,1
# make sure we keep the first line (for dpatch)
if head -n1 $PREFIX/$1|grep -q '^#'; then
RANGE=2,2
fi
sed -i ${RANGE}i"$PATCH_DESC" $PREFIX/$1
}
detect_patch_location() {
# Checks whether the specified patch exists in debian/patches or on the filesystem
FILENAME=${PATCHNAME##*/}
if [ -f "$PREFIX/$FILENAME" ]; then
PATCHTYPE="debian"
elif [ -f "$PATCHNAME" ]; then
PATCHTYPE="file"
PATCHORIG="$PATCHNAME"
else
if [ "$PATCHSYSTEM" = "none" ]; then
fatal_error "No patchsystem detected, cannot create new patch (no dpatch/quilt/cdbs?)"
else
PATCHTYPE="new"
fi
fi
}
edit_patch_none() {
# Dummy edit-patch function, just display a warning message
echo "No patchsystem could be found so the patch was applied inline and a copy \
stored in debian/patches-applied. Please remember to mention this in your changelog."
}
handle_file_patch() {
if [ "$PATCHTYPE" = "file" ]; then
[ -f "$PATCHORIG" ] || fatal_error "No patch detected"
if [ "$PATCHSYSTEM" = "none" ]; then
# If we're supplied a file and there is no patchsys we apply it directly
# and store it in debian/applied patches
[ -d $PREFIX ] || mkdir $PREFIX
patch -p0 < "$PATCHORIG"
cp "$PATCHORIG" "$PREFIX/$PATCHNAME"
else
# Patch type is file but there is a patchsys present, so we add it
# correctly
cp "$PATCHORIG" "$PREFIX/$PATCHNAME"
if [ "$PATCHSYSTEM" = "quilt" ]; then
echo "$PATCHNAME" >> $PREFIX/series
elif [ "$PATCHSYSTEM" = "dpatch" ]; then
echo "$PATCHNAME" >> $PREFIX/00list
# Add the dpatch header to files that don't already have it
if ! grep -q "@DPATCH@" "$PREFIX/$PATCHNAME"; then
sed -i '1i#! /bin/sh /usr/share/dpatch/dpatch-run\n@DPATCH@' $PREFIX/$PATCHNAME
fi
fi
echo "Copying and applying new patch. You can now edit the patch or exit the subshell to save."
fi
fi
}
# TODO:
# - edit-patch --remove implementieren
# - dbs patch system
main() {
# parse args
if [ $# -ne 1 ]; then
fatal_error "Need exactly one patch name"
fi
PATCHNAME="$1"
# do the work
ensure_debian_dir
detect_patchsystem
detect_patch_location
normalize_patch_path
normalize_patch_extension
handle_file_patch
edit_patch_$PATCHSYSTEM $PATCHNAME
add_patch_tagging $PATCHNAME
add_changelog $PATCHNAME
vcs_commit
}
main $@