def _updateChangeSet(self, itemList, uJob, keepExisting = None,
                         recurse = True, updateMode = True, sync = False,
                         useAffinity = True, checkPrimaryPins = True,
                         forceJobClosure = False, ineligible = set(),
                         syncChildren=False, updateOnly=False,
                         installMissing = False, removeNotByDefault = False,
                         exactFlavors = False):
        """
        Updates a trove on the local system to the latest version
        in the respository that the trove was initially installed from.

        @param itemList: List specifying the changes to apply. Each item
        in the list must be a ChangeSetFromFile, or a standard job tuple.
        Versions in the job tuple may be strings, versions, branches, or
        None. Flavors may be None.
        @type itemList: list
        """
        searchSource = uJob.getSearchSource()
        if not isinstance(searchSource, searchsource.AbstractSearchSource):
            if searchSource.isSearchAsDatabase():
                searchSource = searchsource.SearchSource(
                                                  uJob.getSearchSource(),
                                                  self.cfg.flavor, self.db)
            else:
                searchSource = searchsource.NetworkSearchSource(
                                                  uJob.getSearchSource(),
                                                  self.cfg.installLabelPath,
                                                  self.cfg.flavor, self.db)
            uJob.setSearchSource(searchSource)

        def _separateInstalledItems(jobSet):
            present = self.db.hasTroves([ (x[0], x[2][0], x[2][1]) for x in
                                                    jobSet ] )
            oldItems = set([ (job[0], job[2][0], job[2][1]) for job, isPresent
                                in itertools.izip(jobSet, present)
                                if isPresent ])
            newItems = set([ job for job, isPresent
                                in itertools.izip(jobSet, present)
                                if not isPresent ])
            return newItems, oldItems

        def _jobTransitiveClosure(db, troveSource, jobSet):
            # This is an expensive operation. Use it carefully.
            jobQueue = util.IterableQueue()
            jobClosure = set()

            for job in itertools.chain(jobSet, jobQueue):
                if jobClosure in job:
                    continue

                if job[2][0] is None:
                    continue

                jobClosure.add(job)
                if not trove.troveIsCollection(job[0]): continue

                if job[1][0] is None:
                    oldTrv = None
                else:
                    oldTrv = db.getTroves([(job[0], job[1][0], job[1][1])],
                                     withFiles = False, pristine = False)[0]
                    if oldTrv is None:
                        # XXX batching these would be much more efficient
                        oldTrv = troveSource.getTrove(job[0], job[1][0],
                                                      job[1][1],
                                                      withFiles = False)

                try:
                    newTrv = troveSource.getTrove(job[0], job[2][0], job[2][1],
                                                  withFiles = False)
                except (TroveMissing, OpenError):
                    # In the case where we're getting transitive closure
                    # for a relative changeset and hit a trove that is
                    # not included in the relative changeset (because it's
                    # already installed locally), grab it from the local
                    # database instead.
                    newTrv = db.getTroves([(job[0], job[2][0], job[2][1])],
                                           withFiles = False,
                                           pristine = True)[0]
                    # If it not there, maybe we're not installing it anyway.
                    # We'll let the troveMissing error occur when we actually
                    # try to install this trove.
                    if newTrv is None:
                        continue

                recursiveJob = newTrv.diff(oldTrv, absolute = job[3])[2]
                for x in recursiveJob:
                    jobQueue.add(x)

            return jobClosure

        # def _updateChangeSet -- body starts here
        if syncChildren:
            installMissing = True

        # This job describes updates from a networked repository. Duplicates
        # (including installing things already installed) are skipped.
        newJob = set()
        # These are items being removed.
        removeJob = set()
        # This is the full, transitive closure of the job
        transitiveClosure = set()

        toFind = {}
        toFindNoDb = {}
        for item in itemList:
            (troveName, (oldVersionStr, oldFlavorStr),
                        (newVersionStr, newFlavorStr), isAbsolute) = item
            assert(oldVersionStr is None or not isAbsolute)

            if troveName[0] == '-':
                needsOld = True
                needsNew = newVersionStr or (newFlavorStr is not None)
                troveName = troveName[1:]
            elif troveName[0] == '+':
                needsNew = True
                needsOld = oldVersionStr or (oldFlavorStr is not None)
                troveName = troveName[1:]
            else:
                needsOld = oldVersionStr or (oldFlavorStr is not None)
                needsNew = newVersionStr or (newFlavorStr is not None)
                if not (needsOld or needsNew):
                    if updateMode:
                        needsNew = True
                    else:
                        needsOld = True

            if needsOld:
                oldTroves = self.db.findTrove(None,
                                   (troveName, oldVersionStr, oldFlavorStr))
            else:
                oldTroves = []

            if not needsNew:
                assert(newFlavorStr is None)
                assert(not isAbsolute)
                for troveInfo in oldTroves:
                    log.lowlevel("set up removal of %s", troveInfo)
                    removeJob.add((troveInfo[0], (troveInfo[1], troveInfo[2]),
                                   (None, None), False))
                # skip ahead to the next itemList
                continue

            if len(oldTroves) > 2:
                raise UpdateError, "Update of %s specifies multiple " \
                            "troves for removal" % troveName
            elif oldTroves:
                oldTrove = (oldTroves[0][1], oldTroves[0][2])
            else:
                oldTrove = (None, None)
            del oldTroves

            if isinstance(newVersionStr, versions.Version):
                assert(isinstance(newFlavorStr, deps.Flavor))
                jobToAdd = (troveName, oldTrove,
                            (newVersionStr, newFlavorStr), isAbsolute)
                newJob.add(jobToAdd)
                log.lowlevel("set up job %s", jobToAdd)
                del jobToAdd
            elif isinstance(newVersionStr, versions.Branch):
                toFind[(troveName, newVersionStr.asString(),
                        newFlavorStr)] = oldTrove, isAbsolute
            elif (newVersionStr and newVersionStr[0] == '/'):
                # fully qualified versions don't need branch affinity
                # but they do use flavor affinity
                toFind[(troveName, newVersionStr, newFlavorStr)] = \
                                        oldTrove, isAbsolute
            else:
                if not (isAbsolute or not useAffinity):
                    # not isAbsolute means keepExisting. when using
                    # keepExisting, branch affinity doesn't make sense - we are
                    # installing a new, generally unrelated version of this
                    # trove
                    toFindNoDb[(troveName, newVersionStr, newFlavorStr)] \
                                    = oldTrove, isAbsolute
                else:
                    toFind[(troveName, newVersionStr, newFlavorStr)] \
                                    = oldTrove, isAbsolute
        searchSource = uJob.getSearchSource()

        if not useAffinity:
            results = searchSource.findTroves(toFind, useAffinity=False,
                                                   exactFlavors=exactFlavors)
        else:
            results = {}
            if toFind:
                log.lowlevel("looking up troves w/ database affinity")
                results = searchSource.findTroves(toFind,
                                                    useAffinity=True,
                                                    exactFlavors=exactFlavors)
                self._confirmLaterPackages(results)
            if toFindNoDb:
                log.lowlevel("looking up troves w/o database affinity")
                results.update(searchSource.findTroves(toFindNoDb,
                                                   useAffinity=False,
                                                   exactFlavors=exactFlavors))
        for troveSpec, (oldTroveInfo, isAbsolute) in \
                itertools.chain(toFind.iteritems(), toFindNoDb.iteritems()):
            resultList = results[troveSpec]

            if len(resultList) > 1 and oldTroveInfo[0] is not None:
                raise UpdateError, "Relative update of %s specifies multiple " \
                            "troves for install" % troveName

            newJobList = [ (x[0], oldTroveInfo, x[1:], isAbsolute) for x in
                                    resultList ]
            newJob.update(newJobList)
            log.lowlevel("adding jobs %s", newJobList)

        # Items which are already installed shouldn't be installed again. We
        # want to track them though to ensure they aren't removed by some
        # other action.

        if not installMissing:
            jobSet, oldItems = _separateInstalledItems(newJob)
        else:
            # keep our original jobSet, we'll recurse through installed
            # items as well.
            jobSet, oldItems = newJob, _separateInstalledItems(newJob)[1]

        log.lowlevel("items already installed: %s", oldItems)

        jobSet.update(removeJob)
        del newJob, removeJob

        # we now have two things
        #   1. oldItems -- items which we should not remove as a side effect
        #   2. jobSet -- job we need to create a change set for

        if not jobSet:
            raise NoNewTrovesError

        # FIXME changeSetSource: I should just be able to call
        # csSource.createChangeSet but it can't handle recursive
        # createChangeSet calls, and you can only call createChangeSet
        # once on a csSource.  So, we avoid having to call it more than
        # once by checking to see if the changeSets are already in the
        # update job.
        hasTroves = uJob.getTroveSource().hasTroves(
            [ (x[0], x[2][0], x[2][1]) for x in jobSet ] )

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

        if reposChangeSetList != jobSet:
            # we can't trust the closure from the changeset we're getting
            # since we're not getting everything for jobSet
            forceJobClosure = True

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

        cs, notFound = csSource.createChangeSet(reposChangeSetList,
                                                withFiles = False,
                                                recurse = recurse,
                                                callback = self.updateCallback)
        self._replaceIncomplete(cs, csSource,
                                self.db, self.repos)
        if notFound:
            self._trovesNotFound(notFound) # may raise an error
                                           # if there are non-local troves
                                           # in the list
            jobSet.difference_update(notFound)
            if not jobSet:
                raise NoNewTrovesError
        assert(not notFound)
        uJob.getTroveSource().addChangeSet(cs)
        transitiveClosure = set(cs.getJobSet(primaries = False))
        del cs

        redirectHack = self._processRedirects(csSource, uJob, jobSet,
                                              transitiveClosure, recurse)

        if forceJobClosure and recurse:
            # The transitiveClosure we computed can't be trusted; we need
            # to build another one. We could do this all the time, but it's
            # expensive
            transitiveClosure = _jobTransitiveClosure(self.db,
                                            trovesource.stack(
                                                uJob.getTroveSource(),
                                                self.repos), jobSet)
            # Since we couldn't trust the transitive closure generated,
            # we need to check to see if any of the recursive troves we'll
            # need are not in the changeset.  This will be true
            # of group changesets.
            transitiveJobs = list(transitiveClosure)
            hasTroves = uJob.getTroveSource().hasTroves(
                            (x[0], x[2][0], x[2][1]) for x in transitiveJobs)

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

            csSource = trovesource.stack(uJob.getSearchSource(),
                                         self.repos)
            trovesExist = csSource.hasTroves(
                            [(x[0], x[2][0], x[2][1]) for x in reposChangeSetList])
            reposChangeSetList = [ x[1] for x in
                                   itertools.izip(trovesExist, reposChangeSetList)
                                   if x[0] is True ]
            cs, notFound = csSource.createChangeSet(reposChangeSetList,
                                                    withFiles = False,
                                                    recurse = recurse,
                                                    callback = self.updateCallback)
            self._replaceIncomplete(cs, csSource, self.db, self.repos)
            #NOTE: we allow any missing bits (recursive or not) to be skipped.
            # We may not install then anyways
            #They'll show up in notFound.
            #assert(not notFound)
            uJob.getTroveSource().addChangeSet(cs)
        elif forceJobClosure:
            transitiveClosure = jobSet
        # else we trust the transitiveClosure which was passed in

        if not installMissing:
            # we know that all the troves in jobSet are already installed
            # (i.e. in oldItems) when syncing.  We don't want to exclude
            # their children from syncing
            ineligible = ineligible | oldItems

        newJob = self._mergeGroupChanges(uJob, jobSet, transitiveClosure,
                                 redirectHack, recurse, ineligible,
                                 checkPrimaryPins,
                                 installedPrimaries=oldItems,
                                 installMissingRefs=installMissing,
                                 updateOnly=updateOnly,
                                 respectBranchAffinity=not installMissing,
                                 alwaysFollowLocalChanges=installMissing,
                                 removeNotByDefault = removeNotByDefault)

        if not newJob:
            raise NoNewTrovesError

        troveSource = uJob.getTroveSource()
        missingTroves, removedTroves = self._processJobList(newJob, uJob,
                                                troveSource.getChangeSet)
        if removedTroves or missingTroves:
            removed = [ (x[0], x[2][0], x[2][1]) for x in removedTroves ]
            removed.sort()
            missing = [ (x[0], x[2][0], x[2][1]) for x in missingTroves ]
            missing.sort()
            raise MissingTrovesError(missing, removed)

        uJob.setPrimaryJobs(jobSet)

        return newJob
dataset/ETHPy150Open sassoftware/conary/conary/conaryclient/update.py/ClientUpdate._updateChangeSet/swapped operands of `in`