On Mon, 05 Mar 2012 22:10:48 -0400, David Bremner <[email protected]> wrote:
> 
> One thing I think I got wrong in round 1 is the blanket use of
> --ancestor-path. Consider the following branch structure, where 
> upstream has been merged into master several times.

Here is a revised version. Let's pretend there were all kinds of useful
discussions in some other medium that led to this.

No use of ancestor-path in this one, instead we just use git-log
(with 'git debpatch log') for a status command.  

Tagging and untagging is now only for a single commit.

I'm not 100% convinced about the order of parameters for fields with
values, but

    git debpatch +export $sha1 
    git debpatch -export $sha1 

seems quite natural, and 

    git debpatch +forwarded $sha1 $urlorwhatever  

is probably a less common usecase.

Thinking back to earlier discussions about configurability, I can see
this might be a bit _too_ flexible, it would be easy to typo 

    git debpatch +expert $sha1

And then wonder why the patch isn't exported. Perhaps I should put back 
"mark" and "unmark" as aliases for "+export" and "-export"

One thing this version doesn't do is export the metadata in the patch;
that could be useful, but needs a bit more hackery afaict.


>From 1e1029b0e7f78e43c56bc330606884a687bdc1e8 Mon Sep 17 00:00:00 2001
From: David Bremner <[email protected]>
Date: Mon, 5 Mar 2012 12:17:46 -0400
Subject: [PATCH] git-debpatch: select commits to be exported as quilt patches

This script allows the user to mark commits for export as
quilt-patches in debian/patches. gitpkg support is provided via
hooks/quilt-patches-deb-export-hook.
---
 git-debpatch                        |  108 +++++++++++++++++++++++++++++++++++
 git-debpatch.1                      |   68 ++++++++++++++++++++++
 gitpkg.1                            |    3 +-
 hooks/quilt-patches-deb-export-hook |    3 +
 4 files changed, 181 insertions(+), 1 deletions(-)
 create mode 100755 git-debpatch
 create mode 100644 git-debpatch.1

diff --git a/git-debpatch b/git-debpatch
new file mode 100755
index 0000000..945ee13
--- /dev/null
+++ b/git-debpatch
@@ -0,0 +1,108 @@
+#!/bin/bash
+
+GN="git notes --ref debpatch"
+patch_dir=debian/patches
+
+# get_field ref Field
+#
+function get_field() {
+    ${GN} show $1 2>/dev/null | sed -n "s/^$2: \(.*\)$/\1/p"
+}
+
+# set_field ref Field Val
+function set_field() {
+    other_fields=$(${GN} show $1 2>/dev/null | grep -v "^$2:")
+    printf "$2: $3\n$other_fields" | ${GN} add -f -F- $1 2>/dev/null
+}
+
+# remove_field ref Field
+function remove_field() {
+    other_fields=$(${GN} show $1 2>/dev/null | grep -v "^$2:")
+    if [ -n "$other_fields" ] ; then
+	printf "$other_fields" | ${GN} add -f -F- $1 2>/dev/null
+    else
+	$GN remove $1 2>/dev/null
+    fi
+}
+
+function is_exportable() {
+    [ $(get_field $1 Export)x = "truex" ]
+}
+
+function export_one_patch() {
+    if [ -f $patch_dir/series ]; then
+	count=$(wc -l "$patch_dir/series" | cut -f1 -d' ')
+    else
+	mkdir -p "$patch_dir" || exit 1
+	echo "# exported from git by git-debpatch" > "$patch_dir/series"
+	count=1
+    fi
+
+    name=$(git format-patch --start-number $count -1 -o "$patch_dir" $1)
+    echo "$name" | sed -e "s,$patch_dir/,,g" -e 's, ,\n,g' >> "$patch_dir/series"
+}
+
+
+function insist_commits() {
+    if [ $(git rev-parse $1 | wc -l) != $2 ]; then
+	echo "$1 does not expand to exactly $2 commits";
+	exit 1;
+	
+    fi;
+}
+
+function add_tag() {
+    insist_commits $1 1
+    field=${2^}
+    value=${3-true}
+    set_field $ref $field $value
+}
+
+function remove_tag() {
+    insist_commits $1 1
+    field=${2^}
+    value=${3-true}
+    remove_field $1 $field
+}
+
+case $1 in
+    fetch)
+	remote=${2-origin}
+	git fetch $remote refs/notes/debpatch:refs/notes/remotes/$remote/debpatch
+	exit 0;
+	;;
+    merge)
+	remote=${2-origin}
+	${GN} merge --strategy=cat_sort_uniq refs/notes/remotes/$remote/debpatch
+	exit 0;
+	;;
+    pull)
+	git debpatch fetch $2 && git debpatch merge $2
+	exit $?
+	;;
+    push)
+	remote=${2-origin}
+	git push $remote refs/notes/debpatch:refs/notes/debpatch
+	exit 0;
+	;;
+    +*)
+	ref=${2-HEAD}
+	add_tag $ref ${1#+} $3
+	;;
+    -*) 
+	ref=${2-HEAD}
+	remove_tag $ref ${1#-} $3
+	;;
+    toquilt)
+	ref=${2-HEAD}
+	git rev-list --reverse $ref | \
+	    while read hash ; do 
+	    if is_exportable $hash; then
+		export_one_patch $hash
+	    fi
+	done
+	;;
+
+    *)
+	GIT_NOTES_REF=refs/notes/debpatch exec git $*
+esac
diff --git a/git-debpatch.1 b/git-debpatch.1
new file mode 100644
index 0000000..3cf51ee
--- /dev/null
+++ b/git-debpatch.1
@@ -0,0 +1,68 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH GIT-DEBPATCH 1 "March 5, 2012"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+git\-debpatch \- annotate and optionally export commits
+.SH SYNOPSIS
+.B git\-debpatch
+.RI [ command ]  
+.RI [ params ] 
+
+.SH DESCRIPTION
+This program uses the \fBgit-notes\fP(1) facility to track certain
+metadata about git commits, and optionally export them as quilt patches.
+
+.SH COMMANDS
+
+The following commands are available:
+
+.TP
+.BR fetch " [remote]"
+Fetch debpatch specific notes from remote (default origin)
+
+.TP
+.BR merge " [remote]"
+Merge debpatch specific notes from remote (default origin).
+m
+.TP
+.BR pull " [remote]"
+Fetch and then merge.
+
+.TP
+.RI + field " [" commitish "] [" value ]
+Add the given field to the notes for commitish, with a default value
+of "true". The most useful example is "+export"
+
+.TP
+.RI - field " [" commitish ]
+Remove the given field from commitish
+
+.TP 
+.BR toquilt " ref-or-range"
+Export the any "+export" patches in the range to debian/patches. If
+debian/patches/series exists, new patches are appended.
+
+.RE
+Other commands are passed though to git with an appropriate set of
+GIT_NOTES_REF. Useful examples are "git debpatch log" and 
+"git debpatch show".
+
+.SH SEE ALSO
+.BR gitpkg (1),
+.BR git (1)
+.SH AUTHOR
+git-debpatch was written by David Bremner <[email protected]>.
diff --git a/gitpkg.1 b/gitpkg.1
index 1ba10e1..6e0b7cd 100644
--- a/gitpkg.1
+++ b/gitpkg.1
@@ -515,7 +515,8 @@ most cases.  For example:
 .fi
 .hy
 
-
+If the range of commits is prefixed with :debpatch:, then it will be passed to 
+\fBgit-debpatch\fP(1) for export, rather than \fBgit-format-patch\fP.
 
 .SS Hook Library Helpers
 These are even more trivial snippets, for operations which may be shared by
diff --git a/hooks/quilt-patches-deb-export-hook b/hooks/quilt-patches-deb-export-hook
index 98b2aa7..b158779 100644
--- a/hooks/quilt-patches-deb-export-hook
+++ b/hooks/quilt-patches-deb-export-hook
@@ -64,6 +64,9 @@ do_patches (){
 	case $line in
 	    \#*)
 		;;
+	     :debpatch:*)
+		GIT_DIR=$REPO_DIR/.git  git debpatch toquilt ${line//:debpatch:/}
+	        ;;
 	    *)
 		count=$(wc -l "$patch_dir/series" | cut -f1 -d' ')
 		if PATCHES="$(git --git-dir "$REPO_DIR/.git" format-patch --start-number $count -N -o "$patch_dir" "$line")"; then
-- 
1.7.9.1

Reply via email to