Exemple #1
0
    def __init__(self, config):

        self.config = config
        self.output = config['output']

        self.path = config['installed']
        self.output.debug(
            "DB.__init__(): config['installed'] = %s" % self.path, 3)

        if config['nocheck']:
            ignore = 2
        else:
            ignore = 1

        DbBase.__init__(
            self,
            config,
            paths=[
                config['installed'],
            ],
            ignore=ignore,
            allow_missing=True,
        )

        self.repo_conf = RepoConfManager(self.config, self.overlays)

        self.output.debug('DB handler initiated', 6)

        # check and handle the name change
        if not os.access(self.config['installed'], os.F_OK) and \
            os.access(self.config['local_list'], os.F_OK):
            self.output.die("Please run layman-updater, "
                            "then run layman again")
Exemple #2
0
    def __init__(self, config):

        self.config = config
        self.output = config['output']

        self.path = config['installed']
        self.output.debug("DB.__init__(): config['installed'] = %s" % self.path, 3)

        if config['nocheck']:
            ignore = 2
        else:
            ignore = 1


        DbBase.__init__(self,
                          config,
                          paths=[config['installed'], ],
                          ignore=ignore,
                          )

        self.repo_conf = RepoConfManager(self.config, self.overlays)

        self.output.debug('DB handler initiated', 6)

        # check and handle the name change
        if not os.access(self.config['installed'], os.F_OK) and \
            os.access(self.config['local_list'], os.F_OK):
                self.output.die("Please run layman-updater, "
                    "then run layman again")
Exemple #3
0
    def test(self):
        tmpdir = tempfile.mkdtemp(prefix='laymantmp_')
        makeconf = os.path.join(tmpdir, 'make.conf')
        reposconf = os.path.join(tmpdir, 'repos.conf')

        make_txt =\
        'PORTDIR_OVERLAY="\n'\
        '$PORTDIR_OVERLAY"'

        # Create the .conf files so layman doesn't
        # complain.
        with fileopen(makeconf, 'w') as f:
            f.write(make_txt)

        with fileopen(reposconf, 'w') as f:
            f.write('')

        my_opts = {
            'installed': HERE + '/testfiles/global-overlays.xml',
            'make_conf': makeconf,
            'nocheck': 'yes',
            'storage': tmpdir,
            'repos_conf': reposconf,
            'conf_type': ['make.conf', 'repos.conf'],
        }

        config = OptionConfig(my_opts)
        config.set_option('quietness', 3)

        a = DB(config)
        config['output'].set_colorize(False)

        conf = RepoConfManager(config, a.overlays)

        # Set up our success tracker.
        success = []

        # Add all the overlays in global_overlays.xml.
        for overlay in a.overlays.keys():
            conf_success = conf.add(a.overlays[overlay])
            if conf_success == False:
                success.append(False)
            else:
                success.append(True)

        # Disable one overlay.
        self.assertTrue(conf.disable(a.overlays['wrobel']))

        # Enable disabled overlay.
        self.assertTrue(conf.enable(a.overlays['wrobel']))

        # Delete all the overlays in global_overlays.xml.
        for overlay in a.overlays.keys():
            self.assertTrue(conf.delete(a.overlays[overlay]))

        # Clean up.
        os.unlink(makeconf)
        os.unlink(reposconf)

        shutil.rmtree(tmpdir)
Exemple #4
0
    def test(self):
        repo_name = 'tar_test_overlay'
        temp_dir_path = tempfile.mkdtemp(prefix='laymantmp_')
        db_file = os.path.join(temp_dir_path, 'installed.xml')
        make_conf = os.path.join(temp_dir_path, 'make.conf')
        repo_conf = os.path.join(temp_dir_path, 'repos.conf')

        tar_source_path = os.path.join(HERE, 'testfiles',
                                       'layman-test.tar.bz2')

        (_, temp_tarball_path) = tempfile.mkstemp()
        shutil.copyfile(tar_source_path, temp_tarball_path)

        # Write overlay collection XML
        xml_text = '''\
<?xml version="1.0" encoding="UTF-8"?>
<repositories xmlns="" version="1.0">
  <repo quality="experimental" status="unofficial">
    <name>%(repo_name)s</name>
    <description>XXXXXXXXXXX</description>
    <owner>
      <email>[email protected]</email>
    </owner>
    <source type="tar">file://%(temp_tarball_url)s</source>
  </repo>
</repositories>
        '''\
        % {
            'temp_tarball_url': urllib.pathname2url(temp_tarball_path),
            'repo_name': repo_name
          }

        (fd, temp_xml_path) = tempfile.mkstemp()

        my_opts = {
            'installed': temp_xml_path,
            'conf_type': ['make.conf', 'repos.conf'],
            'db_type': 'xml',
            'nocheck': 'yes',
            'make_conf': make_conf,
            'repos_conf': repo_conf,
            'storage': temp_dir_path,
            'check_official': False
        }

        with os.fdopen(fd, 'w') as f:
            f.write(xml_text)

        with fileopen(make_conf, 'w') as f:
            f.write('PORTDIR_OVERLAY="$PORTDIR_OVERLAY"\n')

        with fileopen(repo_conf, 'w') as f:
            f.write('')

        config = OptionConfig(options=my_opts)
        config.set_option('quietness', 3)

        a = DB(config)
        config.set_option('installed', db_file)

        # Add an overlay to a fresh DB file.
        b = DB(config)
        b.add(a.select(repo_name))

        # Make sure it's actually installed.
        specific_overlay_path = os.path.join(temp_dir_path, repo_name)
        self.assertTrue(os.path.exists(specific_overlay_path))

        # Check the DbBase to ensure that it's reading the installed.xml.
        c = DbBase(config, paths=[
            db_file,
        ])
        self.assertEqual(list(c.overlays), ['tar_test_overlay'])

        # Make sure the configs have been written to correctly.
        conf = RepoConfManager(config, b.overlays)
        self.assertEqual(list(conf.overlays), ['tar_test_overlay'])

        # Delete the overlay from the second DB.
        b.delete(b.select(repo_name))
        self.assertEqual(b.overlays, {})

        # Ensure the installed.xml has been cleaned properly.
        c = DbBase(config, paths=[
            db_file,
        ])
        self.assertEqual(c.overlays, {})

        conf = RepoConfManager(config, b.overlays)
        self.assertEqual(conf.overlays, {})

        # Clean up.
        os.unlink(temp_xml_path)
        os.unlink(temp_tarball_path)
        shutil.rmtree(temp_dir_path)
Exemple #5
0
    def test(self):
        tmpdir = tempfile.mkdtemp(prefix='laymantmp_')
        makeconf = os.path.join(tmpdir, 'make.conf')
        reposconf = os.path.join(tmpdir, 'repos.conf')

        make_txt =\
        'PORTDIR_OVERLAY="\n'\
        '$PORTDIR_OVERLAY"'

        # Create the .conf files so layman doesn't
        # complain.
        with fileopen(makeconf, 'w') as f:
            f.write(make_txt)

        with fileopen(reposconf, 'w') as f:
            f.write('')

        my_opts = {
                   'installed' :
                   HERE + '/testfiles/global-overlays.xml',
                   'make_conf' : makeconf,
                   'nocheck'    : 'yes',
                   'storage'   : tmpdir,
                   'repos_conf' : reposconf,
                   'conf_type' : ['make.conf', 'repos.conf'],
                   }

        config = OptionConfig(my_opts)
        config.set_option('quietness', 3)

        a = DB(config)
        config['output'].set_colorize(False)

        conf = RepoConfManager(config, a.overlays)

        # Set up our success tracker.
        success = []

        # Add all the overlays in global_overlays.xml.
        for overlay in a.overlays.keys():
            conf_success = conf.add(a.overlays[overlay])
            if False in conf_success:
                success.append(False)
            else:
                success.append(True)

        # Disable one overlay.
        conf_success = conf.disable(a.overlays['wrobel'])
        if False in conf_success:
            success.append(False)
        else:
            success.append(True)

        # Enable disabled overlay.
        conf_success = conf.enable(a.overlays['wrobel'])
        if False in conf_success:
            success.append(False)
        else:
            success.append(True)
        # Delete all the overlays in global_overlays.xml.
        for overlay in a.overlays.keys():
            conf_success = conf.delete(a.overlays[overlay])
            if False in conf_success:
                success.append(False)
            else:
                success.append(True)

        # Clean up.
        os.unlink(makeconf)
        os.unlink(reposconf)

        shutil.rmtree(tmpdir)

        if False in success:
            success = False
        else:
            success = True

        self.assertTrue(success)
Exemple #6
0
class DB(DbBase):
    ''' Handle the list of installed overlays.'''

    def __init__(self, config):

        self.config = config
        self.output = config['output']

        self.path = config['installed']
        self.output.debug("DB.__init__(): config['installed'] = %s" % self.path, 3)

        if config['nocheck']:
            ignore = 2
        else:
            ignore = 1


        DbBase.__init__(self,
                          config,
                          paths=[config['installed'], ],
                          ignore=ignore,
                          )

        self.repo_conf = RepoConfManager(self.config, self.overlays)

        self.output.debug('DB handler initiated', 6)

        # check and handle the name change
        if not os.access(self.config['installed'], os.F_OK) and \
            os.access(self.config['local_list'], os.F_OK):
                self.output.die("Please run layman-updater, "
                    "then run layman again")


    # overrider
    def _broken_catalog_hint(self):
        return ''


    def _check_official(self, overlay):
        '''
        Prompt user to see if they want to install unofficial overlays.

        @params overlay: layman.overlays.Overlay object.
        @rtype bool: reflect the user's decision to install overlay.
        '''
        if self.config['check_official'] and not overlay.status == 'official':
            msg = 'Overlay "%(repo)s" is not an official. Continue install?'\
                  ' [y/n]: ' % {'repo': overlay.name}
            if not get_ans(msg, color='green'):
                msg = 'layman will not add "%(repo)s", due to user\'s'\
                      ' decision\nto not install unofficial overlays.'\
                      % {'repo': overlay.name}
                hint = 'Hint: To remove this check, set "check_official"'\
                       ' to "No"\nin your layman.cfg.'
                self.output.warn(msg)
                self.output.notice('')
                self.output.warn(hint)
                return False
            else:
                return True
        return True


    def add(self, overlay):
        '''
        Add an overlay to the local list of overlays.

        >>> import tempfile
        >>> tmpdir = tempfile.mkdtemp(prefix="laymantmp_")
        >>> write = os.path.join(tmpdir, 'installed.xml')
        >>> write2 = os.path.join(tmpdir, 'make.conf')
        >>> here = os.path.dirname(os.path.realpath(__file__))
        >>> from layman.config import OptionConfig
        >>> myoptions = {'installed' :
        ...           here + '/tests/testfiles/global-overlays.xml',
        ...           'local_list': here + '/tests/testfiles/overlays.xml',
        ...           'make_conf' : write2,
        ...           'nocheck'    : 'yes',
        ...           'storage'   : tmpdir}

        >>> config = OptionConfig(myoptions)
        >>> config.set_option('quietness', 3)
        >>> a = DB(config)
        >>> config.set_option('installed', write)
        >>> b = DB(config)
        >>> config['output'].set_colorize(False)

        >>> m = MakeConf(config, b.overlays)
        >>> m.path = write2
        >>> success = m.write()
        >>> success
        True

        # Commented out since it needs network access:

        # >>> b.add(a.select('wrobel-stable')) #doctest: +ELLIPSIS
        # * Running command "/usr/bin/rsync -rlptDvz --progress --delete --delete-after --timeout=180 --exclude="distfiles/*" --exclude="local/*" --exclude="packages/*" "rsync://gunnarwrobel.de/wrobel-stable/*" "/tmp/file.../wrobel-stable""...
        # >>> c = DbBase([write, ], dict())
        # >>> c.overlays.keys()
        # ['wrobel-stable']

        # >>> m = MakeConf(config, b.overlays)
        # >>> [i.name for i in m.overlays] #doctest: +ELLIPSIS
        # ['wrobel-stable']

        # >>> os.unlink(write)
        >>> os.unlink(write2)

        >>> import shutil
        >>> shutil.rmtree(tmpdir)
        '''

        if overlay.name not in self.overlays.keys():
            if not self._check_official(overlay):
                return False
            result = overlay.add(self.config['storage'])
            if result == 0:
                if 'priority' in self.config.keys():
                    overlay.set_priority(self.config['priority'])
                self.overlays[overlay.name] = overlay
                self.write(self.path)
                repo_ok = self.repo_conf.add(overlay)
                if False in repo_ok:
                    return False
                return True
            else:
                mdir = path([self.config['storage'], overlay.name])
                delete_empty_directory(mdir, self.output)
                if os.path.exists(mdir):
                    self.output.error('Adding repository "%s" failed!'
                                ' Possible remains of the operation have NOT'
                                ' been removed and may be left at "%s".'
                                ' Please remove them manually if required.' \
                                % (overlay.name, mdir))
                    return False
                else:
                    self.output.error(
                        'Adding repository "%s" failed!' % overlay.name)
                    return False
        else:
            self.output.error('Repository "' + overlay.name +
                '" already in the local (installed) list!')
            return False


    def delete(self, overlay):
        '''
        Add an overlay to the local list of overlays.

        >>> import tempfile
        >>> tmpdir = tempfile.mkdtemp(prefix="laymantmp_")
        >>> write = os.path.join(tmpdir, 'installed.xml')
        >>> write2 = os.path.join(tmpdir, 'make.conf')
        >>> here = os.path.dirname(os.path.realpath(__file__))
        >>> from layman.config import OptionConfig
        >>> myoptions = {'installed' :
        ...           here + '/tests/testfiles/global-overlays.xml',
        ...           'local_list': here + '/tests/testfiles/overlays.xml',
        ...           'make_conf' : write2,
        ...           'nocheck'    : 'yes',
        ...           'storage'   : tmpdir}

        >>> config = OptionConfig(myoptions)
        >>> config.set_option('quietness', 3)
        >>> a = DB(config)
        >>> config.set_option('installed', write)
        >>> b = DB(config)
        >>> config['output'].set_colorize(False)

        >>> m = MakeConf(config, b.overlays)
        >>> m.path = here + '/tests/testfiles/make.conf'
        >>> m.read()
        True

        >>> m.path = write2
        >>> m.write()
        True

        # >>> b.add(a.select('wrobel-stable')) #doctest: +ELLIPSIS
        # * Running command "/usr/bin/rsync -rlptDvz --progress --delete --delete-after --timeout=180 --exclude="distfiles/*" --exclude="local/*" --exclude="packages/*" "rsync://gunnarwrobel.de/wrobel-stable/*" "/tmp/file.../wrobel-stable""...
        # >>> b.add(a.select('wrobel')) #doctest: +ELLIPSIS
        # * Running command "/usr/bin/svn co "https://overlays.gentoo.org/svn/dev/wrobel/" "/tmp/file.../wrobel""...
        # >>> c = DbBase([write, ], dict())
        # >>> c.overlays.keys()
        # ['wrobel', 'wrobel-stable']

        # >>> b.delete(b.select('wrobel'))
        # >>> c = DbBase([write, ], dict())
        # >>> c.overlays.keys()
        # ['wrobel-stable']

        # >>> m = MakeConf(config, b.overlays)
        # >>> [i.name for i in m.overlays] #doctest: +ELLIPSIS
        # ['wrobel-stable']

        # >>> os.unlink(write)
        >>> os.unlink(write2)

        >>> import shutil
        >>> shutil.rmtree(tmpdir)
        '''

        if overlay.name in self.overlays.keys():
            overlay.delete(self.config['storage'])
            repo_ok = self.repo_conf.delete(overlay)
            del self.overlays[overlay.name]
            self.write(self.path)
        else:
            self.output.error('No local overlay named "' + overlay.name + '"!')
            return False
        if False in repo_ok:
            return False
        return True


    def disable(self, overlay):
        if overlay.name in self.overlays.keys():
            result = self.repo_conf.disable(overlay)
        else:
            self.output.error('No local overlay named "%(repo)s"!'\
                % ({'repo': overlay.name}))
            return False
        msg = 'Overlay %(repo)s has been disabled.\n'\
              'All ebuilds in this overlay will not be recognized by portage.'\
              % ({'repo': overlay.name})
        if result:
            self.output.warn(msg)
        return result


    def enable(self, overlay):
        if overlay.name in self.overlays.keys():
            result = self.repo_conf.enable(overlay)
        else:
            self.output.error('No local overlay named "%(repo)s"!'\
                % ({'repo': overlay.name}))
            return False
        msg = 'Overlay %(repo)s has been enabled.\n'\
              'All ebuilds in this overlay will now be recognized by portage.'\
              % ({'repo': overlay.name})
        if result:
            self.output.info(msg)
        return result


    def update(self, overlay, available_srcs):
        '''
        Updates the overlay source via the available source(s).

        @params overlay: layman.overlay.Overlay object.
        @params available_srcs: set of available source URLs.
        '''

        source, result = self.overlays[overlay.name].update(self.config['storage'],
                                                    available_srcs)
        result = [result]
        self.overlays[overlay.name].sources = source
        result.extend(self.repo_conf.update(self.overlays[overlay.name]))
        self.write(self.path)

        if False in result:
            return False
        return True



    def sync(self, overlay_name):
        '''Synchronize the given overlay.'''

        overlay = self.select(overlay_name)
        result = overlay.sync(self.config['storage'])
        if result:
            raise Exception('Syncing overlay "' + overlay_name +
                            '" returned status ' + str(result) + '!' +
                            '\ndb.sync()')
Exemple #7
0
class DB(DbBase):
    ''' Handle the list of installed overlays.'''

    def __init__(self, config):

        self.config = config
        self.output = config['output']

        self.path = config['installed']
        self.output.debug("DB.__init__(): config['installed'] = %s" % self.path, 3)

        if config['nocheck']:
            ignore = 2
        else:
            ignore = 1


        DbBase.__init__(self,
                          config,
                          paths=[config['installed'], ],
                          ignore=ignore,
                          allow_missing=True,
                          )

        self.repo_conf = RepoConfManager(self.config, self.overlays)

        self.output.debug('DB handler initiated', 6)

        # check and handle the name change
        if not os.access(self.config['installed'], os.F_OK) and \
            os.access(self.config['local_list'], os.F_OK):
                self.output.die("Please run layman-updater, "
                    "then run layman again")


    # overrider
    def _broken_catalog_hint(self):
        return ''


    def _check_official(self, overlay):
        '''
        Prompt user to see if they want to install unofficial overlays.

        @params overlay: layman.overlays.Overlay object.
        @rtype bool: reflect the user's decision to install overlay.
        '''
        if self.config['check_official'] and not overlay.status == 'official':
            msg = 'Overlay "%(repo)s" is not official. Continue installing?'\
                  ' [y/n]: ' % {'repo': overlay.name}
            if not get_ans(msg, color='green'):
                msg = 'layman will not add "%(repo)s", due to user\'s'\
                      ' decision\nto not install unofficial overlays.'\
                      % {'repo': overlay.name}
                hint = 'Hint: To remove this check, set "check_official"'\
                       ' to "No"\nin your layman.cfg.'
                self.output.warn(msg)
                self.output.notice('')
                self.output.warn(hint)
                return False
            else:
                return True
        return True


    def add(self, overlay):
        '''
        Add an overlay to the local list of overlays.
        '''
        if overlay.name not in self.overlays.keys():
            if not self._check_official(overlay):
                return False
            result = overlay.add(self.config['storage'])
            if result == 0:
                if 'priority' in self.config.keys():
                    overlay.set_priority(self.config['priority'])
                self.overlays[overlay.name] = overlay
                self.write(self.path)
                repo_ok = self.repo_conf.add(overlay)
                if False in repo_ok:
                    return False
                return True
            else:
                mdir = path([self.config['storage'], overlay.name])
                delete_empty_directory(mdir, self.output)
                if os.path.exists(mdir):
                    self.output.error('Adding repository "%s" failed!'
                                ' Possible remains of the operation have NOT'
                                ' been removed and may be left at "%s".'
                                ' Please remove them manually if required.' \
                                % (overlay.name, mdir))
                    return False
                else:
                    self.output.error(
                        'Adding repository "%s" failed!' % overlay.name)
                    return False
        else:
            self.output.error('Repository "' + overlay.name +
                '" already in the local (installed) list!')
            return False


    def delete(self, overlay):
        '''
        Delete an overlay from the local list of overlays.
        '''
        if overlay.name in self.overlays.keys():
            overlay.delete(self.config['storage'])
            repo_ok = self.repo_conf.delete(overlay)
            self.remove(overlay, self.path)
            self.write(self.path, remove=True)
        else:
            self.output.error('No local overlay named "' + overlay.name + '"!')
            return False
        if False in repo_ok:
            return False
        return True


    def disable(self, overlay):
        if overlay.name in self.overlays.keys():
            result = self.repo_conf.disable(overlay)
        else:
            self.output.error('No local overlay named "%(repo)s"!'\
                % ({'repo': overlay.name}))
            return False
        msg = 'Overlay %(repo)s has been disabled.\n'\
              'All ebuilds in this overlay will not be recognized by portage.'\
              % ({'repo': overlay.name})
        if result:
            self.output.warn(msg)
        return result


    def enable(self, overlay):
        if overlay.name in self.overlays.keys():
            result = self.repo_conf.enable(overlay)
        else:
            self.output.error('No local overlay named "%(repo)s"!'\
                % ({'repo': overlay.name}))
            return False
        msg = 'Overlay %(repo)s has been enabled.\n'\
              'All ebuilds in this overlay will now be recognized by portage.'\
              % ({'repo': overlay.name})
        if result:
            self.output.info(msg)
        return result


    def update(self, overlay, available_srcs):
        '''
        Updates the overlay source via the available source(s).

        @params overlay: layman.overlay.Overlay object.
        @params available_srcs: set of available source URLs.
        '''

        source, result = self.overlays[overlay.name].update(self.config['storage'],
                                                    available_srcs)
        result = [result]
        self.overlays[overlay.name].sources = source
        result.extend(self.repo_conf.update(self.overlays[overlay.name]))
        self.write(self.path)

        if False in result:
            return False
        return True



    def sync(self, overlay_name):
        '''Synchronize the given overlay.'''

        overlay = self.select(overlay_name)
        result = overlay.sync(self.config['storage'])
        if result:
            raise Exception('Syncing overlay "' + overlay_name +
                            '" returned status ' + str(result) + '!' +
                            '\ndb.sync()')
Exemple #8
0
class DB(DbBase):
    ''' Handle the list of installed overlays.'''
    def __init__(self, config):

        self.config = config
        self.output = config['output']

        self.path = config['installed']
        self.output.debug(
            "DB.__init__(): config['installed'] = %s" % self.path, 3)

        if config['nocheck']:
            ignore = 2
        else:
            ignore = 1

        DbBase.__init__(
            self,
            config,
            paths=[
                config['installed'],
            ],
            ignore=ignore,
            allow_missing=True,
        )

        self.repo_conf = RepoConfManager(self.config, self.overlays)

        self.output.debug('DB handler initiated', 6)

        # check and handle the name change
        if not os.access(self.config['installed'], os.F_OK) and \
            os.access(self.config['local_list'], os.F_OK):
            self.output.die("Please run layman-updater, "
                            "then run layman again")

    # overrider
    def _broken_catalog_hint(self):
        return ''

    def _check_official(self, overlay):
        '''
        Prompt user to see if they want to install unofficial overlays.

        @params overlay: layman.overlays.Overlay object.
        @rtype bool: reflect the user's decision to install overlay.
        '''
        if self.config['check_official'] and not overlay.status == 'official':
            msg = 'Overlay "%(repo)s" is not official. Continue installing?'\
                  ' [y/n]: ' % {'repo': overlay.name}
            if not get_ans(msg, color='green'):
                msg = 'layman will not add "%(repo)s", due to user\'s'\
                      ' decision\nto not install unofficial overlays.'\
                      % {'repo': overlay.name}
                hint = 'Hint: To remove this check, set "check_official"'\
                       ' to "No"\nin your layman.cfg.'
                self.output.warn(msg)
                self.output.notice('')
                self.output.warn(hint)
                return False
            else:
                return True
        return True

    def add(self, overlay):
        '''
        Add an overlay to the local list of overlays.
        '''
        if overlay.name not in self.overlays.keys():
            if not self._check_official(overlay):
                return False
            result = overlay.add(self.config['storage'])
            if result == 0:
                if 'priority' in self.config.keys():
                    overlay.set_priority(self.config['priority'])
                self.overlays[overlay.name] = overlay
                self.write(self.path)
                repo_ok = self.repo_conf.add(overlay)
                if False in repo_ok:
                    return False
                return True
            else:
                mdir = path([self.config['storage'], overlay.name])
                delete_empty_directory(mdir, self.output)
                if os.path.exists(mdir):
                    self.output.error('Adding repository "%s" failed!'
                                ' Possible remains of the operation have NOT'
                                ' been removed and may be left at "%s".'
                                ' Please remove them manually if required.' \
                                % (overlay.name, mdir))
                    return False
                else:
                    self.output.error('Adding repository "%s" failed!' %
                                      overlay.name)
                    return False
        else:
            self.output.error('Repository "' + overlay.name +
                              '" already in the local (installed) list!')
            return False

    def delete(self, overlay):
        '''
        Delete an overlay from the local list of overlays.
        '''
        if overlay.name in self.overlays.keys():
            overlay.delete(self.config['storage'])
            repo_ok = self.repo_conf.delete(overlay)
            self.remove(overlay, self.path)
            self.write(self.path, remove=True)
        else:
            self.output.error('No local overlay named "' + overlay.name + '"!')
            return False
        if False in repo_ok:
            return False
        return True

    def disable(self, overlay):
        if overlay.name in self.overlays.keys():
            result = self.repo_conf.disable(overlay)
        else:
            self.output.error('No local overlay named "%(repo)s"!'\
                % ({'repo': overlay.name}))
            return False
        msg = 'Overlay %(repo)s has been disabled.\n'\
              'All ebuilds in this overlay will not be recognized by portage.'\
              % ({'repo': overlay.name})
        if result:
            self.output.warn(msg)
        return result

    def enable(self, overlay):
        if overlay.name in self.overlays.keys():
            result = self.repo_conf.enable(overlay)
        else:
            self.output.error('No local overlay named "%(repo)s"!'\
                % ({'repo': overlay.name}))
            return False
        msg = 'Overlay %(repo)s has been enabled.\n'\
              'All ebuilds in this overlay will now be recognized by portage.'\
              % ({'repo': overlay.name})
        if result:
            self.output.info(msg)
        return result

    def update(self, overlay, available_srcs):
        '''
        Updates the overlay source via the available source(s).

        @params overlay: layman.overlay.Overlay object.
        @params available_srcs: set of available source URLs.
        '''

        source, result = self.overlays[overlay.name].update(
            self.config['storage'], available_srcs)
        result = [result]
        self.overlays[overlay.name].sources = source
        result.extend(self.repo_conf.update(self.overlays[overlay.name]))
        self.write(self.path)

        if False in result:
            return False
        return True

    def sync(self, overlay_name):
        '''Synchronize the given overlay.'''

        overlay = self.select(overlay_name)
        result = overlay.sync(self.config['storage'])
        if result:
            raise Exception('Syncing overlay "' + overlay_name +
                            '" returned status ' + str(result) + '!' +
                            '\ndb.sync()')