Skip to content

Commit

Permalink
Fixed git worktree issue
Browse files Browse the repository at this point in the history
- uses the correct git command depending on the parameters passed.
  • Loading branch information
coordt committed Oct 22, 2023
1 parent 2232682 commit e27636c
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 7 deletions.
30 changes: 23 additions & 7 deletions cookie_composer/git_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from pathlib import Path
from typing import Iterator, Optional, Union

from git import InvalidGitRepositoryError, NoSuchPathError, Repo
from git import GitCommandError, InvalidGitRepositoryError, NoSuchPathError, Repo

from cookie_composer.exceptions import GitError
from cookie_composer.utils import echo
Expand Down Expand Up @@ -194,14 +194,22 @@ def apply_patch(repo: Repo, diff: str) -> None:

@contextmanager
def temp_git_worktree_dir(
repo_path: Path, worktree_path: Optional[Path] = None, branch: str = "master", commit: Optional[str] = None
repo_path: Path, worktree_path: Optional[Path] = None, branch: Optional[str] = None, commit: Optional[str] = None
) -> Iterator[Path]:
"""
Context Manager for a temporary working directory of a branch in a git repo.
Inspired by https://github.com/thomasjahoda/cookiecutter_project_upgrader/blob/master/
cookiecutter_project_upgrader/logic.py
Logic for checking out a branch or commit:
- If a commit is provided, use that
- If a branch is provided, and it is not the current branch, use that
- If a branch is provided, and it is the current branch, use the current commit
- If neither a branch nor a commit is provided, use the current branch and commit
Args:
repo_path: The path to the template git repo
worktree_path: The path put the worktree in. Defaults to a temporary directory.
Expand All @@ -210,19 +218,27 @@ def temp_git_worktree_dir(
Yields:
The worktree_path
Raises:
GitError: If the worktree could not be created
"""
# Create a temporary working directory of a branch in a git repo.
repo = get_repo(repo_path)

tmp_dir = Path(tempfile.mkdtemp(prefix=repo_path.name))
worktree_path = worktree_path or tmp_dir
worktree_path.mkdir(parents=True, exist_ok=True)
repo.git.worktree(
"add",
str(worktree_path),
commit or branch,
)

branch_is_active_branch = branch is None or branch == repo.active_branch.name
git_cmd = ["add", str(worktree_path), commit or branch]
if branch_is_active_branch and commit is None:
git_cmd = ["add", "-d", str(worktree_path)]

try:
repo.git.worktree(*git_cmd)
yield Path(worktree_path)
except GitCommandError as e:
raise GitError(f"Could not create a worktree for {repo_path}") from e

Check warning on line 241 in cookie_composer/git_commands.py

View check run for this annotation

Codecov / codecov/patch

cookie_composer/git_commands.py#L240-L241

Added lines #L240 - L241 were not covered by tests
finally:
# Clean up the temporary working directory.
shutil.rmtree(worktree_path)
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -265,4 +265,5 @@ exclude = '\.git|tests'
require-return-section-when-returning-nothing = false
arg-type-hints-in-docstring = false
check-return-types = false
check-yield-types = false
quiet = true
52 changes: 52 additions & 0 deletions tests/test_layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,58 @@ def test_render_layer_git_template(fixtures_path: Path, tmp_path: Path):
}


def test_render_layer_git_template_branch(fixtures_path: Path, tmp_path: Path):
"""Render a layer of a git-based template specifying a branch."""
from git import Actor, Repo

template_path = fixtures_path / "template1"
git_tmpl_path = copytree(template_path, tmp_path / "template1")
repo = Repo.init(str(git_tmpl_path))
repo.git.add(".")
repo.index.commit(
message="Another commit", committer=Actor("Bob", "bob@example.com"), commit_date="2022-01-02 10:00:00"
)
repo.create_head("my-branch")
repo.heads["my-branch"].checkout()
git_tmpl_path.joinpath("newfile.md").write_text("Hello World!\n\nThis is a test.\n\nThis is a new line.")
repo.index.add(["newfile.md"])
repo.index.commit(
message="first commit on a branch",
committer=Actor("Bob", "bob@example.com"),
commit_date="2022-01-01 12:00:00",
)
latest_sha = repo.head.commit.hexsha

assert latest_sha is not None

template = Template(
repo=get_template_repo(str(git_tmpl_path), tmp_path, checkout="my-branch"),
)
assert template.repo.format == "git"
assert template.repo.latest_sha == latest_sha

layer_conf = LayerConfig(template=template, no_input=True)
render_dir = tmp_path / "render"
rendered_layer = layers.render_layer(layer_conf, render_dir)
expected_context = template.context
expected_context["repo_name"] = "fake-project-template"
expected_context["repo_slug"] = "fake-project-template"
expected = RenderedLayer(
layer=layer_conf,
location=render_dir,
rendered_context=expected_context,
rendered_commit=latest_sha,
)
assert rendered_layer == expected
assert rendered_layer.latest_commit == latest_sha
assert rendered_layer.layer.template.repo.latest_sha == latest_sha
assert {x.name for x in Path(render_dir / "fake-project-template").iterdir()} == {
"README.md",
"requirements.txt",
"demo.jinja",
}


@pytest.mark.parametrize(
("default_context", "initial_context", "full_context", "expected"),
[
Expand Down

0 comments on commit e27636c

Please sign in to comment.