Initial commit
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import configparser
|
||||
import logging
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
|
||||
from app.models import Mirror
|
||||
from app.services.host import host_path, run_on_host
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
MARKER = "mirror-manager"
|
||||
INSTEAD_SECTION = f'url "https://github.com/" managed by {MARKER}'
|
||||
|
||||
|
||||
def _gitconfig_paths() -> list[Path]:
|
||||
paths = []
|
||||
for rel in ("root/.gitconfig", "home/.gitconfig"):
|
||||
p = host_path(rel)
|
||||
if p not in paths:
|
||||
paths.append(p)
|
||||
local = Path.home() / ".gitconfig"
|
||||
if local not in paths:
|
||||
paths.append(local)
|
||||
system = host_path("etc/gitconfig")
|
||||
if system not in paths:
|
||||
paths.append(system)
|
||||
return paths
|
||||
|
||||
|
||||
def read_current_github() -> dict:
|
||||
configs = {}
|
||||
for path in _gitconfig_paths():
|
||||
if path.exists():
|
||||
configs[str(path)] = path.read_text(encoding="utf-8")
|
||||
return configs
|
||||
|
||||
|
||||
def _parse_gitconfig(content: str) -> configparser.ConfigParser:
|
||||
parser = configparser.ConfigParser()
|
||||
parser.read_string(content if content.strip() else "[core]\n")
|
||||
return parser
|
||||
|
||||
|
||||
def _serialize_gitconfig(parser: configparser.ConfigParser) -> str:
|
||||
buf = StringIO()
|
||||
parser.write(buf)
|
||||
return buf.getvalue()
|
||||
|
||||
|
||||
def _remove_mirror_sections(parser: configparser.ConfigParser) -> None:
|
||||
to_remove = []
|
||||
for section in parser.sections():
|
||||
if not section.startswith('url "'):
|
||||
continue
|
||||
instead_of = parser.get(section, "insteadOf", fallback="")
|
||||
if instead_of in ("https://github.com/", "git@github.com:"):
|
||||
to_remove.append(section)
|
||||
for section in to_remove:
|
||||
parser.remove_section(section)
|
||||
|
||||
|
||||
def apply_github(mirror: Mirror) -> dict:
|
||||
meta = mirror.get_meta()
|
||||
instead_prefix = meta.get("instead_prefix") or mirror.url
|
||||
if not instead_prefix:
|
||||
return {"success": False, "error": "prefix میرور GitHub تعریف نشده"}
|
||||
|
||||
instead_prefix = instead_prefix.rstrip("/") + "/"
|
||||
section_name = f'url "{instead_prefix}"'
|
||||
|
||||
applied_paths = []
|
||||
for path in _gitconfig_paths():
|
||||
content = path.read_text(encoding="utf-8") if path.exists() else ""
|
||||
parser = _parse_gitconfig(content)
|
||||
_remove_mirror_sections(parser)
|
||||
|
||||
if not parser.has_section(section_name):
|
||||
parser.add_section(section_name)
|
||||
parser.set(section_name, "insteadOf", "https://github.com/")
|
||||
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(_serialize_gitconfig(parser), encoding="utf-8")
|
||||
applied_paths.append(str(path))
|
||||
|
||||
test = run_on_host(
|
||||
["git", "ls-remote", "https://github.com/octocat/Hello-World.git", "HEAD"],
|
||||
timeout=60,
|
||||
)
|
||||
|
||||
return {
|
||||
"success": test.returncode == 0,
|
||||
"message": f"GitHub mirror اعمال شد: {mirror.name}",
|
||||
"paths": applied_paths,
|
||||
"test_output": (test.stdout or test.stderr)[:300] if test.returncode != 0 else "git ls-remote موفق",
|
||||
"error": test.stderr[:300] if test.returncode != 0 else None,
|
||||
}
|
||||
|
||||
|
||||
def remove_github_config() -> None:
|
||||
for path in _gitconfig_paths():
|
||||
if not path.exists():
|
||||
continue
|
||||
parser = _parse_gitconfig(path.read_text(encoding="utf-8"))
|
||||
_remove_mirror_sections(parser)
|
||||
path.write_text(_serialize_gitconfig(parser), encoding="utf-8")
|
||||
Reference in New Issue
Block a user