From 3a7b2f0b741fd80fb4a0d2802918219f3d5bf05a Mon Sep 17 00:00:00 2001 From: Leonardo Gentile Date: Mon, 3 Mar 2014 18:27:28 +0100 Subject: [PATCH 1/3] Log file support: - Reordered the import list - Added ORPHANED_LOGS_DIR option from django settings - Print the success/error operations status for each file/directory in console and in file if the ORPHANED_LOGS_DIR is set --- django_orphaned/app_settings.py | 1 + .../management/commands/deleteorphaned.py | 92 ++++++++++++++++--- 2 files changed, 81 insertions(+), 12 deletions(-) diff --git a/django_orphaned/app_settings.py b/django_orphaned/app_settings.py index ce45b3d..893732a 100644 --- a/django_orphaned/app_settings.py +++ b/django_orphaned/app_settings.py @@ -2,3 +2,4 @@ from django.utils.importlib import import_module ORPHANED_APPS_MEDIABASE_DIRS = getattr(settings, 'ORPHANED_APPS_MEDIABASE_DIRS',{}) +ORPHANED_LOGS_DIR = getattr(settings, 'ORPHANED_LOGS_DIR','') \ No newline at end of file diff --git a/django_orphaned/management/commands/deleteorphaned.py b/django_orphaned/management/commands/deleteorphaned.py index 3175eeb..c7d7681 100644 --- a/django_orphaned/management/commands/deleteorphaned.py +++ b/django_orphaned/management/commands/deleteorphaned.py @@ -1,11 +1,13 @@ -from django.core.management.base import BaseCommand -from django.contrib.contenttypes.models import ContentType -from django_orphaned.app_settings import ORPHANED_APPS_MEDIABASE_DIRS from itertools import chain from optparse import make_option import os import shutil +from datetime import datetime +from django.core.management.base import BaseCommand +from django.contrib.contenttypes.models import ContentType from django.conf import settings +from django_orphaned.app_settings import ORPHANED_APPS_MEDIABASE_DIRS, ORPHANED_LOGS_DIR + class Command(BaseCommand): help = "Delete all orphaned files" @@ -96,14 +98,10 @@ def should_skip(dir): total_freed_bytes += os.path.getsize(df) total_freed = "%0.1f MB" % (total_freed_bytes/(1024*1024.0)) - # only show + # Only show if (self.only_info): print "\r\n=== %s ===" % app - if len(empty_dirs) > 0: - print "\r\nFollowing empty dirs will be removed:\r\n" - for file in empty_dirs: - print " ", file - + # Files to be deleted if len(delete_files) > 0: print "\r\nFollowing files will be deleted:\r\n" for file in delete_files: @@ -111,10 +109,80 @@ def should_skip(dir): print "\r\nTotally %s files will be deleted, and "\ "totally %s will be freed.\r\n" % (len(delete_files), total_freed) else: - print "No files to delete!" + print "No files to delete!\r\n" + # Empty folders to be deleted + if len(empty_dirs) > 0: + print "\r\nFollowing empty dirs will be removed:\r\n" + for file in empty_dirs: + print " ", file + print "\r\nTotally %s dirs will be deleted\r\n" % (len(empty_dirs)) + else: + print "No empty dirs to delete!\r\n" + # DELETE NOW! else: + deleted_files = 0 + deleted_dirs = 0 + error_files = 0 + error_dirs = 0 + total_freed_bytes = 0 + file_is_open = False + file_log_path = None + if ORPHANED_LOGS_DIR: + filename = datetime.now().strftime("%Y%m%d-%H.%M.%S") + "_orphaned.log" + if empty_dirs: + pass + file_log_path = os.path.join(ORPHANED_LOGS_DIR, filename) + try: + if empty_dirs: + pass + log_file = open(file_log_path, 'w') + file_is_open = True + except IOError: + file_is_open = False + print "Error: Could not Write to File\r\n" + for file in delete_files: - os.remove(file) + try: + file_size_byte = os.path.getsize(file) + os.remove(file) + total_freed_bytes += file_size_byte + deleted_files += 1 + print("DELETED FILE: %s %s Bytes" % (file, file_size_byte)) + if file_is_open: + log_file.write("DELETED FILE: %s %s Bytes\n" % (file, file_size_byte)) + except OSError: + error_files += 1 + print("ERROR: %s\n" % file) + if file_is_open: + log_file.write("ERROR: %s\n" % file) + total_freed = "%0.1f MB" % (total_freed_bytes/(1024*1024.0)) + print("\r\nTotally %s files deleted. Totally %s freed." % \ + (deleted_files, total_freed)) + print("\r%s Errors while deleting files." % (error_files)) + print("\r\n================\r\n") + if file_is_open: + log_file.write("\r\nTotally %s files deleted. Totally %s freed." % \ + (deleted_files, total_freed)) + log_file.write("\r%s Errors while deleting files." % (error_files)) + log_file.write("\r\n================\r\n") for dirs in empty_dirs: - shutil.rmtree(dirs, ignore_errors=True) + try: + shutil.rmtree(dirs, ignore_errors=False) + deleted_dirs += 1 + print("DELETED DIR: %s" % dirs) + if file_is_open: + log_file.write("DELETED DIR: %s\n" % dirs) + except OSError: + error_dirs += 1 + print("ERROR: %s\n" % dirs) + if file_is_open: + log_file.write("ERROR: %s\n" % dirs) + print("\r\nTotally %s dirs deleted." % (deleted_dirs)) + print("\r%s Errors while deleting empty dirs." % (error_dirs)) + if file_log_path: + print("\r\n\nLOG FILE STORED IN: %s\n\r" % (file_log_path)) + if file_is_open: + log_file.write("\r\nTotally %s dirs deleted." % (deleted_dirs)) + log_file.write("\r%s Errors while deleting empty dirs." % (error_dirs)) + log_file.close() From 16ae65ab85bc036154910e12c72835b7c683f161 Mon Sep 17 00:00:00 2001 From: Leonardo Gentile Date: Tue, 4 Mar 2014 15:45:32 +0100 Subject: [PATCH 2/3] Updated the readme file for including the new file log option --- README.md | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 97e6175..bceb4df 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # about -delete all orphaned files +Delete all orphaned files # setup install via easy_install or pip @@ -17,18 +17,35 @@ add it to installed apps in django settings.py ... ) -now add this to your settings.py ('app' is your project name where models.py is located): +now add this to your settings.py ('app1' and app2 are the app names where models.py is located): ORPHANED_APPS_MEDIABASE_DIRS = { - 'app': { - 'root': MEDIABASE_ROOT, # MEDIABASE_ROOT => default location(s) of your uploaded items e.g. /var/www/mediabase - 'skip': ( # optional iterable of subfolders to preserve, e.g. sorl.thumbnail cache - path.join(MEDIABASE_ROOT, 'cache'), - path.join(MEDIABASE_ROOT, 'foobar'), + 'app1': { + # MEDIA_ROOT => default location(s) of your uploaded items e.g. /var/www/mediabase + # It can be a single value or a list of iterable + 'root': ( + os.path.join(MEDIA_ROOT, 'files'), + os.path.join(MEDIA_ROOT, 'images'), ), - 'exclude': ('.gitignore',) # optional iterable of files to preserve + # optional iterable of subfolders to preserve, e.g. sorl.thumbnail cache + 'skip': ( + path.join(MEDIA_ROOT, 'cache'), + path.join(MEDIA_ROOT, 'foobar'), + ), + # optional iterable of files to preserve + 'exclude': ( + '.gitignore', + ) + } + 'app2': { + ... + # same as above + .. } } + # location where the log file will be stored + # if not set or empty the log file will not be created + ORPHANED_LOGS_DIR = MEDIA_ROOT **NOTE**: from version 0.4.2 you can define ''root'' as string or iterable (list, array) @@ -41,4 +58,4 @@ and to finally delete all orphaned files python manage.py deleteorphaned # license -MIT-License, see [LICENSE](/ledil/django-orphaned/blob/master/LICENSE) file. +MIT-License, see [LICENSE](/ledil/django-orphaned/blob/master/LICENSE) file. \ No newline at end of file From 58bb85a5afc2167c7475415e6f38909633ddd59e Mon Sep 17 00:00:00 2001 From: Leonardo Gentile Date: Tue, 4 Mar 2014 15:50:10 +0100 Subject: [PATCH 3/3] added newline at the end of file --- django_orphaned/app_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django_orphaned/app_settings.py b/django_orphaned/app_settings.py index 893732a..f725382 100644 --- a/django_orphaned/app_settings.py +++ b/django_orphaned/app_settings.py @@ -2,4 +2,4 @@ from django.utils.importlib import import_module ORPHANED_APPS_MEDIABASE_DIRS = getattr(settings, 'ORPHANED_APPS_MEDIABASE_DIRS',{}) -ORPHANED_LOGS_DIR = getattr(settings, 'ORPHANED_LOGS_DIR','') \ No newline at end of file +ORPHANED_LOGS_DIR = getattr(settings, 'ORPHANED_LOGS_DIR','')