diff --git a/backup.py b/backup.py index 4a5ad57..f8266ee 100644 --- a/backup.py +++ b/backup.py @@ -1,18 +1,6 @@ import sys -from src import Database, FileSystem -class Backup(FileSystem): - def __init__(self, argv): - super().__init__() - self.db = Database() +from src import Backup - def backup(self, obj: list) -> bool: - db_response = self.db.check_obj(obj) - return True - - def backup_all(self): - for item in self.all(): - self.backup(item) - -Backup(sys.argv).backup_all() +Backup().backup_all() print("OK") \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py index c9d748d..5c467e0 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -3,6 +3,7 @@ from dotenv import load_dotenv from .glob import file_exists from .db import Database from .fs import FileSystem +from .backup import Backup if not file_exists(".env"): raise FileNotFoundError("Environment variable file does not exist. Copy '.env.example' to '.env'") diff --git a/src/backup.py b/src/backup.py new file mode 100644 index 0000000..ac2d259 --- /dev/null +++ b/src/backup.py @@ -0,0 +1,25 @@ +from typing import Union + +from . import Database, FileSystem + +class Backup(FileSystem): + def __init__(self): + super().__init__() + self.db = Database() + + def backup_item(self, item: Union[list, str]) -> bool: + if isinstance(item, str): + item = self.get_item(item) + + # Check item against db if it has changed + db_resp = self.db.check_item(item) + if not db_resp: + return True + + self.db.set_item(item) + + return True + + def backup_all(self): + for item in self.all(): + self.backup_item(item) \ No newline at end of file diff --git a/src/db/config.sql b/src/db/config.sql index 6b96c13..e0d4e63 100644 --- a/src/db/config.sql +++ b/src/db/config.sql @@ -11,6 +11,6 @@ CREATE TABLE manifest ( INSERT INTO flags VALUES - ("CALC_CHECKSUM", 1), + ("ZIP", 1), ("BUCKET_OK", 0), ("INIT", 1); \ No newline at end of file diff --git a/src/db/database.py b/src/db/database.py index c2afba3..9b61ff9 100644 --- a/src/db/database.py +++ b/src/db/database.py @@ -4,9 +4,27 @@ class Database(SQLite): def __init__(self): super().__init__() - # Test if a candidate item should be backed up - def check_item(self, obj: list) -> bool: - sql = f"SELECT anchor, mtime, chksum FROM manifest WHERE anchor = '{obj.anchor}'" - data = self.query(sql) + def item_exists(self, item: list) -> bool: + sql = f"SELECT anchor FROM manifest WHERE anchor = '{item[0]}'" + res = self.query(sql) - return True \ No newline at end of file + return res + + # Test if a candidate item should be backed up + def check_item(self, item: list) -> bool: + sql = f"SELECT anchor, mtime, chksum FROM manifest WHERE anchor = '{item[0]}'" + res = self.query(sql) + if not res: + return True + + return res + + # Insert or update item in database + def set_item(self, item: list) -> bool: + values = ",".join(item) + sql = f"INSERT INTO manifest (anchor, mtime, chksum) VALUES ({values})" + if not self.item_exists(item): + sql = f"UPDATE manifest SET anchor = '{item[0]}', mtime = '{item[1]}', chksum = '{item[2]}' WHERE anchor = '{item[0]}'" + res = self.query(sql) + + return res \ No newline at end of file diff --git a/src/fs/fs.py b/src/fs/fs.py index 8473d30..da74572 100644 --- a/src/fs/fs.py +++ b/src/fs/fs.py @@ -11,20 +11,22 @@ class FileSystem: def get_path() -> str: return os.getenv("SOURCE_FOLDER") + # Calculate a CRC32 checksum of provided data @staticmethod def chksum(data: str) -> str: - return zlib.crc32(data) + encoded = data.encode("utf-8") + return zlib.crc32(encoded) # Get metadata from candidate file or folder - def make_obj(self, anchor: str) -> list: - mtime = os.path.getmtime(anchor) - if os.path.isdir(anchor): + def get_item(self, path: list) -> list: + mtime = os.path.getmtime(path) + chksum = FileSystem.chksum(path + str(mtime)) + data = [path, mtime, chksum] + return data - data = [anchor, mtime, chksum] - return obj - + # Get all second-level files and folders for path def all(self) -> list: - content = os.listdir(self.path) - content = list(map(self.make_obj, content)) + content = [os.path.join(self.path, f) for f in os.listdir(self.path)] + content = list(map(self.get_item, content)) return content \ No newline at end of file