initial commit
[ebuildfind.git] / commands / lib / layman / overlays / overlay.py
blobb9568b17cba06c5c6e8b379f41476a186cb19a96
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 #################################################################################
4 # LAYMAN OVERLAY BASE CLASS
5 #################################################################################
6 # File: overlay.py
8 # Base class for the different overlay types.
10 # Copyright:
11 # (c) 2005 - 2008 Gunnar Wrobel
12 # Distributed under the terms of the GNU General Public License v2
14 # Author(s):
15 # Gunnar Wrobel <wrobel@gentoo.org>
17 ''' Basic overlay class.'''
19 __version__ = "$Id: overlay.py 273 2006-12-30 15:54:50Z wrobel $"
21 #===============================================================================
23 # Dependencies
25 #-------------------------------------------------------------------------------
27 import sys, types, re, os, os.path, shutil, subprocess
29 from layman.utils import node_to_dict, dict_to_node, path
31 from layman.debug import OUT
33 #===============================================================================
35 # Class Overlay
37 #-------------------------------------------------------------------------------
39 class Overlay:
40 ''' Derive the real implementations from this.'''
42 type = 'None'
44 def __init__(self, xml, ignore = 0, quiet = False):
45 '''
46 >>> here = os.path.dirname(os.path.realpath(__file__))
47 >>> document = open(here + '/../tests/testfiles/global-overlays.xml').read()
48 >>> import xml.dom.minidom
49 >>> document = xml.dom.minidom.parseString(document)
50 >>> overlays = document.getElementsByTagName('overlay')
51 >>> a = Overlay(overlays[0])
52 >>> a.name
53 u'wrobel'
54 >>> a.is_official()
55 True
56 >>> a.src
57 u'https://overlays.gentoo.org/svn/dev/wrobel'
58 >>> a.contact
59 u'nobody@gentoo.org'
60 >>> a.description
61 u'Test'
62 >>> a.priority
64 >>> b = Overlay(overlays[1])
65 >>> b.is_official()
66 False
67 '''
68 self.quiet = quiet
70 self.data = node_to_dict(xml)
72 if '&name' in self.data.keys():
73 self.name = self.data['&name']
74 else:
75 raise Exception('Overlay is missing a "name" attribute!')
77 if '&src' in self.data.keys():
78 self.src = self.data['&src']
79 else:
80 raise Exception('Overlay "' + self.name + '" is missing a "src" '
81 'attribute!')
83 if '&contact' in self.data.keys():
84 self.contact = self.data['&contact']
85 else:
86 self.contact = ''
87 if not ignore:
88 raise Exception('Overlay "' + self.name + '" is missing a '
89 '"contact" attribute!')
90 elif ignore == 1:
91 OUT.warn('Overlay "' + self.name + '" is missing a '
92 '"contact" attribute!', 4)
94 if '<description>1' in self.data.keys():
95 self.description = self.data['<description>1']['@'].strip()
96 else:
97 self.description = ''
98 if not ignore:
99 raise Exception('Overlay "' + self.name + '" is missing a '
100 '"description" entry!')
101 elif ignore == 1:
102 OUT.warn('Overlay "' + self.name + '" is missing a '
103 '"description" entry!', 4)
105 if '&status' in self.data.keys():
106 self.status = self.data['&status']
107 else:
108 self.status = ''
110 if '&priority' in self.data.keys():
111 self.priority = int(self.data['&priority'])
112 else:
113 self.priority = 50
115 def set_priority(self, priority):
116 '''Set the priority of this overlay.'''
118 self.data['&priority'] = str(priority)
119 self.priority = int(priority)
121 def to_minidom(self, document):
122 '''Convert to xml.'''
124 return dict_to_node(self.data, document, 'overlay')
126 def add(self, base, quiet = False):
127 '''Add the overlay.'''
129 mdir = path([base, self.name])
131 if os.path.exists(mdir):
132 raise Exception('Directory ' + mdir + ' already exists. Will not ov'
133 'erwrite its contents!')
135 os.makedirs(mdir)
137 def sync(self, base, quiet = False):
138 '''Sync the overlay.'''
139 pass
141 def delete(self, base):
142 '''Delete the overlay.'''
143 mdir = path([base, self.name])
145 if not os.path.exists(mdir):
146 raise Exception('Directory ' + mdir + ' does not exist. Cannot remo'
147 've the overlay!')
149 shutil.rmtree(mdir)
151 def cmd(self, command):
152 '''Run a command.'''
154 OUT.info('Running command "' + command + '"...', 2)
156 if hasattr(sys.stdout,'encoding'):
157 enc = sys.stdout.encoding or sys.getfilesystemencoding()
158 if enc:
159 command = command.encode(enc)
161 if not self.quiet:
162 return os.system(command)
163 else:
164 cmd = subprocess.Popen([command], shell = True,
165 stdout = subprocess.PIPE,
166 stderr = subprocess.PIPE,
167 close_fds = True)
168 result = cmd.wait()
169 return result
171 def __str__(self):
173 >>> here = os.path.dirname(os.path.realpath(__file__))
174 >>> document = open(here + '/../tests/testfiles/global-overlays.xml').read()
175 >>> import xml.dom.minidom
176 >>> document = xml.dom.minidom.parseString(document)
177 >>> overlays = document.getElementsByTagName('overlay')
178 >>> a = Overlay(overlays[0])
179 >>> print str(a)
180 wrobel
181 ~~~~~~
182 Source : https://overlays.gentoo.org/svn/dev/wrobel
183 Contact : nobody@gentoo.org
184 Type : None; Priority: 10
185 <BLANKLINE>
186 Description:
187 Test
188 <BLANKLINE>
191 result = u''
193 result += self.name + u'\n' + (len(self.name) * u'~')
195 result += u'\nSource : ' + self.src
196 result += u'\nContact : ' + self.contact
197 result += u'\nType : ' + self.type
198 result += u'; Priority: ' + str(self.priority) + u'\n'
200 description = self.description
201 description = re.compile(u' +').sub(u' ', description)
202 description = re.compile(u'\n ').sub(u'\n', description)
203 result += u'\nDescription:'
204 result += u'\n '.join((u'\n' + description).split(u'\n'))
205 result += u'\n'
207 if '<link>1' in self.data.keys():
208 link = self.data['<link>1']['@'].strip()
209 link = re.compile(u' +').sub(u' ', link)
210 link = re.compile(u'\n ').sub(u'\n', link)
211 result += u'\nLink:\n'
212 result += u'\n '.join((u'\n' + link).split(u'\n'))
213 result += u'\n'
215 return result
217 def short_list(self, width = 0):
219 >>> here = os.path.dirname(os.path.realpath(__file__))
220 >>> document = open(here + '/../tests/testfiles/global-overlays.xml').read()
221 >>> import xml.dom.minidom
222 >>> document = xml.dom.minidom.parseString(document)
223 >>> overlays = document.getElementsByTagName('overlay')
224 >>> a = Overlay(overlays[0])
225 >>> print a.short_list(80)
226 wrobel [None ] (https://o.g.o/svn/dev/wrobel )
229 def pad(string, length):
230 '''Pad a string with spaces.'''
231 if len(string) <= length:
232 return string + ' ' * (length - len(string))
233 else:
234 return string[:length - 3] + '...'
236 def terminal_width():
237 '''Determine width of terminal window.'''
238 try:
239 width = int(os.environ['COLUMNS'])
240 if width > 0:
241 return width
242 except:
243 pass
244 try:
245 import struct, fcntl, termios
246 query = struct.pack('HHHH', 0, 0, 0, 0)
247 response = fcntl.ioctl(1, termios.TIOCGWINSZ, query)
248 width = struct.unpack('HHHH', response)[1]
249 if width > 0:
250 return width
251 except:
252 pass
253 return 80
255 name = pad(self.name, 25)
256 mtype = ' [' + pad(self.type, 10) + ']'
257 if not width:
258 width = terminal_width()
259 srclen = width - 43
260 source = self.src
261 if len(source) > srclen:
262 source = source.replace("overlays.gentoo.org", "o.g.o")
263 source = ' (' + pad(source, srclen) + ')'
265 return name + mtype + source
267 def supported(self, binaries = []):
268 '''Is the overlay type supported?'''
270 if binaries:
271 for mpath, mtype, package in binaries:
272 if not os.path.exists(mpath):
273 raise Exception('Binary ' + mpath + ' seems to be missing!'
274 ' Overlay type "' + mtype + '" not support'
275 'ed. Did you emerge ' + package + '?')
277 return True
279 def is_supported(self):
280 '''Is the overlay type supported?'''
282 try:
283 self.supported()
284 return True
285 except Exception, error:
286 return False
288 def is_official(self):
289 '''Is the overlay official?'''
291 return self.status == 'official'
293 #================================================================================
295 # Testing
297 #--------------------------------------------------------------------------------
299 if __name__ == '__main__':
300 import doctest, sys
301 doctest.testmod(sys.modules[__name__])