<commit_before>#
# Copyright (c) 2010 rPath, Inc.
#
# All Rights Reserved
#

import datetime
from dateutil import tz

from conary import conaryclient
from conary import versions

from mint.django_rest.rbuilder.inventory import models

import base

class VersionManager(base.BaseManager):
    """
    Class encapsulating all logic around versions, available updates, etc.
    """
    
    def __init__(self, *args, **kwargs):
        base.BaseManager.__init__(self, *args, **kwargs)
        self._cclient = None

    def get_software_versions(self, system):
        pass

    def delete_installed_software(self, system):
        system.installed_software.all().delete()

    def _diffVersions(self, system, new_versions):
        oldInstalled = dict((x.getNVF(), x)
            for x in system.installed_software.all())

        # Do the delta
        toAdd = []
        newInstalled = []
        for new_version in new_versions:
            if isinstance(new_version, basestring):
                trove = self.trove_from_nvf(new_version)
            else:
                trove = new_version
            nvf = trove.getNVF()
            isInst = oldInstalled.pop(nvf, None)
            if isInst is None:
                toAdd.append(trove)
            newInstalled.append(nvf)

        return oldInstalled, newInstalled, toAdd

    @base.exposed
    def setInstalledSoftware(self, system, new_versions):
        oldInstalled, newInstalled, toAdd = \
            self._diffVersions(system, new_versions)
        for trove in oldInstalled.itervalues():
            system.installed_software.remove(trove)
        for trove in toAdd:
            system.installed_software.add(trove)
        for trove in system.installed_software.all():
            self.set_available_updates(trove, force=True)
        system.save()

    @base.exposed
    def updateInstalledSoftware(self, system, new_versions):
        oldInstalled, newInstalled, toAdd = \
            self._diffVersions(system, new_versions)
        sources = []
        for nvf in newInstalled:
            n, v, f = nvf
            sources.append("%s=%s[%s]" % (n, str(v), str(f)))
        self.mgr.scheduleSystemApplyUpdateEvent(system, sources)

    def trove_from_nvf(self, nvf):
        n, v, f = conaryclient.cmdline.parseTroveSpec(nvf)
        f = str(f)

        thawed_v = versions.ThawVersion(v)
        version = models.Version()
        version.fromConaryVersion(thawed_v)
        version.flavor = f

        trove = models.Trove()
        trove.name = n
        trove.version = version
        trove.flavor = f
        return trove

    @classmethod
    def _trove(cls, trove):
        """
        If the trove is new, save it to the db, otherwise return the existing
        one
        """
        # XXX unused
        # First, make sure the flavor is part of the version object
        if not trove.version.flavor:
            trove.version.flavor = trove.flavor
        created, version = models.Version.objects.load_or_create(trove.version)
        trove.version = version
        created, trove = models.Trove.objects.load_or_create(trove)
        return trove

    def cache_available_update(self, nvf, update_nvf):
        trove = self.trove_from_nvf(nvf)
        update_trove = self.trove_from_nvf(update_nvf)
        available_update, created = models.AvailableUpdate.get_or_create(
            trove=trove, trove_available_update=update_trove)
        available_update.save()

    def clear_cached_updates(self, nvf):
        trove = self.trove_from_nvf(nvf)
        trove.available_updates.all().delete()

    def get_conary_client(self):
        if self._cclient is None:
            self._cclient = self.rest_db.productMgr.reposMgr.getUserClient()
        return self._cclient

    @base.exposed
    def set_available_updates(self, trove, force=False):
        one_day = datetime.timedelta(1)

        # Hack to make sure utc is set as the timezone on
        # last_available_update_refresh.
        if trove.last_available_update_refresh is not None:
            trove.last_available_update_refresh = \
                trove.last_available_update_refresh.replace(tzinfo=tz.tzutc())

        if force or trove.last_available_update_refresh is None:
            self.refresh_available_updates(trove)
            trove.last_available_update_refresh = \
                datetime.datetime.now(tz.tzutc())
            trove.save()
            return

        if (trove.last_available_update_refresh + one_day) < \
            datetime.datetime.now(tz.tzutc()):
            self.refresh_available_updates(trove)
            trove.last_available_update_refresh = \
                datetime.datetime.now(tz.tzutc())
            trove.save()

    def refresh_available_updates(self, trove):
        self.cclient = self.get_conary_client()
        # trvName and trvVersion are str's, trvFlavor is a
        # conary.deps.deps.Flavor.
        trvName = trove.name
        trvVersion = trove.version.conaryVersion
        trvFlavor = trove.getFlavor()
        trvLabel = trove.getLabel()

        # Search the label for the trove of the top level item.  It should
        # only (hopefully) return 1 result.
        troves = self.cclient.repos.findTroves(trvLabel,
            [(trvName, trvVersion, trvFlavor)])
        assert(len(troves) == 1)

        # findTroves returns a {} with keys of (name, version, flavor), values<commit_msg>Don't fail if we can't contact the conary repository to check for available updates, log the error and continue<commit_after>#
# Copyright (c) 2010 rPath, Inc.
#
# All Rights Reserved
#

import datetime
import logging
from dateutil import tz

from conary import conaryclient
from conary import versions
from conary.errors import RepositoryError

from mint.django_rest.rbuilder.inventory import models

import base

log = logging.getLogger(__name__)

class VersionManager(base.BaseManager):
    """
    Class encapsulating all logic around versions, available updates, etc.
    """
    
    def __init__(self, *args, **kwargs):
        base.BaseManager.__init__(self, *args, **kwargs)
        self._cclient = None

    def get_software_versions(self, system):
        pass

    def delete_installed_software(self, system):
        system.installed_software.all().delete()

    def _diffVersions(self, system, new_versions):
        oldInstalled = dict((x.getNVF(), x)
            for x in system.installed_software.all())

        # Do the delta
        toAdd = []
        newInstalled = []
        for new_version in new_versions:
            if isinstance(new_version, basestring):
                trove = self.trove_from_nvf(new_version)
            else:
                trove = new_version
            nvf = trove.getNVF()
            isInst = oldInstalled.pop(nvf, None)
            if isInst is None:
                toAdd.append(trove)
            newInstalled.append(nvf)

        return oldInstalled, newInstalled, toAdd

    @base.exposed
    def setInstalledSoftware(self, system, new_versions):
        oldInstalled, newInstalled, toAdd = \
            self._diffVersions(system, new_versions)
        for trove in oldInstalled.itervalues():
            system.installed_software.remove(trove)
        for trove in toAdd:
            system.installed_software.add(trove)
        for trove in system.installed_software.all():
            self.set_available_updates(trove, force=True)
        system.save()

    @base.exposed
    def updateInstalledSoftware(self, system, new_versions):
        oldInstalled, newInstalled, toAdd = \
            self._diffVersions(system, new_versions)
        sources = []
        for nvf in newInstalled:
            n, v, f = nvf
            sources.append("%s=%s[%s]" % (n, str(v), str(f)))
        self.mgr.scheduleSystemApplyUpdateEvent(system, sources)

    def trove_from_nvf(self, nvf):
        n, v, f = conaryclient.cmdline.parseTroveSpec(nvf)
        f = str(f)

        thawed_v = versions.ThawVersion(v)
        version = models.Version()
        version.fromConaryVersion(thawed_v)
        version.flavor = f

        trove = models.Trove()
        trove.name = n
        trove.version = version
        trove.flavor = f
        return trove

    @classmethod
    def _trove(cls, trove):
        """
        If the trove is new, save it to the db, otherwise return the existing
        one
        """
        # XXX unused
        # First, make sure the flavor is part of the version object
        if not trove.version.flavor:
            trove.version.flavor = trove.flavor
        created, version = models.Version.objects.load_or_create(trove.version)
        trove.version = version
        created, trove = models.Trove.objects.load_or_create(trove)
        return trove

    def cache_available_update(self, nvf, update_nvf):
        trove = self.trove_from_nvf(nvf)
        update_trove = self.trove_from_nvf(update_nvf)
        available_update, created = models.AvailableUpdate.get_or_create(
            trove=trove, trove_available_update=update_trove)
        available_update.save()

    def clear_cached_updates(self, nvf):
        trove = self.trove_from_nvf(nvf)
        trove.available_updates.all().delete()

    def get_conary_client(self):
        if self._cclient is None:
            self._cclient = self.rest_db.productMgr.reposMgr.getUserClient()
        return self._cclient

    @base.exposed
    def set_available_updates(self, trove, force=False):
        one_day = datetime.timedelta(1)

        # Hack to make sure utc is set as the timezone on
        # last_available_update_refresh.
        if trove.last_available_update_refresh is not None:
            trove.last_available_update_refresh = \
                trove.last_available_update_refresh.replace(tzinfo=tz.tzutc())

        if force or trove.last_available_update_refresh is None:
            self.refresh_available_updates(trove)
            trove.last_available_update_refresh = \
                datetime.datetime.now(tz.tzutc())
            trove.save()
            return

        if (trove.last_available_update_refresh + one_day) < \
            datetime.datetime.now(tz.tzutc()):
            self.refresh_available_updates(trove)
            trove.last_available_update_refresh = \
                datetime.datetime.now(tz.tzutc())
            trove.save()

    def refresh_available_updates(self, trove):
        self.cclient = self.get_conary_client()
        # trvName and trvVersion are str's, trvFlavor is a
        # conary.deps.deps.Flavor.
        trvName = trove.name
        trvVersion = trove.version.conaryVersion
        trvFlavor = trove.getFlavor()
        trvLabel = trove.getLabel()

        # Search the label for the trove of the top level item.  It should
        # only (hopefully) return 1 result.
        try:
            troves = self.cclient.repos.findTroves(trvLabel,
                [(trvName, trvVersion, trvFlavor)])
        except RepositoryError, e:
            log.error("Error contacting repository to look for available " + \
                "updates for %s=%s[%s]" % (trvName, trvLabel, trvFlavor))
            log.error(e)
            return
        assert(len(troves) == 1)

        # findTroves returns a {} with keys of (name, version, flavor), values
{'fraction_non_alphanumeric': 0.08725011106175033, 'fraction_numerical': 0.001243891603731675, 'mean_word_length': 2.341050756901158, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '253686', 'n_tokens_mistral': 3516, 'n_tokens_neox': 3349, 'n_words': 758}