mirror of
https://codeberg.org/vlw/cloud-backup.git
synced 2025-09-14 10:03:40 +02:00
wip(22w8f): add folder walker
This commit is contained in:
parent
3f51be9e55
commit
b2eae61ec1
6 changed files with 63 additions and 29 deletions
16
backup.py
16
backup.py
|
@ -1,18 +1,6 @@
|
||||||
import sys
|
import sys
|
||||||
from src import Database, FileSystem
|
|
||||||
|
|
||||||
class Backup(FileSystem):
|
from src import Backup
|
||||||
def __init__(self, argv):
|
|
||||||
super().__init__()
|
|
||||||
self.db = Database()
|
|
||||||
|
|
||||||
def backup(self, obj: list) -> bool:
|
Backup().backup_all()
|
||||||
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()
|
|
||||||
print("OK")
|
print("OK")
|
|
@ -3,6 +3,7 @@ from dotenv import load_dotenv
|
||||||
from .glob import file_exists
|
from .glob import file_exists
|
||||||
from .db import Database
|
from .db import Database
|
||||||
from .fs import FileSystem
|
from .fs import FileSystem
|
||||||
|
from .backup import Backup
|
||||||
|
|
||||||
if not file_exists(".env"):
|
if not file_exists(".env"):
|
||||||
raise FileNotFoundError("Environment variable file does not exist. Copy '.env.example' to '.env'")
|
raise FileNotFoundError("Environment variable file does not exist. Copy '.env.example' to '.env'")
|
||||||
|
|
25
src/backup.py
Normal file
25
src/backup.py
Normal file
|
@ -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)
|
|
@ -11,6 +11,6 @@ CREATE TABLE manifest (
|
||||||
|
|
||||||
INSERT INTO flags
|
INSERT INTO flags
|
||||||
VALUES
|
VALUES
|
||||||
("CALC_CHECKSUM", 1),
|
("ZIP", 1),
|
||||||
("BUCKET_OK", 0),
|
("BUCKET_OK", 0),
|
||||||
("INIT", 1);
|
("INIT", 1);
|
|
@ -4,9 +4,27 @@ class Database(SQLite):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
# Test if a candidate item should be backed up
|
def item_exists(self, item: list) -> bool:
|
||||||
def check_item(self, obj: list) -> bool:
|
sql = f"SELECT anchor FROM manifest WHERE anchor = '{item[0]}'"
|
||||||
sql = f"SELECT anchor, mtime, chksum FROM manifest WHERE anchor = '{obj.anchor}'"
|
res = self.query(sql)
|
||||||
data = self.query(sql)
|
|
||||||
|
|
||||||
return True
|
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
|
20
src/fs/fs.py
20
src/fs/fs.py
|
@ -11,20 +11,22 @@ class FileSystem:
|
||||||
def get_path() -> str:
|
def get_path() -> str:
|
||||||
return os.getenv("SOURCE_FOLDER")
|
return os.getenv("SOURCE_FOLDER")
|
||||||
|
|
||||||
|
# Calculate a CRC32 checksum of provided data
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def chksum(data: str) -> str:
|
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
|
# Get metadata from candidate file or folder
|
||||||
def make_obj(self, anchor: str) -> list:
|
def get_item(self, path: list) -> list:
|
||||||
mtime = os.path.getmtime(anchor)
|
mtime = os.path.getmtime(path)
|
||||||
if os.path.isdir(anchor):
|
chksum = FileSystem.chksum(path + str(mtime))
|
||||||
|
|
||||||
|
data = [path, mtime, chksum]
|
||||||
|
return data
|
||||||
|
|
||||||
data = [anchor, mtime, chksum]
|
# Get all second-level files and folders for path
|
||||||
return obj
|
|
||||||
|
|
||||||
def all(self) -> list:
|
def all(self) -> list:
|
||||||
content = os.listdir(self.path)
|
content = [os.path.join(self.path, f) for f in os.listdir(self.path)]
|
||||||
content = list(map(self.make_obj, content))
|
content = list(map(self.get_item, content))
|
||||||
return content
|
return content
|
Loading…
Add table
Reference in a new issue