diff --git a/backup.py b/backup.py index 8120d6a..98d1a56 100644 --- a/backup.py +++ b/backup.py @@ -37,7 +37,6 @@ class Backup: return self - def local(self, key, bdd=None, save_location=None): self.key = key self.save_mode = LOCAL @@ -49,11 +48,32 @@ class Backup: return self + def update(self, path, recurse=True): + self.clear(path, recurse=recurse) + self.__save(path, recurse=recurse) + return self def save(self, path, recurse=True): self.__save(path, recurse=recurse) return self + def clear(self, path, recurse=True): + files = self.bdd.get_files(path) + if not recurse: + files = [f for f in files if (pathlib.Path(f['path'])).parent == pathlib.Path(path)] + for file in files: + file_path = pathlib.Path(file['path']) + if not os.path.isfile(file_path): + # delete it + print("Clear deleted file :", file['path']) + self.bdd.delete_file(file) + orphans = self.bdd.get_orphan_crypt() + for orphan in orphans: + # Delete orphan crypt + self.__delete_file(str(orphan['id']).zfill(ZFILL)) + self.bdd.delete_crypt(orphan['id']) + return self + def __save(self, path, recurse=True): tarball_size = parse_size(self.tarball_size) files = [] @@ -73,8 +93,8 @@ class Backup: print("Proceed", uri, ' ==> ', crypt_id) enc = crypt(compress(uri), self.key) self.bdd.set_crypt_attr(crypt_id, compress_mode="gz", sha1sum=get_hash(enc)) - print(" Size : ", get_size(enc)) - self.upload_file(enc, file_name=str(crypt_id).zfill(ZFILL)) + print(" Size :", get_size(enc)) + self.__upload_file(enc, file_name=str(crypt_id).zfill(ZFILL)) else: files.append({'name': f, 'path': pathlib.Path(uri).as_posix(), @@ -90,14 +110,14 @@ class Backup: tarball = tar([file['path'] for file in files]) enc = crypt(compress(tarball), self.key) self.bdd.set_crypt_attr(crypt_id, compress_mode="tar.gz", sha1sum=get_hash(enc)) - print(" Size : ", get_size(enc)) - self.upload_file(enc, file_name=str(crypt_id).zfill(ZFILL)) + print(" Size :", get_size(enc)) + self.__upload_file(enc, file_name=str(crypt_id).zfill(ZFILL)) def recover_file(self, paths, parents=False, save_path=os.getcwd()): files = self.bdd.get_crypt_name(paths) for file in files: if file['crypt_id'] is not None: - encrypted_file = self.download_file(str(file['crypt_id']).zfill(ZFILL)) + encrypted_file = self.__download_file(str(file['crypt_id']).zfill(ZFILL)) file_hash = get_hash(encrypted_file) if file['sha1sum'] == file_hash: if parents: @@ -109,13 +129,13 @@ class Backup: print("{} {}".format(file_hash, "File")) print() - def upload_file(self, file, file_name): + def __upload_file(self, file, file_name): if self.save_mode == BACKBLAZE: self.buk.upload_bytes(file.read(), file_name) elif self.save_mode == LOCAL: save(file, os.path.join(self.save_location, file_name)) - def download_file(self, file): + def __download_file(self, file): dl = tempfile.SpooledTemporaryFile() if self.save_mode == BACKBLAZE: self.buk.download_file_by_name(file).save(dl) @@ -124,6 +144,16 @@ class Backup: dl.write(infile.read()) return dl + def __delete_file(self, file): + if self.save_mode == BACKBLAZE: + truc = self.buk.get_file_info_by_name(file) + #self.buk.delete_file_version(None, file) + elif self.save_mode == LOCAL: + try: + os.remove(os.path.join(self.save_location, file)) + except FileNotFoundError: + print("Fichier", file, "introuvable") + def get_size(in_file): if type(in_file) is str: @@ -325,6 +355,31 @@ class DataBase: AND path IN ({path})""".format(**params)) return id + def get_files(self, path): + cursor = self.conn.cursor() + cursor.execute("""SELECT id, name, path FROM files WHERE path LIKE '{path}%'""" + .format(path=path)) + list_file = cursor.fetchall() + return list_file + + def delete_file(self, file): + cursor = self.conn.cursor() + cursor.execute("""DELETE FROM files WHERE id='{id}' AND name='{name}' AND path='{path}'""" + .format(**file)) + self.conn.commit() + + def get_orphan_crypt(self): + cursor = self.conn.cursor() + cursor.execute("""SELECT crypt.id FROM crypt + LEFT JOIN files ON files.crypt_id = crypt.id + WHERE files.id IS NULL""") + return cursor.fetchall() + + def delete_crypt(self, crypt_id): + cursor = self.conn.cursor() + cursor.execute("""DELETE FROM crypt WHERE id=?""", (crypt_id,)) + self.conn.commit() + def exist(self, file): cursor = self.conn.cursor() cursor.execute("""SELECT EXISTS (SELECT 1 FROM files WHERE name=? AND path=?) as exist""", @@ -346,7 +401,8 @@ class DataBase: def set_crypt_attr(self, crypt_id, compress_mode=None, sha1sum=None): cursor = self.conn.cursor() - cursor.execute("""UPDATE crypt SET compress_mode='{mode}', sha1sum='{sum}' WHERE id='{id}'""".format(id=crypt_id, mode=compress_mode, sum=sha1sum)) + cursor.execute("""UPDATE crypt SET compress_mode='{mode}', sha1sum='{sum}' WHERE id='{id}'""" + .format(id=crypt_id, mode=compress_mode, sum=sha1sum)) self.conn.commit() def add(self, list_file): diff --git a/main.py b/main.py index c5cf32b..149bc10 100644 --- a/main.py +++ b/main.py @@ -23,7 +23,11 @@ bdd = "bdd.db" #bck = Backup().backblaze(key, bdd=bdd, app_key_id=application_key_id, app_key=application_key, bucket_id=bucket_id) bck = Backup().local(key, bdd=bdd, save_location="crypted") +bck.save("share", recurse=False) + rootdir = "test" -bck.save(rootdir).save("share", recurse=False) +# bck.clear(rootdir, recurse=False) +# bck.save(rootdir) +bck.update(rootdir) bck.recover_file(paths=["test\\tmp597556213336506368.jpg", "share/archive.tar"], save_path="recovered")