4 Generate file lists for apt-ftparchive.
6 @contact: Debian FTP Master <ftpmaster@debian.org>
7 @copyright: 2009 Torsten Werner <twerner@debian.org>
8 @copyright: 2011 Ansgar Burchardt <ansgar@debian.org>
9 @license: GNU General Public License version 2 or later
12 # This program is free software; you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation; either version 2 of the License, or
15 # (at your option) any later version.
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 ################################################################################
28 # Ganneff> Please go and try to lock mhy now. After than try to lock NEW.
30 # dak> twerner: You suck, this is already locked by Ganneff
31 # Ganneff> now try with NEW
33 # dak> twerner: also locked NEW
34 # mhy> Ganneff: oy, stop using me for locks and highlighting me you tall muppet
37 ################################################################################
39 from daklib.dbconn import *
40 from daklib.config import Config
41 from daklib import utils, daklog
42 from daklib.dakmultiprocessing import DakProcessPool, PROC_STATUS_SUCCESS, PROC_STATUS_SIGNALRAISED
43 import apt_pkg, os, stat, sys
45 from daklib.lists import getSources, getBinaries, getArchAll
49 def listPath(suite, component, architecture = None, type = None,
50 incremental_mode = False):
51 """returns full path to the list file"""
52 suffixMap = { 'deb': "binary-",
53 'udeb': "debian-installer_binary-" }
55 suffix = suffixMap[type] + architecture.arch_string
58 filename = "%s_%s_%s.list" % \
59 (suite.suite_name, component.component_name, suffix)
60 pathname = os.path.join(Config()["Dir::Lists"], filename)
61 file = utils.open_file(pathname, "a")
64 timestamp = os.fstat(file.fileno())[stat.ST_MTIME]
68 return (file, timestamp)
70 def writeSourceList(suite_id, component_id, incremental_mode):
71 session = DBConn().session()
72 suite = Suite.get(suite_id, session)
73 component = Component.get(component_id, session)
74 (file, timestamp) = listPath(suite, component,
75 incremental_mode = incremental_mode)
77 message = "sources list for %s %s" % (suite.suite_name, component.component_name)
79 for _, filename in getSources(suite, component, session, timestamp):
80 file.write(filename + '\n')
85 def writeAllList(suite_id, component_id, architecture_id, type, incremental_mode):
86 session = DBConn().session()
87 suite = Suite.get(suite_id, session)
88 component = Component.get(component_id, session)
89 architecture = Architecture.get(architecture_id, session)
90 (file, timestamp) = listPath(suite, component, architecture, type,
93 message = "all list for %s %s (arch=%s, type=%s)" % (suite.suite_name, component.component_name, architecture.arch_string, type)
95 for _, filename in getArchAll(suite, component, architecture, type,
97 file.write(filename + '\n')
102 def writeBinaryList(suite_id, component_id, architecture_id, type, incremental_mode):
103 session = DBConn().session()
104 suite = Suite.get(suite_id, session)
105 component = Component.get(component_id, session)
106 architecture = Architecture.get(architecture_id, session)
107 (file, timestamp) = listPath(suite, component, architecture, type,
110 message = "binary list for %s %s (arch=%s, type=%s)" % (suite.suite_name, component.component_name, architecture.arch_string, type)
112 for _, filename in getBinaries(suite, component, architecture, type,
114 file.write(filename + '\n')
120 print """Usage: dak generate_filelist [OPTIONS]
121 Create filename lists for apt-ftparchive.
123 -s, --suite=SUITE act on this suite
124 -c, --component=COMPONENT act on this component
125 -a, --architecture=ARCH act on this architecture
126 -h, --help show this help and exit
127 -i, --incremental activate incremental mode
129 ARCH, COMPONENT and SUITE can be comma (or space) separated list, e.g.
130 --suite=testing,unstable
132 Incremental mode appends only newer files to existing lists."""
137 Logger = daklog.Logger(cnf, 'generate-filelist')
138 Arguments = [('h', "help", "Filelist::Options::Help"),
139 ('s', "suite", "Filelist::Options::Suite", "HasArg"),
140 ('c', "component", "Filelist::Options::Component", "HasArg"),
141 ('a', "architecture", "Filelist::Options::Architecture", "HasArg"),
142 ('i', "incremental", "Filelist::Options::Incremental")]
143 session = DBConn().session()
144 query_suites = session.query(Suite)
145 suites = [suite.suite_name for suite in query_suites]
146 if not cnf.has_key('Filelist::Options::Suite'):
147 cnf['Filelist::Options::Suite'] = ','.join(suites).encode()
148 query_components = session.query(Component)
150 [component.component_name for component in query_components]
151 if not cnf.has_key('Filelist::Options::Component'):
152 cnf['Filelist::Options::Component'] = ','.join(components).encode()
153 query_architectures = session.query(Architecture)
155 [architecture.arch_string for architecture in query_architectures]
156 if not cnf.has_key('Filelist::Options::Architecture'):
157 cnf['Filelist::Options::Architecture'] = ','.join(architectures).encode()
158 cnf['Filelist::Options::Help'] = ''
159 cnf['Filelist::Options::Incremental'] = ''
160 apt_pkg.ParseCommandLine(cnf.Cnf, Arguments, sys.argv)
161 Options = cnf.SubTree("Filelist::Options")
164 pool = DakProcessPool()
165 query_suites = query_suites. \
166 filter(Suite.suite_name.in_(utils.split_args(Options['Suite'])))
167 query_components = query_components. \
168 filter(Component.component_name.in_(utils.split_args(Options['Component'])))
169 query_architectures = query_architectures. \
170 filter(Architecture.arch_string.in_(utils.split_args(Options['Architecture'])))
172 def parse_results(message):
173 # Split out into (code, msg)
175 if code == PROC_STATUS_SUCCESS:
177 elif code == PROC_STATUS_SIGNALRAISED:
178 Logger.log(['E: Subprocess recieved signal ', msg])
180 Logger.log(['E: ', msg])
182 for suite in query_suites:
183 suite_id = suite.suite_id
184 for component in query_components:
185 component_id = component.component_id
186 for architecture in query_architectures:
187 architecture_id = architecture.arch_id
188 if architecture not in suite.architectures:
190 elif architecture.arch_string == 'source':
191 pool.apply_async(writeSourceList,
192 (suite_id, component_id, Options['Incremental']), callback=parse_results)
193 elif architecture.arch_string == 'all':
194 pool.apply_async(writeAllList,
195 (suite_id, component_id, architecture_id, 'deb',
196 Options['Incremental']), callback=parse_results)
197 pool.apply_async(writeAllList,
198 (suite_id, component_id, architecture_id, 'udeb',
199 Options['Incremental']), callback=parse_results)
201 pool.apply_async(writeBinaryList,
202 (suite_id, component_id, architecture_id, 'deb',
203 Options['Incremental']), callback=parse_results)
204 pool.apply_async(writeBinaryList,
205 (suite_id, component_id, architecture_id, 'udeb',
206 Options['Incremental']), callback=parse_results)
210 # this script doesn't change the database
215 sys.exit(pool.overall_status())
217 if __name__ == '__main__':