Coverage for dak/copy_installer.py: 62%

80 statements  

« prev     ^ index     » next       coverage.py v7.6.0, created at 2026-08-03 16:46 +0000

1"""Copies the installer from one suite to another""" 

2 

3# Copyright (C) 2011 Torsten Werner <twerner@debian.org> 

4 

5# This program is free software; you can redistribute it and/or modify 

6# it under the terms of the GNU General Public License as published by 

7# the Free Software Foundation; either version 2 of the License, or 

8# (at your option) any later version. 

9 

10# This program is distributed in the hope that it will be useful, 

11# but WITHOUT ANY WARRANTY; without even the implied warranty of 

12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

13# GNU General Public License for more details. 

14 

15# You should have received a copy of the GNU General Public License 

16# along with this program; if not, write to the Free Software 

17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

18 

19################################################################################ 

20 

21import glob 

22import os.path 

23import re 

24import subprocess 

25import sys 

26 

27import apt_pkg 

28 

29from daklib.config import Config 

30 

31 

32def usage(exit_code=0): 

33 print( 

34 """Usage: dak copy-installer [OPTION]... VERSION 

35 -h, --help show this help and exit 

36 -s, --source source suite (defaults to unstable) 

37 -d, --destination destination suite (defaults to testing) 

38 -n, --no-action don't change anything 

39 

40Exactly 1 version must be specified.""" 

41 ) 

42 sys.exit(exit_code) 

43 

44 

45def main(): 

46 cnf = Config() 

47 Arguments = [ 

48 ("h", "help", "Copy-Installer::Options::Help"), 

49 ("s", "source", "Copy-Installer::Options::Source", "HasArg"), 

50 ("d", "destination", "Copy-Installer::Options::Destination", "HasArg"), 

51 ("n", "no-action", "Copy-Installer::Options::No-Action"), 

52 ] 

53 for option in ["help", "source", "destination", "no-action"]: 

54 key = "Copy-Installer::Options::%s" % option 

55 if key not in cnf: 55 ↛ 53line 55 didn't jump to line 53 because the condition on line 55 was always true

56 cnf[key] = "" 

57 extra_arguments = apt_pkg.parse_commandline(cnf.Cnf, Arguments, sys.argv) # type: ignore[attr-defined] 

58 Options = cnf.subtree("Copy-Installer::Options") 

59 

60 if Options["Help"]: 60 ↛ 62line 60 didn't jump to line 62 because the condition on line 60 was always true

61 usage() 

62 if len(extra_arguments) != 1: 

63 usage(1) 

64 

65 initializer = {"version": extra_arguments[0]} 

66 if Options["Source"] != "": 

67 initializer["source"] = Options["Source"] 

68 if Options["Destination"] != "": 

69 initializer["dest"] = Options["Destination"] 

70 

71 copier = InstallerCopier(**initializer) 

72 print(copier.get_message()) 

73 if Options["No-Action"]: 

74 print("Do nothing because --no-action has been set.") 

75 else: 

76 copier.do_copy() 

77 print("Installer has been copied successfully.") 

78 

79 

80root_dir = Config()["Dir::Root"] 

81 

82 

83class InstallerCopier: 

84 def __init__(self, source="unstable", dest="testing", **keywords): 

85 self.source = source 

86 self.dest = dest 

87 if "version" not in keywords: 

88 raise KeyError("no version specified") 

89 self.version = keywords["version"] 

90 

91 self.source_dir = os.path.join(root_dir, "dists", source, "main") 

92 self.dest_dir = os.path.join(root_dir, "dists", dest, "main") 

93 self.check_dir(self.source_dir, "source does not exist") 

94 self.check_dir(self.dest_dir, "destination does not exist") 

95 

96 self.architectures = [] 

97 self.skip_architectures = [] 

98 self.trees_to_copy = [] 

99 self.symlinks_to_create = [] 

100 self.dirs_to_create = [] 

101 arch_pattern = os.path.join(self.source_dir, "installer-*", self.version) 

102 for arch_dir in glob.glob(arch_pattern): 

103 self.check_architecture(arch_dir) 

104 

105 def check_dir(self, dir, message): 

106 if not os.path.isdir(dir): 

107 raise Exception("%s (%s)" % (message, dir)) 

108 

109 def check_architecture(self, arch_dir): 

110 architecture = re.sub(".*?/installer-(.*?)/.*", r"\1", arch_dir) 

111 dest_basedir = os.path.join(self.dest_dir, "installer-%s" % architecture) 

112 dest_dir = os.path.join(dest_basedir, self.version) 

113 if os.path.isdir(dest_dir): 

114 self.skip_architectures.append(architecture) 

115 else: 

116 self.architectures.append(architecture) 

117 self.trees_to_copy.append((arch_dir, dest_dir)) 

118 self.dirs_to_create.append(dest_basedir) 

119 symlink_target = os.path.join(dest_basedir, "current") 

120 self.symlinks_to_create.append((self.version, symlink_target)) 

121 

122 def get_message(self): 

123 return """ 

124Will copy installer version %(version)s from suite %(source)s to 

125%(dest)s. 

126Architectures to copy: %(arch_list)s 

127Architectures to skip: %(skip_arch_list)s""" % { 

128 "version": self.version, 

129 "source": self.source, 

130 "dest": self.dest, 

131 "arch_list": ", ".join(self.architectures), 

132 "skip_arch_list": ", ".join(self.skip_architectures), 

133 } 

134 

135 def do_copy(self): 

136 for dest in self.dirs_to_create: 

137 if not os.path.exists(dest): 

138 os.makedirs(dest) 

139 for source, dest in self.trees_to_copy: 

140 subprocess.check_call(["cp", "-al", source, dest]) 

141 for source, dest in self.symlinks_to_create: 

142 if os.path.lexists(dest): 

143 os.unlink(dest) 

144 os.symlink(source, dest)