bgneal@665: """dlorphan - a management command to remove orphaned downloads files.""" bgneal@665: bgneal@665: from optparse import make_option bgneal@665: import os bgneal@665: bgneal@665: from django.core.management.base import NoArgsCommand bgneal@665: from django.conf import settings bgneal@665: bgneal@665: from downloads.models import Download, PendingDownload bgneal@665: bgneal@665: bgneal@665: class Command(NoArgsCommand): bgneal@665: help = "Finds and optionally deletes orphan downloads files" bgneal@665: option_list = NoArgsCommand.option_list + ( bgneal@665: make_option('--delete', bgneal@665: action='store_true', bgneal@665: dest='delete', bgneal@665: default=False, bgneal@665: help='Delete orphan files'), bgneal@665: ) bgneal@665: bgneal@665: def handle_noargs(self, **options): bgneal@665: """Find and optionally delete orphan downloads files.""" bgneal@665: bgneal@665: delete = options.get('delete', False) bgneal@665: bgneal@665: orphans = set() bgneal@665: missing_pending = [] bgneal@665: missing_dls = [] bgneal@665: empty_dirs = [] bgneal@665: bgneal@665: dls_dir = os.path.join(settings.MEDIA_ROOT, 'downloads') bgneal@665: # find the set of all files in the downloads area bgneal@665: for root, dirs, files in os.walk(dls_dir, followlinks=True): bgneal@665: for name in files: bgneal@665: orphans.add(unicode(os.path.join(root, name), 'utf-8')) bgneal@665: bgneal@665: # check for empty directories bgneal@665: if not len(dirs) and not len(files): bgneal@665: empty_dirs.append(root) bgneal@665: bgneal@665: # examine the pending downloads: bgneal@665: for dl in PendingDownload.objects.iterator(): bgneal@665: try: bgneal@665: orphans.remove(dl.file.path) bgneal@665: except KeyError: bgneal@665: missing_pending.append(dl) bgneal@665: bgneal@665: # examine the downloads: bgneal@665: for dl in Download.objects.iterator(): bgneal@665: try: bgneal@665: orphans.remove(dl.file.path) bgneal@665: except KeyError: bgneal@665: missing_dls.append(dl) bgneal@665: bgneal@665: if orphans: bgneal@665: print "Orphan files:" bgneal@665: for orphan in orphans: bgneal@665: print orphan bgneal@665: bgneal@665: if empty_dirs: bgneal@665: print "Empty directories:" bgneal@665: for d in empty_dirs: bgneal@665: print d bgneal@665: bgneal@665: if missing_pending: bgneal@665: print "PendingDownloads with missing files:" bgneal@665: for dl in missing_pending: bgneal@665: print dl bgneal@665: bgneal@665: if missing_dls: bgneal@665: print "Downloads with missing files:" bgneal@665: for dl in missing_dls: bgneal@665: print dl bgneal@665: bgneal@665: if delete: bgneal@665: for path in orphans: bgneal@665: print "Deleting: {}".format(path) bgneal@665: os.remove(path) bgneal@665: bgneal@665: for path in empty_dirs: bgneal@665: print "Deleting: {}".format(path) bgneal@665: os.removedirs(path)