~mvo/update-manager/not-automatic

« back to all changes in this revision

Viewing changes to DistUpgrade/DistUpgradeAptCdrom.py

  • Committer: Michael Vogt
  • Date: 2008-10-08 10:31:21 UTC
  • mto: This revision was merged to the branch mainline in revision 1116.
  • Revision ID: michael.vogt@ubuntu.com-20081008103121-iu8ry6ju8kgdvk9y
initial version pure python implemenation (still incomplete) of apt-cdrom add

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# DistUpgradeAptCdrom.py 
 
2
#  
 
3
#  Copyright (c) 2008 Canonical
 
4
#  
 
5
#  Author: Michael Vogt <michael.vogt@ubuntu.com>
 
6
 
7
#  This program is free software; you can redistribute it and/or 
 
8
#  modify it under the terms of the GNU General Public License as 
 
9
#  published by the Free Software Foundation; either version 2 of the
 
10
#  License, or (at your option) any later version.
 
11
 
12
#  This program is distributed in the hope that it will be useful,
 
13
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
#  GNU General Public License for more details.
 
16
 
17
#  You should have received a copy of the GNU General Public License
 
18
#  along with this program; if not, write to the Free Software
 
19
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 
20
#  USA
 
21
 
 
22
import re
 
23
import os
 
24
import apt_pkg
 
25
import logging
 
26
import gzip
 
27
import shutil
 
28
 
 
29
from gettext import gettext as _
 
30
 
 
31
 
 
32
class AptCdromError(Exception):
 
33
    " base exception for apt cdrom errors "
 
34
    pass
 
35
 
 
36
class AptCdrom(object):
 
37
    " represents a apt cdrom object "
 
38
 
 
39
    def __init__(self, view, path):
 
40
        self.view = view
 
41
        self.cdrompath = path
 
42
        # the directories we found on disk with signatures, packages and i18n
 
43
        self.packagesdirs = set()
 
44
        self.sigdirs = set()
 
45
        self.i18ndirs = set()
 
46
 
 
47
    def restoreBackup(self, backup_ext):
 
48
        " restore the backup copy of the cdroms.list file (*not* sources.list)! "
 
49
        cdromstate = os.path.join(apt_pkg.Config.FindDir("Dir::State"),
 
50
                                  apt_pkg.Config.Find("Dir::State::cdroms"))
 
51
        if os.path.exists(cdromstate+backup_ext):
 
52
            shutil.copy(cdromstate+backup_ext, cdromstate)
 
53
        # mvo: we don't have to care about restoring the sources.list here because
 
54
        #      aptsources will do this for us anyway
 
55
        
 
56
 
 
57
    def _scanCD(self):
 
58
        """ 
 
59
        scan the CD for interessting files and return them as:
 
60
        (packagesfiles, signaturefiles, i18nfiles)
 
61
        """
 
62
        pass
 
63
 
 
64
    def _doAdd(self):
 
65
        " reimplement pkgCdrom::Add() in python "
 
66
        # os.walk() will not follow symlinks so we don't need
 
67
        # pkgCdrom::Score() and not dropRepeats() that deal with
 
68
        # killing the links
 
69
        for root, dirs, files in os.walk(self.cdrompath, topdown=True):
 
70
            if root.endswith("debian-installer"):
 
71
                del dirs[:]
 
72
                continue
 
73
            elif  ".aptignr" in files:
 
74
                continue
 
75
            elif "Packages" in files or "Packages.gz" in files:
 
76
                print "found Packages in ", root
 
77
                packagesdir.add(root)
 
78
            elif "Sources" in files or "Sources.gz" in files:
 
79
                logging.error("Sources entry found in %s but not supported" % root)
 
80
            elif "Release.gpg" in files:
 
81
                print "found Release{.gpg} ", root
 
82
                sigdir = set()
 
83
            elif "i18n" in dirs:
 
84
                print "found translations", root
 
85
                i18ndir = set()
 
86
            # there is nothing under pool but deb packages (no
 
87
            # indexfiles, so we skip that here
 
88
            elif os.path.split(root)[1] == ("pool"):
 
89
                del dirs[:]
 
90
        # now go over the packagesdirs and drop stuff that is not
 
91
        # our binary-$arch 
 
92
        arch = apt_pkg.Config.Find("APT::Architecture")
 
93
        for d in set(packagesdir):
 
94
            if "/binary-" in d and not arch in d:
 
95
                packagesdir.remove(d)
 
96
        if len(packagesdir) == 0:
 
97
            logging.error("no useable indexes found on CD, wrong ARCH?")
 
98
            raise AptCdromError, _("Unable to locate any package files, perhaps this is not a Ubuntu Disc or the wrong architecture?")
 
99
        # now generate a sources.list line
 
100
        info = os.path.join(self.cdrompath, ".disk","info")
 
101
        if os.path.exists(info):
 
102
            diskname = open(info).read()
 
103
            for special in ('"',']','[','_'):
 
104
                diskname = diskname.replace(special,'_')
 
105
        else:
 
106
            logging.error("no .disk/ directory found")
 
107
            return False
 
108
 
 
109
        # see apts indexcopy.cc:364 for details
 
110
        path = ""                                    
 
111
        dist = ""
 
112
        comps = []
 
113
        for d in packagesdir:
 
114
            # match(1) is the path, match(2) the dist
 
115
            # and match(3) the components
 
116
            m = re.match("(.*)/dists/([^/]*)/(.*)/binary-*", d)
 
117
            if not m:
 
118
                raise AptCdromError, _("Could not calculate sources.list entry")
 
119
            path = m.group(1)
 
120
            dist = m.group(2)
 
121
            comps.append(m.group(3))
 
122
        # entry to the sources.lisst
 
123
        pentry = "deb cdrom:[%s]/ %s %s" % (diskname, dist, " ".join(comps))
 
124
 
 
125
        # CopyPackages()
 
126
        for dir in packagesdir:
 
127
            fname = apt_pkg.URItoFileName("cdrom:[%s]/%sPackages" % (diskname,d[len(path)+1:]+"/"))
 
128
            outf = apt_pkg.Config.FindDir("Dir::State::lists")+fname
 
129
            inf = os.path.join(d,"Packages")
 
130
            if os.path.exists(inf):
 
131
                shutil.copy(inf,outf)
 
132
            elif os.path.exists(inf+".gz"):
 
133
                f=gzip.open(inf+".gz")
 
134
                out=open(outf,"w")
 
135
                # uncompress in 64k chunks
 
136
                while True:
 
137
                    s=f.read(64000)
 
138
                    out.write(s)
 
139
                    if s == "":
 
140
                        break
 
141
        # CopyAndVerify()
 
142
        
 
143
 
 
144
        # add CD to cdroms.list
 
145
        # update sources.list
 
146
        return True
 
147
 
 
148
    def add(self, backup_ext=None):
 
149
        " add a cdrom to apt's database "
 
150
        logging.debug("AptCdrom.add() called with '%s'", self.cdrompath)
 
151
        # do backup (if needed) of the cdroms.list file
 
152
        if backup_ext:
 
153
            cdromstate = os.path.join(apt_pkg.Config.FindDir("Dir::State"),
 
154
                                      apt_pkg.Config.Find("Dir::State::cdroms"))
 
155
            if os.path.exists(cdromstate):
 
156
                shutil.copy(cdromstate, cdromstate+backup_ext)
 
157
        # do the actual work
 
158
        apt_pkg.Config.Set("Acquire::cdrom::mount",self.cdrompath)
 
159
        apt_pkg.Config.Set("APT::CDROM::NoMount","true")
 
160
        cdrom = apt_pkg.GetCdrom()
 
161
        # FIXME: add cdrom progress here for the view
 
162
        progress = self.view.getCdromProgress()
 
163
        try:
 
164
            res = cdrom.Add(progress)
 
165
        except (SystemError, AptCdromError), e:
 
166
            logging.error("can't add cdrom: %s" % e)
 
167
            self.view.error(_("Failed to add the CD"),
 
168
                             _("There was a error adding the CD, the "
 
169
                               "upgrade will abort. Please report this as "
 
170
                               "a bug if this is a valid Ubuntu CD.\n\n"
 
171
                               "The error message was:\n'%s'") % e)
 
172
            return False
 
173
        logging.debug("AptCdrom.add() returned: %s" % res)
 
174
        return res
 
175
 
 
176
    def __nonzero__(self):
 
177
        """ helper to use this as 'if cdrom:' """
 
178
        return self.cdrompath is not None