Revert "Add version control system functionality with branch management, history tracking, and merge operations"

This reverts commit f3d28817a5.
This commit is contained in:
pacnpal
2025-02-08 17:37:30 -05:00
parent 03f9df4bab
commit 71b73522ae
125 changed files with 617 additions and 15830 deletions

View File

@@ -1,43 +1,20 @@
# history_tracking/models.py
from django.db import models
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.db.models.fields.related import RelatedField
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.fields import GenericForeignKey
from simple_history.models import HistoricalRecords
from .mixins import HistoricalChangeMixin
from .historical_fields import HistoricalFieldsMixin
from typing import Any, Type, TypeVar, cast, Optional, List
from typing import Any, Type, TypeVar, cast
from django.db.models import QuerySet
from django.core.exceptions import ValidationError
from django.utils import timezone
T = TypeVar('T', bound=models.Model)
User = get_user_model()
class HistoricalModel(models.Model, HistoricalFieldsMixin):
class HistoricalModel(models.Model):
"""Abstract base class for models with history tracking"""
id = models.BigAutoField(primary_key=True)
@classmethod
def __init_subclass__(cls, **kwargs):
"""Initialize subclass with proper configuration."""
super().__init_subclass__(**kwargs)
# Mark historical models
if cls.__name__.startswith('Historical'):
cls._is_historical_model = True
# Remove any inherited generic relations
for field in list(cls._meta.private_fields):
if isinstance(field, GenericRelation):
cls._meta.private_fields.remove(field)
else:
cls._is_historical_model = False
history = HistoricalRecords(
history: HistoricalRecords = HistoricalRecords(
inherit=True,
bases=[HistoricalChangeMixin],
excluded_fields=['comments', 'comment_threads', 'photos', 'reviews'],
use_base_model_db=True # Use base model's db
bases=(HistoricalChangeMixin,)
)
class Meta:
@@ -70,233 +47,3 @@ class HistoricalSlug(models.Model):
def __str__(self) -> str:
return f"{self.content_type} - {self.object_id} - {self.slug}"
class VersionBranch(models.Model):
"""Represents a version control branch for tracking parallel development"""
name = models.CharField(max_length=255, unique=True)
parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE, related_name='children')
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
metadata = models.JSONField(default=dict, blank=True)
is_active = models.BooleanField(default=True)
lock_status = models.JSONField(
default=dict,
help_text="Current lock status: {user: ID, expires: datetime, reason: str}"
)
lock_history = models.JSONField(
default=list,
help_text="History of lock operations: [{user: ID, action: lock/unlock, timestamp: datetime, reason: str}]"
)
class Meta:
ordering = ['-created_at']
indexes = [
models.Index(fields=['name']),
models.Index(fields=['parent']),
models.Index(fields=['created_at']),
]
def __str__(self) -> str:
return f"{self.name} ({'active' if self.is_active else 'inactive'})"
def clean(self) -> None:
# Prevent circular references
if self.parent and self.pk:
branch = self.parent
while branch:
if branch.pk == self.pk:
raise ValidationError("Circular branch reference detected")
branch = branch.parent
class VersionTag(models.Model):
"""Tags specific versions for reference (releases, milestones, etc)"""
name = models.CharField(max_length=255, unique=True)
branch = models.ForeignKey(VersionBranch, on_delete=models.CASCADE, related_name='tags')
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
historical_instance = GenericForeignKey('content_type', 'object_id')
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
metadata = models.JSONField(default=dict, blank=True)
comparison_metadata = models.JSONField(
default=dict,
help_text="Stores diff statistics and comparison results"
)
class Meta:
ordering = ['-created_at']
indexes = [
models.Index(fields=['name']),
models.Index(fields=['branch']),
models.Index(fields=['created_at']),
models.Index(fields=['content_type', 'object_id']),
]
def __str__(self) -> str:
return f"{self.name} ({self.branch.name})"
class HistoricalCommentThread(models.Model):
"""Represents a thread of comments specific to historical records and version control"""
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='created_threads')
anchor = models.JSONField(
default=dict,
help_text="Anchoring information: {line_start: int, line_end: int, file_path: str}"
)
is_resolved = models.BooleanField(default=False)
resolved_by = models.ForeignKey(
User,
on_delete=models.SET_NULL,
null=True,
related_name='resolved_threads'
)
resolved_at = models.DateTimeField(null=True, blank=True)
class Meta:
ordering = ['-created_at']
indexes = [
models.Index(fields=['content_type', 'object_id']),
models.Index(fields=['created_at']),
models.Index(fields=['is_resolved']),
]
def __str__(self) -> str:
return f"Comment Thread {self.pk} on {self.content_type}"
class Comment(models.Model):
"""Individual comment within a thread"""
thread = models.ForeignKey(HistoricalCommentThread, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
mentioned_users = models.ManyToManyField(
User,
related_name='mentioned_in_comments',
blank=True
)
parent_comment = models.ForeignKey(
'self',
on_delete=models.CASCADE,
null=True,
blank=True,
related_name='replies'
)
class Meta:
ordering = ['created_at']
def __str__(self) -> str:
return f"Comment {self.pk} by {self.author}"
def extract_mentions(self) -> None:
"""Extract @mentions from comment content and update mentioned_users"""
# Simple @username extraction - could be enhanced with regex
mentioned = [
word[1:] for word in self.content.split()
if word.startswith('@') and len(word) > 1
]
if mentioned:
users = User.objects.filter(username__in=mentioned)
self.mentioned_users.set(users)
class ChangeSet(models.Model):
"""Groups related changes together for atomic version control operations"""
branch = models.ForeignKey(VersionBranch, on_delete=models.CASCADE, related_name='changesets')
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
description = models.TextField(blank=True)
metadata = models.JSONField(default=dict, blank=True)
dependencies = models.JSONField(default=dict, blank=True)
status = models.CharField(
max_length=20,
choices=[
('draft', 'Draft'),
('pending_approval', 'Pending Approval'),
('approved', 'Approved'),
('rejected', 'Rejected'),
('applied', 'Applied'),
('failed', 'Failed'),
('reverted', 'Reverted')
],
default='draft'
)
approval_state = models.JSONField(
default=list,
help_text="List of approval stages and their status"
)
approval_history = models.JSONField(
default=list,
help_text="History of approval actions and decisions"
)
required_approvers = models.ManyToManyField(
User,
related_name='pending_approvals',
blank=True
)
approval_policy = models.CharField(
max_length=20,
choices=[
('sequential', 'Sequential'),
('parallel', 'Parallel')
],
default='sequential'
)
approval_deadline = models.DateTimeField(
null=True,
blank=True,
help_text="Optional deadline for approvals"
)
# Instead of directly relating to HistoricalRecord, use GenericForeignKey
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
historical_instance = GenericForeignKey('content_type', 'object_id')
class Meta:
ordering = ['-created_at']
indexes = [
models.Index(fields=['branch']),
models.Index(fields=['created_at']),
models.Index(fields=['status']),
models.Index(fields=['content_type', 'object_id']),
]
def __str__(self) -> str:
return f"ChangeSet {self.pk} ({self.branch.name} - {self.status})"
def apply(self) -> None:
"""Apply the changeset to the target branch"""
if self.status != 'pending':
raise ValidationError(f"Cannot apply changeset with status: {self.status}")
try:
# Apply changes through the historical instance
if self.historical_instance:
instance = self.historical_instance.instance
if instance:
instance.save()
self.status = 'applied'
except Exception as e:
self.status = 'failed'
self.metadata['error'] = str(e)
self.save()
def revert(self) -> None:
"""Revert the changes in this changeset"""
if self.status != 'applied':
raise ValidationError(f"Cannot revert changeset with status: {self.status}")
try:
# Revert changes through the historical instance
if self.historical_instance:
instance = self.historical_instance.instance
if instance:
instance.save()
self.status = 'reverted'
except Exception as e:
self.metadata['revert_error'] = str(e)
self.save()