rpm: support conditionals in patch-export
authorMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Mon, 25 Feb 2013 10:11:14 +0000 (12:11 +0200)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 7 Jan 2014 14:21:30 +0000 (16:21 +0200)
One can now define conditional patches that are enclosed in '%if' or
'%ifarch' when the spec file is updated. One can do this by defining
'Gbp-Rpm-If: <conditional>' and 'Gbp-Rpm-IfArch: <conditional>' in the
commit message.

Only one conditional per patch is supported, i.e. you cannot define
'IfArch' and 'If' for the same patch.

Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com>
gbp/rpm/__init__.py
gbp/scripts/import_srpm.py
gbp/scripts/pq_rpm.py
tests/test_rpm.py
tests/test_rpm_data/specs/gbp-test2-reference.spec
tests/test_rpm_data/specs/gbp-test2-reference2.spec

index 92f479e05c4e2aff70a7d9355fee58be76aa01c8..72a846db718632f5b17440851d1f092ff3e78f76 100644 (file)
@@ -541,7 +541,7 @@ class SpecFile(object):
             self._special_directives[key].append(linerec)
         return ret
 
-    def update_patches(self, patchfilenames):
+    def update_patches(self, patches, commands):
         """Update spec with new patch tags and patch macros"""
         # Remove non-ignored patches
         tag_prev = None
@@ -559,14 +559,21 @@ class SpecFile(object):
         # Remove '%patch:' macros
         for macro in self._special_directives['patch']:
             if not macro['id'] in ignored:
+                macro_prev = self._delete_special_macro('patch', macro['id'])
+                # Remove surrounding if-else
+                macro_next = macro_prev.next
+                if (str(macro_prev).startswith('%if') and
+                        str(macro_next).startswith('%endif')):
+                    self._content.delete(macro_next)
+                    macro_prev = self._content.delete(macro_prev)
+
                 # Remove a preceding comment line if it ends with '.patch' or
                 # '.diff' plus an optional compression suffix
-                macro_prev = self._delete_special_macro('patch', macro['id'])
                 if re.match("^\s*#.+(patch|diff)(\.(gz|bz2|xz|lzma))?\s*$",
                             str(macro_prev), flags=re.I):
                     macro_prev = self._content.delete(macro_prev)
 
-        if len(patchfilenames) == 0:
+        if len(patches) == 0:
             return
 
         # Determine where to add Patch tag lines
@@ -613,14 +620,23 @@ class SpecFile(object):
         # Add a comment indicating gbp generated patch tags
         comment_text = "# Patches auto-generated by git-buildpackage:\n"
         tag_line = self._content.insert_after(tag_line, comment_text)
-        for ind, name in enumerate(patchfilenames):
+        for ind, patch in enumerate(patches):
+            cmds = commands[patch] if patch in commands else {}
             patchnum = startnum + ind
-            tag_line = self._set_tag("Patch", patchnum, name, tag_line)
+            tag_line = self._set_tag("Patch", patchnum, patch, tag_line)
             # Add '%patch' macro and a preceding comment line
-            comment_text = "# %s\n" % name
+            comment_text = "# %s\n" % patch
             macro_line = self._content.insert_after(macro_line, comment_text)
             macro_line = self._set_special_macro('patch', patchnum, '-p1',
                                                  macro_line)
+            for cmd, args in cmds.iteritems():
+                if cmd in ('if', 'ifarch'):
+                    self._content.insert_before(macro_line, '%%%s %s\n' %
+                                                (cmd, args))
+                    macro_line = self._content.insert_after(macro_line,
+                                                            '%endif\n')
+                    # We only support one command per patch, for now
+                    break
 
     def patchseries(self, unapplied=False, ignored=False):
         """Return non-ignored patches of the RPM as a gbp patchseries"""
index d6b1ba58fbeae15a379350b3688dfaa938b04e77..491a7aa61efae77071325b650bd1ef88816c6e2e 100755 (executable)
@@ -146,7 +146,7 @@ def import_spec_patches(repo, spec, dirs):
     gbp.log.info("Removing imported patch files from spec and packaging dir")
     rm_patch_files(spec)
     try:
-        spec.update_patches([])
+        spec.update_patches([], {})
         spec.write_spec_file()
     except GbpError:
         repo.force_head('HEAD', hard=True)
index 0d5f78d2e708df176d8a1163e3c558cbc729b671..ad55231d5b340ea717fb7c2bb83c563d60c2d1f8 100755 (executable)
@@ -109,7 +109,7 @@ def generate_patches(repo, start, squash, end, outdir, options):
     # Generate patches
     for commit in reversed(repo.get_commits(start, end_commit)):
         info = repo.get_commit_info(commit)
-        cmds = parse_gbp_commands(info, 'gbp-rpm', ('ignore'), None)
+        cmds = parse_gbp_commands(info, 'gbp-rpm', ('ignore'), ('if', 'ifarch'))
         if not 'ignore' in cmds:
             patch_fn = format_patch(outdir, repo, info, patches,
                                     options.patch_numbers,
@@ -163,9 +163,9 @@ def update_patch_series(repo, spec, start, end, options):
     # Unlink old patch files and generate new patches
     rm_patch_files(spec)
 
-    patches, _commands = generate_patches(repo, start, squash, end,
-                                          spec.specdir, options)
-    spec.update_patches(patches)
+    patches, commands = generate_patches(repo, start, squash, end,
+                                         spec.specdir, options)
+    spec.update_patches(patches, commands)
     spec.write_spec_file()
 
 
index f6469c4b6df5ac9d77e13cd6ba2fdd45f267e5d9..3a6e6ceb55c781d62e275b7b874eca53ba47e9ed 100644 (file)
@@ -156,7 +156,7 @@ class TestSpecFile(object):
 
         reference_spec = os.path.join(SPEC_DIR, 'gbp-test-reference.spec')
         spec = SpecFile(tmp_spec)
-        spec.update_patches(['new.patch'])
+        spec.update_patches(['new.patch'], {})
         spec.write_spec_file()
         assert filecmp.cmp(tmp_spec, reference_spec) is True
 
@@ -173,14 +173,16 @@ class TestSpecFile(object):
 
         reference_spec = os.path.join(SPEC_DIR, 'gbp-test2-reference2.spec')
         spec = SpecFile(tmp_spec)
-        spec.update_patches(['1.patch', '2.patch'])
+        spec.update_patches(['1.patch', '2.patch'],
+                            {'1.patch': {'if': 'true'},
+                             '2.patch': {'ifarch': '%ix86'}})
         spec.set_tag('VCS', None, 'myvcstag')
-        spec.update_patches(['new.patch'])
         spec.write_spec_file()
         assert filecmp.cmp(tmp_spec, reference_spec) is True
 
-        # Test removing the VCS tag
+        # Test updating patches again and removing the VCS tag
         reference_spec = os.path.join(SPEC_DIR, 'gbp-test2-reference.spec')
+        spec.update_patches(['new.patch'], {'new.patch': {'if': '1'}})
         spec.set_tag('VCS', None, '')
         spec.write_spec_file()
         assert filecmp.cmp(tmp_spec, reference_spec) is True
@@ -261,10 +263,10 @@ class TestSpecFile(object):
         spec = SpecFileTester(spec_filepath)
 
         assert len(spec.patchseries()) == 0
-        spec.update_patches(['1.patch', '2.patch', '3.patch'])
+        spec.update_patches(['1.patch', '2.patch', '3.patch'], {})
         assert len(spec.patchseries()) == 3
         spec.protected('_gbp_tags')['ignore-patches'].append({'args': "0"})
-        spec.update_patches(['4.patch'])
+        spec.update_patches(['4.patch'], {})
         assert len(spec.patchseries()) == 1
         assert len(spec.patchseries(ignored=True)) == 2
         spec.protected('_delete_special_macro')('patch', 0)
index e31930d7f074f9ab524ef409a44193365fd9d984..dfd4b91f02c423b2e0284c550c2329fb911faba5 100644 (file)
@@ -27,7 +27,9 @@ echo "Do things"
 
 # Gbp-Patch-Macros
 # new.patch
+%if 1
 %patch0 -p1
+%endif
 
 %build
 make
index 095600d33d24936fcef067897f02757ee376c1cb..0b93f0fa8c5009affda83e72231468d6506d54af 100644 (file)
@@ -11,7 +11,8 @@ Source20:   bar.tar.gz
 # Gbp-Ignore-Patches: -1
 Patch:      my.patch
 # Patches auto-generated by git-buildpackage:
-Patch0:     new.patch
+Patch0:     1.patch
+Patch1:     2.patch
 Packager:   Markus Lehtonen <markus.lehtonen@linux.intel.com>
 VCS:        myvcstag
 
@@ -27,8 +28,14 @@ Package for testing the RPM functionality of git-buildpackage.
 echo "Do things"
 
 # Gbp-Patch-Macros
-# new.patch
+# 1.patch
+%if true
 %patch0 -p1
+%endif
+# 2.patch
+%ifarch %ix86
+%patch1 -p1
+%endif
 
 %build
 make