Package: gitpkg
Version: 0.21
Severity: wishlist

Hi Ron;

Here is the script we discussed on IRC to allow selective export of
git commits as quilt patches, either interactively or as part of a git
hook.  The advantage over the existing scheme is that this supports
patches that are already merged into to the packaging/integration
branch.  Probably it is a bit rough around the edges (e.g. the man
page is a bit user-hostile), but hopefully we can use this bug to
track discussion and whip it into shape.

David
-- System Information:
Debian Release: wheezy/sid
  APT prefers testing
  APT policy: (900, 'testing')
Architecture: amd64 (x86_64)

Kernel: Linux 3.2.0-1-amd64 (SMP w/8 CPU cores)
Locale: LANG=en_CA.UTF-8, LC_CTYPE=en_CA.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages gitpkg depends on:
ii  dpkg-dev  1.16.1.2
ii  git       1:1.7.9.1-1

gitpkg recommends no packages.

Versions of packages gitpkg suggests:
ii  devscripts  2.11.4

-- no debconf information
>From 78ed58fee095218ed7683ac121177c66ae9c0a57 Mon Sep 17 00:00:00 2001
From: David Bremner <brem...@debian.org>
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                        |  127 +++++++++++++++++++++++++++++++++++
 git-debpatch.1                      |   83 +++++++++++++++++++++++
 gitpkg.1                            |    3 +-
 hooks/quilt-patches-deb-export-hook |    3 +
 4 files changed, 215 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..6a20fc1
--- /dev/null
+++ b/git-debpatch
@@ -0,0 +1,127 @@
+#!/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>/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 print_status() {
+    if is_exportable $1; then
+	printf "E\t"
+    else
+	printf "\t"
+    fi
+    printf "%7.7s\t" $1
+    printf "%0.30s" "$(git --no-pager log --format="%s" -1 $1)"
+    printf "\t%s\n" $(get_field $1 Forwarded)
+}
+
+function do_one_commit() {
+    case $1 in
+	export)
+	    set_field $2 Export true
+	    ;;
+	noexport)
+	    remove_field $2 Export 
+	    ;;
+	forwarded)
+	    set_field $2 Forwarded $3
+	    ;;
+	noforwarded)
+	    remove_field $2 Forwarded
+	    ;;
+	status)
+	    print_status $2
+	    ;;
+	toquilt)
+	    if is_exportable $2; then
+		export_one_patch $2
+	    fi
+	    ;;
+	*)
+	    echo "Unknown operation $1"
+	    exit 1;
+    esac
+}
+
+
+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;
+	;;
+    status|export|noexport|toquilt|forwarded)
+	if [ -z $2 ]; then
+	    echo "$1 needs a ref or a range"
+	    exit 1
+	fi
+	;;
+    *)
+	echo "Unknown operation $1"
+	exit 1;
+esac
+	
+case $(git rev-parse $2 | wc -l) in
+    1)
+	do_one_commit $1 $2 $3
+	;;
+    2)
+	git rev-list --ancestry-path --reverse $2 | \
+	    while read hash ; do do_one_commit $1 $hash $3;  done
+	;;
+    *)
+	echo "Internal error."
+	exit 1;
+esac
diff --git a/git-debpatch.1 b/git-debpatch.1
new file mode 100644
index 0000000..5af4af3
--- /dev/null
+++ b/git-debpatch.1
@@ -0,0 +1,83 @@
+.\"                                      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 ] " ref-or-range " [ 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 COMMIT SYNTAX
+
+In the following, remote is a git remote, and ref-or-range refers to
+either to a single git ref (hash, branch, tag), or ref1..ref2 In the
+latter case, this refers to all commits on the "ancestor path" from
+ref2 to ref1, not including ref1. See the \-\-ancestor-path option,
+\fBgit-rev-list\fP(1).
+
+.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
+.BR export " ref-or-range"
+Mark the given commit or range of commits to be exported. 
+
+.TP
+.BR noexport " ref-or-range"
+Mark the given commit or range of commits \fBnot\fP to be exported. 
+
+.TP
+.BR forwarded " ref-or-range " dest
+Mark the given commit or range of commits as forwarded to dest
+
+.TP
+.BR noforwarded " ref-or-range"
+Remove any forwarding annotation
+
+.TP 
+.BR toquilt " ref-or-range"
+Export the any marked patches in the range to debian/patches. If
+debian/patches/series exists, new patches are appended.
+
+.TP
+.BR status " ref-or-range"
+Print out a one line summary for each commit, showing export-status,
+hash, subject, forwarded status, separated by tabs
+
+.SH SEE ALSO
+.BR gitpkg (1),
+.BR git (1)
+.SH AUTHOR
+git-debpatch was written by David Bremner <brem...@debian.org>.
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