Add filetimelapse.py

This commit is contained in:
voussoir 2019-12-10 13:02:04 -08:00
parent cba1d51587
commit daafa1349d

76
filetimelapse.py Normal file
View file

@ -0,0 +1,76 @@
'''
Copy your file every few minutes while you work on it, so that you can have snapshots of its history.
Not a replacement for real version control but could be applicable in very simple situations or in
cases where e.g. git is not.
'''
import argparse
import glob
import hashlib
import os
import shutil
import sys
import time
from voussoirkit import bytestring
from voussoirkit import pathclass
def hash_file(filepath, hasher):
bytestream = read_filebytes(filepath)
for chunk in bytestream:
hasher.update(chunk)
return hasher.hexdigest()
def hash_file_md5(filepath):
return hash_file(filepath, hasher=hashlib.md5())
def read_filebytes(filepath, chunk_size=bytestring.MIBIBYTE):
'''
Yield chunks of bytes from the file between the endpoints.
'''
filepath = pathclass.Path(filepath)
if not filepath.is_file:
raise FileNotFoundError(filepath)
f = open(filepath.absolute_path, 'rb')
with f:
while True:
chunk = f.read(chunk_size)
if len(chunk) == 0:
break
yield chunk
def filetimelapse(filepath, rate):
(noext, extension) = os.path.splitext(filepath)
last_hash = None
existing_timelapses = glob.glob(f'{noext}-*.filetimelapse{extension}')
if existing_timelapses:
last_hash = hash_file_md5(existing_timelapses[-1])
print(f'Starting with previous {existing_timelapses[-1]} {last_hash}')
while True:
new_hash = hash_file_md5(filepath)
if new_hash != last_hash:
timestamp = time.strftime('%Y%m%d%H%M%S')
copy_name = f'{noext}-{timestamp}.filetimelapse{extension}'
shutil.copy(filepath, copy_name)
last_hash = new_hash
print(copy_name, new_hash)
time.sleep(rate)
def filetimelapse_argparse(args):
return filetimelapse(args.filepath, args.rate)
def main(argv):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('filepath')
parser.add_argument('--rate', dest='rate', default=None, required=True, type=int)
parser.set_defaults(func=filetimelapse_argparse)
args = parser.parse_args(argv)
args.func(args)
if __name__ == '__main__':
raise SystemExit(main(sys.argv[1:]))