diff options
-rw-r--r-- | gbp/rpm/__init__.py | 74 | ||||
-rwxr-xr-x | gbp/scripts/import_srpm.py | 4 | ||||
-rwxr-xr-x | gbp/scripts/pq_rpm.py | 20 | ||||
-rw-r--r-- | tests/test_rpm.py | 23 | ||||
-rw-r--r-- | tests/test_rpm_data/specs/gbp-test-tags.spec | 7 |
5 files changed, 74 insertions, 54 deletions
diff --git a/gbp/rpm/__init__.py b/gbp/rpm/__init__.py index d5d306fa..0aac3c53 100644 --- a/gbp/rpm/__init__.py +++ b/gbp/rpm/__init__.py @@ -149,7 +149,6 @@ class SpecFile(object): self.packager = source_header[rpm.RPMTAG_PACKAGER] self.specfile = os.path.basename(specfile) self.specdir = os.path.dirname(os.path.abspath(specfile)) - self.patches = {} self.sources = {} self._tags = {} self._special_directives = defaultdict(list) @@ -211,6 +210,12 @@ class SpecFile(object): return sorted([int(num) for num in data]) return [] + def _patches(self): + """Get all patch tags as a dict""" + if 'patch' not in self._tags: + return {} + return {patch['num']: patch for patch in self._tags['patch']['lines']} + def _macro_replace(self, matchobj): macro_dict = {'name': self.name, 'version': self.upstreamversion, @@ -268,14 +273,6 @@ class SpecFile(object): # 'Patch:' tags elif tagname == 'patch': tagnum = -1 if tagnum is None else tagnum - new_patch = {'name': matchobj.group('name').strip(), - 'filename': matchobj.group('name'), - 'apply': False, - 'strip': '0', - 'macro_line': None, - 'autoupdate': True, - 'tag_line': lineobj} - self.patches[tagnum] = new_patch # Record all tag locations try: @@ -306,16 +303,21 @@ class SpecFile(object): return tagname - def _parse_directive(self, lineobj): - """Parse special directive/scriptlet/macro lines""" + @staticmethod + def _patch_macro_opts(args): + """Parse arguments of the '%patch' macro""" - # Parser for '%patch' macros patchparser = OptionParser() patchparser.add_option("-p", dest="strip") patchparser.add_option("-s", dest="silence") patchparser.add_option("-P", dest="patchnum") patchparser.add_option("-b", dest="backup") patchparser.add_option("-E", dest="removeempty") + arglist = args.split() + return patchparser.parse_args(arglist)[0] + + def _parse_directive(self, lineobj): + """Parse special directive/scriptlet/macro lines""" # Parser for '%setup' macros setupparser = OptionParser() @@ -337,19 +339,13 @@ class SpecFile(object): # '%patch' macros directiveid = None if directivename == 'patch': - arglist = matchobj.group('args').split() - (opts, args) = patchparser.parse_args(arglist) + opts = self._patch_macro_opts(matchobj.group('args')) if matchobj.group('num'): directiveid = int(matchobj.group('num')) elif opts.patchnum: directiveid = int(opts.patchnum) else: directiveid = -1 - - if opts.strip: - self.patches[directiveid]['strip'] = opts.strip - self.patches[directiveid]['macro_line'] = lineobj - self.patches[directiveid]['apply'] = True # '%setup' macros elif directivename == 'setup': arglist = matchobj.group('args').split() @@ -416,6 +412,7 @@ class SpecFile(object): # Update sources info (basically possible macros expanded by rpm) # And, double-check that we parsed spec content correctly + patches = self._patches() for (name, num, typ) in self._specinfo.sources: # workaround rpm parsing bug if typ == 1 or typ == 9: @@ -439,16 +436,11 @@ class SpecFile(object): # having number (2^31-1), we use number -1 if num >= pow(2,30): num = -1 - if num in self.patches: - self.patches[num]['filename'] = name + if num in patches: + patches[num]['linevalue'] = name else: gbp.log.err("BUG: we didn't correctly parse all 'Patch' tags!") - # Mark ignored patches - for patchnum in self.patches: - if patchnum in self.ignorepatches: - self.patches[patchnum]['autoupdate'] = False - def _delete_tag(self, tag, num): """Delete a tag""" key = tag.lower() @@ -577,7 +569,7 @@ class SpecFile(object): macro_prev = None ignored = self.ignorepatches # Remove 'Patch:̈́' tags - for tag in self._tags['patch']['lines']: + for tag in self._patches().values(): if not tag['num'] in ignored: tag_prev = self._delete_tag('patch', tag['num']) # Remove a preceding comment if it seems to originate from GBP @@ -651,20 +643,26 @@ class SpecFile(object): macro_line = self._set_special_macro('patch', patchnum, '-p1', macro_line) - def patchseries(self): - """ - Return patches of the RPM as a gbp patchseries - """ + def patchseries(self, unapplied=False, ignored=False): + """Return non-ignored patches of the RPM as a gbp patchseries""" series = PatchSeries() - patchdir = self.specdir - for n, p in sorted(self.patches.iteritems()): - if p['autoupdate'] and p['apply']: - fname = os.path.basename(p['filename']) - series.append(Patch(os.path.join(patchdir, fname), - strip = int(p['strip']))) + if 'patch' in self._tags: + tags = self._patches() + macros = {macro['id']: macro['args'] + for macro in self._special_directives['patch']} + ignored = [] if ignored else self.ignorepatches + + for num, tag in sorted(tags.iteritems()): + strip = 0 + if num in macros: + opts = self._patch_macro_opts(macros[num]) + strip = int(opts.strip) if opts.strip else 0 + if (unapplied or (num in macros)) and num not in ignored: + filename = os.path.basename(tag['linevalue']) + series.append(Patch(os.path.join(self.specdir, filename), + strip=strip)) return series - def guess_orig_file(self): """ Try to guess the name of the primary upstream/source archive diff --git a/gbp/scripts/import_srpm.py b/gbp/scripts/import_srpm.py index 0db870e0..28802eb5 100755 --- a/gbp/scripts/import_srpm.py +++ b/gbp/scripts/import_srpm.py @@ -318,8 +318,8 @@ def main(argv): raise # Need to copy files to the packaging directory given by caller - files = [os.path.basename(patch['filename']) \ - for patch in spec.patches.itervalues()] + files = [os.path.basename(patch.path) \ + for patch in spec.patchseries(unapplied=True, ignored=True)] for num, src in spec.sources.iteritems(): if num != spec.orig_src_num: files.append(src['filename']) diff --git a/gbp/scripts/pq_rpm.py b/gbp/scripts/pq_rpm.py index 64ba4236..9b1f1662 100755 --- a/gbp/scripts/pq_rpm.py +++ b/gbp/scripts/pq_rpm.py @@ -230,17 +230,15 @@ def rm_patch_files(spec): marked as not maintained by gbp. """ # Remove all old patches from the spec dir - for n, p in spec.patches.iteritems(): - if p['autoupdate']: - f = os.path.join(spec.specdir, p['filename']) - gbp.log.debug("Removing '%s'" % f) - try: - os.unlink(f) - except OSError, (e, msg): - if e != errno.ENOENT: - raise GbpError, "Failed to remove patch: %s" % msg - else: - gbp.log.debug("%s does not exist." % f) + for patch in spec.patchseries(unapplied=True): + gbp.log.debug("Removing '%s'" % patch.path) + try: + os.unlink(patch.path) + except OSError as err: + if err.errno != errno.ENOENT: + raise GbpError("Failed to remove patch: %s" % err) + else: + gbp.log.debug("Patch %s does not exist." % patch.path) def update_patch_series(repo, spec, start, end, options): diff --git a/tests/test_rpm.py b/tests/test_rpm.py index 01d8b277..830e4506 100644 --- a/tests/test_rpm.py +++ b/tests/test_rpm.py @@ -199,6 +199,7 @@ class TestSpecFile(object): spec.protected('_delete_tag')('source', 0) spec.protected('_delete_tag')('patch', 0) spec.protected('_delete_tag')('patch', -1) + assert spec.protected('_patches')() == {} prev = spec.protected('_delete_tag')('invalidtag', None) with assert_raises(GbpError): @@ -248,8 +249,28 @@ class TestSpecFile(object): assert val['value'] == rval, ("'%s:' is '%s', expecting '%s'" % (name, val['value'], rval)) assert spec.ignorepatches == [] + # Check patch numbers and patch filenames + patches = {patch['num']: patch['linevalue'] for patch in + spec.protected('_tags')['patch']['lines']} + assert patches == {0: 'my_patch0', -1: 'my_patch'} - assert spec.patches.keys() == [0, -1] + def test_patch_series(self): + """Test the getting the patches as a patchseries""" + spec_filepath = os.path.join(SPEC_DIR, 'gbp-test-native.spec') + spec = SpecFileTester(spec_filepath) + + assert len(spec.patchseries()) == 0 + 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']) + assert len(spec.patchseries()) == 1 + assert len(spec.patchseries(ignored=True)) == 2 + spec.protected('_delete_special_macro')('patch', 0) + assert len(spec.patchseries(ignored=True)) == 1 + series = spec.patchseries(unapplied=True, ignored=True) + assert len(series) == 2 + assert os.path.basename(series[-1].path) == '4.patch' class TestUtilityFunctions(object): diff --git a/tests/test_rpm_data/specs/gbp-test-tags.spec b/tests/test_rpm_data/specs/gbp-test-tags.spec index acbb9213..c96f035c 100644 --- a/tests/test_rpm_data/specs/gbp-test-tags.spec +++ b/tests/test_rpm_data/specs/gbp-test-tags.spec @@ -9,6 +9,9 @@ %define test_arch_os_tags %(test -n "$GBP_SKIP_ARCH_OS_TAGS" && echo 0 || echo 1) +%define source_fn_base source +%define patch_fn_base patch + # Gbp-Undefined-Tag: foobar # Test that we accept different cases @@ -27,8 +30,8 @@ Packager: my_packager Url: my_url Vcs: my_vcs Source: my_source -Patch: my_patch -Patch0: my_patch0 +Patch: my_%patch_fn_base +Patch0: my_%{patch_fn_base}0 Nosource: 0 Nopatch: 0 #Icon: my_icon |