atles / backup_new_memory_to_git.py
spartan8806's picture
ATLES codebase - Source code only
99b8067
#!/usr/bin/env python3
"""
Backup New Memory Directory to GitHub
Backs up files from the new memory/ directory to git (excluding .db files).
Automatically tracks new files as they're created.
"""
import subprocess
import sys
from pathlib import Path
from datetime import datetime
def run_git_command(cmd: list[str], check: bool = True) -> subprocess.CompletedProcess:
"""Run a git command."""
try:
result = subprocess.run(
["git"] + cmd,
capture_output=True,
text=True,
check=check
)
return result
except subprocess.CalledProcessError as e:
print(f"Git command failed: {' '.join(cmd)}")
print(f"Error: {e.stderr}")
if check:
raise
return e
def check_git_repo() -> bool:
"""Check if we're in a git repository."""
result = run_git_command(["rev-parse", "--git-dir"], check=False)
return result.returncode == 0
def backup_new_memory_files() -> dict[str, any]:
"""Backup new memory files to git."""
memory_dir = Path("memory")
if not memory_dir.exists():
print("⚠️ Memory directory does not exist yet. It will be created when ATLES uses it.")
return {
"success": False,
"error": "Memory directory does not exist",
"files_backed_up": []
}
backup_info = {
"timestamp": datetime.now().isoformat(),
"files_backed_up": [],
"files_skipped": []
}
# Find all files in memory directory (excluding .db files and other excluded types)
all_files = list(memory_dir.rglob("*"))
excluded_extensions = {'.db', '.db-journal', '.db-wal', '.db-shm'}
files_to_backup = [
f for f in all_files
if f.is_file() and f.suffix.lower() not in excluded_extensions
]
if not files_to_backup:
print("ℹ️ No files to backup in memory/ directory (excluding .db files)")
print(" New memory files will be backed up automatically when created.")
return backup_info
print(f"Found {len(files_to_backup)} files to backup:")
for file_path in files_to_backup:
relative_path = file_path.relative_to(Path("."))
print(f" - {relative_path}")
# Force add to git (even if in .gitignore)
result = run_git_command(["add", "-f", str(relative_path)], check=False)
if result.returncode == 0:
backup_info["files_backed_up"].append(str(relative_path))
else:
backup_info["files_skipped"].append(str(relative_path))
print(f" ⚠️ Could not add: {result.stderr.strip()}")
return backup_info
def commit_backup(backup_info: dict[str, any]) -> bool:
"""Commit the backup."""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
commit_message = f"Backup new memory files: {timestamp}\n\nFiles backed up: {len(backup_info['files_backed_up'])}"
# Check if there are changes to commit
result = run_git_command(["status", "--porcelain"], check=False)
if not result.stdout.strip():
print("\nℹ️ No changes to commit.")
return False
# Commit
run_git_command(["commit", "-m", commit_message])
print(f"\n✅ Committed backup: {len(backup_info['files_backed_up'])} files")
return True
def push_backup() -> bool:
"""Push backup to remote."""
print("\nPushing backup to remote...")
result = run_git_command(["push", "origin", "main"], check=False)
if result.returncode == 0:
print("✅ Pushed backup to remote")
return True
else:
print(f"⚠️ Could not push to remote: {result.stderr}")
print("Backup is saved locally, you can push manually later")
return False
def update_gitignore_for_new_memory():
"""Update .gitignore to allow new memory files (but keep .db excluded)."""
gitignore_path = Path(".gitignore")
if not gitignore_path.exists():
return
content = gitignore_path.read_text(encoding='utf-8')
# Check if we need to add exception for new memory files
if "memory/" in content and "!memory/*.json" not in content:
print("\n📝 Updating .gitignore to allow JSON files in memory/...")
# Find the memory/ line and add exception after it
lines = content.split('\n')
new_lines = []
memory_found = False
for line in lines:
new_lines.append(line)
if line.strip() == "memory/" and not memory_found:
# Add exceptions for non-db files
new_lines.append("!memory/*.json")
new_lines.append("!memory/*.txt")
new_lines.append("!memory/*.yaml")
new_lines.append("!memory/*.yml")
memory_found = True
gitignore_path.write_text('\n'.join(new_lines), encoding='utf-8')
print("✅ Updated .gitignore")
return True
return False
def main():
"""Main backup function."""
print("=" * 60)
print("Backup New Memory Directory to GitHub")
print("=" * 60)
print()
# Check if in git repo
if not check_git_repo():
print("❌ Error: Not in a git repository!")
sys.exit(1)
# Check current branch
result = run_git_command(["branch", "--show-current"])
current_branch = result.stdout.strip()
print(f"Current branch: {current_branch}")
print()
# Update .gitignore if needed
update_gitignore_for_new_memory()
# Backup memory files
print("Scanning memory/ directory...")
backup_info = backup_new_memory_files()
if not backup_info.get("files_backed_up"):
print("\n✅ Setup complete!")
print(" New memory files will be backed up automatically when created.")
print(" Run this script again after ATLES creates new memory files.")
return
print(f"\n✅ Found {len(backup_info['files_backed_up'])} files to backup")
if backup_info.get("files_skipped"):
print(f"⚠️ Skipped {len(backup_info['files_skipped'])} files")
# Commit backup
if commit_backup(backup_info):
# Try to push
push_backup()
print()
print("=" * 60)
print("✅ Backup complete!")
print("=" * 60)
print()
print("Note: .db files are excluded (as per .gitignore)")
print("Only non-database files from memory/ are backed up")
if __name__ == "__main__":
main()