commit 2c9cf9de8266aee2b966fb1f89eb6c55fbcc7a23 from: Jelmer Vernooij via: GitHub date: Mon Mar 20 18:20:24 2023 UTC Merge pull request #1162 from jelmer/init-branch Support ``init.defaultBranch`` setting commit - 1ad7903cd8c5410dc6573ea27d284a4fa79ec184 commit + 2c9cf9de8266aee2b966fb1f89eb6c55fbcc7a23 blob - 43ced4d67ba8e0cf0069e523d5112f6b9d8e6d77 blob + 13b839d893f897375de0e9464be3c3b29dadffc0 --- NEWS +++ NEWS @@ -4,6 +4,9 @@ * Fix fetching into MemoryRepo. (Jelmer Vernooij, #1157) + * Support ``init.defaultBranch`` config. + (Jelmer Vernooij) + 0.21.3 2023-02-17 * Add support for ``worktreeconfig`` extension. blob - 95e5d1718f15aad4e0d34e272fd7a4eec94a926f blob + 3435dcdb20838dfe9a2a44f51691c33357fe5588 --- dulwich/objectspec.py +++ dulwich/objectspec.py @@ -20,16 +20,21 @@ """Object specification.""" -from typing import List, Tuple, Union +from typing import List, Tuple, Union, TYPE_CHECKING, Optional, Iterator +if TYPE_CHECKING: + from dulwich.objects import ShaFile, Commit, Tree + from dulwich.refs import RefsContainer, Ref + from dulwich.repo import Repo -def to_bytes(text): + +def to_bytes(text: Union[str, bytes]) -> bytes: if getattr(text, "encode", None) is not None: - text = text.encode("ascii") - return text + text = text.encode("ascii") # type: ignore + return text # type: ignore -def parse_object(repo, objectish): +def parse_object(repo: "Repo", objectish: Union[bytes, str]) -> "ShaFile": """Parse a string referring to an object. Args: @@ -43,7 +48,7 @@ def parse_object(repo, objectish): return repo[objectish] -def parse_tree(repo, treeish): +def parse_tree(repo: "Repo", treeish: Union[bytes, str]) -> "Tree": """Parse a string referring to a tree. Args: @@ -64,7 +69,7 @@ def parse_tree(repo, treeish): return o -def parse_ref(container, refspec): +def parse_ref(container: Union["Repo", "RefsContainer"], refspec: Union[str, bytes]) -> "Ref": """Parse a string referring to a reference. Args: @@ -89,7 +94,10 @@ def parse_ref(container, refspec): raise KeyError(refspec) -def parse_reftuple(lh_container, rh_container, refspec, force=False): +def parse_reftuple( + lh_container: Union["Repo", "RefsContainer"], + rh_container: Union["Repo", "RefsContainer"], refspec: Union[str, bytes], + force: bool = False) -> Tuple[Optional["Ref"], Optional["Ref"], bool]: """Parse a reftuple spec. Args: @@ -104,6 +112,8 @@ def parse_reftuple(lh_container, rh_container, refspec if refspec.startswith(b"+"): force = True refspec = refspec[1:] + lh: Optional[bytes] + rh: Optional[bytes] if b":" in refspec: (lh, rh) = refspec.split(b":") else: @@ -125,8 +135,9 @@ def parse_reftuple(lh_container, rh_container, refspec def parse_reftuples( - lh_container, rh_container, - refspecs: Union[bytes, List[bytes], List[Tuple[bytes, bytes]]], + lh_container: Union["Repo", "RefsContainer"], + rh_container: Union["Repo", "RefsContainer"], + refspecs: Union[bytes, List[bytes]], force: bool = False): """Parse a list of reftuple specs to a list of reftuples. @@ -167,7 +178,7 @@ def parse_refs(container, refspecs): return ret -def parse_commit_range(repo, committishs): +def parse_commit_range(repo: "Repo", committishs: Union[str, bytes]) -> Iterator["Commit"]: """Parse a string referring to a range of commits. Args: @@ -206,7 +217,7 @@ def scan_for_short_id(object_store, prefix): raise AmbiguousShortId(prefix, ret) -def parse_commit(repo, committish): +def parse_commit(repo: "Repo", committish: Union[str, bytes]) -> "Commit": """Parse a string referring to a single commit. Args: blob - a0839bdb675fbf5e928aa5ed3675169d4631af0c blob + f16c847baa1bffa22e2dbad42380c885e3745525 --- dulwich/repo.py +++ dulwich/repo.py @@ -85,7 +85,7 @@ BASE_DIRECTORIES = [ ["info"], ] -DEFAULT_REF = b"refs/heads/master" +DEFAULT_BRANCH = b"master" class InvalidUserIdentity(Exception): @@ -1590,18 +1590,28 @@ class Repo(BaseRepo): self._put_named_file("description", description) @classmethod - def _init_maybe_bare(cls, path, controldir, bare, object_store=None): + def _init_maybe_bare( + cls, path, controldir, bare, object_store=None, config=None, + default_branch=None): for d in BASE_DIRECTORIES: os.mkdir(os.path.join(controldir, *d)) if object_store is None: object_store = DiskObjectStore.init(os.path.join(controldir, OBJECTDIR)) ret = cls(path, bare=bare, object_store=object_store) - ret.refs.set_symbolic_ref(b"HEAD", DEFAULT_REF) + if default_branch is None: + if config is None: + from dulwich.config import StackedConfig + config = StackedConfig.default() + try: + default_branch = config.get("init", "defaultBranch") + except KeyError: + default_branch = DEFAULT_BRANCH + ret.refs.set_symbolic_ref(b"HEAD", LOCAL_BRANCH_PREFIX + default_branch) ret._init_files(bare) return ret @classmethod - def init(cls, path: str, mkdir: bool = False) -> "Repo": + def init(cls, path: str, *, mkdir: bool = False, config=None, default_branch=None) -> "Repo": """Create a new repository. Args: @@ -1614,7 +1624,9 @@ class Repo(BaseRepo): controldir = os.path.join(path, CONTROLDIR) os.mkdir(controldir) _set_filesystem_hidden(controldir) - return cls._init_maybe_bare(path, controldir, False) + return cls._init_maybe_bare( + path, controldir, False, config=config, + default_branch=default_branch) @classmethod def _init_new_working_directory(cls, path, main_repo, identifier=None, mkdir=False): @@ -1655,7 +1667,7 @@ class Repo(BaseRepo): return r @classmethod - def init_bare(cls, path, mkdir=False, object_store=None): + def init_bare(cls, path, *, mkdir=False, object_store=None, config=None, default_branch=None): """Create a new bare repository. ``path`` should already exist and be an empty directory. @@ -1666,7 +1678,7 @@ class Repo(BaseRepo): """ if mkdir: os.mkdir(path) - return cls._init_maybe_bare(path, path, True, object_store=object_store) + return cls._init_maybe_bare(path, path, True, object_store=object_store, config=config, default_branch=default_branch) create = init_bare blob - 6a9bbcf54b7d834597c5bda5a22f1446566cfb2c blob + c3f3a9d30ee15719a3dc3f242d33840bebd9727e --- dulwich/tests/__init__.py +++ dulwich/tests/__init__.py @@ -170,15 +170,33 @@ def tutorial_test_suite(): ] tutorial_files = [f"../../docs/tutorial/{name}.txt" for name in tutorial] + to_restore = [] + + def overrideEnv(name, value): + oldval = os.environ.get(name) + if value is not None: + os.environ[name] = value + else: + del os.environ[name] + to_restore.append((name, oldval)) + def setup(test): test.__old_cwd = os.getcwd() test.tempdir = tempfile.mkdtemp() test.globs.update({"tempdir": test.tempdir}) os.chdir(test.tempdir) + overrideEnv("HOME", "/nonexistent") + overrideEnv("GIT_CONFIG_NOSYSTEM", "1") def teardown(test): os.chdir(test.__old_cwd) shutil.rmtree(test.tempdir) + for name, oldval in to_restore: + if oldval is not None: + os.environ[name] = oldval + else: + del os.environ[name] + to_restore.clear() return doctest.DocFileSuite( module_relative=True,