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