gbp-pq: readiness to configure the pq branch name
authorMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Fri, 6 Feb 2015 14:23:46 +0000 (16:23 +0200)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 3 Mar 2015 08:07:46 +0000 (10:07 +0200)
All other gbp branches have configurable names. This commit adds the
readiness for user to configure/change the name of the patch-queue
branches, as well.

Patch-queue is defined in options as a format string, where '%(branch)s'
refers to the debian/packaging branch. If the pq-branch format string
does not contain '%(branch)s', there is only one patch-queue branch and
the debian/packaging branch is used as its base branch. That is, e.g. a
'gbp-pq switch' operation from the patch-queue branch always switches to
the debian/packaging branch.

Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com>
Signed-off-by: Olev Kartau <olev.kartau@intel.com>
gbp/scripts/common/pq.py
gbp/scripts/pq.py
gbp/scripts/pq_rpm.py
tests/13_test_gbp_pq.py

index ebe3258f0cff3e2b7ebdf69783351d442eeb5665..ab72f6f9637e2686ee59469700d2a8bf7f533014 100644 (file)
@@ -34,43 +34,99 @@ from gbp.git.modifier import GitModifier, GitTz
 from gbp.errors import GbpError
 import gbp.log
 
-PQ_BRANCH_PREFIX = "patch-queue/"
+DEFAULT_PQ_BRANCH_NAME = "patch-queue/%(branch)s"
 
 
-def is_pq_branch(branch):
+def is_pq_branch(branch, options):
     """
     is branch a patch-queue branch?
 
-    >>> is_pq_branch("foo")
+    >>> from optparse import OptionParser
+    >>> (opts, args) = OptionParser().parse_args([])
+    >>> is_pq_branch("foo", opts)
     False
-    >>> is_pq_branch("patch-queue/foo")
+    >>> is_pq_branch("patch-queue/foo", opts)
+    True
+    >>> opts.pq_branch = "%(branch)s/development"
+    >>> is_pq_branch("foo/development/bar", opts)
+    False
+    >>> is_pq_branch("bar/foo/development", opts)
+    True
+    >>> opts.pq_branch = "development"
+    >>> is_pq_branch("development", opts)
+    True
+    >>> opts.pq_branch = "my/%(branch)s/pq"
+    >>> is_pq_branch("my/foo/pqb", opts)
+    False
+    >>> is_pq_branch("my/foo/pq", opts)
     True
     """
-    return [False, True][branch.startswith(PQ_BRANCH_PREFIX)]
+    pq_format_str = DEFAULT_PQ_BRANCH_NAME
+    if hasattr(options, 'pq_branch'):
+        pq_format_str = options.pq_branch
 
+    pq_re = re.compile(r'^%s$' % (pq_format_str % dict(branch="(?P<base>\S+)")))
+    if pq_re.match(branch):
+        return True
+    return False
 
-def pq_branch_name(branch):
+
+def pq_branch_name(branch, options):
     """
     get the patch queue branch corresponding to branch
 
-    >>> pq_branch_name("patch-queue/master")
-    >>> pq_branch_name("foo")
+    >>> from optparse import OptionParser
+    >>> (opts, args) = OptionParser().parse_args([])
+    >>> pq_branch_name("patch-queue/master", opts)
+    >>> pq_branch_name("foo", opts)
     'patch-queue/foo'
+    >>> opts.pq_branch = "%(branch)s/development"
+    >>> pq_branch_name("foo", opts)
+    'foo/development'
+    >>> opts.pq_branch = "development"
+    >>> pq_branch_name("foo", opts)
+    'development'
     """
-    if not is_pq_branch(branch):
-        return PQ_BRANCH_PREFIX + branch
+    pq_format_str = DEFAULT_PQ_BRANCH_NAME
+    if hasattr(options, 'pq_branch'):
+        pq_format_str = options.pq_branch
 
+    if not is_pq_branch(branch, options):
+        return pq_format_str % dict(branch=branch)
 
-def pq_branch_base(pq_branch):
-    """
-    get the branch corresponding to the given patch queue branch
 
-    >>> pq_branch_base("patch-queue/master")
+def pq_branch_base(pq_branch, options):
+    """
+    Get the branch corresponding to the given patch queue branch.
+    Returns the packaging/debian branch if pq format string doesn't contain
+    '%(branch)s' key.
+
+    >>> from optparse import OptionParser
+    >>> (opts, args) = OptionParser().parse_args([])
+    >>> opts.packaging_branch = "packaging"
+    >>> pq_branch_base("patch-queue/master", opts)
     'master'
-    >>> pq_branch_base("foo")
+    >>> pq_branch_base("foo", opts)
+    >>> opts.pq_branch = "my/%(branch)s/development"
+    >>> pq_branch_base("foo/development", opts)
+    >>> pq_branch_base("my/foo/development/bar", opts)
+    >>> pq_branch_base("my/foo/development", opts)
+    'foo'
+    >>> opts.pq_branch = "development"
+    >>> pq_branch_base("foo/development", opts)
+    >>> pq_branch_base("development", opts)
+    'packaging'
     """
-    if is_pq_branch(pq_branch):
-        return pq_branch[len(PQ_BRANCH_PREFIX):]
+    pq_format_str = DEFAULT_PQ_BRANCH_NAME
+    if hasattr(options, 'pq_branch'):
+        pq_format_str = options.pq_branch
+
+    pq_re = re.compile(r'^%s$' % (pq_format_str % dict(branch="(?P<base>\S+)")))
+    m = pq_re.match(pq_branch)
+    if m:
+        if 'base' in m.groupdict():
+            return m.group('base')
+        return options.packaging_branch
 
 
 def parse_gbp_commands(info, cmd_tag, noarg_cmds, arg_cmds, filter_cmds=None):
@@ -275,15 +331,15 @@ def get_maintainer_from_control(repo):
     return GitModifier()
 
 
-def switch_to_pq_branch(repo, branch):
+def switch_to_pq_branch(repo, branch, options):
     """
     Switch to patch-queue branch if not already there, create it if it
     doesn't exist yet
     """
-    if is_pq_branch(branch):
+    if is_pq_branch(branch, options):
         return
 
-    pq_branch = pq_branch_name(branch)
+    pq_branch = pq_branch_name(branch, options)
     if not repo.has_branch(pq_branch):
         try:
             repo.create_branch(pq_branch)
@@ -295,8 +351,9 @@ def switch_to_pq_branch(repo, branch):
     repo.set_branch(pq_branch)
 
 
-def apply_single_patch(repo, branch, patch, fallback_author, topic=None):
-    switch_to_pq_branch(repo, branch)
+def apply_single_patch(repo, branch, patch, fallback_author, options):
+    switch_to_pq_branch(repo, branch, options)
+    topic = None if not hasattr(options, 'topic') else options.topic
     apply_and_commit_patch(repo, patch, fallback_author, topic)
     gbp.log.info("Applied %s" % os.path.basename(patch.path))
 
@@ -326,12 +383,12 @@ def apply_and_commit_patch(repo, patch, fallback_author, topic=None):
     repo.update_ref('HEAD', commit, msg="gbp-pq import %s" % patch.path)
 
 
-def drop_pq(repo, branch):
-    if is_pq_branch(branch):
+def drop_pq(repo, branch, options):
+    if is_pq_branch(branch, options):
         gbp.log.err("On a patch-queue branch, can't drop it.")
         raise GbpError
     else:
-        pq_branch = pq_branch_name(branch)
+        pq_branch = pq_branch_name(branch, options)
 
     if repo.has_branch(pq_branch):
         repo.delete_branch(pq_branch)
@@ -340,11 +397,12 @@ def drop_pq(repo, branch):
         gbp.log.info("No patch queue branch found - doing nothing.")
 
 
-def switch_pq(repo, current):
+def switch_pq(repo, current, options):
     """Switch to patch-queue branch if on base branch and vice versa"""
-    if is_pq_branch(current):
-        base = pq_branch_base(current)
+    if is_pq_branch(current, options):
+        base = pq_branch_base(current, options)
         gbp.log.info("Switching to %s" % base)
         repo.checkout(base)
     else:
-        switch_to_pq_branch(repo, current)
+        switch_to_pq_branch(repo, current, options)
+
index 02ec514883865888e75b361b6aa43eae35448c16..a53a6eb4f26b9aa9ea10955a767f57593cf1988d 100755 (executable)
@@ -170,13 +170,13 @@ def commit_patches(repo, branch, patches, options):
 
 def export_patches(repo, branch, options):
     """Export patches from the pq branch into a patch series"""
-    if is_pq_branch(branch):
-        base = pq_branch_base(branch)
+    if is_pq_branch(branch, options):
+        base = pq_branch_base(branch, options)
         gbp.log.info("On '%s', switching to '%s'" % (branch, base))
         branch = base
         repo.set_branch(branch)
 
-    pq_branch = pq_branch_name(branch)
+    pq_branch = pq_branch_name(branch, options)
     try:
         shutil.rmtree(PATCH_DIR)
     except OSError as (e, msg):
@@ -205,7 +205,7 @@ def export_patches(repo, branch, options):
         gbp.log.info("No patches on '%s' - nothing to do." % pq_branch)
 
     if options.drop:
-        drop_pq(repo, branch)
+        drop_pq(repo, branch, options)
 
 
 def safe_patches(series):
@@ -231,7 +231,7 @@ def safe_patches(series):
     return (tmpdir, series)
 
 
-def import_quilt_patches(repo, branch, series, tries, force):
+def import_quilt_patches(repo, branch, series, tries, options):
     """
     apply a series of quilt patches in the series file 'series' to branch
     the patch-queue branch for 'branch'
@@ -241,24 +241,24 @@ def import_quilt_patches(repo, branch, series, tries, force):
     @param series; series file to read patches from
     @param tries: try that many times to apply the patches going back one
                   commit in the branches history after each failure.
-    @param force: import the patch series even if the branch already exists
+    @param options: gbp-pq command options
     """
     tmpdir = None
 
-    if is_pq_branch(branch):
-        if force:
-            branch = pq_branch_base(branch)
-            pq_branch = pq_branch_name(branch)
+    if is_pq_branch(branch, options):
+        if options.force:
+            branch = pq_branch_base(branch, options)
+            pq_branch = pq_branch_name(branch, options)
             repo.checkout(branch)
         else:
             gbp.log.err("Already on a patch-queue branch '%s' - doing nothing." % branch)
             raise GbpError
     else:
-        pq_branch = pq_branch_name(branch)
+        pq_branch = pq_branch_name(branch, options)
 
     if repo.has_branch(pq_branch):
-        if force:
-            drop_pq(repo, branch)
+        if options.force:
+            drop_pq(repo, branch, options)
         else:
             raise GbpError("Patch queue branch '%s'. already exists. Try 'rebase' instead."
                            % pq_branch)
@@ -305,11 +305,11 @@ def import_quilt_patches(repo, branch, series, tries, force):
         shutil.rmtree(tmpdir)
 
 
-def rebase_pq(repo, branch):
-    if is_pq_branch(branch):
-        base = pq_branch_base(branch)
+def rebase_pq(repo, branch, options):
+    if is_pq_branch(branch, options):
+        base = pq_branch_base(branch, options)
     else:
-        switch_to_pq_branch(repo, branch)
+        switch_to_pq_branch(repo, branch, options)
         base = branch
     GitCommand("rebase")([base])
 
@@ -402,20 +402,20 @@ def main(argv):
         elif action == "import":
             series = SERIES_FILE
             tries = options.time_machine if (options.time_machine > 0) else 1
-            import_quilt_patches(repo, current, series, tries, options.force)
+            import_quilt_patches(repo, current, series, tries, options)
             current = repo.get_branch()
             gbp.log.info("Patches listed in '%s' imported on '%s'" %
                           (series, current))
         elif action == "drop":
-            drop_pq(repo, current)
+            drop_pq(repo, current, options)
         elif action == "rebase":
-            rebase_pq(repo, current)
+            rebase_pq(repo, current, options)
         elif action == "apply":
             patch = Patch(patchfile)
             maintainer = get_maintainer_from_control(repo)
-            apply_single_patch(repo, current, patch, maintainer, options.topic)
+            apply_single_patch(repo, current, patch, maintainer, options)
         elif action == "switch":
-            switch_pq(repo, current)
+            switch_pq(repo, current, options)
     except CommandExecFailed:
         retval = 1
     except (GbpError, GitRepositoryError) as err:
index fa1f445a11ee734eb945f3d511e1dbe52cdce0e7..56389348c303aa74dd32dea35484395f02bc6283 100755 (executable)
@@ -200,13 +200,13 @@ def find_upstream_commit(repo, spec, upstream_tag):
 def export_patches(repo, options):
     """Export patches from the pq branch into a packaging branch"""
     current = repo.get_branch()
-    if is_pq_branch(current):
-        base = pq_branch_base(current)
+    if is_pq_branch(current, options):
+        base = pq_branch_base(current, options)
         gbp.log.info("On branch '%s', switching to '%s'" % (current, base))
         repo.set_branch(base)
         pq_branch = current
     else:
-        pq_branch = pq_branch_name(current)
+        pq_branch = pq_branch_name(current, options)
     spec = parse_spec(options, repo)
     upstream_commit = find_upstream_commit(repo, spec, options.upstream_tag)
     export_treeish = pq_branch
@@ -298,8 +298,8 @@ def import_spec_patches(repo, options):
     """
     current = repo.get_branch()
     # Get spec and related information
-    if is_pq_branch(current):
-        base = pq_branch_base(current)
+    if is_pq_branch(current, options):
+        base = pq_branch_base(current, options)
         if options.force:
             spec = parse_spec(options, repo, base)
             spec_treeish = base
@@ -312,7 +312,7 @@ def import_spec_patches(repo, options):
         base = current
     upstream_commit = find_upstream_commit(repo, spec, options.upstream_tag)
     packager = get_packager(spec)
-    pq_branch = pq_branch_name(base)
+    pq_branch = pq_branch_name(base, options)
 
     # Create pq-branch
     if repo.has_branch(pq_branch) and not options.force:
@@ -361,15 +361,15 @@ def import_spec_patches(repo, options):
 def rebase_pq(repo, options):
     """Rebase pq branch on the correct upstream version (from spec file)."""
     current = repo.get_branch()
-    if is_pq_branch(current):
-        base = pq_branch_base(current)
+    if is_pq_branch(current, options):
+        base = pq_branch_base(current, options)
         spec = parse_spec(options, repo, base)
     else:
         base = current
         spec = parse_spec(options, repo)
     upstream_commit = find_upstream_commit(repo, spec, options.upstream_tag)
 
-    switch_to_pq_branch(repo, base)
+    switch_to_pq_branch(repo, base, options)
     GitCommand("rebase")([upstream_commit])
 
 
@@ -476,14 +476,14 @@ def main(argv):
         elif action == "import":
             import_spec_patches(repo, options)
         elif action == "drop":
-            drop_pq(repo, current)
+            drop_pq(repo, current, options)
         elif action == "rebase":
             rebase_pq(repo, options)
         elif action == "apply":
             patch = Patch(patchfile)
-            apply_single_patch(repo, current, patch, fallback_author=None)
+            apply_single_patch(repo, current, patch, None, options)
         elif action == "switch":
-            switch_pq(repo, current)
+            switch_pq(repo, current, options)
     except CommandExecFailed:
         retval = 1
     except GitRepositoryError as err:
index 57ce83b7184f5ffa607f5c00509b1fb277d6a26c..dedcb9e36044a666d67589a1a60a191a28c56508 100644 (file)
@@ -91,7 +91,8 @@ class TestApplySinglePatch(testutils.DebianGitTestRepo):
 
         patch = gbp.patch_series.Patch(_patch_path('foo.patch'))
 
-        pq.apply_single_patch(self.repo, 'master', patch, None)
+        dummy_opts = object()
+        pq.apply_single_patch(self.repo, 'master', patch, None, dummy_opts)
         self.assertIn('foo', self.repo.list_files())
 
 class TestWritePatch(testutils.DebianGitTestRepo):
@@ -146,7 +147,7 @@ class TestExport(testutils.DebianGitTestRepo):
         repo = self.repo
         start = repo.get_branch()
         pq_branch = os.path.join('patch-queue', start)
-        pq.switch_pq(repo, start)
+        switch_pq(repo, start, TestExport.Options)
         self.assertEqual(repo.get_branch(), pq_branch)
         export_patches(repo, pq_branch, TestExport.Options)
         self.assertEqual(repo.get_branch(), start)