diff --git a/euclid/database/database.py b/euclid/database/database.py index c58d5e5..6b2893b 100644 --- a/euclid/database/database.py +++ b/euclid/database/database.py @@ -13,6 +13,7 @@ from database.models.development_planning import DevelopmentPlanning from database.models.development_steps import DevelopmentSteps from database.models.environment_setup import EnvironmentSetup from database.models.development import Development +from database.models.file_snapshot import FileSnapshot def save_user(user_id, email="email", password="password"): @@ -139,13 +140,14 @@ def create_tables(): DevelopmentPlanning, DevelopmentSteps, EnvironmentSetup, - Development + Development, + FileSnapshot, ]) def drop_tables(): with database.atomic(): - for table in [User, App, ProjectDescription, UserStories, UserTasks, Architecture, DevelopmentPlanning, DevelopmentSteps, EnvironmentSetup, Development]: + for table in [User, App, ProjectDescription, UserStories, UserTasks, Architecture, DevelopmentPlanning, DevelopmentSteps, EnvironmentSetup, Development, FileSnapshot]: database.execute_sql(f'DROP TABLE IF EXISTS "{table._meta.table_name}" CASCADE') diff --git a/euclid/database/models/file_snapshot.py b/euclid/database/models/file_snapshot.py new file mode 100644 index 0000000..35d5c3a --- /dev/null +++ b/euclid/database/models/file_snapshot.py @@ -0,0 +1,15 @@ +from peewee import * + +from database.models.components.base_models import BaseModel +from database.models.development_steps import DevelopmentSteps + +class FileSnapshot(BaseModel): + development_step = ForeignKeyField(DevelopmentSteps, backref='files') + name = CharField() + content = TextField() + + class Meta: + db_table = 'file_snapshot' + indexes = ( + (('development_step', 'name'), True), + ) \ No newline at end of file diff --git a/euclid/helpers/Project.py b/euclid/helpers/Project.py index 64cec9a..e8a74d4 100644 --- a/euclid/helpers/Project.py +++ b/euclid/helpers/Project.py @@ -1,4 +1,6 @@ +import os from const.common import IGNORE_FOLDERS +from helpers.files import get_files_content from helpers.cli import build_directory_tree from helpers.agents.CodeMonkey import CodeMonkey from helpers.agents.TechLead import TechLead @@ -7,6 +9,9 @@ from helpers.agents.Developer import Developer from helpers.agents.Architect import Architect from helpers.agents.ProductOwner import ProductOwner +from database.models.development_steps import DevelopmentSteps +from database.models.file_snapshot import FileSnapshot + class Project: def __init__(self, args, name=None, description=None, user_stories=None, user_tasks=None, architecture=None, development_plan=None, current_step=None): self.args = args @@ -57,3 +62,29 @@ class Project: def get_full_file_path(self, file_name): return self.root_path + '/' + file_name + + def save_files_snapshot(self, development_step_id): + files = get_files_content(self.root_path, ignore=IGNORE_FOLDERS) + development_step, created = DevelopmentSteps.get_or_create(id=development_step_id) + + for file in files: + file_snapshot, created = FileSnapshot.get_or_create( + development_step=development_step, + name=file['name'], + defaults={'content': file.get('content', '')} + ) + file_snapshot.content = content=file['content'] + file_snapshot.save() + + def restore_files(self, development_step_id): + development_step = DevelopmentSteps.get(DevelopmentSteps.id == development_step_id) + file_snapshots = FileSnapshot.select().where(FileSnapshot.development_step == development_step) + + for file_snapshot in file_snapshots: + full_path = self.root_path + '/' + file_snapshot.name + # Ensure directory exists + os.makedirs(os.path.dirname(full_path), exist_ok=True) + + # Write/overwrite the file with its content + with open(full_path, 'w', encoding='utf-8') as f: + f.write(file_snapshot.content) \ No newline at end of file diff --git a/euclid/helpers/files.py b/euclid/helpers/files.py index dca52f4..b42e1aa 100644 --- a/euclid/helpers/files.py +++ b/euclid/helpers/files.py @@ -1,7 +1,34 @@ from termcolor import colored +import os + +from database.models.development_steps import DevelopmentSteps +from database.models.file_snapshot import FileSnapshot def update_file(path, new_content): with open(path, 'w') as file: file.write(new_content) print(colored(f"Updated file {path}", "green")) + +def get_files_content(directory, ignore=[]): + return_array = [] + + for root, dirs, files in os.walk(directory): + # Ignore directories + dirs[:] = [d for d in dirs if d not in ignore] + + for file in files: + if file in ignore: + continue + + path = os.path.join(root, file) + with open(path, 'r', encoding='utf-8', errors='ignore') as f: + file_content = f.read() + + return_array.append({ + 'name': path.replace(directory + '/', ''), + 'content': file_content + }) + + return return_array +