util script
This commit is contained in:
1 file changed
+148
@@ -0,0 +1,148 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
PROJECTS_DIR = Path.home() / "Projects"
|
||||||
|
GITHUB_USER = "SowinskiBraeden"
|
||||||
|
GITEA_HOST = "git.sowinski.dev"
|
||||||
|
|
||||||
|
|
||||||
|
def git(repo: Path, *args: str, check: bool = True) -> subprocess.CompletedProcess:
|
||||||
|
return subprocess.run(
|
||||||
|
["git", "-C", str(repo), *args],
|
||||||
|
text=True,
|
||||||
|
capture_output=True,
|
||||||
|
check=check,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def find_git_repositories(root: Path):
|
||||||
|
"""
|
||||||
|
Find repositories recursively under ~/Projects.
|
||||||
|
|
||||||
|
Once a .git directory/file is found, don't recurse further into that
|
||||||
|
repository looking for nested repositories.
|
||||||
|
"""
|
||||||
|
repositories = []
|
||||||
|
|
||||||
|
for path in root.rglob(".git"):
|
||||||
|
if path.is_dir() or path.is_file():
|
||||||
|
repositories.append(path.parent)
|
||||||
|
|
||||||
|
return sorted(set(repositories))
|
||||||
|
|
||||||
|
|
||||||
|
def github_repo_name(origin: str):
|
||||||
|
"""
|
||||||
|
Recognize origins such as:
|
||||||
|
|
||||||
|
git@github.com:SowinskiBraeden/example.git
|
||||||
|
https://github.com/SowinskiBraeden/example.git
|
||||||
|
ssh://git@github.com/SowinskiBraeden/example.git
|
||||||
|
|
||||||
|
Returns "example" or None.
|
||||||
|
"""
|
||||||
|
|
||||||
|
patterns = [
|
||||||
|
rf"^git@github\.com:{re.escape(GITHUB_USER)}/([^/]+?)(?:\.git)?$",
|
||||||
|
rf"^https?://github\.com/{re.escape(GITHUB_USER)}/([^/]+?)(?:\.git)?/?$",
|
||||||
|
rf"^ssh://git@github\.com/{re.escape(GITHUB_USER)}/([^/]+?)(?:\.git)?/?$",
|
||||||
|
]
|
||||||
|
|
||||||
|
for pattern in patterns:
|
||||||
|
match = re.match(pattern, origin)
|
||||||
|
|
||||||
|
if match:
|
||||||
|
return match.group(1)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def configure_repository(repo: Path):
|
||||||
|
result = git(repo, "remote", "get-url", "origin", check=False)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
print(f"SKIP {repo}")
|
||||||
|
print(" No origin remote")
|
||||||
|
return
|
||||||
|
|
||||||
|
origin = result.stdout.strip()
|
||||||
|
repo_name = github_repo_name(origin)
|
||||||
|
|
||||||
|
if not repo_name:
|
||||||
|
print(f"SKIP {repo}")
|
||||||
|
print(f" Origin is not {GITHUB_USER}'s GitHub: {origin}")
|
||||||
|
return
|
||||||
|
|
||||||
|
github_url = f"git@github.com:{GITHUB_USER}/{repo_name}.git"
|
||||||
|
gitea_url = f"git@{GITEA_HOST}:{GITHUB_USER}/{repo_name}.git"
|
||||||
|
|
||||||
|
existing_push_urls = git(
|
||||||
|
repo,
|
||||||
|
"remote",
|
||||||
|
"get-url",
|
||||||
|
"--all",
|
||||||
|
"--push",
|
||||||
|
"origin",
|
||||||
|
).stdout.splitlines()
|
||||||
|
|
||||||
|
print(f"FOUND {repo}")
|
||||||
|
print(f" Repository: {GITHUB_USER}/{repo_name}")
|
||||||
|
|
||||||
|
# Explicitly establish GitHub as the first push destination.
|
||||||
|
#
|
||||||
|
# If no separate pushurl exists yet, this creates one without changing
|
||||||
|
# the fetch URL.
|
||||||
|
if github_url not in existing_push_urls:
|
||||||
|
git(repo, "remote", "set-url", "--push", "origin", github_url)
|
||||||
|
print(f" + push -> {github_url}")
|
||||||
|
else:
|
||||||
|
print(" = GitHub push already configured")
|
||||||
|
|
||||||
|
# Re-read because set-url --push may have replaced the implicit
|
||||||
|
# origin push URL.
|
||||||
|
existing_push_urls = git(
|
||||||
|
repo,
|
||||||
|
"remote",
|
||||||
|
"get-url",
|
||||||
|
"--all",
|
||||||
|
"--push",
|
||||||
|
"origin",
|
||||||
|
).stdout.splitlines()
|
||||||
|
|
||||||
|
if gitea_url not in existing_push_urls:
|
||||||
|
git(
|
||||||
|
repo,
|
||||||
|
"remote",
|
||||||
|
"set-url",
|
||||||
|
"--add",
|
||||||
|
"--push",
|
||||||
|
"origin",
|
||||||
|
gitea_url,
|
||||||
|
)
|
||||||
|
print(f" + push -> {gitea_url}")
|
||||||
|
else:
|
||||||
|
print(" = Gitea push already configured")
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if not PROJECTS_DIR.exists():
|
||||||
|
raise SystemExit(f"Projects directory does not exist: {PROJECTS_DIR}")
|
||||||
|
|
||||||
|
repositories = find_git_repositories(PROJECTS_DIR)
|
||||||
|
|
||||||
|
print(f"Searching {PROJECTS_DIR}")
|
||||||
|
print(f"Found {len(repositories)} Git repositories.\n")
|
||||||
|
|
||||||
|
for repo in repositories:
|
||||||
|
configure_repository(repo)
|
||||||
|
|
||||||
|
print("Done.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in new issue
Block a user