diff options
author | Markus Lehtonen <markus.lehtonen@linux.intel.com> | 2012-06-08 10:20:12 +0300 |
---|---|---|
committer | Markus Lehtonen <markus.lehtonen@linux.intel.com> | 2013-03-08 13:13:37 +0200 |
commit | 907bc6177d88901ce75e955edabf85d496d2b480 (patch) | |
tree | 957a43ef466e4f570a214540467379b7ad77bd64 | |
parent | b5aa0bef0e5eea517e04bf704043b39f625cda03 (diff) | |
download | git-buildpackage-907bc6177d88901ce75e955edabf85d496d2b480.tar.gz git-buildpackage-907bc6177d88901ce75e955edabf85d496d2b480.tar.bz2 git-buildpackage-907bc6177d88901ce75e955edabf85d496d2b480.zip |
rpm: enhance logic in guessing the prefix of source archives
Now a prefix is guessed for all source archives (not for the one and
only "orig archive"). By default it is
'<archive_name>-<archive_version>/' if name and version can be
determined from the filename. If not, the archive basename (i.e.
filename less archive and compression extensions) is used.
In addition, more logic is applied to the "orig archive": gbp examines
the setup macro (if found) for the source and takes the prefix from
there. If some macros (in the '-n' option of the setup macro) cannot be
expanded archive basename us used as the prefix.
Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com>
-rw-r--r-- | gbp/rpm/__init__.py | 132 | ||||
-rwxr-xr-x | gbp/scripts/buildpackage_rpm.py | 34 | ||||
-rwxr-xr-x | gbp/scripts/import_srpm.py | 8 |
3 files changed, 137 insertions, 37 deletions
diff --git a/gbp/rpm/__init__.py b/gbp/rpm/__init__.py index 360de4fd..f6c97997 100644 --- a/gbp/rpm/__init__.py +++ b/gbp/rpm/__init__.py @@ -48,6 +48,9 @@ class NoSpecError(Exception): """no changelog found""" pass +class MacroExpandError(Exception): + pass + class RpmUpstreamSource(UpstreamSource): """Upstream source class for RPM packages""" @@ -152,6 +155,7 @@ class SpecFile(object): source_re = re.compile(r'^Source(?P<srcnum>[0-9]+)?\s*:\s*(?P<name>[^\s].*[^\s])\s*$', flags=re.I) patchtag_re = re.compile(r'^Patch(?P<patchnum>[0-9]+)?\s*:\s*(?P<name>\S.*)$', flags=re.I) patchmacro_re = re.compile(r'^%patch(?P<patchnum>[0-9]+)?(\s+(?P<args>.*))?$') + setupmacro_re = re.compile(r'^%setup(\s+(?P<args>.*))?$') marker_re = re.compile(r'^#\s+(?P<marker>>>|<<)\s+(?P<what>gbp-[^\s]+)\s*(?P<comment>.*)$') gbptag_re = re.compile(r'^\s*#\s*gbp(?P<tagname>[a-z]+)\s*:\s*(?P<data>\S.*)\s*$', flags=re.I) @@ -199,7 +203,18 @@ class SpecFile(object): num = 0 if typ == 1: if num in self.sources: - self.sources[num]['filename'] = name + self.sources[num]['full_path'] = name + self.sources[num]['filename'] = os.path.basename(name) + self.sources[num]['filename_base'],\ + self.sources[num]['archive_fmt'],\ + self.sources[num]['compression'] = parse_archive_filename(os.path.basename(name)) + # Make a guess about the prefix in the archive + if self.sources[num]['archive_fmt']: + (_name, _version) = RpmUpstreamSource(name).guess_version() or (None, None) + if _name and _version: + self.sources[num]['prefix'] = "%s-%s/" % (_name, _version) + else: + self.sources[num]['prefix'] = self.sources[num]['filename_base'] + "/" else: gbp.log.err("BUG: we didn't correctly parse all 'Source' tags!") if typ == 2: @@ -208,7 +223,7 @@ class SpecFile(object): else: gbp.log.err("BUG: we didn't correctly parse all 'Patch' tags!") - (self.orig_file, self.orig_base, self.orig_archive_fmt, self.orig_comp) = self.guess_orig_file() + self.orig_src_num = self.guess_orig_file() def _get_version(self): @@ -222,6 +237,38 @@ class SpecFile(object): return version version = property(_get_version) + def _get_orig_src(self): + """ + Get the orig src + """ + if self.orig_src_num != None: + return self.sources[self.orig_src_num] + return None + orig_src = property(_get_orig_src) + + def _macro_replace(self, matchobj): + macro_dict = {'name': self.name, + 'version': self.upstreamversion, + 'release': self.release} + + if matchobj.group(2) in macro_dict: + return macro_dict[matchobj.group(2)] + raise MacroExpandError("Unknown macro '%s'" % matchobj.group(0)) + + + def macro_expand(self, text): + """ + Expand the rpm macros (that gbp knows of) in the given text. + + @param text: text to check for macros + @type text: C{str} + @return: text with macros expanded + @rtype: C{str} + """ + # regexp to match '%{macro}' and '%macro' + macro_re = re.compile(r'%({)?(?P<macro_name>[a-z_][a-z0-9_]*)(?(1)})', flags=re.I) + return macro_re.sub(self._macro_replace, text) + def write_spec_file(self): """ @@ -268,6 +315,16 @@ class SpecFile(object): patchparser.add_option("-b", dest="backup") patchparser.add_option("-E", dest="removeempty") + # Parser for patch macros + setupparser = OptionParser() + setupparser.add_option("-n", dest="name") + setupparser.add_option("-c", dest="create_dir", action="store_true") + setupparser.add_option("-D", dest="no_delete_dir", action="store_true") + setupparser.add_option("-T", dest="no_unpack_default", action="store_true") + setupparser.add_option("-b", dest="unpack_before") + setupparser.add_option("-a", dest="unpack_after") + setupparser.add_option("-q", dest="quiet", action="store_true") + numlines = len(self.content) for i in range(numlines): line = self.content[i] @@ -291,7 +348,11 @@ class SpecFile(object): if srcnum in self.sources: self.sources[srcnum]['tag_linenum'] = i else: - self.sources[srcnum] = {'name': m.group('name'), 'filename': m.group('name'), 'tag_linenum': i} + self.sources[srcnum] = {'full_path': m.group('name'), + 'filename': os.path.basename(m.group('name')), + 'tag_linenum': i, + 'prefix': None, + 'setup_options': None, } continue # Find 'Patch' tags @@ -309,7 +370,13 @@ class SpecFile(object): gbp.log.err("Patch%s found multiple times, aborting as gbp spec/patch autoupdate likely fails" % patchnum) raise GbpError, "RPM error while parsing spec, duplicate patches found" else: - new_patch = {'name': m.group('name').strip(), 'filename': m.group('name'), 'apply': False, 'strip': '0', 'macro_linenum': None, 'autoupdate': not patchnum in ignorepatch, 'tag_linenum': i} + new_patch = {'name': m.group('name').strip(), + 'filename': m.group('name'), + 'apply': False, + 'strip': '0', + 'macro_linenum': None, + 'autoupdate': not patchnum in ignorepatch, + 'tag_linenum': i} self.patches[patchnum] = new_patch continue @@ -330,11 +397,27 @@ class SpecFile(object): self.patches[patchnum]['apply'] = True continue + # Find setup macros + m = self.setupmacro_re.match(line) + if m: + (options, args) = setupparser.parse_args(m.group('args').split()) + srcnum = None + if options.no_unpack_default: + if options.unpack_before: + srcnum = int(options.unpack_before) + elif options.unpack_after: + srcnum = int(options.unpack_after) + else: + srcnum = 0 + if srcnum != None: + self.sources[srcnum]['setup_options'] = options + # Save the occurrence of last setup macro + ret['setupmacro'] = i + continue + # Only search for the last occurrence of the following if re.match("^\s*Name:.*$", line, flags=re.I): ret['setupmacro'] = i - if re.match("^%setup(\s.*)?$", line): - ret['setupmacro'] = i if re.match("^%prep(\s.*)?$", line): ret['prepmacro'] = i continue @@ -459,23 +542,40 @@ class SpecFile(object): returns a tuple with full file path, filename base, archive format and compression method. """ - full_path, base, archive_fmt, comp = None, None, None, None - + orig_num = None for (num, src) in sorted(self.sources.iteritems()): - _full_path = src['filename'] - filename = os.path.basename(_full_path) - _base, _archive_fmt, _comp = parse_archive_filename(filename) + filename = os.path.basename(src['filename']) if filename.startswith(self.name): # Take the first archive that starts with pkg name - if _archive_fmt: - full_path, base, archive_fmt, comp = _full_path, _base, _archive_fmt, _comp + if src['archive_fmt']: + orig_num = num break # otherwise we take the first archive - elif not full_path and _archive_fmt: - full_path, base, archive_fmt, comp = _full_path, _base, _archive_fmt, _comp + elif orig_num == None and src['archive_fmt']: + orig_num = num # else don't accept - return (full_path, base, archive_fmt, comp) + # Refine our guess about the prefix + if orig_num != None: + orig = self.sources[orig_num] + setup_opts = orig['setup_options'] + if setup_opts: + if setup_opts.create_dir: + orig['prefix'] = '' + elif setup_opts.name: + try: + orig['prefix'] = self.macro_expand(setup_opts.name) + \ + '/' + except MacroExpandError as err: + gbp.log.warn("Couldn't determine prefix from %%setup "\ + "macro (%s). Using filename base as a " \ + "fallback" % err) + orig['prefix'] = orig['filename_base'] + '/' + else: + # RPM default + orig['prefix'] = "%s-%s/" % (self.name, + self.upstreamversion) + return orig_num def parse_srpm(srpmfile): diff --git a/gbp/scripts/buildpackage_rpm.py b/gbp/scripts/buildpackage_rpm.py index 451aff78..f0853e02 100755 --- a/gbp/scripts/buildpackage_rpm.py +++ b/gbp/scripts/buildpackage_rpm.py @@ -47,23 +47,23 @@ from gbp.scripts.pq_rpm import write_patch def git_archive(repo, spec, output_dir, treeish, comp_level, with_submodules): "create a compressed orig tarball in output_dir using git_archive" comp_opts = '' - if spec.orig_comp: - comp_opts = compressor_opts[spec.orig_comp][0] + if spec.orig_src['compression']: + comp_opts = compressor_opts[spec.orig_src['compression']][0] - output = os.path.join(output_dir, os.path.basename(spec.orig_file)) - prefix = spec.orig_base + output = os.path.join(output_dir, spec.orig_src['filename']) + prefix = spec.orig_src['prefix'] try: if repo.has_submodules() and with_submodules: repo.update_submodules() git_archive_submodules(repo, treeish, output, prefix, - spec.orig_comp, comp_level, comp_opts, - spec.orig_archive_fmt) + spec.orig_src['compression'], comp_level, comp_opts, + spec.orig_src['archive_fmt']) else: git_archive_single(repo, treeish, output, prefix, - spec.orig_comp, comp_level, comp_opts, - spec.orig_archive_fmt) + spec.orig_src['compression'], comp_level, comp_opts, + spec.orig_src['archive_fmt']) except (GitRepositoryError, CommandExecFailed): gbp.log.err("Error generating submodules' archives") return False @@ -84,7 +84,7 @@ def prepare_upstream_tarball(repo, spec, options, output_dir): tarball_dir, symlinking or building it. """ # look in tarball_dir first, if found force a symlink to it - orig_file = os.path.basename(spec.orig_file) + orig_file = spec.orig_src['filename'] if options.tarball_dir: gbp.log.debug("Looking for orig tarball '%s' at '%s'" % (orig_file, options.tarball_dir)) if not RpmPkgPolicy.symlink_orig(orig_file, options.tarball_dir, output_dir, force=True): @@ -176,11 +176,11 @@ def git_archive_build_orig(repo, spec, output_dir, options): @rtype: C{str} """ upstream_tree = get_upstream_tree(repo, spec, options) - gbp.log.info("%s does not exist, creating from '%s'" % (spec.orig_file, + gbp.log.info("%s does not exist, creating from '%s'" % (spec.orig_src['filename'], upstream_tree)) - if spec.orig_comp: + if spec.orig_src['compression']: gbp.log.debug("Building upstream source archive with compression '%s -%s'" % - (spec.orig_comp, options.comp_level)) + (spec.orig_src['compression'], options.comp_level)) if not git_archive(repo, spec, output_dir, upstream_tree, options.comp_level, options.with_submodules): @@ -514,16 +514,16 @@ def main(argv): # Get/build the orig tarball if is_native(repo, options): - if spec.orig_file: + if spec.orig_src: # Just build source archive from the exported tree - gbp.log.info("Creating (native) source archive %s from '%s'" % (spec.orig_file, tree)) - if spec.orig_comp: - gbp.log.debug("Building source archive with compression '%s -%s'" % (spec.orig_comp, options.comp_level)) + gbp.log.info("Creating (native) source archive %s from '%s'" % (spec.orig_src['filename'], tree)) + if spec.orig_src['compression']: + gbp.log.debug("Building source archive with compression '%s -%s'" % (spec.orig_src['compression'], options.comp_level)) if not git_archive(repo, spec, source_dir, tree, options.comp_level, options.with_submodules): raise GbpError, "Cannot create source tarball at '%s'" % export_dir # Non-native packages: create orig tarball from upstream - elif spec.orig_file: + elif spec.orig_src: prepare_upstream_tarball(repo, spec, options, source_dir) # Run postexport hook diff --git a/gbp/scripts/import_srpm.py b/gbp/scripts/import_srpm.py index 42870fad..dd130226 100755 --- a/gbp/scripts/import_srpm.py +++ b/gbp/scripts/import_srpm.py @@ -242,8 +242,8 @@ def main(argv): orig_tarball = None if unpacked: files = [os.path.basename(patch['filename']) for patch in spec.patches.itervalues()] - for src in spec.sources.itervalues(): - if src['filename'] != spec.orig_file: + for num, src in spec.sources.iteritems(): + if num != spec.orig_src_num: files.append(src['filename']) files.append(spec.specfile) for fname in files: @@ -253,8 +253,8 @@ def main(argv): else: gbp.log.err("File '%s' listed in spec not found" % fname) raise GbpError - if spec.orig_base: - orig_tarball=os.path.join(dirs['src'], os.path.basename(spec.orig_file)) + if spec.orig_src: + orig_tarball=os.path.join(dirs['src'], spec.orig_src['filename']) else: gbp.log.info("Extracting src rpm...") src.unpack(dirs['pkgextract-packaging'], dirs['srctarball']) |