bgneal@665
|
1 """dlorphan - a management command to remove orphaned downloads files."""
|
bgneal@665
|
2
|
bgneal@665
|
3 from optparse import make_option
|
bgneal@665
|
4 import os
|
bgneal@665
|
5
|
bgneal@665
|
6 from django.core.management.base import NoArgsCommand
|
bgneal@665
|
7 from django.conf import settings
|
bgneal@665
|
8
|
bgneal@665
|
9 from downloads.models import Download, PendingDownload
|
bgneal@665
|
10
|
bgneal@665
|
11
|
bgneal@665
|
12 class Command(NoArgsCommand):
|
bgneal@665
|
13 help = "Finds and optionally deletes orphan downloads files"
|
bgneal@665
|
14 option_list = NoArgsCommand.option_list + (
|
bgneal@665
|
15 make_option('--delete',
|
bgneal@665
|
16 action='store_true',
|
bgneal@665
|
17 dest='delete',
|
bgneal@665
|
18 default=False,
|
bgneal@665
|
19 help='Delete orphan files'),
|
bgneal@665
|
20 )
|
bgneal@665
|
21
|
bgneal@665
|
22 def handle_noargs(self, **options):
|
bgneal@665
|
23 """Find and optionally delete orphan downloads files."""
|
bgneal@665
|
24
|
bgneal@665
|
25 delete = options.get('delete', False)
|
bgneal@665
|
26
|
bgneal@665
|
27 orphans = set()
|
bgneal@665
|
28 missing_pending = []
|
bgneal@665
|
29 missing_dls = []
|
bgneal@665
|
30
|
bgneal@665
|
31 dls_dir = os.path.join(settings.MEDIA_ROOT, 'downloads')
|
bgneal@665
|
32 # find the set of all files in the downloads area
|
bgneal@665
|
33 for root, dirs, files in os.walk(dls_dir, followlinks=True):
|
bgneal@665
|
34 for name in files:
|
bgneal@665
|
35 orphans.add(unicode(os.path.join(root, name), 'utf-8'))
|
bgneal@665
|
36
|
bgneal@665
|
37 # examine the pending downloads:
|
bgneal@665
|
38 for dl in PendingDownload.objects.iterator():
|
bgneal@665
|
39 try:
|
bgneal@665
|
40 orphans.remove(dl.file.path)
|
bgneal@665
|
41 except KeyError:
|
bgneal@665
|
42 missing_pending.append(dl)
|
bgneal@665
|
43
|
bgneal@665
|
44 # examine the downloads:
|
bgneal@665
|
45 for dl in Download.objects.iterator():
|
bgneal@665
|
46 try:
|
bgneal@665
|
47 orphans.remove(dl.file.path)
|
bgneal@665
|
48 except KeyError:
|
bgneal@665
|
49 missing_dls.append(dl)
|
bgneal@665
|
50
|
bgneal@667
|
51 if orphans and delete:
|
bgneal@667
|
52 for path in orphans:
|
bgneal@667
|
53 self.stdout.write("Deleting: {}\n".format(path))
|
bgneal@667
|
54 os.remove(path)
|
bgneal@667
|
55 elif orphans:
|
bgneal@667
|
56 self.stdout.write("Orphan files:\n")
|
bgneal@665
|
57 for orphan in orphans:
|
bgneal@667
|
58 self.stdout.write("{}\n".format(orphan))
|
bgneal@665
|
59
|
bgneal@665
|
60 if missing_pending:
|
bgneal@667
|
61 self.stdout.write("PendingDownloads with missing files:\n")
|
bgneal@665
|
62 for dl in missing_pending:
|
bgneal@667
|
63 self.stdout.write("{}\n".format(dl))
|
bgneal@665
|
64
|
bgneal@665
|
65 if missing_dls:
|
bgneal@667
|
66 self.stdout.write("Downloads with missing files:\n")
|
bgneal@665
|
67 for dl in missing_dls:
|
bgneal@667
|
68 self.stdout.write("{}\n".format(dl))
|
bgneal@665
|
69
|
bgneal@667
|
70 empty_dirs = []
|
bgneal@667
|
71 # check for empty directories after deletions
|
bgneal@667
|
72 for root, dirs, files in os.walk(dls_dir, followlinks=True):
|
bgneal@667
|
73 if not len(dirs) and not len(files):
|
bgneal@667
|
74 empty_dirs.append(root)
|
bgneal@665
|
75
|
bgneal@667
|
76 if empty_dirs and delete:
|
bgneal@665
|
77 for path in empty_dirs:
|
bgneal@667
|
78 self.stdout.write("Deleting empty dir: {}\n".format(path))
|
bgneal@665
|
79 os.removedirs(path)
|
bgneal@667
|
80 elif empty_dirs:
|
bgneal@667
|
81 self.stdout.write("Empty directories:\n")
|
bgneal@667
|
82 for d in empty_dirs:
|
bgneal@667
|
83 self.stdout.write("{}\n".format(d))
|