spgit

A static page generator for git repositories

git clone git://git.janzachar.dev/spgit.git


0from bs4 import BeautifulSoup as bs
1from pathlib import Path
2import git
3import yaml
4import shutil
5
6from templ import index, repo_file, repo_index
7from classes import Meta, Repo
8import settings
9
10
11def gen_page(dest, func, *args):
12    Path.mkdir(dest.parent, parents=True, exist_ok=True)
13    with open(dest, "w") as f:
14        html = func(*args)
15        f.write(bs(html, "html.parser").prettify())
16
17def gen_pages(tree, repo):
18    for entry in tree:
19        dest = settings.BUILD / repo.path.name / "files" / Path(entry.path + ".html")
20
21        if entry.type in ("blob", "tree"):
22            gen_page(dest, repo_file.gen, repo, entry)
23
24        if entry.type == "tree":
25            gen_pages(entry, repo)
26
27def copy_assets():
28    for p in settings.ASSETS.rglob("*"):
29        if p.is_dir():
30            continue
31        base = p.relative_to(settings.ASSETS)
32        target = settings.BUILD / "assets" / base
33
34        if target.exists():
35            src_modified = p.lstat().st_mtime
36            target_modified = target.lstat().st_mtime
37
38            if src_modified <= target_modified:
39                continue
40
41        Path.mkdir(target.parent, parents=True, exist_ok=True)
42        p.copy(target)
43        print(f"Copying {base} => {target}")
44
45def filter_new(repos):
46    out = []
47    for r in repos:
48        target = Path(settings.BUILD) / r.path.name
49        if target.exists():
50            # get latest modification date inside repo dir
51            src_modified = max(f.lstat().st_mtime for f in r.path.iterdir())
52
53            # index.html is guaranteed to be modified with each repo update
54            target_modified = (target / "index.html").lstat().st_mtime
55
56            if src_modified > target_modified:
57                out.append(r)
58            else:
59                print(target, "is up to date")
60        else:
61            print("No target!")
62            out.append(r)
63    return out
64
65
66def main():
67    # 0. Copy assets
68    copy_assets()
69
70    # 1. Retrieve valid repos at settings.SRC/*
71    repos = [Repo(p) for p in settings.SRC.iterdir()]
72    repos = [*filter((lambda x: x.valid), repos)]
73
74    # 2. Get rid of the old ones
75    cand = filter_new(repos)
76    print(len(repos), "=>", len(cand))
77
78    # 3. Generate main page
79    print("Generating main page...")
80    gen_page(settings.BUILD / "index.html", index.gen, repos)
81
82    # 4. Generate repo pages
83    if not cand:
84        print("Nothing to do...")
85        return 0
86
87    for c in cand:
88        print(f"Generating {c.path.name} ...")
89        dest = settings.BUILD / c.path.name / "index.html"
90        gen_page(dest, repo_index.gen, c)
91
92        tree = c.repo.head.commit.tree
93        gen_pages(tree, c)
94
95if __name__ == "__main__":
96    exit(main())
97
98