]> git.decadent.org.uk Git - dak.git/blob - dak/dominate.py
Merge remote-tracking branch 'jcristau/cs-set-log-suite'
[dak.git] / dak / dominate.py
1 #!/usr/bin/python
2
3 """
4 Remove obsolete source and binary associations from suites.
5
6 @contact: Debian FTP Master <ftpmaster@debian.org>
7 @copyright: 2009  Torsten Werner <twerner@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 daklog, utils
28 import apt_pkg, sys
29
30 Options = None
31 Logger = None
32
33 def fetch(reason, query, args, session):
34     idList = []
35     for row in session.execute(query, args).fetchall():
36         (id, package, version, suite_name, architecture) = row
37         if Options['No-Action']:
38             print "Delete %s %s from %s architecture %s (%s, %d)" % \
39                 (package, version, suite_name, architecture, reason, id)
40         else:
41             Logger.log([reason, package, version, suite_name, \
42                 architecture, id])
43         idList.append(id)
44     return idList
45
46 def obsoleteAnyByAllAssociations(suite, session):
47     query = """
48         SELECT obsolete.id, package, obsolete.version, suite_name, arch_string
49             FROM obsolete_any_by_all_associations AS obsolete
50             JOIN architecture ON obsolete.architecture = architecture.id
51             JOIN suite ON obsolete.suite = suite.id
52             WHERE suite = :suite
53     """
54     return fetch('newer_all', query, { 'suite': suite }, session)
55
56 def obsoleteAnyAssociations(suite, session):
57     query = """
58         SELECT obsolete.id, package, obsolete.version, suite_name, arch_string
59             FROM obsolete_any_associations AS obsolete
60             JOIN architecture ON obsolete.architecture = architecture.id
61             JOIN suite ON obsolete.suite = suite.id
62             WHERE suite = :suite
63     """
64     return fetch('newer_any', query, { 'suite': suite }, session)
65
66 def obsoleteSrcAssociations(suite, session):
67     query = """
68         SELECT obsolete.id, source, obsolete.version, suite_name,
69             'source' AS arch_string
70             FROM obsolete_src_associations AS obsolete
71             JOIN suite ON obsolete.suite = suite.id
72             WHERE suite = :suite
73     """
74     return fetch('old_and_unreferenced', query, { 'suite': suite }, session)
75
76 def obsoleteAllAssociations(suite, session):
77     query = """
78         SELECT obsolete.id, package, obsolete.version, suite_name,
79             'all' AS arch_string
80             FROM obsolete_all_associations AS obsolete
81             JOIN suite ON obsolete.suite = suite.id
82             WHERE suite = :suite
83     """
84     return fetch('old_and_unreferenced', query, { 'suite': suite }, session)
85
86 def deleteAssociations(table, idList, session):
87     global Options
88     query = """
89         DELETE
90             FROM %s
91             WHERE id IN :idList
92     """ % table
93     if not idList or Options['No-Action']:
94         return
95     params = {'idList': tuple(idList)}
96     session.execute(query, params)
97
98 def doDaDoDa(suite, session):
99     # keep this part disabled because it is too dangerous
100     #idList = obsoleteAnyByAllAssociations(suite, session)
101     #deleteAssociations('bin_associations', idList, session)
102
103     idList = obsoleteAnyAssociations(suite, session)
104     deleteAssociations('bin_associations', idList, session)
105
106     idList = obsoleteSrcAssociations(suite, session)
107     deleteAssociations('src_associations', idList, session)
108
109     idList = obsoleteAllAssociations(suite, session)
110     deleteAssociations('bin_associations', idList, session)
111
112 def usage():
113     print """Usage: dak dominate [OPTIONS]
114 Remove obsolete source and binary associations from suites.
115
116     -s, --suite=SUITE          act on this suite
117     -h, --help                 show this help and exit
118     -n, --no-action            don't commit changes
119     -f, --force                also clean up untouchable suites
120
121 SUITE can be comma (or space) separated list, e.g.
122     --suite=testing,unstable"""
123     sys.exit()
124
125 def main():
126     global Options, Logger
127     cnf = Config()
128     Arguments = [('h', "help",      "Obsolete::Options::Help"),
129                  ('s', "suite",     "Obsolete::Options::Suite", "HasArg"),
130                  ('n', "no-action", "Obsolete::Options::No-Action"),
131                  ('f', "force",     "Obsolete::Options::Force")]
132     cnf['Obsolete::Options::Help'] = ''
133     cnf['Obsolete::Options::No-Action'] = ''
134     cnf['Obsolete::Options::Force'] = ''
135     apt_pkg.parse_commandline(cnf.Cnf, Arguments, sys.argv)
136     Options = cnf.subtree("Obsolete::Options")
137     if Options['Help']:
138         usage()
139     if 'Suite' not in Options:
140         query_suites = DBConn().session().query(Suite)
141         suites = [suite.suite_name for suite in query_suites]
142         cnf['Obsolete::Options::Suite'] = str(','.join(suites))
143
144     if not Options['No-Action']:
145        Logger = daklog.Logger("dominate")
146     session = DBConn().session()
147     for suite_name in utils.split_args(Options['Suite']):
148         suite = session.query(Suite).filter_by(suite_name = suite_name).one()
149
150         # Skip policy queues. We don't want to remove obsolete packages from those.
151         policy_queue = session.query(PolicyQueue).filter_by(suite=suite).first()
152         if policy_queue is not None:
153             continue
154
155         if not suite.untouchable or Options['Force']:
156             doDaDoDa(suite.suite_id, session)
157     if Options['No-Action']:
158         session.rollback()
159     else:
160         session.commit()
161     if Logger:
162         Logger.close()
163
164 if __name__ == '__main__':
165     main()
166