mirror of
https://git.srhtnin.garden/sarah/SaraSuite.git
synced 2026-10-13 18:18:12 +02:00
Initial commit
This commit is contained in:
commit
bea0f43947
25 files changed
+2327
No files matched your search
+76
@@ -0,0 +1,76 @@
|
||||
"""Receipts: the record of exactly what an install placed, so updates know
|
||||
what they're replacing and removal can take every piece back out."""
|
||||
|
||||
from dataclasses import asdict, dataclass, field
|
||||
from pathlib import Path
|
||||
|
||||
import tomlkit
|
||||
|
||||
from Core import ReceiptsDir
|
||||
|
||||
|
||||
@dataclass
|
||||
class PlacedFile:
|
||||
Path: str
|
||||
Kind: str # "Template", "Config" or "ConfigNew" (a .new file left beside a config)
|
||||
Root: bool = False
|
||||
# Where a file that already existed at Path (not placed by SaraSuite) was
|
||||
# moved to. It's put back when this program is removed.
|
||||
Displaced: str = ""
|
||||
|
||||
|
||||
@dataclass
|
||||
class IniRecord:
|
||||
File: str
|
||||
Section: str
|
||||
Key: str
|
||||
Value: str
|
||||
HadPrevious: bool = False
|
||||
Previous: str = ""
|
||||
|
||||
|
||||
@dataclass
|
||||
class Receipt:
|
||||
Name: str
|
||||
Version: str = ""
|
||||
Commit: str = ""
|
||||
ManifestHash: str = ""
|
||||
RequirementsHash: str = ""
|
||||
InstalledAt: str = ""
|
||||
UpdatedAt: str = ""
|
||||
# False while an install/update is still running, or if it failed partway.
|
||||
# The files it lists are still real, so Remove still cleans them up.
|
||||
Complete: bool = False
|
||||
Options: dict[str, bool] = field(default_factory=dict)
|
||||
Answers: dict[str, str] = field(default_factory=dict)
|
||||
Files: list[PlacedFile] = field(default_factory=list)
|
||||
IniEdits: list[IniRecord] = field(default_factory=list)
|
||||
EnabledServices: list[str] = field(default_factory=list)
|
||||
|
||||
@property
|
||||
def FilePath(self) -> Path:
|
||||
return ReceiptsDir / f"{self.Name}.toml"
|
||||
|
||||
def FindFile(self, TargetPath: str) -> PlacedFile | None:
|
||||
return next((File for File in self.Files if File.Path == TargetPath), None)
|
||||
|
||||
def FindIni(self, File: str, Section: str, Key: str) -> IniRecord | None:
|
||||
return next(
|
||||
(Edit for Edit in self.IniEdits if (Edit.File, Edit.Section, Edit.Key) == (File, Section, Key)),
|
||||
None,
|
||||
)
|
||||
|
||||
def Save(self) -> None:
|
||||
ReceiptsDir.mkdir(parents=True, exist_ok=True)
|
||||
self.FilePath.write_text(tomlkit.dumps(asdict(self)))
|
||||
|
||||
|
||||
def LoadReceipt(Name: str) -> Receipt | None:
|
||||
ReceiptPath = ReceiptsDir / f"{Name}.toml"
|
||||
if not ReceiptPath.exists():
|
||||
return None
|
||||
Data = tomlkit.parse(ReceiptPath.read_text()).unwrap()
|
||||
Data["Files"] = [PlacedFile(**Item) for Item in Data.get("Files", [])]
|
||||
Data["IniEdits"] = [IniRecord(**Item) for Item in Data.get("IniEdits", [])]
|
||||
Known = set(Receipt.__dataclass_fields__)
|
||||
return Receipt(**{Key: Value for Key, Value in Data.items() if Key in Known})
|
||||
Reference in new issue
Block a user