Coverage for src/debputy/plugins/debputy/debputy_plugin.py: 100%
86 statements
« prev ^ index » next coverage.py v7.8.2, created at 2026-01-16 17:20 +0000
« prev ^ index » next coverage.py v7.8.2, created at 2026-01-16 17:20 +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 )
157 api.packager_provided_file(
158 "bug-control",
159 "/usr/share/bug/{name}/control",
160 allow_name_segment=False,
161 )
163 api.packager_provided_file(
164 "bug-presubj",
165 "/usr/share/bug/{name}/presubj",
166 allow_name_segment=False,
167 )
169 api.packager_provided_file("pam", "/usr/lib/pam.d/{name}")
170 api.packager_provided_file(
171 "ppp.ip-up",
172 "/etc/ppp/ip-up.d/{name}",
173 default_mode=0o0755,
174 )
175 api.packager_provided_file(
176 "ppp.ip-down",
177 "/etc/ppp/ip-down.d/{name}",
178 default_mode=0o0755,
179 )
180 api.packager_provided_file(
181 "lintian-overrides",
182 "/usr/share/lintian/overrides/{name}",
183 allow_name_segment=False,
184 )
185 api.packager_provided_file("logrotate", "/etc/logrotate.d/{name}")
186 api.packager_provided_file(
187 "logcheck.cracking",
188 "/etc/logcheck/cracking.d/{name}",
189 post_formatting_rewrite=_replace_dot_with_underscore,
190 )
191 api.packager_provided_file(
192 "logcheck.violations",
193 "/etc/logcheck/violations.d/{name}",
194 post_formatting_rewrite=_replace_dot_with_underscore,
195 )
196 api.packager_provided_file(
197 "logcheck.violations.ignore",
198 "/etc/logcheck/violations.ignore.d/{name}",
199 post_formatting_rewrite=_replace_dot_with_underscore,
200 )
201 api.packager_provided_file(
202 "logcheck.ignore.workstation",
203 "/etc/logcheck/ignore.d.workstation/{name}",
204 post_formatting_rewrite=_replace_dot_with_underscore,
205 )
206 api.packager_provided_file(
207 "logcheck.ignore.server",
208 "/etc/logcheck/ignore.d.server/{name}",
209 post_formatting_rewrite=_replace_dot_with_underscore,
210 )
211 api.packager_provided_file(
212 "logcheck.ignore.paranoid",
213 "/etc/logcheck/ignore.d.paranoid/{name}",
214 post_formatting_rewrite=_replace_dot_with_underscore,
215 )
217 api.packager_provided_file("mime", "/usr/lib/mime/packages/{name}")
218 api.packager_provided_file("sharedmimeinfo", "/usr/share/mime/packages/{name}.xml")
220 api.packager_provided_file(
221 "if-pre-up",
222 "/etc/network/if-pre-up.d/{name}",
223 default_mode=0o0755,
224 )
225 api.packager_provided_file(
226 "if-up",
227 "/etc/network/if-up.d/{name}",
228 default_mode=0o0755,
229 )
230 api.packager_provided_file(
231 "if-down",
232 "/etc/network/if-down.d/{name}",
233 default_mode=0o0755,
234 )
235 api.packager_provided_file(
236 "if-post-down",
237 "/etc/network/if-post-down.d/{name}",
238 default_mode=0o0755,
239 )
241 api.packager_provided_file(
242 "cron.hourly",
243 "/etc/cron.hourly/{name}",
244 default_mode=0o0755,
245 )
246 api.packager_provided_file(
247 "cron.daily",
248 "/etc/cron.daily/{name}",
249 default_mode=0o0755,
250 )
251 api.packager_provided_file(
252 "cron.weekly",
253 "/etc/cron.weekly/{name}",
254 default_mode=0o0755,
255 )
256 api.packager_provided_file(
257 "cron.monthly",
258 "./etc/cron.monthly/{name}",
259 default_mode=0o0755,
260 )
261 api.packager_provided_file(
262 "cron.yearly",
263 "/etc/cron.yearly/{name}",
264 default_mode=0o0755,
265 )
266 # cron.d uses 0644 unlike the others
267 api.packager_provided_file(
268 "cron.d",
269 "/etc/cron.d/{name}",
270 reference_documentation=packager_provided_file_reference_documentation(
271 format_documentation_uris=["man:crontab(5)"]
272 ),
273 )
275 api.packager_provided_file(
276 "initramfs-hook", f"{INITRAMFS_HOOK_DIR}/{ name} ", default_mode=0o0755
277 )
279 api.packager_provided_file("modprobe", "/usr/lib/modprobe.d/{name}.conf")
281 api.packager_provided_file(
282 "init",
283 "/etc/init.d/{name}",
284 default_mode=0o755,
285 )
286 api.packager_provided_file("default", "/etc/default/{name}")
288 for stem in [
289 "mount",
290 "path",
291 "service",
292 "socket",
293 "target",
294 "timer",
295 ]:
296 api.packager_provided_file(
297 stem,
298 f"/usr/lib/systemd/system/{ name} .{stem}",
299 reference_documentation=packager_provided_file_reference_documentation(
300 format_documentation_uris=[f"man:systemd.{stem}(5)"]
301 ),
302 )
304 for stem in [
305 "path",
306 "service",
307 "socket",
308 "target",
309 "timer",
310 ]:
311 api.packager_provided_file(
312 f"@{stem}", f"/usr/lib/systemd/system/{ name} @.{stem}"
313 )
315 api.packager_provided_file(
316 "udev",
317 "/usr/lib/udev/rules.d/{priority:02}-{name}.rules",
318 default_priority=60,
319 )
321 api.packager_provided_file(
322 "gsettings-override",
323 f"{GSETTINGS_SCHEMA_DIR}/{ priority:02} _{ name} .gschema.override",
324 default_priority=10,
325 )
327 # Special-cases that will probably not be a good example for other plugins
328 api.packager_provided_file(
329 "changelog",
330 # The "changelog.Debian" gets renamed to "changelog" for native packages elsewhere.
331 # Also, the changelog trimming is also done elsewhere.
332 "/usr/share/doc/{name}/changelog.Debian",
333 allow_name_segment=False,
334 packageless_is_fallback_for_all_packages=True,
335 reference_documentation=packager_provided_file_reference_documentation(
336 description=textwrap.dedent(
337 """\
338 This file is the changelog of the package and is mandatory.
340 The changelog contains the version of the source package and is mandatory for all
341 packages.
343 Use `dch --create` to create the changelog.
345 In theory, the binary package can have a different changelog than the source
346 package (by having `debian/binary-package.changelog`). However, it is generally
347 not useful and leads to double administration. It has not been used in practice.
348 """
349 ),
350 format_documentation_uris=[
351 "man:deb-changelog(5)",
352 "https://www.debian.org/doc/debian-policy/ch-source.html#debian-changelog-debian-changelog",
353 "man:dch(1)",
354 ],
355 ),
356 )
357 api.packager_provided_file(
358 "copyright",
359 "/usr/share/doc/{name}/copyright",
360 allow_name_segment=False,
361 packageless_is_fallback_for_all_packages=True,
362 reference_documentation=packager_provided_file_reference_documentation(
363 description=textwrap.dedent(
364 """\
365 This file documents the license and copyright information of the binary package.
366 Packages aimed at the Debian archive (and must derivatives thereof) must have this file.
368 For packages not aimed at Debian, the file can still be useful to convey the license
369 terms of the package (which is often a requirement in many licenses). However, it is
370 not a strict *technical* requirement. Whether it is a legal requirement depends on
371 license.
373 Often, the same file can be used for all packages. In the extremely rare case where
374 one binary package has a "vastly different" license than the other packages, you can
375 provide a package specific version for that package.
376 """
377 ),
378 format_documentation_uris=[
379 "https://www.debian.org/doc/debian-policy/ch-source.html#copyright-debian-copyright",
380 "https://www.debian.org/doc/debian-policy/ch-docs.html#s-copyrightfile",
381 "https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/",
382 ],
383 ),
384 )
385 api.packager_provided_file(
386 "NEWS",
387 "/usr/share/doc/{name}/NEWS.Debian",
388 allow_name_segment=False,
389 packageless_is_fallback_for_all_packages=True,
390 reference_documentation=packager_provided_file_reference_documentation(
391 description=textwrap.dedent(
392 """\
393 Important news that should be shown to the user/admin when upgrading. If a system has
394 apt-listchanges installed, then contents of this file will be shown prior to upgrading
395 the package.
397 Uses a similar format to that of debian/changelog (create with `dch --news --create`).
398 """
399 ),
400 format_documentation_uris=[
401 "https://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.en.html#supplementing-changelogs-with-news-debian-files",
402 "man:dch(1)",
403 ],
404 ),
405 )
406 api.packager_provided_file(
407 "README.Debian",
408 "/usr/share/doc/{name}/README.Debian",
409 allow_name_segment=False,
410 )
411 api.packager_provided_file(
412 "TODO",
413 "/usr/share/doc/{name}/TODO.Debian",
414 allow_name_segment=False,
415 )
416 # From dh-python / dh_python3
417 # api.packager_provided_file(
418 # "bcep",
419 # "/usr/share/python3/bcep/{name}",
420 # allow_name_segment=False,
421 # )
424def _replace_dot_with_underscore(x: str) -> str:
425 return x.replace(".", "_")