]> git.decadent.org.uk Git - dak.git/blob - dak/external_overrides.py
Merge remote-tracking branch 'drkranz/misc' into merge
[dak.git] / dak / external_overrides.py
1 #!/usr/bin/python
2
3 """
4 Modify external overrides.
5
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 """
10
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.
15
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.
20
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
24
25 from daklib.dbconn import *
26 from daklib.config import Config
27 from daklib import utils, daklog
28
29 import apt_pkg
30 import sys
31
32 def usage():
33     print """Usage: dak external-overrides COMMAND
34 Modify external overrides.
35
36   -h, --help                    show this help and exit.
37   -f, --force                   allow processing of untouchable suites.
38
39 Commands can use a long or abbreviated form:
40
41     import SUITE COMPONENT KEY  import external overrides for KEY
42     i SUITE COMPONENT KEY       NOTE: This will replace existing overrides.
43
44     copy FROM TO                copy external overrides from suite FROM to TO
45                                 NOTE: Needs --force for untouchable TO
46
47 For the 'import' command, external overrides are read from standard input and
48 should be given as lines of the form 'PACKAGE KEY VALUE'.
49 """
50     sys.exit()
51
52 #############################################################################
53
54 class ExternalOverrideReader(object):
55     """
56     Parses an external override file
57     """
58     def __init__(self, fh):
59         self.fh = fh
60         self.package = None
61         self.key = None
62         self.value = []
63
64     def _flush(self):
65         """
66         Return the parsed line that is being built and start parsing a new line
67         """
68         res = self.package, self.key, "\n".join(self.value)
69         self.package = self.key = None
70         self.value = []
71         return res
72
73     def __iter__(self):
74         """
75         returns a (package, key, value) tuple for every entry in the external
76         override file
77         """
78         for line in self.fh:
79             if not line: continue
80             if line[0] in (" ", "\t"):
81                 # Continuation line
82                 self.value.append(line.rstrip())
83             else:
84                 if self.package is not None:
85                     yield self._flush()
86
87                 # New line
88                 (self.package, self.key, value) = line.rstrip().split(None, 2)
89                 self.value = [value]
90
91         if self.package is not None:
92             yield self._flush()
93
94 #############################################################################
95
96 def external_overrides_copy(from_suite_name, to_suite_name, force = False):
97     session = DBConn().session()
98
99     from_suite = get_suite(from_suite_name, session)
100     to_suite = get_suite(to_suite_name, session)
101
102     if from_suite is None:
103         print "E: source %s not found." % from_suite_name
104         session.rollback()
105         return False
106     if to_suite is None:
107         print "E: target %s not found." % to_suite_name
108         session.rollback()
109         return False
110
111     if not force and to_suite.untouchable:
112         print "E: refusing to touch untouchable suite %s (not forced)." % to_suite_name
113         session.rollback()
114         return False
115
116     session.query(ExternalOverride).filter_by(suite=to_suite).delete()
117     session.execute("""
118     INSERT INTO external_overrides (suite, component, package, key, value)
119       SELECT :to_suite, component, package, key, value FROM external_overrides WHERE suite = :from_suite
120     """, { 'from_suite': from_suite.suite_id, 'to_suite': to_suite.suite_id })
121
122     session.commit()
123
124 def external_overrides_import(suite_name, component_name, key, file, force = False):
125     session = DBConn().session()
126
127     suite = get_suite(suite_name, session)
128     component = get_component(component_name, session)
129
130     if not force and suite.untouchable:
131         print "E: refusing to touch untouchable suite %s (not forced)." % suite_name
132         session.rollback()
133         return False
134
135     session.query(ExternalOverride).filter_by(suite=suite,component=component,key=key).delete()
136
137     for package, key, value in ExternalOverrideReader(file):
138         eo = ExternalOverride()
139         eo.suite = suite
140         eo.component = component
141         eo.package = package
142         eo.key = key
143         eo.value = value
144         session.add(eo)
145
146     session.commit()
147
148 #############################################################################
149
150 def main():
151     cnf = Config()
152
153     Arguments = [('h',"help","External-Overrides::Options::Help"),
154                  ('f','force','External-Overrides::Options::Force')]
155
156     args = apt_pkg.ParseCommandLine(cnf.Cnf, Arguments, sys.argv)
157     try:
158         Options = cnf.SubTree("External-Overrides::Options")
159     except KeyError:
160         Options = {}
161
162     if Options.has_key("Help"):
163         usage()
164
165     force = False
166     if Options.has_key("Force") and Options["Force"]:
167         force = True
168
169     logger = daklog.Logger('external-overrides')
170
171     command = args[0]
172     if command in ('import', 'i'):
173         external_overrides_import(args[1], args[2], args[3], sys.stdin, force)
174     elif command in ('copy', 'c'):
175         external_overrides_copy(args[1], args[2], force)
176     else:
177         print "E: Unknown commands."
178
179 if __name__ == '__main__':
180     main()