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

79 statements  

« prev     ^ index     » next       coverage.py v7.8.2, created at 2026-02-28 21:56 +0000

1import os.path 

2import subprocess 

3 

4from debian.debian_support import Version 

5 

6from debputy.analysis.debian_dir import resolve_debhelper_config_files 

7from debputy.dh.debhelper_emulation import dhe_pkgfile 

8from debputy.dh.dh_assistant import read_dh_addon_sequences, extract_dh_compat_level 

9from debputy.dh_migration.models import ( 

10 FeatureMigration, 

11 MigrationRequest, 

12) 

13from debputy.plugin.api.impl import plugin_metadata_for_debputys_own_plugin 

14 

15 

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

17 try: 

18 output = subprocess.check_output( 

19 [ 

20 "dpkg-query", 

21 "-W", 

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

23 "debhelper", 

24 ] 

25 ).decode("utf-8") 

26 except (FileNotFoundError, subprocess.CalledProcessError): 

27 return False 

28 else: 

29 parts = output.split() 

30 if len(parts) != 2: 

31 return False 

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

33 return False 

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

35 

36 

37def dh_mbm_migrate_package_files( 

38 migration_request: MigrationRequest, 

39 feature_migration: FeatureMigration, 

40) -> None: 

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

42 debputy_plugin_metadata = plugin_metadata_for_debputys_own_plugin() 

43 dh_compat_level, _ = extract_dh_compat_level() 

44 r = read_dh_addon_sequences(migration_request.debian_dir) 

45 if r is not None: 

46 bd_sequences, dr_sequences, uses_dh_sequencer = r 

47 dh_sequences = bd_sequences | dr_sequences 

48 uses_dh_sequencer = True 

49 else: 

50 dh_sequences = set() 

51 uses_dh_sequencer = False 

52 

53 ( 

54 all_dh_ppfs, 

55 missing_introspection, 

56 _, 

57 _, 

58 ) = resolve_debhelper_config_files( 

59 migration_request.debian_dir, 

60 {p.name: p for p in migration_request.all_packages}, 

61 debputy_plugin_metadata, 

62 migration_request.manifest.plugin_provided_feature_set, 

63 dh_sequences, 

64 dh_compat_level, 

65 uses_dh_sequencer, 

66 ) 

67 for ppf in all_dh_ppfs: 

68 if ( 

69 ppf.uses_explicit_package_name 

70 or ppf.definition.packageless_is_fallback_for_all_packages 

71 ): 

72 continue 

73 basename = ppf.path.name 

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

75 ppf_parent = ppf.path.parent_dir 

76 assert ppf_parent is not None 

77 parent_path = ppf_parent.path 

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

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

80 

81 if not missing_introspection and not _installed_debhelper_version_is_at_least( 

82 "13.26~" 

83 ): 

84 feature_migration.warn( 

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

86 ) 

87 

88 for command in missing_introspection: 

89 feature_migration.warn( 

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

91 ) 

92 

93 if missing_introspection: 

94 feature_migration.warn( 

95 "Please ensure you have the latest versions of the above commands installed and try again." 

96 ) 

97 feature_migration.warn( 

98 "If the issue still persists, then 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." 

99 ) 

100 feature_migration.warn( 

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

102 ) 

103 

104 

105def dh_mbm_migrate_manual_warnings( 

106 migration_request: MigrationRequest, 

107 feature_migration: FeatureMigration, 

108) -> None: 

109 feature_migration.tagline = "Manual parts" 

110 debian_dir = migration_request.debian_dir 

111 r = read_dh_addon_sequences(debian_dir) 

112 if r is not None: 

113 bd_sequences, dr_sequences, uses_dh_sequencer = r 

114 dh_sequences = bd_sequences | dr_sequences 

115 uses_dh_sequencer = True 

116 else: 

117 dh_sequences = set() 

118 uses_dh_sequencer = False 

119 drules = debian_dir.get("rules") 

120 if drules and drules.is_file: 

121 with drules.open() as fd: 

122 migrated_auto_install = 0 

123 for line in fd: 

124 line = line.lstrip() 

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

126 continue 

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

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

129 used_dh_install_files = 0 

130 for dctrl_bin in migration_request.all_packages: 

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

132 if dh_config_file is not None: 

133 used_dh_install_files += 1 

134 main_pkg = migration_request.main_binary 

135 if not migrated_auto_install and not used_dh_install_files: 

136 feature_migration.warn( 

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

138 ) 

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

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