Refactor gbp-pq as preparation for rpm support
authorMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Thu, 12 Jan 2012 13:41:46 +0000 (15:41 +0200)
committerGuido Günther <agx@sigxcpu.org>
Wed, 18 Apr 2012 20:36:48 +0000 (22:36 +0200)
Separate some functions of gbp-pq into a basemodule, intended to be
re-used by the upcoming rpm variant of the tool.

Also, introduces a new python subpackage gbp.scripts.common to be used
for the re-usable parts of the scripts in the refactoring work.

gbp/scripts/common/__init__.py [new file with mode: 0644]
gbp/scripts/common/pq.py [new file with mode: 0644]
gbp/scripts/pq.py

diff --git a/gbp/scripts/common/__init__.py b/gbp/scripts/common/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/gbp/scripts/common/pq.py b/gbp/scripts/common/pq.py
new file mode 100644 (file)
index 0000000..e2293e8
--- /dev/null
@@ -0,0 +1,190 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2011 Guido Günther <agx@sigxcpu.org>
+# (C) 2012 Intel Corporation <markus.lehtonen@linux.intel.com>
+#    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; either version 2 of the License, or
+#    (at your option) any later version.
+#
+#    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+"""Common functionality for Debian and RPM patchqueue management"""
+
+import re
+import os
+import shutil
+import subprocess
+from gbp.git import (GitRepositoryError, GitRepository)
+from gbp.command_wrappers import (Command, GitCommand, RunAtCommand,
+                                  CommandExecFailed)
+from gbp.errors import GbpError
+import gbp.log
+from gbp.patch_series import (PatchSeries, Patch)
+
+PQ_BRANCH_PREFIX = "patch-queue/"
+
+
+def is_pq_branch(branch):
+    """
+    is branch a patch-queue branch?
+
+    >>> is_pq_branch("foo")
+    False
+    >>> is_pq_branch("patch-queue/foo")
+    True
+    """
+    return [False, True][branch.startswith(PQ_BRANCH_PREFIX)]
+
+
+def pq_branch_name(branch):
+    """
+    get the patch queue branch corresponding to branch
+
+    >>> pq_branch_name("patch-queue/master")
+    >>> pq_branch_name("foo")
+    'patch-queue/foo'
+    """
+    if not is_pq_branch(branch):
+        return PQ_BRANCH_PREFIX + branch
+
+
+def pq_branch_base(pq_branch):
+    """
+    get the branch corresponding to the given patch queue branch
+
+    >>> pq_branch_base("patch-queue/master")
+    'master'
+    >>> pq_branch_base("foo")
+    """
+    if is_pq_branch(pq_branch):
+        return pq_branch[len(PQ_BRANCH_PREFIX):]
+
+
+def write_patch(patch, patch_dir, options):
+    """Write the patch exported by 'git-format-patch' to it's final location
+       (as specified in the commit)"""
+    oldname = os.path.basename(patch)
+    newname = oldname
+    tmpname = patch + ".gbp"
+    old = file(patch, 'r')
+    tmp = file(tmpname, 'w')
+    in_patch = False
+    topic = None
+
+    # Skip first line (From <sha1>)
+    old.readline()
+    for line in old:
+        if line.lower().startswith("gbp-pq-topic: "):
+            topic = line.split(" ",1)[1].strip()
+            gbp.log.debug("Topic %s found for %s" % (topic, patch))
+            continue
+        tmp.write(line)
+    tmp.close()
+    old.close()
+
+    if not options.patch_numbers:
+        patch_re = re.compile("[0-9]+-(?P<name>.+)")
+        m = patch_re.match(oldname)
+        if m:
+            newname = m.group('name')
+
+    if topic:
+        topicdir = os.path.join(patch_dir, topic)
+    else:
+        topicdir = patch_dir
+
+    if not os.path.isdir(topicdir):
+        os.makedirs(topicdir, 0755)
+
+    os.unlink(patch)
+    dstname = os.path.join(topicdir, newname)
+    gbp.log.debug("Moving %s to %s" % (tmpname, dstname))
+    shutil.move(tmpname, dstname)
+
+    return dstname
+
+
+def get_maintainer_from_control():
+    """Get the maintainer from the control file"""
+    cmd = 'sed -n -e \"s/Maintainer: \\+\\(.*\\)/\\1/p\" debian/control'
+    cmdout = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout.readlines()
+
+    if len(cmdout) > 0:
+        maintainer = cmdout[0].strip()
+        m = re.match('(?P<name>.*[^ ]) *<(?P<email>.*)>', maintainer)
+        if m:
+            return m.group('name'), m.group('email')
+
+    return None, None
+
+
+def switch_to_pq_branch(repo, branch):
+    """
+    Switch to patch-queue branch if not already there, create it if it
+    doesn't exist yet
+    """
+    if is_pq_branch (branch):
+        return
+
+    pq_branch = pq_branch_name(branch)
+    if not repo.has_branch(pq_branch):
+        try:
+            repo.create_branch(pq_branch)
+        except CommandExecFailed:
+            raise GbpError, ("Cannot create patch-queue branch '%s'. Try 'rebase' instead."
+                % pq_branch)
+
+    gbp.log.info("Switching to '%s'" % pq_branch)
+    repo.set_branch(pq_branch)
+
+
+def apply_single_patch(repo, branch, patch, topic=None):
+    switch_to_pq_branch(repo, branch)
+    apply_and_commit_patch(repo, patch, topic)
+
+
+def apply_and_commit_patch(repo, patch, topic=None):
+    """apply a single patch 'patch', add topic 'topic' and commit it"""
+    author = { 'name': patch.author,
+               'email': patch.email,
+               'date': patch.date }
+
+    if not (patch.author and patch.email):
+        name, email = get_maintainer_from_control()
+        if name:
+            gbp.log.warn("Patch '%s' has no authorship information, "
+                         "using '%s <%s>'" % (patch.path, name, email))
+            author['name'] = name
+            author['email'] = email
+        else:
+            gbp.log.warn("Patch %s has no authorship information")
+
+    repo.apply_patch(patch.path)
+    tree = repo.write_tree()
+    msg = "%s\n\n%s" % (patch.subject, patch.long_desc)
+    if topic:
+        msg += "\nGbp-Pq-Topic: %s" % topic
+    commit = repo.commit_tree(tree, msg, [repo.head], author=author)
+    repo.update_ref('HEAD', commit, msg="gbp-pq import %s" % patch.path)
+
+
+def drop_pq(repo, branch):
+    if is_pq_branch(branch):
+        gbp.log.err("On a patch-queue branch, can't drop it.")
+        raise GbpError
+    else:
+        pq_branch = pq_branch_name(branch)
+
+    if repo.has_branch(pq_branch):
+        repo.delete_branch(pq_branch)
+        gbp.log.info("Dropped branch '%s'." % pq_branch)
+    else:
+        gbp.log.info("No patch queue branch found - doing nothing.")
index ad94525f3a7b45a0160ccf3e3eb1cc944f7e6066..2fcc0c8311879a4f84b6eab1f9eb410eca5f525f 100755 (executable)
 """manage patches in a patch queue"""
 
 import errno
-import re
 import os
 import shutil
-import subprocess
 import sys
 import tempfile
 from gbp.config import (GbpOptionParserDebian, GbpOptionGroup)
@@ -31,91 +29,15 @@ from gbp.command_wrappers import (Command, GitCommand, RunAtCommand,
 from gbp.errors import GbpError
 import gbp.log
 from gbp.patch_series import (PatchSeries, Patch)
+from gbp.scripts.common.pq import (is_pq_branch, pq_branch_name, pq_branch_base,
+                                 write_patch, switch_to_pq_branch,
+                                 apply_single_patch, apply_and_commit_patch,
+                                 drop_pq)
 
-PQ_BRANCH_PREFIX = "patch-queue/"
 PATCH_DIR = "debian/patches/"
 SERIES_FILE = os.path.join(PATCH_DIR,"series")
 
 
-def is_pq_branch(branch):
-    """
-    is branch a patch-queue branch?
-
-    >>> is_pq_branch("foo")
-    False
-    >>> is_pq_branch("patch-queue/foo")
-    True
-    """
-    return [False, True][branch.startswith(PQ_BRANCH_PREFIX)]
-
-
-def pq_branch_name(branch):
-    """
-    get the patch queue branch corresponding to branch
-
-    >>> pq_branch_name("patch-queue/master")
-    >>> pq_branch_name("foo")
-    'patch-queue/foo'
-    """
-    if not is_pq_branch(branch):
-        return PQ_BRANCH_PREFIX + branch
-
-
-def pq_branch_base(pq_branch):
-    """
-    get the branch corresponding to the given patch queue branch
-
-    >>> pq_branch_base("patch-queue/master")
-    'master'
-    >>> pq_branch_base("foo")
-    """
-    if is_pq_branch(pq_branch):
-        return pq_branch[len(PQ_BRANCH_PREFIX):]
-
-def write_patch(patch, patch_dir, options):
-    """Write the patch exported by 'git-format-patch' to it's final location
-       (as specified in the commit)"""
-    oldname = os.path.basename(patch)
-    newname = oldname
-    tmpname = patch + ".gbp"
-    old = file(patch, 'r')
-    tmp = file(tmpname, 'w')
-    in_patch = False
-    topic = None
-
-    # Skip first line (From <sha1>)
-    old.readline()
-    for line in old:
-        if line.lower().startswith("gbp-pq-topic: "):
-            topic = line.split(" ",1)[1].strip()
-            gbp.log.debug("Topic %s found for %s" % (topic, patch))
-            continue
-        tmp.write(line)
-    tmp.close()
-    old.close()
-
-    if not options.patch_numbers:
-        patch_re = re.compile("[0-9]+-(?P<name>.+)")
-        m = patch_re.match(oldname)
-        if m:
-            newname = m.group('name')
-
-    if topic:
-        topicdir = os.path.join(patch_dir, topic)
-    else:
-        topicdir = patch_dir
-
-    if not os.path.isdir(topicdir):
-        os.makedirs(topicdir, 0755)
-
-    os.unlink(patch)
-    dstname = os.path.join(topicdir, newname)
-    gbp.log.debug("Moving %s to %s" % (tmpname, dstname))
-    shutil.move(tmpname, dstname)
-
-    return dstname
-
-
 def export_patches(repo, branch, options):
     """Export patches from the pq branch into a patch series"""
     if is_pq_branch(branch):
@@ -148,20 +70,6 @@ def export_patches(repo, branch, options):
         gbp.log.info("No patches on '%s' - nothing to do." % pq_branch)
 
 
-def get_maintainer_from_control():
-    """Get the maintainer from the control file"""
-    cmd = 'sed -n -e \"s/Maintainer: \\+\\(.*\\)/\\1/p\" debian/control'
-    cmdout = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout.readlines()
-
-    if len(cmdout) > 0:
-        maintainer = cmdout[0].strip()
-        m = re.match('(?P<name>.*[^ ]) *<(?P<email>.*)>', maintainer)
-        if m:
-            return m.group('name'), m.group('email')
-
-    return None, None
-
-
 def safe_patches(series):
     """
     Safe the current patches in a temporary directory
@@ -251,70 +159,6 @@ def import_quilt_patches(repo, branch, series, tries, force):
         shutil.rmtree(tmpdir)
 
 
-def switch_to_pq_branch(repo, branch):
-    """
-    Switch to patch-queue branch if not already there, create it if it
-    doesn't exist yet
-    """
-    if is_pq_branch (branch):
-        return
-
-    pq_branch = pq_branch_name(branch)
-    if not repo.has_branch(pq_branch):
-        try:
-            repo.create_branch(pq_branch)
-        except CommandExecFailed:
-            raise GbpError, ("Cannot create patch-queue branch '%s'. Try 'rebase' instead."
-                % pq_branch)
-
-    gbp.log.info("Switching to '%s'" % pq_branch)
-    repo.set_branch(pq_branch)
-
-
-def apply_single_patch(repo, branch, patch, topic=None):
-    switch_to_pq_branch(repo, branch)
-    apply_and_commit_patch(repo, patch, topic)
-
-
-def apply_and_commit_patch(repo, patch, topic=None):
-    """apply a single patch 'patch', add topic 'topic' and commit it"""
-    author = { 'name': patch.author,
-               'email': patch.email,
-               'date': patch.date }
-
-    if not (patch.author and patch.email):
-        name, email = get_maintainer_from_control()
-        if name:
-            gbp.log.warn("Patch '%s' has no authorship information, "
-                         "using '%s <%s>'" % (patch.path, name, email))
-            author['name'] = name
-            author['email'] = email
-        else:
-            gbp.log.warn("Patch %s has no authorship information")
-
-    repo.apply_patch(patch.path)
-    tree = repo.write_tree()
-    msg = "%s\n\n%s" % (patch.subject, patch.long_desc)
-    if topic:
-        msg += "\nGbp-Pq-Topic: %s" % topic
-    commit = repo.commit_tree(tree, msg, [repo.head], author=author)
-    repo.update_ref('HEAD', commit, msg="gbp-pq import %s" % patch.path)
-
-
-def drop_pq(repo, branch):
-    if is_pq_branch(branch):
-        gbp.log.err("On a patch-queue branch, can't drop it.")
-        raise GbpError
-    else:
-        pq_branch = pq_branch_name(branch)
-
-    if repo.has_branch(pq_branch):
-        repo.delete_branch(pq_branch)
-        gbp.log.info("Dropped branch '%s'." % pq_branch)
-    else:
-        gbp.log.info("No patch queue branch found - doing nothing.")
-
-
 def rebase_pq(repo, branch):
     if is_pq_branch(branch):
         base = pq_branch_base(branch)