def _fullMigrate(self, itemList, uJob, recurse=True):
        def _convertRedirects(searchSource, newTroves):
            troveNames = set(x.getName() for x in newTroves)
            redirects = [ x for x in newTroves if x.isRedirect() ]
            nonRedirects = [ x for x in newTroves if not x.isRedirect() ]
            if not redirects:
                return newTroves, troveNames

            redirectMap = {}
            toFind = {}
            for trv in redirects:
                redirTup = trv.getNameVersionFlavor()
                redirectMap[redirTup] = [redirTup]
                for troveName, branch, flavor in trv.iterRedirects():
                    troveSpec = (troveName, str(branch), flavor)
                    toFind.setdefault(troveSpec, []).append(redirTup)

            if not toFind:
                if not nonRedirects:
                    err = ("Cannot migrate to redirect(s), as they are all"
                           " erases - \n%s" % \
                           "\n".join("%s=%s[%s]" % x.getNameVersionFlavor()
                                     for x in redirects))
                    raise UpdateError(err)
                else:
                    return nonRedirects, troveNames

            while toFind:
                matches = searchSource.findTroves(toFind, useAffinity=True)
                allTroveTups = list(set(itertools.chain(*matches.itervalues())))
                allTroves = searchSource.getTroves(allTroveTups)
                allTroves = dict(itertools.izip(allTroveTups, allTroves))

                newToFind = {}
                for troveSpec, troveTupList in matches.iteritems():
                    for troveTup in troveTupList:
                        redirTups = toFind[troveSpec]
                        for redirTup in redirTups:
                            if redirTup == troveTup:
                                err = "Redirect Loop detected - trove %s=%s[%s] redirects to itself" % redirTup
                                raise UpdateError(err)
                            elif redirTup in redirectMap.get(troveTup, []):
                                err = "Redirect Loop detected - "
                                err += "includes %s=%s[%s] and %s=%s[%s]" % (redirTup + troveTup)
                                raise UpdateError(err)
                            else:
                                redirectMap.setdefault(troveTup, []).append(redirTup)
                        trv = allTroves[troveTup]
                        if trv.isRedirect():
                            for troveName, branch, flavor in trv.iterRedirects():
                                newTroveSpec = (troveName, str(branch), flavor)
                                newToFind.setdefault(newTroveSpec, []).append(troveTup)
                        else:
                            nonRedirects.append(trv)
                            troveNames.add(trv.getName())
                toFind = newToFind
            return set(nonRedirects), troveNames

        def _getTrovesToBeMigrated(db, troves, troveNames):
            """
                Gets the list of troves on the system
                that will be migrated to the new troves in the update
                job (just the top level troves)
            """
            # perform a diff of toplevel troves to find out
            # what version of the troves on the system will be updated.
            existsTrv = trove.Trove("@update", versions.NewVersion(),
                                    deps.Flavor(), None)
            availableTrv = trove.Trove("@update", versions.NewVersion(),
                                         deps.Flavor(), None)
            existsTups = []
            availTups = []
            for troveNVF in db.findByNames(troveNames):
                existsTups.append(troveNVF)
                existsTrv.addTrove(*troveNVF)

            for trv in troves:
                availTups.append(trv.getNameVersionFlavor())
                availableTrv.addTrove(*trv.getNameVersionFlavor())

            oldTroves = set(existsTups) & set(availTups) # oldVer == newVer
                                                         # won't show up in
                                                         # the diff, so grab
                                                         # separately
            jobs = availableTrv.diff(existsTrv)[2]

            oldTroves.update((x[0], x[1][0], x[1][1]) for x in jobs if x[1][0])

            return db.getTroves(oldTroves, withFiles=False)

        def _updateByDefaultFromIncludedGroups(potentialJobs, byDefaultFalseSet,
                                            availByDefaultInfo, searchSource):
            # Find included groups that are byDefault False in the old
            # group structure (but are installed anyway) and keeps them
            # installed, and treats them as if they also had been referenced
            # on the migrate line (meaning all included packages are also
            # installed)
            groupJobs = [ x for x in potentialJobs if trove.troveIsGroup(x[0]) ]
            if not groupJobs:
                return
            oldGroups = []
            newGroups = []
            for job in groupJobs:
                newInfo = (job[0], job[2][0], job[2][1])
                oldInfo = (job[0], job[1][0], job[1][1])
                if not job[2][0] or not job[1][0]:
                    continue
                if availByDefaultInfo[newInfo]:
                    continue
                if (oldInfo in byDefaultFalse
                    and  trove.troveIsGroup(job[0])):
                    oldGroups.append(oldInfo)
                    newGroups.append(newInfo)
                    availByDefaultInfo[newInfo] = True
            newGroups = searchSource.getTroves(newGroups, withFiles=False)
            oldGroups = self.db.getTroves(oldGroups, withFiles=False)

            for trv in newGroups:
                for (troveNVF, byDefault, isWeak) in trv.iterTroveListInfo():
                    # possibly turn more troves to availableByDefault
                    # if they're byDefault True in this subgroup.
                    availByDefaultInfo.update(dict.fromkeys((x[0] for x in trv.iterTroveListInfo() if x[1]), True))
            byDefaultTrue = []
            for trv in oldGroups:
                troveList = list(trv.iterTroveListInfo())
                troveTups = [x[0] for x in troveList]
                hasTroves = self.db.hasTroves(troveTups)
                troveList = (x[0] for x in itertools.izip(troveList, hasTroves) if x[1])
                byDefaultTrue.extend(x[0] for x in troveList if x[1])
            byDefaultFalse.difference_update(byDefaultTrue)



        toFind = []
        for item in itemList:
            (troveName, (oldVersionStr, oldFlavorStr),
                        (newVersionStr, newFlavorStr), isAbsolute) = item
            if (not isAbsolute and oldVersionStr) or troveName[0] == '-':
                raise UpdateError('Cannot perform relative updates '
                                  'or erases as part of full migration')
            toFind.append((troveName, newVersionStr, newFlavorStr))

        searchSource = uJob.getSearchSource()

        results = searchSource.findTroves(toFind, useAffinity=True)
        newTroves = list(set(itertools.chain(*results.itervalues())))
        newTroves = searchSource.getTroves(newTroves, withFiles=False)

        newTroves, troveNames = _convertRedirects(searchSource, newTroves)

        updateSet = []

        availByDefaultInfo = {}

        for trv in newTroves:
            updateSet.append(trv.getNameVersionFlavor())
            availByDefaultInfo[trv.getNameVersionFlavor()] = True
            if not recurse:
                continue
            for (troveNVF, byDefault, isWeak) in trv.iterTroveListInfo():
                updateSet.append(troveNVF)
                if byDefault:
                    availByDefaultInfo[troveNVF] = True
                else:
                    availByDefaultInfo.setdefault(troveNVF, False)

        # We keep groups that you have installed manually (and anything
        # included in those groups as well as kernels.
        # Anything else that is installed manually will be removed.
        # All the following code is to preserve groups and kernels.
        toBeMigrated = _getTrovesToBeMigrated(self.db, newTroves, troveNames)

        byDefaultFalse = []
        byDefaultTrue = []
        count = 0
        for trv in toBeMigrated:
            if not recurse:
                continue
            troveList = list(trv.iterTroveListInfo())

            troveTups = [x[0] for x in troveList]
            hasTroves = self.db.hasTroves(troveTups)
            troveList = (x[0] for x in itertools.izip(troveList, hasTroves) if x[1])
            for (troveNVF, byDefault, isWeak) in troveList:
                count += 1
                if not byDefault:
                    byDefaultFalse.append(troveNVF)
                else:
                    byDefaultTrue.append(troveNVF)
        byDefaultFalse = set(byDefaultFalse)
        byDefaultFalse.difference_update(byDefaultTrue)
        del byDefaultTrue

        updateSet = set(updateSet)
        eraseSet = set(self.db.iterAllTroves())
        toKeep = eraseSet & updateSet
        updateSet.difference_update(toKeep)
        eraseSet.difference_update(toKeep)

        existsTrv = trove.Trove("@update", versions.NewVersion(),
                                deps.Flavor(), None)
        availableTrv = trove.Trove("@update", versions.NewVersion(),
                                     deps.Flavor(), None)
        for troveNVF in updateSet:
            availableTrv.addTrove(*troveNVF)
        for troveNVF in eraseSet:
            existsTrv.addTrove(*troveNVF)
        potentialJobs = availableTrv.diff(existsTrv)[2]
        potentialJobs += [(x[0], (x[1], x[2]), (x[1], x[2]), False) for x in toKeep]
        if recurse:
            _updateByDefaultFromIncludedGroups(potentialJobs,
                                               byDefaultFalse,
                                               availByDefaultInfo,
                                               searchSource)
        finalJobs = []
        for job in potentialJobs:
            newInfo = (job[0], job[2][0], job[2][1])
            oldInfo = (job[0], job[1][0], job[1][1])
            if not job[1][0]:
                if not availByDefaultInfo[newInfo]:
                    # only install byDefault True
                    continue
            elif job[2][0]:
                if availByDefaultInfo[newInfo]:
                    pass
                elif (oldInfo in byDefaultFalse and
                      (job[0].split(':')[0] == 'kernel'
                        or trove.troveIsGroup(job[0]))):
                    pass
                else:
                    # new version is byDefault False and old version
                    # is not byDefault False and a group or and kernel
                    # (the two special cases that are allowed to remain
                    # installed if they're byDefault False)
                    finalJobs.append((job[0], job[1], (None, None), False))
                    continue
            if job[1] != job[2]:
                finalJobs.append(job)


        for troveNVF in toKeep:
            if (not availByDefaultInfo[troveNVF]
                and troveNVF not in byDefaultFalse):
                finalJobs.append((troveNVF[0], (troveNVF[1], troveNVF[2]),
                                 (None, None), False))
        finalJobs = set(finalJobs)

        if not finalJobs:
            raise NoNewTrovesError

        updateJobs = set(x for x in finalJobs if x[2][0])

        removalJobs = [ x for x in finalJobs if x[1][0] ]

        pins = self.db.trovesArePinned([(x[0], x[1][0], x[1][1])
                                        for x in removalJobs])

        csSource = trovesource.stack(uJob.getSearchSource(), self.repos)

        for job, isPinned in itertools.izip(removalJobs, pins):
            if isPinned:
                if not job[2][0]:
                    # this is an erasure of a pinned trove skip it.
                    finalJobs.remove(job)
                    continue

                newJob = self._splitPinnedJob(uJob, csSource, job, force=True)
                if newJob is not None:
                    finalJobs.remove(job)
                    updateJobs.remove(job)
                    finalJobs.add(newJob)
                    updateJobs.add(newJob)
                else:
                    # we can't update this because of the pin.
                    # just leave the old version in place.
                    finalJobs.remove(job)
                    updateJobs.remove(job)

        updateJobs = list(updateJobs)
        hasTroves = uJob.getTroveSource().hasTroves(
            [ (x[0], x[2][0], x[2][1]) for x in updateJobs ] )

        reposChangeSetList = set([ x[1] for x in
                          itertools.izip(hasTroves, updateJobs)
                           if x[0] is not True ])

        cs, notFound = csSource.createChangeSet(reposChangeSetList,
                                                withFiles = False,
                                                recurse = False,
                                                callback = self.updateCallback)
        if notFound:
            self._trovesNotFound(notFound) # may raise an error
                                           # if there are non-local troves
                                           # in the list
            reposChangeSetList.difference_update(notFound)
            if not reposChangeSetList:
                raise NoNewTrovesError

        troveSource = uJob.getTroveSource()
        self._replaceIncomplete(cs, csSource, self.db, self.repos)
        troveSource.addChangeSet(cs)

        # XXX this is horrible; we probablt have everything we need already,
        # I just don't know how to find it
        infoCs = troveSource.createChangeSet(finalJobs, withFiles = False)

        assert(not infoCs[1])
        infoCs = infoCs[0]

        troveSourceCallback = lambda x: infoCs

        self._processJobList(finalJobs, uJob, troveSourceCallback)
        return finalJobs
dataset/ETHPy150Open sassoftware/conary/conary/conaryclient/update.py/ClientUpdate._fullMigrate/original