summaryrefslogtreecommitdiffstats
path: root/debuginfofs-mirror
diff options
context:
space:
mode:
authorWill Woods <wwoods@redhat.com>2009-03-05 18:05:34 -0500
committerWill Woods <wwoods@redhat.com>2009-03-05 18:05:34 -0500
commit87db0232f329e722f9f8cd97ec50285b14069f04 (patch)
tree787a4d4f72f2d5e8a376a64fe8e894287de5d83c /debuginfofs-mirror
parentc9e5a68ad5f6febaed4093817fcce2b9a8d80a5b (diff)
downloaddebuginfofs-87db0232f329e722f9f8cd97ec50285b14069f04.tar.gz
debuginfofs-87db0232f329e722f9f8cd97ec50285b14069f04.tar.xz
debuginfofs-87db0232f329e722f9f8cd97ec50285b14069f04.zip
Rearrange files a bit, and add Requires(post/preun) for semanage
Diffstat (limited to 'debuginfofs-mirror')
-rwxr-xr-xdebuginfofs-mirror352
1 files changed, 0 insertions, 352 deletions
diff --git a/debuginfofs-mirror b/debuginfofs-mirror
deleted file mode 100755
index 695cef2..0000000
--- a/debuginfofs-mirror
+++ /dev/null
@@ -1,352 +0,0 @@
-#!/usr/bin/python
-# Given Fedora arch and version, fetch all debuginfo packages from the mirrors
-# Copyright 2009 Red Hat, Inc.
-#
-# 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 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.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Author: Will Woods <wwoods@redhat.com>
-
-import os
-import sys
-import stat
-import shutil
-import tempfile
-import optparse
-import ConfigParser
-import rpmUtils.arch
-# Why, yes, I do like to arrange imports by line length
-from subprocess import Popen, PIPE
-# Yum stuff
-sys.path.insert(0,'/usr/share/yum-cli')
-import yum.misc
-import yum.Errors
-from yum import _
-from utils import YumUtilBase
-from yum.parser import varReplace
-from yum.yumRepo import YumRepository
-
-configfile = '/etc/debuginfofs.conf'
-c = ConfigParser.RawConfigParser()
-try:
- c.read(configfile)
- conf = dict(c.items('general'))
-except (IOError,
- ConfigParser.MissingSectionHeaderError,
- ConfigParser.NoSectionError):
- print "Error: no 'cachedir' in %s" % configfile
- sys.exit(1)
-
-class DebuginfoFSDownloader(YumUtilBase):
- NAME = 'debuginfofs-mirror'
- VERSION = '0.1'
- USAGE = 'usage: %s REPOID [REPOID..]' % NAME
- def __init__(self):
- YumUtilBase.__init__(self,
- DebuginfoFSDownloader.NAME,
- DebuginfoFSDownloader.VERSION,
- DebuginfoFSDownloader.USAGE)
- self.optparser = self.getOptionParser()
-
- def modify_options(self):
- o = self.optparser
- # FIXME: remove some inappropriate options (--enablerepo etc)
- o.add_option("--cachedir", default=conf['cachedir'],
- help="directory to use for caching RPMs and metadata")
- o.add_option("--exportdir", default=conf['exportdir'],
- help="toplevel directory for debuginfofs exported data")
- # TODO
- #o.add_option("--distro", default="Fedora",
- # help="Use debuginfo repos for this distro.")
- # TODO: validate releasever/basearch
- o.add_option("--releasever", default="10",
- help="download debuginfo for this version of the distro.")
- o.add_option("--basearch", default="i386",
- help="download debuginfo for this arch")
- o.add_option("--savecache", default=False, action="store_true",
- help="don't delete downloaded RPMs after unpacking them")
- o.add_option("--force-download", default=False, action="store_true",
- help="download and unpack RPMs even if they already exist")
- o.add_option("--download-only", default=False, action="store_true",
- help="download RPMs but don't bother unpacking them")
- o.add_option("--keep-src", default=False, action="store_true",
- help="keep the contents of /usr/src/debug from each package")
-
- def setup(self):
- self.modify_options()
- try:
- # sets self.cmds
- opt = self.doUtilConfigSetup()
- except yum.Errors.RepoError, e:
- self.logger.error(str(e))
- sys.exit(50)
- # Kinda stupid, setting up and then immediately tearing down all repos..
- self.repos.disableRepo('*')
- self.repos.setCacheDir(opt.cachedir)
- # No yum cache needed, since we're saving the packages ourselves
- self.conf.cache = 0
- self.repos.setCache(0)
-
- return opt
-
- def listDownloads(self, packages):
- '''Returns a string representation of the packages to be downloaded'''
- n_wid = s_wid = 1
- coldata = []
- for p in packages:
- nevra = pkg_to_nevra(p)
- size = self.format_number(int(p.returnSimple('packagesize')))
- if len(nevra) > n_wid:
- n_wid = len(nevra)
- if len(size) > s_wid:
- s_wid = len(size)
- coldata.append((nevra, size))
- hr = '=' * self.term.columns
- head = self.fmtColumns(((_('Package'),-n_wid),(_('Size'),-s_wid)), u" ")
- out = u"""%s\n%s\n%s""" % (hr, head, hr)
- for nevra, size in coldata:
- cols = ((nevra,-n_wid),(size, s_wid))
- line = self.fmtColumns(cols, u" ", u"\n")
- out += line
- return out
-
-def pkg_to_nevra(p):
- '''return NEVRA string for package object p'''
- (n,a,e,v,r) = p.pkgtup
- return "%s-%s:%s-%s.%s" % (n,e,v,r,a)
-
-def fix_perms(targetdir):
- '''Make all files readable, and all directories read+execute'''
- def chmod_or(f, mask):
- mode = os.lstat(f)[0]
- if not stat.S_ISLNK(mode):
- newmode = mode | mask
- if newmode != mode:
- os.chmod(f, newmode)
- for top, dirs, files in os.walk(targetdir):
- chmod_or(top, 0555)
- for f in files:
- chmod_or(os.path.join(top, f), 0444)
-
-def _unpack_rpm(rpm, targetdir, includepat=None, excludepat=None):
- '''Unpack the given rpm into the given directory'''
- if not os.path.isdir(targetdir):
- os.makedirs(targetdir,mode=0755)
- os.chdir(targetdir)
- cpio = ['cpio','--quiet','-iud']
- if excludepat:
- cpio += ['-f', excludepat]
- if includepat:
- cpio += [includepat]
- p1 = Popen(['rpm2cpio',rpm], stdout=PIPE)
- p2 = Popen(cpio, stdin=p1.stdout, stdout=PIPE)
- output = p2.communicate()[0] # should be empty
- if p2.returncode != 0:
- raise OSError, "cpio failed: %s output:\n%s" % (str(p2.returncode),output)
- # Fix perms so all files are readable
- fix_perms(targetdir)
-
-def unpack_rpm(rpm, targetdir, includepat=None, excludepat=None):
- '''Unpack the given rpm into a temporary directory alongside the targetdir,
- then rename the temp dir once finished.'''
- dir = os.path.dirname(targetdir)
- if not os.path.isdir(dir):
- os.makedirs(targetdir,mode=0755)
- tmpdir = tempfile.mkdtemp(dir=dir)
- try:
- _unpack_rpm(rpm, tmpdir, includepat, excludepat)
- if os.path.isdir(targetdir):
- shutil.rmtree(targetdir)
- os.rename(tmpdir,targetdir)
- return True
- except (OSError, IOError), e:
- print "unpack_rpm failed: %s" % str(e)
- shutil.rmtree(tmpdir)
- return False
-
-def mkdebuginfolinks(sourcedir, targetdir, warn_on_collision=False):
- '''hardlink debuginfo from sourcedir into targetdir'''
- count = 0
- for top, dirs, files in os.walk(sourcedir, topdown=True):
- if '/usr/lib/debug/.build-id/' not in top:
- continue
- for u in [os.path.join(top,f) for f in files if f.endswith('.debug')]:
- target = os.path.realpath(u)
- linkname = u.split('/usr/lib/debug/.build-id/')[1]
- newlink = os.path.join(targetdir,linkname)
- try:
- os.makedirs(os.path.dirname(newlink),mode=0755)
- except OSError, e:
- if e.errno != 17:
- raise e
- if os.path.exists(newlink):
- if warn_on_collision and (os.stat(newlink) != os.stat(target)):
- # TODO: better logging here
- print "WARNING: collision or damaged debuginfo detected"
- print "%s exists - removing" % (newlink,)
- os.unlink(newlink)
- os.link(target,newlink)
- count += 1
- return count
-
-# TODO: break this up into more logical chunks
-def main():
- y = DebuginfoFSDownloader()
- opt = y.setup()
- # FIXME this is stupid - figure out how --verbose works
- if opt.verbose:
- y.logger = y.verbose_logger
- # Validate some of the opts
- # Check permissions on exportdir/cachedir
- perms_ok = True
- for d in (opt.exportdir, opt.cachedir):
- if not os.access(d,os.W_OK):
- perms_ok = False
- y.logger.error("you don't have write permission on %s" % d)
- if not perms_ok:
- sys.exit(1)
-
- if opt.basearch not in rpmUtils.arch.arches:
- y.logger.error("Unrecognized arch %s" % opt.basearch)
- sys.exit(1)
-
- # kind of a cheap hack - use values from conf and opt to re-parse URLs
- my_yumvar = y.conf.yumvar
- my_yumvar.update(conf)
- for a in 'basearch', 'releasever':
- v = getattr(opt,a,None)
- if v:
- my_yumvar[a] = v
- # Another cheap hack - lie about our arch
- if opt.basearch == 'i386':
- # hacks upon hacks. blerg.
- rpmUtils.arch.canonArch = 'i686'
- else:
- rpmUtils.arch.canonArch = opt.basearch
-
- # Set up the requested repos
- for repoid in y.cmds:
- try:
- d = dict([(k,varReplace(v,my_yumvar)) for k,v in c.items(repoid)])
- except ConfigParser.NoSectionError:
- y.logger.error("Unknown repo ID %s" % repoid)
- continue
- if 'mirrorlist' in d:
- y.logger.info("Adding repo %s with mirrorlist %s" % (repoid,d['mirrorlist']))
- repo = YumRepository('%s-%s-%s-debuginfofs' % \
- (repoid, opt.releasever, opt.basearch))
- repo.name = repo.id
- repo.mirrorlist = d['mirrorlist']
- repo.cache = 0
- repo.enable()
- repo.basecachedir = opt.cachedir
- repo.cachedir = repo.id
- y.repos.add(repo)
- y.repos.doSetup(thisrepo=repo.id)
- # FIXME: locking - don't setup a repo that's in use by another process
-
- repolist = y.repos.listEnabled()
- if repolist:
- # Set up progress callbacks for new repos
- y.setupProgressCallbacks()
- for r in repolist:
- try:
- r.ready()
- except yum.Errors.RepoError, e:
- y.logger.error(str(e))
- sys.exit(1)
- else:
- y.logger.error("Couldn't find any repos to set up.")
- repos = [s for s in c.sections() if s != 'general']
- y.logger.error("Known repos: %s" % ", ".join(repos))
- sys.exit(1)
-
- # Figure out which packages we need to fetch
- download_packages = []
- unpack_packages = []
- for p in y.pkgSack.returnPackages():
- repo = y.repos.getRepo(p.repoid)
- remote = p.returnSimple('relativepath')
- local = os.path.join(opt.cachedir,os.path.basename(remote))
- p.localpath = local
- n = p.pkgtup[0]
- nevra = pkg_to_nevra(p)
- #/var/www/debuginfofs/packages/c/coreutils/coreutils-0:6.12-18.fc10.i386
- newdir = os.path.join(n[0],n,nevra)
- targetdir = os.path.join(opt.exportdir,'packages',newdir)
- # Don't bother checking - just add everything to the list
- if opt.force_download:
- download_packages.append(p)
- continue
-
- # Skip it if it's already unpacked
- if os.path.isdir(targetdir):
- y.logger.info("Already unpacked %s" % nevra)
- os.utime(targetdir, None)
- continue
-
- # XXX does y.downloadPackages handle this for us?
- if (os.path.exists(local) and
- os.path.getsize(local) == int(p.returnSimple('packagesize'))):
- y.logger.info("Already downloaded %s" % nevra)
- unpack_packages.append(p)
- else:
- download_packages.append(p)
-
- if not (unpack_packages or download_packages):
- y.verbose_logger.info(_('Nothing to do!'))
- sys.exit(0)
-
- # Show what will be downloaded and get confirmation
- y.verbose_logger.info(y.listDownloads(download_packages))
- y.reportDownloadSize(download_packages)
- # FIXME: show some info on unpack_packages
- y.verbose_logger.info("Downloading to cachedir %s" % opt.cachedir)
- y.verbose_logger.info("Unpacking to exportdir %s" % opt.exportdir)
- if y._promptWanted():
- if not y.userconfirm():
- y.logger.info(_('Exiting on user Command'))
- sys.exit(1)
-
- # Download, unpack, and hardlink debuginfo data
- excludepat=None
- if not opt.keep_src:
- excludepat="*/usr/src/debug/*"
- for p in unpack_packages + download_packages:
- if p in download_packages:
- repo = y.repos.getRepo(p.repoid)
- # FIXME handle possible errors here
- repo.getPackage(p)
- if opt.download_only:
- continue
- local = p.localpath
- n = p.pkgtup[0]
- nevra = pkg_to_nevra(p)
- newdir = os.path.join(n[0],n,nevra)
- targetdir = os.path.join(opt.exportdir,'packages',newdir)
-
- y.verbose_logger.info("Unpacking %s" % nevra)
- unpack_rpm(local, targetdir, excludepat=excludepat)
- # Remove cached package now that we've unpacked it
- if not opt.savecache:
- os.unlink(local)
- # Make hardlinks
- r = mkdebuginfolinks(targetdir, os.path.join(opt.exportdir,'build-id'))
- y.logger.info("Linked %3i debuginfo file%s" % (r, r != 1 and "s" or ""))
-
-if __name__ == '__main__':
- try:
- main()
- except KeyboardInterrupt:
- print "Exiting on keyboard interrupt"