1# This module is part of GitPython and is released under the 
    2# 3-Clause BSD License: https://opensource.org/license/bsd-3-clause/ 
    3 
    4__all__ = [ 
    5    "sm_section", 
    6    "sm_name", 
    7    "mkhead", 
    8    "find_first_remote_branch", 
    9    "SubmoduleConfigParser", 
    10] 
    11 
    12from io import BytesIO 
    13import weakref 
    14 
    15import git 
    16from git.config import GitConfigParser 
    17from git.exc import InvalidGitRepositoryError 
    18 
    19# typing ----------------------------------------------------------------------- 
    20 
    21from typing import Any, Sequence, TYPE_CHECKING, Union 
    22 
    23from git.types import PathLike 
    24 
    25if TYPE_CHECKING: 
    26    from weakref import ReferenceType 
    27 
    28    from git.refs import Head, RemoteReference 
    29    from git.remote import Remote 
    30    from git.repo import Repo 
    31 
    32    from .base import Submodule 
    33 
    34# { Utilities 
    35 
    36 
    37def sm_section(name: str) -> str: 
    38    """:return: Section title used in ``.gitmodules`` configuration file""" 
    39    return f'submodule "{name}"' 
    40 
    41 
    42def sm_name(section: str) -> str: 
    43    """:return: Name of the submodule as parsed from the section name""" 
    44    section = section.strip() 
    45    return section[11:-1] 
    46 
    47 
    48def mkhead(repo: "Repo", path: PathLike) -> "Head": 
    49    """:return: New branch/head instance""" 
    50    return git.Head(repo, git.Head.to_full_path(path)) 
    51 
    52 
    53def find_first_remote_branch(remotes: Sequence["Remote"], branch_name: str) -> "RemoteReference": 
    54    """Find the remote branch matching the name of the given branch or raise 
    55    :exc:`~git.exc.InvalidGitRepositoryError`.""" 
    56    for remote in remotes: 
    57        try: 
    58            return remote.refs[branch_name] 
    59        except IndexError: 
    60            continue 
    61        # END exception handling 
    62    # END for remote 
    63    raise InvalidGitRepositoryError("Didn't find remote branch '%r' in any of the given remotes" % branch_name) 
    64 
    65 
    66# } END utilities 
    67 
    68# { Classes 
    69 
    70 
    71class SubmoduleConfigParser(GitConfigParser): 
    72    """Catches calls to :meth:`~git.config.GitConfigParser.write`, and updates the 
    73    ``.gitmodules`` blob in the index with the new data, if we have written into a 
    74    stream. 
    75 
    76    Otherwise it would add the local file to the index to make it correspond with the 
    77    working tree. Additionally, the cache must be cleared. 
    78 
    79    Please note that no mutating method will work in bare mode. 
    80    """ 
    81 
    82    def __init__(self, *args: Any, **kwargs: Any) -> None: 
    83        self._smref: Union["ReferenceType[Submodule]", None] = None 
    84        self._index = None 
    85        self._auto_write = True 
    86        super().__init__(*args, **kwargs) 
    87 
    88    # { Interface 
    89    def set_submodule(self, submodule: "Submodule") -> None: 
    90        """Set this instance's submodule. It must be called before the first write 
    91        operation begins.""" 
    92        self._smref = weakref.ref(submodule) 
    93 
    94    def flush_to_index(self) -> None: 
    95        """Flush changes in our configuration file to the index.""" 
    96        assert self._smref is not None 
    97        # Should always have a file here. 
    98        assert not isinstance(self._file_or_files, BytesIO) 
    99 
    100        sm = self._smref() 
    101        if sm is not None: 
    102            index = self._index 
    103            if index is None: 
    104                index = sm.repo.index 
    105            # END handle index 
    106            index.add([sm.k_modules_file], write=self._auto_write) 
    107            sm._clear_cache() 
    108        # END handle weakref 
    109 
    110    # } END interface 
    111 
    112    # { Overridden Methods 
    113    def write(self) -> None:  # type: ignore[override] 
    114        rval: None = super().write() 
    115        self.flush_to_index() 
    116        return rval 
    117 
    118    # END overridden methods 
    119 
    120 
    121# } END classes