예제 #1
0
    def __init__(self, config, paths=None, ignore=0,
           ignore_init_read_errors=False, allow_missing=False):

        self.config = config
        self.db_type = config['db_type']
        self.ignore = ignore
        self.ignore_init_read_errors = ignore_init_read_errors
        self.mod_ctl = Modules(path=MOD_PATH,
                               namepath='layman.db_modules',
                               output=config['output'])
        self.output = config['output']
        self.overlays = {}
        self.paths = paths

        path_found = False

        self.output.debug('Initializing overlay list handler', 8)

        if isinstance(self.db_type, STR):
            self.db_type = [x.strip() for x in self.db_type.split(',')]

        if len(self.db_type) > 1:
            msg = 'DbBase; warning, multiple instances of "db_type" found:'\
                  ' %(db_types)s.\nDefaulting to: %(db_type)s'\
                  % {'db_types': self.db_type, 'db_type': self.db_type[0]}
            self.output.warn(msg)

        self.db_type = self.db_type[0] + '_db'

        for path in self.paths:
            if not os.path.exists(path):
                continue

            success = self.read_db(path)
            if not success:
                msg = 'DbBase; error, Failed to read database at "%(path)s"\n'\
                      'Hint: If you manually set db_type. Please reset it and '\
                      'let layman-updater\nmigrate it. Otherwise layman\'s '\
                      'database is not initialized, nor populated\nwith any '\
                      'existing data.\nRun the following: "layman-updater -m '\
                      '<db_type>"' % {'path': path}
                self.output.error(msg)
                sys.exit(-1)

            path_found = True

        if not path_found and not allow_missing:
            msg = 'Warning: an installed db file was not found at: %(path)s'\
                   % {'path': str(self.paths)}
            self.output.warn(msg)
예제 #2
0
    def __init__(self, config, json=None, ovl_dict=None, xml=None, ignore=0):
        self.config = config
        self.output = config['output']
        self.module_controller = Modules(path=MOD_PATH,
                                         namepath='layman.overlays.modules',
                                         output=self.output)
        self._encoding_ = get_encoding(self.output)

        if xml is not None:
            self.from_xml(xml, ignore)
        elif ovl_dict is not None:
            self.from_dict(ovl_dict, ignore)
        elif json is not None:
            self.from_json(json, ignore)
예제 #3
0
    def __init__(self, config, overlays):

        #TODO add custom_conf_type support
        self.config = config
        self.conf_types = config['conf_type']
        self.output = config['output']
        self.overlays = overlays
        self.module_controller = Modules(path=MOD_PATH,
                                         namepath='layman.config_modules',
                                         output=self.output)

        if isinstance(self.conf_types, STR):
            self.conf_types = [x.strip() for x in self.conf_types.split(',')]

        if not self.conf_types and self.config['require_repoconfig']:
            self.output.error('No Repo configuration type found, but' +
                              '\nis required in order to continue...')
예제 #4
0
파일: overlay.py 프로젝트: wking/layman
    def __init__(self, config, xml=None, ovl_dict=None,
        ignore = 0):
        self.config = config
        self.output = config['output']
        self.module_controller = Modules(path=MOD_PATH,
                                         namepath='layman.overlays.modules',
                                         output=self.output)
        self._encoding_ = get_encoding(self.output)

        if xml is not None:
            self.from_xml(xml, ignore)
        elif ovl_dict is not None:
            self.from_dict(ovl_dict, ignore)
예제 #5
0
    def __init__(self, config, overlays):

        #TODO add custom_conf_type support
        self.config = config
        self.conf_types = config['conf_type']
        self.output = config['output']
        self.overlays = overlays
        self.module_controller = Modules(path=MOD_PATH,
                                         namepath='layman.config_modules',
                                         output=self.output)

        if isinstance(self.conf_types, STR):
            self.conf_types = re.split(',\s+', self.conf_types)

        if not self.conf_types and self.config['require_repoconfig']:
            self.output.error('No Repo configuration type found, but'
                + '\nis required in order to continue...')
예제 #6
0
파일: dbbase.py 프로젝트: fatman2021/layman
    def __init__(self, config, paths=None, ignore=0,
           ignore_init_read_errors=False, allow_missing=False):

        self.config = config
        self.db_type = config['db_type']
        self.ignore = ignore
        self.ignore_init_read_errors = ignore_init_read_errors
        self.mod_ctl = Modules(path=MOD_PATH,
                               namepath='layman.db_modules',
                               output=config['output'])
        self.output = config['output']
        self.overlays = {}
        self.paths = paths

        path_found = False

        self.output.debug('Initializing overlay list handler', 8)

        if isinstance(self.db_type, STR):
            self.db_type = [x.strip() for x in self.db_type.split(',')]

        if len(self.db_type) > 1:
            msg = 'DbBase; warning, multiple instances of "db_type" found:'\
                  ' %(db_types)s.\nDefaulting to: %(db_type)s'\
                  % {'db_types': self.db_type, 'db_type': self.db_type[0]}
            self.output.warn(msg)

        self.db_type = self.db_type[0]

        for path in self.paths:
            if not os.path.exists(path):
                continue

            self.read_db(path)
            path_found = True

        if not path_found and not allow_missing:
            msg = 'Warning: an installed db file was not found at: %(path)s'\
                   % {'path': str(self.paths)}
            self.output.warn(msg)
예제 #7
0
class Overlay(object):
    ''' Derive the real implementations from this.'''
    def __init__(self, config, json=None, ovl_dict=None, xml=None, ignore=0):
        self.config = config
        self.output = config['output']
        self.module_controller = Modules(path=MOD_PATH,
                                         namepath='layman.overlays.modules',
                                         output=self.output)
        self._encoding_ = get_encoding(self.output)

        if xml is not None:
            self.from_xml(xml, ignore)
        elif ovl_dict is not None:
            self.from_dict(ovl_dict, ignore)
        elif json is not None:
            self.from_json(json, ignore)

    def __eq__(self, other):
        for i in ('descriptions', 'homepage', 'name', 'owners', 'priority',
                  'status'):
            if getattr(self, i) != getattr(other, i):
                return False
        for i in self.sources + other.sources:
            if not i in self.sources:
                return False
            if not i in other.sources:
                return False
        return True

    def __ne__(self, other):
        return not self.__eq__(other)

    def add(self, base):
        res = 1
        first_s = True

        self.sources = self.filter_protocols(self.sources)
        if not self.sources:
            msg = 'Overlay.add() error: overlay "%(name)s" does not support '\
                  ' the given\nprotocol(s) %(protocol)s and cannot be '\
                  'installed.'\
                  % {'name': self.name,
                     'protocol': str(self.config['protocol_filter'])}
            self.output.error(msg)
            return 1

        for s in self.sources:
            if not first_s:
                self.output.info('\nTrying next source of listed sources...',
                                 4)
            try:
                res = s.add(base)
                if res == 0:
                    # Worked, throw other sources away
                    self.sources = [s]
                    break
            except Exception as error:
                self.output.warn(str(error), 4)
            first_s = False
        return res

    def delete(self, base):
        assert len(self.sources) == 1
        return self.sources[0].delete(base)

    def filter_protocols(self, sources):
        '''
        Filters any protocols not specified in self.config['protocol_filter']
        from the overlay's sources.
        '''
        _sources = []
        if not self.config['protocol_filter']:
            return sources

        for source in sources:
            for protocol in self.config['protocol_filter']:
                protocol = protocol.lower()
                #re.search considers "\+" as the literal "+".
                if protocol == 'git+ssh':
                    protocol = 'git\+ssh'
                protocol += '://'
                if re.search('^' + protocol, source.src):
                    _sources.append(source)

        return _sources

    def from_dict(self, overlay, ignore):
        '''
        Process an overlay dictionary definition
        '''
        msg = 'Overlay from_dict(); overlay %(ovl)s' % {'ovl': str(overlay)}
        self.output.debug(msg, 6)

        _name = overlay['name']
        if _name != None:
            self.name = encode(_name)
        else:
            msg = 'Overlay from_dict(), "name" entry missing from dictionary!'
            raise Exception(msg)

        if 'source' in overlay:
            _sources = overlay['source']
        else:
            _sources = None

        if _sources == None:
            msg = 'Overlay from_dict(), "%(name)s" is missing a "source" '\
                  'entry!' % {'name': self.name}
            raise Exception(msg)

        def create_dict_overlay_source(source_):
            _src, _type, _sub = source_
            self.ovl_type = _type
            try:
                _class = self.module_controller.get_class(_type)
            except InvalidModuleName:
                _class = self.module_controller.get_class('stub')

            _location = encode(_src)
            if _sub:
                self.branch = encode(_sub)
            else:
                self.branch = None

            return _class(parent=self,
                          config=self.config,
                          _location=_location,
                          ignore=ignore)

        self.sources = [create_dict_overlay_source(e) for e in _sources]

        self.owners = []

        if 'owner' in overlay:
            for _owner in overlay['owner']:
                owner = {}
                if 'name' in _owner and _owner['name']:
                    owner['name'] = encode(_owner['name'])
                else:
                    owner['name'] = None

                if 'email' in _owner:
                    owner['email'] = encode(_owner['email'])
                else:
                    owner['email'] = None
                    msg = 'Overlay from_dict(), "%(name)s" is missing an '\
                          '"owner.email" entry!' % {'name': self.name}
                    if not ignore:
                        raise Exception(msg)
                    elif ignore == 1:
                        self.output.warn(msg, 4)

                self.owners.append(owner)

        if 'description' in overlay:
            self.descriptions = []
            _descs = overlay['description']
            for d in _descs:
                d = WHITESPACE_REGEX.sub(' ', d)
                self.descriptions.append(encode(d))
        else:
            self.descriptions = ['']
            if not ignore:
                raise Exception('Overlay from_dict(), "' + self.name +
                                '" is missing a "description" entry!')
            elif ignore == 1:
                self.output.warn(
                    'Overlay from_dict(), "' + self.name +
                    '" is missing a "description" entry!', 4)

        if 'status' in overlay:
            self.status = encode(overlay['status'])
        else:
            self.status = None

        self.quality = 'experimental'
        if 'quality' in overlay:
            if overlay['quality'] in set(QUALITY_LEVELS):
                self.quality = encode(overlay['quality'])

        if 'priority' in overlay:
            self.priority = int(overlay['priority'])
        else:
            self.priority = 50

        if 'license' in overlay:
            self.license = encode(overlay['license'])
        else:
            self.license = None

        if 'homepage' in overlay:
            self.homepage = encode(overlay['homepage'])
        else:
            self.homepage = None

        if 'feed' in overlay:
            self.feeds = [encode(e) \
                for e in overlay['feed']]
        else:
            self.feeds = None

        if 'irc' in overlay:
            self.irc = encode(overlay['irc'])
        else:
            self.irc = None

        # end of from_dict

    def from_json(self, json, ignore):
        '''
        Process a json overlay definition
        '''
        msg = 'Overlay from_json(); overlay %(ovl)s' % {'ovl': str(json)}
        self.output.debug(msg, 6)

        _name = json['name']
        if _name != None:
            self.name = encode(_name)
        else:
            msg = 'Overlay from_json(), "name" entry missing from json!'
            raise Exception(msg)

        if 'source' in json:
            _sources = json['source']
        else:
            _sources = None

        if _sources == None:
            msg = 'Overlay from_json(), "%(name)s" is missing a "source" '\
                  'entry!' % {'name': self.name}
            raise Exception(msg)

        def create_json_overlay_source(source_):
            _src = source_['#text']
            _type = source_['@type']
            if '@branch' in source_:
                _sub = source_['@branch']
            else:
                _sub = ''

            self.ovl_type = _type

            try:
                _class = self.module_controller.get_class(_type)
            except InvalidModuleName:
                _class = self.module_controller.get_class('stub')

            _location = encode(_src)
            if _sub:
                self.branch = encode(_sub)
            else:
                self.branch = None

            return _class(parent=self,
                          config=self.config,
                          _location=_location,
                          ignore=ignore)

        self.sources = [create_json_overlay_source(e) for e in _sources]

        _owners = json['owner']
        self.owners = []

        for _owner in _owners:
            owner = {}
            if 'name' in _owner:
                owner['name'] = encode(_owner['name'])
            else:
                owner['name'] = None
            if 'email' in _owner:
                owner['email'] = encode(_owner['email'])
            else:
                owner['email'] = None
                msg = 'Overlay from_json(), "%(name)s" is missing an '\
                      '"owner.email" entry!' % {'name': self.name}
                if not ignore:
                    raise Exception(msg)
                elif ignore == 1:
                    self.output.warn(msg, 4)
            self.owners.append(owner)

        if 'description' in json:
            self.descriptions = []
            _descs = json['description']
            for d in _descs:
                d = WHITESPACE_REGEX.sub(' ', d)
                self.descriptions.append(encode(d))
        else:
            self.descriptions = ['']
            msg = 'Overlay from_json() "%(name)s" is missing description'\
                  'entry!' % {'name': self.name}
            if not ignore:
                raise Exception(msg)
            elif ignore == 1:
                self.output.warn(msg, 4)

        if '@status' in json:
            self.status = encode(json['@status'])
        else:
            self.status = None

        self.quality = 'experimental'
        if '@quality' in json:
            if json['@quality'] in set(QUALITY_LEVELS):
                self.quality = encode(json['@quality'])

        if '@priority' in json:
            self.priority = int(json['@priority'])
        else:
            self.priority = 50

        if '@license' in json:
            self.license = encode(json['@license'])
        else:
            self.license = None

        if 'homepage' in json:
            self.homepage = encode(json['homepage'])
        else:
            self.homepage = None

        if 'feed' in json:
            self.feeds = [encode(e) \
                for e in json['feed']]
        else:
            self.feeds = None

        if 'irc' in json:
            self.irc = encode(json['irc'])
        else:
            self.irc = None

        # end of from_json()

    def from_xml(self, xml, ignore):
        '''
        Process an xml overlay definition
        '''
        def strip_text(node):
            res = node.text
            if res is None:
                return ''
            return res.strip()

        _name = xml.find('name')

        if _name != None:
            self.name = encode(strip_text(_name))
        elif 'name' in xml.attrib:
            self.name = encode(xml.attrib['name'])
        else:
            msg = 'Overlay from_xml(), "name" entry missing from xml!'
            raise Exception(msg)

        _sources = xml.findall('source')

        # new xml format
        if _sources != []:
            _sources = [e for e in _sources if 'type' in e.attrib]
        #old xml format
        elif ('src' in xml.attrib) and ('type' in xml.attrib):
            s = ET.Element('source', type=xml.attrib['type'])
            s.text = xml.attrib['src']
            _sources = [s]
            del s

        def create_overlay_source(source_elem):
            _branch = ''
            _type = source_elem.attrib['type']
            self.ovl_type = _type

            if 'branch' in source_elem.attrib:
                _branch = source_elem.attrib['branch']

            try:
                _class = self.module_controller.get_class(_type)
            except InvalidModuleName:
                _class = self.module_controller.get_class('stub')

            _location = encode(strip_text(source_elem))
            self.branch = _branch

            return _class(parent=self,
                          config=self.config,
                          _location=_location,
                          ignore=ignore)

        if not len(_sources):
            msg = 'Overlay from_xml(), "%(name)" is missing a "source" entry!'\
                  % {'name': self.name}
            raise Exception(msg)

        self.sources = [create_overlay_source(e) for e in _sources]

        _owners = xml.findall('owner')
        self.owners = []

        # For backwards compatibility with older Overlay XML formats
        # default to this.
        if 'contact' in xml.attrib:
            owner = {'email': encode(xml.attrib['contact']), 'name': None}
            self.owners.append(owner)
        else:
            for _owner in _owners:
                owner = {}

                _email = _owner.find('email')
                _name = _owner.find('name')

                if _name != None:
                    owner['name'] = encode(strip_text(_name))
                else:
                    owner['name'] = None
                if _email != None:
                    owner['email'] = encode(strip_text(_email))
                else:
                    owner['email'] = None
                    msg = 'Overlay from_xml(), "%(name)s" is missing an '\
                          '"owner.email" entry!' % {'name': self.name}
                    if not ignore:
                        raise Exception(msg)
                    elif ignore == 1:
                        self.output.warn(msg, 4)

                self.owners.append(owner)

        _desc = xml.findall('description')
        if _desc != None:
            self.descriptions = []
            for d in _desc:
                d = WHITESPACE_REGEX.sub(' ', strip_text(d))
                self.descriptions.append(encode(d))
        else:
            self.descriptions = ['']
            msg = 'Overlay from_xml(), "%(name)s is missing a '\
                  '"description" entry!' % {'name': self.name}
            if not ignore:
                raise Exception(msg)
            elif ignore == 1:
                self.output.warn(msg, 4)

        if 'status' in xml.attrib:
            self.status = encode(xml.attrib['status'])
        else:
            self.status = None

        self.quality = 'experimental'
        if 'quality' in xml.attrib:
            if xml.attrib['quality'] in set(QUALITY_LEVELS):
                self.quality = encode(xml.attrib['quality'])

        if 'priority' in xml.attrib:
            self.priority = int(xml.attrib['priority'])
        else:
            self.priority = 50

        if 'license' in xml.attrib:
            self.license = encode(xml.attrib['license'])
        else:
            self.license = None

        h = xml.find('homepage')
        l = xml.find('link')

        if h != None:
            self.homepage = encode(strip_text(h))
        elif l != None:
            self.homepage = encode(strip_text(l))
        else:
            self.homepage = None

        self.feeds = [encode(strip_text(e)) for e in xml.findall('feed')]

        _irc = xml.find('irc')
        if _irc != None:
            self.irc = encode(strip_text(_irc))
        else:
            self.irc = None

    def get_infostr(self):
        '''
        Gives more detailed string of overlay information.

        @rtype str: encoded overlay information.
        '''

        result = ''

        result += self.name + '\n' + (len(self.name) * '~')

        if len(self.sources) == 1:
            result += '\nSource  : ' + self.sources[0].src
        else:
            result += '\nSources : '
            for i, v in enumerate(self.sources):
                result += '\n  %d. %s' % (i + 1, v.src)
            result += '\n'

        if len(self.owners) == 1:
            if 'name' in self.owners[0] and self.owners[0]['name'] != None:
                result += '\nContact : %s <%s>' \
                    % (self.owners[0]['name'], self.owners[0]['email'])
            else:
                result += '\nContact : ' + self.owners[0]['email']
        else:
            result += '\nContacts: '
            for i, v in enumerate(self.owners):
                result += '\n %d. ' % (i + 1)
                if 'name' in v and v['name'] != None:
                    result += '%s <%s>' % (v['name'], v['email'])
                else:
                    result += v['email']
            result += '\n'

        if len(self.sources) == 1:
            result += '\nType    : ' + self.sources[0].type
        else:
            result += '\nType    : ' + '/'.join(
                sorted(set(e.type for e in self.sources)))
        result += '; Priority: ' + str(self.priority) + '\n'
        result += 'Quality : ' + self.quality + '\n'

        for description in self.descriptions:
            description = re.compile(' +').sub(' ', description)
            description = re.compile('\n ').sub('\n', description)
            result += '\nDescription:'
            result += '\n  '.join(('\n' + description).split('\n'))
            result += '\n'

        if self.homepage != None:
            link = self.homepage
            link = re.compile(' +').sub(' ', link)
            link = re.compile('\n ').sub('\n', link)
            result += '\nLink:'
            result += '\n  '.join(('\n' + link).split('\n'))
            result += '\n'

        if self.irc != None:
            result += '\nIRC : ' + self.irc + '\n'

        if len(self.feeds):
            result += '\n%s:' % ((len(self.feeds) == 1) and "Feed" or "Feeds")
            for i in self.feeds:
                result += '\n  %s' % i
            result += '\n'

        return encoder(result, self._encoding_)

    def is_supported(self):
        return any(e.is_supported() for e in self.sources)

    def set_priority(self, priority):
        '''
        Set the priority of this overlay.
        '''
        self.priority = int(priority)

    def short_list(self, width=0):
        '''
        Return a shortened list of overlay information.

        @params width: int specifying terminal width.
        @rtype str: string of overlay information.
        '''
        if len(self.name) > 25:
            name = self.name + "   ###\n"
            name += pad(" ", 25)
        else:
            name = pad(self.name, 25)

        if len(set(e.type for e in self.sources)) == 1:
            _type = self.sources[0].type
        else:
            _type = '%s/..' % self.sources[0].type

        mtype = ' [' + pad(_type, 10) + ']'
        if not width:
            width = terminal_width() - 1
        srclen = width - 43
        source = ', '.join(self.source_uris())
        if len(source) > srclen:
            source = source.replace("overlays.gentoo.org", "o.g.o")
        source = ' (' + pad(source, srclen) + ')'

        return encoder(name + mtype + source, self._encoding_)

    def source_types(self):
        for i in self.sources:
            yield i.type

    def is_official(self):
        '''
        Is the overlay official?
        '''
        return self.status == 'official'

    def source_uris(self):
        for i in self.sources:
            yield i.src

    def sync(self, base):
        msg = 'Overlay.sync(); name = %(name)s' % {'name': self.name}
        self.output.debug(msg, 4)

        assert len(self.sources) == 1
        return self.sources[0].sync(base)

    def to_json(self):
        '''
        Convert to json.
        '''
        repo = {}

        repo['@priority'] = str(self.priority)
        repo['@quality'] = self.quality
        if self.status != None:
            repo['@status'] = self.status
        if self.license != None:
            repo['@license'] = self.license
        repo['name'] = self.name
        repo['description'] = [i for i in self.descriptions]
        if self.homepage != None:
            repo['homepage'] = self.homepage
        if self.irc != None:
            repo['irc'] = self.irc
        repo['owner'] = [i for i in self.owners]
        repo['source'] = []
        for i in self.sources:
            source = {'@type': i.__class__.type_key}
            if i.branch:
                source['@branch'] = i.branch
            source['#text'] = i.src
            repo['source'].append(source)
        if self.feeds != None:
            repo['feed'] = []
            for feed in self.feeds:
                repo['feed'].append(feed)

        return repo

    def to_xml(self):
        '''
        Convert to xml.
        '''
        repo = ET.Element('repo')
        if self.status != None:
            repo.attrib['status'] = self.status
        repo.attrib['quality'] = self.quality
        repo.attrib['priority'] = str(self.priority)
        if self.license != None:
            repo.attrib['license'] = self.license
        name = ET.Element('name')
        name.text = self.name
        repo.append(name)
        for i in self.descriptions:
            desc = ET.Element('description')
            desc.text = i
            repo.append(desc)
            del desc
        if self.homepage != None:
            homepage = ET.Element('homepage')
            homepage.text = self.homepage
            repo.append(homepage)
        if self.irc != None:
            irc = ET.Element('irc')
            irc.text = self.irc
            repo.append(irc)
        for _owner in self.owners:
            owner = ET.Element('owner')
            owner_email = ET.Element('email')
            owner_email.text = _owner['email']
            owner.append(owner_email)
            if 'name' in _owner and _owner['name']:
                owner_name = ET.Element('name')
                owner_name.text = _owner['name']
                owner.append(owner_name)
            repo.append(owner)
        for i in self.sources:
            if not i.branch:
                source = ET.Element('source', type=i.__class__.type_key)
            else:
                source = ET.Element('source',
                                    type=i.__class__.type_key,
                                    branch=i.branch)
            source.text = i.src
            repo.append(source)
            del source
        for i in self.sources:
            # NOTE: Two loops on purpose so the
            # hooks are called with all sources in
            i.to_xml_hook(repo)
        if self.feeds != None:
            for i in self.feeds:
                feed = ET.Element('feed')
                feed.text = i
                repo.append(feed)
                del feed
        return repo

    def update(self, base, available_srcs):
        res = 1
        first_src = True
        result = False

        self.sources = self.filter_protocols(self.sources)
        available_srcs = self.filter_protocols(available_srcs)
        if not self.sources or not available_srcs:
            msg = 'Overlay.update() error: overlay "%(name)s" does not support'\
                  ' the given protocol(s) %(protocol)s and cannot be updated.'\
                  % {'name': self.name,
                     'protocol': str(self.config['protocol_filter'])}
            self.output.error(msg)
            return 1

        if isinstance(available_srcs, str):
            available_srcs = [available_srcs]

        if self.sources[0].type in self.config.get_option(
                'support_url_updates'):
            for src in available_srcs:
                if not first_src:
                    self.output.info(
                        '\nTrying next source of listed sources...', 4)
                try:
                    res = self.sources[0].update(base, src)
                    if res == 0:
                        # Updating it worked, no need to bother
                        # checking other sources.
                        self.sources[0].src = src
                        result = True
                        break
                except Exception as error:
                    self.output.warn(str(error), 4)
                first_s = False
        else:
            # Update the overlay source with the remote
            # source, assuming that it's telling the truth
            # so it can be written to the installed.xml.
            msg = 'Overlay.update(); type: "%(src_type)s does not support '\
                  'source URL updating' % {'src_type': self.sources[0].type}
            self.output.debug(msg, 4)

            self.sources[0].src = available_srcs.pop()
            result = True
        return (self.sources, result)
예제 #8
0
파일: overlay.py 프로젝트: dewey/layman
class Overlay(object):
    ''' Derive the real implementations from this.'''

    def __init__(self, config, json=None, ovl_dict=None, xml=None, ignore=0):
        self.config = config
        self.output = config['output']
        self.module_controller = Modules(path=MOD_PATH,
                                         namepath='layman.overlays.modules',
                                         output=self.output)
        self._encoding_ = get_encoding(self.output)

        if xml is not None:
            self.from_xml(xml, ignore)
        elif ovl_dict is not None:
            self.from_dict(ovl_dict, ignore)
        elif json is not None:
            self.from_json(json, ignore)


    def __eq__(self, other):
        for i in ('descriptions', 'homepage', 'name', 'owners', 'priority',
                  'status'):
            if getattr(self, i) != getattr(other, i):
                return False
        for i in self.sources + other.sources:
            if not i in self.sources:
                return False
            if not i in other.sources:
                return False
        return True


    def __ne__(self, other):
        return not self.__eq__(other)


    def add(self, base):
        res = 1
        first_s = True

        self.sources = self.filter_protocols(self.sources)
        if not self.sources:
            msg = 'Overlay.add() error: overlay "%(name)s" does not support '\
                  ' the given\nprotocol(s) %(protocol)s and cannot be '\
                  'installed.'\
                  % {'name': self.name,
                     'protocol': str(self.config['protocol_filter'])}
            self.output.error(msg)
            return 1

        for s in self.sources:
            if not first_s:
                self.output.info('\nTrying next source of listed sources...', 4)
            try:
                res = s.add(base)
                if res == 0:
                    # Worked, throw other sources away
                    self.sources = [s]
                    break
            except Exception as error:
                self.output.warn(str(error), 4)
            first_s = False
        return res


    def delete(self, base):
        assert len(self.sources) == 1
        return self.sources[0].delete(base)


    def filter_protocols(self, sources):
        '''
        Filters any protocols not specified in self.config['protocol_filter']
        from the overlay's sources.
        '''
        _sources = []
        if not self.config['protocol_filter']:
            return sources

        for source in sources:
            for protocol in self.config['protocol_filter']:
                protocol = protocol.lower()
                #re.search considers "\+" as the literal "+".
                if protocol == 'git+ssh':
                    protocol = 'git\+ssh'
                protocol += '://'
                if re.search('^' + protocol, source.src):
                    _sources.append(source)

        return _sources


    def from_dict(self, overlay, ignore):
        '''
        Process an overlay dictionary definition
        '''
        msg = 'Overlay from_dict(); overlay %(ovl)s' % {'ovl': str(overlay)}
        self.output.debug(msg, 6)

        _name = overlay['name']
        if _name != None:
            self.name = encode(_name)
        else:
            msg = 'Overlay from_dict(), "name" entry missing from dictionary!'
            raise Exception(msg)

        if 'source' in overlay:
            _sources = overlay['source']
        else:
            _sources = None

        if _sources == None:
            msg = 'Overlay from_dict(), "%(name)s" is missing a "source" '\
                  'entry!' % {'name': self.name}
            raise Exception(msg)

        def create_dict_overlay_source(source_):
            _src, _type, _sub = source_
            self.ovl_type = _type
            try:
                _class = self.module_controller.get_class(_type)
            except InvalidModuleName:
                _class = self.module_controller.get_class('stub')

            _location = encode(_src)
            if _sub:
                self.branch = encode(_sub)
            else:
                self.branch = None

            return _class(parent=self, config=self.config,
                _location=_location, ignore=ignore)

        self.sources = [create_dict_overlay_source(e) for e in _sources]

        self.owners = []

        if 'owner' in overlay:
            for _owner in overlay['owner']:
                owner = {}
                if 'name' in _owner and _owner['name']:
                    owner['name'] = encode(_owner['name'])
                else:
                    owner['name'] = None

                if 'email' in _owner:
                    owner['email'] = encode(_owner['email'])
                else:
                    owner['email'] = None
                    msg = 'Overlay from_dict(), "%(name)s" is missing an '\
                          '"owner.email" entry!' % {'name': self.name}
                    if not ignore:
                        raise Exception(msg)
                    elif ignore == 1:
                        self.output.warn(msg, 4)

                self.owners.append(owner)

        if 'description' in overlay:
            self.descriptions = []
            _descs = overlay['description']
            for d in _descs:
                d = WHITESPACE_REGEX.sub(' ', d)
                self.descriptions.append(encode(d))
        else:
            self.descriptions = ['']
            if not ignore:
                raise Exception('Overlay from_dict(), "' + self.name +
                    '" is missing a "description" entry!')
            elif ignore == 1:
                self.output.warn('Overlay from_dict(), "' + self.name +
                    '" is missing a "description" entry!', 4)

        if 'status' in overlay:
            self.status = encode(overlay['status'])
        else:
            self.status = None

        self.quality = 'experimental'
        if 'quality' in overlay:
            if overlay['quality'] in set(QUALITY_LEVELS):
                self.quality = encode(overlay['quality'])

        if 'priority' in overlay:
            self.priority = int(overlay['priority'])
        else:
            self.priority = 50

        if 'license' in overlay:
            self.license = encode(overlay['license'])
        else:
            self.license = None

        if 'homepage' in overlay:
            self.homepage = encode(overlay['homepage'])
        else:
            self.homepage = None

        if 'feed' in overlay:
            self.feeds = [encode(e) \
                for e in overlay['feed']]
        else:
            self.feeds = None

        if 'irc' in overlay:
            self.irc = encode(overlay['irc'])
        else:
            self.irc = None

        # end of from_dict


    def from_json(self, json, ignore):
        '''
        Process a json overlay definition
        '''
        msg = 'Overlay from_json(); overlay %(ovl)s' % {'ovl': str(json)}
        self.output.debug(msg, 6)

        _name = json['name']
        if _name != None:
            self.name = encode(_name)
        else:
            msg = 'Overlay from_json(), "name" entry missing from json!'
            raise Exception(msg)

        if 'source' in json:
            _sources = json['source']
        else:
            _sources = None

        if _sources == None:
            msg = 'Overlay from_json(), "%(name)s" is missing a "source" '\
                  'entry!' % {'name': self.name}
            raise Exception(msg)

        def create_json_overlay_source(source_):
            _src = source_['#text']
            _type = source_['@type']
            if '@branch' in source_:
                _sub = source_['@branch']
            else:
                _sub = ''

            self.ovl_type = _type

            try:
                _class = self.module_controller.get_class(_type)
            except InvalidModuleName:
                _class = self.module_controller.get_class('stub')

            _location = encode(_src)
            if _sub:
                self.branch = encode(_sub)
            else:
                self.branch = None

            return _class(parent=self, config=self.config,
                _location=_location, ignore=ignore)

        self.sources = [create_json_overlay_source(e) for e in _sources]

        _owners = json['owner']
        self.owners = []

        for _owner in _owners:
            owner = {}
            if 'name' in _owner:
                owner['name'] = encode(_owner['name'])
            else:
                owner['name'] = None
            if 'email' in _owner:
                owner['email'] = encode(_owner['email'])
            else:
                owner['email'] = None
                msg = 'Overlay from_json(), "%(name)s" is missing an '\
                      '"owner.email" entry!' % {'name': self.name}
                if not ignore:
                    raise Exception(msg)
                elif ignore == 1:
                    self.output.warn(msg, 4)
            self.owners.append(owner)

        if 'description' in json:
            self.descriptions = []
            _descs = json['description']
            for d in _descs:
                d = WHITESPACE_REGEX.sub(' ', d)
                self.descriptions.append(encode(d))
        else:
            self.descriptions = ['']
            msg = 'Overlay from_json() "%(name)s" is missing description'\
                  'entry!' % {'name': self.name}
            if not ignore:
                raise Exception(msg)
            elif ignore == 1:
                self.output.warn(msg, 4)

        if '@status' in json:
            self.status = encode(json['@status'])
        else:
            self.status = None

        self.quality = 'experimental'
        if '@quality' in json:
            if json['@quality'] in set(QUALITY_LEVELS):
                self.quality = encode(json['@quality'])

        if '@priority' in json:
            self.priority = int(json['@priority'])
        else:
            self.priority = 50

        if '@license' in json:
            self.license = encode(json['@license'])
        else:
            self.license = None

        if 'homepage' in json:
            self.homepage = encode(json['homepage'])
        else:
            self.homepage = None

        if 'feed' in json:
            self.feeds = [encode(e) \
                for e in json['feed']]
        else:
            self.feeds = None

        if 'irc' in json:
            self.irc = encode(json['irc'])
        else:
            self.irc = None

        # end of from_json()


    def from_xml(self, xml, ignore):
        '''
        Process an xml overlay definition
        '''
        def strip_text(node):
            res = node.text
            if res is None:
                return ''
            return res.strip()

        _name = xml.find('name')

        if _name != None:
            self.name = encode(strip_text(_name))
        elif 'name' in xml.attrib:
            self.name = encode(xml.attrib['name'])
        else:
            msg = 'Overlay from_xml(), "name" entry missing from xml!'
            raise Exception(msg)

        _sources = xml.findall('source')

        # new xml format
        if _sources != []:
            _sources = [e for e in _sources if 'type' in e.attrib]
        #old xml format
        elif ('src' in xml.attrib) and ('type' in xml.attrib):
            s = ET.Element('source', type=xml.attrib['type'])
            s.text = xml.attrib['src']
            _sources = [s]
            del s

        def create_overlay_source(source_elem):
            _branch = ''
            _type = source_elem.attrib['type']
            self.ovl_type = _type

            if 'branch' in source_elem.attrib:
                _branch = source_elem.attrib['branch']

            try:
                _class = self.module_controller.get_class(_type)
            except InvalidModuleName:
                _class = self.module_controller.get_class('stub')

            _location = encode(strip_text(source_elem))
            self.branch = _branch

            return _class(parent=self, config=self.config,
                _location=_location, ignore=ignore)

        if not len(_sources):
            msg = 'Overlay from_xml(), "%(name)" is missing a "source" entry!'\
                  % {'name': self.name}
            raise Exception(msg)

        self.sources = [create_overlay_source(e) for e in _sources]

        _owners = xml.findall('owner')
        self.owners = []

        # For backwards compatibility with older Overlay XML formats
        # default to this.
        if 'contact' in xml.attrib:
            owner = {'email': encode(xml.attrib['contact']),
                     'name': None}
            self.owners.append(owner)
        else:
            for _owner in _owners:
                owner = {}

                _email = _owner.find('email')
                _name = _owner.find('name')

                if _name != None:
                    owner['name'] = encode(strip_text(_name))
                else:
                    owner['name'] = None
                if _email != None:
                    owner['email'] = encode(strip_text(_email))
                else:
                    owner['email'] = None
                    msg = 'Overlay from_xml(), "%(name)s" is missing an '\
                          '"owner.email" entry!' % {'name': self.name}
                    if not ignore:
                        raise Exception(msg)
                    elif ignore == 1:
                        self.output.warn(msg, 4)

                self.owners.append(owner)

        _desc = xml.findall('description')
        if _desc != None:
            self.descriptions = []
            for d in _desc:
                d = WHITESPACE_REGEX.sub(' ', strip_text(d))
                self.descriptions.append(encode(d))
        else:
            self.descriptions = ['']
            msg = 'Overlay from_xml(), "%(name)s is missing a '\
                  '"description" entry!' % {'name': self.name}
            if not ignore:
                raise Exception(msg)
            elif ignore == 1:
                self.output.warn(msg, 4)

        if 'status' in xml.attrib:
            self.status = encode(xml.attrib['status'])
        else:
            self.status = None

        self.quality = 'experimental'
        if 'quality' in xml.attrib:
            if xml.attrib['quality'] in set(QUALITY_LEVELS):
                self.quality = encode(xml.attrib['quality'])

        if 'priority' in xml.attrib:
            self.priority = int(xml.attrib['priority'])
        else:
            self.priority = 50

        if 'license' in xml.attrib:
            self.license = encode(xml.attrib['license'])
        else:
            self.license = None

        h = xml.find('homepage')
        l = xml.find('link')

        if h != None:
            self.homepage = encode(strip_text(h))
        elif l != None:
            self.homepage = encode(strip_text(l))
        else:
            self.homepage = None

        self.feeds = [encode(strip_text(e)) for e in xml.findall('feed')]

        _irc = xml.find('irc')
        if _irc != None:
            self.irc = encode(strip_text(_irc))
        else:
            self.irc = None


    def get_infostr(self):
        '''
        Gives more detailed string of overlay information.

        @rtype str: encoded overlay information.
        '''

        result = ''

        result += self.name + '\n' + (len(self.name) * '~')

        if len(self.sources) == 1:
            result += '\nSource  : ' + self.sources[0].src
        else:
            result += '\nSources : '
            for i, v in enumerate(self.sources):
                result += '\n  %d. %s' % (i + 1, v.src)
            result += '\n'

        if len(self.owners) == 1:
            if 'name' in self.owners[0] and self.owners[0]['name'] != None:
                result += '\nContact : %s <%s>' \
                    % (self.owners[0]['name'], self.owners[0]['email'])
            else:
                result += '\nContact : ' + self.owners[0]['email']
        else:
            result += '\nContacts: '
            for i, v in enumerate(self.owners):
                result += '\n %d. ' % (i + 1)
                if 'name' in v and v['name'] != None:
                    result += '%s <%s>' % (v['name'], v['email'])
                else:
                    result += v['email']
            result += '\n'

        if len(self.sources) == 1:
            result += '\nType    : ' + self.sources[0].type
        else:
            result += '\nType    : ' + '/'.join(
                sorted(set(e.type for e in self.sources)))
        result += '; Priority: ' + str(self.priority) + '\n'
        result += 'Quality : ' + self.quality + '\n'


        for description in self.descriptions:
            description = re.compile(' +').sub(' ', description)
            description = re.compile('\n ').sub('\n', description)
            result += '\nDescription:'
            result += '\n  '.join(('\n' + description).split('\n'))
            result += '\n'

        if self.homepage != None:
            link = self.homepage
            link = re.compile(' +').sub(' ', link)
            link = re.compile('\n ').sub('\n', link)
            result += '\nLink:'
            result += '\n  '.join(('\n' + link).split('\n'))
            result += '\n'

        if self.irc != None:
            result += '\nIRC : ' + self.irc + '\n'

        if len(self.feeds):
            result += '\n%s:' % ((len(self.feeds) == 1) and "Feed" or "Feeds")
            for i in self.feeds:
                result += '\n  %s' % i
            result += '\n'

        return encoder(result, self._encoding_)


    def is_supported(self):
        return any(e.is_supported() for e in self.sources)


    def set_priority(self, priority):
        '''
        Set the priority of this overlay.
        '''
        self.priority = int(priority)


    def short_list(self, width = 0):
        '''
        Return a shortened list of overlay information.

        @params width: int specifying terminal width.
        @rtype str: string of overlay information.
        '''
        if len(self.name) > 25:
            name = self.name + "   ###\n"
            name += pad(" ", 25)
        else:
            name   = pad(self.name, 25)

        if len(set(e.type for e in self.sources)) == 1:
            _type = self.sources[0].type
        else:
            _type = '%s/..' % self.sources[0].type

        mtype  = ' [' + pad(_type, 10) + ']'
        if not width:
            width = terminal_width()-1
        srclen = width - 43
        source = ', '.join(self.source_uris())
        if len(source) > srclen:
            source = source.replace("overlays.gentoo.org", "o.g.o")
        source = ' (' + pad(source, srclen) + ')'

        return encoder(name + mtype + source, self._encoding_)


    def source_types(self):
        for i in self.sources:
            yield i.type


    def is_official(self):
        '''
        Is the overlay official?
        '''
        return self.status == 'official'


    def source_uris(self):
        for i in self.sources:
            yield i.src


    def sync(self, base):
        msg = 'Overlay.sync(); name = %(name)s' % {'name': self.name}
        self.output.debug(msg, 4)

        assert len(self.sources) == 1
        return self.sources[0].sync(base)


    def to_json(self):
        '''
        Convert to json.
        '''
        repo = {}

        repo['@priority'] = str(self.priority)
        repo['@quality'] = self.quality
        if self.status != None:
            repo['@status'] = self.status
        if self.license != None:
            repo['@license'] = self.license
        repo['name'] = self.name
        repo['description'] = [i for i in self.descriptions]
        if self.homepage != None:
            repo['homepage'] = self.homepage
        if self.irc != None:
            repo['irc'] = self.irc
        repo['owner'] = [i for i in self.owners]
        repo['source'] = []
        for i in self.sources:
            source = {'@type': i.__class__.type_key}
            if i.branch:
                source['@branch'] = i.branch
            source['#text'] = i.src
            repo['source'].append(source)
        if self.feeds != None:
            repo['feed'] = []
            for feed in self.feeds:
                repo['feed'].append(feed)

        return repo


    def to_xml(self):
        '''
        Convert to xml.
        '''
        repo = ET.Element('repo')
        if self.status != None:
            repo.attrib['status'] = self.status
        repo.attrib['quality'] = self.quality
        repo.attrib['priority'] = str(self.priority)
        if self.license != None:
            repo.attrib['license'] = self.license
        name = ET.Element('name')
        name.text = self.name
        repo.append(name)
        for i in self.descriptions:
            desc = ET.Element('description')
            desc.text = i
            repo.append(desc)
            del desc
        if self.homepage != None:
            homepage = ET.Element('homepage')
            homepage.text = self.homepage
            repo.append(homepage)
        if self.irc != None:
            irc = ET.Element('irc')
            irc.text = self.irc
            repo.append(irc)
        for _owner in self.owners:
            owner = ET.Element('owner')
            owner_email = ET.Element('email')
            owner_email.text = _owner['email']
            owner.append(owner_email)
            if 'name' in _owner and _owner['name']:
                owner_name = ET.Element('name')
                owner_name.text = _owner['name']
                owner.append(owner_name)
            repo.append(owner)
        for i in self.sources:
            if not i.branch:
                source = ET.Element('source', type=i.__class__.type_key)
            else:
                source = ET.Element('source', type=i.__class__.type_key, branch=i.branch)
            source.text = i.src
            repo.append(source)
            del source
        for i in self.sources:
            # NOTE: Two loops on purpose so the
            # hooks are called with all sources in
            i.to_xml_hook(repo)
        if self.feeds != None:
            for i in self.feeds:
                feed = ET.Element('feed')
                feed.text = i
                repo.append(feed)
                del feed
        return repo


    def update(self, base, available_srcs):
        res = 1
        first_src = True
        result = False

        self.sources = self.filter_protocols(self.sources)
        available_srcs = self.filter_protocols(available_srcs)
        if not self.sources or not available_srcs:
            msg = 'Overlay.update() error: overlay "%(name)s" does not support'\
                  ' the given protocol(s) %(protocol)s and cannot be updated.'\
                  % {'name': self.name,
                     'protocol': str(self.config['protocol_filter'])}
            self.output.error(msg)
            return 1

        if isinstance(available_srcs, str):
            available_srcs = [available_srcs]

        if self.sources[0].type in self.config.get_option('support_url_updates'):
            for src in available_srcs:
                if not first_src:
                    self.output.info('\nTrying next source of listed sources...', 4)
                try:
                    res = self.sources[0].update(base, src)
                    if res == 0:
                        # Updating it worked, no need to bother 
                        # checking other sources.
                        self.sources[0].src = src
                        result = True
                        break
                except Exception as error:
                    self.output.warn(str(error), 4)
                first_s = False
        else:
            # Update the overlay source with the remote
            # source, assuming that it's telling the truth
            # so it can be written to the installed.xml.
            msg = 'Overlay.update(); type: "%(src_type)s does not support '\
                  'source URL updating' % {'src_type': self.sources[0].type}
            self.output.debug(msg, 4)

            self.sources[0].src = available_srcs.pop()
            result = True
        return (self.sources, result)
예제 #9
0
class RepoConfManager:
    def __init__(self, config, overlays):

        #TODO add custom_conf_type support
        self.config = config
        self.conf_types = config['conf_type']
        self.output = config['output']
        self.overlays = overlays
        self.module_controller = Modules(path=MOD_PATH,
                                         namepath='layman.config_modules',
                                         output=self.output)

        if isinstance(self.conf_types, STR):
            self.conf_types = [x.strip() for x in self.conf_types.split(',')]

        if not self.conf_types and self.config['require_repoconfig']:
            self.output.error('No Repo configuration type found, but' +
                              '\nis required in order to continue...')

    def add(self, overlay):
        '''
        Adds overlay information to the specified config type(s).

        @param overlay: layman.overlay.Overlay instance.
        @return boolean: represents success or failure.
        '''
        if self.config['require_repoconfig']:
            results = []
            for types in self.conf_types:
                types = types.replace('.', '')
                conf = self.module_controller.get_class(types)\
                                  (self.config, self.overlays)
                conf_ok = conf.add(overlay)
                results.append(conf_ok)
            return results
        return [True]

    def delete(self, overlay):
        '''
        Deletes overlay information from the specified config type(s).

        @param overlay: layman.overlay.Overlay instance.
        @return boolean: represents success or failure.
        '''
        if self.config['require_repoconfig']:
            results = []
            for types in self.conf_types:
                types = types.replace('.', '')
                conf = self.module_controller.get_class(types)\
                                  (self.config, self.overlays)
                conf_ok = conf.delete(overlay)
                results.append(conf_ok)
            return results
        return [True]

    def disable(self, overlay):
        '''
        Allows an overlay to become no longer accessible to portage
        without deleting the overlay.

        @param overlay: layman.overlay.Overlay instance.
        @return boolean: represents success or failure.
        '''
        if self.config['require_repoconfig']:
            for types in self.conf_types:
                types = types.replace('.', '')
                conf = self.module_controller.get_class(types)\
                                  (self.config, self.overlays)
                conf_ok = conf.disable(overlay)
            return conf_ok
        return True

    def enable(self, overlay):
        '''
        Allows an overlay to become accessible to portage
        after overlay was "forgotten".

        @param overlay: layman.overlay.Overlay instance.
        @return boolean: represents success or failure.
        '''
        if self.config['require_repoconfig']:
            for types in self.conf_types:
                types = types.replace('.', '')
                conf = self.module_controller.get_class(types)\
                                  (self.config, self.overlays)
                conf_ok = conf.enable(overlay)
            return conf_ok
        return True

    def update(self, overlay):
        '''
        Updates the source URL for the specified config type(s).

        @param overlay: layman.overlay.Overlay instance.
        @return boolean: represents success or failure.
        '''
        if self.config['require_repoconfig']:
            results = []
            for types in self.conf_types:
                types = types.replace('.', '')
                conf = self.module_controller.get_class(types)\
                                  (self.config, self.overlays)
                conf_ok = conf.update(overlay)
                results.append(conf_ok)
            return results
        return [True]
예제 #10
0
파일: dbbase.py 프로젝트: fatman2021/layman
class DbBase(object):
    '''
    Handle a list of overlays.
    '''

    def __init__(self, config, paths=None, ignore=0,
           ignore_init_read_errors=False, allow_missing=False):

        self.config = config
        self.db_type = config['db_type']
        self.ignore = ignore
        self.ignore_init_read_errors = ignore_init_read_errors
        self.mod_ctl = Modules(path=MOD_PATH,
                               namepath='layman.db_modules',
                               output=config['output'])
        self.output = config['output']
        self.overlays = {}
        self.paths = paths

        path_found = False

        self.output.debug('Initializing overlay list handler', 8)

        if isinstance(self.db_type, STR):
            self.db_type = [x.strip() for x in self.db_type.split(',')]

        if len(self.db_type) > 1:
            msg = 'DbBase; warning, multiple instances of "db_type" found:'\
                  ' %(db_types)s.\nDefaulting to: %(db_type)s'\
                  % {'db_types': self.db_type, 'db_type': self.db_type[0]}
            self.output.warn(msg)

        self.db_type = self.db_type[0]

        for path in self.paths:
            if not os.path.exists(path):
                continue

            self.read_db(path)
            path_found = True

        if not path_found and not allow_missing:
            msg = 'Warning: an installed db file was not found at: %(path)s'\
                   % {'path': str(self.paths)}
            self.output.warn(msg)


    def __eq__(self, other):
        for key in set(self.overlays.keys()) | set(other.overlays.keys()):
            if self.overlays[key] != other.overlays[key]:
                return False
        return True


    def __ne__(self, other):
        return not self.__eq__(other)


    def _add_from_dict(self, overlays=None):
        '''
        Add a new overlay from a list of dictionary values
        '''
        self.output.info('DbBase: add_from_dict()')

        for overlay in overlays:
            self.output.debug('Parsing overlay entry', 8)
            ovl = Overlay(self.config, ovl_dict=overlay,
                          ignore=self.ignore)
            self.overlays[ovl.name] = ovl

        return


    def _broken_catalog_hint(self):
        this_function_name = sys._getframe().f_code.co_name
        msg = 'Method "%(name)s.%(func)s" not implemented'\
              % {'name': self.__class__.__name__,
                 'func': this_function_name}

        raise NotImplementedError(msg)


    def add_new(self, xml=None, origin=None, from_dict=None):
        '''
        Reads xml text and dictionary definitions and adds
        them to the db.

        NOTE: Currently being refactored. Will be disabled until fixed.
        '''
        '''
        if xml is not None:
            self.read(xml, origin)
        if from_dict is not None:
            self.output.info("DbBase: add_new() from_dict")
            if isinstance(from_dict, dict):
                from_dict = [from_dict]
            self._add_from_dict(from_dict)
        '''

        return


    def read_db(self, path, text=None, text_type=None):
        '''
        Read the overlay database for installed overlay definitions.
        '''
        if text and text_type:
            db_type = text_type
        else:
            db_type = self.db_type

        #Added to keep xml functionality for cached overlay XML definitions
        if 'cache' in path and '.xml' in path:
            db_type = 'xml_db'

        db_ctl = self.mod_ctl.get_class(db_type)(self.config,
                 self.overlays,
                 self.paths,
                 self.ignore,
                 self.ignore_init_read_errors)

        db_ctl.read_db(path, text=text)


    def write(self, path):
        '''
        Write the list of overlays to a file.
        '''
        db_ctl = self.mod_ctl.get_class(self.db_type)(self.config,
                 self.overlays,
                 self.paths,
                 self.ignore,
                 self.ignore_init_read_errors)

        db_ctl.write(path)


    def select(self, overlay):
        '''
        Select an overlay from the list.
        '''
        ovl = {'ovl': overlay}
        msg = 'DbBase.select(), overlay = %(ovl)s' % ovl
        self.output.debug(msg, 5)

        if not overlay in self.overlays.keys():
            msg = 'DbBase.select(), unknown overlay = %(ovl)s' % ovl
            self.output.debug(msg, 4)
            ovls = {'ovls': ', '.join(self.overlays.keys())}
            msg = 'DbBase.select(), known overlays = %(ovls)s' % ovls
            self.output.debug(ovls, 4)
            raise UnknownOverlayException(overlay)
        return self.overlays[overlay]


    def list(self, repos=None, verbose=False, width=0):
        '''
        List all overlays.
        '''
        result = []

        selection = [overlay for (a, overlay) in self.overlays.items()]
        if repos is not None:
            selection = [ovl for ovl in selection if ovl.name in repos]

        for overlay in selection:
            if verbose:
                result.append((overlay.get_infostr(), overlay.is_supported(),
                               overlay.is_official()))
            else:
                result.append((overlay.short_list(width),
                               overlay.is_supported(), overlay.is_official()))

        result = sorted(result, key=lambda summary_supported_official:\
                                summary_supported_official[0].lower())

        return result


    def list_ids(self):
        '''
        Returns a list of the overlay names
        '''
        return sorted(self.overlays)
예제 #11
0
class DbBase(object):
    '''
    Handle a list of overlays.
    '''

    def __init__(self, config, paths=None, ignore=0,
           ignore_init_read_errors=False, allow_missing=False):

        self.config = config
        self.db_type = config['db_type']
        self.ignore = ignore
        self.ignore_init_read_errors = ignore_init_read_errors
        self.mod_ctl = Modules(path=MOD_PATH,
                               namepath='layman.db_modules',
                               output=config['output'])
        self.output = config['output']
        self.overlays = {}
        self.paths = paths

        path_found = False

        self.output.debug('Initializing overlay list handler', 8)

        if isinstance(self.db_type, STR):
            self.db_type = [x.strip() for x in self.db_type.split(',')]

        if len(self.db_type) > 1:
            msg = 'DbBase; warning, multiple instances of "db_type" found:'\
                  ' %(db_types)s.\nDefaulting to: %(db_type)s'\
                  % {'db_types': self.db_type, 'db_type': self.db_type[0]}
            self.output.warn(msg)

        self.db_type = self.db_type[0] + '_db'

        for path in self.paths:
            if not os.path.exists(path):
                continue

            success = self.read_db(path)
            if not success:
                msg = 'DbBase; error, Failed to read database at "%(path)s"\n'\
                      'Hint: If you manually set db_type. Please reset it and '\
                      'let layman-updater\nmigrate it. Otherwise layman\'s '\
                      'database is not initialized, nor populated\nwith any '\
                      'existing data.\nRun the following: "layman-updater -m '\
                      '<db_type>"' % {'path': path}
                self.output.error(msg)
                sys.exit(-1)

            path_found = True

        if not path_found and not allow_missing:
            msg = 'Warning: an installed db file was not found at: %(path)s'\
                   % {'path': str(self.paths)}
            self.output.warn(msg)


    def __eq__(self, other):
        for key in set(self.overlays.keys()) | set(other.overlays.keys()):
            if self.overlays[key] != other.overlays[key]:
                return False
        return True


    def __ne__(self, other):
        return not self.__eq__(other)


    def _add_from_dict(self, overlays=None):
        '''
        Add a new overlay from a list of dictionary values
        '''
        self.output.info('DbBase: add_from_dict()')

        for overlay in overlays:
            self.output.debug('Parsing overlay entry', 8)
            ovl = Overlay(self.config, ovl_dict=overlay,
                          ignore=self.ignore)
            self.overlays[ovl.name] = ovl

        return


    def _broken_catalog_hint(self):
        this_function_name = sys._getframe().f_code.co_name
        msg = 'Method "%(name)s.%(func)s" not implemented'\
              % {'name': self.__class__.__name__,
                 'func': this_function_name}

        raise NotImplementedError(msg)


    def _get_dbctl(self, db_type):
        '''
        Returns database module controller for class or dies trying.
        '''
        try:
            db_ctl = self.mod_ctl.get_class(db_type)(self.config,
                        self.overlays,
                        self.paths,
                        self.ignore,
                        self.ignore_init_read_errors)
        except InvalidModuleName:
            msg = 'DbBase._get_dbctl() error:\nDatabase module name '\
                  '"%(name)s" is invalid or not found.\nPlease set db_type '\
                  'variable to proper value to continue.'\
                  % {'name': db_type.replace('_db', '')}
            self.output.die(msg)

        return db_ctl


    def add_new(self, xml=None, origin=None, from_dict=None):
        '''
        Reads xml text and dictionary definitions and adds
        them to the db.

        NOTE: Currently being refactored. Will be disabled until fixed.
        '''
        '''
        if xml is not None:
            self.read(xml, origin)
        if from_dict is not None:
            self.output.info("DbBase: add_new() from_dict")
            if isinstance(from_dict, dict):
                from_dict = [from_dict]
            self._add_from_dict(from_dict)
        '''

        return


    def read_db(self, path, text=None, text_type=None):
        '''
        Read the overlay database for installed overlay definitions.
        '''
        db_type = self.db_type

        if text and text_type:
            db_type = text_type + '_db'

        #Added to keep xml functionality for cached overlay XML definitions
        if 'cache' in path and '.xml' in path:
            db_type = 'xml_db'

        db_ctl = self._get_dbctl(db_type)
        return db_ctl.read_db(path, text=text)


    def write(self, path, remove=False, migrate_type=None):
        '''
        Write the list of overlays to a file.
        '''
        db_type = self.db_type

        if migrate_type:
            db_type = migrate_type + '_db'

        db_ctl = self._get_dbctl(db_type)
        db_ctl.write(path, remove=remove)


    def remove(self, overlay, path):
        '''
        Remove an overlay from the database.
        '''
        db_ctl = self._get_dbctl(self.db_type)
        db_ctl.remove(overlay, path)


    def select(self, overlay):
        '''
        Select an overlay from the list.
        '''
        ovl = {'ovl': overlay}
        msg = 'DbBase.select(), overlay = %(ovl)s' % ovl
        self.output.debug(msg, 5)

        if not overlay in self.overlays.keys():
            msg = 'DbBase.select(), unknown overlay = %(ovl)s' % ovl
            self.output.debug(msg, 4)
            ovls = {'ovls': ', '.join(self.overlays.keys())}
            msg = 'DbBase.select(), known overlays = %(ovls)s' % ovls
            self.output.debug(ovls, 4)
            raise UnknownOverlayException(overlay)
        return self.overlays[overlay]


    def list(self, repos=None, verbose=False, width=0):
        '''
        List all overlays.
        '''
        result = []

        selection = [overlay for (a, overlay) in self.overlays.items()]
        if repos is not None:
            selection = [ovl for ovl in selection if ovl.name in repos]

        for overlay in selection:
            if verbose:
                result.append((overlay.get_infostr(), overlay.is_supported(),
                               overlay.is_official()))
            else:
                result.append((overlay.short_list(width),
                               overlay.is_supported(), overlay.is_official()))

        result = sorted(result, key=lambda summary_supported_official:\
                                summary_supported_official[0].lower())

        return result


    def list_ids(self):
        '''
        Returns a list of the overlay names
        '''
        return sorted(self.overlays)
예제 #12
0
파일: overlay.py 프로젝트: wking/layman
class Overlay(object):
    ''' Derive the real implementations from this.'''

    def __init__(self, config, xml=None, ovl_dict=None,
        ignore = 0):
        self.config = config
        self.output = config['output']
        self.module_controller = Modules(path=MOD_PATH,
                                         namepath='layman.overlays.modules',
                                         output=self.output)
        self._encoding_ = get_encoding(self.output)

        if xml is not None:
            self.from_xml(xml, ignore)
        elif ovl_dict is not None:
            self.from_dict(ovl_dict, ignore)


    def from_xml(self, xml, ignore):
        """Process an xml overlay definition
        """
        def strip_text(node):
            res = node.text
            if res is None:
                return ''
            return res.strip()

        _name = xml.find('name')
        if _name != None:
            self.name = encode(strip_text(_name))
        elif 'name' in xml.attrib:
            self.name = encode(xml.attrib['name'])
        else:
            raise Exception('Overlay from_xml(), "' + self.name + \
                'is missing a "name" entry!')

        _sources = xml.findall('source')
        # new xml format
        if _sources != []:
            _sources = [e for e in _sources if 'type' in e.attrib]
        #old xml format
        elif ('src' in xml.attrib) and ('type' in xml.attrib):
            s = ET.Element('source', type=xml.attrib['type'])
            s.text = xml.attrib['src']
            _sources = [s]
            del s

        def create_overlay_source(source_elem):
            _branch = ''
            _type = source_elem.attrib['type']
            self.ovl_type = _type
            if 'branch' in source_elem.attrib:
                _branch = source_elem.attrib['branch']

            try:
                _class = self.module_controller.get_class(_type)
            except InvalidModuleName:
                _class = self.module_controller.get_class('stub')

            _location = encode(strip_text(source_elem))

            self.branch = _branch

            return _class(parent=self, config=self.config,
                _location=_location, ignore=ignore)

        if not len(_sources):
            raise Exception('Overlay from_xml(), "' + self.name + \
                '" is missing a "source" entry!')

        self.sources = [create_overlay_source(e) for e in _sources]

        _owner = xml.find('owner')
        if _owner == None:
            _email = None
        else:
            _email = _owner.find('email')
        if _owner != None and _email != None:
            self.owner_email = encode(strip_text(_email))
            _name = _owner.find('name')
            if _name != None:
                self.owner_name = encode(strip_text(_name))
            else:
                self.owner_name = None
        elif 'contact' in xml.attrib:
            self.owner_email = encode(xml.attrib['contact'])
            self.owner_name = None
        else:
            self.owner_email = ''
            self.owner_name = None
            if not ignore:
                raise Exception('Overlay  from_xml(), "' + self.name + \
                    '" is missing an "owner.email" entry!')
            elif ignore == 1:
                self.output.warn('Overlay "' + self.name + '" is missing a '
                         '"owner.email" entry!', 4)

        _desc = xml.findall('description')
        if _desc != None:
            self.descriptions = []
            for d in _desc:
                d = WHITESPACE_REGEX.sub(' ', strip_text(d))
                self.descriptions.append(encode(d))
        else:
            self.descriptions = ['']
            if not ignore:
                raise Exception('Overlay  from_xml(), "' + self.name + \
                    '" is missing a description" entry!')
            elif ignore == 1:
                self.output.warn('Overlay "' + self.name + '" is missing a '
                         '"description" entry!', 4)

        if 'status' in xml.attrib:
            self.status = encode(xml.attrib['status'])
        else:
            self.status = None

        self.quality = 'experimental'
        if 'quality' in xml.attrib:
            if xml.attrib['quality'] in set(QUALITY_LEVELS):
                self.quality = encode(xml.attrib['quality'])

        if 'priority' in xml.attrib:
            self.priority = int(xml.attrib['priority'])
        else:
            self.priority = 50

        h = xml.find('homepage')
        l = xml.find('link')
        if h != None:
            self.homepage = encode(strip_text(h))
        elif l != None:
            self.homepage = encode(strip_text(l))
        else:
            self.homepage = None

        self.feeds = [encode(strip_text(e)) \
            for e in xml.findall('feed')]

        _irc = xml.find('irc')
        if _irc != None:
            self.irc = encode(strip_text(_irc))
        else:
            self.irc = None


    def from_dict(self, overlay, ignore):
        """Process an overlay dictionary definition
        """
        self.output.debug("Overlay from_dict(); overlay" + str(overlay), 6)
        _name = overlay['name']
        if _name != None:
            self.name = encode(_name)
        else:
            raise Exception('Overlay from_dict(), "' + self.name +
                'is missing a "name" entry!')

        _sources = overlay['sources']

        if _sources == None:
            raise Exception('Overlay from_dict(), "' + self.name +
                '" is missing a "source" entry!')

        def create_dict_overlay_source(source_):
            _src, _type, _sub = source_
            self.ovl_type = _type
            try:
                _class = self.module_controller.get_class(_type)
            except InvalidModuleName:
                _class = self.module_controller.get_class('stub')

            _location = encode(_src)
            if _sub:
                self.branch = encode(_sub)
            else:
                self.branch = None

            return _class(parent=self, config=self.config,
                _location=_location, ignore=ignore)

        self.sources = [create_dict_overlay_source(e) for e in _sources]

        if 'owner_name' in overlay:
            _owner = overlay['owner_name']
            self.owner_name = encode(_owner)
        else:
            self.owner_name = None

        if 'owner_email' in overlay:
            _email = overlay['owner_email']
            self.owner_email = encode(_email)
        else:
            self.owner_email = None
            if not ignore:
                raise Exception('Overlay from_dict(), "' + self.name +
                    '" is missing an "owner.email" entry!')
            elif ignore == 1:
                self.output.warn('Overlay from_dict(), "' + self.name +
                    '" is missing an "owner.email" entry!', 4)

        if 'descriptions' in overlay:
            self.descriptions = []
            _descs = overlay['descriptions']
            for d in _descs:
                d = WHITESPACE_REGEX.sub(' ', d)
                self.descriptions.append(encode(d))
        else:
            self.descriptions = ['']
            if not ignore:
                raise Exception('Overlay from_dict(), "' + self.name +
                    '" is missing a "description" entry!')
            elif ignore == 1:
                self.output.warn('Overlay from_dict(), "' + self.name +
                    '" is missing a "description" entry!', 4)

        if 'status' in overlay:
            self.status = encode(overlay['status'])
        else:
            self.status = None

        self.quality = 'experimental'
        if 'quality' in overlay:
            if overlay['quality'] in set(QUALITY_LEVELS):
                self.quality = encode(overlay['quality'])

        if 'priority' in overlay:
            self.priority = int(overlay['priority'])
        else:
            self.priority = 50

        if 'homepage' in overlay:
            self.homepage = encode(overlay['homepage'])
        else:
            self.homepage = None

        if 'feeds' in overlay:
            self.feeds = [encode(e) \
                for e in overlay['feeds']]
        else:
            self.feeds = None

        if 'irc' in overlay:
            self.irc = encode(overlay['irc'])
        else:
            self.irc = None

        #xml = self.to_xml()
        # end of from_dict


    def __eq__(self, other):
        for i in ('descriptions', 'homepage', 'name', 'owner_email',
                'owner_name', 'priority', 'status'):
            if getattr(self, i) != getattr(other, i):
                return False
        for i in self.sources + other.sources:
            if not i in self.sources:
                return False
            if not i in other.sources:
                return False
        return True


    def __ne__(self, other):
        return not self.__eq__(other)


    def set_priority(self, priority):
        '''Set the priority of this overlay.'''
        self.priority = int(priority)


    def to_xml(self):
        '''Convert to xml.'''
        repo = ET.Element('repo')
        if self.status != None:
            repo.attrib['status'] = self.status
        repo.attrib['quality'] = self.quality
        repo.attrib['priority'] = str(self.priority)
        name = ET.Element('name')
        name.text = self.name
        repo.append(name)
        for i in self.descriptions:
            desc = ET.Element('description')
            desc.text = i
            repo.append(desc)
            del desc
        if self.homepage != None:
            homepage = ET.Element('homepage')
            homepage.text = self.homepage
            repo.append(homepage)
        if self.irc != None:
            irc = ET.Element('irc')
            irc.text = self.irc
            repo.append(irc)
        owner = ET.Element('owner')
        repo.append(owner)
        owner_email = ET.Element('email')
        owner_email.text = self.owner_email
        owner.append(owner_email)
        if self.owner_name != None:
            owner_name = ET.Element('name')
            owner_name.text = self.owner_name
            owner.append(owner_name)
        for i in self.sources:
            if not i.branch:
                source = ET.Element('source', type=i.__class__.type_key)
            else:
                source = ET.Element('source', type=i.__class__.type_key, branch=i.branch)
            source.text = i.src
            repo.append(source)
            del source
        for i in self.sources:
            # NOTE: Two loops on purpose so the
            # hooks are called with all sources in
            i.to_xml_hook(repo)
        if self.feeds != None:
            for i in self.feeds:
                feed = ET.Element('feed')
                feed.text = i
                repo.append(feed)
                del feed
        return repo


    def add(self, base):
        res = 1
        first_s = True
        for s in self.sources:
            if not first_s:
                self.output.info("\nTrying next source of listed sources...", 4)
            try:
                res = s.add(base)
                if res == 0:
                    # Worked, throw other sources away
                    self.sources = [s]
                    break
            except Exception as error:
                self.output.warn(str(error), 4)
            first_s = False
        return res


    def update(self, base, available_srcs):
        res = 1
        first_src = True
        result = False

        if isinstance(available_srcs, str):
            available_srcs = [available_srcs]

        if self.sources[0].type in self.config.get_option('support_url_updates'):
            for src in available_srcs:
                if not first_src:
                    self.output.info("\nTrying next source of listed sources...", 4)
                try:
                    res = self.sources[0].update(base, src)
                    if res == 0:
                        # Updating it worked, no need to bother 
                        # checking other sources.
                        self.sources[0].src = src
                        result = True
                        break
                except Exception as error:
                    self.output.warn(str(error), 4)
                first_s = False
        else:
            # Update the overlay source with the remote
            # source, assuming that it's telling the truth
            # so it can be written to the installed.xml.
            self.output.debug("overlay.update(); type: %s does not support"\
                " source URL updating" % self.sources[0].type, 4)
            self.sources[0].src = available_srcs.pop()
            result = True
        return (self.sources, result)


    def sync(self, base):
        self.output.debug("overlay.sync(); name = %s" % self.name, 4)
        assert len(self.sources) == 1
        return self.sources[0].sync(base)


    def delete(self, base):
        assert len(self.sources) == 1
        return self.sources[0].delete(base)


    def get_infostr(self):
        '''
        Gives more detailed string of overlay information.

        @rtype str: encoded overlay information.
        '''

        result = ''

        result += self.name + '\n' + (len(self.name) * '~')

        if len(self.sources) == 1:
            result += '\nSource  : ' + self.sources[0].src
        else:
            result += '\nSources:'
            for i, v in enumerate(self.sources):
                result += '\n  %d. %s' % (i + 1, v.src)
            result += '\n'

        if self.owner_name != None:
            result += '\nContact : %s <%s>' \
                % (self.owner_name, self.owner_email)
        else:
            result += '\nContact : ' + self.owner_email
        if len(self.sources) == 1:
            result += '\nType    : ' + self.sources[0].type
        else:
            result += '\nType    : ' + '/'.join(
                sorted(set(e.type for e in self.sources)))
        result += '; Priority: ' + str(self.priority) + '\n'
        result += 'Quality : ' + self.quality + '\n'


        for description in self.descriptions:
            description = re.compile(' +').sub(' ', description)
            description = re.compile('\n ').sub('\n', description)
            result += '\nDescription:'
            result += '\n  '.join(('\n' + description).split('\n'))
            result += '\n'

        if self.homepage != None:
            link = self.homepage
            link = re.compile(' +').sub(' ', link)
            link = re.compile('\n ').sub('\n', link)
            result += '\nLink:'
            result += '\n  '.join(('\n' + link).split('\n'))
            result += '\n'

        if self.irc != None:
            result += '\nIRC : ' + self.irc + '\n'

        if len(self.feeds):
            result += '\n%s:' % ((len(self.feeds) == 1) and "Feed" or "Feeds")
            for i in self.feeds:
                result += '\n  %s' % i
            result += '\n'

        return encoder(result, self._encoding_)


    def short_list(self, width = 0):
        '''
        Return a shortened list of overlay information.

        @params width: int specifying terminal width.
        @rtype str: string of overlay information.
        '''
        if len(self.name) > 25:
            name = self.name + "   ###\n"
            name += pad(" ", 25)
        else:
            name   = pad(self.name, 25)

        if len(set(e.type for e in self.sources)) == 1:
            _type = self.sources[0].type
        else:
            _type = '%s/..' % self.sources[0].type

        mtype  = ' [' + pad(_type, 10) + ']'
        if not width:
            width = terminal_width()-1
        srclen = width - 43
        source = ', '.join(self.source_uris())
        if len(source) > srclen:
            source = source.replace("overlays.gentoo.org", "o.g.o")
        source = ' (' + pad(source, srclen) + ')'

        return encoder(name + mtype + source, self._encoding_)


    def is_official(self):
        '''Is the overlay official?'''
        return self.status == 'official'


    def is_supported(self):
        return any(e.is_supported() for e in self.sources)


    def source_uris(self):
        for i in self.sources:
            yield i.src


    def source_types(self):
        for i in self.sources:
            yield i.type
예제 #13
0
class RepoConfManager:

    def __init__(self, config, overlays):

        #TODO add custom_conf_type support
        self.config = config
        self.conf_types = config['conf_type']
        self.output = config['output']
        self.overlays = overlays
        self.module_controller = Modules(path=MOD_PATH,
                                         namepath='layman.config_modules',
                                         output=self.output)

        if isinstance(self.conf_types, STR):
            self.conf_types = re.split(',\s+', self.conf_types)

        if not self.conf_types and self.config['require_repoconfig']:
            self.output.error('No Repo configuration type found, but'
                + '\nis required in order to continue...')


    def add(self, overlay):
        '''
        Adds overlay information to the specified config type(s).

        @param overlay: layman.overlay.Overlay instance.
        @return boolean: represents success or failure.
        '''
        if self.config['require_repoconfig']:
            results = []
            for types in self.conf_types:
                types = types.replace('.', '')
                conf = self.module_controller.get_class(types)\
                                  (self.config, self.overlays)
                conf_ok = conf.add(overlay)
                results.append(conf_ok)
            return results
        return [True]



    def delete(self, overlay):
        '''
        Deletes overlay information from the specified config type(s).

        @param overlay: layman.overlay.Overlay instance.
        @return boolean: represents success or failure.
        '''
        if self.config['require_repoconfig']:
            results = []
            for types in self.conf_types:
                types = types.replace('.', '')
                conf = self.module_controller.get_class(types)\
                                  (self.config, self.overlays)
                conf_ok = conf.delete(overlay)
                results.append(conf_ok)
            return results
        return [True]


    def disable(self, overlay):
        '''
        Allows an overlay to become no longer accessible to portage
        without deleting the overlay.

        @param overlay: layman.overlay.Overlay instance.
        @return boolean: represents success or failure.
        '''
        if self.config['require_repoconfig']:
            for types in self.conf_types:
                types = types.replace('.', '')
                conf = self.module_controller.get_class(types)\
                                  (self.config, self.overlays)
                conf_ok = conf.disable(overlay)
            return conf_ok
        return True
                                                                                                                                                

    def enable(self, overlay):
        '''
        Allows an overlay to become accessible to portage
        after overlay was "forgotten".

        @param overlay: layman.overlay.Overlay instance.
        @return boolean: represents success or failure.
        '''
        if self.config['require_repoconfig']:
            for types in self.conf_types:
                types = types.replace('.', '')
                conf = self.module_controller.get_class(types)\
                                  (self.config, self.overlays)
                conf_ok = conf.enable(overlay)
            return conf_ok
        return True

    
    def update(self, overlay):
        '''
        Updates the source URL for the specified config type(s).
    
        @param overlay: layman.overlay.Overlay instance.
        @return boolean: represents success or failure.
        '''
        if self.config['require_repoconfig']:
            results = []
            for types in self.conf_types:
                types = types.replace('.', '')
                conf = self.module_controller.get_class(types)\
                                  (self.config, self.overlays)
                conf_ok = conf.update(overlay)
                results.append(conf_ok)
            return results
        return [True]