def getPrimaryLocalUpdates(self, troveNames=None):
        """
            Returns a set of changes (jobs) that explain how the user is likely
            to have modified their system to get it to its current state.

            The changes made are the top-level jobs, that is, if the user
            updated foo (which includes foo:runtime) from branch a to branch b,
            an update job for foo will be returned but not foo:runtime.

            @param troveNames: If specified, then the changes returned are
            those I{related} to the given trove names. They may include changes
            of troves with other names, however. For example, if you
            request changes for troves named C{foo}, and C{foo} is included by
            C{group-dist}, and the only change related to C{foo} you have made
            is installing C{group-dist}, then a job showing the install of
            C{group-dist} will be returned.
            @type troveNames: list

            @rtype: list of jobs
        """
        if troveNames is not None and not troveNames:
            return []


        allJobs = []        # allJobs is returned from this fn

        noParents = []      # troves with no parents that could be part of
                            # unknown local updates.

        troves = []         # troveId -> troveInfo map (troveId == index)
                            # contains (troveTup, isPresent, hasParent,
                            #           isWeak)

        maxId = 0           # next index for troves list
        troveIdsByInfo = {} # (name,ver,flavor) -> troveId

        parentIds = {}      # name -> [parents of troves w/ name, troveIds]
        childIds = {}       # troveId -> childIds

        ISPRESENT = 1
        HASPARENT = 2
        ISWEAK = 3

        # 1. Create needed data structures
        #    troves, parentIds, childIds
        for (troveInfo, parentInfo, isPresent, weakRef) \
                                in self.db.iterUpdateContainerInfo(troveNames):
            troveId = troveIdsByInfo.setdefault(troveInfo, maxId)
            if troveId == maxId:
                maxId += 1
                troves.append([troveInfo, isPresent, bool(parentInfo), weakRef])
            else:
                if isPresent:
                    troves[troveId][ISPRESENT] = True
                if parentInfo:
                    troves[troveId][HASPARENT] = True
                if not weakRef:
                    troves[troveId][ISWEAK] = False

            if parentInfo:
                parentId = troveIdsByInfo.setdefault(parentInfo, maxId)
                if parentId == maxId:
                    maxId += 1
                    troves.append([parentInfo, False, False, True])

            l = parentIds.setdefault(troveInfo[0], [set(), []])
            l[1].append(troveId)

            if parentInfo:
                childIds.setdefault(parentId, []).append(troveId)
                l[0].add(parentId)

        del maxId

        # remove troves that don't are not present and have no parents - they
        # won't be part of local updates.
        allTroves = set(x[0] for x in enumerate(troves)
                        if (x[1][ISPRESENT] or x[1][HASPARENT])
                           and not (x[1][ISPRESENT] and x[1][HASPARENT] and not x[1][ISWEAK]))
        for name, (parents, troveIds) in parentIds.items():
            parents.intersection_update(allTroves)
            parentIds[name][1] = set(troveIds)
            parentIds[name][1].intersection_update(allTroves)
        del allTroves

        noParents = (x[1][1] for x in parentIds.iteritems() if not x[1][0])
        noParents = set(itertools.chain(*noParents))

        while noParents:
            exists = trove.Trove('@update', versions.NewVersion(),
                                 deps.Flavor(), None)
            refd = trove.Trove('@update', versions.NewVersion(),
                               deps.Flavor(), None)

            for troveId in noParents:
                info, isPresent, hasParent, isWeak = troves[troveId]
                if isPresent:
                    exists.addTrove(presentOkay=True, *info)
                else:
                    refd.addTrove(presentOkay=True, *info)

            for job in exists.diff(refd)[2]:
                if not job[2][0]:
                    #oldInfo = troves[troveIdsByInfo[job[0], job[1][0], job[1][1]]]
                    #allJobs.append(job)
                    continue
                newInfo = troves[troveIdsByInfo[job[0], job[2][0], job[2][1]]]
                if not job[1][0] and newInfo[HASPARENT]:
                    # it's a new install.  If it has a parent,
                    # then it's already covered by the install of that
                    # parent.
                    continue
                elif newInfo[HASPARENT] and newInfo[ISWEAK]:
                    oldInfo = troves[troveIdsByInfo[job[0], job[1][0], job[1][1]]]
                    if oldInfo[ISWEAK]:
                        continue
                allJobs.append(job)

            # we've created all local updates related to this set of
            # troves - remove them as parents of other troves to generate
            # next noParent set.
            toDiscard = {}
            for troveId in noParents:
                for childId in childIds.get(troveId, []):
                    toDiscard.setdefault(troves[childId][0][0],
                                         []).append(troveId)

            newNoParents = []
            for name, troveIds in toDiscard.iteritems():
                parentIds[name][0].difference_update(troveIds)
                if not parentIds[name][0]:
                    newNoParents.extend(parentIds[name][1])
            del toDiscard

            noParents = noParents - set(newNoParents)

        return allJobs
dataset/ETHPy150Open sassoftware/conary/conary/conaryclient/update.py/ClientUpdate.getPrimaryLocalUpdates/swapped operands of `-`