File: helpers.py

package info (click to toggle)
git-changelog 2.7.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 612 kB
  • sloc: python: 4,026; makefile: 33; javascript: 13
file content (110 lines) | stat: -rw-r--r-- 3,180 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
"""Helpers for writing tests."""

from __future__ import annotations

import os
import random
import shutil
import subprocess
import uuid
from contextlib import contextmanager
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from collections.abc import Iterator
    from pathlib import Path


class GitRepo:
    """Test utility class to initalize and work with a Git repository."""

    _git_exec = shutil.which("git") or "git"

    def __init__(self, repo: Path) -> None:
        """Initialization the Git repository wrapper.

        Initializes a new Git repository under the given path.

        Parameters:
            repo: Path to the git repository.
        """
        self.path = repo
        self.path.mkdir(parents=True, exist_ok=True)
        self.git("init", "-b", "main")
        self.git("remote", "add", "origin", "git@github.com:example/example")
        self.first_hash = self.commit("chore: Initial repository creation")

    def git(self, *args: str) -> str:
        """Run a Git command in the repository.

        Parameters:
            *args: Arguments passed to the Git command.

        Returns:
            The output of the command.
        """
        return subprocess.check_output(  # noqa: S603
            [self._git_exec, "-C", str(self.path), *args],
            text=True,
        )

    def commit(self, message: str) -> str:
        """Create, add and commit a new file into the Git repository.

        Parameters:
            message: The commit message.

        Returns:
            The Git commit hash.
        """
        with self.path.joinpath(str(uuid.uuid4())).open("w", encoding="utf8") as fh:
            fh.write(str(random.randint(0, 1)))  # noqa: S311
        self.git("add", "-A")
        self.git("commit", "-m", message)
        return self.git("rev-parse", "HEAD").rstrip()

    def tag(self, tagname: str) -> None:
        """Create a new tag in the GIt repository.

        Parameters:
            tagname: The name of the new tag.
        """
        self.git("tag", tagname)

    def branch(self, branchname: str) -> None:
        """Create a new branch in the Git repository.

        Parameters:
            branchname: The name of the new branch.
        """
        self.git("branch", branchname)

    def checkout(self, branchname: str) -> None:
        """Checkout a branch.

        Parameters:
            branchname: The name of the branch.
        """
        self.git("checkout", branchname)

    def merge(self, branchname: str) -> str:
        """Merge a branch into the current branch, creating a new merge commit.

        Parameters:
            branchname: The name of the branch to merge.

        Returns:
            The Git commit hash of the merge commit.
        """
        self.git("merge", "--no-ff", "--commit", "-m", f"merge: Merge branch '{branchname}'", branchname)
        return self.git("rev-parse", "HEAD").rstrip()

    @contextmanager
    def enter(self) -> Iterator[None]:
        """Context manager to enter the repository directory."""
        old_cwd = os.getcwd()
        os.chdir(self.path)
        try:
            yield
        finally:
            os.chdir(old_cwd)