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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
from __future__ import annotations
from pathlib import Path
import pytest
from pygit2 import init_repository
from pygittools.tui.projects import (
_branch_for_worktree,
_export_ok,
_find_projects_in_dir,
_projects_from_file,
list_projects,
)
from pygittools.tui.pygitweb_layout import PygitwebLayout
def _layout(tmp_path: Path, **overrides: object) -> PygitwebLayout:
root = tmp_path / "root"
root.mkdir()
defaults = {
"projectroot": root,
"projects_list": root,
"project_maxdepth": 2,
"list_all": True,
"export_ok": "",
}
defaults.update(overrides)
return PygitwebLayout(**defaults) # type: ignore[arg-type]
def _init_repo_with_commit(path: Path) -> None:
from pygit2 import Signature, init_repository
repo = init_repository(str(path), bare=False)
workdir = Path(repo.workdir)
(workdir / "README").write_text("x\n", encoding="utf-8")
repo.index.add("README")
repo.index.write()
tree = repo.index.write_tree()
sig = Signature("t", "t@example.com")
repo.create_commit("HEAD", sig, sig, "init", tree, [])
def test_list_projects_from_directory(tmp_path: Path) -> None:
layout = _layout(tmp_path)
project = layout.projectroot / "alpha"
project.mkdir()
_init_repo_with_commit(project)
entries = list_projects(layout)
assert len(entries) == 1
assert entries[0].path == "alpha"
assert entries[0].branch in {"main", "master"}
def test_list_projects_from_file(tmp_path: Path) -> None:
layout = _layout(tmp_path)
project = layout.projectroot / "beta"
project.mkdir()
_init_repo_with_commit(project)
projects_file = tmp_path / "projects.txt"
projects_file.write_text("beta\n", encoding="utf-8")
layout = PygitwebLayout(
projectroot=layout.projectroot,
projects_list=projects_file,
project_maxdepth=1,
list_all=True,
export_ok="",
)
entries = list_projects(layout)
assert [entry.path for entry in entries] == ["beta"]
def test_list_projects_respects_export_ok(tmp_path: Path) -> None:
layout = _layout(tmp_path, list_all=False, export_ok="git-daemon-export-ok")
project = layout.projectroot / "hidden"
project.mkdir()
_init_repo_with_commit(project)
assert list_projects(layout) == []
(project / "git-daemon-export-ok").write_text("", encoding="utf-8")
assert len(list_projects(layout)) == 1
def test_list_projects_missing_projects_list(tmp_path: Path) -> None:
layout = PygitwebLayout(
projectroot=tmp_path / "root",
projects_list=tmp_path / "missing",
project_maxdepth=1,
list_all=True,
export_ok="",
)
assert list_projects(layout) == []
def test_projects_from_file_skips_invalid_lines(tmp_path: Path) -> None:
layout = _layout(tmp_path)
projects_file = tmp_path / "projects.txt"
projects_file.write_text("\n \nmissing\n%20encoded\n", encoding="utf-8")
assert (
_projects_from_file(
PygitwebLayout(
projectroot=layout.projectroot,
projects_list=projects_file,
project_maxdepth=1,
list_all=True,
export_ok="",
),
)
== []
)
def test_find_projects_respects_maxdepth(tmp_path: Path) -> None:
layout = _layout(tmp_path, project_maxdepth=1)
deep = layout.projectroot / "a" / "b"
deep.mkdir(parents=True)
init_repository(str(deep), bare=False)
assert _find_projects_in_dir(layout) == []
def test_export_ok_requires_repository(tmp_path: Path) -> None:
path = tmp_path / "not-a-repo"
path.mkdir()
assert _export_ok(path, "") is False
def test_projects_from_file_read_error(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
layout = _layout(tmp_path)
projects_file = tmp_path / "projects.txt"
projects_file.write_text("alpha\n", encoding="utf-8")
def fail_read_text(self: Path, encoding: str = "utf-8") -> str:
raise OSError("nope")
monkeypatch.setattr(Path, "read_text", fail_read_text)
assert (
_projects_from_file(
PygitwebLayout(
projectroot=layout.projectroot,
projects_list=projects_file,
project_maxdepth=1,
list_all=True,
export_ok="",
),
)
== []
)
def test_find_projects_skips_inaccessible_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
layout = _layout(tmp_path)
project = layout.projectroot / "secret"
project.mkdir()
_init_repo_with_commit(project)
monkeypatch.setattr("pygittools.tui.projects.os.access", lambda _path, _mode: False)
assert _find_projects_in_dir(layout) == []
def test_branch_for_invalid_worktree(tmp_path: Path) -> None:
bad = tmp_path / "bad"
bad.mkdir()
assert _branch_for_worktree(bad) == "?"