diff --git a/anvil/packaging/helpers/envra_helper.py b/anvil/packaging/helpers/envra_helper.py new file mode 100644 index 00000000..d2a0581f --- /dev/null +++ b/anvil/packaging/helpers/envra_helper.py @@ -0,0 +1,48 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (C) 2012 Yahoo! Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import collections +import json + +from anvil import shell as sh + + +class Helper(object): + def __init__(self): + self._executable = sh.which("explode_envra", ["tools/"]) + + def explode(self, *filenames): + if not filenames: + return [] + cmdline = [self._executable] + for filename in filenames: + cmdline.append(sh.basename(filename)) + (stdout, _stderr) = sh.execute(cmdline) + results = [] + missing = collections.deque(filenames) + for line in stdout.splitlines(): + decoded = json.loads(line) + decoded['origin'] = missing.popleft() + results.append(decoded) + if missing: + raise AssertionError("%s filenames names were lost during" + " exploding: %s" % (len(missing), + list(missing))) + if len(results) > len(filenames): + diff = len(results) - len(filenames) + raise AssertionError("%s filenames appeared unexpectedly while" + " exploding" % (diff)) + return results diff --git a/anvil/packaging/yum.py b/anvil/packaging/yum.py index efd2388d..933fa40d 100644 --- a/anvil/packaging/yum.py +++ b/anvil/packaging/yum.py @@ -28,6 +28,7 @@ from anvil import colorizer from anvil import exceptions as excp from anvil import log as logging from anvil.packaging import base +from anvil.packaging.helpers import envra_helper from anvil.packaging.helpers import pip_helper from anvil.packaging.helpers import py2rpm_helper from anvil.packaging.helpers import yum_helper @@ -90,6 +91,7 @@ class YumDependencyHandler(base.DependencyHandler): self.specprint_executable = sh.which('specprint', ["tools/"]) # We inspect yum for packages, this helper allows us to do this. self.helper = yum_helper.Helper(self.log_dir, self.REPOS) + self.envra_helper = envra_helper.Helper() # See if we are requested to run at a higher make parallelism level try: self.jobs = max(self.JOBS, int(self.opts.get('jobs'))) @@ -299,13 +301,17 @@ class YumDependencyHandler(base.DependencyHandler): for repo_name in self.REPOS: repo_dir = sh.joinpths(self.anvil_repo_dir, self.SRC_REPOS[repo_name]) matched_paths = [] - for path in list_src_rpms(repo_dir): - package_name = sh.basename(path)[0:-len('.src.rpm')] + paths = list_src_rpms(repo_dir) + envra_details = self.envra_helper.explode(*paths) + for (path, envra_detail) in zip(paths, envra_details): + package_name = envra_detail.get('name') if package_name in build_requirements: matched_paths.append(path) build_requirements.discard(package_name) if matched_paths: with sh.remove_before(self.prebuild_dir) as prebuild_dir: + if not sh.isdir(prebuild_dir): + sh.mkdirslist(prebuild_dir, tracewriter=self.tracewriter) for path in matched_paths: sh.move(path, sh.joinpths(prebuild_dir, sh.basename(path))) build(prebuild_dir, repo_name, diff --git a/tools/README.rst b/tools/README.rst index f6693a3a..65d8af0e 100644 --- a/tools/README.rst +++ b/tools/README.rst @@ -109,6 +109,16 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. +explode_envra +------------- + +`specprint` uses the rpm API to provide a interface to printing the details +of an rpm filename in a easy to parse format (aka the envra format). It writes results of its +work to standard output in JSON (which is much easier to use from other programs):: + + $ ./tools/explode_envra 'gtk3-3.10.9-1.fc20.x86_64.rpm' 'libxslt-1.1.28-5.fc20.x86_64.src.rpm' + {"release": "1.fc20", "epoch": "", "version": "3.10.9", "arch": "x86_64", "name": "gtk3"} + {"release": "5.fc20.x86_64", "epoch": "", "version": "1.1.28", "arch": "src", "name": "libxslt"} specprint --------- diff --git a/tools/explode_envra b/tools/explode_envra new file mode 100755 index 00000000..d3df2571 --- /dev/null +++ b/tools/explode_envra @@ -0,0 +1,48 @@ +#!/usr/bin/python + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Copyright 2005 Duke University +# Parts Copyright 2007 Red Hat, Inc + +from rpmUtils import miscutils + +import os +import sys + +try: + import simplejson as json +except ImportError: + import json + + +def main(): + if len(sys.argv) <= 1: + print("%s filename ..." % os.path.basename(sys.argv[0])) + return 1 + for filename in sys.argv[1:]: + (name, ver, rel, epoch, arch) = miscutils.splitFilename(filename) + holder = { + 'name': name, + 'version': ver, + 'release': rel, + 'epoch': epoch, + 'arch': arch, + } + print(json.dumps(holder)) + return 0 + + +if __name__ == '__main__': + sys.exit(main())