From 674813364633299f6861098c29f60fe961cfaeb1 Mon Sep 17 00:00:00 2001 From: Jesse Keating Date: Sun, 2 Dec 2007 14:31:26 -0500 Subject: [PATCH] Support re-using existing destdirs better, with a --force option. --- Changelog | 4 ++++ doc/pungi.8 | 4 +++- pungi | 6 ++++++ pypungi/__init__.py | 26 ++++++++++++++++++++++++-- pypungi/gather.py | 5 +++-- pypungi/pungi.py | 15 +++++++++------ 6 files changed, 49 insertions(+), 11 deletions(-) diff --git a/Changelog b/Changelog index f8458d1d..280189d9 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,7 @@ +* Sun Dec 02 Jesse Keating +- Add a --force option to reuse an existing destdir +- Only overwrite dirs if --force is offered, clean out some specific dirs + * Fri Nov 30 2007 Jesse Keating - Only check for root if you're doing root level tasks (buildinstall) diff --git a/doc/pungi.8 b/doc/pungi.8 index beb48857..b9ed4647 100644 --- a/doc/pungi.8 +++ b/doc/pungi.8 @@ -18,7 +18,7 @@ Display program's version number and then quit\&. .IP "\fB\-\-name=string\fP" Set the name for your distribution (defaults to "Fedora")\&. .IP "\fB\-\-ver=string\fP" -Set the version for your distribution (defaults to datestamp)\&. +Set the version for your distribution (defaults to datestamp, used for $releasever in yum)\&. .IP "\fB\-\-flavor=string\fP" Set the flavor of your spin (optional)\&. .IP "\fB\-\-destdir=pathspec\fP" @@ -34,6 +34,8 @@ Disable gathering of source packages (optional)\&. .IP "\fB\-\-nosplitmedia\fP" Disable creation of split media (optional)\&. .IP "\fB\-\-sourceisos\fP" +Force reuse of an existing destination directory (will overwrite files)\&. +.IP "\fB\-\-force\fP" Create the source media images (other arch runs must be done)\&. .IP "\fB\-c ksfile, \-\-config=ksfile\fP" Path to kickstart configuration file\&. diff --git a/pungi b/pungi index a4677cde..0a4dddb3 100755 --- a/pungi +++ b/pungi @@ -41,6 +41,8 @@ def main(): for part in ksparser.handler.partition.partitions: if part.mountpoint == 'iso': config.set('default', 'cdsize', str(part.size)) + + config.set('default', 'force', opts.force) # Set up our directories if not os.path.exists(config.get('default', 'destdir')): @@ -49,6 +51,8 @@ def main(): except OSError, e: print >> sys.stderr, "Error: Cannot create destination dir %s" % config.get('default', 'destdir') sys.exit(1) + else: + print >> sys.stdout, "Warning: Reusing existing destination directory." cachedir = config.get('default', 'cachedir') @@ -138,6 +142,8 @@ if __name__ == '__main__': help='disable creation of split media (optional)') parser.add_option("--sourceisos", default=False, action="store_true", dest="sourceisos", help='Create the source isos (other arch runs must be done)') + parser.add_option("--force", default=False, action="store_true", + help='Force reuse of an existing destination directory (will overwrite files)') parser.add_option("-c", "--config", dest="config", help='Path to kickstart config file') diff --git a/pypungi/__init__.py b/pypungi/__init__.py index 03286913..27d847a0 100644 --- a/pypungi/__init__.py +++ b/pypungi/__init__.py @@ -16,6 +16,7 @@ import logging import os import subprocess import shutil +import sys class PungiBase(object): """The base Pungi class. Set up config items and logging here""" @@ -37,8 +38,7 @@ class PungiBase(object): logdir = os.path.join(self.config.get('default', 'destdir'), 'logs') - if not os.path.exists(logdir): - os.makedirs(logdir) + _ensuredir(logdir, force=True) # Always allow logs to be written out if self.config.get('default', 'flavor'): logfile = os.path.join(logdir, '%s.%s.log' % (self.config.get('default', 'flavor'), @@ -85,3 +85,25 @@ def _link(local, target, force=False): # Can't hardlink cross file systems shutil.copy2(local, target) +def _ensuredir(target, force=False, clean=False): + """Ensure that a directory exists, if it already exists, only continue + if force is set.""" + + def whoops(func, path, exc_info): + self.logger.error('Could not remove %s' % path) + sys.exit(1) + + if os.path.exists(target) and not os.path.isdir(target): + self.logger.error('%s exists but is not a directory.' % target) + sys.exit(1) + + if not os.path.isdir(target): + os.makedirs(target) + elif force and clean: + shutil.rmtree(target, onerror=whoops) + os.makedirs(target) + elif force: + return + else: + self.logger.error('Directory %s already exists. Use --force to overwrite.' % target) + sys.exit(1) \ No newline at end of file diff --git a/pypungi/gather.py b/pypungi/gather.py index 373ba1aa..2f84e3ed 100755 --- a/pypungi/gather.py +++ b/pypungi/gather.py @@ -46,6 +46,7 @@ class PungiYum(yum.YumBase): logfile = os.path.join(logdir, '%s.log' % (self.pungiconfig.get('default', 'arch'))) yum.logging.basicConfig(level=yum.logging.DEBUG, filename=logfile) + self.logger.error('foobar') def doFileLogSetup(self, uid, logfile): # This function overrides a yum function, allowing pungi to control @@ -320,8 +321,8 @@ class Gather(pypungi.PungiBase): self.config.get('default', 'flavor'), relpkgdir) - if not os.path.exists(pkgdir): - os.makedirs(pkgdir) + # Ensure the pkgdir exists, force if requested, and make sure we clean it out + pypungi._ensuredir(pkgdir, force=self.config.getbool('default', 'force'), clean=True) probs = self.ayum.downloadPkgs(polist) diff --git a/pypungi/pungi.py b/pypungi/pungi.py index e7d4a372..2501f028 100755 --- a/pypungi/pungi.py +++ b/pypungi/pungi.py @@ -44,8 +44,7 @@ class Pungi(pypungi.PungiBase): self.topdir = os.path.join(self.archdir, 'os') self.isodir = os.path.join(self.archdir, self.config.get('default','isodir')) - if not os.path.exists(self.workdir): - os.makedirs(self.workdir) + pypungi._ensuredir(workdir, force=self.config.getbool('default', 'force')) self.common_files = [] self.infofile = os.path.join(self.config.get('default', 'destdir'), @@ -174,7 +173,7 @@ class Pungi(pypungi.PungiBase): for pattern in self.config.get('default', 'relnotedirre').split(): dirres.append(re.compile(pattern)) - os.makedirs(docsdir) + pypungi._ensuredir(docsdir, force=self.config.getbool('default', 'force'), clean=True) # Expload the packages we list as relnote packages pkgs = os.listdir(os.path.join(self.topdir, self.config.get('default', 'product_path'))) @@ -269,7 +268,9 @@ class Pungi(pypungi.PungiBase): # this is stolen from splittree.py in anaconda-runtime. Blame them if its ugly (: for i in range(timber.src_list[0], timber.src_list[-1] + 1): - os.makedirs("%s-disc%d/SRPMS" % (timber.dist_dir, i)) + pypungi._ensuredir('%s-disc%d/SRPMS' % (timper.dist_dir, i), + force=self.config.getbool('default', 'force'), + clean=True) timber.linkFiles(timber.dist_dir, "%s-disc%d" %(timber.dist_dir, i), timber.common_files) @@ -303,7 +304,8 @@ class Pungi(pypungi.PungiBase): createrepo.append('--outputdir') if self.config.getint('default', 'discs') == 1: - os.makedirs('%s-disc1' % self.topdir) # rename this for single disc + pypungi._ensuredir('%s-disc1', force=self.config.getbool('default', 'force'), + clean=True) # rename this for single disc createrepo.append('%s-disc1' % self.topdir) createrepo.append('--basedir') @@ -344,7 +346,8 @@ cost=500 anaruntime = '/usr/lib/anaconda-runtime/boot' discinfofile = os.path.join(self.topdir, '.discinfo') # we use this a fair amount - os.makedirs(self.isodir) + pypungi._ensuredir(self.isodir, force=self.config.getbool('default', 'force'), + clean=True) # This is risky... # setup the base command mkisofs = ['/usr/bin/mkisofs']