86
91
# actions for "invoke_manager"
87
92
(INSTALL, UPDATE) = range(2)
89
SYNAPTIC_PINFILE = "/var/lib/synaptic/preferences"
91
CHANGELOGS_URI="http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
94
class MyCache(apt.Cache):
95
def __init__(self, progress, rootdir=None):
96
apt.Cache.__init__(self, progress, rootdir)
97
# raise if we have packages in reqreinst state
98
# and let the caller deal with that (runs partial upgrade)
99
assert len(self.reqReinstallPkgs) == 0
100
# init the regular cache
102
self.all_changes = {}
103
# on broken packages, try to fix via saveDistUpgrade()
104
if self._depcache.BrokenCount > 0:
105
self.saveDistUpgrade()
106
assert (self._depcache.BrokenCount == 0 and
107
self._depcache.DelCount == 0)
109
def _initDepCache(self):
110
#apt_pkg.Config.Set("Debug::pkgPolicy","1")
111
#self.depcache = apt_pkg.GetDepCache(self.cache)
112
#self._depcache = apt_pkg.GetDepCache(self._cache)
113
self._depcache.ReadPinFile()
114
if os.path.exists(SYNAPTIC_PINFILE):
115
self._depcache.ReadPinFile(SYNAPTIC_PINFILE)
116
self._depcache.Init()
120
def requiredDownload(self):
121
""" get the size of the packages that are required to download """
122
pm = apt_pkg.GetPackageManager(self._depcache)
123
fetcher = apt_pkg.GetAcquire()
124
pm.GetArchives(fetcher, self._list, self._records)
125
return fetcher.FetchNeeded
127
def installCount(self):
128
return self._depcache.InstCount
129
def saveDistUpgrade(self):
130
""" this functions mimics a upgrade but will never remove anything """
131
self._depcache.Upgrade(True)
132
wouldDelete = self._depcache.DelCount
133
if self._depcache.DelCount > 0:
135
assert self._depcache.BrokenCount == 0 and self._depcache.DelCount == 0
136
self._depcache.Upgrade()
138
def matchPackageOrigin(self, pkg, matcher):
139
""" match 'pkg' origin against 'matcher', take versions between
140
installedVersion and candidateVersion into account too
141
Useful if installed pkg A v1.0 is available in both
142
-updates (as v1.2) and -security (v1.1). we want to display
143
it as a security update then
145
inst_ver = pkg._pkg.CurrentVer
146
cand_ver = self._depcache.GetCandidateVer(pkg._pkg)
147
# init with empty match
148
update_origin = matcher[(None,None)]
149
for ver in pkg._pkg.VersionList:
150
# discard is < than installed ver
152
apt_pkg.VersionCompare(ver.VerStr, inst_ver.VerStr) <= 0):
153
#print "skipping '%s' " % ver.VerStr
155
# check if we have a match
156
for(verFileIter,index) in ver.FileList:
157
if matcher.has_key((verFileIter.Archive, verFileIter.Origin)):
158
indexfile = pkg._list.FindIndex(verFileIter)
159
if indexfile: # and indexfile.IsTrusted:
160
match = matcher[verFileIter.Archive, verFileIter.Origin]
161
if match.importance > update_origin.importance:
162
update_origin = match
165
def get_changelog(self, name, lock):
166
# don't touch the gui in this function, it needs to be thread-safe
169
# get the src package name
170
srcpkg = pkg.sourcePackageName
172
# assume "main" section
174
# use the section of the candidate as a starting point
175
section = pkg._depcache.GetCandidateVer(pkg._pkg).Section
177
# get the source version, start with the binaries version
178
binver = pkg.candidateVersion
179
srcver = pkg.candidateVersion
180
#print "bin: %s" % binver
182
l = section.split("/")
186
# lib is handled special
188
if srcpkg.startswith("lib"):
189
prefix = "lib" + srcpkg[3]
191
# stip epoch, but save epoch for later when displaying the
192
# launchpad changelog
193
srcver_epoch = srcver
194
l = string.split(srcver,":")
196
srcver = "".join(l[1:])
199
uri = CHANGELOGS_URI % (src_section,prefix,srcpkg,srcpkg, srcver)
200
# print "Trying: %s " % uri
201
changelog = urllib2.urlopen(uri)
202
#print changelog.read()
203
# do only get the lines that are new
205
regexp = "^%s \((.*)\)(.*)$" % (re.escape(srcpkg))
209
line = changelog.readline()
212
match = re.match(regexp,line)
214
# strip epoch from installed version
215
# and from changelog too
216
installed = pkg.installedVersion
217
if installed and ":" in installed:
218
installed = installed.split(":",1)[1]
219
changelogver = match.group(1)
220
if changelogver and ":" in changelogver:
221
changelogver = changelogver.split(":",1)[1]
222
# we test for "==" here to ensure that the version
223
# is actually really in the changelog - if not
224
# just display it all, this catches cases like:
225
# gcc-defaults with "binver=4.3.1" and srcver=1.76
227
apt_pkg.VersionCompare(changelogver,installed)==0):
229
alllines = alllines + line
231
# Print an error if we failed to extract a changelog
232
if len(alllines) == 0:
233
alllines = _("The changelog does not contain any relevant changes.\n\n"
234
"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
235
"until the changes become available or try again "
236
"later.") % (srcpkg, srcver_epoch),
237
# only write if we where not canceld
239
self.all_changes[name] = [alllines, srcpkg]
240
except urllib2.HTTPError, e:
242
self.all_changes[name] = [
243
_("The list of changes is not available yet.\n\n"
244
"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
245
"until the changes become available or try again "
246
"later.") % (srcpkg, srcver_epoch),
248
except (IOError, httplib.BadStatusLine, socket.error), e:
249
print "caught exception: ", e
251
self.all_changes[name] = [_("Failed to download the list "
252
"of changes. \nPlease "
253
"check your Internet "
254
"connection."), srcpkg]
260
def __init__(self, desc, importance):
262
self.importance = importance
263
self.description = desc
265
def __init__(self, parent):
266
# a map of packages under their origin
268
pipe = os.popen("lsb_release -c -s")
269
dist = pipe.read().strip()
272
print "Error in lsb_release: %s" % e
273
parent.error(_("Failed to detect distribution"),
274
_("A error '%s' occurred while checking what system "
275
"you are using.") % e)
277
self.distUpgradeWouldDelete = 0
280
self.matcher = self.initMatcher(dist)
282
def initMatcher(self, dist):
283
# (origin, archive, description, importance)
284
matcher_templates = [
285
("%s-security" % dist, "Ubuntu", _("Important security updates"),10),
286
("%s-updates" % dist, "Ubuntu", _("Recommended updates"), 9),
287
("%s-proposed" % dist, "Ubuntu", _("Proposed updates"), 8),
288
("%s-backports" % dist, "Ubuntu", _("Backports"), 7),
289
(dist, "Ubuntu", _("Distribution updates"), 6)
292
for (origin, archive, desc, importance) in matcher_templates:
293
matcher[(origin, archive)] = self.UpdateOrigin(desc, importance)
294
matcher[(None,None)] = self.UpdateOrigin(_("Other updates"), -1)
297
def update(self, cache):
301
self.distUpgradeWouldDelete = cache.saveDistUpgrade()
303
dselect_upgrade_origin = self.UpdateOrigin(_("Previous selected"), 1)
307
if pkg.isUpgradable or pkg.markedInstall:
308
if pkg.candidateOrigin == None:
309
# can happen for e.g. locked packages
310
# FIXME: do something more sensible here (but what?)
311
print "WARNING: upgradable but no canidateOrigin?!?: ", pkg.name
313
# check where the package belongs
314
origin_node = cache.matchPackageOrigin(pkg, self.matcher)
315
if not self.pkgs.has_key(origin_node):
316
self.pkgs[origin_node] = []
317
self.pkgs[origin_node].append(pkg)
318
self.num_updates = self.num_updates + 1
319
if pkg.isUpgradable and not (pkg.markedUpgrade or pkg.markedInstall):
320
self.held_back.append(pkg.name)
321
for l in self.pkgs.keys():
322
self.pkgs[l].sort(lambda x,y: cmp(x.name,y.name))
323
self.keepcount = cache._depcache.KeepCount
326
95
class UpdateManagerDbusControler(dbus.service.Object):
327
96
""" this is a helper to provide the UpdateManagerIFace """