Skip to content

cmd(git): More commands #465

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat(git): enhance git init support with all options and tests
- Add support for all git-init options (template, separate_git_dir, object_format, etc.)
- Add comprehensive tests for each option
- Fix path handling for separate_git_dir
- Fix string formatting for bytes paths
- Update docstrings with examples for all options
  • Loading branch information
tony committed Feb 25, 2025
commit 1a9ccf2b770a970dc6535b76b65d21b737feb8fc
102 changes: 71 additions & 31 deletions src/libvcs/cmd/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -1035,7 +1035,7 @@ def init(
object_format: t.Literal["sha1", "sha256"] | None = None,
branch: str | None = None,
initial_branch: str | None = None,
shared: bool | None = None,
shared: bool | str | None = None,
quiet: bool | None = None,
bare: bool | None = None,
# libvcs special behavior
Expand All @@ -1046,60 +1046,100 @@ def init(

Parameters
----------
quiet : bool
``--quiet``
bare : bool
``--bare``
object_format :
Hash algorithm used for objects. SHA-256 is still experimental as of git
2.36.0.
template : str, optional
Directory from which templates will be used. The template directory
contains files and directories that will be copied to the $GIT_DIR
after it is created.
separate_git_dir : :attr:`libvcs._internal.types.StrOrBytesPath`, optional
Instead of placing the git repository in <directory>/.git/, place it in
the specified path.
object_format : "sha1" | "sha256", optional
Specify the hash algorithm to use. The default is sha1. Note that
sha256 is still experimental in git.
branch : str, optional
Use the specified name for the initial branch. If not specified, fall
back to the default name (currently "master").
initial_branch : str, optional
Alias for branch parameter. Specify the name for the initial branch.
shared : bool | str, optional
Specify that the git repository is to be shared amongst several users.
Can be 'false', 'true', 'umask', 'group', 'all', 'world',
'everybody', or an octal number.
quiet : bool, optional
Only print error and warning messages; all other output will be
suppressed.
bare : bool, optional
Create a bare repository. If GIT_DIR environment is not set, it is set
to the current working directory.

Examples
--------
>>> new_repo = tmp_path / 'example'
>>> new_repo.mkdir()
>>> git = Git(path=new_repo)
>>> git = Git(path=tmp_path)
>>> git.init()
'Initialized empty Git repository in ...'
>>> pathlib.Path(new_repo / 'test').write_text('foo', 'utf-8')
3
>>> git.run(['add', '.'])
''

Bare:
Create with a specific initial branch name:

>>> new_repo = tmp_path / 'example1'
>>> new_repo = tmp_path / 'branch_example'
>>> new_repo.mkdir()
>>> git = Git(path=new_repo)
>>> git.init(branch='main')
'Initialized empty Git repository in ...'

Create a bare repository:

>>> bare_repo = tmp_path / 'bare_example'
>>> bare_repo.mkdir()
>>> git = Git(path=bare_repo)
>>> git.init(bare=True)
'Initialized empty Git repository in ...'
>>> pathlib.Path(new_repo / 'HEAD').exists()
True

Existing repo:
Create with a separate git directory:

>>> git = Git(path=new_repo)
>>> git = Git(path=example_git_repo.path)
>>> git_remote_repo = create_git_remote_repo()
>>> git.init()
'Reinitialized existing Git repository in ...'
>>> repo_path = tmp_path / 'repo'
>>> git_dir = tmp_path / 'git_dir'
>>> repo_path.mkdir()
>>> git_dir.mkdir()
>>> git = Git(path=repo_path)
>>> git.init(separate_git_dir=str(git_dir.absolute()))
'Initialized empty Git repository in ...'

Create with shared permissions:

>>> shared_repo = tmp_path / 'shared_example'
>>> shared_repo.mkdir()
>>> git = Git(path=shared_repo)
>>> git.init(shared='group')
'Initialized empty shared Git repository in ...'

Create with a template directory:

>>> template_repo = tmp_path / 'template_example'
>>> template_repo.mkdir()
>>> git = Git(path=template_repo)
>>> git.init(template=str(tmp_path))
'Initialized empty Git repository in ...'
"""
required_flags: list[str] = [str(self.path)]
local_flags: list[str] = []
required_flags: list[str] = [str(self.path)]

if template is not None:
local_flags.append(f"--template={template}")
if separate_git_dir is not None:
local_flags.append(f"--separate-git-dir={separate_git_dir!r}")
if isinstance(separate_git_dir, pathlib.Path):
separate_git_dir = str(separate_git_dir.absolute())
local_flags.append(f"--separate-git-dir={separate_git_dir!s}")
if object_format is not None:
local_flags.append(f"--object-format={object_format}")
if branch is not None:
local_flags.extend(["--branch", branch])
if initial_branch is not None:
local_flags.extend(["--initial-branch", branch])
elif initial_branch is not None:
local_flags.extend(["--initial-branch", initial_branch])
if shared is True:
local_flags.append("--shared")
if shared is not None:
if isinstance(shared, bool):
local_flags.append("--shared")
else:
local_flags.append(f"--shared={shared}")
if quiet is True:
local_flags.append("--quiet")
if bare is True:
Expand Down
113 changes: 113 additions & 0 deletions tests/cmd/test_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,116 @@ def test_git_constructor(
repo = git.Git(path=path_type(tmp_path))

assert repo.path == tmp_path


def test_git_init_basic(tmp_path: pathlib.Path) -> None:
"""Test basic git init functionality."""
repo = git.Git(path=tmp_path)
result = repo.init()
assert "Initialized empty Git repository" in result
assert (tmp_path / ".git").is_dir()


def test_git_init_bare(tmp_path: pathlib.Path) -> None:
"""Test git init with bare repository."""
repo = git.Git(path=tmp_path)
result = repo.init(bare=True)
assert "Initialized empty Git repository" in result
# Bare repos have files directly in the directory
assert (tmp_path / "HEAD").exists()


def test_git_init_template(tmp_path: pathlib.Path) -> None:
"""Test git init with template directory."""
template_dir = tmp_path / "template"
template_dir.mkdir()
(template_dir / "hooks").mkdir()
(template_dir / "hooks" / "pre-commit").write_text("#!/bin/sh\nexit 0\n")

repo_dir = tmp_path / "repo"
repo_dir.mkdir()
repo = git.Git(path=repo_dir)
result = repo.init(template=str(template_dir))

assert "Initialized empty Git repository" in result
assert (repo_dir / ".git" / "hooks" / "pre-commit").exists()


def test_git_init_separate_git_dir(tmp_path: pathlib.Path) -> None:
"""Test git init with separate git directory."""
repo_dir = tmp_path / "repo"
git_dir = tmp_path / "git_dir"
repo_dir.mkdir()
git_dir.mkdir()

repo = git.Git(path=repo_dir)
result = repo.init(separate_git_dir=str(git_dir.absolute()))

assert "Initialized empty Git repository" in result
assert git_dir.is_dir()
assert (git_dir / "HEAD").exists()


def test_git_init_initial_branch(tmp_path: pathlib.Path) -> None:
"""Test git init with custom initial branch name."""
repo = git.Git(path=tmp_path)
result = repo.init(branch="main")

assert "Initialized empty Git repository" in result
# Check if HEAD points to the correct branch
head_content = (tmp_path / ".git" / "HEAD").read_text()
assert "ref: refs/heads/main" in head_content


def test_git_init_shared(tmp_path: pathlib.Path) -> None:
"""Test git init with shared repository settings."""
repo = git.Git(path=tmp_path)

# Test boolean shared
result = repo.init(shared=True)
assert "Initialized empty shared Git repository" in result

# Test string shared value
repo_dir = tmp_path / "shared_group"
repo_dir.mkdir()
repo = git.Git(path=repo_dir)
result = repo.init(shared="group")
assert "Initialized empty shared Git repository" in result


def test_git_init_quiet(tmp_path: pathlib.Path) -> None:
"""Test git init with quiet flag."""
repo = git.Git(path=tmp_path)
result = repo.init(quiet=True)
# Quiet mode should suppress normal output
assert result == "" or "Initialized empty Git repository" not in result


def test_git_init_object_format(tmp_path: pathlib.Path) -> None:
"""Test git init with different object formats."""
repo = git.Git(path=tmp_path)

# Test with sha1 (default)
result = repo.init(object_format="sha1")
assert "Initialized empty Git repository" in result

# Note: sha256 test is commented out as it might not be supported in all
# git versions
# repo_dir = tmp_path / "sha256"
# repo_dir.mkdir()
# repo = git.Git(path=repo_dir)
# result = repo.init(object_format="sha256")
# assert "Initialized empty Git repository" in result


def test_git_reinit(tmp_path: pathlib.Path) -> None:
"""Test reinitializing an existing repository."""
repo = git.Git(path=tmp_path)

# Initial init
first_result = repo.init()
assert "Initialized empty Git repository" in first_result

# Reinit
second_result = repo.init()
assert "Reinitialized existing Git repository" in second_result
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy