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
« 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"""
3# Copyright (C) 2011 Torsten Werner <twerner@debian.org>
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.
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.
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
19################################################################################
21import glob
22import os.path
23import re
24import subprocess
25import sys
27import apt_pkg
29from daklib.config import Config
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
40Exactly 1 version must be specified."""
41 )
42 sys.exit(exit_code)
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")
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)
65 initializer = {"version": extra_arguments[0]}
66 if Options["Source"] != "":
67 initializer["source"] = Options["Source"]
68 if Options["Destination"] != "":
69 initializer["dest"] = Options["Destination"]
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.")
80root_dir = Config()["Dir::Root"]
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"]
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")
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)
105 def check_dir(self, dir, message):
106 if not os.path.isdir(dir):
107 raise Exception("%s (%s)" % (message, dir))
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))
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 }
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)