10 class DataclassEncoder(json
.JSONEncoder
):
11 def default(self
, it
):
12 if dataclasses
.is_dataclass(it
):
13 return dataclasses
.asdict(it
)
14 return super().default(it
)
17 @dataclasses.dataclass
20 description
: str |
None
24 def __hash__(self
) -> int:
25 return hash(self
.name
)
28 def from_yaml(cls
, path
: pathlib
.Path
):
29 data
= yaml
.safe_load(path
.open())
31 name
=data
["identifier"],
32 description
=data
["description"],
33 project_path
=data
["projectpath"],
34 repo_path
=data
["repopath"]
38 def get_git_commit(path
: pathlib
.Path
):
39 return subprocess
.check_output(["git", "-C", path
, "rev-parse", "--short", "HEAD"]).decode().strip()
42 def validate_unique(projects
: list[Project
], attr
: str):
45 attr_value
= getattr(item
, attr
)
46 if attr_value
in seen
:
47 raise Exception(f
"Duplicate {attr}: {attr_value}")
52 "third-party/appstream": "appstream-qt",
53 "third-party/cmark": "cmark",
54 "third-party/gpgme": "gpgme",
55 "third-party/kdsoap": "kdsoap",
56 "third-party/libaccounts-qt": "accounts-qt",
57 "third-party/libgpg-error": "libgpg-error",
58 "third-party/libquotient": "libquotient",
59 "third-party/packagekit-qt": "packagekit-qt",
60 "third-party/poppler": "poppler",
61 "third-party/qcoro": "qcoro",
62 "third-party/qmltermwidget": "qmltermwidget",
63 "third-party/qtkeychain": "qtkeychain",
64 "third-party/signond": "signond",
65 "third-party/taglib": "taglib",
66 "third-party/wayland-protocols": "wayland-protocols",
67 "third-party/wayland": "wayland",
68 "third-party/zxing-cpp": "zxing-cpp",
72 "kdesupport/phonon-directshow",
73 "kdesupport/phonon-mmf",
74 "kdesupport/phonon-mplayer",
75 "kdesupport/phonon-quicktime",
76 "kdesupport/phonon-waveout",
77 "kdesupport/phonon-xine"
83 @dataclasses.dataclass
84 class KDERepoMetadata
:
86 projects
: list[Project
]
87 dep_graph
: dict[Project
, set[Project
]]
89 @functools.cached_property
90 def projects_by_name(self
):
91 return {p
.name
: p
for p
in self
.projects
}
93 @functools.cached_property
94 def projects_by_path(self
):
95 return {p
.project_path
: p
for p
in self
.projects
}
97 def try_lookup_package(self
, path
):
100 project
= self
.projects_by_path
.get(path
)
101 if project
is None and path
not in WARNED
:
103 print(f
"Warning: unknown project {path}")
107 def from_repo_metadata_checkout(cls
, repo_metadata
: pathlib
.Path
):
109 Project
.from_yaml(metadata_file
)
110 for metadata_file
in repo_metadata
.glob("projects-invent/**/metadata.yaml")
112 Project(id, None, project_path
, None)
113 for project_path
, id in THIRD_PARTY
.items()
116 validate_unique(projects
, "name")
117 validate_unique(projects
, "project_path")
120 version
=get_git_commit(repo_metadata
),
125 dep_specs
= ["dependency-data-stable-kf6-qt6"]
126 dep_graph
= collections
.defaultdict(set)
128 for spec
in dep_specs
:
129 spec_path
= repo_metadata
/ "dependencies" / spec
130 for line
in spec_path
.open():
132 if line
.startswith("#"):
137 dependent
, dependency
= line
.split(": ")
139 dependent
= self
.try_lookup_package(dependent
)
140 if dependent
is None:
143 dependency
= self
.try_lookup_package(dependency
)
144 if dependency
is None:
147 dep_graph
[dependent
].add(dependency
)
149 self
.dep_graph
= dep_graph
153 def write_json(self
, root
: pathlib
.Path
):
154 root
.mkdir(parents
=True, exist_ok
=True)
156 with (root
/ "projects.json").open("w") as fd
:
157 json
.dump(self
.projects_by_name
, fd
, cls
=DataclassEncoder
, sort_keys
=True, indent
=2)
159 with (root
/ "dependencies.json").open("w") as fd
:
160 deps
= {k
.name
: sorted(dep
.name
for dep
in v
) for k
, v
in self
.dep_graph
.items()}
161 json
.dump({"version": self
.version
, "dependencies": deps
}, fd
, cls
=DataclassEncoder
, sort_keys
=True, indent
=2)
164 def from_json(cls
, root
: pathlib
.Path
):
166 Project(**v
) for v
in json
.load((root
/ "projects.json").open()).values()
169 deps
= json
.load((root
/ "dependencies.json").open())
171 version
=deps
["version"],
176 dep_graph
= collections
.defaultdict(set)
177 for dependent
, dependencies
in deps
["dependencies"].items():
178 for dependency
in dependencies
:
179 dep_graph
[self
.projects_by_name
[dependent
]].add(self
.projects_by_name
[dependency
])
181 self
.dep_graph
= dep_graph