~ubuntu-core-dev/software-properties/main

« back to all changes in this revision

Viewing changes to SoftwareProperties/aptsources.py

  • Committer: Michael Vogt
  • Date: 2005-11-15 13:18:07 UTC
  • Revision ID: egon@top-20051115131807-12fada324eb74180
* initial revision (after accidently killing it)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# aptsource.py.in - parse sources.list
 
2
#  
 
3
#  Copyright (c) 2004 Canonical
 
4
#                2004 Michiel Sikkes
 
5
#  
 
6
#  Author: Michiel Sikkes <michiel@eyesopened.nl>
 
7
#          Michael Vogt <mvo@debian.org>
 
8
 
9
#  This program is free software; you can redistribute it and/or 
 
10
#  modify it under the terms of the GNU General Public License as 
 
11
#  published by the Free Software Foundation; either version 2 of the
 
12
#  License, or (at your option) any later version.
 
13
 
14
#  This program is distributed in the hope that it will be useful,
 
15
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
#  GNU General Public License for more details.
 
18
 
19
#  You should have received a copy of the GNU General Public License
 
20
#  along with this program; if not, write to the Free Software
 
21
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 
22
#  USA
 
23
 
 
24
import string
 
25
import gettext
 
26
import re
 
27
import apt_pkg
 
28
import glob
 
29
 
 
30
from DistInfo import DistInfo
 
31
 
 
32
# actual source.list entries
 
33
class SourceEntry:
 
34
 
 
35
  def __init__(self, line,file):
 
36
    self.invalid = False
 
37
    self.disabled = False
 
38
    self.type = ""
 
39
    self.uri = ""
 
40
    self.dist = ""
 
41
    self.comps = []
 
42
    self.comment = ""
 
43
    self.line = line
 
44
    self.file = file
 
45
    self.parse(line)
 
46
 
 
47
  # works mostely like split but takes [] into account
 
48
  def mysplit(self, line):
 
49
    line = string.strip(line)
 
50
    pieces = []
 
51
    tmp = ""
 
52
    # we are inside a [..] block
 
53
    p_found = False
 
54
    space_found = False
 
55
    for i in range(len(line)):
 
56
      if line[i] == "[":
 
57
        p_found=True
 
58
        tmp += line[i]
 
59
      elif line[i] == "]":
 
60
        p_found=False
 
61
        tmp += line[i]
 
62
      elif space_found and not line[i].isspace(): # we skip one or more space
 
63
        space_found = False
 
64
        pieces.append(tmp)
 
65
        tmp = line[i]
 
66
      elif line[i].isspace() and not p_found:     # found a whitespace
 
67
        space_found = True
 
68
      else:
 
69
        tmp += line[i]
 
70
    # append last piece
 
71
    if len(tmp) > 0:
 
72
      pieces.append(tmp)
 
73
    return pieces
 
74
 
 
75
 
 
76
  # parse a given source line and split it into the fields we need
 
77
  def parse(self,line):
 
78
    line  = string.strip(self.line)
 
79
    #print line
 
80
    # check if the source is enabled/disabled
 
81
    if line == "" or line == "#": # empty line
 
82
      self.invalid = True
 
83
      return
 
84
    if line[0] == "#":
 
85
      self.disabled = True
 
86
      pieces = string.split(line[1:])
 
87
      # if it looks not like a disabled deb line return 
 
88
      if not (pieces[0] == "deb" or pieces[0] == "deb-src"):
 
89
        self.invalid = True
 
90
        return
 
91
      else:
 
92
        line = line[1:]
 
93
    # check for another "#" in the line (this is treated as a comment)
 
94
    i = line.find("#")
 
95
    if i > 0:
 
96
      self.comment = line[i+1:]
 
97
      line = line[:i]
 
98
    # source is ok, split it and see what we have
 
99
    pieces = self.mysplit(line)
 
100
    # Type, deb or deb-src
 
101
    self.type = string.strip(pieces[0])
 
102
    # URI
 
103
    self.uri = string.strip(pieces[1])
 
104
    # distro and components (optional)
 
105
    # Directory or distro
 
106
    self.dist = string.strip(pieces[2])
 
107
    if len(pieces) > 3:
 
108
      # List of components
 
109
      self.comps = pieces[3:]
 
110
    else:
 
111
      self.comps = []
 
112
 
 
113
    #print self.__dict__
 
114
 
 
115
 
 
116
  # set enabled/disabled
 
117
  def set_enabled(self, new_value):
 
118
    self.disabled = not new_value
 
119
    # enable, remove all "#" from the start of the line
 
120
    if new_value == True:
 
121
      i=0
 
122
      self.line = string.lstrip(self.line)
 
123
      while self.line[i] == "#":
 
124
        i += 1
 
125
      self.line = self.line[i:]
 
126
    else:
 
127
      # disabled, add a "#" 
 
128
      if string.strip(self.line)[0] != "#":
 
129
        self.line = "#" + self.line
 
130
 
 
131
  def str(self):
 
132
    return self.line
 
133
 
 
134
 
 
135
def uniq(s):
 
136
  """ simple (and not efficient) way to return uniq list """
 
137
  u = []
 
138
  for x in s:
 
139
    if x not in u:
 
140
      u.append(x)
 
141
  return u 
 
142
  
 
143
 
 
144
# the SourceList file as a class
 
145
class SourcesList:
 
146
  def __init__(self):
 
147
    self.list = []      # of Type SourceEntries
 
148
    # read sources.list
 
149
    dir = apt_pkg.Config.FindDir("Dir::Etc")
 
150
    file = apt_pkg.Config.Find("Dir::Etc::sourcelist")
 
151
    self.load(dir+file)
 
152
    # read sources.list.d
 
153
    partsdir = apt_pkg.Config.FindDir("Dir::Etc::sourceparts")
 
154
    for file in glob.glob("%s/*.list" % partsdir):
 
155
      self.load(file)
 
156
 
 
157
  def is_mirror(self, add_uri, orig_uri):
 
158
    """check if the given add_url is idential or a mirror of orig_uri
 
159
       e.g. add_uri = archive.ubuntu.com
 
160
            orig_uri = de.archive.ubuntu.com
 
161
            -> True
 
162
    """
 
163
    # remove traling spaces and "/"
 
164
    add_uri = add_uri.rstrip("/ ")
 
165
    orig_uri = orig_uri.rstrip("/ ")
 
166
    # uri is identical
 
167
    if add_uri == orig_uri:
 
168
      #print "Identical"
 
169
      return True
 
170
    # add uri is a master site and orig_uri has the from "XX.mastersite"
 
171
    # (e.g. de.archive.ubuntu.com)
 
172
    try:
 
173
      add_srv = add_uri.split("//")[1]
 
174
      orig_srv = orig_uri.split("//")[1]
 
175
      #print "%s == %s " % (add_srv, orig_srv)
 
176
    except IndexError: # ok, somethings wrong here
 
177
      #print "IndexError"
 
178
      return False
 
179
    if add_srv == orig_srv[3:]:
 
180
      #print "Mirror"
 
181
      return True
 
182
    return False
 
183
 
 
184
  def add(self, type, uri, dist, comps, comment="", pos=-1):
 
185
    # if there is a repo with the same (type, uri, dist) just add the
 
186
    # components
 
187
    for i in self.list:
 
188
      if i.type == type and self.is_mirror(uri,i.uri) and i.dist == dist:
 
189
        comps = uniq(i.comps + comps)
 
190
        # set to the old position and preserve comment
 
191
        comment = i.comment
 
192
        pos = self.list.index(i)
 
193
        self.list.remove(i)
 
194
    line = "%s %s %s" % (type,uri,dist)
 
195
    for c in comps:
 
196
      line = line + " " + c;
 
197
    if comment != "":
 
198
      line = "%s #%s\n" %(line,comment)
 
199
    line = line + "\n"
 
200
    self.list.insert(pos, SourceEntry(line))
 
201
 
 
202
  def remove(self, source_entry):
 
203
    self.list.remove(source_entry)
 
204
 
 
205
  def load(self,file):
 
206
    f = open(file, "r")
 
207
    lines = f.readlines()
 
208
    for line in lines:
 
209
      source = SourceEntry(line,file)
 
210
      self.list.append(source)
 
211
    f.close()
 
212
 
 
213
  def save(self,file):
 
214
    files = {}
 
215
    for source in self.list:
 
216
      if not files.has_key(source.file):
 
217
        files[source.file]=open(source.file,"w")
 
218
      files[source.file].write(source.str())
 
219
    for f in files:
 
220
      files[f].close()
 
221
 
 
222
 
 
223
# templates for the add dialog
 
224
class SourceEntryTemplate(SourceEntry):
 
225
  def __init__(self,a_type,uri,dist,description,comps):
 
226
    self.comps = []
 
227
    self.comps_descriptions = []
 
228
    self.type = a_type
 
229
    self.uri = uri
 
230
    self.dist = dist
 
231
    self.description = description
 
232
    self.comps = comps
 
233
 
 
234
class SourceCompTemplate:
 
235
  def __init__(self, name, description, on_by_default):
 
236
    self.name = name
 
237
    self.description = description
 
238
    self.on_by_default = on_by_default
 
239
 
 
240
class SourceEntryTemplates:
 
241
  def __init__(self):
 
242
    _ = gettext.gettext
 
243
    self.templates = []
 
244
 
 
245
    dinfo = DistInfo ()
 
246
 
 
247
    for suite in dinfo.suites:
 
248
      comps = []
 
249
      for comp in suite.components:
 
250
        comps.append(SourceCompTemplate(comp.name, _(comp.description),
 
251
                                        comp.enabled))
 
252
      self.templates.append (SourceEntryTemplate(suite.repository_type,
 
253
                                                 suite.base_uri,
 
254
                                                 suite.name,
 
255
                                                 suite.description,
 
256
                                                 comps))
 
257
 
 
258
# matcher class to make a source entry look nice
 
259
# lots of predefined matchers to make it i18n/gettext friendly
 
260
class SourceEntryMatcher:
 
261
  class MatchType:
 
262
    def __init__(self, a_type,a_descr):
 
263
      self.type = a_type
 
264
      self.description = a_descr
 
265
  
 
266
  class MatchDist:
 
267
    def __init__(self,a_uri,a_dist, a_descr,l_comps, l_comps_descr):
 
268
      self.uri = a_uri
 
269
      self.dist = a_dist
 
270
      self.description = a_descr
 
271
      self.comps = l_comps
 
272
      self.comps_descriptions = l_comps_descr
 
273
 
 
274
  def __init__(self):
 
275
    _ = gettext.gettext
 
276
    self.type_list = []
 
277
    self.type_list.append(self.MatchType("^deb$",_("Binary")))
 
278
    self.type_list.append(self.MatchType("^deb-src$",_("Source")))
 
279
 
 
280
    self.dist_list = []
 
281
 
 
282
    ubuntu_comps = ["^main$","^restricted$","^universe$","^multiverse$"]
 
283
    ubuntu_comps_descr = [_("Officially supported"),
 
284
                          _("Restricted copyright"),
 
285
                          _("Community maintained (Universe)"),
 
286
                          _("Non-free (Multiverse)")]
 
287
    # CDs
 
288
    self.dist_list.append(self.MatchDist("cdrom:\[Ubuntu.*5.10",
 
289
                                         ".*",
 
290
                                        _("CD disk with Ubuntu 5.10 \"Breezy Badger\""),
 
291
                                         ubuntu_comps, ubuntu_comps_descr))
 
292
    self.dist_list.append(self.MatchDist("cdrom:\[Ubuntu.*5.04",
 
293
                                         ".*",
 
294
                                        _("CD disk with Ubuntu 5.04 \"Hoary Hedgehog\""),
 
295
                                         ubuntu_comps, ubuntu_comps_descr))
 
296
    self.dist_list.append(self.MatchDist("cdrom:\[Ubuntu.*4.10",
 
297
                                         ".*",
 
298
                                        _("CD disk with Ubuntu 4.10 \"Warty Warthog\""),
 
299
                                         ubuntu_comps, ubuntu_comps_descr))
 
300
    # URIs
 
301
    # Warty
 
302
    self.dist_list.append(self.MatchDist(".*archive.ubuntu.com/ubuntu",
 
303
                                         "^warty$",
 
304
                                         "Ubuntu 4.10 \"Warty Warthog\"",
 
305
                                         ubuntu_comps, ubuntu_comps_descr))
 
306
    self.dist_list.append(self.MatchDist(".*security.ubuntu.com/ubuntu",
 
307
                                         "^warty-security$",
 
308
                                         _("Ubuntu 4.10 Security Updates"),
 
309
                                         ubuntu_comps, ubuntu_comps_descr))
 
310
    self.dist_list.append(self.MatchDist(".*archive.ubuntu.com/ubuntu",
 
311
                                         "^warty-security$",
 
312
                                         _("Ubuntu 4.10 Security Updates"),
 
313
                                         ubuntu_comps, ubuntu_comps_descr))
 
314
    self.dist_list.append(self.MatchDist(".*archive.ubuntu.com/ubuntu",
 
315
                                         "^warty-updates$",
 
316
                                         _("Ubuntu 4.10 Updates"),
 
317
                                         ubuntu_comps, ubuntu_comps_descr))
 
318
    # Hoary
 
319
    self.dist_list.append(self.MatchDist(".*archive.ubuntu.com/ubuntu",
 
320
                                         "^hoary-security$",
 
321
                                         _("Ubuntu 5.04 Security Updates"),
 
322
                                         ubuntu_comps, ubuntu_comps_descr))
 
323
    self.dist_list.append(self.MatchDist(".*security.ubuntu.com/ubuntu",
 
324
                                         "^hoary-security$",
 
325
                                         _("Ubuntu 5.04 Security Updates"),
 
326
                                         ubuntu_comps, ubuntu_comps_descr))
 
327
    self.dist_list.append(self.MatchDist(".*archive.ubuntu.com/ubuntu",
 
328
                                         "^hoary$",
 
329
                                         "Ubuntu 5.04 \"Hoary Hedgehog\"",
 
330
                                         ubuntu_comps, ubuntu_comps_descr))
 
331
    self.dist_list.append(self.MatchDist(".*archive.ubuntu.com/ubuntu",
 
332
                                         "^hoary-updates$",
 
333
                                         _("Ubuntu 5.04 Updates"),
 
334
                                         ubuntu_comps, ubuntu_comps_descr))
 
335
    # Breezy
 
336
    self.dist_list.append(self.MatchDist(".*archive.ubuntu.com/ubuntu",
 
337
                                         "^breezy-security$",
 
338
                                         _("Ubuntu 5.10 Security Updates"),
 
339
                                         ubuntu_comps, ubuntu_comps_descr))
 
340
    self.dist_list.append(self.MatchDist(".*security.ubuntu.com/ubuntu",
 
341
                                         "^breezy-security$",
 
342
                                         _("Ubuntu 5.10 Security Updates"),
 
343
                                         ubuntu_comps, ubuntu_comps_descr))
 
344
    self.dist_list.append(self.MatchDist(".*archive.ubuntu.com/ubuntu",
 
345
                                         "^breezy$",
 
346
                                         "Ubuntu 5.10 \"Breezy Badger\"",
 
347
                                         ubuntu_comps, ubuntu_comps_descr))
 
348
    self.dist_list.append(self.MatchDist(".*archive.ubuntu.com/ubuntu",
 
349
                                         "^breezy-updates$",
 
350
                                         _("Ubuntu 5.10 Updates"),
 
351
                                         ubuntu_comps, ubuntu_comps_descr))
 
352
 
 
353
 
 
354
    # DEBIAN
 
355
    debian_comps =  ["^main$","^contrib$","^non-free$","^non-US$"]
 
356
    debian_comps_descr = [_("Officially supported"),
 
357
                          _("Contributed software"),
 
358
                          _("Non-free software"),
 
359
                          _("US export restricted software")
 
360
                          ]
 
361
 
 
362
    # dists by name
 
363
    self.dist_list.append(self.MatchDist(".*debian.org/debian",
 
364
                                         "^sarge$",
 
365
                                         _("Debian 3.1 \"Sarge\""),
 
366
                                         debian_comps, debian_comps_descr))
 
367
    self.dist_list.append(self.MatchDist(".*debian.org/debian",
 
368
                                         "^woody$",
 
369
                                         _("Debian 3.0 \"Woody\""),
 
370
                                         debian_comps, debian_comps_descr))
 
371
    # securtiy
 
372
    self.dist_list.append(self.MatchDist(".*security.debian.org",
 
373
                                         "^stable.*$",
 
374
                                         _("Debian Stable Security Updates"),
 
375
                                         debian_comps, debian_comps_descr))
 
376
    # dists by status
 
377
    self.dist_list.append(self.MatchDist(".*debian.org/debian",
 
378
                                         "^stable$",
 
379
                                         _("Debian Stable"),
 
380
                                         debian_comps, debian_comps_descr))
 
381
    self.dist_list.append(self.MatchDist(".*debian.org/debian",
 
382
                                         "^testing$",
 
383
                                         _("Debian Testing"),
 
384
                                         debian_comps, debian_comps_descr))
 
385
    self.dist_list.append(self.MatchDist(".*debian.org/debian",
 
386
                                         "^unstable$",
 
387
                                         _("Debian Unstable \"Sid\""),
 
388
                                         debian_comps, debian_comps_descr))
 
389
 
 
390
    # non-us
 
391
    self.dist_list.append(self.MatchDist(".*debian.org/debian-non-US",
 
392
                                         "^stable.*$",
 
393
                                         _("Debian Non-US (Stable)"),
 
394
                                         debian_comps, debian_comps_descr))
 
395
    self.dist_list.append(self.MatchDist(".*debian.org/debian-non-US",
 
396
                                         "^testing.*$",
 
397
                                         _("Debian Non-US (Testing)"),
 
398
                                         debian_comps, debian_comps_descr))
 
399
    self.dist_list.append(self.MatchDist(".*debian.org/debian-non-US",
 
400
                                         "^unstable.*$",
 
401
                                         _("Debian Non-US (Unstable)"),
 
402
                                         debian_comps, debian_comps_descr))
 
403
 
 
404
 
 
405
 
 
406
  
 
407
  def match(self,source):
 
408
    _ = gettext.gettext
 
409
    # some sane defaults first
 
410
    type_description = source.type
 
411
    dist_description = source.uri + " " + source.dist
 
412
    comp_description = ""
 
413
    for c in source.comps:
 
414
      comp_description = comp_description + " " + c 
 
415
    
 
416
    for t in self.type_list:
 
417
      if re.match(t.type, source.type):
 
418
        type_description = _(t.description)
 
419
        break
 
420
 
 
421
    for d in self.dist_list:
 
422
      #print "'%s'" %source.uri
 
423
      if re.match(d.uri, source.uri) and re.match(d.dist,source.dist):
 
424
        dist_description = d.description
 
425
        comp_description = ""
 
426
        for c in source.comps:
 
427
          found = False
 
428
          for i in range(len(d.comps)):
 
429
            if re.match(d.comps[i], c):
 
430
              comp_description = comp_description+"\n"+d.comps_descriptions[i]
 
431
              found = True
 
432
          if found == False:
 
433
            comp_description = comp_description+" "+c
 
434
        break
 
435
      
 
436
      
 
437
    return (type_description,dist_description,comp_description)