Coverage for src/debputy/plugins/debputy/debputy_plugin.py: 100%
86 statements
« prev ^ index » next coverage.py v7.8.2, created at 2026-04-19 20:37 +0000
« prev ^ index » next coverage.py v7.8.2, created at 2026-04-19 20:37 +0000
1import textwrap
3from debputy.plugin.api import (
4 DebputyPluginInitializer,
5 packager_provided_file_reference_documentation,
6)
7from debputy.plugins.debputy.metadata_detectors import (
8 detect_systemd_tmpfiles,
9 detect_kernel_modules,
10 detect_icons,
11 detect_gsettings_dependencies,
12 detect_xfonts,
13 detect_initramfs_hooks,
14 detect_systemd_sysusers,
15 detect_pycompile_files,
16 translate_capabilities,
17 pam_auth_update,
18 auto_depends_arch_any_solink,
19 detect_commands,
20 detect_built_using,
21)
22from debputy.plugins.debputy.paths import (
23 SYSTEMD_TMPFILES_DIR,
24 INITRAMFS_HOOK_DIR,
25 GSETTINGS_SCHEMA_DIR,
26 SYSTEMD_SYSUSERS_DIR,
27)
28from debputy.plugins.debputy.private_api import initialize_via_private_api
29from debputy.util import PackageTypeSelector
32def initialize_debputy_features(api: DebputyPluginInitializer) -> None:
33 initialize_via_private_api(api)
34 declare_manifest_variables(api)
35 register_packager_provided_files(api)
36 register_package_metadata_detectors(api)
39def declare_manifest_variables(api: DebputyPluginInitializer) -> None:
40 api.manifest_variable(
41 "path:BASH_COMPLETION_DIR",
42 "/usr/share/bash-completion/completions",
43 variable_reference_documentation="Directory to install bash completions into",
44 )
45 api.manifest_variable(
46 "path:FISH_COMPLETION_DIR",
47 "/usr/share/fish/vendor_completions.d",
48 variable_reference_documentation="Directory to install fish completions into",
49 )
50 api.manifest_variable(
51 "path:ZSH_COMPLETION_DIR",
52 "/usr/share/zsh/vendor-completions",
53 variable_reference_documentation="Directory to install zsh completions into",
54 )
55 api.manifest_variable(
56 "path:GNU_INFO_DIR",
57 "/usr/share/info",
58 variable_reference_documentation="Directory to install GNU INFO files into",
59 )
61 api.manifest_variable(
62 "token:NL",
63 "\n",
64 variable_reference_documentation="Literal newline (linefeed) character",
65 )
66 api.manifest_variable(
67 "token:NEWLINE",
68 "\n",
69 variable_reference_documentation="Literal newline (linefeed) character",
70 )
71 api.manifest_variable(
72 "token:TAB",
73 "\t",
74 variable_reference_documentation="Literal tab character",
75 )
76 api.manifest_variable(
77 "token:OPEN_CURLY_BRACE",
78 "{",
79 variable_reference_documentation='Literal "{" character',
80 )
81 api.manifest_variable(
82 "token:CLOSE_CURLY_BRACE",
83 "}",
84 variable_reference_documentation='Literal "}" character',
85 )
86 api.manifest_variable(
87 "token:DOUBLE_OPEN_CURLY_BRACE",
88 "{{",
89 variable_reference_documentation='Literal "{{" character - useful to avoid triggering a substitution',
90 )
91 api.manifest_variable(
92 "token:DOUBLE_CLOSE_CURLY_BRACE",
93 "}}",
94 variable_reference_documentation='Literal "}}" string - useful to avoid triggering a substitution',
95 )
98def register_package_metadata_detectors(api: DebputyPluginInitializer) -> None:
99 api.metadata_or_maintscript_detector("systemd-tmpfiles", detect_systemd_tmpfiles)
100 api.metadata_or_maintscript_detector("systemd-sysusers", detect_systemd_sysusers)
101 api.metadata_or_maintscript_detector("list-commands", detect_commands)
102 api.metadata_or_maintscript_detector("kernel-modules", detect_kernel_modules)
103 api.metadata_or_maintscript_detector("icon-cache", detect_icons)
104 api.metadata_or_maintscript_detector(
105 "gsettings-dependencies",
106 detect_gsettings_dependencies,
107 )
108 api.metadata_or_maintscript_detector("xfonts", detect_xfonts)
109 api.metadata_or_maintscript_detector("initramfs-hooks", detect_initramfs_hooks)
110 api.metadata_or_maintscript_detector("pycompile-files", detect_pycompile_files)
111 api.metadata_or_maintscript_detector(
112 "translate-capabilities",
113 translate_capabilities,
114 )
115 api.metadata_or_maintscript_detector("pam-auth-update", pam_auth_update)
116 api.metadata_or_maintscript_detector(
117 "auto-depends-arch-any-solink",
118 auto_depends_arch_any_solink,
119 )
120 api.metadata_or_maintscript_detector(
121 "built-using-relations",
122 detect_built_using,
123 package_types=PackageTypeSelector.DEB | PackageTypeSelector.UDEB,
124 )
127def register_packager_provided_files(api: DebputyPluginInitializer) -> None:
128 api.packager_provided_file(
129 "tmpfiles",
130 f"{SYSTEMD_TMPFILES_DIR}/{ name} .conf",
131 reference_documentation=packager_provided_file_reference_documentation(
132 format_documentation_uris=["man:tmpfiles.d(5)"]
133 ),
134 )
135 api.packager_provided_file(
136 "sysusers",
137 f"{SYSTEMD_SYSUSERS_DIR}/{ name} .conf",
138 reference_documentation=packager_provided_file_reference_documentation(
139 format_documentation_uris=["man:sysusers.d(5)"]
140 ),
141 )
142 api.packager_provided_file(
143 "bash-completion", "/usr/share/bash-completion/completions/{name}"
144 )
145 api.packager_provided_file(
146 "fish-completion", "/usr/share/fish/vendor_completions.d/{name}"
147 )
148 api.packager_provided_file(
149 "zsh-completion", "/usr/share/zsh/vendor-completions/{name}"
150 )
151 api.packager_provided_file(
152 "bug-script",
153 "./usr/share/bug/{name}/script",
154 default_mode=0o0755,
155 allow_name_segment=False,
156 package_types=PackageTypeSelector.DEB,
157 )
158 api.packager_provided_file(
159 "bug-control",
160 "/usr/share/bug/{name}/control",
161 allow_name_segment=False,
162 package_types=PackageTypeSelector.DEB,
163 )
165 api.packager_provided_file(
166 "bug-presubj",
167 "/usr/share/bug/{name}/presubj",
168 allow_name_segment=False,
169 package_types=PackageTypeSelector.DEB,
170 )
172 api.packager_provided_file("pam", "/usr/lib/pam.d/{name}")
173 api.packager_provided_file(
174 "ppp.ip-up",
175 "/etc/ppp/ip-up.d/{name}",
176 default_mode=0o0755,
177 )
178 api.packager_provided_file(
179 "ppp.ip-down",
180 "/etc/ppp/ip-down.d/{name}",
181 default_mode=0o0755,
182 )
183 api.packager_provided_file(
184 "lintian-overrides",
185 "/usr/share/lintian/overrides/{name}",
186 allow_name_segment=False,
187 package_types=PackageTypeSelector.DEB,
188 )
189 api.packager_provided_file("logrotate", "/etc/logrotate.d/{name}")
190 api.packager_provided_file(
191 "logcheck.cracking",
192 "/etc/logcheck/cracking.d/{name}",
193 post_formatting_rewrite=_replace_dot_with_underscore,
194 )
195 api.packager_provided_file(
196 "logcheck.violations",
197 "/etc/logcheck/violations.d/{name}",
198 post_formatting_rewrite=_replace_dot_with_underscore,
199 )
200 api.packager_provided_file(
201 "logcheck.violations.ignore",
202 "/etc/logcheck/violations.ignore.d/{name}",
203 post_formatting_rewrite=_replace_dot_with_underscore,
204 )
205 api.packager_provided_file(
206 "logcheck.ignore.workstation",
207 "/etc/logcheck/ignore.d.workstation/{name}",
208 post_formatting_rewrite=_replace_dot_with_underscore,
209 )
210 api.packager_provided_file(
211 "logcheck.ignore.server",
212 "/etc/logcheck/ignore.d.server/{name}",
213 post_formatting_rewrite=_replace_dot_with_underscore,
214 )
215 api.packager_provided_file(
216 "logcheck.ignore.paranoid",
217 "/etc/logcheck/ignore.d.paranoid/{name}",
218 post_formatting_rewrite=_replace_dot_with_underscore,
219 )
221 api.packager_provided_file("mime", "/usr/lib/mime/packages/{name}")
222 api.packager_provided_file("sharedmimeinfo", "/usr/share/mime/packages/{name}.xml")
224 api.packager_provided_file(
225 "if-pre-up",
226 "/etc/network/if-pre-up.d/{name}",
227 default_mode=0o0755,
228 )
229 api.packager_provided_file(
230 "if-up",
231 "/etc/network/if-up.d/{name}",
232 default_mode=0o0755,
233 )
234 api.packager_provided_file(
235 "if-down",
236 "/etc/network/if-down.d/{name}",
237 default_mode=0o0755,
238 )
239 api.packager_provided_file(
240 "if-post-down",
241 "/etc/network/if-post-down.d/{name}",
242 default_mode=0o0755,
243 )
245 api.packager_provided_file(
246 "cron.hourly",
247 "/etc/cron.hourly/{name}",
248 default_mode=0o0755,
249 )
250 api.packager_provided_file(
251 "cron.daily",
252 "/etc/cron.daily/{name}",
253 default_mode=0o0755,
254 )
255 api.packager_provided_file(
256 "cron.weekly",
257 "/etc/cron.weekly/{name}",
258 default_mode=0o0755,
259 )
260 api.packager_provided_file(
261 "cron.monthly",
262 "./etc/cron.monthly/{name}",
263 default_mode=0o0755,
264 )
265 api.packager_provided_file(
266 "cron.yearly",
267 "/etc/cron.yearly/{name}",
268 default_mode=0o0755,
269 )
270 # cron.d uses 0644 unlike the others
271 api.packager_provided_file(
272 "cron.d",
273 "/etc/cron.d/{name}",
274 reference_documentation=packager_provided_file_reference_documentation(
275 format_documentation_uris=["man:crontab(5)"]
276 ),
277 )
279 api.packager_provided_file(
280 "initramfs-hook", f"{INITRAMFS_HOOK_DIR}/{ name} ", default_mode=0o0755
281 )
283 api.packager_provided_file("modprobe", "/usr/lib/modprobe.d/{name}.conf")
285 api.packager_provided_file(
286 "init",
287 "/etc/init.d/{name}",
288 default_mode=0o755,
289 )
290 api.packager_provided_file("default", "/etc/default/{name}")
292 for stem in [
293 "mount",
294 "path",
295 "service",
296 "socket",
297 "target",
298 "timer",
299 ]:
300 api.packager_provided_file(
301 stem,
302 f"/usr/lib/systemd/system/{ name} .{stem}",
303 reference_documentation=packager_provided_file_reference_documentation(
304 format_documentation_uris=[f"man:systemd.{stem}(5)"]
305 ),
306 )
308 for stem in [
309 "path",
310 "service",
311 "socket",
312 "target",
313 "timer",
314 ]:
315 api.packager_provided_file(
316 f"@{stem}", f"/usr/lib/systemd/system/{ name} @.{stem}"
317 )
319 api.packager_provided_file(
320 "udev",
321 "/usr/lib/udev/rules.d/{priority:02}-{name}.rules",
322 default_priority=60,
323 )
325 api.packager_provided_file(
326 "gsettings-override",
327 f"{GSETTINGS_SCHEMA_DIR}/{ priority:02} _{ name} .gschema.override",
328 default_priority=10,
329 )
331 # Special-cases that will probably not be a good example for other plugins
332 api.packager_provided_file(
333 "changelog",
334 # The "changelog.Debian" gets renamed to "changelog" for native packages elsewhere.
335 # Also, the changelog trimming is also done elsewhere.
336 "/usr/share/doc/{name}/changelog.Debian",
337 allow_name_segment=False,
338 packageless_is_fallback_for_all_packages=True,
339 package_types=PackageTypeSelector.DEB,
340 reference_documentation=packager_provided_file_reference_documentation(
341 description=textwrap.dedent("""\
342 This file is the changelog of the package and is mandatory.
344 The changelog contains the version of the source package and is mandatory for all
345 packages.
347 Use `dch --create` to create the changelog.
349 In theory, the binary package can have a different changelog than the source
350 package (by having `debian/binary-package.changelog`). However, it is generally
351 not useful and leads to double administration. It has not been used in practice.
352 """),
353 format_documentation_uris=[
354 "man:deb-changelog(5)",
355 "https://www.debian.org/doc/debian-policy/ch-source.html#debian-changelog-debian-changelog",
356 "man:dch(1)",
357 ],
358 ),
359 )
360 api.packager_provided_file(
361 "copyright",
362 "/usr/share/doc/{name}/copyright",
363 allow_name_segment=False,
364 packageless_is_fallback_for_all_packages=True,
365 package_types=PackageTypeSelector.DEB,
366 reference_documentation=packager_provided_file_reference_documentation(
367 description=textwrap.dedent("""\
368 This file documents the license and copyright information of the binary package.
369 Packages aimed at the Debian archive (and must derivatives thereof) must have this file.
371 For packages not aimed at Debian, the file can still be useful to convey the license
372 terms of the package (which is often a requirement in many licenses). However, it is
373 not a strict *technical* requirement. Whether it is a legal requirement depends on
374 license.
376 Often, the same file can be used for all packages. In the extremely rare case where
377 one binary package has a "vastly different" license than the other packages, you can
378 provide a package specific version for that package.
379 """),
380 format_documentation_uris=[
381 "https://www.debian.org/doc/debian-policy/ch-source.html#copyright-debian-copyright",
382 "https://www.debian.org/doc/debian-policy/ch-docs.html#s-copyrightfile",
383 "https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/",
384 ],
385 ),
386 )
387 api.packager_provided_file(
388 "NEWS",
389 "/usr/share/doc/{name}/NEWS.Debian",
390 allow_name_segment=False,
391 packageless_is_fallback_for_all_packages=True,
392 package_types=PackageTypeSelector.DEB,
393 reference_documentation=packager_provided_file_reference_documentation(
394 description=textwrap.dedent("""\
395 Important news that should be shown to the user/admin when upgrading. If a system has
396 apt-listchanges installed, then contents of this file will be shown prior to upgrading
397 the package.
399 Uses a similar format to that of debian/changelog (create with `dch --news --create`).
400 """),
401 format_documentation_uris=[
402 "https://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.en.html#supplementing-changelogs-with-news-debian-files",
403 "man:dch(1)",
404 ],
405 ),
406 )
407 api.packager_provided_file(
408 "README.Debian",
409 "/usr/share/doc/{name}/README.Debian",
410 allow_name_segment=False,
411 package_types=PackageTypeSelector.DEB,
412 )
413 api.packager_provided_file(
414 "TODO",
415 "/usr/share/doc/{name}/TODO.Debian",
416 allow_name_segment=False,
417 package_types=PackageTypeSelector.DEB,
418 )
419 # From dh-python / dh_python3
420 # api.packager_provided_file(
421 # "bcep",
422 # "/usr/share/python3/bcep/{name}",
423 # allow_name_segment=False,
424 # )
427def _replace_dot_with_underscore(x: str) -> str:
428 return x.replace(".", "_")