128 lines
3.7 KiB
Python
128 lines
3.7 KiB
Python
from typing import Optional, Dict, Union
|
|
import re
|
|
from datetime import datetime
|
|
from sqlalchemy.orm import Session
|
|
from models.version import Version
|
|
from schemas.version import VersionCreate, VersionUpdate
|
|
|
|
def validate_version_number(version_number: str) -> bool:
|
|
"""
|
|
Validate version number format (e.g., 1.0.0, 2.1.3)
|
|
|
|
Args:
|
|
version_number: Version number string to validate
|
|
|
|
Returns:
|
|
bool: True if version format is valid, False otherwise
|
|
"""
|
|
pattern = r'^\d+\.\d+\.\d+$'
|
|
return bool(re.match(pattern, version_number))
|
|
|
|
def parse_version_components(version_number: str) -> Dict[str, int]:
|
|
"""
|
|
Parse version number into major, minor and patch components
|
|
|
|
Args:
|
|
version_number: Version number string (e.g. '1.2.3')
|
|
|
|
Returns:
|
|
Dict containing major, minor and patch numbers
|
|
"""
|
|
major, minor, patch = version_number.split('.')
|
|
return {
|
|
'major': int(major),
|
|
'minor': int(minor),
|
|
'patch': int(patch)
|
|
}
|
|
|
|
def compare_versions(version1: str, version2: str) -> int:
|
|
"""
|
|
Compare two version numbers
|
|
|
|
Args:
|
|
version1: First version number
|
|
version2: Second version number
|
|
|
|
Returns:
|
|
1 if version1 > version2
|
|
-1 if version1 < version2
|
|
0 if version1 == version2
|
|
"""
|
|
v1_components = parse_version_components(version1)
|
|
v2_components = parse_version_components(version2)
|
|
|
|
for component in ['major', 'minor', 'patch']:
|
|
if v1_components[component] > v2_components[component]:
|
|
return 1
|
|
elif v1_components[component] < v2_components[component]:
|
|
return -1
|
|
return 0
|
|
|
|
def get_latest_version(db: Session) -> Optional[Version]:
|
|
"""
|
|
Get the latest version from database
|
|
|
|
Args:
|
|
db: Database session
|
|
|
|
Returns:
|
|
Latest Version object if exists, None otherwise
|
|
"""
|
|
return db.query(Version).order_by(Version.version_number.desc()).first()
|
|
|
|
def create_version_safely(db: Session, version_data: VersionCreate) -> Union[Version, Dict[str, str]]:
|
|
"""
|
|
Create a new version with validation and error handling
|
|
|
|
Args:
|
|
db: Database session
|
|
version_data: Version data for creation
|
|
|
|
Returns:
|
|
Version object if created successfully, error dict otherwise
|
|
"""
|
|
if not validate_version_number(version_data.version_number):
|
|
return {"error": "Invalid version number format"}
|
|
|
|
existing_version = db.query(Version).filter(
|
|
Version.version_number == version_data.version_number
|
|
).first()
|
|
|
|
if existing_version:
|
|
return {"error": "Version already exists"}
|
|
|
|
db_version = Version(
|
|
version_number=version_data.version_number,
|
|
description=version_data.description
|
|
)
|
|
|
|
db.add(db_version)
|
|
db.commit()
|
|
db.refresh(db_version)
|
|
|
|
return db_version
|
|
|
|
def increment_version(current_version: str, increment_type: str = 'patch') -> str:
|
|
"""
|
|
Increment version number based on semantic versioning
|
|
|
|
Args:
|
|
current_version: Current version number
|
|
increment_type: Type of increment ('major', 'minor', or 'patch')
|
|
|
|
Returns:
|
|
New version number
|
|
"""
|
|
components = parse_version_components(current_version)
|
|
|
|
if increment_type == 'major':
|
|
components['major'] += 1
|
|
components['minor'] = 0
|
|
components['patch'] = 0
|
|
elif increment_type == 'minor':
|
|
components['minor'] += 1
|
|
components['patch'] = 0
|
|
else: # patch
|
|
components['patch'] += 1
|
|
|
|
return f"{components['major']}.{components['minor']}.{components['patch']}" |