Last active
May 11, 2024 18:46
-
-
Save f0ster/88c55f169a79c48479a9cfd8c9b0fb59 to your computer and use it in GitHub Desktop.
Summarize git repositories
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# script to provide a summary of the repositories by only listing each one's name | |
# along with its status (public, public with changes, or private) | |
import os | |
import subprocess | |
import json | |
from concurrent.futures import ThreadPoolExecutor, as_completed | |
def execute_command(command, cwd): | |
"""Executes a shell command in a specified directory and returns the output.""" | |
result = subprocess.run(command, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True) | |
if result.returncode != 0: | |
return None | |
return result.stdout.strip() | |
def is_git_repo(path): | |
"""Check if a directory is a git repository.""" | |
return execute_command("git rev-parse --is-inside-work-tree", cwd=path) is not None | |
def get_remote_urls(path): | |
"""Retrieve all remote URLs of the git repository.""" | |
return execute_command("git remote -v", cwd=path) | |
def is_public(url): | |
"""Determine if the git repository URL suggests it is public.""" | |
private_indicators = ["gitlab.mycompany.com", "github-private.com"] | |
return not any(private in url for private in private_indicators) | |
def check_for_local_changes(path): | |
"""Check for local branch changes not pushed to remote.""" | |
local_branches = execute_command("git branch -vv", cwd=path) | |
return "ahead" in local_branches if local_branches else False | |
def analyze_repository(repo_path): | |
"""Analyze a single repository to determine its status and return detailed info.""" | |
if is_git_repo(repo_path): | |
urls = get_remote_urls(repo_path) | |
if urls: | |
if is_public(urls): | |
has_changes = check_for_local_changes(repo_path) | |
status = 'Public + Changes' if has_changes else 'Public' | |
else: | |
status = 'Private' | |
return {'path': repo_path, 'status': status} | |
return None | |
def main(): | |
root_dir = input("Enter the directory path containing git repositories: ") | |
repo_details = [] | |
# Collect top-level directory paths within the specified root | |
top_level_repos = [os.path.join(root_dir, d) for d in os.listdir(root_dir) if os.path.isdir(os.path.join(root_dir, d))] | |
# Use ThreadPoolExecutor to process repositories in parallel | |
with ThreadPoolExecutor(max_workers=10) as executor: | |
futures = [executor.submit(analyze_repository, repo_path) for repo_path in top_level_repos if is_git_repo(repo_path)] | |
for future in as_completed(futures): | |
result = future.result() | |
if result: | |
repo_details.append(result) | |
# Save results to JSON | |
with open('repository_summary.json', 'w') as json_file: | |
json.dump(repo_details, json_file, indent=4) | |
print("\nDetailed repository status has been saved to 'repository_summary.json'.") | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
jq '.[] | select(.status == "Public + Changes")' repository_summary.json