Add restore (any) feature
This commit is contained in:
@@ -76,6 +76,19 @@ def strip_mirro_header(text: str) -> str:
|
|||||||
return "".join(lines[i:])
|
return "".join(lines[i:])
|
||||||
|
|
||||||
|
|
||||||
|
def extract_original_path(backup_text: str) -> Path | None:
|
||||||
|
"""
|
||||||
|
Extract the original file path from a mirro backup header.
|
||||||
|
"""
|
||||||
|
for line in backup_text.splitlines():
|
||||||
|
if line.startswith("# Original file:"):
|
||||||
|
path = line.split(":", 1)[1].strip()
|
||||||
|
return Path(path).expanduser()
|
||||||
|
if line.strip() == "":
|
||||||
|
break
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="Safely edit a file with automatic original backup if changed."
|
description="Safely edit a file with automatic original backup if changed."
|
||||||
@@ -107,6 +120,13 @@ def main():
|
|||||||
help="Restore the last backup of the given file and exit",
|
help="Restore the last backup of the given file and exit",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--restore",
|
||||||
|
metavar="BACKUP",
|
||||||
|
type=str,
|
||||||
|
help="Restore the given backup file and exit",
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--prune-backups",
|
"--prune-backups",
|
||||||
nargs="?",
|
nargs="?",
|
||||||
@@ -334,6 +354,45 @@ def main():
|
|||||||
print(f"Restored {target} from backup {last.name}")
|
print(f"Restored {target} from backup {last.name}")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if args.restore:
|
||||||
|
backup_arg = args.restore
|
||||||
|
backup_dir = Path(args.backup_dir).expanduser().resolve()
|
||||||
|
|
||||||
|
# Resolve backup path
|
||||||
|
if os.path.isabs(backup_arg) or backup_arg.startswith("~"):
|
||||||
|
backup_path = Path(backup_arg).expanduser().resolve()
|
||||||
|
else:
|
||||||
|
backup_path = backup_dir / backup_arg
|
||||||
|
|
||||||
|
if not backup_path.exists():
|
||||||
|
print(f"Backup not found: {backup_path}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
raw = backup_path.read_text(encoding="utf-8", errors="replace")
|
||||||
|
|
||||||
|
target = extract_original_path(raw)
|
||||||
|
if not target:
|
||||||
|
print(
|
||||||
|
"Could not determine original file location from backup header."
|
||||||
|
)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
restored_text = strip_mirro_header(raw)
|
||||||
|
|
||||||
|
# Permission checks
|
||||||
|
if target.exists() and not os.access(target, os.W_OK):
|
||||||
|
print(f"Need elevated privileges to restore {target}")
|
||||||
|
return 1
|
||||||
|
if not target.exists() and not os.access(target.parent, os.W_OK):
|
||||||
|
print(f"Need elevated privileges to create {target}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
target.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
target.write_text(restored_text, encoding="utf-8")
|
||||||
|
|
||||||
|
print(f"Restored {target} from backup {backup_path.name}")
|
||||||
|
return 0
|
||||||
|
|
||||||
if args.prune_backups is not None:
|
if args.prune_backups is not None:
|
||||||
mode = args.prune_backups
|
mode = args.prune_backups
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user