1#! /usr/bin/env python3
3""" Copies the installer from one suite to another """
4# Copyright (C) 2011 Torsten Werner <twerner@debian.org>
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.
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.
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
20################################################################################
22from daklib.config import Config
24import apt_pkg
25import glob
26import os.path
27import re
28import subprocess
29import sys
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
39Exactly 1 version must be specified.""")
40 sys.exit(exit_code)
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")
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)
63 initializer = {"version": extra_arguments[0]}
64 if Options["Source"] != "":
65 initializer["source"] = Options["Source"]
66 if Options["Destination"] != "":
67 initializer["dest"] = Options["Destination"]
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.')
78root_dir = Config()['Dir::Root']
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']
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')
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)
104 def check_dir(self, dir, message):
105 if not os.path.isdir(dir):
106 raise Exception("%s (%s)" % (message, dir))
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))
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)}
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)
146if __name__ == '__main__':
147 main()