|
| 1 | +import subprocess |
| 2 | +import yaml |
| 3 | +import tempfile |
| 4 | +import os |
| 5 | +from colorama import Fore, Style, init |
| 6 | + |
| 7 | +# Initialize colorama for Windows compatibility (does nothing on Linux/macOS) |
| 8 | +init(autoreset=True) |
| 9 | + |
| 10 | +# Define the ages you're interested in |
| 11 | +AGES = ["now", "1 month ago", "2 months ago", "3 months ago", "4 months ago", "5 months ago", "6 months ago"] |
| 12 | + |
| 13 | +# Path to the Git repository |
| 14 | +REPO_PATH = "/Users/fprior/Development/GitFarm/workplace/fprior/update-mirror-3/update-mirror/src/AWSDocsSdkExamplesPublic" |
| 15 | + |
| 16 | +# Path to the YAML file you want to extract from each commit |
| 17 | +FILE_PATH = "tools/update_mirror/config.yaml" |
| 18 | + |
| 19 | +# Function to run git commands |
| 20 | +def run_git_command(command, cwd=None): |
| 21 | + try: |
| 22 | + result = subprocess.run(command, cwd=cwd, text=True, capture_output=True, shell=True) |
| 23 | + if result.returncode != 0: |
| 24 | + raise subprocess.CalledProcessError(result.returncode, command, result.stderr) |
| 25 | + return result.stdout.strip() |
| 26 | + except Exception as e: |
| 27 | + print(f"{Fore.RED}Error running command: {command}\n{Fore.RED}Error: {e}") |
| 28 | + return None |
| 29 | + |
| 30 | +# Function to clone a repository if it's not already cloned |
| 31 | +def clone_or_reuse_repo(repo_url, branch, clone_dir): |
| 32 | + if os.path.exists(clone_dir): |
| 33 | + print(f"{Fore.YELLOW}Repository {repo_url} already cloned in {clone_dir}. Reusing existing clone.") |
| 34 | + else: |
| 35 | + print(f"{Fore.GREEN}Cloning repository {repo_url} into {clone_dir}...") |
| 36 | + clone_cmd = f"git clone {repo_url} {clone_dir}" |
| 37 | + run_git_command(clone_cmd) |
| 38 | + |
| 39 | + # Checkout the correct branch |
| 40 | + print(f"{Fore.CYAN}Checking out branch {branch} in {clone_dir}...") |
| 41 | + checkout_cmd = f"git checkout {branch}" |
| 42 | + run_git_command(checkout_cmd, cwd=clone_dir) |
| 43 | + |
| 44 | +# Function to get the latest commit hash for the specific age in the repo |
| 45 | +def get_commit_hash_for_age(repo_dir, age): |
| 46 | + log_cmd = f'git rev-list -1 --before="{age}" HEAD' |
| 47 | + commit_hash = run_git_command(log_cmd, cwd=repo_dir) |
| 48 | + if commit_hash: |
| 49 | + return commit_hash |
| 50 | + else: |
| 51 | + print(f"{Fore.RED}Failed to find commit hash for {age} in {repo_dir}") |
| 52 | + return None |
| 53 | + |
| 54 | +# Function to force checkout to the specific commit hash |
| 55 | +def checkout_commit(repo_dir, commit_hash): |
| 56 | + print(f"{Fore.CYAN}Checking out commit {commit_hash} in {repo_dir}") |
| 57 | + checkout_cmd = f'git checkout --force {commit_hash}' |
| 58 | + run_git_command(checkout_cmd, cwd=repo_dir) |
| 59 | + |
| 60 | +# Function to run the specific Git log command and Python command |
| 61 | +def run_commands_in_repo(repo_dir, commit_hash, age): |
| 62 | + # Checkout the repository to the specific commit |
| 63 | + checkout_commit(repo_dir, commit_hash) |
| 64 | + |
| 65 | + # Retrieve the commit details |
| 66 | + log_cmd = f'git log -n 1 {commit_hash} --pretty=format:"%H|%an|%aI"' |
| 67 | + log_output = run_git_command(log_cmd, cwd=repo_dir) |
| 68 | + |
| 69 | + if log_output: |
| 70 | + log_parts = log_output.split('|') |
| 71 | + commit_hash = log_parts[0] |
| 72 | + author_name = log_parts[1] |
| 73 | + commit_date = log_parts[2] |
| 74 | + |
| 75 | + print(f"{Fore.MAGENTA}Commit for {age}: {commit_hash}, Author: {author_name}, Date: {commit_date}") |
| 76 | + |
| 77 | + # Now run the Python command on the repository |
| 78 | + python_cmd = f'python3 -m aws_doc_sdk_examples_tools.stats "{repo_dir}"' |
| 79 | + print(f"{Fore.CYAN}Running stats command for repository: {repo_dir}") |
| 80 | + output = run_git_command(python_cmd, cwd=repo_dir) |
| 81 | + if output: |
| 82 | + print(output) |
| 83 | + print("###########################") |
| 84 | + else: |
| 85 | + print(f"{Fore.RED}No commit found for {age} in {repo_dir}") |
| 86 | + |
| 87 | +# Main function to gather file contents from specific commits and clone repositories |
| 88 | +def get_file_from_commits_and_clone(repo_path, file_path, ages): |
| 89 | + age_content_dict = {} |
| 90 | + cloned_repos = {} # To track cloned repositories and their directories |
| 91 | + |
| 92 | + # Create a temporary directory for the clones |
| 93 | + with tempfile.TemporaryDirectory() as tmp_dir: |
| 94 | + # First, fetch the configuration file from the main repository for each age |
| 95 | + for age in ages: |
| 96 | + print(f"{Style.BRIGHT}{Fore.BLUE}#############################################################") |
| 97 | + print(f"{Style.BRIGHT}{Fore.BLUE}######################## {age.upper()} ##############################") |
| 98 | + print(f"{Style.BRIGHT}{Fore.BLUE}#############################################################") |
| 99 | + |
| 100 | + # Get the commit hash for the main repository |
| 101 | + main_commit_hash = get_commit_hash_for_age(repo_path, age) |
| 102 | + if not main_commit_hash: |
| 103 | + print(f"{Fore.RED}Skipping {age} because commit hash could not be retrieved for the main repository.") |
| 104 | + continue |
| 105 | + |
| 106 | + # Get the YAML configuration from that commit |
| 107 | + file_content = run_git_command(f"git show {main_commit_hash}:{file_path}", cwd=repo_path) |
| 108 | + |
| 109 | + if file_content: |
| 110 | + try: |
| 111 | + # Parse the YAML content |
| 112 | + yaml_content = yaml.safe_load(file_content) |
| 113 | + |
| 114 | + # Extract the mirrors section |
| 115 | + mirrors = yaml_content.get('mirrors', {}) |
| 116 | + age_content_dict[age] = mirrors |
| 117 | + |
| 118 | + # Clone or reuse repositories for each mirror |
| 119 | + for mirror_name, mirror_info in mirrors.items(): |
| 120 | + repo_url = mirror_info.get('git_mirror') |
| 121 | + branch = mirror_info.get('branch') |
| 122 | + dir_name = mirror_info.get('dir') |
| 123 | + |
| 124 | + # Check if this repository has already been cloned |
| 125 | + if repo_url not in cloned_repos: |
| 126 | + # If not, clone the repository to a subfolder in the temp directory |
| 127 | + clone_dir = os.path.join(tmp_dir, dir_name) |
| 128 | + clone_or_reuse_repo(repo_url, branch, clone_dir) |
| 129 | + |
| 130 | + # Mark this repo as cloned |
| 131 | + cloned_repos[repo_url] = clone_dir |
| 132 | + else: |
| 133 | + print(f"{Fore.YELLOW}Reusing cloned repository {repo_url} for mirror {mirror_name}.") |
| 134 | + |
| 135 | + # Get the specific commit hash for this repo at this age |
| 136 | + repo_commit_hash = get_commit_hash_for_age(cloned_repos[repo_url], age) |
| 137 | + if repo_commit_hash: |
| 138 | + # Run commands in the cloned repository for the specific commit hash |
| 139 | + run_commands_in_repo(cloned_repos[repo_url], repo_commit_hash, age) |
| 140 | + else: |
| 141 | + print(f"{Fore.RED}Skipping {mirror_name} in {age} due to failure in retrieving commit hash.") |
| 142 | + |
| 143 | + except yaml.YAMLError as exc: |
| 144 | + print(f"{Fore.RED}Error parsing YAML file for {age}: {exc}") |
| 145 | + else: |
| 146 | + print(f"{Fore.RED}No file content found for commit {main_commit_hash} at {age}") |
| 147 | + |
| 148 | + return age_content_dict |
| 149 | + |
| 150 | +# Review the contents (age range as key and the list of mirror repositories as values) |
| 151 | +def display_age_content_dict(age_content_dict): |
| 152 | + print(f"{Style.BRIGHT}{Fore.GREEN}File contents grouped by age range:") |
| 153 | + for age, mirrors in age_content_dict.items(): |
| 154 | + print(f"{Fore.YELLOW}Age: {age}") |
| 155 | + print(f"{Fore.CYAN}Mirrors:") |
| 156 | + for mirror_name, mirror_info in mirrors.items(): |
| 157 | + print(f"{Fore.MAGENTA} - {mirror_name}:") |
| 158 | + print(f" {Fore.CYAN}git_mirror: {mirror_info.get('git_mirror')}") |
| 159 | + print(f" {Fore.CYAN}branch: {mirror_info.get('branch')}") |
| 160 | + print(f" {Fore.CYAN}dir: {mirror_info.get('dir')}") |
| 161 | + print("-----------------") |
| 162 | + |
| 163 | +if __name__ == "__main__": |
| 164 | + # Get the contents from the commits and clone the repos |
| 165 | + age_content_dict = get_file_from_commits_and_clone(REPO_PATH, FILE_PATH, AGES) |
| 166 | + |
| 167 | + # Display the contents in the dictionary format |
| 168 | + display_age_content_dict(age_content_dict) |
0 commit comments