File: MetaRelease.py

package info (click to toggle)
update-manager 0.68.debian-7
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 6,796 kB
  • ctags: 814
  • sloc: python: 5,646; xml: 1,571; sh: 433; makefile: 356; ansic: 264
file content (188 lines) | stat: -rw-r--r-- 7,519 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# MetaRelease.py 
#  
#  Copyright (c) 2004,2005 Canonical
#  
#  Author: Michael Vogt <michael.vogt@ubuntu.com>
# 
#  This program is free software; you can redistribute it and/or 
#  modify it under the terms of the GNU General Public License as 
#  published by the Free Software Foundation; either version 2 of the
#  License, or (at your option) any later version.
# 
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
# 
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
#  USA

import thread
import urllib2
import os
import string
import apt_pkg
import time
import sys
import rfc822
from subprocess import Popen,PIPE

class Dist(object):
    def __init__(self, name, version, date, supported):
        self.name = name
        self.version = version
        self.date = date
        self.supported = supported
        self.releaseNotesURI = None
        self.upgradeTool = None
        self.upgradeToolSig = None

class MetaReleaseCore(object):

    # some constants
    METARELEASE_URI = "http://changelogs.ubuntu.com/meta-release"
    METARELEASE_URI_UNSTABLE = "http://changelogs.ubuntu.com/meta-release-development"
    METARELEASE_URI_PROPOSED = "http://changelogs.ubuntu.com/meta-release-proposed"
    METARELEASE_FILE = "/var/lib/update-manager/meta-release"

    def __init__(self, useDevelopmentRelease=False, useProposed=False):
        # check what uri to use
        if useDevelopmentRelease:
            self.METARELEASE_URI = self.METARELEASE_URI_UNSTABLE
        elif useProposed:
            self.METARELEASE_URI = self.METARELEASE_URI_PROPOSED

        # check if we can write to the global location, if not,
        # write to homedir
        try:
            open(self.METARELEASE_FILE,"a")
        except IOError, e:
            path = os.path.expanduser("~/.update-manager-core/")
            if not os.path.exists(path):
                os.mkdir(path)
            self.METARELEASE_FILE = os.path.join(path,"meta-release")
        self.metarelease_information = None
        self.downloading = True
        # information about the available dists
        self.new_dist = None
        self.no_longer_supported = None
        # we start the download thread here and we have a timeout
        t=thread.start_new_thread(self.download, ())
        #t=thread.start_new_thread(self.check, ())

    def dist_no_longer_supported(self, dist):
        """ virtual function that is called when the distro is no longer
            supported
        """
        self.no_longer_supported = dist
    def new_dist_available(self, dist):
        """ virtual function that is called when a new distro release
            is available
        """
        self.new_dist = dist

    def get_dist(self):
        " return the codename of the current runing distro "
        p = Popen(["lsb_release","-c","-s"],stdout=PIPE)
        res = p.wait()
        if res != 0:
            sys.stderr.write("lsb_release returned exitcode: %i\n" % res)
            return "unknown distribution"
        dist = string.strip(p.stdout.readline())
        return dist
    
    def parse(self):
        #print "parse"
        current_dist_name = self.get_dist()
        current_dist = None
        dists = []

        # parse the metarelease_information file
        index_tag = apt_pkg.ParseTagFile(self.metarelease_information)
        step_result = index_tag.Step()
        while step_result:
            if index_tag.Section.has_key("Dist"):
                name = index_tag.Section["Dist"]
                #print name
                rawdate = index_tag.Section["Date"]
                date = time.mktime(rfc822.parsedate(rawdate))
                supported = bool(index_tag.Section["Supported"])
                version = index_tag.Section["Version"]
                # add the information to a new date object
                dist = Dist(name, version, date,supported)
                if index_tag.Section.has_key("ReleaseNotes"):
                    dist.releaseNotesURI = index_tag.Section["ReleaseNotes"]
                if index_tag.Section.has_key("UpgradeTool"):
                    dist.upgradeTool =  index_tag.Section["UpgradeTool"]
                if index_tag.Section.has_key("UpgradeToolSignature"):
                    dist.upgradeToolSig =  index_tag.Section["UpgradeToolSignature"]
                dists.append(dist)
                if name == current_dist_name:
                    current_dist = dist 
            step_result = index_tag.Step()

        # first check if the current runing distro is in the meta-release
        # information. if not, we assume that we run on something not
        # supported and silently return
        if current_dist == None:
            print "current dist not found in meta-release file"
            return False

        # then see what we can upgrade to (only upgrade to supported dists)
        upgradable_to = ""
        for dist in dists:
            if dist.date > current_dist.date and dist.supported == True: 
                upgradable_to = dist
                #print "new dist: %s" % upgradable_to
                break

        # only warn if unsupported and a new dist is available (because 
        # the development version is also unsupported)
        if upgradable_to != "" and not current_dist.supported:
            self.dist_no_longer_supported(upgradabl_to)
        elif upgradable_to != "":
            self.new_dist_available(upgradable_to)

        # parsing done and sucessfully
        return True

    # the network thread that tries to fetch the meta-index file
    # can't touch the gui, runs as a thread
    def download(self):
        #print "download"
        lastmodified = 0
        req = urllib2.Request(self.METARELEASE_URI)
        # make sure that we always get the latest file (#107716)
        req.add_header("Cache-Control", "No-Cache")
        req.add_header("Pragma", "no-cache")
        if os.access(self.METARELEASE_FILE, os.W_OK):
            lastmodified = os.stat(self.METARELEASE_FILE).st_mtime
        if lastmodified > 0:
            req.add_header("If-Modified-Since", time.asctime(time.gmtime(lastmodified)))
        try:
            uri=urllib2.urlopen(req)
            # sometime there is a root owned meta-relase file
            # there, try to remove it so that we get it
            # with proper permissions
            if (os.path.exists(self.METARELEASE_FILE) and
                not os.access(self.METARELEASE_FILE,os.W_OK)):
                try:
                    os.unlink(self.METARELEASE_FILE)
                except OSError,e:
                    print "Can't unlink '%s' (%s)" % (self.METARELEASE_FILE,e)
            f=open(self.METARELEASE_FILE,"w+")
            for line in uri.readlines():
                f.write(line)
            f.flush()
            f.seek(0,0)
            self.metarelease_information=f
            uri.close()
        except urllib2.URLError:
            if os.path.exists(self.METARELEASE_FILE):
                self.metarelease_information=open(self.METARELEASE_FILE,"r")
        # now check the information we have
        if self.metarelease_information != None:
            self.parse()
        self.downloading = False