self.epoch = str(source_header[rpm.RPMTAG_EPOCH]) \
if source_header[rpm.RPMTAG_EPOCH] != None else None
self.packager = source_header[rpm.RPMTAG_PACKAGER]
- self.patches = {}
self.sources = {}
self._tags = {}
self._special_directives = defaultdict(list)
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,
# '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:
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()
# '%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()
# 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:
# 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()
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
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
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):
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):