Skip to main content
Glama

Voice Mode

by mbailey
version_helpers.py•5.99 kB
"""Version management helpers for service installations.""" import subprocess import logging from typing import List, Optional, Tuple from pathlib import Path import re logger = logging.getLogger("voicemode") def get_git_tags(repo_url: str) -> List[str]: """Fetch git tags from a repository URL.""" try: # Use git ls-remote to get tags without cloning result = subprocess.run( ["git", "ls-remote", "--tags", repo_url], capture_output=True, text=True, check=True ) tags = [] for line in result.stdout.strip().split('\n'): if line: # Extract tag name from refs/tags/tagname parts = line.split('\t') if len(parts) == 2 and 'refs/tags/' in parts[1]: tag = parts[1].replace('refs/tags/', '') # Skip annotated tag references (ending with ^{}) if not tag.endswith('^{}'): tags.append(tag) return sorted(tags, key=parse_version, reverse=True) except subprocess.CalledProcessError as e: logger.error(f"Failed to fetch tags from {repo_url}: {e}") return [] def parse_version(version: str) -> Tuple: """Parse version string for sorting. Handles versions like v1.2.3, v1.2.3-pre, v1.2.3-rc1, etc. Returns tuple for proper sorting. """ # Remove 'v' prefix if present if version.startswith('v'): version = version[1:] # Split on dash for pre-release info parts = version.split('-', 1) main_version = parts[0] pre_release = parts[1] if len(parts) > 1 else None # Parse main version try: version_parts = [int(x) for x in main_version.split('.')] except ValueError: # Handle versions with non-numeric parts version_parts = [] for part in main_version.split('.'): try: version_parts.append(int(part)) except ValueError: # Convert non-numeric parts to 0 for consistent comparison version_parts.append(0) # Pad version parts to ensure consistent comparison while len(version_parts) < 3: version_parts.append(0) # Handle pre-release sorting # Stable releases come after pre-releases if pre_release is None: pre_release_order = (1, '') # Stable else: # Extract pre-release type and number match = re.match(r'(alpha|beta|rc|pre)(\d*)', pre_release) if match: pre_type, pre_num = match.groups() pre_num = int(pre_num) if pre_num else 0 # Order: alpha < beta < rc/pre < stable type_order = {'alpha': 0, 'beta': 1, 'rc': 2, 'pre': 2} pre_release_order = (0, type_order.get(pre_type, 3), pre_num) else: pre_release_order = (0, 4, pre_release) return tuple(version_parts + [pre_release_order]) def get_latest_stable_tag(tags: List[str]) -> Optional[str]: """Get the latest stable release tag (no pre-release suffixes).""" for tag in tags: # Skip pre-release versions if not any(suffix in tag for suffix in ['-pre', '-rc', '-alpha', '-beta', 'post']): return tag return tags[0] if tags else None def get_current_version(install_dir: Path) -> Optional[str]: """Get the currently installed version from a git repository.""" if not install_dir.exists() or not (install_dir / '.git').exists(): return None try: # Try git describe first (shows tag + commits since tag) result = subprocess.run( ["git", "describe", "--tags", "--always"], cwd=install_dir, capture_output=True, text=True, check=True ) version = result.stdout.strip() # If we got a commit hash only, try to get the exact tag if re.match(r'^[0-9a-f]+$', version): result = subprocess.run( ["git", "describe", "--tags", "--exact-match"], cwd=install_dir, capture_output=True, text=True ) if result.returncode == 0: version = result.stdout.strip() return version except subprocess.CalledProcessError: # Fallback to commit hash try: result = subprocess.run( ["git", "rev-parse", "--short", "HEAD"], cwd=install_dir, capture_output=True, text=True, check=True ) return result.stdout.strip() except subprocess.CalledProcessError: return None def checkout_version(install_dir: Path, version: str) -> bool: """Checkout a specific version in a git repository.""" try: # Fetch latest tags subprocess.run( ["git", "fetch", "--tags"], cwd=install_dir, check=True, capture_output=True ) # Checkout the version subprocess.run( ["git", "checkout", version], cwd=install_dir, check=True, capture_output=True ) return True except subprocess.CalledProcessError as e: logger.error(f"Failed to checkout version {version}: {e}") return False def is_version_installed(install_dir: Path, version: str) -> bool: """Check if a specific version is currently installed.""" current = get_current_version(install_dir) if not current: return False # Handle exact matches if current == version: return True # Handle cases where current is "v1.2.3-4-gabcdef" and version is "v1.2.3" if '-' in current: base_version = current.split('-')[0] if base_version == version: return True return False

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mbailey/voicemode'

If you have feedback or need assistance with the MCP directory API, please join our Discord server