3 """ Create all the Release files
5 @contact: Debian FTPMaster <ftpmaster@debian.org>
6 @copyright: 2011 Joerg Jaspert <joerg@debian.org>
7 @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 # <mhy> I wish they wouldnt leave biscuits out, thats just tempting. Damnit.
29 ################################################################################
39 from tempfile import mkstemp, mkdtemp
41 from multiprocessing import Pool, TimeoutError
43 from daklib import utils, daklog
44 from daklib.regexes import re_getsarelease, re_includeinarelease
45 from daklib.dak_exceptions import *
46 from daklib.dbconn import *
47 from daklib.config import Config
49 ################################################################################
50 Options = None #: Commandline arguments parsed into this
51 Logger = None #: Our logging object
52 results = [] #: Results of the subprocesses
54 ################################################################################
56 def usage (exit_code=0):
57 """ Usage information"""
59 print """Usage: dak generate-releases [OPTIONS]
60 Generate the Release files
62 -s, --suite=SUITE(s) process this suite
63 Default: All suites not marked 'untouchable'
64 -f, --force Allow processing of untouchable suites
65 CAREFUL: Only to be used at (point) release time!
66 -h, --help show this help and exit
68 SUITE can be a space seperated list, e.g.
69 --suite=unstable testing
73 ########################################################################
80 ## FIXME: Hardcoded for now. This needs to go via database, but mhy is working on that part.
81 ## until that is done, we just hardcode it here.
82 SC = { "unstable": ("main", "contrib", "non-free"),
83 "oldstable": ("main", "contrib", "non-free"),
84 "testing": ("main", "contrib", "non-free"),
85 "testing-proposed-updates": ("main", "contrib", "non-free"),
86 "experimental": ("main", "contrib", "non-free"),
87 "proposed-updates": ("main", "contrib", "non-free"),
88 "oldstable-proposed-updates": ("main", "contrib", "non-free"),
89 "squeeze-updates": ("main", "contrib", "non-free"),
90 "stable": ("main", "contrib", "non-free"),
91 "squeeze-backports": ("main", "contrib", "non-free"),
92 "lenny-backports": ("main", "contrib", "non-free"),
93 "lenny-backports-sloppy": ("main", "contrib", "non-free"),
97 def generate_release_files(suite, tmppath):
99 Generate Release files for the given suite
102 @param suite: Suite name
104 @type tmppath: string
105 @param tmppath: The temporary path to work in
108 architectures = get_suite_architectures(suite.suite_name, skipall=True, skipsrc=True)
110 # Attribs contains a list of field names to fetch from suite table. Should the entry in the
111 # suite table be named differently, |realname will help it out.
112 attribs=('origin', 'label', 'suite|suite_name', 'version', 'codename', 'description')
113 # A "Sub" Release file has slightly different fields
114 subattribs=('origin', 'label', 'archive|suite_name', 'version')
115 # Boolean stuff. If we find it true in database, write out "yes" into the release file
116 boolattrs=('notautomatic', 'butautomaticupgrades')
120 outfile=os.path.join(cnf["Dir::Root"], suite.suite_name, "Release")
121 print "Working on: %s" % (outfile)
122 # out = open(outfile, "w")
123 out = open("/tmp/lala", "w")
127 if key.find('|') > 0:
134 if getattr(suite, query) is None:
136 out.write("%s: %s\n" % (pout.capitalize(), getattr(suite, query)))
137 out.write("Date: %s\n" % (time.strftime("%a, %d %b %Y %H:%M:%S UTC", time.gmtime(time.time()))))
139 validtime=float(suite.validtime)
140 out.write("Valid-Until: %s\n" % (time.strftime("%a, %d %b %Y %H:%M:%S UTC", time.gmtime(time.time()+validtime))))
142 for key in boolattrs:
143 if hasattr(suite, key):
144 if getattr(suite, key):
145 out.write("%s: yes\n" % (key.capitalize()))
146 out.write("Architectures: %s\n" % (" ".join([a.arch_string for a in architectures])))
147 suite_suffix = "%s" % (cnf.Find("Dinstall::SuiteSuffix"))
148 ## FIXME: Components need to be adjusted to whatever will be in the db. see comment above at SC
149 out.write("Components: %s\n" % ( " ".join(map(lambda x: "%s%s" % (suite_suffix, x), SC[suite.suite_name] ))))
151 for comp in SC[suite.suite_name]:
152 for dirpath, dirnames, filenames in os.walk("%sdists/%s/%s" % (cnf["Dir::Root"], suite.suite_name, comp), topdown=True):
153 if not re_getsarelease.match(dirpath):
156 outfile=os.path.join(dirpath, "Release")
157 print "Processing %s" % (outfile)
158 # subrel = open(outfile, "w")
159 subrel = open("/tmp/lala2", "w")
161 ## FIXME: code dupe, line 127.
164 if key.find('|') > 0:
171 if getattr(suite, query) is None:
173 subrel.write("%s: %s\n" % (pout.capitalize(), getattr(suite, query)))
174 for key in boolattrs:
175 if hasattr(suite, key):
176 if getattr(suite, key):
177 subrel.write("%s: yes\n" % (key.capitalize()))
178 subrel.write("Component: %s%s\n" % (suite_suffix, comp))
181 # Now that we have done the groundwork, we want to get off and add the files with
182 # their checksums to the main Release file
186 os.chdir("%sdists/%s" % (cnf["Dir::Root"], suite.suite_name))
188 for dirpath, dirnames, filenames in os.walk(".", topdown=True):
191 for entry in filenames:
192 if not re_includeinarelease.match(entry):
194 filename=os.path.join(dirpath.lstrip('./'), entry)
195 files.append(filename)
203 global Options, Logger, results
207 for i in ["Help", "Suite", "Force"]:
208 if not cnf.has_key("Generate-Releases::Options::%s" % (i)):
209 cnf["Generate-Releases::Options::%s" % (i)] = ""
211 Arguments = [('h',"help","Generate-Releases::Options::Help"),
212 ('s',"suite","Generate-Releases::Options::Suite"),
213 ('f',"force","Generate-Releases::Options::Force")]
215 suite_names = apt_pkg.ParseCommandLine(cnf.Cnf, Arguments, sys.argv)
216 Options = cnf.SubTree("Generate-Releases::Options")
221 Logger = daklog.Logger(cnf, 'generate-releases')
223 session = DBConn().session()
227 for s in suite_names:
228 suite = get_suite(s.lower(), session)
232 print "cannot find suite %s" % s
233 Logger.log(['cannot find suite %s' % s])
235 suites=session.query(Suite).filter(Suite.untouchable == False).all()
237 startdir = os.getcwd()
238 os.chdir(cnf["Dir::TempPath"])
241 # For each given suite, run one process
244 # Setup a multiprocessing Pool. As many workers as we have CPU cores.
246 # Logger.log(['Release file for Suite: %s' % (s.suite_name)])
247 # pool.apply_async(generate_release_files, (s, cnf["Dir::TempPath"]), callback=get_result)
248 # As long as we test, just one and not with mp module
249 generate_release_files(s, cnf["Dir::TempPath"])
252 # No more work will be added to our pool, close it and then wait for all to finish
257 Logger.log(['Release file generation broken: %s' % (results)])
258 print "Release file generation broken: %s" % (results)
262 # this script doesn't change the database
266 #######################################################################################
268 if __name__ == '__main__':