From 5ed89d8b1a090bcf47482251f8dd05ea49fbd356 Mon Sep 17 00:00:00 2001 From: Lukasz Langa Date: Tue, 9 Aug 2016 14:51:57 -0700 Subject: [PATCH] [0.9.0] Python 3 compat, --quiet obeyed for bitrot.db checksum checks --- README.rst | 7 ++++++ setup.py | 14 +++++------ src/bitrot.py | 68 +++++++++++++++++++++++++++++++-------------------- 3 files changed, 54 insertions(+), 35 deletions(-) diff --git a/README.rst b/README.rst index 7d4bbd2..c05f0c4 100644 --- a/README.rst +++ b/README.rst @@ -36,6 +36,13 @@ a 100 GB Aperture library in under 10 minutes. Both tests on HFS+. Change Log ---------- +0.9.0 +~~~~~ + +* bugfix: bitrot.db checksum checking messages now obey --quiet + +* Python 3 compatibility + 0.8.0 ~~~~~ diff --git a/setup.py b/setup.py index d38ac36..bfcb0f7 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (C) 2013 by Łukasz Langa -# +# # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights @@ -21,15 +21,13 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. +import codecs import os import sys from setuptools import setup, find_packages -reload(sys) -sys.setdefaultencoding('utf8') - current_dir = os.path.abspath(os.path.dirname(__file__)) -ld_file = open(os.path.join(current_dir, 'README.rst')) +ld_file = codecs.open(os.path.join(current_dir, 'README.rst'), encoding='utf8') try: long_description = ld_file.read() finally: @@ -44,7 +42,7 @@ setup( name = 'bitrot', version = release, - author = 'Łukasz Langa', + author = u'Łukasz Langa', author_email = 'lukasz@langa.pl', description = ("Detects bit rotten files on the hard drive to save your " "precious photo and music collection from slow decay."), @@ -63,11 +61,11 @@ ], classifiers = [ - 'Development Status :: 3 - Alpha', + 'Development Status :: 4 - Beta', 'License :: OSI Approved :: MIT License', 'Natural Language :: English', 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 2 :: Only', + 'Programming Language :: Python :: 3', 'Programming Language :: Python', 'Topic :: System :: Filesystems', 'Topic :: System :: Monitoring', diff --git a/src/bitrot.py b/src/bitrot.py index f80cef2..1f27a0a 100644 --- a/src/bitrot.py +++ b/src/bitrot.py @@ -42,11 +42,16 @@ DEFAULT_CHUNK_SIZE = 16384 DOT_THRESHOLD = 200 -VERSION = (0, 8, 0) +VERSION = (0, 9, 0) IGNORED_FILE_SYSTEM_ERRORS = {errno.ENOENT, errno.EACCES} FSENCODING = sys.getfilesystemencoding() +if sys.version[0] == '2': + str = type(u'text') + # use `bytes` for bytestrings + + def sha1(path, chunk_size): digest = hashlib.sha1() with open(path, 'rb') as f: @@ -62,6 +67,7 @@ def ts(): def get_sqlite3_cursor(path, copy=False): + path = path.decode(FSENCODING) if copy: if not os.path.exists(path): raise ValueError("error: bitrot database at {} does not exist." @@ -162,7 +168,7 @@ def maybe_commit(self, conn): self._last_commit_ts = time.time() def run(self): - check_sha512_integrity() + check_sha512_integrity(verbosity=self.verbosity) bitrot_db = get_path() bitrot_sha512 = get_path(ext=b'sha512') @@ -278,7 +284,7 @@ def run(self): missing_paths, ) - update_sha512_integrity() + update_sha512_integrity(verbosity=self.verbosity) if errors: raise BitrotException( @@ -340,7 +346,7 @@ def report_done( print(' ', path) if not any((new_paths, updated_paths, missing_paths)): print() - if self.test: + if self.test and self.verbosity: print('warning: database file not updated on disk (test mode).') def handle_unknown_path(self, cur, new_path, new_mtime, new_sha1): @@ -396,43 +402,48 @@ def stable_sum(bitrot_db): return digest.hexdigest() -def check_sha512_integrity(): - sha512_path = get_path(ext='sha512') +def check_sha512_integrity(verbosity=1): + sha512_path = get_path(ext=b'sha512') if not os.path.exists(sha512_path): return - print('Checking bitrot.db integrity... ', end='') + if verbosity: + print('Checking bitrot.db integrity... ', end='') + sys.stdout.flush() with open(sha512_path, 'rb') as f: old_sha512 = f.read().strip() bitrot_db = get_path() digest = hashlib.sha512() with open(bitrot_db, 'rb') as f: digest.update(f.read()) - new_sha512 = digest.hexdigest() + new_sha512 = digest.hexdigest().encode('ascii') if new_sha512 != old_sha512: - if len(old_sha512) == 128: - print( - "error: SHA512 of the file is different, bitrot.db might be " - "corrupt." - ) - else: + if verbosity: + if len(old_sha512) == 128: + print( + "error: SHA512 of the file is different, bitrot.db might " + "be corrupt.", + ) + else: + print( + "error: SHA512 of the file is different but bitrot.sha512 " + "has a suspicious length. It might be corrupt.", + ) print( - "error: SHA512 of the file is different but bitrot.sha512 has " - "a suspicious length. It might be corrupt." + "If you'd like to continue anyway, delete the .bitrot.sha512 " + "file and try again.", + file=sys.stderr, ) - print( - "If you'd like to continue anyway, delete the .bitrot.sha512 " - "file and try again." - ) raise BitrotException( 3, 'bitrot.db integrity check failed, cannot continue.', ) - print('ok.') + if verbosity: + print('ok.') -def update_sha512_integrity(): +def update_sha512_integrity(verbosity=1): old_sha512 = 0 - sha512_path = get_path(ext='sha512') + sha512_path = get_path(ext=b'sha512') if os.path.exists(sha512_path): with open(sha512_path, 'rb') as f: old_sha512 = f.read().strip() @@ -440,12 +451,15 @@ def update_sha512_integrity(): digest = hashlib.sha512() with open(bitrot_db, 'rb') as f: digest.update(f.read()) - new_sha512 = digest.hexdigest() + new_sha512 = digest.hexdigest().encode('ascii') if new_sha512 != old_sha512: - print('Updating bitrot.sha512... ', end='') + if verbosity: + print('Updating bitrot.sha512... ', end='') + sys.stdout.flush() with open(sha512_path, 'wb') as f: f.write(new_sha512) - print('done.') + if verbosity: + print('done.') def run_from_command_line(): global FSENCODING @@ -492,7 +506,7 @@ def run_from_command_line(): try: print(stable_sum()) except RuntimeError as e: - print(unicode(e).encode('utf8'), file=sys.stderr) + print(str(e).encode('utf8'), file=sys.stderr) else: verbosity = 1 if args.quiet: