Coverage for src/debputy/plugin/debputy/debputy_plugin.py: 100%

82 statements  

« prev     ^ index     » next       coverage.py v7.6.0, created at 2025-01-27 13:59 +0000

1import textwrap 

2 

3from debputy.plugin.api import ( 

4 DebputyPluginInitializer, 

5 packager_provided_file_reference_documentation, 

6) 

7from debputy.plugin.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) 

20from debputy.plugin.debputy.paths import ( 

21 SYSTEMD_TMPFILES_DIR, 

22 INITRAMFS_HOOK_DIR, 

23 GSETTINGS_SCHEMA_DIR, 

24 SYSTEMD_SYSUSERS_DIR, 

25) 

26from debputy.plugin.debputy.private_api import initialize_via_private_api 

27 

28 

29def initialize_debputy_features(api: DebputyPluginInitializer) -> None: 

30 initialize_via_private_api(api) 

31 declare_manifest_variables(api) 

32 register_packager_provided_files(api) 

33 register_package_metadata_detectors(api) 

34 

35 

36def declare_manifest_variables(api: DebputyPluginInitializer) -> None: 

37 api.manifest_variable( 

38 "path:BASH_COMPLETION_DIR", 

39 "/usr/share/bash-completion/completions", 

40 variable_reference_documentation="Directory to install bash completions into", 

41 ) 

42 api.manifest_variable( 

43 "path:FISH_COMPLETION_DIR", 

44 "/usr/share/fish/vendor_completions.d", 

45 variable_reference_documentation="Directory to install fish completions into", 

46 ) 

47 api.manifest_variable( 

48 "path:ZSH_COMPLETION_DIR", 

49 "/usr/share/zsh/vendor-completions", 

50 variable_reference_documentation="Directory to install zsh completions into", 

51 ) 

52 api.manifest_variable( 

53 "path:GNU_INFO_DIR", 

54 "/usr/share/info", 

55 variable_reference_documentation="Directory to install GNU INFO files into", 

56 ) 

57 

58 api.manifest_variable( 

59 "token:NL", 

60 "\n", 

61 variable_reference_documentation="Literal newline (linefeed) character", 

62 ) 

63 api.manifest_variable( 

64 "token:NEWLINE", 

65 "\n", 

66 variable_reference_documentation="Literal newline (linefeed) character", 

67 ) 

68 api.manifest_variable( 

69 "token:TAB", 

70 "\t", 

71 variable_reference_documentation="Literal tab character", 

72 ) 

73 api.manifest_variable( 

74 "token:OPEN_CURLY_BRACE", 

75 "{", 

76 variable_reference_documentation='Literal "{" character', 

77 ) 

78 api.manifest_variable( 

79 "token:CLOSE_CURLY_BRACE", 

80 "}", 

81 variable_reference_documentation='Literal "}" character', 

82 ) 

83 api.manifest_variable( 

84 "token:DOUBLE_OPEN_CURLY_BRACE", 

85 "{{", 

86 variable_reference_documentation='Literal "{{" character - useful to avoid triggering a substitution', 

87 ) 

88 api.manifest_variable( 

89 "token:DOUBLE_CLOSE_CURLY_BRACE", 

90 "}}", 

91 variable_reference_documentation='Literal "}}" string - useful to avoid triggering a substitution', 

92 ) 

93 

94 

95def register_package_metadata_detectors(api: DebputyPluginInitializer) -> None: 

96 api.metadata_or_maintscript_detector("systemd-tmpfiles", detect_systemd_tmpfiles) 

97 api.metadata_or_maintscript_detector("systemd-sysusers", detect_systemd_sysusers) 

98 api.metadata_or_maintscript_detector("kernel-modules", detect_kernel_modules) 

99 api.metadata_or_maintscript_detector("icon-cache", detect_icons) 

100 api.metadata_or_maintscript_detector( 

101 "gsettings-dependencies", 

102 detect_gsettings_dependencies, 

103 ) 

104 api.metadata_or_maintscript_detector("xfonts", detect_xfonts) 

105 api.metadata_or_maintscript_detector("initramfs-hooks", detect_initramfs_hooks) 

106 api.metadata_or_maintscript_detector("pycompile-files", detect_pycompile_files) 

107 api.metadata_or_maintscript_detector( 

108 "translate-capabilities", 

109 translate_capabilities, 

110 ) 

111 api.metadata_or_maintscript_detector("pam-auth-update", pam_auth_update) 

112 api.metadata_or_maintscript_detector( 

113 "auto-depends-arch-any-solink", 

114 auto_depends_arch_any_solink, 

115 ) 

116 

117 

118def register_packager_provided_files(api: DebputyPluginInitializer) -> None: 

119 api.packager_provided_file( 

120 "tmpfiles", 

121 f"{SYSTEMD_TMPFILES_DIR}/{ name} .conf", 

122 reference_documentation=packager_provided_file_reference_documentation( 

123 format_documentation_uris=["man:tmpfiles.d(5)"] 

124 ), 

125 ) 

126 api.packager_provided_file( 

127 "sysusers", 

128 f"{SYSTEMD_SYSUSERS_DIR}/{ name} .conf", 

129 reference_documentation=packager_provided_file_reference_documentation( 

130 format_documentation_uris=["man:sysusers.d(5)"] 

131 ), 

132 ) 

133 api.packager_provided_file( 

134 "bash-completion", "/usr/share/bash-completion/completions/{name}" 

135 ) 

136 api.packager_provided_file( 

137 "fish-completion", "/usr/share/fish/vendor_completions.d/{name}" 

138 ) 

139 api.packager_provided_file( 

140 "zsh-completion", "/usr/share/zsh/vendor-completions/{name}" 

141 ) 

142 api.packager_provided_file( 

143 "bug-script", 

144 "./usr/share/bug/{name}/script", 

145 default_mode=0o0755, 

146 allow_name_segment=False, 

147 ) 

148 api.packager_provided_file( 

149 "bug-control", 

150 "/usr/share/bug/{name}/control", 

151 allow_name_segment=False, 

152 ) 

153 

154 api.packager_provided_file( 

155 "bug-presubj", 

156 "/usr/share/bug/{name}/presubj", 

157 allow_name_segment=False, 

158 ) 

159 

160 api.packager_provided_file("pam", "/usr/lib/pam.d/{name}") 

161 api.packager_provided_file( 

162 "ppp.ip-up", 

163 "/etc/ppp/ip-up.d/{name}", 

164 default_mode=0o0755, 

165 ) 

166 api.packager_provided_file( 

167 "ppp.ip-down", 

168 "/etc/ppp/ip-down.d/{name}", 

169 default_mode=0o0755, 

170 ) 

171 api.packager_provided_file( 

172 "lintian-overrides", 

173 "/usr/share/lintian/overrides/{name}", 

174 allow_name_segment=False, 

175 ) 

176 api.packager_provided_file("logrotate", "/etc/logrotate.d/{name}") 

177 api.packager_provided_file( 

178 "logcheck.cracking", 

179 "/etc/logcheck/cracking.d/{name}", 

180 post_formatting_rewrite=_replace_dot_with_underscore, 

181 ) 

182 api.packager_provided_file( 

183 "logcheck.violations", 

184 "/etc/logcheck/violations.d/{name}", 

185 post_formatting_rewrite=_replace_dot_with_underscore, 

186 ) 

187 api.packager_provided_file( 

188 "logcheck.violations.ignore", 

189 "/etc/logcheck/violations.ignore.d/{name}", 

190 post_formatting_rewrite=_replace_dot_with_underscore, 

191 ) 

192 api.packager_provided_file( 

193 "logcheck.ignore.workstation", 

194 "/etc/logcheck/ignore.d.workstation/{name}", 

195 post_formatting_rewrite=_replace_dot_with_underscore, 

196 ) 

197 api.packager_provided_file( 

198 "logcheck.ignore.server", 

199 "/etc/logcheck/ignore.d.server/{name}", 

200 post_formatting_rewrite=_replace_dot_with_underscore, 

201 ) 

202 api.packager_provided_file( 

203 "logcheck.ignore.paranoid", 

204 "/etc/logcheck/ignore.d.paranoid/{name}", 

205 post_formatting_rewrite=_replace_dot_with_underscore, 

206 ) 

207 

208 api.packager_provided_file("mime", "/usr/lib/mime/packages/{name}") 

209 api.packager_provided_file("sharedmimeinfo", "/usr/share/mime/packages/{name}.xml") 

210 

211 api.packager_provided_file( 

212 "if-pre-up", 

213 "/etc/network/if-pre-up.d/{name}", 

214 default_mode=0o0755, 

215 ) 

216 api.packager_provided_file( 

217 "if-up", 

218 "/etc/network/if-up.d/{name}", 

219 default_mode=0o0755, 

220 ) 

221 api.packager_provided_file( 

222 "if-down", 

223 "/etc/network/if-down.d/{name}", 

224 default_mode=0o0755, 

225 ) 

226 api.packager_provided_file( 

227 "if-post-down", 

228 "/etc/network/if-post-down.d/{name}", 

229 default_mode=0o0755, 

230 ) 

231 

232 api.packager_provided_file( 

233 "cron.hourly", 

234 "/etc/cron.hourly/{name}", 

235 default_mode=0o0755, 

236 ) 

237 api.packager_provided_file( 

238 "cron.daily", 

239 "/etc/cron.daily/{name}", 

240 default_mode=0o0755, 

241 ) 

242 api.packager_provided_file( 

243 "cron.weekly", 

244 "/etc/cron.weekly/{name}", 

245 default_mode=0o0755, 

246 ) 

247 api.packager_provided_file( 

248 "cron.monthly", 

249 "./etc/cron.monthly/{name}", 

250 default_mode=0o0755, 

251 ) 

252 api.packager_provided_file( 

253 "cron.yearly", 

254 "/etc/cron.yearly/{name}", 

255 default_mode=0o0755, 

256 ) 

257 # cron.d uses 0644 unlike the others 

258 api.packager_provided_file( 

259 "cron.d", 

260 "/etc/cron.d/{name}", 

261 reference_documentation=packager_provided_file_reference_documentation( 

262 format_documentation_uris=["man:crontab(5)"] 

263 ), 

264 ) 

265 

266 api.packager_provided_file( 

267 "initramfs-hook", f"{INITRAMFS_HOOK_DIR}/{ name} ", default_mode=0o0755 

268 ) 

269 

270 api.packager_provided_file("modprobe", "/etc/modprobe.d/{name}.conf") 

271 

272 api.packager_provided_file( 

273 "init", 

274 "/etc/init.d/{name}", 

275 default_mode=0o755, 

276 ) 

277 api.packager_provided_file("default", "/etc/default/{name}") 

278 

279 for stem in [ 

280 "mount", 

281 "path", 

282 "service", 

283 "socket", 

284 "target", 

285 "timer", 

286 ]: 

287 api.packager_provided_file( 

288 stem, 

289 f"/usr/lib/systemd/system/{ name} .{stem}", 

290 reference_documentation=packager_provided_file_reference_documentation( 

291 format_documentation_uris=[f"man:systemd.{stem}(5)"] 

292 ), 

293 ) 

294 

295 for stem in [ 

296 "path", 

297 "service", 

298 "socket", 

299 "target", 

300 "timer", 

301 ]: 

302 api.packager_provided_file( 

303 f"@{stem}", f"/usr/lib/systemd/system/{ name} @.{stem}" 

304 ) 

305 

306 # api.packager_provided_file( 

307 # "udev", 

308 # "./lib/udev/rules.d/{priority:02}-{name}.rules", 

309 # default_priority=60, 

310 # ) 

311 

312 api.packager_provided_file( 

313 "gsettings-override", 

314 f"{GSETTINGS_SCHEMA_DIR}/{ priority:02} _{ name} .gschema.override", 

315 default_priority=10, 

316 ) 

317 

318 # Special-cases that will probably not be a good example for other plugins 

319 api.packager_provided_file( 

320 "changelog", 

321 # The "changelog.Debian" gets renamed to "changelog" for native packages elsewhere. 

322 # Also, the changelog trimming is also done elsewhere. 

323 "/usr/share/doc/{name}/changelog.Debian", 

324 allow_name_segment=False, 

325 packageless_is_fallback_for_all_packages=True, 

326 reference_documentation=packager_provided_file_reference_documentation( 

327 description=textwrap.dedent( 

328 """\ 

329 This file is the changelog of the package and is mandatory. 

330 

331 The changelog contains the version of the source package and is mandatory for all 

332 packages. 

333 

334 Use `dch --create` to create the changelog. 

335 

336 In theory, the binary package can have a different changelog than the source 

337 package (by having `debian/binary-package.changelog`). However, it is generally 

338 not useful and leads to double administration. It has not been used in practice. 

339 """ 

340 ), 

341 format_documentation_uris=[ 

342 "man:deb-changelog(5)", 

343 "https://www.debian.org/doc/debian-policy/ch-source.html#debian-changelog-debian-changelog", 

344 "man:dch(1)", 

345 ], 

346 ), 

347 ) 

348 api.packager_provided_file( 

349 "copyright", 

350 "/usr/share/doc/{name}/copyright", 

351 allow_name_segment=False, 

352 packageless_is_fallback_for_all_packages=True, 

353 reference_documentation=packager_provided_file_reference_documentation( 

354 description=textwrap.dedent( 

355 """\ 

356 This file documents the license and copyright information of the binary package. 

357 Packages aimed at the Debian archive (and must derivatives thereof) must have this file. 

358 

359 For packages not aimed at Debian, the file can still be useful to convey the license 

360 terms of the package (which is often a requirement in many licenses). However, it is 

361 not a strict *technical* requirement. Whether it is a legal requirement depends on 

362 license. 

363 

364 Often, the same file can be used for all packages. In the extremely rare case where 

365 one binary package has a "vastly different" license than the other packages, you can 

366 provide a package specific version for that package. 

367 """ 

368 ), 

369 format_documentation_uris=[ 

370 "https://www.debian.org/doc/debian-policy/ch-source.html#copyright-debian-copyright", 

371 "https://www.debian.org/doc/debian-policy/ch-docs.html#s-copyrightfile", 

372 "https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/", 

373 ], 

374 ), 

375 ) 

376 api.packager_provided_file( 

377 "NEWS", 

378 "/usr/share/doc/{name}/NEWS.Debian", 

379 allow_name_segment=False, 

380 packageless_is_fallback_for_all_packages=True, 

381 reference_documentation=packager_provided_file_reference_documentation( 

382 description=textwrap.dedent( 

383 """\ 

384 Important news that should be shown to the user/admin when upgrading. If a system has 

385 apt-listchanges installed, then contents of this file will be shown prior to upgrading 

386 the package. 

387 

388 Uses a similar format to that of debian/changelog (create with `dch --news --create`). 

389 """ 

390 ), 

391 format_documentation_uris=[ 

392 "https://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.en.html#supplementing-changelogs-with-news-debian-files", 

393 "man:dch(1)", 

394 ], 

395 ), 

396 ) 

397 api.packager_provided_file( 

398 "README.Debian", 

399 "/usr/share/doc/{name}/README.Debian", 

400 allow_name_segment=False, 

401 ) 

402 api.packager_provided_file( 

403 "TODO", 

404 "/usr/share/doc/{name}/TODO.Debian", 

405 allow_name_segment=False, 

406 ) 

407 # From dh-python / dh_python3 

408 # api.packager_provided_file( 

409 # "bcep", 

410 # "/usr/share/python3/bcep/{name}", 

411 # allow_name_segment=False, 

412 # ) 

413 

414 

415def _replace_dot_with_underscore(x: str) -> str: 

416 return x.replace(".", "_")