Coverage for core/src/version_finder/common.py: 85%
62 statements
« prev ^ index » next coverage.py v7.7.0, created at 2025-03-18 10:30 +0000
« prev ^ index » next coverage.py v7.7.0, created at 2025-03-18 10:30 +0000
1"""
2common.py
3====================================
4Common utilities and constants for version_finder.
5"""
6import argparse
7import os
8from pathlib import Path
9from typing import Optional
11# Default configuration values
12DEFAULT_GIT_TIMEOUT = 30 # seconds
13DEFAULT_GIT_MAX_RETRIES = 0
14DEFAULT_GIT_RETRY_DELAY = 1 # seconds
16# Environment variable names
17ENV_GIT_TIMEOUT = "GIT_TIMEOUT"
18ENV_GIT_MAX_RETRIES = "GIT_MAX_RETRIES"
19ENV_GIT_RETRY_DELAY = "GIT_RETRY_DELAY"
20ENV_DEBUG = "VERSION_FINDER_DEBUG"
22# Git command constants
23GIT_CMD_FETCH = ["fetch", "--all"]
24GIT_CMD_CHECKOUT = ["checkout"]
25GIT_CMD_SUBMODULE_UPDATE = ["submodule", "update", "--init", "--recursive"]
26GIT_CMD_LIST_BRANCHES = ["branch", "-a"]
27GIT_CMD_LIST_SUBMODULES = ["submodule", "status"]
28GIT_CMD_LOG = ["log"]
29GIT_CMD_SHOW = ["show"]
30GIT_CMD_REV_PARSE = ["rev-parse"]
31GIT_CMD_GREP = ["grep"]
33# Regex patterns
34BRANCH_PATTERN = r"\s*(?:\*\s)?(.*)"
36# UI constants
37MAX_COMMITS_DISPLAY = 1000 # Maximum number of commits to display in UI
38MAX_LOG_ENTRIES = 500 # Maximum number of log entries to keep in UI
40# File paths
41DEFAULT_CONFIG_PATH = os.path.expanduser("~/.version_finder/config.json")
44def parse_arguments() -> argparse.Namespace:
45 """
46 Parse command-line arguments.
48 Returns:
49 argparse.Namespace: Parsed arguments
50 """
51 parser = argparse.ArgumentParser(description="Version Finder - Find and compare versions in Git repositories")
52 parser.add_argument("--path", "-p", type=str, default="", help="Path to the Git repository")
53 parser.add_argument("--debug", "-d", action="store_true", help="Enable debug logging")
54 parser.add_argument("--config", "-c", type=str, default=DEFAULT_CONFIG_PATH, help="Path to configuration file")
55 parser.add_argument("--version", "-v", action="store_true", help="Show version information")
56 parser.add_argument("--verbose", action="store_true", help="Enable verbose output")
57 parser.add_argument(
58 "--force",
59 "-f",
60 action="store_true",
61 help="Force operation even if repository has uncommitted changes")
62 parser.add_argument("--restore-state", "-r", action="store_true",
63 help="Restore repository to original state after operation")
64 parser.add_argument("--branch", "-b", type=str, help="Branch to use")
65 parser.add_argument("--commit", type=str, help="Commit SHA to find version for")
66 parser.add_argument("--submodule", "-s", type=str, help="Submodule to use")
67 parser.add_argument("--cli", action="store_true", help="Run the CLI version")
68 parser.add_argument("--gui", action="store_true", help="Run the GUI version")
69 parser.add_argument("--task", "-t", type=str, help="Task to run")
71 return parser.parse_args()
74def get_repository_path(path_arg: str) -> Optional[Path]:
75 """
76 Get the repository path from the command-line argument or current directory.
78 Args:
79 path_arg: Path argument from command line
81 Returns:
82 Path: Repository path or None if invalid
83 """
84 if path_arg:
85 path = Path(path_arg)
86 else:
87 path = Path.cwd()
89 # Check if path exists and is a directory
90 if not path.exists() or not path.is_dir():
91 return None
93 # Check if it's a git repository
94 git_dir = path / ".git"
95 if not git_dir.exists() or not git_dir.is_dir():
96 return None
98 return path
101def args_to_command(args):
102 """
103 Convert argparse.Namespace object to command-line arguments string.
105 Args:
106 args: argparse.Namespace object containing command-line arguments
108 Returns:
109 str: Command-line arguments as a string
111 Raises:
112 AttributeError: If args is not an argparse.Namespace object
113 """
114 if not isinstance(args, argparse.Namespace):
115 raise AttributeError("args must be an argparse.Namespace object")
117 command_parts = []
119 for key, value in vars(args).items():
120 # Replace underscores with hyphens in argument names
121 arg_name = key.replace('_', '-')
123 # Include boolean flags that are True
124 if isinstance(value, bool):
125 if value:
126 command_parts.append(f"--{arg_name}")
127 # Include non-None and non-False values
128 elif value is not None:
129 command_parts.append(f"--{arg_name} {value}")
131 return " ".join(command_parts)