diff --git a/make/topdir.mk b/make/topdir.mk index c0522179..936dd577 100644 --- a/make/topdir.mk +++ b/make/topdir.mk @@ -229,3 +229,6 @@ echo-hash: recache-vars: rm -f $(TOPDIR)/make clean-cache cache + +canonicalize-remotes: + $(PYTHON) $(JWB_SCRIPT_DIR)/jw-pkg.py projects canonicalize-remotes diff --git a/src/python/jw/pkg/cmds/projects/CmdCanonicalizeRemotes.py b/src/python/jw/pkg/cmds/projects/CmdCanonicalizeRemotes.py new file mode 100644 index 00000000..3f10dda5 --- /dev/null +++ b/src/python/jw/pkg/cmds/projects/CmdCanonicalizeRemotes.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- + +from __future__ import annotations +from typing import TYPE_CHECKING + +from argparse import Namespace, ArgumentParser + +from ...lib.log import * +from ...lib.ExecContext import InputMode +from ..Cmd import Cmd +from ..CmdProjects import CmdProjects +from ...App import Scope + +if TYPE_CHECKING: + from ...lib.ExecContext import Result + +class CmdCanonicalizeRemotes(Cmd): # export + + def __rewrite_url(self, url: str) -> str: + return url.replace('/srv/git', '') + + def __init__(self, parent: CmdProjects) -> None: + super().__init__(parent, 'canonicalize-remotes', help='Streamline janware Git remotes') + + def add_arguments(self, parser: ArgumentParser) -> None: + super().add_arguments(parser) + parser.add_argument('-n', '--dry-run', default=False, action='store_true', help='Only log what would be done') + + async def _run(self, args: Namespace) -> None: + + async def git(cmd: list[str], ro=False, throw=True) -> Result: + cmd = ['/usr/bin/git', *cmd] + log(NOTICE, f'-- {" ".join(cmd)}') + if ro or not args.dry_run: + return await self.app.exec_context.run(cmd, cmd_input=InputMode.NonInteractive, throw=throw) + remotes: dict[str, dict[str, str]] = {} + stdout, stderr, status = await git(['remote', '-v'], ro=True) + for line in stdout.decode().splitlines(): + name, url, fp = line.split() + remote = remotes.setdefault(name, {}) + key = 'url' if fp == '(fetch)' else 'pushurl' + fpurls = remote.setdefault(key, []) + fpurls.append(url) + for remote, config in remotes.items(): + dirty_keys: set[str] = set() + for key, urls in config.items(): + for url in urls: + if url != self.__rewrite_url(url): + dirty_keys.add(key) + for key in dirty_keys: + urls = config[key] + await git(['config', '--unset-all', f'remote.{remote}.{key}'], throw=False) + for url in urls: + await git(['config', '--add', f'remote.{remote}.{key}', self.__rewrite_url(url)])