#!/usr/bin/env python3 """ Debian Version Detector Automatically detects Debian version and provides appropriate configuration Similar to how Fedora/RHEL handle version detection in OSBuild """ import os import subprocess import re from pathlib import Path from typing import Optional, Dict, Any, Tuple class DebianVersionDetector: """Detects Debian version and provides appropriate configuration""" def __init__(self): self.version_info = self._detect_debian_version() def _detect_debian_version(self) -> Dict[str, Any]: """Detect Debian version from multiple sources""" version_info = { 'codename': None, 'version': None, 'release': None, 'is_debian': False, 'is_supported': False, 'support_status': 'unknown' } # Method 1: Check /etc/os-release if os.path.exists('/etc/os-release'): with open('/etc/os-release', 'r') as f: content = f.read() # Check if this is actually Debian if 'debian' in content.lower(): version_info['is_debian'] = True # Extract version info version_match = re.search(r'VERSION_ID="?([^"\n]+)"?', content) codename_match = re.search(r'VERSION_CODENAME="?([^"\n]+)"?', content) if version_match: version_info['version'] = version_match.group(1) if codename_match: version_info['codename'] = codename_match.group(1) # Method 2: Check /etc/debian_version if os.path.exists('/etc/debian_version'): version_info['is_debian'] = True with open('/etc/debian_version', 'r') as f: version_info['release'] = f.read().strip() # Method 3: Check lsb_release command try: result = subprocess.run(['lsb_release', '-a'], capture_output=True, text=True, check=True) for line in result.stdout.split('\n'): if 'Distributor ID:' in line and 'debian' in line.lower(): version_info['is_debian'] = True elif 'Codename:' in line and version_info['is_debian']: version_info['codename'] = line.split(':', 1)[1].strip() elif 'Release:' in line and version_info['is_debian']: version_info['version'] = line.split(':', 1)[1].strip() except (subprocess.CalledProcessError, FileNotFoundError): pass # If not Debian, return early if not version_info['is_debian']: return { 'codename': None, 'version': None, 'release': None, 'is_debian': False, 'is_supported': False, 'support_status': 'not_debian', 'support_level': 'none', 'debian_version': 'unknown' } # Determine support status for Debian systems version_info.update(self._determine_support_status(version_info)) return version_info def _determine_support_status(self, version_info: Dict[str, Any]) -> Dict[str, Any]: """Determine if the detected version is supported""" codename = version_info.get('codename', '').lower() version = version_info.get('version', '') # Debian 13+ support policy supported_codenames = { 'trixie': {'version': '13', 'status': 'stable', 'support': 'full'}, 'forky': {'version': '14', 'status': 'testing', 'support': 'development'}, 'sid': {'version': 'unstable', 'status': 'unstable', 'support': 'experimental'} } # Check if codename is supported if codename in supported_codenames: return { 'is_supported': True, 'support_status': supported_codenames[codename]['status'], 'support_level': supported_codenames[codename]['support'], 'debian_version': supported_codenames[codename]['version'] } # Check version number if codename not found try: version_num = int(version.split('.')[0]) if version_num >= 13: return { 'is_supported': True, 'support_status': 'stable', 'support_level': 'full', 'debian_version': str(version_num) } except (ValueError, IndexError): pass # Not supported return { 'is_supported': False, 'support_status': 'unsupported', 'support_level': 'none', 'debian_version': 'unknown' } def get_recommended_suite(self) -> str: """Get the recommended Debian suite for this system""" if not self.version_info['is_debian']: return 'trixie' # Default for non-Debian systems if self.version_info['is_supported']: return self.version_info['codename'] or 'trixie' return 'trixie' # Default to supported version def get_mirror_url(self) -> str: """Get appropriate Debian mirror URL""" if not self.version_info['is_debian']: return 'http://deb.debian.org/debian' # Default for non-Debian systems codename = self.version_info.get('codename', 'trixie') # Use official Debian mirrors mirrors = { 'trixie': 'http://deb.debian.org/debian', 'forky': 'http://deb.debian.org/debian', 'sid': 'http://deb.debian.org/debian' } return mirrors.get(codename, 'http://deb.debian.org/debian') def get_apt_sources(self) -> str: """Generate appropriate apt sources.list content""" if not self.version_info['is_debian']: # Return default sources for non-Debian systems return """deb http://deb.debian.org/debian trixie main deb http://deb.debian.org/debian trixie-updates main deb http://deb.debian.org/debian trixie-security main deb http://deb.debian.org/debian trixie-backports main """ codename = self.version_info.get('codename', 'trixie') mirror = self.get_mirror_url() sources = f"""deb {mirror} {codename} main deb {mirror} {codename}-updates main deb {mirror} {codename}-security main """ # Add backports for stable releases if codename == 'trixie': sources += f"deb {mirror} {codename}-backports main\n" return sources def get_support_warning(self) -> Optional[str]: """Get warning message if version is not fully supported""" if not self.version_info['is_debian']: return "Note: This is not a Debian system. Debian Forge will use default Debian settings." if not self.version_info['is_supported']: return f"Warning: Debian {self.version_info.get('version', 'unknown')} ({self.version_info.get('codename', 'unknown')}) is not officially supported. Debian Forge supports Debian 13+ (Trixie and newer)." if self.version_info['support_level'] == 'experimental': return f"Warning: {self.version_info['codename']} is unstable. Use with caution for production builds." return None def print_version_info(self): """Print detailed version information""" print("Debian Version Detection:") print("=" * 40) if not self.version_info['is_debian']: print("System: Non-Debian system detected") print("Status: Using default Debian Forge settings") print(f"Recommended suite: {self.get_recommended_suite()}") print(f"Mirror URL: {self.get_mirror_url()}") return print(f"System: Debian") print(f"Codename: {self.version_info.get('codename', 'unknown')}") print(f"Version: {self.version_info.get('version', 'unknown')}") print(f"Release: {self.version_info.get('release', 'unknown')}") print(f"Supported: {self.version_info['is_supported']}") print(f"Status: {self.version_info['support_status']}") print(f"Support Level: {self.version_info['support_level']}") warning = self.get_support_warning() if warning: print(f"\n⚠️ {warning}") print(f"\nRecommended suite: {self.get_recommended_suite()}") print(f"Mirror URL: {self.get_mirror_url()}") # Global instance version_detector = DebianVersionDetector() def get_recommended_suite() -> str: """Get recommended Debian suite (convenience function)""" return version_detector.get_recommended_suite() def get_mirror_url() -> str: """Get appropriate Debian mirror URL (convenience function)""" return version_detector.get_mirror_url() def get_apt_sources() -> str: """Get appropriate apt sources (convenience function)""" return version_detector.get_apt_sources() def is_version_supported() -> bool: """Check if current Debian version is supported (convenience function)""" return version_detector.version_info['is_supported'] def is_debian_system() -> bool: """Check if this is a Debian system (convenience function)""" return version_detector.version_info['is_debian'] def print_version_info(): """Print version information (convenience function)""" version_detector.print_version_info() if __name__ == '__main__': print_version_info()