Coverage for src/debputy/dh_migration/dh_related_migrations.py: 13%

81 statements  

« prev     ^ index     » next       coverage.py v7.8.2, created at 2025-09-07 09:27 +0000

1import os.path 

2import subprocess 

3from typing import Optional 

4 

5from debian.debian_support import Version 

6 

7from debputy.analysis.debian_dir import resolve_debhelper_config_files 

8from debputy.dh.debhelper_emulation import dhe_pkgfile 

9from debputy.dh.dh_assistant import read_dh_addon_sequences, extract_dh_compat_level 

10from debputy.dh_migration.models import AcceptableMigrationIssues, FeatureMigration 

11from debputy.highlevel_manifest import HighLevelManifest 

12from debputy.plugin.api import VirtualPath 

13from debputy.plugin.api.impl import plugin_metadata_for_debputys_own_plugin 

14from debputy.plugin.api.spec import DebputyIntegrationMode 

15 

16 

17def _installed_debhelper_version_is_at_least(desired_version: str) -> bool: 

18 try: 

19 output = subprocess.check_output( 

20 [ 

21 "dpkg-query", 

22 "-W", 

23 "--showformat=${Version} ${db:Status-Status}\n", 

24 "debhelper", 

25 ] 

26 ).decode("utf-8") 

27 except (FileNotFoundError, subprocess.CalledProcessError): 

28 return False 

29 else: 

30 parts = output.split() 

31 if len(parts) != 2: 

32 return False 

33 if parts[1] != "installed": 

34 return False 

35 return Version(parts[0]) >= Version(desired_version) 

36 

37 

38def dh_mbm_migrate_package_files( 

39 debian_dir: VirtualPath, 

40 manifest: HighLevelManifest, 

41 _acceptable_migration_issues: AcceptableMigrationIssues, 

42 feature_migration: FeatureMigration, 

43 _migration_target: Optional[DebputyIntegrationMode], 

44) -> None: 

45 feature_migration.tagline = "Add explicit package name to debhelper config files" 

46 debputy_plugin_metadata = plugin_metadata_for_debputys_own_plugin() 

47 dh_compat_level, _ = extract_dh_compat_level() 

48 r = read_dh_addon_sequences(debian_dir) 

49 if r is not None: 

50 bd_sequences, dr_sequences, uses_dh_sequencer = r 

51 dh_sequences = bd_sequences | dr_sequences 

52 uses_dh_sequencer = True 

53 else: 

54 dh_sequences = set() 

55 uses_dh_sequencer = False 

56 

57 ( 

58 all_dh_ppfs, 

59 missing_introspection, 

60 _, 

61 _, 

62 ) = resolve_debhelper_config_files( 

63 debian_dir, 

64 {p.name: p for p in manifest.all_packages}, 

65 debputy_plugin_metadata, 

66 manifest.plugin_provided_feature_set, 

67 dh_sequences, 

68 dh_compat_level, 

69 uses_dh_sequencer, 

70 ) 

71 for ppf in all_dh_ppfs: 

72 if ( 

73 ppf.uses_explicit_package_name 

74 or ppf.definition.packageless_is_fallback_for_all_packages 

75 ): 

76 continue 

77 basename = ppf.path.name 

78 new_basename = f"{ppf.package_name}.{basename}" 

79 ppf_parent = ppf.path.parent_dir 

80 assert ppf_parent is not None 

81 parent_path = ppf_parent.path 

82 new_path = os.path.join(parent_path, new_basename) 

83 feature_migration.rename_on_success(ppf.path.path, new_path) 

84 

85 if not missing_introspection and not _installed_debhelper_version_is_at_least( 

86 "13.26~" 

87 ): 

88 feature_migration.warn( 

89 "Please upgrade to `debhelper/13.26` to ensure reliability. Some files might be silently missed." 

90 ) 

91 

92 for command in missing_introspection: 

93 feature_migration.warn( 

94 f"The command `{command}` is used but `dh_assistant` was not aware of whether it had configuration files." 

95 ) 

96 

97 if missing_introspection: 

98 feature_migration.warn( 

99 "Please file a bug against the provider of the commands asking them to supply the relevant hints (see doc/PROGRAMMING.md in debhelper/13.26+) with the debhelper maintainers in CC." 

100 ) 

101 

102 feature_migration.warn( 

103 "Any architecture restricted file (such `debian/install.amd64`) and templating based files (such as debian/install.tmpl) may be missed. Please validate these manually." 

104 ) 

105 

106 

107def dh_mbm_migrate_manual_warnings( 

108 debian_dir: VirtualPath, 

109 manifest: HighLevelManifest, 

110 _acceptable_migration_issues: AcceptableMigrationIssues, 

111 feature_migration: FeatureMigration, 

112 _migration_target: Optional[DebputyIntegrationMode], 

113) -> None: 

114 feature_migration.tagline = "Manual parts" 

115 r = read_dh_addon_sequences(debian_dir) 

116 if r is not None: 

117 bd_sequences, dr_sequences, uses_dh_sequencer = r 

118 dh_sequences = bd_sequences | dr_sequences 

119 uses_dh_sequencer = True 

120 else: 

121 dh_sequences = set() 

122 uses_dh_sequencer = False 

123 drules = debian_dir.get("rules") 

124 if drules and drules.is_file: 

125 with drules.open() as fd: 

126 migrated_auto_install = 0 

127 for line in fd: 

128 line = line.lstrip() 

129 if not line or line.startswith("#"): 

130 continue 

131 if line.startswith("\t") and "dh_auto_install" in line: 

132 migrated_auto_install += 1 if "--destdir" in line else 0 

133 used_dh_install_files = 0 

134 for dctrl_bin in manifest.all_packages: 

135 dh_config_file = dhe_pkgfile(debian_dir, dctrl_bin, "install") 

136 if dh_config_file is not None: 

137 used_dh_install_files += 1 

138 main_pkg = [p for p in manifest.all_packages if p.is_main_package][0] 

139 if not migrated_auto_install and not used_dh_install_files: 

140 feature_migration.warn( 

141 f"Ensure `dh_auto_install --destdir debian/{main_pkg.name}` or `dh_install` is used. Remember Replaces/Breaks if files are moved" 

142 ) 

143 if uses_dh_sequencer and "single-binary" in dh_sequences: 

144 feature_migration.warn("Remove `single-binary` add-on")