1#! /usr/bin/env python3 

2 

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

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

5 

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

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

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

9# (at your option) any later version. 

10 

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

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

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

14# GNU General Public License for more details. 

15 

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

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

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

19 

20################################################################################ 

21 

22import glob 

23import os.path 

24import re 

25import subprocess 

26import sys 

27 

28import apt_pkg 

29 

30from daklib.config import Config 

31 

32 

33def usage(exit_code=0): 

34 print( 

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

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

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

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

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

40 

41Exactly 1 version must be specified.""" 

42 ) 

43 sys.exit(exit_code) 

44 

45 

46def main(): 

47 cnf = Config() 

48 Arguments = [ 

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

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

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

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

53 ] 

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

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

56 if key not in cnf: 56 ↛ 54line 56 didn't jump to line 54, because the condition on line 56 was never false

57 cnf[key] = "" 

58 extra_arguments = apt_pkg.parse_commandline(cnf.Cnf, Arguments, sys.argv) 

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

60 

61 if Options["Help"]: 61 ↛ 63line 61 didn't jump to line 63, because the condition on line 61 was never false

62 usage() 

63 if len(extra_arguments) != 1: 

64 usage(1) 

65 

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

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

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

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

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

71 

72 copier = InstallerCopier(**initializer) 

73 print(copier.get_message()) 

74 if Options["No-Action"]: 

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

76 else: 

77 copier.do_copy() 

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

79 

80 

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

82 

83 

84class InstallerCopier: 

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

86 self.source = source 

87 self.dest = dest 

88 if "version" not in keywords: 

89 raise KeyError("no version specified") 

90 self.version = keywords["version"] 

91 

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

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

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

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

96 

97 self.architectures = [] 

98 self.skip_architectures = [] 

99 self.trees_to_copy = [] 

100 self.symlinks_to_create = [] 

101 self.dirs_to_create = [] 

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

103 for arch_dir in glob.glob(arch_pattern): 

104 self.check_architecture(arch_dir) 

105 

106 def check_dir(self, dir, message): 

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

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

109 

110 def check_architecture(self, arch_dir): 

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

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

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

114 if os.path.isdir(dest_dir): 

115 self.skip_architectures.append(architecture) 

116 else: 

117 self.architectures.append(architecture) 

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

119 self.dirs_to_create.append(dest_basedir) 

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

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

122 

123 def get_message(self): 

124 return """ 

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

126%(dest)s. 

127Architectures to copy: %(arch_list)s 

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

129 "version": self.version, 

130 "source": self.source, 

131 "dest": self.dest, 

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

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

134 } 

135 

136 def do_copy(self): 

137 for dest in self.dirs_to_create: 

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

139 os.makedirs(dest) 

140 for source, dest in self.trees_to_copy: 

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

142 for source, dest in self.symlinks_to_create: 

143 if os.path.lexists(dest): 

144 os.unlink(dest) 

145 os.symlink(source, dest) 

146 

147 

148if __name__ == "__main__": 

149 main()