branch-from command
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
import shutil
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
COMMAND_TO_METHOD = {
|
||||
"branch-from": "branch_from",
|
||||
"bash-completions": "bash_completions",
|
||||
}
|
||||
METHOD_TO_COMMAND = {method: command for command, method in COMMAND_TO_METHOD.items()}
|
||||
@@ -36,6 +39,28 @@ class DevHelper:
|
||||
command = f"rm -rf build && cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug"
|
||||
self._exec_in_root(command, replace=True)
|
||||
|
||||
##
|
||||
# Checks out a branch named after a Gitea issue URL.
|
||||
# If the issue is from this project's repo, the branch name will be:
|
||||
# issue-<issue_number>/<issue_title>
|
||||
# If the issue is from another repo (presumably upstream), the branch name will be:
|
||||
# <issue_owner>-issue-<issue_number>/<issue_title>
|
||||
def branch_from(self, *args, **kwargs):
|
||||
issue_url = args[0] if args else None
|
||||
if issue_url is None:
|
||||
raise ValueError("Must provide a Gitea issue URL.")
|
||||
|
||||
base_url, issue_repo, issue_number = self._parse_issue_url(issue_url)
|
||||
issue_title = self._fetch_issue_title(base_url, issue_repo, issue_number)
|
||||
branch_name = self._format_branch_name(issue_repo, issue_number, issue_title)
|
||||
|
||||
exists = subprocess.run(
|
||||
["git", "-C", self._project_root(), "rev-parse", "--verify", "--quiet", f"refs/heads/{branch_name}"],
|
||||
stdout=subprocess.DEVNULL,
|
||||
).returncode == 0
|
||||
flag = "" if exists else "-b "
|
||||
self._exec_in_root(f"git checkout {flag}{shlex.quote(branch_name)}", replace=True)
|
||||
|
||||
def renderdoc(self, *args, **kwargs):
|
||||
qrenderdoc = self._find_qrenderdoc()
|
||||
self._exec_in_root(qrenderdoc, replace=True)
|
||||
@@ -84,6 +109,39 @@ class DevHelper:
|
||||
print(" ".join(completions))
|
||||
|
||||
# Private helpers
|
||||
def _parse_issue_url(self, url):
|
||||
match = re.match(r"^(https?://[^/]+)/([^/]+)/([^/]+)/issues/(\d+)", url)
|
||||
if match is None:
|
||||
raise ValueError(f"Not a Gitea issue URL: {url}")
|
||||
return match[1], f"{match[2]}/{match[3]}", match[4]
|
||||
|
||||
def _fetch_issue_title(self, base_url, repo, issue_number):
|
||||
if shutil.which("tea") is None:
|
||||
raise RuntimeError("tea not found on PATH (install gitea tea and run `tea login add`)")
|
||||
|
||||
endpoint = f"{base_url}/api/v1/repos/{repo}/issues/{issue_number}"
|
||||
print(f"Running: tea api {endpoint}")
|
||||
result = subprocess.run(["tea", "api", endpoint], stdout=subprocess.PIPE, text=True)
|
||||
if result.returncode != 0:
|
||||
raise RuntimeError(f"failed to fetch issue title from {endpoint}")
|
||||
return json.loads(result.stdout)["title"]
|
||||
|
||||
def _format_branch_name(self, issue_repo, issue_number, issue_title):
|
||||
formatted_title = re.sub(r"-+", "-", re.sub(r"[^a-z0-9\-]", "", re.sub(r"\s+", "-", issue_title.lower().strip())))
|
||||
if issue_repo == self._origin_repo():
|
||||
return f"issue-{issue_number}/{formatted_title}"
|
||||
issue_owner = issue_repo.split("/")[0]
|
||||
return f"{issue_owner}-issue-{issue_number}/{formatted_title}"
|
||||
|
||||
def _origin_repo(self):
|
||||
result = subprocess.run(
|
||||
["git", "-C", self._project_root(), "remote", "get-url", "origin"],
|
||||
stdout=subprocess.PIPE,
|
||||
text=True,
|
||||
)
|
||||
match = re.search(r"[:/]([^/:]+/[^/]+?)(?:\.git)?$", result.stdout.strip())
|
||||
return match[1] if match else None
|
||||
|
||||
def _find_glslc(self):
|
||||
glslc = shutil.which("glslc")
|
||||
if glslc is None:
|
||||
|
||||
Reference in New Issue
Block a user