예제 #1
0
    def testRdiff8(self):
        # CNY-1753
        # Different files living on different branches
        raise testhelp.SkipTestException(
            "Unable to reproduce CNY-1753 in a test case")
        # Manifested in running conary rdiff
        # mkinitrd=conary.rpath.com@rpl:1--usplash.rb.rpath.com@rpl:1

        rf1 = rephelp.RegularFile(
            contents='\000\001\002\003',
            perms=0644,
            mtime=1176921017,
        )
        rf2 = rephelp.RegularFile(
            contents='\000\001\003\005',
            perms=0644,
            mtime=1176921317,
        )

        v1 = versions.ThawVersion('/localhost@rpl:1/1:1-1-1')
        v2 = versions.ThawVersion('/localhost1@rpl:2/2:2-2-2')

        self.openRepository()
        self.openRepository(1)

        self.addComponent('foo:run', v1, [('/bin/foo', rf1)])
        self.addCollection('foo', v1, [':run'])

        self.addComponent('foo:run', v2, [('/bin/foo', rf2)])
        self.addCollection('foo', v2, [':run'])

        troveSpec = cmdline.parseChangeList('foo=%s--%s' % (v1, v2))[0]
        ret, outs = self.captureOutput(queryrep.diffTroves, self.cfg,
                                       troveSpec)
        self.assertEqual(outs, '')
예제 #2
0
    def testLatestByLabel(self):
        def _build(*specList):
            for (v, f) in specList:
                self.addComponent('t:rt', v, flavor=f)

        v1 = versions.ThawVersion('/localhost@rpl:foo//1/1:1.0-1-1')
        v2 = versions.ThawVersion('/localhost@rpl:bar//1/2:1.0-1-2')
        l = v1.trailingLabel()
        defFlavor = deps.parseFlavor('readline,ssl')
        noReadLine = deps.parseFlavor('~!readline,ssl')
        reqNoReadLine = deps.parseFlavor('!readline,ssl')

        _build((v1, defFlavor), (v2, defFlavor))

        repos = self.openRepository()

        d = repos.getTroveLatestByLabel({'t:rt': {l: None}})
        assert (d['t:rt'].keys() == [v2])

        d = repos.getTroveLatestByLabel({'t:rt': {l: [defFlavor]}})
        assert (d['t:rt'].keys() == [v2])

        d = repos.getTroveLatestByLabel({'t:rt': {
            l: [defFlavor]
        }},
                                        bestFlavor=True)
        assert (d['t:rt'].keys() == [v2])

        _build((v1, noReadLine))

        d = repos.getTroveLatestByLabel({'t:rt': {l: None}})
        assert (d['t:rt']) == {v1: [noReadLine], v2: [defFlavor]}

        d = repos.getTroveLatestByLabel({'t:rt': {
            l: [noReadLine]
        }},
                                        bestFlavor=True)
        assert (d['t:rt']) == {v2: [defFlavor]}

        d = repos.getTroveLatestByLabel({'t:rt': {
            l: [reqNoReadLine]
        }},
                                        bestFlavor=True)
        assert (d['t:rt']) == {v1: [noReadLine]}

        d = repos.getTroveLatestByLabel({'t:rt': {l: [noReadLine]}})
        assert (d['t:rt']) == {v2: [defFlavor], v1: [noReadLine]}

        d = repos.getTroveLatestByLabel({'t:rt': {l: [defFlavor, noReadLine]}})
        assert (d['t:rt']) == {v2: [defFlavor], v1: [noReadLine]}

        d = repos.getTroveLatestByLabel(
            {'t:rt': {
                l: [defFlavor, reqNoReadLine]
            }}, bestFlavor=True)
        assert (d['t:rt']) == {v2: [defFlavor], v1: [noReadLine]}
예제 #3
0
class JobTupleTest(testhelp.TestCase):

    old = (versions.ThawVersion('/conary.rpath.com@rpl:devel//2/1000000000.000:2.9.10-2-0.1'),
            deps.parseFlavor('is: x86_64'))
    new = (versions.ThawVersion('/conary.rpath.com@rpl:devel//2/1200000000.000:3.0.00-1-0.1'),
            deps.parseFlavor('is: x86_64'))

    def testNewTuple(self):
        n = 'tmpwatch'
        a = self.old
        b = self.new
        atup = (n, a[0], a[1])
        btup = trovetup.TroveTuple(n, b[0], b[1])
        self.assertEqual((n, a, b, False), trovetup.JobTuple((n, a, b, False)))
        self.assertEqual((n, a, b, False), trovetup.JobTuple(n, a, b, False))
        self.assertEqual((n, a, b, False), trovetup.JobTuple(n, a, b))
        self.assertEqual((n, a, b, False), trovetup.JobTuple(n, atup, btup))
        self.assertEqual((n, (None, None), b, True), trovetup.JobTuple(n, new=b))
        self.assertEqual((n, (None, None), b, True), trovetup.JobTuple(n, new=btup))
        self.assertEqual((n, a, (None, None), False), trovetup.JobTuple(n, old=a))
        self.assertEqual((n, a, (None, None), False), trovetup.JobTuple(n, old=atup))
        self.assertEqual((n, (None, None), b, True), btup.asJob())

    def testStringify(self):
        x = trovetup.JobTuple('tmpwatch', new=self.new)
        self.assertEqual(str(x), "tmpwatch=/conary.rpath.com@rpl:devel//2/3.0.00-1-0.1[is: x86_64]")
        self.assertEqual(repr(x), "JobTuple('tmpwatch=/conary.rpath.com@rpl:devel//2/1200000000.000:3.0.00-1-0.1[is: x86_64]')")
        x = x._replace(absolute=False)
        self.assertEqual(str(x), "tmpwatch=/conary.rpath.com@rpl:devel//2/3.0.00-1-0.1[is: x86_64]")
        self.assertEqual(repr(x), "JobTuple('tmpwatch=/conary.rpath.com@rpl:devel//2/1200000000.000:3.0.00-1-0.1[is: x86_64]', absolute=False)")
        x = trovetup.JobTuple('tmpwatch', self.old, self.new)
        self.assertEqual(str(x), "tmpwatch=/conary.rpath.com@rpl:devel//2/2.9.10-2-0.1[is: x86_64]"
                "--/conary.rpath.com@rpl:devel//2/3.0.00-1-0.1[is: x86_64]")
        self.assertEqual(repr(x), "JobTuple('tmpwatch=/conary.rpath.com@rpl:devel//2/1000000000.000:2.9.10-2-0.1[is: x86_64]"
                "--/conary.rpath.com@rpl:devel//2/1200000000.000:3.0.00-1-0.1[is: x86_64]')")
        x = x._replace(absolute=True)
        self.assertEqual(str(x), "tmpwatch=/conary.rpath.com@rpl:devel//2/2.9.10-2-0.1[is: x86_64]"
                "--/conary.rpath.com@rpl:devel//2/3.0.00-1-0.1[is: x86_64]")
        self.assertEqual(repr(x), "JobTuple('tmpwatch=/conary.rpath.com@rpl:devel//2/1000000000.000:2.9.10-2-0.1[is: x86_64]"
                "--/conary.rpath.com@rpl:devel//2/1200000000.000:3.0.00-1-0.1[is: x86_64]', absolute=True)")
        x = trovetup.JobTuple('tmpwatch', self.old)
        self.assertEqual(str(x), "tmpwatch=/conary.rpath.com@rpl:devel//2/2.9.10-2-0.1[is: x86_64]--")
        self.assertEqual(repr(x), "JobTuple('tmpwatch=/conary.rpath.com@rpl:devel//2/1000000000.000:2.9.10-2-0.1[is: x86_64]--')")

    def testParser(self):
        p = trovetup.JobTuple
        self.assertRaises(ParseError, p, u'spam\xFF=foo[bar]')
        self.assertEqual(p('tmpwatch=/conary.rpath.com@rpl:devel//2/1200000000.000:3.0.00-1-0.1[is: x86_64]'),
                ('tmpwatch', (None, None), self.new, True))
        self.assertEqual(p('tmpwatch=/conary.rpath.com@rpl:devel//2/1000000000.000:2.9.10-2-0.1[is: x86_64]'
                '--/conary.rpath.com@rpl:devel//2/1200000000.000:3.0.00-1-0.1[is: x86_64]'),
                ('tmpwatch', self.old, self.new, False))
        self.assertEqual(p('tmpwatch=/conary.rpath.com@rpl:devel//2/1000000000.000:2.9.10-2-0.1[is: x86_64]--'),
                ('tmpwatch', self.old, (None, None), False))
예제 #4
0
파일: state.py 프로젝트: tensor5/conary
    def parseLines(self, lines, stateVersion, repos):
        kwargs = {}

        while lines:
            fields = lines[0][:-1].split()

            # the file count ends the list of fields
            if len(fields) == 1: break
            assert (len(fields) == 2)
            del lines[0]

            what = fields[0]
            assert (not kwargs.has_key(what))
            if what not in self.fields:
                raise ConaryStateError('Invalid field "%s"' % what)

            isVer = self.fields[what][0]

            if isVer:
                kwargs[what] = versions.ThawVersion(fields[1])
            else:
                kwargs[what] = fields[1]

        required = set([x[0] for x in self.fields.items() if x[1][1]])
        assert ((set(kwargs.keys()) & required) == required)

        SourceState.__init__(self, **kwargs)

        self._readFileList(lines, stateVersion, repos)
예제 #5
0
 def __thaw__(item):
     if len(item) == 3:
         context = ''
         n, v, f = item
     else:
         n, v, f, context = item
     return (n, versions.ThawVersion(v), ThawFlavor(f), context)
예제 #6
0
    def testStringVersion(self):
        # make sure you can represent VERSION -> None diff
        v1 = StringVersionStream()
        v2 = StringVersionStream()
        v1.set(versions.ThawVersion('/a@b:c/15:1.1-1'))
        assert (v1.freeze() == '/a@b:c/1.1-1')
        v1.twm(v2.diff(v1), v1)
        assert (v1.freeze() == '')

        # make sure that twm works properly
        v1.set(versions.ThawVersion('/a@b:c/15:1.1-1'))
        v2 = StringVersionStream()
        diff = v1.diff(v2)
        v2.twm(diff, v2)
        assert (v1 == v2)
        assert (v1.diff(v2) is None)
예제 #7
0
    def deleteJobs(self, jobIdList):
        cu = self.db.cursor()
        troveIdList = []
        logHashes = set()
        for jobId in jobIdList:
            cu.execute(
                '''SELECT troveId, troveName, version, flavor, logPath
                                      FROM BuildTroves WHERE jobId=?''', jobId)
            for troveId, name, version, flavor, logPath in cu:
                version = versions.ThawVersion(version)
                flavor = deps.ThawFlavor(flavor)
                if logPath:
                    logHashes.add(logPath)
                cu.execute('DELETE FROM BinaryTroves where troveId=?', troveId)

            for table in [
                    'Jobs', 'JobConfig', 'Subscriber', 'BuildTroves',
                    'StateLogs', 'JobQueue'
            ]:
                cu.execute('DELETE FROM %s WHERE jobId=?' % table, jobId)
            cu.execute(
                '''DELETE FROM JobConfig
                          WHERE key="jobContext" AND value=?''', jobId)
        if logHashes:
            # Prebuilt troves can refer to logs produced by previous builds.
            # Keep any logs that are still referenced by jobs not being
            # deleted.
            placeholders = ','.join('?' for x in logHashes)
            cu.execute(
                "SELECT logPath FROM BuildTroves WHERE logPath IN (%s)" %
                (placeholders, ), list(logHashes))
            for logPath, in cu:
                logHashes.discard(logPath)
        return logHashes
예제 #8
0
 def _loadTimestamps(self):
     if self.version < (4, 0):
         return
     timeStampList = self._loadPickle(self._timeStampsPathId)
     for (name, frozenVersion) in timeStampList:
         thawed = versions.ThawVersion(frozenVersion)
         self.timeStampCache[(name, thawed)] = thawed
예제 #9
0
    def _checkRemovals(self, group, updateId):
        """
        Check to make sure that all configured package removals have happened.
        """

        # get package removals from the config object.
        removePackages = self._cfg.updateRemovesPackages.get(updateId, [])
        removeObsoleted = self._cfg.removeObsoleted.get(updateId, [])
        removeSource = [x[0] for x in self._cfg.removeSource.get(updateId, [])]

        # get names and versions
        troves = set()
        labels = set()
        for pkgKey, pkgData in group.iteritems():
            name = str(pkgData.name)

            version = None
            if pkgData.version:
                versionObj = versions.ThawVersion(pkgData.version)
                labels.add(versionObj.branch().label())
                version = str(versionObj.asString())

            flavor = None
            troves.add((name, version, flavor))

        # Get flavors and such.
        foundTroves = set([
            x for x in itertools.chain(
                *self._helper.findTroves(troves, labels=labels).itervalues())
        ])

        # get sources for each name version pair
        sources = self._helper.getSourceVersions(foundTroves)

        # collapse to sourceName: [ binNames, ] dictionary
        sourceNameMap = dict([(x[0].split(':')[0], [z[0] for z in y])
                              for x, y in sources.iteritems()])

        binRemovals = set(
            itertools.chain(
                *
                [sourceNameMap[x] for x in removeSource
                 if x in sourceNameMap]))

        # take the union
        removals = set(removePackages) | set(removeObsoleted) | binRemovals

        errors = []
        # Make sure these packages are not in the group model.
        for pkgKey, pkgData in group.iteritems():
            if pkgData.name in removals:
                errors.append(pkgData.name)

        if errors:
            log.info('found packages that should be removed %s' % errors)
            raise ExpectedRemovalValidationFailedError(updateId=updateId,
                                                       pkgNames=errors)
예제 #10
0
    def _checkNameVersionConflict(self, group):
        """
        Check for packages taht have the same source name, but different
        versions.
        """

        # get names and versions
        troves = set()
        labels = set()
        for pkgKey, pkgData in group.iteritems():
            name = str(pkgData.name)

            version = None
            if pkgData.version:
                versionObj = versions.ThawVersion(pkgData.version)
                labels.add(versionObj.branch().label())
                version = str(versionObj.asString())

            flavor = None
            # FIXME: At some point we might want to add proper flavor handling,
            #        note that group flavor handling is different than what
            #        findTroves normally does.
            #if pkgData.flavor:
            #    flavor = deps.ThawFlavor(str(pkgData.flavor))

            troves.add((name, version, flavor))

        # Get flavors and such.
        foundTroves = set([
            x for x in itertools.chain(
                *self._helper.findTroves(troves, labels=labels).itervalues())
        ])

        # get sources for each name version pair
        sources = self._helper.getSourceVersions(foundTroves)

        seen = {}
        for (n, v, f), pkgSet in sources.iteritems():
            binVer = list(pkgSet)[0][1]
            seen.setdefault(n, set()).add(binVer)

        binPkgs = {}
        conflicts = {}
        for name, vers in seen.iteritems():
            if len(vers) > 1:
                log.error('found multiple versions of %s' % name)
                for binVer in vers:
                    srcVer = binVer.getSourceVersion()
                    nvf = (name, srcVer, None)
                    conflicts.setdefault(name, []).append(srcVer)
                    binPkgs[nvf] = sources[nvf]

        if conflicts:
            raise NameVersionConflictsFoundError(groupName=group.groupName,
                                                 conflicts=conflicts,
                                                 binPkgs=binPkgs)
예제 #11
0
 def __thaw__(tupList):
     results = []
     for tup in tupList:
         if len(tup) == 3 or not tup[3]:
             context = ''
         else:
             context = tup[3]
         results.append((tup[0], versions.ThawVersion(tup[1]),
                         ThawFlavor(tup[2]), context))
     return results
예제 #12
0
    def __init__(self,
                 conaryClient,
                 troveSpec,
                 troveChangeRequest=None,
                 troveSpecOther=None):
        self.conaryClient = conaryClient

        n, v, f = conaryclient.cmdline.parseTroveSpec(troveSpec)
        self.trvName = n
        self.trvNewVersion = versions.ThawVersion(v)
        self.trvNewFlavor = f

        self._fromTroveChangeRequest(troveChangeRequest)
        self._fromOtherTroveSpec(troveSpecOther)
예제 #13
0
 def _loadDepSolutions(self):
     if self.version < (2, 0):
         # Earlier versions were missing timestamps, which interferes with
         # dep solver tie-breaking.
         return
     depSolutionsList = self._loadPickle(self._depSolutionsPathId)
     for (sig, depSet, aResult) in depSolutionsList:
         depSet = deps.ThawDependencySet(depSet)
         allResults = []
         for resultList in aResult:
             allResults.append([(x[0], versions.ThawVersion(x[1]),
                                 deps.ThawFlavor(x[2]))
                                for x in resultList])
         self.addDepSolution(sig, depSet, allResults)
예제 #14
0
 def _loadDepSolutions(self):
     if self.version < (3, 0):
         # Version 1 was missing timestamps, which interferes with dep
         # solver tie-breaking.
         # Version 2 could have bogus unresolved dep solutions due to a bug
         # so the version was bumped to invalidate those.
         return
     depSolutionsList = self._loadPickle(self._depSolutionsPathId)
     for (sig, depSet, aResult) in depSolutionsList:
         depSet = deps.ThawDependencySet(depSet)
         allResults = []
         for resultList in aResult:
             allResults.append([
                 (x[0], versions.ThawVersion(x[1]), deps.ThawFlavor(x[2]))
                 for x in resultList])
         self.addDepSolution(sig, depSet, allResults)
예제 #15
0
    def thaw(self, data):
        del self[:]
        if not data: return

        l = data.split("\0")
        i = 0

        while i < len(l):
            name = l[i]
            version = versions.ThawVersion(l[i + 1])
            flavor = l[i + 2]

            flavor = deps.ThawFlavor(flavor)

            self.append((name, version, flavor))
            i += 3
예제 #16
0
    def testNewTuple(self):
        n, v, f = self.sample
        vo = versions.ThawVersion(v)
        fo = deps.parseFlavor(f)
        ex_str = '%s=%s[%s]' % (n, v, f)
        expect = "TroveTuple(%r)" % (ex_str,)

        p = trovetup.TroveTuple
        self.assertEquals(repr(p(n, v, f)), expect)
        self.assertEquals(repr(p((n, v, f))), expect)
        self.assertEquals(repr(p(ex_str)), expect)
        self.assertEquals(repr(p(ex_str.decode('ascii'))), expect)
        self.assertEquals(repr(p(n, vo, fo)), expect)
        self.assertEquals(repr(p((n, vo, fo))), expect)

        self.assertEquals(repr(p('%s=%s' % (n, v))),
                "TroveTuple('%s=%s[]')" % (n, v))
예제 #17
0
    def _fromTroveChangeRequest(self, troveChangeRequest):
        if troveChangeRequest is None:
            return
        fromVersion = self.trvNewVersion
        versionChange = troveChangeRequest.get_versionChange()
        if versionChange is not None:
            fromVersionStr = versionChange.get_from()
            if fromVersionStr:
                fromVersion = versions.ThawVersion(fromVersionStr)
        self.trvOldVersion = fromVersion

        fromFlavor = self.trvNewFlavor
        flavorChange = troveChangeRequest.get_flavorChange()
        if flavorChange is not None:
            fromFlavorStr = flavorChange.get_from()
            if fromFlavorStr:
                fromFlavor = deps.parseFlavor(str(fromFlavorStr))
        self.trvOldFlavor = fromFlavor
예제 #18
0
    def troveInfo(self, auth, t, v):
        t = unquote(t)
        leaves = {}
        for serverName in self.serverNameList:
            newLeaves = self.repos.getTroveVersionList(serverName, {t: [None]})
            leaves.update(newLeaves)
        if t not in leaves:
            return self._write("error",
                               error='%s was not found on this server.' % t)

        versionList = sorted(leaves[t].keys(), reverse=True)

        if not v:
            reqVer = versionList[0]
        else:
            try:
                reqVer = versions.VersionFromString(v)
            except (versions.ParseError, ValueError):
                try:
                    reqVer = versions.ThawVersion(v)
                except:
                    return self._write("error",
                                       error="Invalid version: %s" % v)

        try:
            query = [(t, reqVer, x) for x in leaves[t][reqVer]]
        except KeyError:
            return self._write(
                "error",
                error="Version %s of %s was not found on this server." %
                (reqVer, t))
        troves = self.repos.getTroves(query, withFiles=False)
        mdata = self.repos.getMetadata([t, reqVer.branch()],
                                       reqVer.branch().label())
        if t in mdata:
            mdata = mdata[t]

        return self._write("trove_info",
                           troveName=t,
                           troves=troves,
                           versionList=versionList,
                           reqVer=reqVer,
                           metadata=mdata)
예제 #19
0
 def files(self, auth, t, v, f):
     v = versions.ThawVersion(v)
     f = deps.ThawFlavor(f)
     parentTrove = self.repos.getTrove(t, v, f, withFiles=False)
     # non-source group troves only show contained troves
     if trove.troveIsGroup(t):
         troves = sorted(parentTrove.iterTroveList(strongRefs=True))
         return self._write("group_contents", troveName=t, troves=troves)
     fileIters = []
     for n, v, f in self.repos.walkTroveSet(parentTrove, withFiles=False):
         files = self.repos.iterFilesInTrove(n,
                                             v,
                                             f,
                                             withFiles=True,
                                             sortByPath=True)
         fileIters.append(files)
     return self._write("files",
                        troveName=t,
                        fileIters=itertools.chain(*fileIters))
예제 #20
0
    def deleteJobs(self, jobIdList):
        cu = self.db.cursor()
        troveIdList = []
        troveList = []
        for jobId in jobIdList:
            cu.execute('''SELECT troveId, troveName, version, flavor 
                                      FROM BuildTroves WHERE jobId=?''', jobId)
            for troveId, name, version, flavor in cu:
                version = versions.ThawVersion(version)
                flavor = deps.ThawFlavor(flavor)
                troveList.append((jobId, name, version, flavor))
                cu.execute('DELETE FROM BinaryTroves where troveId=?', troveId)

            for table in ['Jobs', 'JobConfig', 'Subscriber', 'BuildTroves',
                          'StateLogs', 'JobQueue' ]:
                cu.execute('DELETE FROM %s WHERE jobId=?' % table, jobId)
            cu.execute('''DELETE FROM JobConfig
                          WHERE key="jobContext" AND value=?''', jobId)
        return troveList
예제 #21
0
    def testRedirectOnBranch(self):
        # CNY-1181
        # create test and test-foo on localhost@rpl:linux
        self.addComponent('test:source', '1.0')
        self.addComponent('test:runtime', '1.0')
        self.addComponent('test-foo:runtime', '1.0')
        self.addCollection('test', '1.0', [':runtime'])
        self.addCollection('test-foo', '1.0', [':runtime'])

        # branch test to /localhost@rpl:linux/:branch
        self.mkbranch("/localhost@rpl:linux",
                      versions.Label("localhost@foo:branch"), "test")
        b = '/localhost@rpl:linux/1.0-1-0/branch/2.0-1-1'
        # add a new version
        self.addComponent('test:runtime', b)
        self.addCollection('test', b, [':runtime'])

        r = """
class testRedirect(RedirectRecipe):
    name = 'test'
    version = '1.0'
    clearBuildReqs()

    def setup(r):
        r.addRedirect("test-foo", "localhost@rpl:linux")
"""
        # use the source version that would match :source on the branch
        v = versions.ThawVersion(
            '/localhost@rpl:linux/123.0:1.0-1/branch/456.0:2.0-1')
        built, str = self.captureOutput(self.buildRecipe,
                                        r,
                                        'testRedirect',
                                        sourceVersion=v)

        self.checkUpdate(['test=:branch'],
                         ['test-foo=--1.0', 'test-foo:runtime=--1.0'])
예제 #22
0
파일: repquery.py 프로젝트: pombreda/crest
def searchTroves(cu, roleIds, label = None, filterSet = None, mkUrl = None,
                 latest = True, start = 0, limit = None, name = None):
    d = { 'labelCheck' : '', 'nameCheck' : '' }
    args = []
    regex = None
    if label:
        d['labelCheck'] = "label = ? AND"
        args.append(label)

    if name:
        if set('?.*[]\\()+') & set(name):
            # if only .* appears, replace them with '%' and use LIKE. this
            # code currently fails with \.* in the regex, but neither .
            # nor \* are valid trove names anyway
            likeName = name
            while '.*' in likeName:
                likeName = likeName.replace('.*', '%')

            if set('?.*[]\\()+') & set(name):
                regex = re.compile(name)
            else:
                d['nameCheck'] = "WHERE item LIKE ?"
                args.append(likeName)
        else:
            d['nameCheck' ] = "WHERE item = ?"
            args.append(name)

    d['roleIds'] = ",".join( str(x) for x in roleIds)

    if latest:
        cu.execute("""
            SELECT item, version, flavor, ts FROM
                (SELECT DISTINCT Nodes.itemId AS itemId,
                                 Nodes.versionId AS versionId, flavorId,
                                 Nodes.timeStamps AS ts FROM Labels
                    JOIN LabelMap USING (labelId)
                    JOIN LatestCache USING (itemId, branchId)
                    JOIN Nodes USING (itemId, versionId)
                    WHERE %(labelCheck)s
                          LatestCache.latestType = 1 AND
                          LatestCache.userGroupId in (%(roleIds)s))
                AS idTable JOIN
                Items USING (itemId) JOIN
                Versions ON (idTable.versionId = Versions.versionId) JOIN
                Flavors ON (idTable.flavorId = Flavors.flavorId)
                %(nameCheck)s
                ORDER BY item, version, flavor
        """ % d, *args)
    else:
        cu.execute("""
            SELECT item, version, flavor, ts FROM
                (SELECT DISTINCT Instances.itemId AS itemId,
                                 Instances.versionId AS versionId,
                                 Instances.flavorId AS flavorId,
                                 Nodes.timeStamps AS ts
                                 FROM Labels
                    JOIN LabelMap USING (labelId)
                    JOIN Nodes USING (itemId, branchid)
                    JOIN Instances USING (itemid, versionid)
                    JOIN usergroupinstancescache AS ugi USING (instanceid)
                    WHERE %(labelCheck)s
                          ugi.userGroupId in (%(roleIds)s))
                AS idTable JOIN
                Items USING (itemId) JOIN
                Versions ON (idTable.versionId = Versions.versionId) JOIN
                Flavors ON (idTable.flavorId = Flavors.flavorId)
                %(nameCheck)s
                ORDER BY item, version, flavor
        """ % d, *args)

    l = list(cu)
    filteredL = typeFilter(l, filterSet)

    if regex:
        filteredL = [ x for x in filteredL if regex.match(x[0]) ]

    if limit is None:
        limit = len(filteredL) - start

    troveList = datamodel.NamedTroveIdentList(total = len(filteredL),
                                              start = start)

    for (name, version, flavor, ts) in filteredL[start:start + limit]:
        flavor = str(deps.ThawFlavor(flavor))
        frzVer = versions.strToFrozen(version,
                                      [ x for x in ts.split(":") ])
        ver = versions.ThawVersion(frzVer)

        troveList.append(name = name, version = ver, flavor = flavor,
                         mkUrl = mkUrl)

    return troveList
예제 #23
0
class CapsuleTest(rephelp.RepositoryHelper):

    id1 = md5FromString("00010001000100010001000100010001")
    id2 = md5FromString("00010001000100010001000100010002")
    id3 = md5FromString("00010001000100010001000100010003")
    id4 = md5FromString("00010001000100010001000100010004")
    id5 = md5FromString("00010001000100010001000100010005")

    fid1 = sha1FromString("1001000100010001000100010001000100010001")
    fid2 = sha1FromString("1001000100010001000100010001000100010002")
    fid3 = sha1FromString("1001000100010001000100010001000100010003")
    fid4 = sha1FromString("1001000100010001000100010001000100010004")
    fid5 = sha1FromString("1001000100010001000100010001000100010005")

    v1 = versions.ThawVersion('/localhost@foo:bar/1.0:1.0-1-1')

    @conary_test.rpm
    def test01_Trove(self):
        t = trove.Trove('foo:continer', self.v1, deps.Flavor())
        t.addFile(self.id1, '/1', self.v1, self.fid1)
        t.addFile(self.id2, '/2', self.v1, self.fid2)
        h = { rpmhelper.NAME    : 'foorpm',
              rpmhelper.VERSION : '1.0',
              rpmhelper.RELEASE : '1',
              rpmhelper.ARCH    : 'i386',
              rpmhelper.EPOCH   : [ 1 ] }
        t.addRpmCapsule('foo.rpm', self.v1, self.fid5, h)

        assert([ x[1] for x in t.iterFileList() ] ==
                    [ '/1', '/2'] )
        assert([ x[1] for x in t.iterFileList(members = True) ] ==
                    [ '/1', '/2'] )
        assert([ x[0:2] for x in t.iterFileList(capsules = True) ] ==
                    [ (trove.CAPSULE_PATHID, 'foo.rpm' ) ] )
        assert([ x[1] for x in t.iterFileList(members = True,
                                              capsules = True) ] ==
                    [ '/1', 'foo.rpm', '/2' ])
        assert([ x[1] for x in t.iterFileList(members = False,
                                              capsules = False) ] == [])

    @conary_test.rpm
    @testhelp.context('rollback')
    def test02_Repository(self):
        def csContents(repos, job):
            p = os.path.join(self.workDir, 'foo.ccs')
            repos.createChangeSetFile(job, p)
            fc = filecontainer.FileContainer(
                                    util.ExtendedFile(p, buffering = False))
            l = []
            info = fc.getNextFile()
            while info:
                l.append(info)
                info = fc.getNextFile()

            return l

        cmp = self.addRPMComponent("simple:rpm=1.0", 'simple-1.0-1.i386.rpm')
        repos = self.openRepository()
        reposCmp = repos.getTrove(*cmp.getNameVersionFlavor())
        assert(reposCmp == cmp)
        l = csContents(repos, [ ("simple:rpm", (None, None),
                                cmp.getNameVersionFlavor()[1:], True) ])
        assert([ x[0][0:16] for x in l ] ==
               ['CONARYCHANGESET',
                '\x8d\xeb\xb9\x15M!\xe0\xc5\x08D\x87\xf7\xe1\xf9fW',
                trove.CAPSULE_PATHID ])
        cmp = self.addRPMComponent("simple:rpm=1.1", 'simple-1.1-1.i386.rpm')

        self.updatePkg('simple:rpm=1.0')
        assert(os.path.isdir(self.rootDir + "/dir"))
        self.verifyFile(self.rootDir + "/config", "config\n")
        self.verifyFile(self.rootDir + "/normal", "normal\n")

        self.updatePkg('simple:rpm=1.1')
        self.verifyFile(self.rootDir + "/config", "changed-config\n")
        self.verifyFile(self.rootDir + "/normal", "changed-normal\n")

        self.rollback(self.rootDir, 1)
        self.verifyFile(self.rootDir + "/config", "config\n")
        self.verifyFile(self.rootDir + "/normal", "normal\n")

        self.writeFile(self.rootDir + '/config', 'config\nlocal config\n')
        rc, str = self.captureOutput(self.updatePkg, 'simple:rpm=1.1')
        self.assertEquals(str, 'warning: /config saved as /config.rpmsave\n')
        self.verifyFile(self.rootDir + '/config', 'changed-config\n')
        self.rollback(self.rootDir, 1)
        self.verifyFile(self.rootDir + '/config', 'config\nlocal config\n')

        rc, str = self.captureOutput(self.erasePkg, self.rootDir, 'simple:rpm')
        self.assertEquals(str, 'warning: /config saved as /config.rpmsave\n')
        assert(not os.path.exists(self.rootDir + '/config'))
        self.rollback(self.rootDir, 1)
        self.verifyFile(self.rootDir + '/config', 'config\nlocal config\n')

        rc, str = self.captureOutput(self.rollback, self.rootDir, 0)
        self.assertEquals(str, 'warning: /config saved as /config.rpmsave\n')
        assert(not os.path.exists(self.rootDir + "/dir"))
        assert(not os.path.exists(self.rootDir + "/config"))
        assert(not os.path.exists(self.rootDir + "/normal"))

    @conary_test.rpm
    @testhelp.context('rollback')
    def test03_Overlap(self):
        osA1 = self.addRPMComponent("overlap-same-A:rpm=1.0",
                                    'overlap-same-A-1.0-1.i386.rpm')
        osB1 = self.addRPMComponent("overlap-same-B:rpm=1.0",
                                    'overlap-same-B-1.0-1.i386.rpm')
        self.updatePkg('overlap-same-A:rpm=1.0')
        self.updatePkg('overlap-same-B:rpm=1.0')
        assert(os.path.exists(self.rootDir + '/A-1'))
        assert(os.path.exists(self.rootDir + '/B-1'))
        self.checkOwners('/file', [ osA1, osB1 ])

        self.erasePkg(self.rootDir, 'overlap-same-B:rpm')
        assert(os.path.exists(self.rootDir + '/A-1'))
        assert(os.path.exists(self.rootDir + '/file'))
        self.checkOwners('/file', [ osA1 ])

        self.rollback(2)
        self.checkOwners('/file', [ osA1, osB1 ])

        self.rollback(1)
        self.checkOwners('/file', [ osA1 ])

    @conary_test.rpm
    def test04_DirectoryPreexisting(self):
        self.addRPMComponent("simple:rpm=1.0", 'simple-1.0-1.i386.rpm')
        os.mkdir(self.rootDir + '/dir')
        self.updatePkg('simple:rpm')
        assert(os.path.exists(self.rootDir + '/normal'))

    @conary_test.rpm
    def test05_NoJobSplitting(self):
        self.addRPMComponent("simple:rpm=1.0", 'simple-1.0-1.i386.rpm')
        self.addRPMComponent("ownerships:rpm=1.0", 'ownerships-1.0-1.i386.rpm')

        try:
            old = self.cfg.updateThreshold
            self.cfg.updateThreshold = 1
            rc, txt = self.captureOutput(self.updatePkg,
                                         [ 'simple:rpm', 'ownerships:rpm' ],
                                         raiseError=True, info=True)

            # if job splitting happens you get "Job 1 of 2" here because of the
            # small updateThreashold
            self.assertEquals(txt, '    Install ownerships:rpm=1.0-1-1\n'
                                   '    Install simple:rpm=1.0-1-1\n')

            # make sure having a critical update doesn't make the splitting
            # break
            criticalUpdateInfo = updatecmd.CriticalUpdateInfo()
            criticalUpdateInfo.setCriticalTroveRegexps(['simple:rpm'])
            itemsList = [
                ('simple:rpm', (None, None), (None, None), True),
                ('ownerships:rpm', (None, None), (None, None), True),
            ]
            client = conaryclient.ConaryClient(self.cfg)
            updJob = client.newUpdateJob()
            client.prepareUpdateJob(updJob, itemsList, migrate=True,
                                    criticalUpdateInfo = criticalUpdateInfo)
        finally:
            self.cfg.updateThreshold = old

        # info components should get split out of course CNY-3387
        self.addComponent("info-disk:user=1.0")
        rc, txt = self.captureOutput(self.updatePkg,
                        [ 'simple:rpm', 'info-disk:user' ], info = True )
        self.assertEquals(txt,
            'Job 1 of 2:\n'
            '    Install info-disk:user=1.0-1-1\n'
            'Job 2 of 2:\n'
            '    Install simple:rpm=1.0-1-1\n')

    @conary_test.rpm
    def test06_GhostPreexisting(self):
        self.addRPMComponent("ghost:rpm=1.0", 'ghost-1.0-1.i386.rpm')
        os.mkdir(self.rootDir + '/foo')
        self.writeFile(self.rootDir + '/foo/ghost', 'orig contents')
        rc, str = self.captureOutput(self.updatePkg, 'ghost:rpm')
        assert(not str)
        self.verifyFile(self.rootDir + '/foo/ghost', 'orig contents')

    @conary_test.rpm
    def test07_BadRpmCapsule(self):
        cmp = self.addRPMComponent("ghost:rpm=1.0", 'epoch-1.0-1.i386.rpm')
        repos = self.openRepository()
        orig = self.workDir + '/ghost.ccs'
        modified = self.workDir + '/ghost-new.ccs'
        repos.createChangeSetFile([ (cmp.getName(), (None, None),
                                     cmp.getNameVersionFlavor()[1:],
                                     True) ], orig)
        fc = filecontainer.FileContainer(
                                util.ExtendedFile(orig, buffering = False))
        newFc = filecontainer.FileContainer(
                        util.ExtendedFile(modified, "w", buffering = False))
        # CONARYCHANGESET
        (name, tag, contents) = fc.getNextFile()
        newFc.addFile(name, filecontents.FromFile(contents), tag,
                      precompressed = True)
        # the RPM
        (name, tag, contents) = fc.getNextFile()
        contents = filecontents.FromString("busted!")
        newFc.addFile(name, contents, tag)
        cs = changeset.ChangeSetFromFile(modified)
        # this throws away the output about the install failing
        self.assertRaises(files.Sha1Exception, self.captureOutput,
                          self.updatePkg, self.rootDir, cs)

    @conary_test.rpm
    @testhelp.context('sysmodel', 'rollback')
    def test08_OverlapConflict(self):
        osA1 = self.addRPMComponent("overlap-same-A:rpm=1.0",
                                    'overlap-same-A-1.0-1.i386.rpm')
        self.addCollection('overlap-same-A', '1.0', [ ':rpm' ])
        osB1 = self.addRPMComponent("overlap-conflict:rpm",
                                    'overlap-conflict-1.0-1.i386.rpm')
        self.addCollection('overlap-conflict', '1.0', [ ':rpm' ])
        self.updatePkg('overlap-same-A:rpm=1.0')
        self.assertRaises(update.UpdateError,
            self.updatePkg, 'overlap-conflict:rpm=1.0', raiseError=True)

        self.updatePkg('overlap-conflict:rpm=1.0', replaceFiles = True)
        self.checkOwners('/file', [ osB1 ])
        self.rollback(1)
        self.checkOwners('/file', [ osA1 ])

        # now test that allowing overlaps via groups pathConflicts is OK
        # in system model
        self.addCollection('group-dist', '1.0', [
            ('overlap-same-A:rpm', '1.0'),
            ('overlap-conflict:rpm', '1.0')],
            pathConflicts=['/file'])

        root = self.cfg.root
        util.mkdirChain(root+'/etc/conary')
        file(root+'/etc/conary/system-model', 'w').write(
            'install group-dist=localhost@rpl:linux/1.0\n')
        model = cml.CML(self.cfg)
        modelFile = systemmodel.SystemModelFile(model)
        updatecmd.doModelUpdate(self.cfg, model, modelFile, [],
            keepExisting=True)



        self.resetRoot()
        self.updatePkg(['overlap-same-A:rpm',
                        'overlap-conflict:rpm=1.0'], replaceFiles = True)
        self.rollback(0)

    @conary_test.rpm
    def test08_CapsuleTroveDisplay(self):
        cmp = self.addRPMComponent("simple:rpm=1.0", 'simple-1.0-1.i386.rpm')
        repos = self.openRepository()
        cs = repos.createChangeSet([ (cmp.getName(), (None, None),
                                      cmp.getNameVersionFlavor()[1:], True) ])

        db = self.openDatabase()
        self.updatePkg('simple:rpm')

        for method, args in [
                (showchangeset.displayChangeSet, (None, cs, None, self.cfg) ),
                (queryrep.displayTroves, (self.cfg, [ "simple:rpm" ]) ),
                (query.displayTroves, (db, self.cfg, [ "simple:rpm" ]) ) ]:
            rc, res = self.captureOutput(method, ls = True, *args)
            self.assertEquals(res, '/config\n/dir\n/normal\n')

            rc, res = self.captureOutput(method, capsules = True, ls = True,
                                         *args)
            self.assertEquals(res, 'simple-1.0-1.i386.rpm\n')

    @conary_test.rpm
    def test09_CapsuleInstallFlags(self):
        # test some random flags, like --test, --justdb, and
        # --replace-unmanaged-files
        cmp = self.addRPMComponent("simple:rpm=1.0", 'simple-1.0-1.i386.rpm')
        self.updatePkg('simple:rpm', test = True)
        assert(not os.path.exists(self.rootDir + '/normal'))
        assert(not self.owners('/normal'))
        str = os.popen('rpm --root %s -qa' % self.rootDir).readlines()
        assert(not str)

        self.updatePkg('simple:rpm', justDatabase = True)
        assert(len(self.owners('/normal')) == 1)
        assert(not os.path.exists(self.rootDir + '/normal'))
        str = os.popen('rpm --root %s -qa' % self.rootDir).readlines()
        self.assertEquals(str, [ 'simple-1.0-1.i386\n' ])
        rc, str = self.captureOutput(self.erasePkg, self.rootDir,
                                     'simple:rpm',
                                     justDatabase = True)
        self.assertEquals(str,
            'warning: cannot remove /normal: No such file or directory\n'
            'warning: cannot remove /config: No such file or directory\n'
            'warning: cannot remove /dir: No such file or directory\n')
        str = os.popen('rpm --root %s -qa' % self.rootDir).readlines()
        self.assertEquals(str, [])
        assert(not self.owners('/normal'))

        self.writeFile(self.rootDir + '/normal', 'placeholder')
        rc, str = self.captureOutput(self.updatePkg, 'simple:rpm')
        self.assertEquals(str,
                'error: changeset cannot be applied:\n'
                'applying update would cause errors:\n'
                '/normal is in the way of a newly created file in '
                        'simple:rpm=/localhost@rpl:linux/1.0-1-1[]\n')
        rc, str = self.captureOutput(self.updatePkg, 'simple:rpm',
                                     replaceUnmanagedFiles = True)
        self.assertEquals(str, '')
        self.verifyFile(self.rootDir + '/normal', 'normal\n')

        self.resetRoot()

        self.updatePkg('simple:rpm', justDatabase = True, skipCapsuleOps = True)
        assert(len(self.owners('/normal')) == 1)
        assert(not os.path.exists(self.rootDir + '/normal'))
        str = os.popen('rpm --root %s -qa' % self.rootDir).readlines()
        self.assertEquals(str, [ ])
        # syncCapsuleDatabase would helpfully erase the trove before we get a
        # chance to do the same thing, so turn it off for this test
        self.cfg.syncCapsuleDatabase = 'false'
        try:
            rc, str = self.captureOutput(self.erasePkg, self.rootDir,
                                     'simple:rpm',
                                     justDatabase = True,
                                     skipCapsuleOps = True)
        finally:
            self.cfg.resetToDefault('syncCapsuleDatabase')
        self.assertEquals(str,
            'warning: cannot remove /normal: No such file or directory\n'
            'warning: cannot remove /config: No such file or directory\n'
            'warning: cannot remove /dir: No such file or directory\n')
        str = os.popen('rpm --root %s -qa' % self.rootDir).readlines()
        self.assertEquals(str, [])
        assert(not self.owners('/normal'))

    @conary_test.rpm
    def test10_UnchangedRPM(self):
        cmp = self.addRPMComponent("simple:rpm=1.0-1-1",
                                   'simple-1.0-1.i386.rpm')
        cmp = self.addRPMComponent("simple:rpm=1.0-1-2",
                                   'simple-1.0-1.i386.rpm')
        self.updatePkg('simple:rpm=1.0-1-1')
        self.updatePkg('simple:rpm=1.0-1-2')
        # this makes sure the right version is installed
        self.erasePkg(self.rootDir, 'simple:rpm=1.0-1-2')

    @conary_test.rpm
    def test11_UnchangedUpdate(self):
        # CNY-3335
        simple10  = self.addRPMComponent("simple:rpm=1.0-1-1",
                                         'simple-1.0-1.i386.rpm')
        simple101 = self.addRPMComponent("simple:rpm=1.0.1-1-1",
                                         'simple-1.0.1-1.i386.rpm',
                                         versus = simple10)
        self.updatePkg('simple:rpm=1.0-1-1')
        self.updatePkg('simple:rpm=1.0.1-1-1')

    @conary_test.rpm
    def test_unchangedFileid(self):
        # CNY-3719
        simple10  = self.addRPMComponent("simple:rpm=1.0-1-1",
                                         'simple-1.0-1.i386.rpm')
        # Commit a new version so all the file versions are new
        simple11 = self.addRPMComponent("simple:rpm=1.1-1-1",
                                         'simple-1.1-1.i386.rpm',
                                         versus = simple10)
        # Now go back to the old fileids, the filevers will be new again
        simple101  = self.addRPMComponent("simple:rpm=1.0.1-1-1",
                                         'simple-1.0.1-1.i386.rpm',
                                         versus = simple11)
        self.updatePkg('simple:rpm=1.0-1-1')
        self.updatePkg('simple:rpm=1.0.1-1-1')

    @conary_test.rpm
    def test12_TroveZeroEpoch(self):
        t = trove.Trove('foo:continer', self.v1, deps.Flavor())
        t.addFile(self.id1, '/1', self.v1, self.fid1)
        t.addFile(self.id2, '/2', self.v1, self.fid2)
        h = { rpmhelper.NAME    : 'foorpm',
              rpmhelper.VERSION : '1.0',
              rpmhelper.RELEASE : '1',
              rpmhelper.ARCH    : 'i386',
              rpmhelper.EPOCH   : [ 0 ] }
        t.addRpmCapsule('foo.rpm', self.v1, self.fid5, h)

        self.assertEqual(t.troveInfo.capsule.rpm.name(), 'foorpm')
        self.assertEqual(t.troveInfo.capsule.rpm.epoch(), 0)
        self.assertEqual(t.troveInfo.capsule.rpm.version(), '1.0')
        self.assertEqual(t.troveInfo.capsule.rpm.release(), '1')
        self.assertEqual(t.troveInfo.capsule.rpm.arch(), 'i386')

    @conary_test.rpm
    def testChangesetExploder(self):
        simple10  = self.addRPMComponent("simple:rpm=1.0-1-1",
                                         'simple-1.0-1.i386.rpm')
        repos = self.openRepository()
        cs = repos.createChangeSet([
            (simple10.getName(), (None, None),
             simple10.getNameVersionFlavor()[1:], True) ])
        changeset.ChangesetExploder(cs, self.rootDir)
        assert(os.path.isdir(self.rootDir + '/dir'))
        self.assertEquals(
            os.stat(self.rootDir + '/normal').st_size, 7)

    @conary_test.rpm
    @testhelp.context('rollback')
    def testRpmFileColoring(self):
        if os.uname()[4] != 'x86_64':
            # this test only works on x86_64 platforms
            return

        i386md5 = '0fc54eafb8daf886ff7d43c4448acc71'
        x64md5 = '4cb13908ca1d7989be493c581a6fa1d3'

        oldtrv  = self.addRPMComponent("tmpwatch:rpm=0.1-1-1",
                                       'tmpwatch-2.9.1-1.i386.rpm')
        i386trv  = self.addRPMComponent("tmpwatch:rpm=1.0-1-1",
                                        'tmpwatch-2.9.7-1.1.el5.2.i386.rpm')
        x64trv  = self.addRPMComponent("tmpwatch:rpm=2.0-1-1",
                                       'tmpwatch-2.9.7-1.1.el5.2.x86_64.rpm')

        self.updatePkg('tmpwatch:rpm=1.0-1-1')
        self.checkMd5('/usr/sbin/tmpwatch', i386md5)
        self.checkOwners('/usr/sbin/tmpwatch',  [ i386trv ])
        self.updatePkg('tmpwatch:rpm=2.0-1-1', keepExisting = True)
        self.checkMd5('/usr/sbin/tmpwatch', x64md5)
        self.checkOwners('/usr/sbin/tmpwatch',  [ x64trv ])
        self.erasePkg(self.rootDir, 'tmpwatch:rpm=2.0-1-1')
        # it's a shame we don't restore the file here
        assert(not os.path.exists(self.rootDir + '/usr/sbin/tmpwatch'))
        self.rollback(2)
        self.checkMd5('/usr/sbin/tmpwatch', x64md5)
        self.rollback(1)
        self.checkMd5('/usr/sbin/tmpwatch', i386md5)
        self.checkOwners('/usr/sbin/tmpwatch',  [ i386trv ])

        self.resetRoot()
        self.updatePkg('tmpwatch:rpm=2.0-1-1')
        self.checkMd5('/usr/sbin/tmpwatch', x64md5)
        self.checkOwners('/usr/sbin/tmpwatch',  [ x64trv ])
        self.updatePkg('tmpwatch:rpm=1.0-1-1', keepExisting = True)
        self.checkMd5('/usr/sbin/tmpwatch', x64md5)
        self.checkOwners('/usr/sbin/tmpwatch',  [ x64trv ])
        self.erasePkg(self.rootDir, 'tmpwatch:rpm=1.0-1-1')
        self.checkMd5('/usr/sbin/tmpwatch', x64md5)

        self.resetRoot()
        self.updatePkg([ 'tmpwatch:rpm=1.0-1-1', 'tmpwatch:rpm=2.0-1-1' ])
        self.checkMd5('/usr/sbin/tmpwatch', x64md5)
        self.checkOwners('/usr/sbin/tmpwatch',  [ x64trv ])

        # this still causes conflicts
        rc, str = self.captureOutput(self.updatePkg, 'tmpwatch:rpm=0.1')
        assert('conflicts' in str)

    @conary_test.rpm
    def testFileColorUsedByScript(self):
        """
        Post script references a file that is being "shared" in the same job

        @tests: CNY-3884
        """
        if os.uname()[4] != 'x86_64':
            # this test only works on x86_64 platforms
            return

        i386md5 = '0fc54eafb8daf886ff7d43c4448acc71'
        x64md5 = '4cb13908ca1d7989be493c581a6fa1d3'

        i386trv = self.addRPMComponent("tmpwatch:rpm=1.0-1-1",
                'tmpwatch-2.9.7-1.1.el5.2.i386.rpm')
        x64trv = self.addRPMComponent("tmpwatch:rpm=2.0-1-1",
                'tmpwatch-2.9.7-1.1.el5.2.x86_64.rpm')
        consumer = self.addRPMComponent('usetmpwatch:rpm=1.0-1-1',
                'usetmpwatch-1.0-1.x86_64.rpm')

        self.updatePkg('tmpwatch:rpm=2.0-1-1')
        self.checkMd5('/usr/sbin/tmpwatch', x64md5)
        self.checkOwners('/usr/sbin/tmpwatch',  [ x64trv ])
        rc, out = self.captureOutput(self.updatePkg,
                ['tmpwatch:rpm=1.0-1-1', 'usetmpwatch:rpm'],
                keepExisting=True)
        self.checkMd5('/usr/sbin/tmpwatch', x64md5)
        self.checkOwners('/usr/sbin/tmpwatch',  [ x64trv ])
        self.assertEqual(out, 'PRESENT\n')

    @conary_test.rpm
    @testhelp.context('rollback')
    def test14_testRpmSharedHardLinks(self):
        # we build fro msource here rather than use addRPMComponent to get
        # the hard links right
        recipestr1 = r"""
class HardLinks(CapsuleRecipe):
    name = 'hardlinkconflict'
    version = '%s'
    clearBuildReqs()

    def setup(r):
        r.addCapsule('%s')
"""
        built, d = self.buildRecipe(
            recipestr1 % ('1.0_1',
                          'hardlinkconflict-1.0-1.x86_64.rpm'), "HardLinks")
        built, d = self.buildRecipe(
            recipestr1 % ('1.0_2',
                          'hardlinkconflict-1.0-2.x86_64.rpm'), "HardLinks")

        self.updatePkg('hardlinkconflict=1.0_1')
        self.updatePkg('hardlinkconflict=1.0_2', keepExisting = True)
        assert(len(self.owners('/foo')) == 2)
        self.erasePkg(self.rootDir, 'hardlinkconflict=1.0_2')
        assert(len(self.owners('/foo')) == 1)

        self.resetRoot()
        self.updatePkg([ 'hardlinkconflict=1.0_1', 'hardlinkconflict=1.0_2' ])
        assert(len(self.owners('/foo')) == 2)
        self.erasePkg(self.rootDir, 'hardlinkconflict=1.0_2')
        assert(len(self.owners('/foo')) == 1)

    @conary_test.rpm
    def test15_SetupHandling(self):
        oldTrv  = self.addRPMComponent("setup:rpm=0.1-1-1",
                                       'setup-2.5.58-7.el5.noarch.rpm')
        self.resetRoot()
        util.mkdirChain(self.rootDir + '/etc')
        self.writeFile(self.rootDir + '/etc/passwd',
                       "passwd junk\n"
                       "root:wrong rootuser\n")
        self.writeFile(self.rootDir + '/etc/group',
                       "group junk\n"
                       "root:wrong root group\n")
        self.updatePkg('setup:rpm', replaceFiles = True)

        p = open(self.rootDir + '/etc/passwd').readlines()
        self.assertEquals(p[0], 'root:*:0:0:root:/root:/bin/bash\n')
        self.assertEquals(p[-1], 'passwd junk\n')
        assert(not os.path.exists(self.rootDir + '/etc/passwd.rpmnew'))

        p = open(self.rootDir + '/etc/group').readlines()
        self.assertEquals(p[0], 'root::0:root\n')
        self.assertEquals(p[-1], 'group junk\n')
        assert(not os.path.exists(self.rootDir + '/etc/group.rpmnew'))

    @conary_test.rpm
    def testScriptFailures(self):
        'test what happens when RPM scripts fail'
        # CNY-3454
        f = self.addRPMComponent('aaa_first:rpm=1.0-1-1',
                                 'aaa_first-1.0-1.noarch.rpm')
        f = self.addRPMComponent('failpost:rpm=1.0-1-1',
                                 'failpost-1.0-1.noarch.rpm')
        f = self.addRPMComponent('failpostun:rpm=1.0-1-1',
                                 'failpostun-1.0-1.noarch.rpm')
        f = self.addRPMComponent('failpre:rpm=1.0-1-1',
                                 'failpre-1.0-1.noarch.rpm')
        f = self.addRPMComponent('failpreun:rpm=1.0-1-1',
                                 'failpreun-1.0-1.noarch.rpm')
        f = self.addRPMComponent('zzz_last:rpm=1.0-1-1',
                                 'zzz_last-1.0-1.noarch.rpm')
        f == f

        self.updatePkg('aaa_first:rpm=1.0-1-1')
        self.checkOrdering('aaa_first-1.0-1.noarch')
        self.verifyFile(self.rootDir + '/dummy/aaa_first')
        util.mkdirChain(self.rootDir+'/var/tmp')
        rc, str = self.captureOutput(self.updatePkg, 'failpost:rpm=1.0-1-1')
        self.assertEquals(str,
            'warning: %post(failpost-1.0-1.noarch) scriptlet failed, exit status 127\n')
        self.checkOrdering('failpost-1.0-1.noarch')
        self.assertEquals(rc, None)
        self.verifyFile(self.rootDir + '/dummy/file')
        self.updatePkg('zzz_last:rpm=1.0-1-1')
        self.checkOrdering('zzz_last-1.0-1.noarch')
        self.verifyFile(self.rootDir + '/dummy/zzz_last')
        self.resetRoot(); util.mkdirChain(self.rootDir+'/var/tmp')


        rc, str = self.captureOutput(self.updatePkg,
                       ['aaa_first:rpm=1.0-1-1',
                        'failpost:rpm=1.0-1-1',
                        'zzz_last:rpm=1.0-1-1'])
        self.assertEquals(str,
            'warning: %post(failpost-1.0-1.noarch) scriptlet failed, exit status 127\n')
        self.assertEquals(rc, None)
        self.checkOrdering('aaa_first-1.0-1.noarch'
                           ' failpost-1.0-1.noarch'
                           ' zzz_last-1.0-1.noarch')
        self.verifyFile(self.rootDir + '/dummy/aaa_first')
        self.verifyFile(self.rootDir + '/dummy/file')
        self.verifyFile(self.rootDir + '/dummy/zzz_last')
        self.resetRoot(); util.mkdirChain(self.rootDir+'/var/tmp')

        self.updatePkg(['aaa_first:rpm=1.0-1-1',
                        'failpostun:rpm=1.0-1-1',
                        'zzz_last:rpm=1.0-1-1'])
        self.verifyFile(self.rootDir + '/dummy/aaa_first')
        self.verifyFile(self.rootDir + '/dummy/file')
        self.checkOrdering('aaa_first-1.0-1.noarch'
                           ' failpostun-1.0-1.noarch'
                           ' zzz_last-1.0-1.noarch')
        rc, str = self.captureOutput(self.erasePkg, self.rootDir,
            'failpostun:rpm=1.0-1-1')
        self.assertEquals(str,
            'warning: %postun(failpostun-1.0-1.noarch) scriptlet failed, exit status 127\n')
        self.verifyNoFile(self.rootDir + '/dummy/file')
        self.verifyFile(self.rootDir + '/dummy/zzz_last')
        self.resetRoot(); util.mkdirChain(self.rootDir+'/var/tmp')

        rc, str = self.captureOutput(self.updatePkg,
                        ['aaa_first:rpm=1.0-1-1',
                        'failpre:rpm=1.0-1-1',
                        'zzz_last:rpm=1.0-1-1'])
        self.assertEquals(str, '\n'.join((
          'error: %pre(failpre-1.0-1.noarch) scriptlet failed, exit status 127',
          'error: install: %pre scriptlet failed (2), skipping failpre-1.0-1',
          'error: RPM failed to install requested packages: failpre-1.0-1.noarch',
          '')))
        self.assertEquals(rc, None)
        self.checkOrdering('aaa_first-1.0-1.noarch'
                           ' failpre-1.0-1.noarch'
                           ' zzz_last-1.0-1.noarch')
        self.verifyFile(self.rootDir + '/dummy/aaa_first')
        self.verifyNoFile(self.rootDir + '/dummy/file')
        self.verifyFile(self.rootDir + '/dummy/zzz_last')
        self.resetRoot(); util.mkdirChain(self.rootDir+'/var/tmp')

        rc, str = self.captureOutput(self.updatePkg,
                       ['aaa_first:rpm=1.0-1-1',
                        'failpreun:rpm=1.0-1-1',
                        'zzz_last:rpm=1.0-1-1'])
        self.assertEquals(rc, None)
        self.assertEquals(str, '')
        self.checkOrdering('aaa_first-1.0-1.noarch'
                           ' failpreun-1.0-1.noarch'
                           ' zzz_last-1.0-1.noarch')
        self.verifyFile(self.rootDir + '/dummy/aaa_first')
        self.verifyFile(self.rootDir + '/dummy/file')
        self.verifyFile(self.rootDir + '/dummy/zzz_last')
        rc, str = self.captureOutput(self.erasePkg,
            self.rootDir, 'failpreun:rpm=1.0-1-1')
        self.assertEquals(str,
            'error: %preun(failpreun-1.0-1.noarch) scriptlet failed, exit status 127\n')
        self.verifyNoFile(self.rootDir + '/dummy/file')

    @conary_test.rpm
    def testNonRootUnpackFailures(self):
        'test what happens when RPM unpack fails as non-root'
        # CNY-3462
        f = self.addRPMComponent('aaa_first:rpm=1.0-1-1',
                                 'aaa_first-1.0-1.noarch.rpm')
        f = self.addRPMComponent('dev:rpm=1.0-1-1',
                                 'dev-1.0-1.noarch.rpm')
        rc, str = self.captureOutput(self.updatePkg,
                       ['aaa_first:rpm=1.0-1-1',
                        'dev:rpm=1.0-1-1'])
        warning = str.strip().split('\n')[-1]
        self.assertEquals(warning,
                          'warning: RPM failed to unpack dev-1.0-1.noarch')
        self.verifyFile(self.rootDir + '/dummy/aaa_first')

    @conary_test.rpm
    def testDuplicateRpms(self):
        # CNY-3470
        v1 = self.addRPMComponent("simple:rpm=1.0-1", 'simple-1.0-1.i386.rpm')
        v2 = self.addRPMComponent("simple:rpm=1.0-2", 'simple-1.0-1.i386.rpm')

        self.updatePkg('simple:rpm=1.0-1')
        self.updatePkg('simple:rpm=1.0-2', keepExisting = True)
        self.erasePkg(self.rootDir, 'simple:rpm=1.0-1')
        self.erasePkg(self.rootDir, 'simple:rpm=1.0-2')

        self.updatePkg('simple:rpm=1.0-1')
        self.updatePkg('simple:rpm=1.0-2', keepExisting = True)
        self.erasePkg(self.rootDir, [ 'simple:rpm=1.0-1', 'simple:rpm=1.0-2' ])

        self.updatePkg('simple:rpm=1.0-1')
        self.updatePkg('simple:rpm=1.0-2')
        self.erasePkg(self.rootDir, 'simple:rpm=1.0-2')

    @conary_test.rpm
    def testNetSharedPath(self):
        # CNY-3503
        p = self.addRPMComponent('netshared:rpm=1.0-1',
                                 'netshared-1.0-1.noarch.rpm')

        util.mkdirChain(self.cfg.root + '/etc/rpm/')
        #self.updatePkg('netshared:rpm=1.0-1')
        #self.verifyFile(self.rootDir + '/local/shouldexist')
        ##self.verifyFile(self.rootDir + '/excluded/shouldnotexist')

        self.resetRoot()
        util.mkdirChain(self.cfg.root + '/etc/rpm/')
        util.mkdirChain(self.cfg.root + '/excluded')
        self.writeFile(self.cfg.root + '/excluded/shouldnotexist', 'unmanaged')

        # inside the method to let @conary_test.rpm keep the import conditional
        import rpm
        rpm.addMacro('_netsharedpath', '/excluded:/usr/local')
        try:
            self.updatePkg('netshared:rpm=1.0-1')
        finally:
            rpm.delMacro('_netsharedpath')

        self.verifyFile(self.rootDir + '/local/shouldexist')
        self.verifyFile(self.rootDir + '/excluded/shouldnotexist', 'unmanaged')

        self.erasePkg(self.rootDir, 'netshared:rpm')

    @conary_test.rpm
    def testFileOverrides(self):
        # CNY-3586; CNY-3590
        # Unfortunately we can't use addRPMComponent, we need the policy to
        # mark files as being overwritten
        recipe = r"""
class TestPackage(CapsuleRecipe):
    name = 'with-config-special'
    version = '0.1'

    clearBuildReqs()
    def setup(r):
        r.addCapsule('with-config-special-0.3-1.noarch.rpm')
        r.Create('/usr/share/with-config-special.txt',
            contents='some other content\n', mode=0755)
        r.Create('/usr/share/new-content.txt',
            contents='some new content\n', mode=0644)
"""
        pkgname = 'with-config-special'
        self.makeSourceTrove(pkgname, recipe)
        built = self.cookFromRepository(pkgname)
        nvf = built[0]

        self.updatePkg('%s=0.1-1-1' % pkgname)
        self.verifyFile(self.rootDir + '/usr/share/with-config-special.txt',
            'Some extra data\n', perms=0644)
        # File additions should be honored
        self.verifyFile(self.rootDir + '/usr/share/new-content.txt',
            'some new content\n', perms=0644)

    @conary_test.rpm
    def testFileModeChanges(self):
        # CNY-3590
        # Unfortunately we can't use addRPMComponent, we need the policy to
        # mark files as being overwritten
        recipe = r"""
class TestPackage(CapsuleRecipe):
    name = 'with-config-special'
    version = '0.1'

    clearBuildReqs()
    def setup(r):
        r.addCapsule('with-config-special-0.3-1.noarch.rpm')
        r.SetModes('/usr/share/with-config-special.txt', 0755)
"""
        pkgname = 'with-config-special'
        self.makeSourceTrove(pkgname, recipe)
        built = self.cookFromRepository(pkgname)
        nvf = built[0]

        self.updatePkg('%s=0.1-1-1' % pkgname)
        # Make sure we DO NOT change the mode here (see CNY-3590)
        self.verifyFile(self.rootDir + '/usr/share/with-config-special.txt',
            'Some extra data\n', perms=0644)

    @conary_test.rpm
    def testUnchangedRPM(self):
        cmp1 = self.addRPMComponent("simple:rpm=1.0-1-1",
                                    'simple-1.0-1.i386.rpm')
        self.updatePkg('simple:rpm')
        cmp1 = self.addRPMComponent("simple:rpm=1.0-1-2",
                                    'simple-1.0-1.i386.rpm')
        self.updatePkg('simple:rpm')

    @conary_test.rpm
    @testhelp.context('rollback')
    def testFileTypeChange(self):
        self.addRPMComponent("file-type-change:rpm=1-1-1",
                             'file-type-change-1-1.i386.rpm')
        self.addRPMComponent("file-type-change:rpm=2-1-1",
                             'file-type-change-2-1.i386.rpm')
        self.updatePkg('file-type-change:rpm=1')
        self.assertEquals(os.readlink(self.rootDir + '/test'), 'foo')
        self.updatePkg('file-type-change:rpm=2')
        self.verifyFile(self.rootDir + '/test', '')
        self.rollback(1)
        self.assertEquals(os.readlink(self.rootDir + '/test'), 'foo')

    @conary_test.rpm
    def testChangingSharedUpdateRPM(self):
        'CNY-3620'
        if 'x86_64' not in str(self.cfg.buildFlavor):
            raise testhelp.SkipTestException('Skip test on x86 arch')
        # avoid needing to flavor using names
        su1032 = self.addRPMComponent('shared-update-32:rpm=1.0',
                                      'shared-update-1.0-1.i386.rpm')
        su1064 = self.addRPMComponent('shared-update-64:rpm=1.0',
                                      'shared-update-1.0-1.x86_64.rpm')
        su1132 = self.addRPMComponent('shared-update-32:rpm=1.1',
                                      'shared-update-1.1-1.i386.rpm',
                                      versus=su1032)
        su1164 = self.addRPMComponent('shared-update-64:rpm=1.1',
                                      'shared-update-1.1-1.x86_64.rpm',
                                      versus=su1064)
        self.updatePkg(['shared-update-32:rpm=1.0', 'shared-update-64:rpm=1.0'])
        self.verifyFile(self.rootDir + '/usr/share/test', 'contents1.0\n')
        self.updatePkg(['shared-update-32:rpm=1.1', 'shared-update-64:rpm=1.1'])
        self.verifyFile(self.rootDir + '/usr/share/test', 'contents1.1\n')

    @conary_test.rpm
    def testRPMJobOrdering(self):
        """
        Ensure that introducing a native conary package in the dependency chain
        between two encapsuled RPM packages causes Conary to split the three
        packages into separate jobs.

        foo:rpm -> bar:runtime -> baz:rpm
        """

        self.addRPMComponent('baz:rpm=1.0', 'simple-1.0-1.i386.rpm')
        self.addComponent('bar:runtime=1.0',
            requires=deps.parseDep('trove: baz:rpm'))
        self.addRPMComponent('foo:rpm=1.0', 'ownerships-1.0-1.i386.rpm',
            requires=deps.parseDep('trove: bar:runtime'))

        rc, txt = self.captureOutput(self.updatePkg,
            [ 'foo:rpm', ], resolve=True, raiseError=True, info=True)

        self.assertEquals(txt, 'Job 1 of 3:\n'
                               '    Install baz:rpm=1.0-1-1\n'
                               'Job 2 of 3:\n'
                               '    Install bar:runtime=1.0-1-1\n'
                               'Job 3 of 3:\n'
                               '    Install foo:rpm=1.0-1-1\n')

    @conary_test.rpm
    @testhelp.context('rollback')
    def testCapsuleLocalRollbacks(self):
        try:
            self.cfg.localRollbacks = True
            c = self.addRPMComponent("simple:rpm=1.0", 'simple-1.0-1.i386.rpm')
            csPath = self.workDir + '/simple.ccs'
            repos = self.getRepositoryClient()
            repos.createChangeSetFile([
                (c.getName(), ( None, None ),
                              ( c.getVersion(), c.getFlavor() ), True ) ]
                                      , csPath)
            file("/tmp/foo", "w").write(c.freeze())
            self.addRPMComponent("simple:rpm=1.1", 'simple-1.1-1.i386.rpm')
            self.updatePkg('simple:rpm=1.0')

            testPath = os.path.join(self.rootDir, 'normal')
            self.verifyFile(testPath, 'normal\n')
            f = file(testPath, "w")
            f.write("rollback check")

            self.updatePkg('simple:rpm=1.1')
            self.verifyFile(testPath, 'changed-normal\n')

            e = self.assertRaises(errors.MissingRollbackCapsule,
                                  self.rollback, 1)
            assert('simple-1.0-1.i386.rpm' in str(e))
            self.rollback(1, capsuleChangesets = [ csPath ] )
            f.write("rollback check")

            self.updatePkg('simple:rpm=1.1')
            self.verifyFile(testPath, 'changed-normal\n')
            self.writeFile(self.workDir + '/other', 'some file')
            self.rollback(1, capsuleChangesets = [ self.workDir ] )
            f.write("rollback check")

            self.erasePkg(self.rootDir, 'simple:rpm')
            self.rollback(1, capsuleChangesets = [ self.workDir ] )
        finally:
            self.cfg.localRollbacks = False

    def checkMd5(self, path, md5):
        d = md5String(open(self.rootDir + path).read())
        self.assertEquals(md5ToString(d), md5)

    def owners(self, path):
        db = self.openDatabase()
        return set( x[0:3] for x in db.iterFindPathReferences(
                                            path, justPresent = True) )

    def checkOrdering(self, troves):
        lastOrder = [x[22:].strip() for x in
                     file(self.rootDir + '/var/log/conary').readlines()
                     if 'RPM install order' in x][-1]
        self.assertEquals(lastOrder.split(': ', 1)[1], troves)

    def checkOwners(self, path, troves):
        assert(self.owners(path) ==
                set( x.getNameVersionFlavor() for x in troves ))

    @conary_test.rpm
    def testEncapToNative(self):
        """
        Update from encapsulated package to native package with the same
        contents and modes, ensure that the file does not disappear.

        @tests: CNY-3762
        """
        self.addRPMComponent('foo:rpm=1.0', 'simple-1.0-1.i386.rpm')
        self.updatePkg('foo:rpm', raiseError=True)

        recipe = r"""
class TestPackage(CapsuleRecipe):
    name = 'foo'
    version = '2.0'

    clearBuildReqs()
    def setup(r):
        r.addArchive('simple-1.0-1.i386.rpm', dir='/', preserveOwnership=True)
"""
        src = self.makeSourceTrove('foo', recipe)
        self.cookFromRepository('foo')[0]
        self.updatePkg(['-foo:rpm', 'foo:runtime'], depCheck=False,
                raiseError=True)
        path = os.path.join(self.rootDir, 'normal')
        self.assertEqual(os.stat(path).st_size, 7)

    @conary_test.rpm
    def testEncapToNativeSloppy(self):
        """
        Update from encapsulated package to native package with the same
        contents but different modes, ensure that the file does not disappear.

        @tests: CNY-3762
        """
        self.addRPMComponent('foo:rpm=1.0', 'simple-1.0-1.i386.rpm')
        self.updatePkg('foo:rpm', raiseError=True)

        recipe = r"""
class TestPackage(CapsuleRecipe):
    name = 'foo'
    version = '2.0'

    clearBuildReqs()
    def setup(r):
        r.addArchive('simple-1.0-1.i386.rpm', dir='/')
        r.Ownership('nobody', 'nobody', '.*')
        r.SetModes('/dir', 0700)
        r.SetModes('/normal', 0600)
"""
        src = self.makeSourceTrove('foo', recipe)
        self.cookFromRepository('foo')[0]
        self.updatePkg(['-foo:rpm', 'foo:runtime'], depCheck=False,
                raiseError=True)
        path = os.path.join(self.rootDir, 'normal')
        self.assertEqual(os.stat(path).st_size, 7)
        self.assertEqual(oct(os.stat(path).st_mode), '0100600')
        path = os.path.join(self.rootDir, 'dir')
        self.assertEqual(oct(os.stat(path).st_mode), '040700')

    @conary_test.rpm
    def testEncapToNativeChanged(self):
        """
        Update from encapsulated to native package with some different contents

        @tests: CNY-3762
        """
        # Intentionally put a trailing slash on the root dir to tickle bugs
        # where a path not created with joinPaths() might cause mismatches. Of
        # course the most common real-world case, root = '/', has a "trailing"
        # slash, whereas usually in the testsuite a chroot is used and no
        # trailing slash is present.
        self.rootDir += '/'

        self.addRPMComponent('foo:rpm=1.0', 'simple-1.0-1.i386.rpm')
        self.updatePkg('foo:rpm', raiseError=True)

        recipe = r"""
class TestPackage(CapsuleRecipe):
    name = 'foo'
    version = '2.0'

    clearBuildReqs()
    def setup(r):
        r.addArchive('simple-1.0-1.i386.rpm', dir='/')
        r.Ownership('nobody', 'nobody', '.*')
        r.SetModes('/dir', 0700)
        r.Create('/normal', contents='different stuff\n', mode=0600)
"""
        src = self.makeSourceTrove('foo', recipe)
        self.cookFromRepository('foo')[0]
        self.updatePkg(['-foo:rpm', 'foo:runtime'], depCheck=False,
                raiseError=True)
        path = os.path.join(self.rootDir, 'normal')
        self.assertEqual(os.stat(path).st_size, 16)
        self.assertEqual(oct(os.stat(path).st_mode), '0100600')
        path = os.path.join(self.rootDir, 'dir')
        self.assertEqual(oct(os.stat(path).st_mode), '040700')

    @conary_test.rpm
    def testUsrmoveUpdate(self):
        """
        Update file from /sbin to /usr/sbin while /sbin is a symlink

        @tests: CNY-3885
        """
        os.makedirs(os.path.join(self.rootDir, 'usr/sbin'))
        os.symlink('usr/sbin', os.path.join(self.rootDir, 'sbin'))
        self.addRPMComponent('usrmove:rpm=1.0', 'usrmove-1.0-1.x86_64.rpm')
        self.updatePkg('usrmove:rpm', raiseError=True)
        self.addRPMComponent('usrmove:rpm=2.0', 'usrmove-2.0-1.x86_64.rpm')
        self.updatePkg('usrmove:rpm', raiseError=True)
        self.assertEqual(open(os.path.join(self.rootDir, 'usr/sbin/usrmove')).read(), '2.0\n')
예제 #24
0
 def __thaw__(jobList):
     return [(x[0], (None, None), (versions.ThawVersion(x[1]),
                                   ThawFlavor(x[2])), x[3])
             for x in jobList]
예제 #25
0
 def __thaw__(tupList):
     return [(x[0], versions.ThawVersion(x[1]), ThawFlavor(x[2]))
             for x in tupList]
예제 #26
0
 def _fromOtherTroveSpec(self, troveSpec):
     if not troveSpec:
         return
     n, v, f = conaryclient.cmdline.parseTroveSpec(troveSpec)
     self.trvOldVersion = versions.ThawVersion(v)
     self.trvOldFlavor = f
예제 #27
0
 def __thaw__((n, v, f)):
     return (n, versions.ThawVersion(v), ThawFlavor(f))
예제 #28
0
 def __thaw__(versionStr):
     return versions.ThawVersion(versionStr)
예제 #29
0
파일: repquery.py 프로젝트: pombreda/crest
def getTrove(cu, roleIds, name, version, flavor, mkUrl = None,
             thisHost = None, displayFlavor = None, excludeCapsules = False):

    def buildTupleList(tuples, name, mkUrl = mkUrl):
        l = getattr(datamodel.SingleTrove, name)()
        for troveInfo in sorted(tuples.iter()):
            l.append(name = troveInfo.name(), version = troveInfo.version(),
                     flavor = troveInfo.flavor(), mkUrl = mkUrl)

        return l

    def fileQuery(gfcu, filesInstanceId, dirName = None):
        # XXX restricing by dirName seems and obvious thing to do here,
        # but it actually slows things down??
        #
        # the distinct here is unfortunate, but conary repositories had
        # a bug for about a year which caused it to store duplicate paths
        # if a path was committed for the first time duplicate times in
        # a single commit job
        gfcu.execute("""
            SELECT DISTINCT dirName, basename, version, pathId, fileId
                FROM TroveFiles
                JOIN Versions USING (versionId)
                JOIN FileStreams ON (TroveFiles.streamId = FileStreams.streamId)
                JOIN FilePaths ON (TroveFiles.filePathId = FilePaths.filePathId)
                JOIN DirNames ON
                    FilePaths.dirNameId = DirNames.dirNameId
                JOIN Basenames ON (FilePaths.baseNameId = Basenames.baseNameId)
                WHERE TroveFiles.instanceId = ? ORDER BY dirName, basename
        """, filesInstanceId)

    cu.execute("""
        SELECT Instances.instanceId, Nodes.timeStamps FROM Instances
            JOIN Nodes USING (itemId, versionId)
            JOIN Items USING (itemId)
            JOIN Versions ON (Instances.versionId = Versions.versionId)
            JOIN Flavors ON (Instances.flavorId = Flavors.flavorId)
            JOIN UserGroupInstancesCache AS ugi
                ON (instances.instanceId = ugi.instanceId AND
                    ugi.userGroupId in (%s))
        WHERE
            item = ? AND version = ? AND flavor = ?
    """ % ",".join( str(x) for x in roleIds), name, version,
        deps.parseFlavor(flavor).freeze())

    l = [ (x[0], x[1]) for x in cu ]
    if not l:
        return None

    instanceId, timeStamps = l[0]
    frzVer = versions.strToFrozen(version, timeStamps.split(":"))
    verobj = versions.ThawVersion(frzVer)

    tupleLists = [ ( trove._TROVEINFO_TAG_BUILDDEPS, 'builddeps' ),
                   ( trove._TROVEINFO_TAG_POLICY_PROV, 'policyprovider' ),
                   ( trove._TROVEINFO_TAG_LOADEDTROVES, 'loadedtroves' ),
                   ( trove._TROVEINFO_TAG_COPIED_FROM, 'copiedfrom' ),
                   ( trove._TROVEINFO_TAG_DERIVEDFROM, 'derivedfrom' ) ]

    cu.execute("""
    SELECT infoType, data FROM TroveInfo WHERE instanceId = ? AND
        infoType IN (%s)
                """ % ",".join(str(x) for x in
                        [ trove._TROVEINFO_TAG_SOURCENAME,
                          trove._TROVEINFO_TAG_CLONEDFROM,
                          trove._TROVEINFO_TAG_CLONEDFROMLIST,
                          trove._TROVEINFO_TAG_BUILDTIME,
                          trove._TROVEINFO_TAG_SIZE,
                          trove._TROVEINFO_TAG_METADATA,
                          trove._TROVEINFO_TAG_CAPSULE,
                        ] + [ x[0] for x in tupleLists ]
                ), instanceId)

    troveInfo = {}
    for infoType, data in cu:
        data = cu.frombinary(data)
        infoClass = trove.TroveInfo.streamDict[infoType][1]
        troveInfo[infoType] = infoClass(data)

    kwargs = { 'name' : name,
               'version' : verobj,
               'flavor' : flavor }

    if displayFlavor is not None:
        kwargs['displayflavor'] = displayFlavor

    if trove._TROVEINFO_TAG_BUILDTIME in troveInfo:
        kwargs['buildtime'] = int(troveInfo[trove._TROVEINFO_TAG_BUILDTIME]())

    if trove._TROVEINFO_TAG_SOURCENAME in troveInfo:
        kwargs['source'] = (troveInfo[trove._TROVEINFO_TAG_SOURCENAME](),
            verobj.getSourceVersion(), '')

    if trove._TROVEINFO_TAG_SIZE in troveInfo:
        kwargs['size'] = troveInfo[trove._TROVEINFO_TAG_SIZE]()

    if trove._TROVEINFO_TAG_METADATA in troveInfo:
        md = troveInfo[trove._TROVEINFO_TAG_METADATA].get()
        kwargs['shortdesc'] = md['shortDesc']
        kwargs['longdesc'] = md['longDesc']

        if md['licenses']:
            kwargs['license'] = [ x for x in md['licenses' ]]
        if md['crypto']:
            kwargs['crypto'] = [ x for x in md['crypto'] ]

    for (tag, tagName) in tupleLists:
        if tag in troveInfo:
            kwargs[tagName] = buildTupleList(troveInfo[tag], tagName,
                                             mkUrl = mkUrl)

    t = datamodel.SingleTrove(mkUrl = mkUrl, thisHost = thisHost, **kwargs)

    if trove._TROVEINFO_TAG_CLONEDFROMLIST in troveInfo:
        clonedFromList = troveInfo[trove._TROVEINFO_TAG_CLONEDFROMLIST]
    elif (trove._TROVEINFO_TAG_CLONEDFROM in troveInfo):
        clonedFromList = [ troveInfo[trove._TROVEINFO_TAG_CLONEDFROM]() ]
    else:
        clonedFromList = []

    for ver in clonedFromList:
        t.addClonedFrom(name, ver, flavor, mkUrl = mkUrl)

    hasCapsule = False
    if trove._TROVEINFO_TAG_CAPSULE in troveInfo:
        if troveInfo[trove._TROVEINFO_TAG_CAPSULE].type():
            hasCapsule = True

    fileQuery(cu, instanceId)

    for (dirName, baseName, fileVersion, pathId, fileId) in cu:
        dirName = cu.frombinary(dirName)
        baseName = cu.frombinary(baseName)
        if pathId == trove.CAPSULE_PATHID:
            isCapsule = 1
            contentAvailable = not excludeCapsules
        else:
            isCapsule = None
            contentAvailable = not hasCapsule

        fileObj = datamodel.FileReference(
                        path = os.path.join(dirName, baseName),
                        version = fileVersion,
                        pathId = md5ToString(cu.frombinary(pathId)),
                        fileId = sha1ToString(cu.frombinary(fileId)),
                        isCapsule = isCapsule,
                        contentAvailable = contentAvailable,
                        mkUrl = mkUrl, thisHost = thisHost)
        t.addFile(fileObj)

    cu.execute("""
        SELECT item, version, flavor, TroveTroves.includedId, Nodes.timeStamps
          FROM TroveTroves
            JOIN Instances ON (Instances.instanceId = TroveTroves.includedId)
            JOIN Nodes USING (itemId, versionId)
            JOIN Items USING (itemId)
            JOIN Versions ON (Versions.versionId = Instances.versionId)
            JOIN Flavors ON (Flavors.flavorId = Instances.flavorId)
            WHERE
                TroveTroves.instanceId = ? AND
                (TroveTroves.flags & %d) = 0
            ORDER BY item, version, flavor
    """ % schema.TROVE_TROVES_WEAKREF, instanceId)

    for (subName, subVersion, subFlavor, refInstanceId, subTS) in cu:
        subFlavor = str(deps.ThawFlavor(subFlavor))
        frzVer = versions.strToFrozen(subVersion,
                [ x for x in subTS.split(":") ])
        subV = versions.ThawVersion(frzVer)
        t.addReferencedTrove(subName, subV, subFlavor, mkUrl = mkUrl)

        # It would be far better to use file tags to identify these build
        # logs, but it's significantly slower as well because they're in
        # the file objects rather than the trove (and those file objects
        # could be stored on a different repository)
        if not subName.endswith(':debuginfo'):
            continue

        fileQuery(cu, refInstanceId, dirName = '/usr/src/debug/buildlogs')
        logHost = subV.getHost()
        for (dirName, baseName, fileVersion, pathId, fileId) in cu:
            if (dirName) != '/usr/src/debug/buildlogs':
                continue

            if baseName.endswith('-log.bz2'):
                t.setBuildLog(logHost, sha1ToString(fileId))
            elif baseName.endswith('-xml.bz2'):
                t.setXMLBuildLog(logHost, sha1ToString(fileId))

    return t
예제 #30
0
파일: repquery.py 프로젝트: pombreda/crest
def searchNodes(cu, roleIds, label = None, mkUrl = None, filterSet = None,
                db = None, name = None, latest = 1):
    args = []
    d = { 'labelCheck' : '', 'itemCheck' : '' }
    d['roleIds'] = ",".join( str(x) for x in roleIds)
    d['SOURCENAME'] = trove._TROVEINFO_TAG_SOURCENAME
    d['METADATA'] = trove._TROVEINFO_TAG_METADATA

    if label:
        d['labelCheck'] = "label = ? AND"
        args.append(label)

    if name:
        d['itemCheck'] = "item = ? AND"
        args.append(name)

    if latest:
        cu.execute("""
            SELECT idTable.item, version, ts, finalTs, SourceNameTroveInfo.data,
                   MetadataTroveInfo.data FROM
                (SELECT DISTINCT Items.item AS item,
                                 Nodes.versionId AS versionId,
                                 Nodes.timeStamps AS ts,
                                 Nodes.finalTimeStamp as finalTs,
                                 MIN(Instances.instanceId) AS instanceId
                    FROM Labels
                    JOIN LabelMap USING (labelId)
                    JOIN LatestCache USING (itemId, branchId)
                    JOIN Nodes USING (itemId, versionId)
                    JOIN Instances USING (itemId, versionId)
                    JOIN Items USING (itemId)
                    WHERE %(labelCheck)s
                          %(itemCheck)s
                          LatestCache.latestType = 1 AND
                          LatestCache.userGroupId in (%(roleIds)s)
                    GROUP BY
                          Items.item, Nodes.versionId, Nodes.timeStamps,
                          Nodes.finalTimestamp)
                AS idTable
                JOIN Versions ON (idTable.versionId = Versions.versionId)
                LEFT OUTER JOIN TroveInfo AS SourceNameTroveInfo ON
                    idTable.instanceId = SourceNameTroveInfo.instanceId AND
                    SourceNameTroveInfo.infoType = %(SOURCENAME)d
                LEFT OUTER JOIN TroveInfo AS MetadataTroveInfo ON
                    idTable.instanceId = MetadataTroveInfo.instanceId AND
                    MetadataTroveInfo.infoType = %(METADATA)d
        """ % d, args)
    else:
        cu.execute("""
            SELECT idTable.item, version, ts, finalTs, SourceNameTroveInfo.data,
                   MetadataTroveInfo.data FROM
                (SELECT DISTINCT Items.item AS item,
                                 Nodes.versionId AS versionId,
                                 Nodes.timeStamps AS ts,
                                 Nodes.finalTimeStamp as finalTs,
                                 MIN(Instances.instanceId) AS instanceId
                    FROM Labels
                    JOIN LabelMap USING (labelId)
                    JOIN Nodes USING (itemId, branchId)
                    JOIN Instances USING (itemId, versionId)
                    JOIN Items USING (itemId)
                    JOIN usergroupinstancescache AS ugi ON
                        Instances.instanceId = ugi.instanceId
                    WHERE %(labelCheck)s
                          %(itemCheck)s
                          ugi.userGroupId in (%(roleIds)s)
                    GROUP BY
                          Items.item, Nodes.versionId, Nodes.timeStamps,
                          Nodes.finalTimestamp)
                AS idTable
                JOIN Versions ON (idTable.versionId = Versions.versionId)
                LEFT OUTER JOIN TroveInfo AS SourceNameTroveInfo ON
                    idTable.instanceId = SourceNameTroveInfo.instanceId AND
                    SourceNameTroveInfo.infoType = %(SOURCENAME)d
                LEFT OUTER JOIN TroveInfo AS MetadataTroveInfo ON
                    idTable.instanceId = MetadataTroveInfo.instanceId AND
                    MetadataTroveInfo.infoType = %(METADATA)d
        """ % d, args)

    l = list(cu)
    filteredL = typeFilter(l, filterSet)

    # sort based on (name, version, desc(finalTimestamp))
    def sortorder(x, y):
        c = cmp(x[0], y[0])
        if c:
            return c

        return -(cmp(x[3], y[3]))

    filteredL.sort(sortorder)

    if latest:
        # keep the latest
        newL = []
        last = None
        for item in filteredL:
            if last and last[0] == item[0]:
                continue

            newL.append(item)
            last = item

        filteredL = newL

    nodeList = datamodel.NamedNodeList(total = len(filteredL), start = 0)

    addList = []
    for (name, version, ts, finalTs, sourceName, metadata) in filteredL:
        sourceName = cu.frombinary(sourceName)
        if sourceName is None and trove.troveIsSourceComponent(name):
            sourceName = name
        addList.append((sourceName,
                str(versions.VersionFromString(version).getSourceVersion())))

    schema.resetTable(cu, 'tmpNVF')

    # This is painful, but it converts the source name from a blob to
    # a string
    db.bulkload("tmpNVF", [ (x[0],) + x[1] for x in enumerate(addList) ],
                ["idx", "name", "version"],
                start_transaction = False)
    cu.execute("""
        SELECT ChangeLogs.name, ChangeLogs.message, tmpNVF.name
            FROM tmpNVF JOIN Items AS SourceItems ON
                tmpNVF.name = SourceItems.item
            LEFT OUTER JOIN Versions AS SourceVersion ON
                tmpNVF.version = SourceVersion.version
            LEFT OUTER JOIN Nodes ON
                SourceItems.itemId = Nodes.itemId AND
                SourceVersion.versionId = Nodes.versionId
            LEFT OUTER JOIN ChangeLogs USING (nodeId)
            ORDER BY tmpNVF.idx
    """)

    for ( (name, version, ts, finalTs, sourceName, metadata),
          (clName, clMessage, troveName) ) in itertools.izip(filteredL, cu):
        frzVer = versions.strToFrozen(version,
                                      [ x for x in ts.split(":") ])
        ver = versions.ThawVersion(frzVer)

        shortdesc = None

        if metadata:
            metadata = cu.frombinary(metadata)
            md = trove.Metadata(metadata)
            shortdesc = md.get()['shortDesc']

        if clName:
            cl = datamodel.ChangeLog(name = clName, message = clMessage)
        else:
            cl = None

        nodeList.append(name = name, version = ver, mkUrl = mkUrl,
                        changeLog = cl, shortdesc = shortdesc)

    return nodeList