Files
poky/meta/recipes-devtools/guilt/files/guilt.patch
Richard Purdie 29d6678fd5 Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things
and is generally overwhelming. This commit splits it into several
logical sections roughly based on function, recipes.txt gives more
information about the classifications used.

The opportunity is also used to switch from "packages" to "recipes"
as used in OpenEmbedded as the term "packages" can be confusing to
people and has many different meanings.

Not all recipes have been classified yet, this is just a first pass
at separating things out. Some packages are moved to meta-extras as
they're no longer actively used or maintained.

Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
2010-08-27 15:29:45 +01:00

318 lines
9.1 KiB
Diff

guilt: enhanced patch queue management
guilt prefers to track the status and series of patches
under .git/patches. But this location doesn't allow the
status of a quilt queue to be committed to a secondary
repository and later restored.
This change does three things:
- allows GUILT_BASE to be changed (with a default to "wrs")
- allows shadow tracking of the patches (for rebase)
- enhances the header detection and creation of patches
as they are pushed onto the tree.
Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
---
guilt | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 159 insertions(+), 24 deletions(-)
--- a/guilt
+++ b/guilt
@@ -153,14 +153,16 @@ get_branch()
verify_branch()
{
- [ ! -d "$GIT_DIR/patches" ] &&
+ [ ! -d "$GUILT_DIR" ] &&
die "Patches directory doesn't exist, try guilt-init"
- [ ! -d "$GIT_DIR/patches/$branch" ] &&
+ [ ! -d "$GUILT_DIR/$branch" ] &&
die "Branch $branch is not initialized, try guilt-init"
- [ ! -f "$GIT_DIR/patches/$branch/series" ] &&
+ [ ! -f "$GUILT_DIR/$branch/series" ] &&
die "Branch $branch does not have a series file"
- [ ! -f "$GIT_DIR/patches/$branch/status" ] &&
+ [ ! -f "$GUILT_DIR/$branch/status" ] &&
die "Branch $branch does not have a status file"
+ [ -f "$GUILT_DIR/$branch/applied" ] &&
+ die "Warning: Branch $branch has 'applied' file - guilt is not compatible with stgit"
[ -f "$GIT_DIR/patches/$branch/applied" ] &&
die "Warning: Branch $branch has 'applied' file - guilt is not compatible with stgit"
}
@@ -339,6 +341,17 @@ BEGIN{}
'
}
+# usage: do_get_only_patch patchfile
+# similar to do_get_patch except everything leading up to
+# the first diff line and after the last chunk are removed
+do_get_only_patch()
+{
+ cat "$1" | awk '
+BEGIN{}
+/^(diff )/,/^(-- |END{})/
+' | sed '/^-- *$/D'
+}
+
# usage: do_get_header patchfile
do_get_header()
{
@@ -352,8 +365,13 @@ do_get_header()
BEGIN{skip=0}
/^Subject:/ && (NR==1){print substr($0, 10); next}
/^From:/{skip=1; next}
+/^Author:/{skip=1; next}
+/^Date:/{skip=1; next}
+/^commit/{skip=1; next}
/^[ \t\f\n\r\v]*$/ && (skip==1){skip=0; next}
/^(diff |---$|--- )/{exit}
+/^diff --git/{exit}
+/^Index: /{exit}
{print $0}
END{}
'
@@ -415,6 +433,15 @@ series_insert_patch()
mv "$series.tmp" "$series"
}
+series_append_patch()
+{
+ # unlike series_insert_patch, which inserts the passed
+ # patch after the current top patch, this function always
+ # appends the patch to the series
+
+ echo $1 >> "$series"
+}
+
# usage: series_remove_patch <patchname>
series_remove_patch()
{
@@ -473,8 +500,7 @@ remove_patch_refs()
# usage: pop_many_patches <commitish> <number of patches>
pop_many_patches()
{
- assert_head_check
-
+ head_check "`tail -1 < "$applied" | cut -d: -f 1`"
(
cd_to_toplevel
@@ -508,50 +534,149 @@ remove_ref()
)
}
+prep_patch()
+{
+ patch=$1;
+ tgt=$2;
+
+ if test -f $patch; then
+ case $patch in
+ *.gz) gzip -dc $patch > $tgt ;;
+ *.bz2) bzip2 -dc $patch > $tgt ;;
+ *) cp $patch $tgt ;;
+ esac;
+ fi;
+}
+
# usage: commit patchname parent
commit()
{
(
TMP_MSG=`get_tmp_file msg`
+ TMP_PATCH=`get_tmp_file patch`
+ TMP_PATCH_OUT=`get_tmp_file patch_out`
+ TMP_INFO=`get_tmp_file info`
p="$GUILT_DIR/$branch/$1"
pname="$1"
+ prep_patch "$p" "$TMP_PATCH"
+ p=$TMP_PATCH
+
cd_to_toplevel
git diff-files --name-only | (while read n; do git update-index "$n" ; done)
+ # borrowed from git-am
+ header_type=git
+ git mailinfo "$TMP_MSG" "$TMP_PATCH_OUT" \
+ <"$p" >"$TMP_INFO";
+
+ # skip pine's internal folder data
+ grep '^Author: Mail System Internal Data$' \
+ <"$TMP_INFO" >/dev/null
+
+ git stripspace < "$TMP_MSG" > "$TMP_MSG.clean"
+ mv "$TMP_MSG.clean" "$TMP_MSG"
+ git stripspace < "$TMP_INFO" > "$TMP_INFO.clean"
+ mv "$TMP_INFO.clean" "$TMP_INFO"
+
+ # If mailinfo couldn't get something , try another way
# grab a commit message out of the patch
- do_get_header "$p" > "$TMP_MSG"
+ if [ ! -s "$TMP_MSG" ] || [ ! -s "$TMP_INFO" ]; then
+ do_get_header "$p" > "$TMP_MSG"
+ header_type=guilt
+ fi
- # make a default commit message if patch doesn't contain one
- [ ! -s "$TMP_MSG" ] && echo "patch $pname" > "$TMP_MSG"
+ # last try: make a default commit message if patch doesn't contain one
+ [ ! -s "$TMP_MSG" ] && echo "auto_msg: patch $pname" > "$TMP_MSG"
- # extract a From line from the patch header, and set
- # GIT_AUTHOR_{NAME,EMAIL}
- author_str=`sed -n -e '/^From:/ { s/^From: //; p; q; }; /^(diff |---$|--- )/ q' "$p"`
- if [ ! -z "$author_str" ]; then
+
+ if [ "$header_type" = "guilt" ]; then
+
+ # extract a From line from the patch header, and set
+ # GIT_AUTHOR_{NAME,EMAIL}
+ author_str=`sed -n -e '/^From:/ { s/^From: //; p; q }; /^(diff |---)/ q' "$p"`
+ if [ ! -z "$author_str" ]; then
GIT_AUTHOR_NAME=`echo $author_str | sed -e 's/ *<.*$//'`
export GIT_AUTHOR_NAME="${GIT_AUTHOR_NAME:-" "}"
export GIT_AUTHOR_EMAIL="`echo $author_str | sed -e 's/[^<]*//'`"
- fi
+ fi
+
+
+ # check in the patch for a subject
+ SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$p")"
+ if [ -z "$SUBJECT" ]; then
+ # if we can't find a subject in the patch, then let's construct
+ # one from the header of the patch itself
+ SUBJECT=`cat "$TMP_MSG" | head -n 1`
+ if [ ${#SUBJECT} -gt 60 ]; then
+ SUBJECT=${SUBJECT: -60}
+ fi
+ fi
+
+ if [ -z "$SUBJECT" ]; then
+ # if we are *still* without a subject, then just use
+ # the patch name
+ SUBJECT=`echo $1 | sed 's%^patch *%%'`
+
+ if [ ${#SUBJECT} -gt 60 ]; then
+ SUBJECT=${SUBJECT: -60}
+ fi
+ fi
- # must strip nano-second part otherwise git gets very
- # confused, and makes up strange timestamps from the past
- # (chances are it decides to interpret it as a unix
- # timestamp).
- export GIT_AUTHOR_DATE="`stat -c %y "$p" | sed -e '
+ SUBJECT=`echo $SUBJECT | sed s'%^ *%%'`
+
+ if [ ! -z "$SUBJECT" ]; then
+ echo "$SUBJECT" >> $TMP_MSG.subject
+ echo "" >> $TMP_MSG.subject
+ cat "$TMP_MSG" >> $TMP_MSG.subject
+ mv "$TMP_MSG.subject" "$TMP_MSG"
+ fi
+
+ # must strip nano-second part otherwise git gets very
+ # confused, and makes up strange timestamps from the past
+ # (chances are it decides to interpret it as a unix
+ # timestamp).
+ export GIT_AUTHOR_DATE="`stat -c %y "$p" | sed -e '\
s/^\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\) \([0-9]\{2\}\):\([0-9]\{2\}\):\([0-9]\{2\}\)\.[0-9]* \(.*\)$/\1-\2-\3 \4:\5:\6 \7/'`"
- export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
+ export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
+ else
+ # using git headers, closely related to git-am
+
+ GIT_AUTHOR_NAME="$(sed -n '/^Author/ s/Author: //p' "$TMP_INFO")"
+ GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' "$TMP_INFO")"
+ GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' "$TMP_INFO")"
+ if test -z "$GIT_AUTHOR_EMAIL"
+ then
+ echo "Warning: patch does not have a valid e-mail address."
+ GIT_AUTHOR_EMAIL=$GIT_AUTHOR_NAME
+ fi
+
+ SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$TMP_INFO")"
+ if [ ! -z "$SUBJECT" ]; then
+ echo "$SUBJECT" >> $TMP_MSG.subject
+ echo "" >> $TMP_MSG.subject
+ cat "$TMP_MSG" >> $TMP_MSG.subject
+ mv "$TMP_MSG.subject" "$TMP_MSG"
+ fi
+ export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
+ fi
# commit
treeish=`git write-tree`
commitish=`git commit-tree $treeish -p $2 < "$TMP_MSG"`
+ if [ ! $? -eq 0 ]; then
+ echo "ERROR. Could not commit tree"
+ git-reset --hard HEAD^
+ exit 1
+ fi
git update-ref HEAD $commitish
# mark patch as applied
git update-ref "refs/patches/$branch/$pname" HEAD
- rm -f "$TMP_MSG"
+ rm -f "$TMP_MSG" "$TMP_LOG" "$TMP_PATCH" "$TMP_INFO" "$TMP_PATCH_OUT"
+
)
}
@@ -568,7 +693,7 @@ push_patch()
bail_action="$2"
reject="--reject"
- assert_head_check
+ head_check "`tail -1 < "$applied" | cut -d: -f 1`"
cd_to_toplevel
# apply the patch if and only if there is something to apply
@@ -671,7 +796,7 @@ refresh_patch()
# incldiffstat
__refresh_patch()
{
- assert_head_check
+ head_check "`tail -1 < "$applied" | cut -d: -f 1`"
(
TMP_DIFF=`get_tmp_file diff`
@@ -711,6 +836,10 @@ __refresh_patch()
head -n "-$N" < "$applied" > "$applied.tmp"
mv "$applied.tmp" "$applied"
+
+ # update the shadow status.
+ ref=`cat $GIT_DIR/refs/tags/${branch}_top`
+ echo "$ref:$1" >> $applied_shadow
)
}
@@ -791,7 +920,12 @@ diffstat=`git config --bool guilt.diffst
# The following gets run every time this file is source'd
#
-GUILT_DIR="$GIT_DIR/patches"
+
+# GUILT_DIR="$GIT_DIR/patches"
+if [ -z "$GUILT_BASE" ]; then
+ GUILT_BASE=wrs
+fi
+GUILT_DIR="$GUILT_BASE/patches"
branch=`get_branch`
@@ -814,6 +948,7 @@ fi
# very useful files
series="$GUILT_DIR/$branch/series"
applied="$GUILT_DIR/$branch/status"
+applied_shadow="$GUILT_DIR/$branch/shadow_status"
guards_file="$GUILT_DIR/$branch/guards"
# determine a pager to use for anything interactive (fall back to more)