from __future__ import annotations from argparse import ArgumentParser, Namespace from typing import TYPE_CHECKING from ...lib.base import InputMode from ...lib.log import NOTICE, log from .Cmd import Cmd, Parent if TYPE_CHECKING: from ...lib.base import Result class CmdCanonicalizeRemotes(Cmd): # export def __rewrite_url(self, url: str) -> str: return url.replace('/srv/git', '') def __init__(self, parent: Parent) -> 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 ) return Result(b'', None, 0) remotes: dict[str, dict[str, str | list[str]]] = {} result = await git(['remote', '-v'], ro = True) for line in result.stdout_str.splitlines(): name, url, fp = line.split() remote = remotes.setdefault(name, {}) key = 'url' if fp == '(fetch)' else 'pushurl' fpurls = remote.setdefault(key, []) assert isinstance(fpurls, list) fpurls.append(url) for name, remote in remotes.items(): dirty_keys: set[str] = set() for key, urls in remote.items(): for url in urls: if url != self.__rewrite_url(url): dirty_keys.add(key) for key in dirty_keys: urls = remote[key] await git( ['config', '--unset-all', f'remote.{name}.{key}'], throw = False ) for url in urls: await git( [ 'config', '--add', f'remote.{name}.{key}', self.__rewrite_url(url), ] )