From d477e79342d015291871a69779bb089d58388c43 Mon Sep 17 00:00:00 2001 From: Will Woods Date: Mon, 23 Feb 2009 16:29:28 -0500 Subject: Add warn_on_collision to mkdebuginfolinks and make unpack_rpm atomically create the target dir --- debuginfofs-mirror | 54 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/debuginfofs-mirror b/debuginfofs-mirror index f9ed607..b6ff618 100755 --- a/debuginfofs-mirror +++ b/debuginfofs-mirror @@ -135,33 +135,36 @@ def fix_perms(targetdir): mode = os.stat(i)[0] os.chmod(i, mode | 0444) -def unpack_rpm(rpm, targetdir): - created_dir = False +def _unpack_rpm(rpm, targetdir): + '''Unpack the given rpm into the given directory''' if not os.path.isdir(targetdir): - os.makedirs(targetdir) - created_dir = True + os.makedirs(targetdir,mode=0755) + os.chdir(targetdir) + # rpm2cpio $rpm | cpio --quiet -iumd + p1 = Popen(['rpm2cpio',rpm], stdout=PIPE) + p2 = Popen(['cpio','--quiet','-iumd'], 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): + '''Unpack the given rpm into a temporary directory alongside the targetdir, + then rename the temp dir once finished.''' + tmpdir = tempfile.mkdtemp(dir=os.path.dirname(targetdir)) try: - # FIXME: unpack into a tmpdir and then move into place after finishing - # or else interrupted unpacks will leave us with incomplete output - os.chdir(targetdir) - # rpm2cpio $rpm | cpio --quiet -iumd - p1 = Popen(['rpm2cpio',rpm], stdout=PIPE) - p2 = Popen(['cpio','--quiet','-iumd'], 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) - except (IOError, OSError), e: - print str(e) - if created_dir: - print "removing %s" % targetdir + _unpack_rpm(rpm, tmpdir) + 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 - return True -def mkdebuginfolinks(sourcedir, targetdir): +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): @@ -172,13 +175,15 @@ def mkdebuginfolinks(sourcedir, targetdir): linkname = u.split('/usr/lib/debug/.build-id/')[1] newlink = os.path.join(targetdir,linkname) try: - os.makedirs(os.path.dirname(newlink)) + os.makedirs(os.path.dirname(newlink),mode=0755) except OSError, e: if e.errno != 17: raise e if os.path.exists(newlink): - # TODO: check to see if the contents of target == newlink - # If not, we have a collision. That's bad. + 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 @@ -238,6 +243,7 @@ def main(): 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: -- cgit