1#! /usr/bin/env python3
3"""
4Modify external overrides.
6@contact: Debian FTP Master <ftpmaster@debian.org>
7@copyright: 2011 Ansgar Burchardt <ansgar@debian.org>
8@license: GNU General Public License version 2 or later
9"""
11# This program is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation; either version 2 of the License, or
14# (at your option) any later version.
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
21# You should have received a copy of the GNU General Public License
22# along with this program; if not, write to the Free Software
23# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25import sys
27import apt_pkg
29from daklib.config import Config
30from daklib.dbconn import DBConn, ExternalOverride, get_component, get_suite
33def usage():
34 print(
35 """Usage: dak external-overrides COMMAND
36Modify external overrides.
38 -h, --help show this help and exit.
39 -f, --force allow processing of untouchable suites.
41Commands can use a long or abbreviated form:
43 import SUITE COMPONENT KEY import external overrides for KEY
44 i SUITE COMPONENT KEY NOTE: This will replace existing overrides.
46 copy FROM TO copy external overrides from suite FROM to TO
47 NOTE: Needs --force for untouchable TO
49For the 'import' command, external overrides are read from standard input and
50should be given as lines of the form 'PACKAGE KEY VALUE'.
51"""
52 )
53 sys.exit()
56#############################################################################
59class ExternalOverrideReader:
60 """
61 Parses an external override file
62 """
64 def __init__(self, fh):
65 self.fh = fh
66 self.package = None
67 self.key = None
68 self.value = []
70 def _flush(self):
71 """
72 Return the parsed line that is being built and start parsing a new line
73 """
74 res = self.package, self.key, "\n".join(self.value)
75 self.package = self.key = None
76 self.value = []
77 return res
79 def __iter__(self):
80 """
81 returns a (package, key, value) tuple for every entry in the external
82 override file
83 """
84 for line in self.fh:
85 if not line:
86 continue
87 if line[0] in (" ", "\t"):
88 # Continuation line
89 self.value.append(line.rstrip())
90 else:
91 if self.package is not None:
92 yield self._flush()
94 # New line
95 (self.package, self.key, value) = line.rstrip().split(None, 2)
96 self.value = [value]
98 if self.package is not None:
99 yield self._flush()
102#############################################################################
105def external_overrides_copy(from_suite_name, to_suite_name, force=False):
106 session = DBConn().session()
108 from_suite = get_suite(from_suite_name, session)
109 to_suite = get_suite(to_suite_name, session)
111 if from_suite is None:
112 print("E: source %s not found." % from_suite_name)
113 session.rollback()
114 return False
115 if to_suite is None:
116 print("E: target %s not found." % to_suite_name)
117 session.rollback()
118 return False
120 if not force and to_suite.untouchable:
121 print("E: refusing to touch untouchable suite %s (not forced)." % to_suite_name)
122 session.rollback()
123 return False
125 session.query(ExternalOverride).filter_by(suite=to_suite).delete()
126 session.execute(
127 """
128 INSERT INTO external_overrides (suite, component, package, key, value)
129 SELECT :to_suite, component, package, key, value FROM external_overrides WHERE suite = :from_suite
130 """,
131 {"from_suite": from_suite.suite_id, "to_suite": to_suite.suite_id},
132 )
134 session.commit()
137def external_overrides_import(suite_name, component_name, key, file, force=False):
138 session = DBConn().session()
140 suite = get_suite(suite_name, session)
141 component = get_component(component_name, session)
143 if not force and suite.untouchable:
144 print("E: refusing to touch untouchable suite %s (not forced)." % suite_name)
145 session.rollback()
146 return False
148 session.query(ExternalOverride).filter_by(
149 suite=suite, component=component, key=key
150 ).delete()
152 for package, key, value in ExternalOverrideReader(file):
153 eo = ExternalOverride()
154 eo.suite = suite
155 eo.component = component
156 eo.package = package
157 eo.key = key
158 eo.value = value
159 session.add(eo)
161 session.commit()
164#############################################################################
167def main():
168 cnf = Config()
170 Arguments = [
171 ("h", "help", "External-Overrides::Options::Help"),
172 ("f", "force", "External-Overrides::Options::Force"),
173 ]
175 args = apt_pkg.parse_commandline(cnf.Cnf, Arguments, sys.argv)
176 try:
177 Options = cnf.subtree("External-Overrides::Options")
178 except KeyError:
179 Options = {}
181 if "Help" in Options: 181 ↛ 184line 181 didn't jump to line 184, because the condition on line 181 was never false
182 usage()
184 force = False
185 if "Force" in Options and Options["Force"]:
186 force = True
188 command = args[0]
189 if command in ("import", "i"):
190 external_overrides_import(args[1], args[2], args[3], sys.stdin, force)
191 elif command in ("copy", "c"):
192 external_overrides_copy(args[1], args[2], force)
193 else:
194 print("E: Unknown commands.")
197if __name__ == "__main__":
198 main()