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', 'origin'), ('Label', 'label'), ('Suite', 'suite_name'),
113 ('Version', 'version'), ('Codename', 'codename'), ('Description', 'description'))
114 # A "Sub" Release file has slightly different fields
115 subattribs=( ('Origin', 'origin'), ('Label', 'label'), ('Archive', 'suite_name'),
116 ('Version', 'version'))
117 # Boolean stuff. If we find it true in database, write out "yes" into the release file
118 boolattrs=('notautomatic', 'butautomaticupgrades')
124 outfile=os.path.join(cnf["Dir::Root"], suite.suite_name, "Release")
125 print "Working on: %s" % (outfile)
126 # out = open(outfile, "w")
127 out = open("/tmp/lala", "w")
130 if getattr(suite, key[DBFIELD]) is None:
132 out.write("%s: %s\n" % (key[KEYWORD], getattr(suite, key[DBFIELD])))
134 out.write("Date: %s\n" % (time.strftime("%a, %d %b %Y %H:%M:%S UTC", time.gmtime(time.time()))))
136 validtime=float(suite.validtime)
137 out.write("Valid-Until: %s\n" % (time.strftime("%a, %d %b %Y %H:%M:%S UTC", time.gmtime(time.time()+validtime))))
139 for key in boolattrs:
140 if hasattr(suite, key):
141 if getattr(suite, key):
142 out.write("%s: yes\n" % (key.capitalize()))
143 out.write("Architectures: %s\n" % (" ".join([a.arch_string for a in architectures])))
144 suite_suffix = "%s" % (cnf.Find("Dinstall::SuiteSuffix"))
145 ## FIXME: Components need to be adjusted to whatever will be in the db. see comment above at SC
146 out.write("Components: %s\n" % ( " ".join(map(lambda x: "%s%s" % (suite_suffix, x), SC[suite.suite_name] ))))
148 for comp in SC[suite.suite_name]:
149 for dirpath, dirnames, filenames in os.walk("%sdists/%s/%s" % (cnf["Dir::Root"], suite.suite_name, comp), topdown=True):
150 if not re_getsarelease.match(dirpath):
153 outfile=os.path.join(dirpath, "Release")
154 print "Processing %s" % (outfile)
155 # subrel = open(outfile, "w")
156 subrel = open("/tmp/lala2", "w")
158 ## FIXME: code dupe, line 127.
159 for key in subattribs:
160 if getattr(suite, key[DBFIELD]) is None:
162 subrel.write("%s: %s\n" % (key[KEYWORD], getattr(suite, key[DBFIELD])))
164 for key in boolattrs:
165 if hasattr(suite, key):
166 if getattr(suite, key):
167 subrel.write("%s: yes\n" % (key.capitalize()))
168 subrel.write("Component: %s%s\n" % (suite_suffix, comp))
171 # Now that we have done the groundwork, we want to get off and add the files with
172 # their checksums to the main Release file
176 os.chdir("%sdists/%s" % (cnf["Dir::Root"], suite.suite_name))
178 for dirpath, dirnames, filenames in os.walk(".", topdown=True):
181 for entry in filenames:
182 if not re_includeinarelease.match(entry):
184 filename=os.path.join(dirpath.lstrip('./'), entry)
185 files.append(filename)
193 global Options, Logger, results
197 for i in ["Help", "Suite", "Force"]:
198 if not cnf.has_key("Generate-Releases::Options::%s" % (i)):
199 cnf["Generate-Releases::Options::%s" % (i)] = ""
201 Arguments = [('h',"help","Generate-Releases::Options::Help"),
202 ('s',"suite","Generate-Releases::Options::Suite"),
203 ('f',"force","Generate-Releases::Options::Force")]
205 suite_names = apt_pkg.ParseCommandLine(cnf.Cnf, Arguments, sys.argv)
206 Options = cnf.SubTree("Generate-Releases::Options")
211 Logger = daklog.Logger(cnf, 'generate-releases')
213 session = DBConn().session()
217 for s in suite_names:
218 suite = get_suite(s.lower(), session)
222 print "cannot find suite %s" % s
223 Logger.log(['cannot find suite %s' % s])
225 suites=session.query(Suite).filter(Suite.untouchable == False).all()
227 startdir = os.getcwd()
228 os.chdir(cnf["Dir::TempPath"])
231 # For each given suite, run one process
234 # Setup a multiprocessing Pool. As many workers as we have CPU cores.
236 # Logger.log(['Release file for Suite: %s' % (s.suite_name)])
237 # pool.apply_async(generate_release_files, (s, cnf["Dir::TempPath"]), callback=get_result)
238 # As long as we test, just one and not with mp module
239 generate_release_files(s, cnf["Dir::TempPath"])
242 # No more work will be added to our pool, close it and then wait for all to finish
247 Logger.log(['Release file generation broken: %s' % (results)])
248 print "Release file generation broken: %s" % (results)
252 # this script doesn't change the database
256 #######################################################################################
258 if __name__ == '__main__':