]> git.decadent.org.uk Git - dak.git/blob - dak/generate_filelist.py
b7e0b5071511e0d3a650123f89843a73a80d4e6e
[dak.git] / dak / generate_filelist.py
1 #!/usr/bin/python
2
3 """
4 Generate file lists for apt-ftparchive.
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 ################################################################################
26
27 # Ganneff> Please go and try to lock mhy now. After than try to lock NEW.
28 # twerner> !lock mhy
29 # dak> twerner: You suck, this is already locked by Ganneff
30 # Ganneff> now try with NEW
31 # twerner> !lock NEW
32 # dak> twerner: also locked NEW
33 # mhy> Ganneff: oy, stop using me for locks and highlighting me you tall muppet
34 # Ganneff> hehe :)
35
36 ################################################################################
37
38 from daklib.dbconn import *
39 from daklib.config import Config
40 from daklib import utils
41 import apt_pkg, os, sys
42
43 def fetch(query, args, session):
44     return [path + filename for (path, filename) in \
45         session.execute(query, args).fetchall()]
46
47 def getSources(suite, component, session):
48     query = """
49         SELECT path, filename
50             FROM srcfiles_suite_component
51             WHERE suite = :suite AND component = :component
52             ORDER BY filename
53     """
54     args = { 'suite': suite.suite_id,
55              'component': component.component_id }
56     return fetch(query, args, session)
57
58 def getBinaries(suite, component, architecture, type, session):
59     query = """
60 CREATE TEMP TABLE gf_candidates (
61     filename text,
62     path text,
63     architecture integer,
64     src integer,
65     source text);
66
67 INSERT INTO gf_candidates (filename, path, architecture, src, source)
68     SELECT f.filename, l.path, b.architecture, b.source as src, s.source
69         FROM binaries b
70         JOIN bin_associations ba ON b.id = ba.bin
71         JOIN source s ON b.source = s.id
72         JOIN files f ON b.file = f.id
73         JOIN location l ON f.location = l.id
74         WHERE ba.suite = :suite AND b.type = :type AND
75             l.component = :component AND b.architecture IN (2, :architecture);
76
77 WITH arch_any AS
78
79     (SELECT path, filename FROM gf_candidates
80         WHERE architecture > 2),
81
82      arch_all_with_any AS
83     (SELECT path, filename FROM gf_candidates
84         WHERE architecture = 2 AND
85               src IN (SELECT src FROM gf_candidates WHERE architecture > 2)),
86
87      arch_all_without_any AS
88     (SELECT path, filename FROM gf_candidates
89         WHERE architecture = 2 AND
90               source NOT IN (SELECT DISTINCT source FROM gf_candidates WHERE architecture > 2)),
91
92      filelist AS
93     (SELECT * FROM arch_any
94     UNION
95     SELECT * FROM arch_all_with_any
96     UNION
97     SELECT * FROM arch_all_without_any)
98
99     SELECT * FROM filelist ORDER BY filename
100     """
101     args = { 'suite': suite.suite_id,
102              'component': component.component_id,
103              'architecture': architecture.arch_id,
104              'type': type }
105     return fetch(query, args, session)
106
107 def listPath(suite, component, architecture = None, type = None):
108     """returns full path to the list file"""
109     suffixMap = { 'deb': "binary-",
110                   'udeb': "debian-installer_binary-" }
111     if architecture:
112         suffix = suffixMap[type] + architecture.arch_string
113     else:
114         suffix = "source"
115     filename = "%s_%s_%s.list" % \
116         (suite.suite_name, component.component_name, suffix)
117     pathname = os.path.join(Config()["Dir::Lists"], filename)
118     return utils.open_file(pathname, "w")
119
120 def writeSourceList(suite, component, session):
121     file = listPath(suite, component)
122     for filename in getSources(suite, component, session):
123         file.write(filename + '\n')
124     file.close()
125
126 def writeBinaryList(suite, component, architecture, type):
127     file = listPath(suite, component, architecture, type)
128     session = DBConn().session()
129     for filename in getBinaries(suite, component, architecture, type, session):
130         file.write(filename + '\n')
131     session.close()
132     file.close()
133
134 def usage():
135     print """Usage: dak generate_filelist [OPTIONS]
136 Create filename lists for apt-ftparchive.
137
138   -s, --suite=SUITE            act on this suite
139   -c, --component=COMPONENT    act on this component
140   -a, --architecture=ARCH      act on this architecture
141   -h, --help                   show this help and exit
142
143 ARCH, COMPONENT and SUITE can be comma (or space) separated list, e.g.
144     --suite=testing,unstable"""
145     sys.exit()
146
147 def main():
148     cnf = Config()
149     Arguments = [('h', "help",         "Filelist::Options::Help"),
150                  ('s', "suite",        "Filelist::Options::Suite", "HasArg"),
151                  ('c', "component",    "Filelist::Options::Component", "HasArg"),
152                  ('a', "architecture", "Filelist::Options::Architecture", "HasArg")]
153     query_suites = DBConn().session().query(Suite)
154     suites = [suite.suite_name for suite in query_suites.all()]
155     if not cnf.has_key('Filelist::Options::Suite'):
156         cnf['Filelist::Options::Suite'] = ','.join(suites)
157     # we can ask the database for components if 'mixed' is gone
158     if not cnf.has_key('Filelist::Options::Component'):
159         cnf['Filelist::Options::Component'] = 'main,contrib,non-free'
160     query_architectures = DBConn().session().query(Architecture)
161     architectures = \
162         [architecture.arch_string for architecture in query_architectures.all()]
163     if not cnf.has_key('Filelist::Options::Architecture'):
164         cnf['Filelist::Options::Architecture'] = ','.join(architectures)
165     cnf['Filelist::Options::Help'] = ''
166     apt_pkg.ParseCommandLine(cnf.Cnf, Arguments, sys.argv)
167     Options = cnf.SubTree("Filelist::Options")
168     if Options['Help']:
169         usage()
170     session = DBConn().session()
171     suite_arch = session.query(SuiteArchitecture)
172     for suite_name in utils.split_args(Options['Suite']):
173         suite = query_suites.filter_by(suite_name = suite_name).one()
174         join = suite_arch.filter_by(suite_id = suite.suite_id)
175         for component_name in utils.split_args(Options['Component']):
176             component = session.query(Component).\
177                 filter_by(component_name = component_name).one()
178             for architecture_name in utils.split_args(Options['Architecture']):
179                 architecture = query_architectures.\
180                     filter_by(arch_string = architecture_name).one()
181                 try:
182                     join.filter_by(arch_id = architecture.arch_id).one()
183                     if architecture_name == 'source':
184                         writeSourceList(suite, component, session)
185                     elif architecture_name != 'all':
186                         writeBinaryList(suite, component, architecture, 'deb')
187                         writeBinaryList(suite, component, architecture, 'udeb')
188                 except:
189                     pass
190     # this script doesn't change the database
191     session.close()
192
193 if __name__ == '__main__':
194     main()
195