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

82 statements  

« prev     ^ index     » next       coverage.py v7.8.2, created at 2025-10-19 09:24 +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 ( 

11 AcceptableMigrationIssues, 

12 FeatureMigration, 

13 MigrationRequest, 

14) 

15from debputy.highlevel_manifest import HighLevelManifest 

16from debputy.plugin.api import VirtualPath 

17from debputy.plugin.api.impl import plugin_metadata_for_debputys_own_plugin 

18from debputy.plugin.api.spec import DebputyIntegrationMode 

19 

20 

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

22 try: 

23 output = subprocess.check_output( 

24 [ 

25 "dpkg-query", 

26 "-W", 

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

28 "debhelper", 

29 ] 

30 ).decode("utf-8") 

31 except (FileNotFoundError, subprocess.CalledProcessError): 

32 return False 

33 else: 

34 parts = output.split() 

35 if len(parts) != 2: 

36 return False 

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

38 return False 

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

40 

41 

42def dh_mbm_migrate_package_files( 

43 migration_request: MigrationRequest, 

44 feature_migration: FeatureMigration, 

45) -> None: 

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

47 debputy_plugin_metadata = plugin_metadata_for_debputys_own_plugin() 

48 dh_compat_level, _ = extract_dh_compat_level() 

49 r = read_dh_addon_sequences(migration_request.debian_dir) 

50 if r is not None: 

51 bd_sequences, dr_sequences, uses_dh_sequencer = r 

52 dh_sequences = bd_sequences | dr_sequences 

53 uses_dh_sequencer = True 

54 else: 

55 dh_sequences = set() 

56 uses_dh_sequencer = False 

57 

58 ( 

59 all_dh_ppfs, 

60 missing_introspection, 

61 _, 

62 _, 

63 ) = resolve_debhelper_config_files( 

64 migration_request.debian_dir, 

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

66 debputy_plugin_metadata, 

67 migration_request.manifest.plugin_provided_feature_set, 

68 dh_sequences, 

69 dh_compat_level, 

70 uses_dh_sequencer, 

71 ) 

72 for ppf in all_dh_ppfs: 

73 if ( 

74 ppf.uses_explicit_package_name 

75 or ppf.definition.packageless_is_fallback_for_all_packages 

76 ): 

77 continue 

78 basename = ppf.path.name 

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

80 ppf_parent = ppf.path.parent_dir 

81 assert ppf_parent is not None 

82 parent_path = ppf_parent.path 

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

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

85 

86 if not missing_introspection and not _installed_debhelper_version_is_at_least( 

87 "13.26~" 

88 ): 

89 feature_migration.warn( 

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

91 ) 

92 

93 for command in missing_introspection: 

94 feature_migration.warn( 

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

96 ) 

97 

98 if missing_introspection: 

99 feature_migration.warn( 

100 "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." 

101 ) 

102 

103 feature_migration.warn( 

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

105 ) 

106 

107 

108def dh_mbm_migrate_manual_warnings( 

109 migration_request: MigrationRequest, 

110 feature_migration: FeatureMigration, 

111) -> None: 

112 feature_migration.tagline = "Manual parts" 

113 debian_dir = migration_request.debian_dir 

114 r = read_dh_addon_sequences(debian_dir) 

115 if r is not None: 

116 bd_sequences, dr_sequences, uses_dh_sequencer = r 

117 dh_sequences = bd_sequences | dr_sequences 

118 uses_dh_sequencer = True 

119 else: 

120 dh_sequences = set() 

121 uses_dh_sequencer = False 

122 drules = debian_dir.get("rules") 

123 if drules and drules.is_file: 

124 with drules.open() as fd: 

125 migrated_auto_install = 0 

126 for line in fd: 

127 line = line.lstrip() 

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

129 continue 

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

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

132 used_dh_install_files = 0 

133 for dctrl_bin in migration_request.all_packages: 

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

135 if dh_config_file is not None: 

136 used_dh_install_files += 1 

137 main_pkg = migration_request.main_binary 

138 if not migrated_auto_install and not used_dh_install_files: 

139 feature_migration.warn( 

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

141 ) 

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

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