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 

22from daklib.config import Config 

23 

24import apt_pkg 

25import glob 

26import os.path 

27import re 

28import subprocess 

29import sys 

30 

31 

32def usage(exit_code=0): 

33 print("""Usage: dak copy-installer [OPTION]... VERSION 

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

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

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

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

38 

39Exactly 1 version must be specified.""") 

40 sys.exit(exit_code) 

41 

42 

43def main(): 

44 cnf = Config() 

45 Arguments = [ 

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

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

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

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

50 ] 

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

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

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

54 cnf[key] = "" 

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

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

57 

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

59 usage() 

60 if len(extra_arguments) != 1: 

61 usage(1) 

62 

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

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

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

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

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

68 

69 copier = InstallerCopier(**initializer) 

70 print(copier.get_message()) 

71 if Options["No-Action"]: 

72 print('Do nothing because --no-action has been set.') 

73 else: 

74 copier.do_copy() 

75 print('Installer has been copied successfully.') 

76 

77 

78root_dir = Config()['Dir::Root'] 

79 

80 

81class InstallerCopier: 

82 def __init__(self, source='unstable', dest='testing', 

83 **keywords): 

84 self.source = source 

85 self.dest = dest 

86 if 'version' not in keywords: 

87 raise KeyError('no version specified') 

88 self.version = keywords['version'] 

89 

90 self.source_dir = os.path.join(root_dir, 'dists', source, 'main') 

91 self.dest_dir = os.path.join(root_dir, 'dists', dest, 'main') 

92 self.check_dir(self.source_dir, 'source does not exist') 

93 self.check_dir(self.dest_dir, 'destination does not exist') 

94 

95 self.architectures = [] 

96 self.skip_architectures = [] 

97 self.trees_to_copy = [] 

98 self.symlinks_to_create = [] 

99 self.dirs_to_create = [] 

100 arch_pattern = os.path.join(self.source_dir, 'installer-*', self.version) 

101 for arch_dir in glob.glob(arch_pattern): 

102 self.check_architecture(arch_dir) 

103 

104 def check_dir(self, dir, message): 

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

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

107 

108 def check_architecture(self, arch_dir): 

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

110 dest_basedir = os.path.join(self.dest_dir, 

111 '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 def do_copy(self): 

135 for dest in self.dirs_to_create: 

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

137 os.makedirs(dest) 

138 for source, dest in self.trees_to_copy: 

139 subprocess.check_call(['cp', '-al', source, dest]) 

140 for source, dest in self.symlinks_to_create: 

141 if os.path.lexists(dest): 

142 os.unlink(dest) 

143 os.symlink(source, dest) 

144 

145 

146if __name__ == '__main__': 

147 main()