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################################################################################
22import glob
23import os.path
24import re
25import subprocess
26import sys
28import apt_pkg
30from daklib.config import Config
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
41Exactly 1 version must be specified."""
42 )
43 sys.exit(exit_code)
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")
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)
66 initializer = {"version": extra_arguments[0]}
67 if Options["Source"] != "":
68 initializer["source"] = Options["Source"]
69 if Options["Destination"] != "":
70 initializer["dest"] = Options["Destination"]
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.")
81root_dir = Config()["Dir::Root"]
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"]
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")
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)
106 def check_dir(self, dir, message):
107 if not os.path.isdir(dir):
108 raise Exception("%s (%s)" % (message, dir))
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))
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 }
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)
148if __name__ == "__main__":
149 main()