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
from __future__ import annotations
import os
import tempfile
import zipfile
from pathlib import Path
from pygitweb.api.project import Project
from pygitweb.tasks import create_board_for_project
class ProjectZip(Project):
def __init__(
self,
path: os.PathLike[str] | str,
zip_content: bytes,
create_task_board: bool = False,
do_maintenance: bool = False,
) -> None:
self.path: str = str(Path(path))
with tempfile.TemporaryDirectory() as tmpdir:
zip_path = os.path.join(tmpdir, "repo.zip")
with open(zip_path, "wb") as file_obj:
file_obj.write(zip_content)
with zipfile.ZipFile(zip_path, "r") as zip_file:
zip_file.extractall(tmpdir)
repo_root: str = self._discover_repo_root(tmpdir)
super().__init__(
path=self.path,
remote_url=repo_root,
create_task_board=False,
do_maintenance=do_maintenance,
)
if create_task_board:
create_board_for_project(Path(self.path).name, name="Tasks", description="")
@staticmethod
def _discover_repo_root(tmpdir: str) -> str:
for name in os.listdir(tmpdir):
if name == "repo.zip":
continue
candidate = os.path.join(tmpdir, name)
if os.path.isdir(candidate) and os.path.isdir(os.path.join(candidate, ".git")):
return candidate
if os.path.isdir(os.path.join(tmpdir, ".git")):
return tmpdir
subdirs: list[str] = [
name for name in os.listdir(tmpdir) if name != "repo.zip" and os.path.isdir(os.path.join(tmpdir, name))
]
if len(subdirs) == 1:
return os.path.join(tmpdir, subdirs[0])
for name in os.listdir(tmpdir):
if name != "repo.zip":
candidate = os.path.join(tmpdir, name)
if os.path.isdir(candidate):
return candidate
return tmpdir
@classmethod
def form_content(cls) -> str:
return (
'<label class="form-label" for="repo_zip">Upload .zip (git repo)</label>'
'<div class="dropzone border rounded p-4 text-center" id="dropzone" style="min-height: 120px;">'
'<input type="file" class="form-control d-none" id="repo_zip" name="repo_zip" accept=".zip" '
"data-dropzone-target>"
'<div class="dropzone-placeholder text-muted" data-dropzone-placeholder>'
"Drag a .zip file here or click to choose."
"</div>"
'<div class="dropzone-filename d-none text-start small mt-2" data-dropzone-filename></div>'
"</div>"
)