britney2-ubuntu/doc/html/britney_8py-source.html
Fabio Tranchitella f7b9bdc1f4 Support for fake source packages, which solved the last compatibility issues for the old britney code.
Added documentation and comments to explain the code. It is possible to generate HTML and LaTeX documentation using doxygen.
2006-06-24 17:49:43 +00:00

1117 lines
132 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>briteny: britney.py Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
<link href="tabs.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.4.6 -->
<div class="tabs">
<ul>
<li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
<li><a href="namespaces.html"><span>Packages</span></a></li>
<li><a href="annotated.html"><span>Classes</span></a></li>
<li id="current"><a href="files.html"><span>Files</span></a></li>
</ul></div>
<h1>britney.py</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a><a class="code" href="namespacebritney.html">00001</a> <span class="comment">#!/usr/bin/env python2.4</span>
<a name="l00002"></a>00002 <span class="comment"># -*- coding: utf-8 -*-</span>
<a name="l00003"></a>00003
<a name="l00004"></a>00004 <span class="comment"># Copyright (C) 2001-2004 Anthony Towns &lt;ajt@debian.org&gt;</span>
<a name="l00005"></a>00005 <span class="comment"># Andreas Barth &lt;aba@debian.org&gt;</span>
<a name="l00006"></a>00006 <span class="comment"># Fabio Tranchitella &lt;kobold@debian.org&gt;</span>
<a name="l00007"></a>00007
<a name="l00008"></a>00008 <span class="comment"># This program is free software; you can redistribute it and/or modify</span>
<a name="l00009"></a>00009 <span class="comment"># it under the terms of the GNU General Public License as published by</span>
<a name="l00010"></a>00010 <span class="comment"># the Free Software Foundation; either version 2 of the License, or</span>
<a name="l00011"></a>00011 <span class="comment"># (at your option) any later version.</span>
<a name="l00012"></a>00012
<a name="l00013"></a>00013 <span class="comment"># This program is distributed in the hope that it will be useful,</span>
<a name="l00014"></a>00014 <span class="comment"># but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<a name="l00015"></a>00015 <span class="comment"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span>
<a name="l00016"></a>00016 <span class="comment"># GNU General Public License for more details.</span>
<a name="l00017"></a>00017
<a name="l00018"></a>00018 <span class="keyword">import</span> os
<a name="l00019"></a>00019 <span class="keyword">import</span> re
<a name="l00020"></a>00020 <span class="keyword">import</span> sys
<a name="l00021"></a>00021 <span class="keyword">import</span> string
<a name="l00022"></a>00022 <span class="keyword">import</span> time
<a name="l00023"></a>00023 <span class="keyword">import</span> optparse
<a name="l00024"></a>00024
<a name="l00025"></a>00025 <span class="keyword">import</span> apt_pkg
<a name="l00026"></a>00026
<a name="l00027"></a>00027 <span class="keyword">from</span> excuse <span class="keyword">import</span> Excuse
<a name="l00028"></a>00028
<a name="l00029"></a>00029 __author__ = <span class="stringliteral">'Fabio Tranchitella'</span>
<a name="l00030"></a>00030 __version__ = <span class="stringliteral">'2.0.alpha1'</span>
<a name="l00031"></a>00031
<a name="l00032"></a>00032
<a name="l00033"></a><a class="code" href="classbritney_1_1Britney.html">00033</a> <span class="keyword">class </span><a class="code" href="classbritney_1_1Britney.html">Britney</a>:
<a name="l00034"></a>00034 <span class="stringliteral">"""Britney, the debian testing updater script</span>
<a name="l00035"></a>00035 <span class="stringliteral"> </span>
<a name="l00036"></a><a class="code" href="classbritney_1_1Britney.html#ebbe3f40cca59e2de275b0558556ee63">00036</a> <span class="stringliteral"> This is the script that updates the testing_ distribution. It is executed</span>
<a name="l00037"></a><a class="code" href="classbritney_1_1Britney.html#a088d6fd96963f87f88c9c40cda10bfa">00037</a> <span class="stringliteral"> each day after the installation of the updated packages. It generates the </span>
<a name="l00038"></a>00038 <span class="stringliteral"> `Packages' files for the testing distribution, but it does so in an</span>
<a name="l00039"></a><a class="code" href="classbritney_1_1Britney.html#5846d81eace24f479292c47e30fd1851">00039</a> <span class="stringliteral"> intelligent manner; it try to avoid any inconsistency and to use only</span>
<a name="l00040"></a>00040 <span class="stringliteral"> non-buggy packages.</span>
<a name="l00041"></a>00041 <span class="stringliteral"></span>
<a name="l00042"></a>00042 <span class="stringliteral"> For more documentation on this script, please read the Developers Reference.</span>
<a name="l00043"></a>00043 <span class="stringliteral"> """</span>
<a name="l00044"></a>00044
<a name="l00045"></a>00045 HINTS_STANDARD = (<span class="stringliteral">"easy"</span>, <span class="stringliteral">"hint"</span>, <span class="stringliteral">"remove"</span>, <span class="stringliteral">"block"</span>, <span class="stringliteral">"unblock"</span>, <span class="stringliteral">"urgent"</span>, <span class="stringliteral">"approve"</span>)
<a name="l00046"></a>00046 HINTS_ALL = (<span class="stringliteral">"force"</span>, <span class="stringliteral">"force-hint"</span>, <span class="stringliteral">"block-all"</span>) + HINTS_STANDARD
<a name="l00047"></a>00047
<a name="l00048"></a>00048 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#5846d81eace24f479292c47e30fd1851">__init__</a>(self):
<a name="l00049"></a>00049 <span class="stringliteral">"""Class constructor</span>
<a name="l00050"></a>00050 <span class="stringliteral"></span>
<a name="l00051"></a>00051 <span class="stringliteral"> This method initializes and populates the data lists, which contain all</span>
<a name="l00052"></a>00052 <span class="stringliteral"> the information needed by the other methods of the class.</span>
<a name="l00053"></a>00053 <span class="stringliteral"> """</span>
<a name="l00054"></a>00054 self.date_now = int(((time.time() / (60*60)) - 15) / 24)
<a name="l00055"></a>00055
<a name="l00056"></a>00056 <span class="comment"># parse the command line arguments</span>
<a name="l00057"></a>00057 self.<a class="code" href="classbritney_1_1Britney.html#506f9800068902cf7cac6236b78d1dc4">__parse_arguments</a>()
<a name="l00058"></a>00058
<a name="l00059"></a>00059 <span class="comment"># initialize the apt_pkg back-end</span>
<a name="l00060"></a>00060 apt_pkg.init()
<a name="l00061"></a>00061
<a name="l00062"></a>00062 <span class="comment"># read the source and binary packages for the involved distributions</span>
<a name="l00063"></a>00063 self.sources = {<span class="stringliteral">'testing'</span>: self.<a class="code" href="classbritney_1_1Britney.html#054f44c47f17c0c4f5a069e821b7f868">read_sources</a>(self.options.testing),
<a name="l00064"></a>00064 <span class="stringliteral">'unstable'</span>: self.<a class="code" href="classbritney_1_1Britney.html#054f44c47f17c0c4f5a069e821b7f868">read_sources</a>(self.options.unstable),
<a name="l00065"></a>00065 <span class="stringliteral">'tpu'</span>: self.<a class="code" href="classbritney_1_1Britney.html#054f44c47f17c0c4f5a069e821b7f868">read_sources</a>(self.options.tpu),}
<a name="l00066"></a>00066 self.binaries = {<span class="stringliteral">'testing'</span>: {}, <span class="stringliteral">'unstable'</span>: {}, <span class="stringliteral">'tpu'</span>: {}}
<a name="l00067"></a>00067 <span class="keywordflow">for</span> arch <span class="keywordflow">in</span> self.options.architectures:
<a name="l00068"></a>00068 self.binaries[<span class="stringliteral">'testing'</span>][arch] = self.<a class="code" href="classbritney_1_1Britney.html#1b2b0f42e4af1cee472f93e955b30421">read_binaries</a>(self.options.testing, <span class="stringliteral">"testing"</span>, arch)
<a name="l00069"></a>00069 self.binaries[<span class="stringliteral">'unstable'</span>][arch] = self.<a class="code" href="classbritney_1_1Britney.html#1b2b0f42e4af1cee472f93e955b30421">read_binaries</a>(self.options.unstable, <span class="stringliteral">"unstable"</span>, arch)
<a name="l00070"></a>00070 self.binaries[<span class="stringliteral">'tpu'</span>][arch] = self.<a class="code" href="classbritney_1_1Britney.html#1b2b0f42e4af1cee472f93e955b30421">read_binaries</a>(self.options.tpu, <span class="stringliteral">"tpu"</span>, arch)
<a name="l00071"></a>00071
<a name="l00072"></a>00072 <span class="comment"># read the release-critical bug summaries for testing and unstable</span>
<a name="l00073"></a>00073 self.bugs = {<span class="stringliteral">'unstable'</span>: self.<a class="code" href="classbritney_1_1Britney.html#6c777aae69e7bec2efebaf23ddd4a86c">read_bugs</a>(self.options.unstable),
<a name="l00074"></a>00074 <span class="stringliteral">'testing'</span>: self.<a class="code" href="classbritney_1_1Britney.html#6c777aae69e7bec2efebaf23ddd4a86c">read_bugs</a>(self.options.testing),}
<a name="l00075"></a><a class="code" href="classbritney_1_1Britney.html#506f9800068902cf7cac6236b78d1dc4">00075</a> self.<a class="code" href="classbritney_1_1Britney.html#5a6af4a100cfd54e872a27fa7f48ac3c">normalize_bugs</a>()
<a name="l00076"></a>00076
<a name="l00077"></a>00077 <span class="comment"># read additional data</span>
<a name="l00078"></a>00078 self.dates = self.<a class="code" href="classbritney_1_1Britney.html#085af5ac906813ea40fc2e623748f517">read_dates</a>(self.options.testing)
<a name="l00079"></a>00079 self.urgencies = self.<a class="code" href="classbritney_1_1Britney.html#09fc27899506b4830b1961f125a7b6a4">read_urgencies</a>(self.options.testing)
<a name="l00080"></a>00080 self.approvals = self.<a class="code" href="classbritney_1_1Britney.html#39248f0cfea1c8798b2ca5a97d37eaf8">read_approvals</a>(self.options.tpu)
<a name="l00081"></a>00081 self.hints = self.<a class="code" href="classbritney_1_1Britney.html#46d535f617fcf1faaaf5d841ea23c184">read_hints</a>(self.options.unstable)
<a name="l00082"></a>00082 self.excuses = []
<a name="l00083"></a>00083
<a name="l00084"></a>00084 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#506f9800068902cf7cac6236b78d1dc4">__parse_arguments</a>(self):
<a name="l00085"></a>00085 <span class="stringliteral">"""Parse the command line arguments</span>
<a name="l00086"></a>00086 <span class="stringliteral"></span>
<a name="l00087"></a>00087 <span class="stringliteral"> This method parses and initializes the command line arguments.</span>
<a name="l00088"></a>00088 <span class="stringliteral"> While doing so, it preprocesses some of the options to be converted</span>
<a name="l00089"></a>00089 <span class="stringliteral"> in a suitable form for the other methods of the class.</span>
<a name="l00090"></a>00090 <span class="stringliteral"> """</span>
<a name="l00091"></a>00091 <span class="comment"># initialize the parser</span>
<a name="l00092"></a>00092 self.parser = optparse.OptionParser(version=<span class="stringliteral">"%prog"</span>)
<a name="l00093"></a>00093 self.parser.add_option(<span class="stringliteral">"-v"</span>, <span class="stringliteral">""</span>, action=<span class="stringliteral">"count"</span>, dest=<span class="stringliteral">"verbose"</span>, help=<span class="stringliteral">"enable verbose output"</span>)
<a name="l00094"></a>00094 self.parser.add_option(<span class="stringliteral">"-c"</span>, <span class="stringliteral">"--config"</span>, action=<span class="stringliteral">"store"</span>, dest=<span class="stringliteral">"config"</span>,
<a name="l00095"></a>00095 default=<span class="stringliteral">"/etc/britney.conf"</span>, help=<span class="stringliteral">"path for the configuration file"</span>)
<a name="l00096"></a>00096 (self.options, self.args) = self.parser.parse_args()
<a name="l00097"></a>00097
<a name="l00098"></a>00098 <span class="comment"># if the configuration file exists, than read it and set the additional options</span>
<a name="l00099"></a>00099 <span class="keywordflow">if</span> <span class="keywordflow">not</span> os.path.isfile(self.options.config):
<a name="l00100"></a>00100 self.<a class="code" href="classbritney_1_1Britney.html#678036a5200302d77249f5e702532681">__log</a>(<span class="stringliteral">"Unable to read the configuration file (%s), exiting!"</span> % self.options.config, type=<span class="stringliteral">"E"</span>)
<a name="l00101"></a>00101 sys.exit(1)
<a name="l00102"></a>00102
<a name="l00103"></a>00103 <span class="comment"># minimum days for unstable-testing transition and the list of hints</span>
<a name="l00104"></a>00104 <span class="comment"># are handled as an ad-hoc case</span>
<a name="l00105"></a>00105 self.MINDAYS = {}
<a name="l00106"></a>00106 self.HINTS = {}
<a name="l00107"></a>00107 <span class="keywordflow">for</span> k, v <span class="keywordflow">in</span> [map(string.strip,r.split(<span class="stringliteral">'='</span>, 1)) <span class="keywordflow">for</span> r <span class="keywordflow">in</span> file(self.options.config) <span class="keywordflow">if</span> <span class="stringliteral">'='</span> <span class="keywordflow">in</span> r <span class="keywordflow">and</span> <span class="keywordflow">not</span> r.strip().startswith(<span class="stringliteral">'#'</span>)]:
<a name="l00108"></a>00108 <span class="keywordflow">if</span> k.startswith(<span class="stringliteral">"MINDAYS_"</span>):
<a name="l00109"></a>00109 self.MINDAYS[k.split(<span class="stringliteral">"_"</span>)[1].lower()] = int(v)
<a name="l00110"></a>00110 <span class="keywordflow">elif</span> k.startswith(<span class="stringliteral">"HINTS_"</span>):
<a name="l00111"></a>00111 self.HINTS[k.split(<span class="stringliteral">"_"</span>)[1].lower()] = \
<a name="l00112"></a>00112 reduce(<span class="keyword">lambda</span> x,y: x+y, [hasattr(self, <span class="stringliteral">"HINTS_"</span> + i) <span class="keywordflow">and</span> getattr(self, <span class="stringliteral">"HINTS_"</span> + i) <span class="keywordflow">or</span> (i,) <span class="keywordflow">for</span> i <span class="keywordflow">in</span> v.split()])
<a name="l00113"></a>00113 <span class="keywordflow">else</span>:
<a name="l00114"></a>00114 setattr(self.options, k.lower(), v)
<a name="l00115"></a><a class="code" href="classbritney_1_1Britney.html#678036a5200302d77249f5e702532681">00115</a>
<a name="l00116"></a>00116 <span class="comment"># Sort the architecture list</span>
<a name="l00117"></a>00117 allarches = sorted(self.options.architectures.split())
<a name="l00118"></a>00118 arches = [x <span class="keywordflow">for</span> x <span class="keywordflow">in</span> allarches <span class="keywordflow">if</span> x <span class="keywordflow">in</span> self.options.nobreakall_arches]
<a name="l00119"></a>00119 arches += [x <span class="keywordflow">for</span> x <span class="keywordflow">in</span> allarches <span class="keywordflow">if</span> x <span class="keywordflow">not</span> <span class="keywordflow">in</span> arches <span class="keywordflow">and</span> x <span class="keywordflow">not</span> <span class="keywordflow">in</span> self.options.fucked_arches]
<a name="l00120"></a>00120 arches += [x <span class="keywordflow">for</span> x <span class="keywordflow">in</span> allarches <span class="keywordflow">if</span> x <span class="keywordflow">not</span> <span class="keywordflow">in</span> arches <span class="keywordflow">and</span> x <span class="keywordflow">not</span> <span class="keywordflow">in</span> self.options.break_arches]
<a name="l00121"></a>00121 arches += [x <span class="keywordflow">for</span> x <span class="keywordflow">in</span> allarches <span class="keywordflow">if</span> x <span class="keywordflow">not</span> <span class="keywordflow">in</span> arches]
<a name="l00122"></a>00122 self.options.architectures = arches
<a name="l00123"></a>00123
<a name="l00124"></a>00124 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#678036a5200302d77249f5e702532681">__log</a>(self, msg, type="I"):
<a name="l00125"></a>00125 <span class="stringliteral">"""Print info messages according to verbosity level</span>
<a name="l00126"></a>00126 <span class="stringliteral"> </span>
<a name="l00127"></a>00127 <span class="stringliteral"> An easy-and-simple log method which prints messages to the standard</span>
<a name="l00128"></a>00128 <span class="stringliteral"> output. The type parameter controls the urgency of the message, and</span>
<a name="l00129"></a>00129 <span class="stringliteral"> can be equal to `I' for `Information', `W' for `Warning' and `E' for</span>
<a name="l00130"></a><a class="code" href="classbritney_1_1Britney.html#054f44c47f17c0c4f5a069e821b7f868">00130</a> <span class="stringliteral"> `Error'. Warnings and errors are always printed, and information are</span>
<a name="l00131"></a>00131 <span class="stringliteral"> printed only if the verbose logging is enabled.</span>
<a name="l00132"></a>00132 <span class="stringliteral"> """</span>
<a name="l00133"></a>00133 <span class="keywordflow">if</span> self.options.verbose <span class="keywordflow">or</span> type <span class="keywordflow">in</span> (<span class="stringliteral">"E"</span>, <span class="stringliteral">"W"</span>):
<a name="l00134"></a>00134 <span class="keywordflow">print</span> <span class="stringliteral">"%s: [%s] - %s"</span> % (type, time.asctime(), msg)
<a name="l00135"></a>00135
<a name="l00136"></a>00136 <span class="comment"># Data reading/writing methods</span>
<a name="l00137"></a>00137 <span class="comment"># ----------------------------</span>
<a name="l00138"></a>00138
<a name="l00139"></a>00139 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#054f44c47f17c0c4f5a069e821b7f868">read_sources</a>(self, basedir):
<a name="l00140"></a>00140 <span class="stringliteral">"""Read the list of source packages from the specified directory</span>
<a name="l00141"></a>00141 <span class="stringliteral"> </span>
<a name="l00142"></a>00142 <span class="stringliteral"> The source packages are read from the `Sources' file within the</span>
<a name="l00143"></a>00143 <span class="stringliteral"> directory specified as `basedir' parameter. Considering the</span>
<a name="l00144"></a>00144 <span class="stringliteral"> large amount of memory needed, not all the fields are loaded</span>
<a name="l00145"></a>00145 <span class="stringliteral"> in memory. The available fields are Version, Maintainer and Section.</span>
<a name="l00146"></a>00146 <span class="stringliteral"></span>
<a name="l00147"></a>00147 <span class="stringliteral"> The method returns a list where every item represents a source</span>
<a name="l00148"></a>00148 <span class="stringliteral"> package as a dictionary.</span>
<a name="l00149"></a>00149 <span class="stringliteral"> """</span>
<a name="l00150"></a>00150 sources = {}
<a name="l00151"></a>00151 package = <span class="keywordtype">None</span>
<a name="l00152"></a>00152 filename = os.path.join(basedir, <span class="stringliteral">"Sources"</span>)
<a name="l00153"></a>00153 self.<a class="code" href="classbritney_1_1Britney.html#678036a5200302d77249f5e702532681">__log</a>(<span class="stringliteral">"Loading source packages from %s"</span> % filename)
<a name="l00154"></a>00154 packages = apt_pkg.ParseTagFile(open(filename))
<a name="l00155"></a><a class="code" href="classbritney_1_1Britney.html#1b2b0f42e4af1cee472f93e955b30421">00155</a> <span class="keywordflow">while</span> packages.Step():
<a name="l00156"></a>00156 pkg = packages.Section.get(<span class="stringliteral">'Package'</span>)
<a name="l00157"></a>00157 sources[pkg] = {<span class="stringliteral">'binaries'</span>: [],
<a name="l00158"></a>00158 <span class="stringliteral">'version'</span>: packages.Section.get(<span class="stringliteral">'Version'</span>),
<a name="l00159"></a>00159 <span class="stringliteral">'maintainer'</span>: packages.Section.get(<span class="stringliteral">'Maintainer'</span>),
<a name="l00160"></a>00160 <span class="stringliteral">'section'</span>: packages.Section.get(<span class="stringliteral">'Section'</span>),
<a name="l00161"></a>00161 }
<a name="l00162"></a>00162 <span class="keywordflow">return</span> sources
<a name="l00163"></a>00163
<a name="l00164"></a>00164 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#1b2b0f42e4af1cee472f93e955b30421">read_binaries</a>(self, basedir, distribution, arch):
<a name="l00165"></a>00165 <span class="stringliteral">"""Read the list of binary packages from the specified directory</span>
<a name="l00166"></a>00166 <span class="stringliteral"> </span>
<a name="l00167"></a>00167 <span class="stringliteral"> The binary packages are read from the `Packages_${arch}' files</span>
<a name="l00168"></a>00168 <span class="stringliteral"> within the directory specified as `basedir' parameter, replacing</span>
<a name="l00169"></a>00169 <span class="stringliteral"> ${arch} with the value of the arch parameter. Considering the</span>
<a name="l00170"></a>00170 <span class="stringliteral"> large amount of memory needed, not all the fields are loaded</span>
<a name="l00171"></a>00171 <span class="stringliteral"> in memory. The available fields are Version, Source, Pre-Depends,</span>
<a name="l00172"></a>00172 <span class="stringliteral"> Depends, Conflicts, Provides and Architecture.</span>
<a name="l00173"></a>00173 <span class="stringliteral"> </span>
<a name="l00174"></a>00174 <span class="stringliteral"> After reading the packages, reverse dependencies are computed</span>
<a name="l00175"></a>00175 <span class="stringliteral"> and saved in the `rdepends' keys, and the `Provides' field is</span>
<a name="l00176"></a>00176 <span class="stringliteral"> used to populate the virtual packages list.</span>
<a name="l00177"></a>00177 <span class="stringliteral"></span>
<a name="l00178"></a>00178 <span class="stringliteral"> The dependencies are parsed with the apt.pkg.ParseDepends method,</span>
<a name="l00179"></a>00179 <span class="stringliteral"> and they are stored both as the format of its return value and</span>
<a name="l00180"></a>00180 <span class="stringliteral"> text.</span>
<a name="l00181"></a>00181 <span class="stringliteral"></span>
<a name="l00182"></a>00182 <span class="stringliteral"> The method returns a tuple. The first element is a list where</span>
<a name="l00183"></a>00183 <span class="stringliteral"> every item represents a binary package as a dictionary; the second</span>
<a name="l00184"></a>00184 <span class="stringliteral"> element is a dictionary which maps virtual packages to real</span>
<a name="l00185"></a>00185 <span class="stringliteral"> packages that provide it.</span>
<a name="l00186"></a>00186 <span class="stringliteral"> """</span>
<a name="l00187"></a>00187
<a name="l00188"></a>00188 packages = {}
<a name="l00189"></a>00189 provides = {}
<a name="l00190"></a>00190 package = <span class="keywordtype">None</span>
<a name="l00191"></a>00191 filename = os.path.join(basedir, <span class="stringliteral">"Packages_%s"</span> % arch)
<a name="l00192"></a>00192 self.<a class="code" href="classbritney_1_1Britney.html#678036a5200302d77249f5e702532681">__log</a>(<span class="stringliteral">"Loading binary packages from %s"</span> % filename)
<a name="l00193"></a>00193 Packages = apt_pkg.ParseTagFile(open(filename))
<a name="l00194"></a>00194 <span class="keywordflow">while</span> Packages.Step():
<a name="l00195"></a>00195 pkg = Packages.Section.get(<span class="stringliteral">'Package'</span>)
<a name="l00196"></a>00196 version = Packages.Section.get(<span class="stringliteral">'Version'</span>)
<a name="l00197"></a>00197 dpkg = {<span class="stringliteral">'rdepends'</span>: [],
<a name="l00198"></a>00198 <span class="stringliteral">'version'</span>: version,
<a name="l00199"></a>00199 <span class="stringliteral">'source'</span>: pkg,
<a name="l00200"></a>00200 <span class="stringliteral">'source-ver'</span>: version,
<a name="l00201"></a>00201 <span class="stringliteral">'pre-depends'</span>: Packages.Section.get(<span class="stringliteral">'Pre-Depends'</span>),
<a name="l00202"></a>00202 <span class="stringliteral">'depends'</span>: Packages.Section.get(<span class="stringliteral">'Depends'</span>),
<a name="l00203"></a>00203 <span class="stringliteral">'conflicts'</span>: Packages.Section.get(<span class="stringliteral">'Conflicts'</span>),
<a name="l00204"></a>00204 <span class="stringliteral">'provides'</span>: Packages.Section.get(<span class="stringliteral">'Provides'</span>),
<a name="l00205"></a>00205 <span class="stringliteral">'architecture'</span>: Packages.Section.get(<span class="stringliteral">'Architecture'</span>),
<a name="l00206"></a>00206 }
<a name="l00207"></a>00207
<a name="l00208"></a>00208 <span class="comment"># retrieve the name and the version of the source package</span>
<a name="l00209"></a>00209 source = Packages.Section.get(<span class="stringliteral">'Source'</span>)
<a name="l00210"></a>00210 <span class="keywordflow">if</span> source:
<a name="l00211"></a>00211 dpkg[<span class="stringliteral">'source'</span>] = source.split(<span class="stringliteral">" "</span>)[0]
<a name="l00212"></a>00212 <span class="keywordflow">if</span> <span class="stringliteral">"("</span> <span class="keywordflow">in</span> source:
<a name="l00213"></a>00213 dpkg[<span class="stringliteral">'source-ver'</span>] = source.split(<span class="stringliteral">"("</span>)[1].split(<span class="stringliteral">")"</span>)[0]
<a name="l00214"></a>00214
<a name="l00215"></a>00215 <span class="comment"># if the source package is available in the distribution, then register this binary package</span>
<a name="l00216"></a>00216 <span class="keywordflow">if</span> dpkg[<span class="stringliteral">'source'</span>] <span class="keywordflow">in</span> self.sources[distribution]:
<a name="l00217"></a>00217 self.sources[distribution][dpkg[<span class="stringliteral">'source'</span>]][<span class="stringliteral">'binaries'</span>].append(pkg + <span class="stringliteral">"/"</span> + arch)
<a name="l00218"></a>00218 <span class="comment"># if the source package doesn't exist, create a fake one</span>
<a name="l00219"></a>00219 <span class="keywordflow">else</span>:
<a name="l00220"></a>00220 self.sources[distribution][dpkg[<span class="stringliteral">'source'</span>]] = {<span class="stringliteral">'binaries'</span>: [pkg + <span class="stringliteral">"/"</span> + arch],
<a name="l00221"></a>00221 <span class="stringliteral">'version'</span>: dpkg[<span class="stringliteral">'source-ver'</span>], <span class="stringliteral">'maintainer'</span>: <span class="keywordtype">None</span>, <span class="stringliteral">'section'</span>: <span class="keywordtype">None</span>, <span class="stringliteral">'fake'</span>: <span class="keyword">True</span>}
<a name="l00222"></a>00222
<a name="l00223"></a>00223 <span class="comment"># register virtual packages and real packages that provide them</span>
<a name="l00224"></a>00224 <span class="keywordflow">if</span> dpkg[<span class="stringliteral">'provides'</span>]:
<a name="l00225"></a>00225 parts = map(string.strip, dpkg[<span class="stringliteral">'provides'</span>].split(<span class="stringliteral">","</span>))
<a name="l00226"></a>00226 <span class="keywordflow">for</span> p <span class="keywordflow">in</span> parts:
<a name="l00227"></a>00227 <span class="keywordflow">try</span>:
<a name="l00228"></a>00228 provides[p].append(pkg)
<a name="l00229"></a>00229 <span class="keywordflow">except</span> KeyError:
<a name="l00230"></a>00230 provides[p] = [pkg]
<a name="l00231"></a>00231 del dpkg[<span class="stringliteral">'provides'</span>]
<a name="l00232"></a>00232
<a name="l00233"></a>00233 <span class="comment"># append the resulting dictionary to the package list</span>
<a name="l00234"></a>00234 packages[pkg] = dpkg
<a name="l00235"></a>00235
<a name="l00236"></a>00236 <span class="comment"># loop again on the list of packages to register reverse dependencies</span>
<a name="l00237"></a>00237 <span class="keywordflow">for</span> pkg <span class="keywordflow">in</span> packages:
<a name="l00238"></a>00238 dependencies = []
<a name="l00239"></a>00239
<a name="l00240"></a>00240 <span class="comment"># analyze dependencies</span>
<a name="l00241"></a>00241 <span class="keywordflow">if</span> packages[pkg][<span class="stringliteral">'depends'</span>]:
<a name="l00242"></a>00242 packages[pkg][<span class="stringliteral">'depends-txt'</span>] = packages[pkg][<span class="stringliteral">'depends'</span>]
<a name="l00243"></a>00243 packages[pkg][<span class="stringliteral">'depends'</span>] = apt_pkg.ParseDepends(packages[pkg][<span class="stringliteral">'depends'</span>])
<a name="l00244"></a>00244 dependencies.extend(packages[pkg][<span class="stringliteral">'depends'</span>])
<a name="l00245"></a>00245
<a name="l00246"></a>00246 <span class="comment"># analyze pre-dependencies</span>
<a name="l00247"></a>00247 <span class="keywordflow">if</span> packages[pkg][<span class="stringliteral">'pre-depends'</span>]:
<a name="l00248"></a>00248 packages[pkg][<span class="stringliteral">'pre-depends-txt'</span>] = packages[pkg][<span class="stringliteral">'pre-depends'</span>]
<a name="l00249"></a>00249 packages[pkg][<span class="stringliteral">'pre-depends'</span>] = apt_pkg.ParseDepends(packages[pkg][<span class="stringliteral">'pre-depends'</span>])
<a name="l00250"></a>00250 dependencies.extend(packages[pkg][<span class="stringliteral">'pre-depends'</span>])
<a name="l00251"></a>00251
<a name="l00252"></a><a class="code" href="classbritney_1_1Britney.html#6c777aae69e7bec2efebaf23ddd4a86c">00252</a> <span class="comment"># register the list of the dependencies for the depending packages</span>
<a name="l00253"></a>00253 <span class="keywordflow">for</span> p <span class="keywordflow">in</span> dependencies:
<a name="l00254"></a>00254 <span class="keywordflow">for</span> a <span class="keywordflow">in</span> p:
<a name="l00255"></a>00255 <span class="keywordflow">if</span> a[0] <span class="keywordflow">not</span> <span class="keywordflow">in</span> packages: <span class="keywordflow">continue</span>
<a name="l00256"></a>00256 packages[a[0]][<span class="stringliteral">'rdepends'</span>].append((pkg, a[1], a[2]))
<a name="l00257"></a>00257
<a name="l00258"></a>00258 <span class="comment"># return a tuple with the list of real and virtual packages</span>
<a name="l00259"></a>00259 <span class="keywordflow">return</span> (packages, provides)
<a name="l00260"></a>00260
<a name="l00261"></a>00261 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#6c777aae69e7bec2efebaf23ddd4a86c">read_bugs</a>(self, basedir):
<a name="l00262"></a>00262 <span class="stringliteral">"""Read the release critial bug summary from the specified directory</span>
<a name="l00263"></a>00263 <span class="stringliteral"> </span>
<a name="l00264"></a>00264 <span class="stringliteral"> The RC bug summaries are read from the `Bugs' file within the</span>
<a name="l00265"></a>00265 <span class="stringliteral"> directory specified as `basedir' parameter. The file contains</span>
<a name="l00266"></a>00266 <span class="stringliteral"> rows with the format:</span>
<a name="l00267"></a>00267 <span class="stringliteral"></span>
<a name="l00268"></a>00268 <span class="stringliteral"> &lt;package-name&gt; &lt;count-of-rc-bugs&gt;</span>
<a name="l00269"></a>00269 <span class="stringliteral"></span>
<a name="l00270"></a>00270 <span class="stringliteral"> The method returns a dictionary where the key is the binary package</span>
<a name="l00271"></a>00271 <span class="stringliteral"> name and the value is the number of open RC bugs for it.</span>
<a name="l00272"></a>00272 <span class="stringliteral"> """</span>
<a name="l00273"></a>00273 bugs = {}
<a name="l00274"></a>00274 filename = os.path.join(basedir, <span class="stringliteral">"Bugs"</span>)
<a name="l00275"></a>00275 self.<a class="code" href="classbritney_1_1Britney.html#678036a5200302d77249f5e702532681">__log</a>(<span class="stringliteral">"Loading RC bugs count from %s"</span> % filename)
<a name="l00276"></a><a class="code" href="classbritney_1_1Britney.html#0affb1945986a52c61a4492c9732968e">00276</a> <span class="keywordflow">for</span> line <span class="keywordflow">in</span> open(filename):
<a name="l00277"></a>00277 l = line.strip().split()
<a name="l00278"></a>00278 <span class="keywordflow">if</span> len(l) != 2: <span class="keywordflow">continue</span>
<a name="l00279"></a>00279 <span class="keywordflow">try</span>:
<a name="l00280"></a>00280 bugs[l[0]] = int(l[1])
<a name="l00281"></a>00281 <span class="keywordflow">except</span> ValueError:
<a name="l00282"></a>00282 self.<a class="code" href="classbritney_1_1Britney.html#678036a5200302d77249f5e702532681">__log</a>(<span class="stringliteral">"Bugs, unable to parse \"%s\""</span> % line, type=<span class="stringliteral">"E"</span>)
<a name="l00283"></a>00283 <span class="keywordflow">return</span> bugs
<a name="l00284"></a>00284
<a name="l00285"></a>00285 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#0affb1945986a52c61a4492c9732968e">__maxver</a>(self, pkg, dist):
<a name="l00286"></a>00286 <span class="stringliteral">"""Return the maximum version for a given package name</span>
<a name="l00287"></a>00287 <span class="stringliteral"> </span>
<a name="l00288"></a>00288 <span class="stringliteral"> This method returns None if the specified source package</span>
<a name="l00289"></a>00289 <span class="stringliteral"> is not available in the `dist' distribution. If the package</span>
<a name="l00290"></a>00290 <span class="stringliteral"> exists, then it returns the maximum version between the</span>
<a name="l00291"></a>00291 <span class="stringliteral"> source package and its binary packages.</span>
<a name="l00292"></a>00292 <span class="stringliteral"> """</span>
<a name="l00293"></a>00293 maxver = <span class="keywordtype">None</span>
<a name="l00294"></a><a class="code" href="classbritney_1_1Britney.html#5a6af4a100cfd54e872a27fa7f48ac3c">00294</a> <span class="keywordflow">if</span> self.sources[dist].has_key(pkg):
<a name="l00295"></a>00295 maxver = self.sources[dist][pkg][<span class="stringliteral">'version'</span>]
<a name="l00296"></a>00296 <span class="keywordflow">for</span> arch <span class="keywordflow">in</span> self.options.architectures:
<a name="l00297"></a>00297 <span class="keywordflow">if</span> <span class="keywordflow">not</span> self.binaries[dist][arch][0].has_key(pkg): <span class="keywordflow">continue</span>
<a name="l00298"></a>00298 pkgv = self.binaries[dist][arch][0][pkg][<span class="stringliteral">'version'</span>]
<a name="l00299"></a>00299 <span class="keywordflow">if</span> maxver == <span class="keywordtype">None</span> <span class="keywordflow">or</span> apt_pkg.VersionCompare(pkgv, maxver) &gt; 0:
<a name="l00300"></a>00300 maxver = pkgv
<a name="l00301"></a>00301 <span class="keywordflow">return</span> maxver
<a name="l00302"></a>00302
<a name="l00303"></a>00303 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#5a6af4a100cfd54e872a27fa7f48ac3c">normalize_bugs</a>(self):
<a name="l00304"></a>00304 <span class="stringliteral">"""Normalize the release critical bug summaries for testing and unstable</span>
<a name="l00305"></a>00305 <span class="stringliteral"> </span>
<a name="l00306"></a>00306 <span class="stringliteral"> The method doesn't return any value: it directly modifies the</span>
<a name="l00307"></a>00307 <span class="stringliteral"> object attribute `bugs'.</span>
<a name="l00308"></a>00308 <span class="stringliteral"> """</span>
<a name="l00309"></a>00309 <span class="comment"># loop on all the package names from testing and unstable bug summaries</span>
<a name="l00310"></a>00310 <span class="keywordflow">for</span> pkg <span class="keywordflow">in</span> set(self.bugs[<span class="stringliteral">'testing'</span>].keys() + self.bugs[<span class="stringliteral">'unstable'</span>].keys()):
<a name="l00311"></a>00311
<a name="l00312"></a>00312 <span class="comment"># make sure that the key is present in both dictionaries</span>
<a name="l00313"></a>00313 <span class="keywordflow">if</span> <span class="keywordflow">not</span> self.bugs[<span class="stringliteral">'testing'</span>].has_key(pkg):
<a name="l00314"></a>00314 self.bugs[<span class="stringliteral">'testing'</span>][pkg] = 0
<a name="l00315"></a>00315 <span class="keywordflow">elif</span> <span class="keywordflow">not</span> self.bugs[<span class="stringliteral">'unstable'</span>].has_key(pkg):
<a name="l00316"></a>00316 self.bugs[<span class="stringliteral">'unstable'</span>][pkg] = 0
<a name="l00317"></a>00317
<a name="l00318"></a>00318 <span class="comment"># retrieve the maximum version of the package in testing:</span>
<a name="l00319"></a>00319 maxvert = self.<a class="code" href="classbritney_1_1Britney.html#0affb1945986a52c61a4492c9732968e">__maxver</a>(pkg, <span class="stringliteral">'testing'</span>)
<a name="l00320"></a>00320
<a name="l00321"></a>00321 <span class="comment"># if the package is not available in testing or it has the</span>
<a name="l00322"></a>00322 <span class="comment"># same RC bug count, then do nothing</span>
<a name="l00323"></a>00323 <span class="keywordflow">if</span> maxvert == <span class="keywordtype">None</span> <span class="keywordflow">or</span> \
<a name="l00324"></a>00324 self.bugs[<span class="stringliteral">'testing'</span>][pkg] == self.bugs[<span class="stringliteral">'unstable'</span>][pkg]:
<a name="l00325"></a>00325 <span class="keywordflow">continue</span>
<a name="l00326"></a>00326
<a name="l00327"></a>00327 <span class="comment"># retrieve the maximum version of the package in testing:</span>
<a name="l00328"></a>00328 maxveru = self.<a class="code" href="classbritney_1_1Britney.html#0affb1945986a52c61a4492c9732968e">__maxver</a>(pkg, <span class="stringliteral">'unstable'</span>)
<a name="l00329"></a><a class="code" href="classbritney_1_1Britney.html#085af5ac906813ea40fc2e623748f517">00329</a>
<a name="l00330"></a>00330 <span class="comment"># if the package is not available in unstable, then do nothing</span>
<a name="l00331"></a>00331 <span class="keywordflow">if</span> maxveru == <span class="keywordtype">None</span>:
<a name="l00332"></a>00332 <span class="keywordflow">continue</span>
<a name="l00333"></a>00333 <span class="comment"># else if the testing package is more recent, then use the</span>
<a name="l00334"></a>00334 <span class="comment"># unstable RC bug count for testing, too</span>
<a name="l00335"></a>00335 <span class="keywordflow">elif</span> apt_pkg.VersionCompare(maxvert, maxveru) &gt;= 0:
<a name="l00336"></a>00336 self.bugs[<span class="stringliteral">'testing'</span>][pkg] = self.bugs[<span class="stringliteral">'unstable'</span>][pkg]
<a name="l00337"></a>00337
<a name="l00338"></a>00338 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#085af5ac906813ea40fc2e623748f517">read_dates</a>(self, basedir):
<a name="l00339"></a>00339 <span class="stringliteral">"""Read the upload date for the packages from the specified directory</span>
<a name="l00340"></a>00340 <span class="stringliteral"> </span>
<a name="l00341"></a>00341 <span class="stringliteral"> The upload dates are read from the `Date' file within the directory</span>
<a name="l00342"></a>00342 <span class="stringliteral"> specified as `basedir' parameter. The file contains rows with the</span>
<a name="l00343"></a>00343 <span class="stringliteral"> format:</span>
<a name="l00344"></a>00344 <span class="stringliteral"></span>
<a name="l00345"></a>00345 <span class="stringliteral"> &lt;package-name&gt; &lt;version&gt; &lt;date-of-upload&gt;</span>
<a name="l00346"></a>00346 <span class="stringliteral"></span>
<a name="l00347"></a>00347 <span class="stringliteral"> The dates are expressed as days starting from the 1970-01-01.</span>
<a name="l00348"></a>00348 <span class="stringliteral"></span>
<a name="l00349"></a>00349 <span class="stringliteral"> The method returns a dictionary where the key is the binary package</span>
<a name="l00350"></a>00350 <span class="stringliteral"> name and the value is tuple with two items, the version and the date.</span>
<a name="l00351"></a>00351 <span class="stringliteral"> """</span>
<a name="l00352"></a>00352 dates = {}
<a name="l00353"></a>00353 filename = os.path.join(basedir, <span class="stringliteral">"Dates"</span>)
<a name="l00354"></a>00354 self.<a class="code" href="classbritney_1_1Britney.html#678036a5200302d77249f5e702532681">__log</a>(<span class="stringliteral">"Loading upload data from %s"</span> % filename)
<a name="l00355"></a><a class="code" href="classbritney_1_1Britney.html#09fc27899506b4830b1961f125a7b6a4">00355</a> <span class="keywordflow">for</span> line <span class="keywordflow">in</span> open(filename):
<a name="l00356"></a>00356 l = line.strip().split()
<a name="l00357"></a>00357 <span class="keywordflow">if</span> len(l) != 3: <span class="keywordflow">continue</span>
<a name="l00358"></a>00358 <span class="keywordflow">try</span>:
<a name="l00359"></a>00359 dates[l[0]] = (l[1], int(l[2]))
<a name="l00360"></a>00360 <span class="keywordflow">except</span> ValueError:
<a name="l00361"></a>00361 self.<a class="code" href="classbritney_1_1Britney.html#678036a5200302d77249f5e702532681">__log</a>(<span class="stringliteral">"Dates, unable to parse \"%s\""</span> % line, type=<span class="stringliteral">"E"</span>)
<a name="l00362"></a>00362 <span class="keywordflow">return</span> dates
<a name="l00363"></a>00363
<a name="l00364"></a>00364 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#09fc27899506b4830b1961f125a7b6a4">read_urgencies</a>(self, basedir):
<a name="l00365"></a>00365 <span class="stringliteral">"""Read the upload urgency of the packages from the specified directory</span>
<a name="l00366"></a>00366 <span class="stringliteral"> </span>
<a name="l00367"></a>00367 <span class="stringliteral"> The upload urgencies are read from the `Urgency' file within the</span>
<a name="l00368"></a>00368 <span class="stringliteral"> directory specified as `basedir' parameter. The file contains rows</span>
<a name="l00369"></a>00369 <span class="stringliteral"> with the format:</span>
<a name="l00370"></a>00370 <span class="stringliteral"></span>
<a name="l00371"></a>00371 <span class="stringliteral"> &lt;package-name&gt; &lt;version&gt; &lt;urgency&gt;</span>
<a name="l00372"></a>00372 <span class="stringliteral"></span>
<a name="l00373"></a>00373 <span class="stringliteral"> The method returns a dictionary where the key is the binary package</span>
<a name="l00374"></a>00374 <span class="stringliteral"> name and the value is the greatest urgency from the versions of the</span>
<a name="l00375"></a>00375 <span class="stringliteral"> package that are higher then the testing one.</span>
<a name="l00376"></a>00376 <span class="stringliteral"> """</span>
<a name="l00377"></a>00377
<a name="l00378"></a>00378 urgencies = {}
<a name="l00379"></a>00379 filename = os.path.join(basedir, <span class="stringliteral">"Urgency"</span>)
<a name="l00380"></a>00380 self.<a class="code" href="classbritney_1_1Britney.html#678036a5200302d77249f5e702532681">__log</a>(<span class="stringliteral">"Loading upload urgencies from %s"</span> % filename)
<a name="l00381"></a>00381 <span class="keywordflow">for</span> line <span class="keywordflow">in</span> open(filename):
<a name="l00382"></a>00382 l = line.strip().split()
<a name="l00383"></a>00383 <span class="keywordflow">if</span> len(l) != 3: <span class="keywordflow">continue</span>
<a name="l00384"></a>00384
<a name="l00385"></a>00385 <span class="comment"># read the minimum days associated to the urgencies</span>
<a name="l00386"></a>00386 urgency_old = urgencies.get(l[0], self.options.default_urgency)
<a name="l00387"></a>00387 mindays_old = self.MINDAYS.get(urgency_old, self.MINDAYS[self.options.default_urgency])
<a name="l00388"></a>00388 mindays_new = self.MINDAYS.get(l[2], self.MINDAYS[self.options.default_urgency])
<a name="l00389"></a>00389
<a name="l00390"></a>00390 <span class="comment"># if the new urgency is lower (so the min days are higher), do nothing</span>
<a name="l00391"></a>00391 <span class="keywordflow">if</span> mindays_old &lt;= mindays_new:
<a name="l00392"></a>00392 <span class="keywordflow">continue</span>
<a name="l00393"></a>00393
<a name="l00394"></a>00394 <span class="comment"># if the package exists in testing and it is more recent, do nothing</span>
<a name="l00395"></a>00395 tsrcv = self.sources[<span class="stringliteral">'testing'</span>].get(l[0], <span class="keywordtype">None</span>)
<a name="l00396"></a>00396 <span class="keywordflow">if</span> tsrcv <span class="keywordflow">and</span> apt_pkg.VersionCompare(tsrcv[<span class="stringliteral">'version'</span>], l[1]) &gt;= 0:
<a name="l00397"></a>00397 <span class="keywordflow">continue</span>
<a name="l00398"></a>00398
<a name="l00399"></a>00399 <span class="comment"># if the package doesn't exist in unstable or it is older, do nothing</span>
<a name="l00400"></a><a class="code" href="classbritney_1_1Britney.html#39248f0cfea1c8798b2ca5a97d37eaf8">00400</a> usrcv = self.sources[<span class="stringliteral">'unstable'</span>].get(l[0], <span class="keywordtype">None</span>)
<a name="l00401"></a>00401 <span class="keywordflow">if</span> <span class="keywordflow">not</span> usrcv <span class="keywordflow">or</span> apt_pkg.VersionCompare(usrcv[<span class="stringliteral">'version'</span>], l[1]) &lt; 0:
<a name="l00402"></a>00402 <span class="keywordflow">continue</span>
<a name="l00403"></a>00403
<a name="l00404"></a>00404 <span class="comment"># update the urgency for the package</span>
<a name="l00405"></a>00405 urgencies[l[0]] = l[2]
<a name="l00406"></a>00406
<a name="l00407"></a>00407 <span class="keywordflow">return</span> urgencies
<a name="l00408"></a>00408
<a name="l00409"></a>00409 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#39248f0cfea1c8798b2ca5a97d37eaf8">read_approvals</a>(self, basedir):
<a name="l00410"></a>00410 <span class="stringliteral">"""Read the approval commands from the specified directory</span>
<a name="l00411"></a>00411 <span class="stringliteral"> </span>
<a name="l00412"></a>00412 <span class="stringliteral"> The approval commands are read from the files contained by the </span>
<a name="l00413"></a>00413 <span class="stringliteral"> `Approved' directory within the directory specified as `basedir'</span>
<a name="l00414"></a>00414 <span class="stringliteral"> parameter. The name of the files has to be the same of the</span>
<a name="l00415"></a>00415 <span class="stringliteral"> authorized users for the approvals.</span>
<a name="l00416"></a>00416 <span class="stringliteral"> </span>
<a name="l00417"></a>00417 <span class="stringliteral"> The file contains rows with the format:</span>
<a name="l00418"></a>00418 <span class="stringliteral"></span>
<a name="l00419"></a>00419 <span class="stringliteral"> &lt;package-name&gt; &lt;version&gt;</span>
<a name="l00420"></a>00420 <span class="stringliteral"></span>
<a name="l00421"></a>00421 <span class="stringliteral"> The method returns a dictionary where the key is the binary package</span>
<a name="l00422"></a>00422 <span class="stringliteral"> name followed by an underscore and the version number, and the value</span>
<a name="l00423"></a>00423 <span class="stringliteral"> is the user who submitted the command.</span>
<a name="l00424"></a>00424 <span class="stringliteral"> """</span>
<a name="l00425"></a>00425 approvals = {}
<a name="l00426"></a><a class="code" href="classbritney_1_1Britney.html#46d535f617fcf1faaaf5d841ea23c184">00426</a> <span class="keywordflow">for</span> approver <span class="keywordflow">in</span> self.options.approvers.split():
<a name="l00427"></a>00427 filename = os.path.join(basedir, <span class="stringliteral">"Approved"</span>, approver)
<a name="l00428"></a>00428 self.<a class="code" href="classbritney_1_1Britney.html#678036a5200302d77249f5e702532681">__log</a>(<span class="stringliteral">"Loading approvals list from %s"</span> % filename)
<a name="l00429"></a>00429 <span class="keywordflow">for</span> line <span class="keywordflow">in</span> open(filename):
<a name="l00430"></a>00430 l = line.strip().split()
<a name="l00431"></a>00431 <span class="keywordflow">if</span> len(l) != 2: <span class="keywordflow">continue</span>
<a name="l00432"></a>00432 approvals[<span class="stringliteral">"%s_%s"</span> % (l[0], l[1])] = approver
<a name="l00433"></a>00433 <span class="keywordflow">return</span> approvals
<a name="l00434"></a>00434
<a name="l00435"></a>00435 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#46d535f617fcf1faaaf5d841ea23c184">read_hints</a>(self, basedir):
<a name="l00436"></a>00436 <span class="stringliteral">"""Read the hint commands from the specified directory</span>
<a name="l00437"></a>00437 <span class="stringliteral"> </span>
<a name="l00438"></a>00438 <span class="stringliteral"> The hint commands are read from the files contained by the `Hints'</span>
<a name="l00439"></a>00439 <span class="stringliteral"> directory within the directory specified as `basedir' parameter. </span>
<a name="l00440"></a>00440 <span class="stringliteral"> The name of the files has to be the same of the authorized users</span>
<a name="l00441"></a>00441 <span class="stringliteral"> for the hints.</span>
<a name="l00442"></a>00442 <span class="stringliteral"> </span>
<a name="l00443"></a>00443 <span class="stringliteral"> The file contains rows with the format:</span>
<a name="l00444"></a>00444 <span class="stringliteral"></span>
<a name="l00445"></a>00445 <span class="stringliteral"> &lt;command&gt; &lt;package-name&gt;[/&lt;version&gt;]</span>
<a name="l00446"></a>00446 <span class="stringliteral"></span>
<a name="l00447"></a>00447 <span class="stringliteral"> The method returns a dictionary where the key is the command, and</span>
<a name="l00448"></a>00448 <span class="stringliteral"> the value is the list of affected packages.</span>
<a name="l00449"></a>00449 <span class="stringliteral"> """</span>
<a name="l00450"></a>00450 hints = dict([(k,[]) <span class="keywordflow">for</span> k <span class="keywordflow">in</span> self.<a class="code" href="classbritney_1_1Britney.html#a088d6fd96963f87f88c9c40cda10bfa">HINTS_ALL</a>])
<a name="l00451"></a>00451
<a name="l00452"></a>00452 <span class="keywordflow">for</span> who <span class="keywordflow">in</span> self.HINTS.keys():
<a name="l00453"></a>00453 filename = os.path.join(basedir, <span class="stringliteral">"Hints"</span>, who)
<a name="l00454"></a>00454 self.<a class="code" href="classbritney_1_1Britney.html#678036a5200302d77249f5e702532681">__log</a>(<span class="stringliteral">"Loading hints list from %s"</span> % filename)
<a name="l00455"></a>00455 <span class="keywordflow">for</span> line <span class="keywordflow">in</span> open(filename):
<a name="l00456"></a>00456 line = line.strip()
<a name="l00457"></a>00457 <span class="keywordflow">if</span> line == <span class="stringliteral">""</span>: <span class="keywordflow">continue</span>
<a name="l00458"></a>00458 l = line.split()
<a name="l00459"></a>00459 <span class="keywordflow">if</span> l[0] == <span class="stringliteral">'finished'</span>:
<a name="l00460"></a>00460 <span class="keywordflow">break</span>
<a name="l00461"></a>00461 <span class="keywordflow">elif</span> l[0] <span class="keywordflow">not</span> <span class="keywordflow">in</span> self.HINTS[who]:
<a name="l00462"></a>00462 <span class="keywordflow">continue</span>
<a name="l00463"></a>00463 <span class="keywordflow">elif</span> l[0] <span class="keywordflow">in</span> [<span class="stringliteral">"easy"</span>, <span class="stringliteral">"hint"</span>, <span class="stringliteral">"force-hint"</span>]:
<a name="l00464"></a>00464 hints[l[0]].append((who, [k.split(<span class="stringliteral">"/"</span>) <span class="keywordflow">for</span> k <span class="keywordflow">in</span> l <span class="keywordflow">if</span> <span class="stringliteral">"/"</span> <span class="keywordflow">in</span> k]))
<a name="l00465"></a>00465 <span class="keywordflow">elif</span> l[0] <span class="keywordflow">in</span> [<span class="stringliteral">"block-all"</span>]:
<a name="l00466"></a>00466 hints[l[0]].extend([(y, who) <span class="keywordflow">for</span> y <span class="keywordflow">in</span> l[1:]])
<a name="l00467"></a>00467 <span class="keywordflow">elif</span> l[0] <span class="keywordflow">in</span> [<span class="stringliteral">"block"</span>]:
<a name="l00468"></a>00468 hints[l[0]].extend([(y, who) <span class="keywordflow">for</span> y <span class="keywordflow">in</span> l[1:]])
<a name="l00469"></a>00469 <span class="keywordflow">elif</span> l[0] <span class="keywordflow">in</span> [<span class="stringliteral">"remove"</span>, <span class="stringliteral">"approve"</span>, <span class="stringliteral">"unblock"</span>, <span class="stringliteral">"force"</span>, <span class="stringliteral">"urgent"</span>]:
<a name="l00470"></a>00470 hints[l[0]].extend([(k.split(<span class="stringliteral">"/"</span>)[0], (k.split(<span class="stringliteral">"/"</span>)[1],who) ) <span class="keywordflow">for</span> k <span class="keywordflow">in</span> l <span class="keywordflow">if</span> <span class="stringliteral">"/"</span> <span class="keywordflow">in</span> k])
<a name="l00471"></a>00471
<a name="l00472"></a>00472 <span class="keywordflow">for</span> x <span class="keywordflow">in</span> [<span class="stringliteral">"block"</span>, <span class="stringliteral">"block-all"</span>, <span class="stringliteral">"unblock"</span>, <span class="stringliteral">"force"</span>, <span class="stringliteral">"urgent"</span>, <span class="stringliteral">"remove"</span>]:
<a name="l00473"></a>00473 z = {}
<a name="l00474"></a>00474 <span class="keywordflow">for</span> a, b <span class="keywordflow">in</span> hints[x]:
<a name="l00475"></a>00475 <span class="keywordflow">if</span> z.has_key(a):
<a name="l00476"></a><a class="code" href="classbritney_1_1Britney.html#85d2e45e8431779b62f398c34972ddf1">00476</a> self.<a class="code" href="classbritney_1_1Britney.html#678036a5200302d77249f5e702532681">__log</a>(<span class="stringliteral">"Overriding %s[%s] = %s with %s"</span> % (x, a, z[a], b), type=<span class="stringliteral">"W"</span>)
<a name="l00477"></a>00477 z[a] = b
<a name="l00478"></a>00478 hints[x] = z
<a name="l00479"></a>00479
<a name="l00480"></a>00480 <span class="keywordflow">return</span> hints
<a name="l00481"></a>00481
<a name="l00482"></a>00482 <span class="comment"># Utility methods for package analisys</span>
<a name="l00483"></a>00483 <span class="comment"># ------------------------------------</span>
<a name="l00484"></a>00484
<a name="l00485"></a>00485 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#85d2e45e8431779b62f398c34972ddf1">same_source</a>(self, sv1, sv2):
<a name="l00486"></a>00486 <span class="stringliteral">"""Check if two version numbers are built from the same source</span>
<a name="l00487"></a>00487 <span class="stringliteral"></span>
<a name="l00488"></a>00488 <span class="stringliteral"> This method returns a boolean value which is true if the two</span>
<a name="l00489"></a>00489 <span class="stringliteral"> version numbers specified as parameters are built from the same</span>
<a name="l00490"></a>00490 <span class="stringliteral"> source. The main use of this code is to detect binary-NMU.</span>
<a name="l00491"></a>00491 <span class="stringliteral"> """</span>
<a name="l00492"></a>00492 <span class="keywordflow">if</span> sv1 == sv2:
<a name="l00493"></a>00493 <span class="keywordflow">return</span> 1
<a name="l00494"></a>00494
<a name="l00495"></a>00495 m = re.match(<span class="stringliteral">r'^(.*)\+b\d+$'</span>, sv1)
<a name="l00496"></a>00496 <span class="keywordflow">if</span> m: sv1 = m.group(1)
<a name="l00497"></a>00497 m = re.match(<span class="stringliteral">r'^(.*)\+b\d+$'</span>, sv2)
<a name="l00498"></a>00498 <span class="keywordflow">if</span> m: sv2 = m.group(1)
<a name="l00499"></a>00499
<a name="l00500"></a>00500 <span class="keywordflow">if</span> sv1 == sv2:
<a name="l00501"></a>00501 <span class="keywordflow">return</span> 1
<a name="l00502"></a>00502
<a name="l00503"></a>00503 <span class="keywordflow">if</span> re.search(<span class="stringliteral">"-"</span>, sv1) <span class="keywordflow">or</span> re.search(<span class="stringliteral">"-"</span>, sv2):
<a name="l00504"></a>00504 m = re.match(<span class="stringliteral">r'^(.*-[^.]+)\.0\.\d+$'</span>, sv1)
<a name="l00505"></a>00505 <span class="keywordflow">if</span> m: sv1 = m.group(1)
<a name="l00506"></a>00506 m = re.match(<span class="stringliteral">r'^(.*-[^.]+\.[^.]+)\.\d+$'</span>, sv1)
<a name="l00507"></a>00507 <span class="keywordflow">if</span> m: sv1 = m.group(1)
<a name="l00508"></a>00508
<a name="l00509"></a>00509 m = re.match(<span class="stringliteral">r'^(.*-[^.]+)\.0\.\d+$'</span>, sv2)
<a name="l00510"></a>00510 <span class="keywordflow">if</span> m: sv2 = m.group(1)
<a name="l00511"></a>00511 m = re.match(<span class="stringliteral">r'^(.*-[^.]+\.[^.]+)\.\d+$'</span>, sv2)
<a name="l00512"></a>00512 <span class="keywordflow">if</span> m: sv2 = m.group(1)
<a name="l00513"></a>00513
<a name="l00514"></a>00514 <span class="keywordflow">return</span> (sv1 == sv2)
<a name="l00515"></a><a class="code" href="classbritney_1_1Britney.html#5461f49e3e75a251ebedfd37d2a5ff0c">00515</a> <span class="keywordflow">else</span>:
<a name="l00516"></a>00516 m = re.match(<span class="stringliteral">r'^([^-]+)\.0\.\d+$'</span>, sv1)
<a name="l00517"></a>00517 <span class="keywordflow">if</span> m <span class="keywordflow">and</span> sv2 == m.group(1): <span class="keywordflow">return</span> 1
<a name="l00518"></a>00518
<a name="l00519"></a>00519 m = re.match(<span class="stringliteral">r'^([^-]+)\.0\.\d+$'</span>, sv2)
<a name="l00520"></a>00520 <span class="keywordflow">if</span> m <span class="keywordflow">and</span> sv1 == m.group(1): <span class="keywordflow">return</span> 1
<a name="l00521"></a>00521
<a name="l00522"></a>00522 <span class="keywordflow">return</span> 0
<a name="l00523"></a>00523
<a name="l00524"></a>00524 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#5461f49e3e75a251ebedfd37d2a5ff0c">get_dependency_solvers</a>(self, block, arch, distribution):
<a name="l00525"></a>00525 <span class="stringliteral">"""Find the packages which satisfy a dependency block</span>
<a name="l00526"></a>00526 <span class="stringliteral"></span>
<a name="l00527"></a>00527 <span class="stringliteral"> This method returns the list of packages which satisfy a dependency</span>
<a name="l00528"></a>00528 <span class="stringliteral"> block (as returned by apt_pkg.ParseDepends) for the given architecture</span>
<a name="l00529"></a>00529 <span class="stringliteral"> and distribution.</span>
<a name="l00530"></a>00530 <span class="stringliteral"></span>
<a name="l00531"></a>00531 <span class="stringliteral"> It returns a tuple with two items: the first is a boolean which is</span>
<a name="l00532"></a>00532 <span class="stringliteral"> True if the dependency is satisfied, the second is the list of the</span>
<a name="l00533"></a>00533 <span class="stringliteral"> solving packages.</span>
<a name="l00534"></a>00534 <span class="stringliteral"> """</span>
<a name="l00535"></a>00535
<a name="l00536"></a>00536 packages = []
<a name="l00537"></a>00537
<a name="l00538"></a>00538 <span class="comment"># for every package, version and operation in the block</span>
<a name="l00539"></a>00539 <span class="keywordflow">for</span> name, version, op <span class="keywordflow">in</span> block:
<a name="l00540"></a>00540 <span class="comment"># look for the package in unstable</span>
<a name="l00541"></a>00541 <span class="keywordflow">if</span> name <span class="keywordflow">in</span> self.binaries[distribution][arch][0]:
<a name="l00542"></a>00542 package = self.binaries[distribution][arch][0][name]
<a name="l00543"></a>00543 <span class="comment"># check the versioned dependency (if present)</span>
<a name="l00544"></a>00544 <span class="keywordflow">if</span> op == <span class="stringliteral">''</span> <span class="keywordflow">and</span> version == <span class="stringliteral">''</span> <span class="keywordflow">or</span> apt_pkg.CheckDep(package[<span class="stringliteral">'version'</span>], op, version):
<a name="l00545"></a>00545 packages.append(name)
<a name="l00546"></a>00546
<a name="l00547"></a>00547 <span class="comment"># look for the package in the virtual packages list</span>
<a name="l00548"></a>00548 <span class="keywordflow">if</span> name <span class="keywordflow">in</span> self.binaries[distribution][arch][1]:
<a name="l00549"></a>00549 <span class="comment"># loop on the list of packages which provides it</span>
<a name="l00550"></a>00550 <span class="keywordflow">for</span> prov <span class="keywordflow">in</span> self.binaries[distribution][arch][1][name]:
<a name="l00551"></a>00551 package = self.binaries[distribution][arch][0][prov]
<a name="l00552"></a>00552 <span class="comment"># check the versioned dependency (if present)</span>
<a name="l00553"></a><a class="code" href="classbritney_1_1Britney.html#f51c60a69f3a9dc2bc5afdb2ffaf3990">00553</a> <span class="comment"># TODO: this is forbidden by the debian policy, which says that versioned</span>
<a name="l00554"></a>00554 <span class="comment"># dependencies on virtual packages are never satisfied. The old britney</span>
<a name="l00555"></a>00555 <span class="comment"># does it and we have to go with it, but at least a warning should be raised.</span>
<a name="l00556"></a>00556 <span class="keywordflow">if</span> op == <span class="stringliteral">''</span> <span class="keywordflow">and</span> version == <span class="stringliteral">''</span> <span class="keywordflow">or</span> apt_pkg.CheckDep(package[<span class="stringliteral">'version'</span>], op, version):
<a name="l00557"></a>00557 packages.append(prov)
<a name="l00558"></a>00558 <span class="keywordflow">break</span>
<a name="l00559"></a>00559
<a name="l00560"></a>00560 <span class="keywordflow">return</span> (len(packages) &gt; 0, packages)
<a name="l00561"></a>00561
<a name="l00562"></a>00562 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#f51c60a69f3a9dc2bc5afdb2ffaf3990">excuse_unsat_deps</a>(self, pkg, src, arch, suite, excuse):
<a name="l00563"></a>00563 <span class="stringliteral">"""Find unsatisfied dependencies for a binary package</span>
<a name="l00564"></a>00564 <span class="stringliteral"></span>
<a name="l00565"></a>00565 <span class="stringliteral"> This method analyzes the dependencies of the binary package specified</span>
<a name="l00566"></a>00566 <span class="stringliteral"> by the parameter `pkg', built from the source package `src', for the</span>
<a name="l00567"></a>00567 <span class="stringliteral"> architecture `arch' within the suite `suite'. If the dependency can't</span>
<a name="l00568"></a>00568 <span class="stringliteral"> be satisfied in testing and/or unstable, it updates the excuse passed</span>
<a name="l00569"></a>00569 <span class="stringliteral"> as parameter.</span>
<a name="l00570"></a>00570 <span class="stringliteral"></span>
<a name="l00571"></a>00571 <span class="stringliteral"> The dependency fields checked are Pre-Depends and Depends.</span>
<a name="l00572"></a>00572 <span class="stringliteral"> """</span>
<a name="l00573"></a>00573 <span class="comment"># retrieve the binary package from the specified suite and arch</span>
<a name="l00574"></a>00574 binary_u = self.binaries[suite][arch][0][pkg]
<a name="l00575"></a>00575
<a name="l00576"></a>00576 <span class="comment"># analyze the dependency fields (if present)</span>
<a name="l00577"></a>00577 <span class="keywordflow">for</span> type <span class="keywordflow">in</span> (<span class="stringliteral">'Pre-Depends'</span>, <span class="stringliteral">'Depends'</span>):
<a name="l00578"></a>00578 type_key = type.lower()
<a name="l00579"></a>00579 <span class="keywordflow">if</span> <span class="keywordflow">not</span> binary_u[type_key]:
<a name="l00580"></a>00580 <span class="keywordflow">continue</span>
<a name="l00581"></a>00581
<a name="l00582"></a>00582 <span class="comment"># this list will contain the packages that satisfy the dependency</span>
<a name="l00583"></a>00583 packages = []
<a name="l00584"></a>00584
<a name="l00585"></a>00585 <span class="comment"># for every block of dependency (which is formed as conjunction of disconjunction)</span>
<a name="l00586"></a>00586 <span class="keywordflow">for</span> block, block_txt <span class="keywordflow">in</span> map(<span class="keywordtype">None</span>, binary_u[type_key], binary_u[type_key + <span class="stringliteral">'-txt'</span>].split(<span class="stringliteral">','</span>)):
<a name="l00587"></a>00587 <span class="comment"># if the block is satisfied in testing, then skip the block</span>
<a name="l00588"></a>00588 solved, packages = self.<a class="code" href="classbritney_1_1Britney.html#5461f49e3e75a251ebedfd37d2a5ff0c">get_dependency_solvers</a>(block, arch, <span class="stringliteral">'testing'</span>)
<a name="l00589"></a>00589 <span class="keywordflow">if</span> solved: <span class="keywordflow">continue</span>
<a name="l00590"></a>00590
<a name="l00591"></a>00591 <span class="comment"># check if the block can be satisfied in unstable, and list the solving packages</span>
<a name="l00592"></a>00592 solved, packages = self.<a class="code" href="classbritney_1_1Britney.html#5461f49e3e75a251ebedfd37d2a5ff0c">get_dependency_solvers</a>(block, arch, suite)
<a name="l00593"></a>00593 packages = [self.binaries[suite][arch][0][p][<span class="stringliteral">'source'</span>] <span class="keywordflow">for</span> p <span class="keywordflow">in</span> packages]
<a name="l00594"></a>00594
<a name="l00595"></a>00595 <span class="comment"># if the dependency can be satisfied by the same source package, skip the block:</span>
<a name="l00596"></a>00596 <span class="comment"># obviously both binary packages will enter testing togheter</span>
<a name="l00597"></a>00597 <span class="keywordflow">if</span> src <span class="keywordflow">in</span> packages: <span class="keywordflow">continue</span>
<a name="l00598"></a>00598
<a name="l00599"></a>00599 <span class="comment"># if no package can satisfy the dependency, add this information to the excuse</span>
<a name="l00600"></a>00600 <span class="keywordflow">if</span> len(packages) == 0:
<a name="l00601"></a>00601 excuse.addhtml(<span class="stringliteral">"%s/%s unsatisfiable %s: %s"</span> % (pkg, arch, type, block_txt.strip()))
<a name="l00602"></a>00602
<a name="l00603"></a>00603 <span class="comment"># for the solving packages, update the excuse to add the dependencies</span>
<a name="l00604"></a><a class="code" href="classbritney_1_1Britney.html#f8a6c9adbdec7a5a982dd2b74febcc08">00604</a> <span class="keywordflow">for</span> p <span class="keywordflow">in</span> packages:
<a name="l00605"></a>00605 <span class="keywordflow">if</span> arch <span class="keywordflow">not</span> <span class="keywordflow">in</span> self.options.break_arches.split():
<a name="l00606"></a>00606 excuse.add_dep(p)
<a name="l00607"></a>00607 <span class="keywordflow">else</span>:
<a name="l00608"></a>00608 excuse.add_break_dep(p, arch)
<a name="l00609"></a>00609
<a name="l00610"></a>00610 <span class="comment"># Package analisys methods</span>
<a name="l00611"></a>00611 <span class="comment"># ------------------------</span>
<a name="l00612"></a>00612
<a name="l00613"></a>00613 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#f8a6c9adbdec7a5a982dd2b74febcc08">should_remove_source</a>(self, pkg):
<a name="l00614"></a>00614 <span class="stringliteral">"""Check if a source package should be removed from testing</span>
<a name="l00615"></a>00615 <span class="stringliteral"> </span>
<a name="l00616"></a>00616 <span class="stringliteral"> This method checks if a source package should be removed from the</span>
<a name="l00617"></a>00617 <span class="stringliteral"> testing distribution; this happen if the source package is not</span>
<a name="l00618"></a>00618 <span class="stringliteral"> present in the unstable distribution anymore.</span>
<a name="l00619"></a>00619 <span class="stringliteral"></span>
<a name="l00620"></a>00620 <span class="stringliteral"> It returns True if the package can be removed, False otherwise.</span>
<a name="l00621"></a>00621 <span class="stringliteral"> In the former case, a new excuse is appended to the the object</span>
<a name="l00622"></a>00622 <span class="stringliteral"> attribute excuses.</span>
<a name="l00623"></a>00623 <span class="stringliteral"> """</span>
<a name="l00624"></a>00624 <span class="comment"># if the soruce package is available in unstable, then do nothing</span>
<a name="l00625"></a>00625 <span class="keywordflow">if</span> self.sources[<span class="stringliteral">'unstable'</span>].has_key(pkg):
<a name="l00626"></a>00626 <span class="keywordflow">return</span> <span class="keyword">False</span>
<a name="l00627"></a>00627 <span class="comment"># otherwise, add a new excuse for its removal and return True</span>
<a name="l00628"></a><a class="code" href="classbritney_1_1Britney.html#bd18d7acde434387e94344a39db5b0e5">00628</a> src = self.sources[<span class="stringliteral">'testing'</span>][pkg]
<a name="l00629"></a>00629 excuse = Excuse(<span class="stringliteral">"-"</span> + pkg)
<a name="l00630"></a>00630 excuse.set_vers(src[<span class="stringliteral">'version'</span>], <span class="keywordtype">None</span>)
<a name="l00631"></a>00631 src[<span class="stringliteral">'maintainer'</span>] <span class="keywordflow">and</span> excuse.set_maint(src[<span class="stringliteral">'maintainer'</span>].strip())
<a name="l00632"></a>00632 src[<span class="stringliteral">'section'</span>] <span class="keywordflow">and</span> excuse.set_section(src[<span class="stringliteral">'section'</span>].strip())
<a name="l00633"></a>00633 excuse.addhtml(<span class="stringliteral">"Valid candidate"</span>)
<a name="l00634"></a>00634 self.excuses.append(excuse)
<a name="l00635"></a>00635 <span class="keywordflow">return</span> <span class="keyword">True</span>
<a name="l00636"></a>00636
<a name="l00637"></a>00637 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#bd18d7acde434387e94344a39db5b0e5">should_upgrade_srcarch</a>(self, src, arch, suite):
<a name="l00638"></a>00638 <span class="stringliteral">"""Check if binary package should be upgraded</span>
<a name="l00639"></a>00639 <span class="stringliteral"></span>
<a name="l00640"></a>00640 <span class="stringliteral"> This method checks if a binary package should be upgraded; this can</span>
<a name="l00641"></a>00641 <span class="stringliteral"> happen only if the binary package is a binary-NMU for the given arch.</span>
<a name="l00642"></a>00642 <span class="stringliteral"> The analisys is performed for the source package specified by the</span>
<a name="l00643"></a>00643 <span class="stringliteral"> `src' parameter, checking the architecture `arch' for the distribution</span>
<a name="l00644"></a>00644 <span class="stringliteral"> `suite'.</span>
<a name="l00645"></a>00645 <span class="stringliteral"> </span>
<a name="l00646"></a>00646 <span class="stringliteral"> It returns False if the given package doesn't need to be upgraded,</span>
<a name="l00647"></a>00647 <span class="stringliteral"> True otherwise. In the former case, a new excuse is appended to</span>
<a name="l00648"></a>00648 <span class="stringliteral"> the the object attribute excuses.</span>
<a name="l00649"></a>00649 <span class="stringliteral"> """</span>
<a name="l00650"></a>00650 <span class="comment"># retrieve the source packages for testing and suite</span>
<a name="l00651"></a>00651 source_t = self.sources[<span class="stringliteral">'testing'</span>][src]
<a name="l00652"></a>00652 source_u = self.sources[suite][src]
<a name="l00653"></a>00653
<a name="l00654"></a>00654 <span class="comment"># build the common part of the excuse, which will be filled by the code below</span>
<a name="l00655"></a>00655 ref = <span class="stringliteral">"%s/%s%s"</span> % (src, arch, suite != <span class="stringliteral">'unstable'</span> <span class="keywordflow">and</span> <span class="stringliteral">"_"</span> + suite <span class="keywordflow">or</span> <span class="stringliteral">""</span>)
<a name="l00656"></a>00656 excuse = Excuse(ref)
<a name="l00657"></a>00657 excuse.set_vers(source_t[<span class="stringliteral">'version'</span>], source_t[<span class="stringliteral">'version'</span>])
<a name="l00658"></a>00658 source_u[<span class="stringliteral">'maintainer'</span>] <span class="keywordflow">and</span> excuse.set_maint(source_u[<span class="stringliteral">'maintainer'</span>].strip())
<a name="l00659"></a>00659 source_u[<span class="stringliteral">'section'</span>] <span class="keywordflow">and</span> excuse.set_section(source_u[<span class="stringliteral">'section'</span>].strip())
<a name="l00660"></a>00660
<a name="l00661"></a>00661 <span class="comment"># if there is a `remove' hint and the requested version is the same of the</span>
<a name="l00662"></a>00662 <span class="comment"># version in testing, then stop here and return False</span>
<a name="l00663"></a>00663 <span class="keywordflow">if</span> self.hints[<span class="stringliteral">"remove"</span>].has_key(src) <span class="keywordflow">and</span> \
<a name="l00664"></a>00664 self.<a class="code" href="classbritney_1_1Britney.html#85d2e45e8431779b62f398c34972ddf1">same_source</a>(source_t[<span class="stringliteral">'version'</span>], self.hints[<span class="stringliteral">"remove"</span>][src][0]):
<a name="l00665"></a>00665 excuse.addhtml(<span class="stringliteral">"Removal request by %s"</span> % (self.hints[<span class="stringliteral">"remove"</span>][src][1]))
<a name="l00666"></a>00666 excuse.addhtml(<span class="stringliteral">"Trying to remove package, not update it"</span>)
<a name="l00667"></a>00667 excuse.addhtml(<span class="stringliteral">"Not considered"</span>)
<a name="l00668"></a>00668 self.excuses.append(excuse)
<a name="l00669"></a>00669 <span class="keywordflow">return</span> <span class="keyword">False</span>
<a name="l00670"></a>00670
<a name="l00671"></a>00671 <span class="comment"># the starting point is that there is nothing wrong and nothing worth doing</span>
<a name="l00672"></a>00672 anywrongver = <span class="keyword">False</span>
<a name="l00673"></a>00673 anyworthdoing = <span class="keyword">False</span>
<a name="l00674"></a>00674
<a name="l00675"></a>00675 <span class="comment"># for every binary package produced by this source in unstable for this architecture</span>
<a name="l00676"></a>00676 <span class="keywordflow">for</span> pkg <span class="keywordflow">in</span> sorted(filter(<span class="keyword">lambda</span> x: x.endswith(<span class="stringliteral">"/"</span> + arch), source_u[<span class="stringliteral">'binaries'</span>])):
<a name="l00677"></a>00677 pkg_name = pkg.split(<span class="stringliteral">"/"</span>)[0]
<a name="l00678"></a>00678
<a name="l00679"></a>00679 <span class="comment"># retrieve the testing (if present) and unstable corresponding binary packages</span>
<a name="l00680"></a>00680 binary_t = pkg <span class="keywordflow">in</span> source_t[<span class="stringliteral">'binaries'</span>] <span class="keywordflow">and</span> self.binaries[<span class="stringliteral">'testing'</span>][arch][0][pkg_name] <span class="keywordflow">or</span> <span class="keywordtype">None</span>
<a name="l00681"></a>00681 binary_u = self.binaries[suite][arch][0][pkg_name]
<a name="l00682"></a>00682
<a name="l00683"></a>00683 <span class="comment"># this is the source version for the new binary package</span>
<a name="l00684"></a>00684 pkgsv = self.binaries[suite][arch][0][pkg_name][<span class="stringliteral">'source-ver'</span>]
<a name="l00685"></a>00685
<a name="l00686"></a>00686 <span class="comment"># if the new binary package is architecture-independent, then skip it</span>
<a name="l00687"></a>00687 <span class="keywordflow">if</span> binary_u[<span class="stringliteral">'architecture'</span>] == <span class="stringliteral">'all'</span>:
<a name="l00688"></a>00688 excuse.addhtml(<span class="stringliteral">"Ignoring %s %s (from %s) as it is arch: all"</span> % (pkg_name, binary_u[<span class="stringliteral">'version'</span>], pkgsv))
<a name="l00689"></a>00689 <span class="keywordflow">continue</span>
<a name="l00690"></a>00690
<a name="l00691"></a>00691 <span class="comment"># if the new binary package is not from the same source as the testing one, then skip it</span>
<a name="l00692"></a>00692 <span class="keywordflow">if</span> <span class="keywordflow">not</span> self.<a class="code" href="classbritney_1_1Britney.html#85d2e45e8431779b62f398c34972ddf1">same_source</a>(source_t[<span class="stringliteral">'version'</span>], pkgsv):
<a name="l00693"></a>00693 anywrongver = <span class="keyword">True</span>
<a name="l00694"></a>00694 excuse.addhtml(<span class="stringliteral">"From wrong source: %s %s (%s not %s)"</span> % (pkg_name, binary_u[<span class="stringliteral">'version'</span>], pkgsv, source_t[<span class="stringliteral">'version'</span>]))
<a name="l00695"></a>00695 <span class="keywordflow">break</span>
<a name="l00696"></a>00696
<a name="l00697"></a>00697 <span class="comment"># find unsatisfied dependencies for the new binary package</span>
<a name="l00698"></a>00698 self.<a class="code" href="classbritney_1_1Britney.html#f51c60a69f3a9dc2bc5afdb2ffaf3990">excuse_unsat_deps</a>(pkg_name, src, arch, suite, excuse)
<a name="l00699"></a>00699
<a name="l00700"></a>00700 <span class="comment"># if the binary is not present in testing, then it is a new binary;</span>
<a name="l00701"></a>00701 <span class="comment"># in this case, there is something worth doing</span>
<a name="l00702"></a>00702 <span class="keywordflow">if</span> <span class="keywordflow">not</span> binary_t:
<a name="l00703"></a>00703 excuse.addhtml(<span class="stringliteral">"New binary: %s (%s)"</span> % (pkg_name, binary_u[<span class="stringliteral">'version'</span>]))
<a name="l00704"></a>00704 anyworthdoing = <span class="keyword">True</span>
<a name="l00705"></a>00705 <span class="keywordflow">continue</span>
<a name="l00706"></a>00706
<a name="l00707"></a>00707 <span class="comment"># at this point, the binary package is present in testing, so we can compare</span>
<a name="l00708"></a>00708 <span class="comment"># the versions of the packages ...</span>
<a name="l00709"></a>00709 vcompare = apt_pkg.VersionCompare(binary_t[<span class="stringliteral">'version'</span>], binary_u[<span class="stringliteral">'version'</span>])
<a name="l00710"></a>00710
<a name="l00711"></a>00711 <span class="comment"># ... if updating would mean downgrading, then stop here: there is something wrong</span>
<a name="l00712"></a>00712 <span class="keywordflow">if</span> vcompare &gt; 0:
<a name="l00713"></a>00713 anywrongver = <span class="keyword">True</span>
<a name="l00714"></a>00714 excuse.addhtml(<span class="stringliteral">"Not downgrading: %s (%s to %s)"</span> % (pkg_name, binary_t[<span class="stringliteral">'version'</span>], binary_u[<span class="stringliteral">'version'</span>]))
<a name="l00715"></a>00715 <span class="keywordflow">break</span>
<a name="l00716"></a>00716 <span class="comment"># ... if updating would mean upgrading, then there is something worth doing</span>
<a name="l00717"></a>00717 <span class="keywordflow">elif</span> vcompare &lt; 0:
<a name="l00718"></a>00718 excuse.addhtml(<span class="stringliteral">"Updated binary: %s (%s to %s)"</span> % (pkg_name, binary_t[<span class="stringliteral">'version'</span>], binary_u[<span class="stringliteral">'version'</span>]))
<a name="l00719"></a>00719 anyworthdoing = <span class="keyword">True</span>
<a name="l00720"></a>00720
<a name="l00721"></a>00721 <span class="comment"># if there is nothing wrong and there is something worth doing or the source</span>
<a name="l00722"></a>00722 <span class="comment"># package is not fake, then check what packages shuold be removed</span>
<a name="l00723"></a>00723 <span class="keywordflow">if</span> <span class="keywordflow">not</span> anywrongver <span class="keywordflow">and</span> (anyworthdoing <span class="keywordflow">or</span> self.sources[suite][src].has_key(<span class="stringliteral">'fake'</span>)):
<a name="l00724"></a>00724 srcv = self.sources[suite][src][<span class="stringliteral">'version'</span>]
<a name="l00725"></a>00725 ssrc = self.<a class="code" href="classbritney_1_1Britney.html#85d2e45e8431779b62f398c34972ddf1">same_source</a>(source_t[<span class="stringliteral">'version'</span>], srcv)
<a name="l00726"></a>00726 <span class="comment"># for every binary package produced by this source in testing for this architecture</span>
<a name="l00727"></a>00727 <span class="keywordflow">for</span> pkg <span class="keywordflow">in</span> sorted([x.split(<span class="stringliteral">"/"</span>)[0] <span class="keywordflow">for</span> x <span class="keywordflow">in</span> self.sources[<span class="stringliteral">'testing'</span>][src][<span class="stringliteral">'binaries'</span>] <span class="keywordflow">if</span> x.endswith(<span class="stringliteral">"/"</span>+arch)]):
<a name="l00728"></a>00728 <span class="comment"># if the package is architecture-independent, then ignore it</span>
<a name="l00729"></a>00729 <span class="keywordflow">if</span> self.binaries[<span class="stringliteral">'testing'</span>][arch][0][pkg][<span class="stringliteral">'architecture'</span>] == <span class="stringliteral">'all'</span>:
<a name="l00730"></a>00730 excuse.addhtml(<span class="stringliteral">"Ignoring removal of %s as it is arch: all"</span> % (pkg))
<a name="l00731"></a>00731 <span class="keywordflow">continue</span>
<a name="l00732"></a>00732 <span class="comment"># if the package is not produced by the new source package, then remove it from testing</span>
<a name="l00733"></a>00733 <span class="keywordflow">if</span> <span class="keywordflow">not</span> self.binaries[suite][arch][0].has_key(pkg):
<a name="l00734"></a>00734 tpkgv = self.binaries[<span class="stringliteral">'testing'</span>][arch][0][pkg][<span class="stringliteral">'version'</span>]
<a name="l00735"></a>00735 excuse.addhtml(<span class="stringliteral">"Removed binary: %s %s"</span> % (pkg, tpkgv))
<a name="l00736"></a>00736 <span class="keywordflow">if</span> ssrc: anyworthdoing = <span class="keyword">True</span>
<a name="l00737"></a>00737
<a name="l00738"></a>00738 <span class="comment"># if there is nothing wrong and there is something worth doing, this is valid candidate</span>
<a name="l00739"></a>00739 <span class="keywordflow">if</span> <span class="keywordflow">not</span> anywrongver <span class="keywordflow">and</span> anyworthdoing:
<a name="l00740"></a>00740 excuse.addhtml(<span class="stringliteral">"Valid candidate"</span>)
<a name="l00741"></a>00741 self.excuses.append(excuse)
<a name="l00742"></a><a class="code" href="classbritney_1_1Britney.html#94785175a85f44b1afaf3add167a211f">00742</a> <span class="comment"># else if there is something worth doing (but something wrong, too) this package won't be considered</span>
<a name="l00743"></a>00743 <span class="keywordflow">elif</span> anyworthdoing:
<a name="l00744"></a>00744 excuse.addhtml(<span class="stringliteral">"Not considered"</span>)
<a name="l00745"></a>00745 self.excuses.append(excuse)
<a name="l00746"></a>00746 <span class="keywordflow">return</span> <span class="keyword">False</span>
<a name="l00747"></a>00747
<a name="l00748"></a>00748 <span class="comment"># otherwise, return True</span>
<a name="l00749"></a>00749 <span class="keywordflow">return</span> <span class="keyword">True</span>
<a name="l00750"></a>00750
<a name="l00751"></a>00751 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#94785175a85f44b1afaf3add167a211f">should_upgrade_src</a>(self, src, suite):
<a name="l00752"></a>00752 <span class="stringliteral">"""Check if source package should be upgraded</span>
<a name="l00753"></a>00753 <span class="stringliteral"></span>
<a name="l00754"></a>00754 <span class="stringliteral"> This method checks if a source package should be upgraded. The analisys</span>
<a name="l00755"></a>00755 <span class="stringliteral"> is performed for the source package specified by the `src' parameter, </span>
<a name="l00756"></a>00756 <span class="stringliteral"> checking the architecture `arch' for the distribution `suite'.</span>
<a name="l00757"></a>00757 <span class="stringliteral"> </span>
<a name="l00758"></a>00758 <span class="stringliteral"> It returns False if the given package doesn't need to be upgraded,</span>
<a name="l00759"></a>00759 <span class="stringliteral"> True otherwise. In the former case, a new excuse is appended to</span>
<a name="l00760"></a>00760 <span class="stringliteral"> the the object attribute excuses.</span>
<a name="l00761"></a>00761 <span class="stringliteral"> """</span>
<a name="l00762"></a>00762
<a name="l00763"></a>00763 <span class="comment"># retrieve the source packages for testing (if available) and suite</span>
<a name="l00764"></a>00764 source_u = self.sources[suite][src]
<a name="l00765"></a>00765 <span class="keywordflow">if</span> src <span class="keywordflow">in</span> self.sources[<span class="stringliteral">'testing'</span>]:
<a name="l00766"></a>00766 source_t = self.sources[<span class="stringliteral">'testing'</span>][src]
<a name="l00767"></a>00767 <span class="comment"># if testing and unstable have the same version, then this is a candidate for binary-NMUs only</span>
<a name="l00768"></a>00768 <span class="keywordflow">if</span> apt_pkg.VersionCompare(source_t[<span class="stringliteral">'version'</span>], source_u[<span class="stringliteral">'version'</span>]) == 0:
<a name="l00769"></a>00769 <span class="keywordflow">return</span> <span class="keyword">False</span>
<a name="l00770"></a>00770 <span class="keywordflow">else</span>:
<a name="l00771"></a>00771 source_t = <span class="keywordtype">None</span>
<a name="l00772"></a>00772
<a name="l00773"></a>00773 <span class="comment"># build the common part of the excuse, which will be filled by the code below</span>
<a name="l00774"></a>00774 ref = <span class="stringliteral">"%s%s"</span> % (src, suite != <span class="stringliteral">'unstable'</span> <span class="keywordflow">and</span> <span class="stringliteral">"_"</span> + suite <span class="keywordflow">or</span> <span class="stringliteral">""</span>)
<a name="l00775"></a>00775 excuse = Excuse(ref)
<a name="l00776"></a>00776 excuse.set_vers(source_t <span class="keywordflow">and</span> source_t[<span class="stringliteral">'version'</span>] <span class="keywordflow">or</span> <span class="keywordtype">None</span>, source_u[<span class="stringliteral">'version'</span>])
<a name="l00777"></a>00777 source_u[<span class="stringliteral">'maintainer'</span>] <span class="keywordflow">and</span> excuse.set_maint(source_u[<span class="stringliteral">'maintainer'</span>].strip())
<a name="l00778"></a>00778 source_u[<span class="stringliteral">'section'</span>] <span class="keywordflow">and</span> excuse.set_section(source_u[<span class="stringliteral">'section'</span>].strip())
<a name="l00779"></a>00779
<a name="l00780"></a>00780 <span class="comment"># the starting point is that we will update the candidate</span>
<a name="l00781"></a>00781 update_candidate = <span class="keyword">True</span>
<a name="l00782"></a>00782
<a name="l00783"></a>00783 <span class="comment"># if the version in unstable is older, then stop here with a warning in the excuse and return False</span>
<a name="l00784"></a>00784 <span class="keywordflow">if</span> source_t <span class="keywordflow">and</span> apt_pkg.VersionCompare(source_u[<span class="stringliteral">'version'</span>], source_t[<span class="stringliteral">'version'</span>]) &lt; 0:
<a name="l00785"></a>00785 excuse.addhtml(<span class="stringliteral">"ALERT: %s is newer in testing (%s %s)"</span> % (src, source_t[<span class="stringliteral">'version'</span>], source_u[<span class="stringliteral">'version'</span>]))
<a name="l00786"></a>00786 self.excuses.append(excuse)
<a name="l00787"></a>00787 <span class="keywordflow">return</span> <span class="keyword">False</span>
<a name="l00788"></a>00788
<a name="l00789"></a>00789 <span class="comment"># check if the source package really exists or if it is a fake one</span>
<a name="l00790"></a>00790 <span class="keywordflow">if</span> source_u.has_key(<span class="stringliteral">'fake'</span>):
<a name="l00791"></a>00791 excuse.addhtml(<span class="stringliteral">"%s source package doesn't exist"</span> % (src))
<a name="l00792"></a>00792 update_candidate = <span class="keyword">False</span>
<a name="l00793"></a>00793
<a name="l00794"></a>00794 <span class="comment"># retrieve the urgency for the upload, ignoring it if this is a NEW package (not present in testing)</span>
<a name="l00795"></a>00795 urgency = self.urgencies.get(src, self.options.default_urgency)
<a name="l00796"></a>00796 <span class="keywordflow">if</span> <span class="keywordflow">not</span> source_t <span class="keywordflow">and</span> urgency != self.options.default_urgency:
<a name="l00797"></a>00797 excuse.addhtml(<span class="stringliteral">"Ignoring %s urgency setting for NEW package"</span> % (urgency))
<a name="l00798"></a>00798 urgency = self.options.default_urgency
<a name="l00799"></a>00799
<a name="l00800"></a>00800 <span class="comment"># if there is a `remove' hint and the requested version is the same of the</span>
<a name="l00801"></a>00801 <span class="comment"># version in testing, then stop here and return False</span>
<a name="l00802"></a>00802 <span class="keywordflow">if</span> self.hints[<span class="stringliteral">"remove"</span>].has_key(src):
<a name="l00803"></a>00803 <span class="keywordflow">if</span> source_t <span class="keywordflow">and</span> self.<a class="code" href="classbritney_1_1Britney.html#85d2e45e8431779b62f398c34972ddf1">same_source</a>(source_t[<span class="stringliteral">'version'</span>], self.hints[<span class="stringliteral">'remove'</span>][src][0]) <span class="keywordflow">or</span> \
<a name="l00804"></a>00804 self.<a class="code" href="classbritney_1_1Britney.html#85d2e45e8431779b62f398c34972ddf1">same_source</a>(source_u[<span class="stringliteral">'version'</span>], self.hints[<span class="stringliteral">'remove'</span>][src][0]):
<a name="l00805"></a>00805 excuse.addhtml(<span class="stringliteral">"Removal request by %s"</span> % (self.hints[<span class="stringliteral">"remove"</span>][src][1]))
<a name="l00806"></a>00806 excuse.addhtml(<span class="stringliteral">"Trying to remove package, not update it"</span>)
<a name="l00807"></a>00807 update_candidate = <span class="keyword">False</span>
<a name="l00808"></a>00808
<a name="l00809"></a>00809 <span class="comment"># check if there is a `block' hint for this package or a `block-all source' hint</span>
<a name="l00810"></a>00810 blocked = <span class="keywordtype">None</span>
<a name="l00811"></a>00811 <span class="keywordflow">if</span> self.hints[<span class="stringliteral">"block"</span>].has_key(src):
<a name="l00812"></a>00812 blocked = self.hints[<span class="stringliteral">"block"</span>][src]
<a name="l00813"></a>00813 <span class="keywordflow">elif</span> self.hints[<span class="stringliteral">"block-all"</span>].has_key(<span class="stringliteral">"source"</span>):
<a name="l00814"></a>00814 blocked = self.hints[<span class="stringliteral">"block-all"</span>][<span class="stringliteral">"source"</span>]
<a name="l00815"></a>00815
<a name="l00816"></a>00816 <span class="comment"># if the source is blocked, then look for an `unblock' hint; the unblock request</span>
<a name="l00817"></a>00817 <span class="comment"># is processed only if the specified version is correct</span>
<a name="l00818"></a>00818 <span class="keywordflow">if</span> blocked:
<a name="l00819"></a>00819 unblock = self.hints[<span class="stringliteral">"unblock"</span>].get(src,(<span class="keywordtype">None</span>,<span class="keywordtype">None</span>))
<a name="l00820"></a>00820 <span class="keywordflow">if</span> unblock[0] != <span class="keywordtype">None</span>:
<a name="l00821"></a>00821 <span class="keywordflow">if</span> self.<a class="code" href="classbritney_1_1Britney.html#85d2e45e8431779b62f398c34972ddf1">same_source</a>(unblock[0], source_u[<span class="stringliteral">'version'</span>]):
<a name="l00822"></a>00822 excuse.addhtml(<span class="stringliteral">"Ignoring request to block package by %s, due to unblock request by %s"</span> % (blocked, unblock[1]))
<a name="l00823"></a>00823 <span class="keywordflow">else</span>:
<a name="l00824"></a>00824 excuse.addhtml(<span class="stringliteral">"Unblock request by %s ignored due to version mismatch: %s"</span> % (unblock[1], unblock[0]))
<a name="l00825"></a>00825 <span class="keywordflow">else</span>:
<a name="l00826"></a>00826 excuse.addhtml(<span class="stringliteral">"Not touching package, as requested by %s (contact debian-release if update is needed)"</span> % (blocked))
<a name="l00827"></a>00827 update_candidate = <span class="keyword">False</span>
<a name="l00828"></a>00828
<a name="l00829"></a>00829 <span class="comment"># if the suite is unstable, then we have to check the urgency and the minimum days of</span>
<a name="l00830"></a>00830 <span class="comment"># permanence in unstable before updating testing; if the source package is too young,</span>
<a name="l00831"></a>00831 <span class="comment"># the check fails and we set update_candidate to False to block the update</span>
<a name="l00832"></a>00832 <span class="keywordflow">if</span> suite == <span class="stringliteral">'unstable'</span>:
<a name="l00833"></a>00833 <span class="keywordflow">if</span> <span class="keywordflow">not</span> self.dates.has_key(src):
<a name="l00834"></a>00834 self.dates[src] = (source_u[<span class="stringliteral">'version'</span>], self.date_now)
<a name="l00835"></a>00835 <span class="keywordflow">elif</span> <span class="keywordflow">not</span> self.<a class="code" href="classbritney_1_1Britney.html#85d2e45e8431779b62f398c34972ddf1">same_source</a>(self.dates[src][0], source_u[<span class="stringliteral">'version'</span>]):
<a name="l00836"></a>00836 self.dates[src] = (source_u[<span class="stringliteral">'version'</span>], self.date_now)
<a name="l00837"></a>00837
<a name="l00838"></a>00838 days_old = self.date_now - self.dates[src][1]
<a name="l00839"></a>00839 min_days = self.MINDAYS[urgency]
<a name="l00840"></a>00840 excuse.setdaysold(days_old, min_days)
<a name="l00841"></a>00841 <span class="keywordflow">if</span> days_old &lt; min_days:
<a name="l00842"></a>00842 <span class="keywordflow">if</span> self.hints[<span class="stringliteral">"urgent"</span>].has_key(src) <span class="keywordflow">and</span> self.<a class="code" href="classbritney_1_1Britney.html#85d2e45e8431779b62f398c34972ddf1">same_source</a>(source_u[<span class="stringliteral">'version'</span>], self.hints[<span class="stringliteral">"urgent"</span>][src][0]):
<a name="l00843"></a>00843 excuse.addhtml(<span class="stringliteral">"Too young, but urgency pushed by %s"</span> % (self.hints[<span class="stringliteral">"urgent"</span>][src][1]))
<a name="l00844"></a>00844 <span class="keywordflow">else</span>:
<a name="l00845"></a>00845 update_candidate = <span class="keyword">False</span>
<a name="l00846"></a>00846
<a name="l00847"></a>00847 <span class="comment"># at this point, we check what is the status of the builds on all the supported architectures</span>
<a name="l00848"></a>00848 <span class="comment"># to catch the out-of-date ones</span>
<a name="l00849"></a>00849 pkgs = {src: [<span class="stringliteral">"source"</span>]}
<a name="l00850"></a>00850 <span class="keywordflow">for</span> arch <span class="keywordflow">in</span> self.options.architectures:
<a name="l00851"></a>00851 oodbins = {}
<a name="l00852"></a>00852 <span class="comment"># for every binary package produced by this source in the suite for this architecture</span>
<a name="l00853"></a>00853 <span class="keywordflow">for</span> pkg <span class="keywordflow">in</span> sorted([x.split(<span class="stringliteral">"/"</span>)[0] <span class="keywordflow">for</span> x <span class="keywordflow">in</span> self.sources[suite][src][<span class="stringliteral">'binaries'</span>] <span class="keywordflow">if</span> x.endswith(<span class="stringliteral">"/"</span>+arch)]):
<a name="l00854"></a>00854 <span class="keywordflow">if</span> <span class="keywordflow">not</span> pkgs.has_key(pkg): pkgs[pkg] = []
<a name="l00855"></a>00855 pkgs[pkg].append(arch)
<a name="l00856"></a>00856
<a name="l00857"></a>00857 <span class="comment"># retrieve the binary package and its source version</span>
<a name="l00858"></a>00858 binary_u = self.binaries[suite][arch][0][pkg]
<a name="l00859"></a>00859 pkgsv = binary_u[<span class="stringliteral">'source-ver'</span>]
<a name="l00860"></a>00860
<a name="l00861"></a>00861 <span class="comment"># if it wasn't builded by the same source, it is out-of-date</span>
<a name="l00862"></a>00862 <span class="keywordflow">if</span> <span class="keywordflow">not</span> self.<a class="code" href="classbritney_1_1Britney.html#85d2e45e8431779b62f398c34972ddf1">same_source</a>(source_u[<span class="stringliteral">'version'</span>], pkgsv):
<a name="l00863"></a>00863 <span class="keywordflow">if</span> <span class="keywordflow">not</span> oodbins.has_key(pkgsv):
<a name="l00864"></a>00864 oodbins[pkgsv] = []
<a name="l00865"></a>00865 oodbins[pkgsv].append(pkg)
<a name="l00866"></a>00866 <span class="keywordflow">continue</span>
<a name="l00867"></a>00867
<a name="l00868"></a>00868 <span class="comment"># if the package is architecture-dependent or the current arch is `nobreakall'</span>
<a name="l00869"></a>00869 <span class="comment"># find unsatisfied dependencies for the binary package</span>
<a name="l00870"></a>00870 <span class="keywordflow">if</span> binary_u[<span class="stringliteral">'architecture'</span>] != <span class="stringliteral">'all'</span> <span class="keywordflow">or</span> arch <span class="keywordflow">in</span> self.options.nobreakall_arches:
<a name="l00871"></a>00871 self.<a class="code" href="classbritney_1_1Britney.html#f51c60a69f3a9dc2bc5afdb2ffaf3990">excuse_unsat_deps</a>(pkg, src, arch, suite, excuse)
<a name="l00872"></a>00872
<a name="l00873"></a>00873 <span class="comment"># if there are out-of-date packages, warn about them in the excuse and set update_candidate</span>
<a name="l00874"></a>00874 <span class="comment"># to False to block the update; if the architecture where the package is out-of-date is</span>
<a name="l00875"></a>00875 <span class="comment"># in the `fucked_arches' list, then do not block the update</span>
<a name="l00876"></a>00876 <span class="keywordflow">if</span> oodbins:
<a name="l00877"></a>00877 oodtxt = <span class="stringliteral">""</span>
<a name="l00878"></a>00878 <span class="keywordflow">for</span> v <span class="keywordflow">in</span> oodbins.keys():
<a name="l00879"></a>00879 <span class="keywordflow">if</span> oodtxt: oodtxt = oodtxt + <span class="stringliteral">"; "</span>
<a name="l00880"></a>00880 oodtxt = oodtxt + <span class="stringliteral">"%s (from &lt;a href=\"http://buildd.debian.org/build.php?"</span> \
<a name="l00881"></a>00881 <span class="stringliteral">"arch=%s&amp;pkg=%s&amp;ver=%s\" target=\"_blank\"&gt;%s&lt;/a&gt;)"</span> % \
<a name="l00882"></a>00882 (<span class="stringliteral">", "</span>.join(sorted(oodbins[v])), arch, src, v, v)
<a name="l00883"></a>00883 text = <span class="stringliteral">"out of date on &lt;a href=\"http://buildd.debian.org/build.php?"</span> \
<a name="l00884"></a>00884 <span class="stringliteral">"arch=%s&amp;pkg=%s&amp;ver=%s\" target=\"_blank\"&gt;%s&lt;/a&gt;: %s"</span> % \
<a name="l00885"></a>00885 (arch, src, source_u[<span class="stringliteral">'version'</span>], arch, oodtxt)
<a name="l00886"></a>00886
<a name="l00887"></a>00887 <span class="keywordflow">if</span> arch <span class="keywordflow">in</span> self.options.fucked_arches:
<a name="l00888"></a>00888 text = text + <span class="stringliteral">" (but %s isn't keeping up, so nevermind)"</span> % (arch)
<a name="l00889"></a>00889 <span class="keywordflow">else</span>:
<a name="l00890"></a>00890 update_candidate = <span class="keyword">False</span>
<a name="l00891"></a>00891
<a name="l00892"></a>00892 <span class="keywordflow">if</span> self.date_now != self.dates[src][1]:
<a name="l00893"></a>00893 excuse.addhtml(text)
<a name="l00894"></a>00894
<a name="l00895"></a>00895 <span class="comment"># if the source package has no binaries, set update_candidate to False to block the update</span>
<a name="l00896"></a>00896 <span class="keywordflow">if</span> len(self.sources[suite][src][<span class="stringliteral">'binaries'</span>]) == 0:
<a name="l00897"></a>00897 excuse.addhtml(<span class="stringliteral">"%s has no binaries on any arch"</span> % src)
<a name="l00898"></a>00898 update_candidate = <span class="keyword">False</span>
<a name="l00899"></a>00899
<a name="l00900"></a>00900 <span class="comment"># if the suite is unstable, then we have to check the release-critical bug counts before</span>
<a name="l00901"></a>00901 <span class="comment"># updating testing; if the unstable package have a RC bug count greater than the testing</span>
<a name="l00902"></a>00902 <span class="comment"># one, the check fails and we set update_candidate to False to block the update</span>
<a name="l00903"></a>00903 <span class="keywordflow">if</span> suite == <span class="stringliteral">'unstable'</span>:
<a name="l00904"></a>00904 <span class="keywordflow">for</span> pkg <span class="keywordflow">in</span> pkgs.keys():
<a name="l00905"></a>00905 <span class="keywordflow">if</span> <span class="keywordflow">not</span> self.bugs[<span class="stringliteral">'testing'</span>].has_key(pkg):
<a name="l00906"></a>00906 self.bugs[<span class="stringliteral">'testing'</span>][pkg] = 0
<a name="l00907"></a>00907 <span class="keywordflow">if</span> <span class="keywordflow">not</span> self.bugs[<span class="stringliteral">'unstable'</span>].has_key(pkg):
<a name="l00908"></a>00908 self.bugs[<span class="stringliteral">'unstable'</span>][pkg] = 0
<a name="l00909"></a>00909
<a name="l00910"></a>00910 <span class="keywordflow">if</span> self.bugs[<span class="stringliteral">'unstable'</span>][pkg] &gt; self.bugs[<span class="stringliteral">'testing'</span>][pkg]:
<a name="l00911"></a>00911 excuse.addhtml(<span class="stringliteral">"%s (%s) is &lt;a href=\"http://bugs.debian.org/cgi-bin/pkgreport.cgi?"</span> \
<a name="l00912"></a>00912 <span class="stringliteral">"which=pkg&amp;data=%s&amp;sev-inc=critical&amp;sev-inc=grave&amp;sev-inc=serious\" "</span> \
<a name="l00913"></a>00913 <span class="stringliteral">"target=\"_blank\"&gt;buggy&lt;/a&gt;! (%d &gt; %d)"</span> % \
<a name="l00914"></a>00914 (pkg, <span class="stringliteral">", "</span>.join(pkgs[pkg]), pkg, self.bugs[<span class="stringliteral">'unstable'</span>][pkg], self.bugs[<span class="stringliteral">'testing'</span>][pkg]))
<a name="l00915"></a>00915 update_candidate = <span class="keyword">False</span>
<a name="l00916"></a>00916 <span class="keywordflow">elif</span> self.bugs[<span class="stringliteral">'unstable'</span>][pkg] &gt; 0:
<a name="l00917"></a>00917 excuse.addhtml(<span class="stringliteral">"%s (%s) is (less) &lt;a href=\"http://bugs.debian.org/cgi-bin/pkgreport.cgi?"</span> \
<a name="l00918"></a>00918 <span class="stringliteral">"which=pkg&amp;data=%s&amp;sev-inc=critical&amp;sev-inc=grave&amp;sev-inc=serious\" "</span> \
<a name="l00919"></a>00919 <span class="stringliteral">"target=\"_blank\"&gt;buggy&lt;/a&gt;! (%d &lt;= %d)"</span> % \
<a name="l00920"></a>00920 (pkg, <span class="stringliteral">", "</span>.join(pkgs[pkg]), pkg, self.bugs[<span class="stringliteral">'unstable'</span>][pkg], self.bugs[<span class="stringliteral">'testing'</span>][pkg]))
<a name="l00921"></a>00921
<a name="l00922"></a>00922 <span class="comment"># check if there is a `force' hint for this package, which allows it to go in even if it is not updateable</span>
<a name="l00923"></a>00923 <span class="keywordflow">if</span> <span class="keywordflow">not</span> update_candidate <span class="keywordflow">and</span> self.hints[<span class="stringliteral">"force"</span>].has_key(src) <span class="keywordflow">and</span> \
<a name="l00924"></a>00924 self.<a class="code" href="classbritney_1_1Britney.html#85d2e45e8431779b62f398c34972ddf1">same_source</a>(source_u[<span class="stringliteral">'version'</span>], self.hints[<span class="stringliteral">"force"</span>][src][0]):
<a name="l00925"></a>00925 excuse.dontinvalidate = 1
<a name="l00926"></a>00926 excuse.addhtml(<span class="stringliteral">"Should ignore, but forced by %s"</span> % (self.hints[<span class="stringliteral">"force"</span>][src][1]))
<a name="l00927"></a>00927 update_candidate = <span class="keyword">True</span>
<a name="l00928"></a>00928
<a name="l00929"></a>00929 <span class="comment"># if the suite is testing-proposed-updates, the package needs an explicit approval in order to go in</span>
<a name="l00930"></a>00930 <span class="keywordflow">if</span> suite == <span class="stringliteral">"tpu"</span>:
<a name="l00931"></a>00931 <span class="keywordflow">if</span> self.approvals.has_key(<span class="stringliteral">"%s_%s"</span> % (src, source_u[<span class="stringliteral">'version'</span>])):
<a name="l00932"></a>00932 excuse.addhtml(<span class="stringliteral">"Approved by %s"</span> % approvals[<span class="stringliteral">"%s_%s"</span> % (src, source_u[<span class="stringliteral">'version'</span>])])
<a name="l00933"></a>00933 <span class="keywordflow">else</span>:
<a name="l00934"></a>00934 excuse.addhtml(<span class="stringliteral">"NEEDS APPROVAL BY RM"</span>)
<a name="l00935"></a>00935 update_candidate = <span class="keyword">False</span>
<a name="l00936"></a>00936
<a name="l00937"></a>00937 <span class="comment"># if the package can be updated, it is a valid candidate</span>
<a name="l00938"></a><a class="code" href="classbritney_1_1Britney.html#be1b4af9d6c6650c70b24267412bc1a8">00938</a> <span class="keywordflow">if</span> update_candidate:
<a name="l00939"></a>00939 excuse.addhtml(<span class="stringliteral">"Valid candidate"</span>)
<a name="l00940"></a>00940 <span class="comment"># else it won't be considered</span>
<a name="l00941"></a>00941 <span class="keywordflow">else</span>:
<a name="l00942"></a>00942 excuse.addhtml(<span class="stringliteral">"Not considered"</span>)
<a name="l00943"></a>00943
<a name="l00944"></a>00944 self.excuses.append(excuse)
<a name="l00945"></a>00945 <span class="keywordflow">return</span> update_candidate
<a name="l00946"></a>00946
<a name="l00947"></a>00947 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#be1b4af9d6c6650c70b24267412bc1a8">reversed_exc_deps</a>(self):
<a name="l00948"></a>00948 <span class="stringliteral">"""Reverse the excuses dependencies</span>
<a name="l00949"></a>00949 <span class="stringliteral"></span>
<a name="l00950"></a>00950 <span class="stringliteral"> This method returns a dictionary where the keys are the package names</span>
<a name="l00951"></a><a class="code" href="classbritney_1_1Britney.html#171969785db449d7a06c3f762774e0cd">00951</a> <span class="stringliteral"> and the values are the excuse names which depend on it.</span>
<a name="l00952"></a>00952 <span class="stringliteral"> """</span>
<a name="l00953"></a>00953 res = {}
<a name="l00954"></a>00954 <span class="keywordflow">for</span> exc <span class="keywordflow">in</span> self.excuses:
<a name="l00955"></a>00955 <span class="keywordflow">for</span> d <span class="keywordflow">in</span> exc.deps:
<a name="l00956"></a>00956 <span class="keywordflow">if</span> <span class="keywordflow">not</span> res.has_key(d): res[d] = []
<a name="l00957"></a>00957 res[d].append(exc.name)
<a name="l00958"></a>00958 <span class="keywordflow">return</span> res
<a name="l00959"></a>00959
<a name="l00960"></a>00960 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#171969785db449d7a06c3f762774e0cd">invalidate_excuses</a>(self, valid, invalid):
<a name="l00961"></a>00961 <span class="stringliteral">"""Invalidate impossible excuses</span>
<a name="l00962"></a>00962 <span class="stringliteral"></span>
<a name="l00963"></a>00963 <span class="stringliteral"> This method invalidates the impossible excuses, which depend</span>
<a name="l00964"></a>00964 <span class="stringliteral"> on invalid excuses. The two parameters contains the list of</span>
<a name="l00965"></a>00965 <span class="stringliteral"> `valid' and `invalid' excuses.</span>
<a name="l00966"></a>00966 <span class="stringliteral"> """</span>
<a name="l00967"></a>00967 <span class="comment"># build a lookup-by-name map</span>
<a name="l00968"></a>00968 exclookup = {}
<a name="l00969"></a>00969 <span class="keywordflow">for</span> e <span class="keywordflow">in</span> self.excuses:
<a name="l00970"></a>00970 exclookup[e.name] = e
<a name="l00971"></a>00971
<a name="l00972"></a>00972 <span class="comment"># build the reverse dependencies</span>
<a name="l00973"></a>00973 revdeps = self.<a class="code" href="classbritney_1_1Britney.html#be1b4af9d6c6650c70b24267412bc1a8">reversed_exc_deps</a>()
<a name="l00974"></a>00974
<a name="l00975"></a>00975 <span class="comment"># loop on the invalid excuses</span>
<a name="l00976"></a>00976 i = 0
<a name="l00977"></a>00977 <span class="keywordflow">while</span> i &lt; len(invalid):
<a name="l00978"></a>00978 <span class="comment"># if there is no reverse dependency, skip the item</span>
<a name="l00979"></a>00979 <span class="keywordflow">if</span> <span class="keywordflow">not</span> revdeps.has_key(invalid[i]):
<a name="l00980"></a>00980 i += 1
<a name="l00981"></a>00981 <span class="keywordflow">continue</span>
<a name="l00982"></a>00982 <span class="comment"># if there dependency can be satisfied by a testing-proposed-updates excuse, skip the item</span>
<a name="l00983"></a>00983 <span class="keywordflow">if</span> (invalid[i] + <span class="stringliteral">"_tpu"</span>) <span class="keywordflow">in</span> valid:
<a name="l00984"></a>00984 i += 1
<a name="l00985"></a>00985 <span class="keywordflow">continue</span>
<a name="l00986"></a>00986 <span class="comment"># loop on the reverse dependencies</span>
<a name="l00987"></a>00987 <span class="keywordflow">for</span> x <span class="keywordflow">in</span> revdeps[invalid[i]]:
<a name="l00988"></a>00988 <span class="comment"># if the item is valid and it is marked as `dontinvalidate', skip the item</span>
<a name="l00989"></a>00989 <span class="keywordflow">if</span> x <span class="keywordflow">in</span> valid <span class="keywordflow">and</span> exclookup[x].dontinvalidate:
<a name="l00990"></a>00990 <span class="keywordflow">continue</span>
<a name="l00991"></a>00991
<a name="l00992"></a>00992 <span class="comment"># otherwise, invalidate the dependency and mark as invalidated and</span>
<a name="l00993"></a><a class="code" href="classbritney_1_1Britney.html#010f6deffca32f7f71ecf1f5c1bb4985">00993</a> <span class="comment"># remove the depending excuses</span>
<a name="l00994"></a>00994 exclookup[x].invalidate_dep(invalid[i])
<a name="l00995"></a>00995 <span class="keywordflow">if</span> x <span class="keywordflow">in</span> valid:
<a name="l00996"></a>00996 p = valid.index(x)
<a name="l00997"></a>00997 invalid.append(valid.pop(p))
<a name="l00998"></a>00998 exclookup[x].addhtml(<span class="stringliteral">"Invalidated by dependency"</span>)
<a name="l00999"></a>00999 exclookup[x].addhtml(<span class="stringliteral">"Not considered"</span>)
<a name="l01000"></a>01000 i = i + 1
<a name="l01001"></a>01001
<a name="l01002"></a>01002 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#010f6deffca32f7f71ecf1f5c1bb4985">write_excuses</a>(self):
<a name="l01003"></a>01003 <span class="stringliteral">"""Produce and write the update excuses</span>
<a name="l01004"></a>01004 <span class="stringliteral"></span>
<a name="l01005"></a>01005 <span class="stringliteral"> This method handles the update excuses generation: the packages are</span>
<a name="l01006"></a>01006 <span class="stringliteral"> looked to determine whether they are valid candidates. For the details</span>
<a name="l01007"></a>01007 <span class="stringliteral"> of this procedure, please refer to the module docstring.</span>
<a name="l01008"></a>01008 <span class="stringliteral"> """</span>
<a name="l01009"></a>01009
<a name="l01010"></a>01010 <span class="comment"># this list will contain the packages which are valid candidates;</span>
<a name="l01011"></a>01011 <span class="comment"># if a package is going to be removed, it will have a "-" prefix</span>
<a name="l01012"></a>01012 upgrade_me = []
<a name="l01013"></a>01013
<a name="l01014"></a>01014 <span class="comment"># for every source package in testing, check if it should be removed</span>
<a name="l01015"></a>01015 <span class="keywordflow">for</span> pkg <span class="keywordflow">in</span> self.sources[<span class="stringliteral">'testing'</span>]:
<a name="l01016"></a>01016 <span class="keywordflow">if</span> self.<a class="code" href="classbritney_1_1Britney.html#f8a6c9adbdec7a5a982dd2b74febcc08">should_remove_source</a>(pkg):
<a name="l01017"></a>01017 upgrade_me.append(<span class="stringliteral">"-"</span> + pkg)
<a name="l01018"></a>01018
<a name="l01019"></a>01019 <span class="comment"># for every source package in unstable check if it should be upgraded</span>
<a name="l01020"></a>01020 <span class="keywordflow">for</span> pkg <span class="keywordflow">in</span> self.sources[<span class="stringliteral">'unstable'</span>]:
<a name="l01021"></a>01021 <span class="comment"># if the source package is already present in testing,</span>
<a name="l01022"></a>01022 <span class="comment"># check if it should be upgraded for every binary package</span>
<a name="l01023"></a>01023 <span class="keywordflow">if</span> self.sources[<span class="stringliteral">'testing'</span>].has_key(pkg):
<a name="l01024"></a>01024 <span class="keywordflow">for</span> arch <span class="keywordflow">in</span> self.options.architectures:
<a name="l01025"></a>01025 <span class="keywordflow">if</span> self.<a class="code" href="classbritney_1_1Britney.html#bd18d7acde434387e94344a39db5b0e5">should_upgrade_srcarch</a>(pkg, arch, <span class="stringliteral">'unstable'</span>):
<a name="l01026"></a>01026 upgrade_me.append(<span class="stringliteral">"%s/%s"</span> % (pkg, arch))
<a name="l01027"></a>01027
<a name="l01028"></a>01028 <span class="comment"># check if the source package should be upgraded</span>
<a name="l01029"></a>01029 <span class="keywordflow">if</span> self.<a class="code" href="classbritney_1_1Britney.html#94785175a85f44b1afaf3add167a211f">should_upgrade_src</a>(pkg, <span class="stringliteral">'unstable'</span>):
<a name="l01030"></a>01030 upgrade_me.append(pkg)
<a name="l01031"></a>01031
<a name="l01032"></a>01032 <span class="comment"># for every source package in testing-proposed-updates, check if it should be upgraded</span>
<a name="l01033"></a>01033 <span class="keywordflow">for</span> pkg <span class="keywordflow">in</span> self.sources[<span class="stringliteral">'tpu'</span>]:
<a name="l01034"></a>01034 <span class="comment"># if the source package is already present in testing,</span>
<a name="l01035"></a>01035 <span class="comment"># check if it should be upgraded for every binary package</span>
<a name="l01036"></a>01036 <span class="keywordflow">if</span> self.sources[<span class="stringliteral">'testing'</span>].has_key(pkg):
<a name="l01037"></a>01037 <span class="keywordflow">for</span> arch <span class="keywordflow">in</span> self.options.architectures:
<a name="l01038"></a>01038 <span class="keywordflow">if</span> self.<a class="code" href="classbritney_1_1Britney.html#bd18d7acde434387e94344a39db5b0e5">should_upgrade_srcarch</a>(pkg, arch, <span class="stringliteral">'tpu'</span>):
<a name="l01039"></a>01039 upgrade_me.append(<span class="stringliteral">"%s/%s_tpu"</span> % (pkg, arch))
<a name="l01040"></a>01040
<a name="l01041"></a>01041 <span class="comment"># check if the source package should be upgraded</span>
<a name="l01042"></a>01042 <span class="keywordflow">if</span> self.<a class="code" href="classbritney_1_1Britney.html#94785175a85f44b1afaf3add167a211f">should_upgrade_src</a>(pkg, <span class="stringliteral">'tpu'</span>):
<a name="l01043"></a>01043 upgrade_me.append(<span class="stringliteral">"%s_tpu"</span> % pkg)
<a name="l01044"></a>01044
<a name="l01045"></a>01045 <span class="comment"># process the `remove' hints, if the given package is not yet in upgrade_me</span>
<a name="l01046"></a>01046 <span class="keywordflow">for</span> src <span class="keywordflow">in</span> self.hints[<span class="stringliteral">"remove"</span>].keys():
<a name="l01047"></a>01047 <span class="keywordflow">if</span> src <span class="keywordflow">in</span> upgrade_me: <span class="keywordflow">continue</span>
<a name="l01048"></a>01048 <span class="keywordflow">if</span> (<span class="stringliteral">"-"</span>+src) <span class="keywordflow">in</span> upgrade_me: <span class="keywordflow">continue</span>
<a name="l01049"></a>01049 <span class="keywordflow">if</span> <span class="keywordflow">not</span> self.sources[<span class="stringliteral">'testing'</span>].has_key(src): <span class="keywordflow">continue</span>
<a name="l01050"></a>01050
<a name="l01051"></a>01051 <span class="comment"># check if the version specified in the hint is the same of the considered package</span>
<a name="l01052"></a>01052 tsrcv = self.sources[<span class="stringliteral">'testing'</span>][src][<span class="stringliteral">'version'</span>]
<a name="l01053"></a>01053 <span class="keywordflow">if</span> <span class="keywordflow">not</span> self.<a class="code" href="classbritney_1_1Britney.html#85d2e45e8431779b62f398c34972ddf1">same_source</a>(tsrcv, self.hints[<span class="stringliteral">"remove"</span>][src][0]): <span class="keywordflow">continue</span>
<a name="l01054"></a>01054
<a name="l01055"></a>01055 <span class="comment"># add the removal of the package to upgrade_me and build a new excuse</span>
<a name="l01056"></a>01056 upgrade_me.append(<span class="stringliteral">"-%s"</span> % (src))
<a name="l01057"></a>01057 excuse = Excuse(<span class="stringliteral">"-%s"</span> % (src))
<a name="l01058"></a>01058 excuse.set_vers(tsrcv, <span class="keywordtype">None</span>)
<a name="l01059"></a>01059 excuse.addhtml(<span class="stringliteral">"Removal request by %s"</span> % (self.hints[<span class="stringliteral">"remove"</span>][src][1]))
<a name="l01060"></a>01060 excuse.addhtml(<span class="stringliteral">"Package is broken, will try to remove"</span>)
<a name="l01061"></a>01061 self.excuses.append(excuse)
<a name="l01062"></a>01062
<a name="l01063"></a>01063 <span class="comment"># sort the excuses by daysold and name</span>
<a name="l01064"></a>01064 self.excuses.sort(<span class="keyword">lambda</span> x, y: cmp(x.daysold, y.daysold) <span class="keywordflow">or</span> cmp(x.name, y.name))
<a name="l01065"></a>01065
<a name="l01066"></a>01066 <span class="comment"># extract the not considered packages, which are in the excuses but not in upgrade_me</span>
<a name="l01067"></a>01067 unconsidered = [e.name <span class="keywordflow">for</span> e <span class="keywordflow">in</span> self.excuses <span class="keywordflow">if</span> e.name <span class="keywordflow">not</span> <span class="keywordflow">in</span> upgrade_me]
<a name="l01068"></a>01068
<a name="l01069"></a>01069 <span class="comment"># invalidate impossible excuses</span>
<a name="l01070"></a>01070 <span class="keywordflow">for</span> e <span class="keywordflow">in</span> self.excuses:
<a name="l01071"></a>01071 <span class="keywordflow">for</span> d <span class="keywordflow">in</span> e.deps:
<a name="l01072"></a>01072 <span class="keywordflow">if</span> d <span class="keywordflow">not</span> <span class="keywordflow">in</span> upgrade_me <span class="keywordflow">and</span> d <span class="keywordflow">not</span> <span class="keywordflow">in</span> unconsidered:
<a name="l01073"></a>01073 e.addhtml(<span class="stringliteral">"Unpossible dep: %s -&gt; %s"</span> % (e.name, d))
<a name="l01074"></a>01074 self.<a class="code" href="classbritney_1_1Britney.html#171969785db449d7a06c3f762774e0cd">invalidate_excuses</a>(upgrade_me, unconsidered)
<a name="l01075"></a>01075
<a name="l01076"></a>01076 <span class="comment"># write excuses to the output file</span>
<a name="l01077"></a>01077 f = open(self.options.excuses_output, <span class="stringliteral">'w'</span>)
<a name="l01078"></a>01078 f.write(<span class="stringliteral">"&lt;!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\"&gt;\n"</span>)
<a name="l01079"></a><a class="code" href="classbritney_1_1Britney.html#0e9551bdf927388f55be5ce15a48c94f">01079</a> f.write(<span class="stringliteral">"&lt;html&gt;&lt;head&gt;&lt;title&gt;excuses...&lt;/title&gt;"</span>)
<a name="l01080"></a>01080 f.write(<span class="stringliteral">"&lt;meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"&gt;&lt;/head&gt;&lt;body&gt;\n"</span>)
<a name="l01081"></a>01081 f.write(<span class="stringliteral">"&lt;p&gt;Generated: "</span> + time.strftime(<span class="stringliteral">"%Y.%m.%d %H:%M:%S %z"</span>, time.gmtime(time.time())) + <span class="stringliteral">"&lt;/p&gt;\n"</span>)
<a name="l01082"></a>01082 f.write(<span class="stringliteral">"&lt;ul&gt;\n"</span>)
<a name="l01083"></a>01083 <span class="keywordflow">for</span> e <span class="keywordflow">in</span> self.excuses:
<a name="l01084"></a>01084 f.write(<span class="stringliteral">"&lt;li&gt;%s"</span> % e.html())
<a name="l01085"></a>01085 f.write(<span class="stringliteral">"&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;\n"</span>)
<a name="l01086"></a>01086 f.close()
<a name="l01087"></a>01087
<a name="l01088"></a>01088 <span class="keyword">def </span><a class="code" href="classbritney_1_1Britney.html#0e9551bdf927388f55be5ce15a48c94f">main</a>(self):
<a name="l01089"></a>01089 <span class="stringliteral">"""Main method</span>
<a name="l01090"></a>01090 <span class="stringliteral"> </span>
<a name="l01091"></a>01091 <span class="stringliteral"> This is the entry point for the class: it includes the list of calls</span>
<a name="l01092"></a>01092 <span class="stringliteral"> for the member methods which will produce the output files.</span>
<a name="l01093"></a>01093 <span class="stringliteral"> """</span>
<a name="l01094"></a>01094 self.<a class="code" href="classbritney_1_1Britney.html#010f6deffca32f7f71ecf1f5c1bb4985">write_excuses</a>()
<a name="l01095"></a>01095
<a name="l01096"></a>01096 <span class="keywordflow">if</span> __name__ == <span class="stringliteral">'__main__'</span>:
<a name="l01097"></a>01097 Britney().main()
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Sat Jun 24 18:50:20 2006 for briteny by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.4.6 </small></address>
</body>
</html>