-
Notifications
You must be signed in to change notification settings - Fork 2
/
save_added_date.py
executable file
·154 lines (122 loc) · 4.81 KB
/
save_added_date.py
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
#!/usr/bin/env python3
import argparse
import tomlkit
import json
from datetime import datetime
from git import Repo, Commit
from pathlib import Path
import logging
from typing import Callable
import appslib.get_apps_repo as get_apps_repo
def git_bisect(repo: Repo, is_newer: Callable[[Commit], bool]) -> Commit | None:
# Start with whole repo
first_commit = repo.git.rev_list("HEAD", reverse=True, max_parents=0)
try:
# If a git bisect is in progress, just erase it
repo.git.bisect("log")
repo.git.bisect("reset")
except Exception:
pass
repo.git.bisect("start", "--no-checkout", "HEAD", first_commit)
while True:
try:
status = "bad" if is_newer(repo.commit("BISECT_HEAD")) else "good"
except Exception:
status = "skip"
result_string = repo.git.bisect(status)
if "is the first bad commit" in result_string.splitlines()[0]:
return repo.commit(result_string.splitlines()[0].split(" ", 1)[0])
def get_app_info(commit: Commit, filebase: str, name: str) -> dict | None:
data = None
try:
filestream = commit.tree.join(f"{filebase}.toml")
filedata = filestream.data_stream.read().decode("utf-8")
dictdata = tomlkit.loads(filedata)
data = dictdata[name]
except KeyError:
pass
try:
filestream = commit.tree.join(f"{filebase}.json")
filedata = filestream.data_stream.read().decode("utf-8")
dictdata = json.loads(filedata)
data = dictdata[name]
except KeyError:
pass
assert isinstance(data, dict) or data is None
return data
def app_is_present(commit: Commit, name: str) -> bool:
info = get_app_info(commit, "apps", name)
# if info is None:
# info = get_app_info(commit, "graveyard", name)
return info is not None
def app_is_deprecated(commit: Commit, name: str) -> bool:
info = get_app_info(commit, "apps", name)
if info is None:
return False
antifeatures = info.get("antifeatures", [])
return "deprecated-software" in antifeatures
def date_added(repo: Repo, name: str) -> int | None:
result = git_bisect(repo, lambda x: app_is_present(x, name))
print(result)
return None if result is None else result.committed_date
def date_deprecated(repo: Repo, name: str) -> int | None:
result = git_bisect(repo, lambda x: app_is_deprecated(x, name))
return None if result is None else result.committed_date
def add_deprecation_dates(repo: Repo, file: Path) -> None:
key = "deprecated_date"
document = tomlkit.load(file.open("r", encoding="utf-8"))
for app, info in document.items():
if key in info.keys():
continue
if "deprecated-software" not in info.get("antifeatures", []):
continue
logging.info(f"Searching deprecated date for {app}...")
date = date_deprecated(repo, app)
if date is None:
continue
info[key] = date
info[key].comment(datetime.fromtimestamp(info[key]).strftime("%Y/%m/%d"))
info[key].trivia.comment_ws = " "
tomlkit.dump(document, file.open("w"))
def date_added_to(repo: Repo, match: str, file: Path) -> int | None:
commits = repo.git.log(
"-S",
match,
"--first-parent",
"--reverse",
"--date=unix",
"--format=%cd",
"--",
str(file),
).splitlines()
if not commits:
return None
first_commit = commits[0]
return int(first_commit)
def add_apparition_dates(repo: Repo, file: Path, key: str) -> None:
document = tomlkit.load(file.open("r", encoding="utf-8"))
for app, info in document.items():
if key in info.keys():
continue
logging.info(f"Searching added date for {key}...")
date = date_added_to(repo, f"[{app}]", file)
assert date is not None
info[key] = date
info[key].comment(datetime.fromtimestamp(info[key]).strftime("%Y/%m/%d"))
info[key].trivia.comment_ws = " "
tomlkit.dump(document, file.open("w"))
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--debug", action="store_true")
get_apps_repo.add_args(parser, allow_temp=False)
args = parser.parse_args()
logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO)
apps_repo_dir = get_apps_repo.from_args(args)
apps_repo = Repo(apps_repo_dir)
add_apparition_dates(apps_repo, apps_repo_dir / "apps.toml", key="added_date")
add_apparition_dates(apps_repo, apps_repo_dir / "wishlist.toml", key="added_date")
add_apparition_dates(apps_repo, apps_repo_dir / "graveyard.toml", key="killed_date")
add_deprecation_dates(apps_repo, apps_repo_dir / "apps.toml")
add_deprecation_dates(apps_repo, apps_repo_dir / "graveyard.toml")
if __name__ == "__main__":
main()