Exemplo n.º 1
0
 def testFindTrove(self):
     db = database.Database(':memory:', ':memory:')
     self.assertEqual(db.getTransactionCounter(), 0)
     flavor = deps.parseFlavor('~readline,!foo')
     v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10-1")
     f1 = files.FileFromFilesystem("/etc/passwd", self.id1)
     trv = trove.Trove("testcomp", v10, flavor, None)
     trv.addFile(self.id1, "/bin/1", v10, f1.fileId())
     trvInfo = db.addTrove(trv)
     db.addTroveDone(trvInfo)
     f2 = files.FileFromFilesystem("/etc/group", self.id2)
     v20 = ThawVersion("/conary.rpath.com@local:blah/20:1.3-2-1")
     trv = trove.Trove("testcomp", v20, flavor, None)
     trv.addFile(self.id2, "/bin/2", v20, f2.fileId())
     trvInfo = db.addTrove(trv)
     db.addTroveDone(trvInfo)
     tup = [('testcomp', v10, flavor)]
     tup2 = [('testcomp', v10, flavor), ('testcomp', v20, flavor)]
     assert (db.findTrove(None, ('testcomp', '1.2-10-1', None)) == tup)
     assert (db.findTrove(None, ('testcomp', '1.2', None)) == tup)
     assert (set(db.findTrove(
         None, ('testcomp', None, parseFlavor('!foo')))) == set(tup2))
     assert (db.findTrove(None, ('testcomp', ':trunk', None)) == tup)
     assert (db.findTrove([Label('conary.rpath.com@test:foo')],
                          ('testcomp', ':trunk', None)) == tup)
     assert (db.findTrove(None, ('testcomp', ':trunk', None)) == tup)
     assert (db.findTrove(None, ('testcomp', '@test:trunk', None)) == tup)
     assert (db.findTrove([Label('conary.rpath.com@blah:foo')],
                          ('testcomp', '@test:trunk', None)) == tup)
     # Transaction counter changes upon commit
     self.assertEqual(db.getTransactionCounter(), 0)
     db.commit()
     self.assertEqual(db.getTransactionCounter(), 1)
Exemplo n.º 2
0
    def testFileContentsMissing(self):
        # currently causes a 500 error
        #raise testhelp.SkipTestException
        # create an absolute changeset
        cs = changeset.ChangeSet()

        # add a pkg diff
        flavor = deps.deps.parseFlavor('')
        v = versions.VersionFromString('/%s/1.0-1-1'
                                       %self.cfg.buildLabel.asString()).copy()
        v.resetTimeStamps()
        t = trove.Trove('test:test', v, flavor, None)
        path = self.workDir + '/blah'
        f = open(path, 'w')
        f.write('hello, world!\n')
        f.close()
        pathId = sha1helper.md5String('/blah')
        f = files.FileFromFilesystem(path, pathId)
        # add the file, but munge the fileid
        fileId = f.fileId()
        cs.addFile(None, fileId, f.freeze())
        t.addFile(pathId, '/blah', v, fileId)
        # skip adding the file contents
        t.computeDigests()

        diff = t.diff(None, absolute = 1)[0]
        cs.newTrove(diff)

        repos = self.openRepository()
        try:
            repos.commitChangeSet(cs)
            assert 0, "Did not raise integrity error"
        except errors.IntegrityError, e:
            assert(str(e).startswith("Missing file contents for pathId e806729b6a2b568fa7e77c3efa3a9684, fileId"))
Exemplo n.º 3
0
    def testFileObjMissing(self):
        # create an absolute changeset
        cs = changeset.ChangeSet()

        # add a pkg diff
        flavor = deps.deps.parseFlavor('')
        v = versions.VersionFromString('/%s/1.0-1-1'
                                       %self.cfg.buildLabel.asString()).copy()
        v.resetTimeStamps()
        t = trove.Trove('test:test', v, flavor, None)
        path = self.workDir + '/blah'
        f = open(path, 'w')
        f.write('hello, world!\n')
        f.close()
        pathId = sha1helper.md5String('/blah')
        f = files.FileFromFilesystem(path, pathId)
        # add the file, and SKIP including
        # the filestream by using cs.addFile().  This creates an
        # incomplete changeset
        t.addFile(pathId, '/blah', v, f.fileId())
        cs.addFileContents(pathId, f.fileId(), changeset.ChangedFileTypes.file,
                           filecontents.FromFilesystem(path),
                           f.flags.isConfig())

        t.computeDigests()
        diff = t.diff(None, absolute = 1)[0]
        cs.newTrove(diff)

        repos = self.openRepository()
        try:
            repos.commitChangeSet(cs)
            assert 0, "Did not raise IntegrityError"
        except errors.IntegrityError, e:
            assert(str(e).startswith("Incomplete changeset specified: missing pathId e806729b6a2b568fa7e77c3efa3a9684 fileId"))
Exemplo n.º 4
0
    def testCommonFiles(self):
        # this test simulates a trove having the ame file in different
        # path locations with only changed mtimes.
        store = self._connect()
        flavor = deps.Flavor()
        version = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10")

        baseNames = set(['file'])
        dirNames = set(['/junk1', '/junk2'])

        f = files.FileFromFilesystem("/etc/passwd", self.id)
        trv = trove.Trove("junk:data", version, flavor, None)
        trv.addFile(self.id1, "/junk1/file", version, f.fileId())
        trv.addFile(self.id2, "/junk2/file", version, f.fileId())
        trv.computeDigests()

        store.db.transaction()
        store.addTroveSetStart([], dirNames, baseNames)
        ti = store.addTrove(trv, trv.diff(None)[0])
        f.inode.mtime.set(1)
        ti.addFile(self.id1,
                   "/junk1/file",
                   f.fileId(),
                   version,
                   fileStream=f.freeze())
        f.inode.mtime.set(2)
        ti.addFile(self.id2,
                   "/junk2/file",
                   f.fileId(),
                   version,
                   fileStream=f.freeze())
        store.addTroveDone(ti)
        store.commit()
Exemplo n.º 5
0
    def testSymbolicLink(self):
        s = files.SymbolicLink(None)
        s.inode.perms.set(0604)
        s.inode.mtime.set(0100)
        s.inode.owner.set('daemon')
        s.inode.group.set('uucp')
        # to make sure that referenced names "exist"
        files.userCache.nameCache['daemon'] = 2
        files.groupCache.nameCache['uucp'] = 14
        s.flags.set(0)
        s.target.set("/some/target")
        assert(s.sizeString() == "      12")
        d = tempfile.mkdtemp()
        try:
            p = d + "/bar/foo"
            s.restore(None, d, p)
            what = os.readlink(p)
            assert(what == "/some/target")
            s2 = files.SymbolicLink(None)
            s2.target.set("/some/place")
            s2.restore(None, d, p)
            s3 = files.FileFromFilesystem(p, None)
            assert(s2.target == s3.target)
            assert(s.target != s3.target)
        finally:
            shutil.rmtree(d)

        s2 = files.ThawFile(s.freeze(), None)
        assert(s == s2)

        # make sure that the frozen form matches what we expect
        self.assertEqual(s.freeze(), 'l\x03\x00\x04\x00\x00\x00\x00\x05\x00\x1c\x01\x00\x02\x01\x84\x02\x00\x04\x00\x00\x00@\x03\x00\x06daemon\x04\x00\x04uucp\t\x00\x0c/some/target')
Exemplo n.º 6
0
    def testHidden(self):
        store = self._connect()
        cu = store.db.cursor()

        flavor = deps.Flavor()
        version = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10")

        f = files.FileFromFilesystem("/etc/passwd", self.id)
        trv = trove.Trove("junk:data", version, flavor, None)
        trv.computeDigests()

        store.addTroveSetStart([], set(['/etc']), set(['passwd']))
        ti = store.addTrove(trv, trv.diff(None)[0], hidden=True)
        store.addTroveDone(ti)
        store.addTroveSetDone()

        assert (cu.execute("select count(*) from latestcache").fetchall()[0][0]
                == 0)
        assert (cu.execute("select isPresent from instances").fetchall()[0][0]
                == instances.INSTANCE_PRESENT_HIDDEN)

        store.presentHiddenTroves()
        assert (cu.execute("select count(*) from latestcache").fetchall()[0][0]
                == 3)
        assert (cu.execute("select isPresent from instances").fetchall()[0][0]
                == instances.INSTANCE_PRESENT_NORMAL)
Exemplo n.º 7
0
    def testSocket(self):
        s = files.Socket(None)
        s.inode.perms.set(0604)
        s.inode.mtime.set(0100)
        s.inode.owner.set(self.owner)
        s.inode.group.set(self.group)
        s.flags.set(0)
        assert(s.sizeString() == "       0")
        d = tempfile.mkdtemp()
        try:
            p = d + "/bar/foo"
            s.restore(None, d, p)
            what = os.stat(p)
            assert(stat.S_ISSOCK(what.st_mode))
            assert(what.st_mtime == 0100)
            assert(what.st_mode & 07777 == 0604)

            s2 = files.FileFromFilesystem(p, None)
            assert(s == s2)

            # make sure an os.unlink() happens
            s.restore(None, d, p)
        finally:
            shutil.rmtree(d)

        s2 = files.ThawFile(s.freeze(), None)
        assert(s == s2)
Exemplo n.º 8
0
    def testUnknownUser(self):
        # CNY-1071
        # Tests that FileFromFilesystem packs '+UID' as the owner (and '+GID'
        # as the group) if the owner/group don't exist.
        fobj = tempfile.NamedTemporaryFile()
        fobj.write("test\n")
        fobj.flush()

        uid, gid = self.findUnknownIds()

        import posix
        origLstat = os.lstat
        def myLstat(path):
            s = origLstat(path)
            if path == fobj.name:
                # Convert the stat info to a tuple
                s = tuple(s)
                # Replace st_uid and st_gid
                s = s[:4] + (uid, gid) + s[6:]
                # Convert to stat_result
                s = posix.stat_result(s)
                self.assertEqual(s.st_uid, uid)
                self.assertEqual(s.st_gid, gid)
            return s

        try:
            os.lstat = myLstat
            # No failure here
            f = files.FileFromFilesystem(fobj.name, None)
            self.assertEqual(f.inode.owner(), "+" + str(uid))
            self.assertEqual(f.inode.group(), "+" + str(gid))
        finally:
            os.lstat = origLstat
Exemplo n.º 9
0
    def testFileIdWrong(self):
        # create an absolute changeset
        cs = changeset.ChangeSet()

        # add a pkg diff
        flavor = deps.deps.parseFlavor('')
        v = versions.VersionFromString('/%s/1.0-1-1'
                                       %self.cfg.buildLabel.asString()).copy()
        v.resetTimeStamps()
        t = trove.Trove('test:test', v, flavor, None)
        path = self.workDir + '/blah'
        f = open(path, 'w')
        f.write('hello, world!\n')
        f.close()
        pathId = sha1helper.md5String('/blah')
        f = files.FileFromFilesystem(path, pathId)
        # add the file, but munge the fileid
        brokenFileId = ''.join(reversed(f.fileId()))
        cs.addFile(None, brokenFileId, f.freeze())
        t.addFile(pathId, '/blah', v, brokenFileId)
        t.computeDigests()

        diff = t.diff(None, absolute = 1)[0]
        cs.newTrove(diff)

        repos = self.openRepository()
        try:
            repos.commitChangeSet(cs)
            assert 0, "Integrity Error not raised"
        except errors.TroveIntegrityError, e:
            assert(str(e) == 'fileObj.fileId() != fileId in changeset for '
                             'pathId %s' % sha1helper.md5ToString(pathId))
Exemplo n.º 10
0
    def addFile(self, path, realPath):
        """
        Add a file to the build component

        @param path: the destination of the file in the component
        @param realPath: the location of the actual file on the filesystem,
        used to obtain the contents of the file when creating a changeset
        to commit to the repository
        """
        # skip uid/gid lookups because packagepolicy will change the
        # ownerships according to Ownership settings anyway
        (f, linkCount, inode) = files.FileFromFilesystem(realPath, None,
                                        inodeInfo = True, assumeRoot = True)
        f.inode.perms.set(f.inode.perms() & 01777)
        self[path] = (realPath, f)
        if (f.inode.perms() & 0400) != 0400:
            # we can safely change the permissions now, the original
            # permissions have been recorded
            os.chmod(realPath, f.inode.perms() | 0400)

        if linkCount > 1:
            if f.hasContents:
                l = self.linkGroups.get(inode, [])
                l.append(path)
                self.linkGroups[inode] = l
                # add to list to check for config files later
                self.hardlinkMap[path] = l
            else:
                if not isinstance(f, files.Directory):
                    # no hardlinks allowed for special files other than dirs
                    self.badhardlinks.append(path)
        return f
Exemplo n.º 11
0
    def testDatabase2(self):
        db = sqldb.Database(':memory:')

        f1 = files.FileFromFilesystem("/etc/passwd", self.id1)
        f2 = files.FileFromFilesystem("/etc/services", self.id2)
        f3 = files.FileFromFilesystem("/etc/group", self.id3)

        trv = trove.Trove("testcomp", self.v10, self.emptyFlavor, None)
        trv.addFile(self.id1, "/bin/1", self.v10, f1.fileId())
        trv.addFile(self.id2, "/bin/2", self.v10, f2.fileId())
        trv.addFile(self.id3, "/bin/3", self.v10, f3.fileId())
        trvInfo = db.addTrove(trv)

        db.addFile(trvInfo,
                   f1.pathId(),
                   "/bin/1",
                   f1.fileId(),
                   self.v10,
                   fileStream=f1.freeze())
        db.addFile(trvInfo,
                   f2.pathId(),
                   "/bin/2",
                   f2.fileId(),
                   self.v10,
                   fileStream=f2.freeze())
        db.addFile(trvInfo,
                   f3.pathId(),
                   "/bin/3",
                   f3.fileId(),
                   self.v10,
                   fileStream=f3.freeze())

        db.addTroveDone(trvInfo)

        assert (db.getTroves([("testcomp", self.v10, self.emptyFlavor),
                              ("testcomp", self.v20, self.emptyFlavor)],
                             True) == [trv, None])
        assert (db.hasTroves([("testcomp", self.v10, self.emptyFlavor),
                              ("testcomp", self.v20, self.emptyFlavor)
                              ]) == [True, False])

        f2 = files.FileFromFilesystem("/etc/hosts", self.id2)

        trv2 = trove.Trove("testcomp", self.v20, self.emptyFlavor, None)
        trv2.addFile(self.id1, "/bin/1", self.v10, self.fid1)
        trv2.addFile(self.id2, "/bin/2", self.v20, self.fid2)
Exemplo n.º 12
0
 def _addFile(self, cs, trv, path):
     pathId = sha1helper.md5String(path)
     absPath = self.cfg.root + path
     fileObj = files.FileFromFilesystem(absPath, pathId)
     fileId = fileObj.fileId()
     trv.addFile(pathId, path, trv.getVersion(), fileId)
     cs.addFile(None, fileId, fileObj.freeze())
     if fileObj.hasContents:
         cs.addFileContents(pathId, fileId, changeset.ChangedFileTypes.file,
                            filecontents.FromFilesystem(absPath), False)
Exemplo n.º 13
0
    def testPrelink(self):
        user = pwd.getpwuid(os.getuid()).pw_name
        group = grp.getgrgid(os.getgid()).gr_name
        archivePath = resources.get_archive()
        self.addComponent('test:foo=1',
                          fileContents=[
                              ('/prelinktest',
                               rephelp.RegularFile(
                                   contents=open(archivePath + '/prelinktest'),
                                   owner=user,
                                   group=group,
                                   mode=0755)),
                              ('/prelinktest-orig',
                               rephelp.RegularFile(
                                   contents=open(archivePath + '/prelinktest'),
                                   owner=user,
                                   group=group,
                                   mode=0755))
                          ])
        self.updatePkg('test:foo=1')

        db = database.Database(self.rootDir, self.cfg.dbPath)
        rc, str = self.captureOutput(verify.verify, ['test:foo'], db, self.cfg)
        self.assertEquals(str, '')

        binary = self.rootDir + '/prelinktest'
        # the test suite can't set the mtime on the file; we'll preserve
        # it ourself
        sb = os.stat(binary)
        os.system("cp %s/prelinktest-prelinked %s" % (archivePath, binary))
        os.utime(binary, (sb.st_atime, sb.st_mtime))

        self.assertEquals(files.PRELINK_CMD, ('/usr/sbin/prelink', ))
        oldCmd = files.PRELINK_CMD
        try:
            files.PRELINK_CMD = (archivePath + '/prelink', )
            files._havePrelink = None
            rc, str = self.captureOutput(verify.verify, ['test:foo'],
                                         db,
                                         self.cfg,
                                         forceHashCheck=True)
            self.assertEquals(str, '')

            # Also verify a path used by addCapsule
            f, nlinks, devino = files.FileFromFilesystem(binary,
                                                         pathId='\0' * 16,
                                                         inodeInfo=True)
            self.assertEquals(
                digestlib.sha1(open(binary).read()).hexdigest(),
                '1114f3a978b60d76d7618dc43aaf207bc999f997')
            self.assertEquals(f.contents.sha1().encode('hex'),
                              '23ad3a2c940a30809b68a5b8a13392196004efab')
        finally:
            files.PRELINK_CMD = oldCmd
            files._havePrelink = None
Exemplo n.º 14
0
    def testFileUpdateMissingKey(self):
        fingerprint = '95B457D16843B21EA3FC73BBC7C32FC1F94E405E'

        # make a changeset with useful stuff that could be installed
        cs = changeset.ChangeSet()
        flavor = deps.parseFlavor('')
        v = versions.VersionFromString('/%s/1.0-1-1' %
                                       self.cfg.buildLabel.asString()).copy()
        v.resetTimeStamps()
        t = trove.Trove('test:test', v, flavor, None)

        path = self.workDir + '/blah'
        f = open(path, 'w')
        f.write('hello, world!\n')
        f.close()
        pathId = sha1helper.md5String('/blah')
        f = files.FileFromFilesystem(path, pathId)

        fileId = f.fileId()
        t.addFile(pathId, '/blah', v, fileId)
        cs.addFile(None, fileId, f.freeze())
        cs.addFileContents(pathId, fileId, changeset.ChangedFileTypes.file,
                           filecontents.FromFilesystem(path),
                           f.flags.isConfig())
        diff = t.diff(None, absolute=1)[0]
        cs.newTrove(diff)
        cs.addPrimaryTrove('test:test', v, flavor)

        # sign the changeset
        csPath = os.path.join(self.workDir, 'test-1.0-1.ccs')
        cs = cook.signAbsoluteChangeset(cs, fingerprint)
        cs.writeToFile(csPath)

        tmpPath = mkdtemp()

        keyCache = openpgpkey.getKeyCache()
        newKeyCache = openpgpkey.OpenPGPKeyFileCache()

        pubRing = self.cfg.pubRing

        self.cfg.pubRing = [tmpPath + '/pubring.gpg']
        keyCacheCallback = openpgpkey.KeyCacheCallback(None, self.cfg)
        newKeyCache.setCallback(keyCacheCallback)

        openpgpkey.setKeyCache(newKeyCache)

        try:
            self.updatePkg(self.rootDir, csPath)
        finally:
            self.cfg.pubRing = pubRing
            openpgpkey.setKeyCache(keyCache)
Exemplo n.º 15
0
 def testEmptyPerms(self):
     # make sure we can read in a file with no perms; we mistook '0'
     # for None (CNY-1678)
     fd, fpath = tempfile.mkstemp()
     os.write(fd, "test\n")
     os.close(fd)
     try:
         os.chmod(fpath, 000)
         f = files.FileFromFilesystem(fpath, None)
         assert(f.inode.owner() != None)
         assert(f.inode.group() != None)
         assert(f.inode.perms() == 0)
     finally:
         os.unlink(fpath)
Exemplo n.º 16
0
    def testChangeSetFromFile(self):
        # ensure that absolute changesets that are read from disk
        # that contain config files write out changesets to a file
        # that do not change the file type to a diff.
        # set up a file with some contents
        cont = self.workDir + '/contents'
        f = open(cont, 'w')
        f.write('hello, world!\n')
        f.close()
        pathId = sha1helper.md5FromString('0' * 32)
        f = files.FileFromFilesystem(cont, pathId)
        f.flags.isConfig(1)

        # create an absolute changeset
        cs = changeset.ChangeSet()

        # add a pkg diff
        v = versions.VersionFromString('/localhost@rpl:devel/1.0-1-1',
                                       timeStamps=[1.000])
        flavor = deps.parseFlavor('')
        t = trove.Trove('test', v, flavor, None)
        t.addFile(pathId, '/contents', v, f.fileId())
        diff = t.diff(None, absolute=1)[0]
        cs.newTrove(diff)

        # add the file and file contents
        cs.addFile(None, f.fileId(), f.freeze())
        cs.addFileContents(pathId, f.fileId(), changeset.ChangedFileTypes.file,
                           filecontents.FromFilesystem(cont),
                           f.flags.isConfig())

        # write out the changeset
        cs.writeToFile(self.workDir + '/foo.ccs')
        # read it back in
        cs2 = changeset.ChangeSetFromFile(self.workDir + '/foo.ccs')
        # write it out again (there was a bug where all config files
        # became diffs)
        cs2.writeToFile(self.workDir + '/bar.ccs')
        # read it again
        cs3 = changeset.ChangeSetFromFile(self.workDir + '/bar.ccs')
        # verify that the file is a file, not a diff
        ctype, contents = cs3.getFileContents(pathId, f.fileId())
        assert (ctype == changeset.ChangedFileTypes.file)
Exemplo n.º 17
0
    def testDuplicatePaths(self):
        store = self._connect()

        v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10")
        flavor1 = deps.Flavor()
        flavor2 = deps.parseFlavor('is:x86')
        cl = changelog.ChangeLog("test", "*****@*****.**", "Changes\n")
        f1 = files.FileFromFilesystem("/etc/passwd", self.id1)

        trv1 = trove.Trove('testcomp', v10, flavor1, cl)
        trv1.addFile(f1.pathId(), "/bin/1", v10, f1.fileId())

        trv2 = trove.Trove('testcomp', v10, flavor2, cl)
        trv2.addFile(f1.pathId(), "/bin/1", v10, f1.fileId())

        store.db.transaction()
        store.addTroveSetStart([], set(['/bin']), set(['1']))

        troveInfo = store.addTrove(trv1, trv1.diff(None)[0])
        troveInfo.addFile(f1.pathId(),
                          "/bin/1",
                          f1.fileId(),
                          v10,
                          fileStream=f1.freeze())
        store.addTroveDone(troveInfo)

        troveInfo = store.addTrove(trv2, trv2.diff(None)[0])
        troveInfo.addFile(f1.pathId(),
                          "/bin/1",
                          f1.fileId(),
                          v10,
                          fileStream=f1.freeze())
        store.addTroveDone(troveInfo)

        store.addTroveSetDone()
        store.db.commit()

        # make sure the path was inserted into FilePaths and friends once
        cu = store.db.cursor()
        for tbl in ['FilePaths', 'Dirnames', 'Basenames']:
            cu.execute("select count(*) from %s" % tbl)
            self.assertEquals(cu.next()[0], 1)
Exemplo n.º 18
0
    def testDuplicateStreams(self):
        store = self._connect()
        flavor = deps.Flavor()

        v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10")
        v20 = ThawVersion("/conary.rpath.com@test:trunk/20:1.2-20")

        dirNames = set(['/bin', '/etc'])
        baseNames = set(['1', '2'])

        f1 = files.FileFromFilesystem("/etc/passwd", self.id1)

        trv = trove.Trove("testpkg:runtime", v10, flavor, None)
        trv.addFile(f1.pathId(), "/bin/1", v10, f1.fileId())
        trv.computeDigests()

        store.db.transaction()
        store.addTroveSetStart([], dirNames, baseNames)
        troveInfo = store.addTrove(trv, trv.diff(None)[0])
        troveInfo.addFile(f1.pathId(), "/bin/1", f1.fileId(), v10)
        store.addTroveDone(troveInfo)
        store.addTroveSetDone()
        store.db.commit()

        trv = trove.Trove("testpkg:runtime", v20, flavor, None)
        trv.addFile(f1.pathId(), "/bin/1", v20, f1.fileId())
        trv.addFile(f1.pathId(), "/bin/2", v20, f1.fileId())
        trv.computeDigests()

        store.db.transaction()
        store.addTroveSetStart([], dirNames, baseNames)
        troveInfo = store.addTrove(trv, trv.diff(None)[0])
        troveInfo.addFile(f1.pathId(), "/bin/1", f1.fileId(), v10)
        troveInfo.addFile(f1.pathId(), "/bin/2", f1.fileId(), v10)
        store.addTroveDone(troveInfo)
        store.db.commit()
Exemplo n.º 19
0
    def remove(self, trv):
        SingleCapsuleOperation.remove(self, trv)

        # make sure everything was erased which should have been; RPM's
        # shared file handling means it may not erase things which we think
        # ought to be
        for trv in self.removes:
            dbFileObjs = self.db.getFileVersions([(x[0], x[2], x[3])
                                                  for x in trv.iterFileList()])

            for (pathId, path, fileId, version), fileObj in \
                    itertools.izip(trv.iterFileList(), dbFileObjs):
                hasCapsule = trv.troveInfo.capsule.type() or False
                fullPath = util.joinPaths(self.root, path)
                if not os.path.exists(fullPath):
                    continue

                if (fileObj.flags.isCapsuleAddition()):
                    # this was added to the package outside of the RPM;
                    # we don't have any responsibility for it
                    continue
                elif (fileObj.hasContents
                      and trove.conaryContents(hasCapsule, pathId, fileObj)):
                    # this content isn't part of the capsule; remember to put
                    # it back when RPM is done
                    self.preservePath(path, unlink=True)
                    continue

                fsFileObj = files.FileFromFilesystem(fullPath,
                                                     pathId,
                                                     possibleMatch=fileObj)
                self.fsJob._remove(fsFileObj,
                                   path,
                                   fullPath,
                                   'removing rpm owned file %s',
                                   ignoreMissing=True)
Exemplo n.º 20
0
    def install(self, flags, troveCs):
        ACTION_RESTORE = 1
        ACTION_SKIP = 2
        ACTION_CONFLICT = 3

        rc = SingleCapsuleOperation.install(self, flags, troveCs)
        if rc is None:
            # parent class thinks we should just ignore this troveCs; I'm
            # not going to argue with it (it's probably because the capsule
            # hasn't changed
            return None

        (oldTrv, trv) = rc
        trvInfo = troveCs.getNewNameVersionFlavor()
        oldTrvInfo = troveCs.getOldNameVersionFlavor()
        hasCapsule = troveCs.hasCapsule()

        # Updates the fsJob metadata for installing the current trove.
        # It assumes files are replaced on install, and complains if something
        # is in the way unless the appropriate flags are set. This is a very
        # much simplified version of FilesystemJob._singleTrove() which maps
        # out a complete install strategy for native packages. Note that
        # we walk all of the files in this trove, not just the new files
        # or the changed files, because RPM installs all of the files.
        toRestore = []

        changedByPathId = dict((x[0], x) for x in troveCs.getChangedFileList())

        # things which aren't change, new, or removed are unchanged
        unchangedByPathId = (set(x[0] for x in trv.iterFileList()) -
                             set(changedByPathId.iterkeys()) -
                             set(x[0] for x in troveCs.getNewFileList()) -
                             set(troveCs.getOldFileList()))

        l = []
        for oldFileInfo in troveCs.getChangedFileList():
            oldFileId, oldVersion = oldTrv.getFile(oldFileInfo[0])[1:3]
            l.append((oldFileInfo[0], oldFileId, oldVersion))

        for unchangedPathId in unchangedByPathId:
            unchangedFileId, unchangedFileVersion = \
                                    trv.getFile(unchangedPathId)[1:3]
            l.append((unchangedPathId, unchangedFileId, unchangedFileVersion))

        fileObjs = self.db.getFileVersions(l)
        fileObjsByPathId = dict([(x[0], y)
                                 for x, y in itertools.izip(l, fileObjs)])

        for fileInfo in trv.iterFileList():
            pathId, path, fileId, version = fileInfo

            if os.path.dirname(path) in self.netSharedPath:
                # we do nothing. really. nothing.
                #
                # we don't back it up. we don't mark it as removed in
                # our database. we don't look for conflicts. nothing.
                continue

            if pathId in changedByPathId:
                oldFileId = oldTrv.getFile(pathId)[1]
                fileChange = self.changeSet.getFileChange(oldFileId, fileId)
                if (oldFileId == fileId):
                    # only the version number changed; we don't need
                    # to merge anything here
                    fileObj = fileObjsByPathId[pathId]
                elif fileChange[0] == '\x01':
                    fileObj = fileObjsByPathId[pathId]
                    fileObj.twm(fileChange, fileObj)
                else:
                    fileObj = files.ThawFile(fileChange, pathId)
            elif pathId in unchangedByPathId:
                fileObj = fileObjsByPathId[pathId]
            else:
                # if it's not changed and it's not unchanged, it must be new
                fileStream = self.changeSet.getFileChange(None, fileId)
                fileObj = files.ThawFile(fileStream, pathId)

            absolutePath = util.joinPaths(self.root, path)

            if (fileObj.flags.isCapsuleAddition()):
                # this was added to the package outside of the RPM; we don't
                # have any responsibility for it
                continue
            elif (trove.conaryContents(hasCapsule, pathId, fileObj)
                  and fileObj.lsTag != 'd'):
                # this content isn't part of the capsule; remember to put
                # it back when RPM is done
                self.preservePath(path, unlink=True)
                continue

            s = util.lstat(absolutePath)
            if not s:
                # there is nothing in the way, so there is nothing which
                # concerns us here. Track the file for later.
                toRestore.append((fileInfo, fileObj))
                continue

            action = ACTION_CONFLICT

            existingOwners = list(
                self.db.iterFindPathReferences(path,
                                               justPresent=True,
                                               withStream=True))

            if existingOwners:
                # Don't complain about files owned by the previous version
                # of this trove.
                l = [x for x in existingOwners if x[0:3] == oldTrvInfo]
                if l:
                    existingOwners.remove(l[0])

                if not existingOwners:
                    action = ACTION_RESTORE
            elif stat.S_ISDIR(s.st_mode) and fileObj.lsTag == 'd':
                # Don't let existing directories stop us from taking over
                # ownership of the directory
                action = ACTION_RESTORE
            elif fileObj.flags.isInitialContents():
                # Initial contents files may be restored on top of things
                # already in the filesystem. They're ghosts or config files
                # and RPM will get the contents right either way, and we
                # should remove them either way.
                action = ACTION_RESTORE

            if action == ACTION_CONFLICT and not existingOwners:
                # Check for "conflicts" that might just be a view across a
                # symlink.
                if self.fsJob.findAliasedRemovals(absolutePath):
                    action = ACTION_RESTORE

            if action == ACTION_CONFLICT and existingOwners:
                if fileId in [x[4] for x in existingOwners]:
                    # The files share metadata same. Whatever it looks like on
                    # disk, RPM is going to blow it away with the new one.
                    for info in existingOwners:
                        self.fsJob.sharedFile(info[0], info[1], info[2],
                                              info[3])
                    action = ACTION_RESTORE
                elif path.startswith('/usr/share/doc/'):
                    # Mirror badness Red Hat patches into RPM for rhel4
                    # and rhel5
                    action = ACTION_RESTORE
                else:
                    existingFiles = [
                        files.ThawFile(x[5], pathId) for x in existingOwners
                    ]

                    compatibility = [
                        1 for x in existingFiles if fileObj.compatibleWith(x)
                    ]

                    if 1 in compatibility:
                        # files can be shared even though the fileId's
                        # are different
                        for info in existingOwners:
                            self.fsJob.sharedFile(info[0], info[1], info[2],
                                                  info[3])
                        action = ACTION_RESTORE
                    elif 1 in [
                            files.rpmFileColorCmp(x, fileObj)
                            for x in existingFiles
                    ]:
                        # rpm file colors and the default rpm setting for
                        # file color policy make elf64 files silently replace
                        # elf32 files. follow that behavior here.
                        #
                        # no, i'm not making this up
                        #
                        # yes, really
                        action = ACTION_SKIP
                    elif (self._checkReplaceManagedFiles(flags, path) or 1 in [
                            files.rpmFileColorCmp(fileObj, x)
                            for x in existingFiles
                    ]):
                        # The files are different. Bail unless we're supposed
                        # to replace managed files.
                        existingFile = files.FileFromFilesystem(
                            absolutePath, pathId)
                        for info in existingOwners:
                            self.fsJob.userRemoval(
                                fileObj=existingFile,
                                content=filecontents.FromFilesystem(
                                    absolutePath),
                                *info[0:4])
                        action = ACTION_RESTORE
                    else:
                        # it's not up to us to decide if this is a true
                        # conflict; the database layer will do that for
                        # us (see checkPathConflicts)
                        action = ACTION_RESTORE
            elif flags.replaceUnmanagedFiles:
                # we don't own it, but it's on disk. RPM will just write over
                # it and we have the flag saying we're good with that
                action = ACTION_RESTORE

            if action == ACTION_RESTORE:
                # We may proceed, and RPM will replace this file for us. We
                # need to track that it's being restored to avoid conflicts
                # with other restorations though.
                toRestore.append((fileInfo, fileObj))
            elif action == ACTION_CONFLICT:
                # The file exists already, we can't share it, and we're not
                # allowed to overwrite it.
                self._error(
                    errors.FileInWayError(util.normpath(path),
                                          troveCs.getName(),
                                          troveCs.getNewVersion(),
                                          troveCs.getNewFlavor()))
            else:
                assert (action == ACTION_SKIP)
                self.preservePath(path, unlink=False)
                self.fsJob.userRemoval(trv.getName(), trv.getVersion(),
                                       trv.getFlavor(), pathId)

        # toRestore is the list of what is going to be restored. We need to get
        # the fileObjects which will be created so we can track them in the
        # filesystem job. This lets the filesystem job look for resolveable
        # conflicts within this update. We handle newly created files first
        # and files which have changed (so we have to look up the diff)
        # a bit later.
        for fileInfo, fileObj in toRestore:
            fullPath = util.joinPaths(self.root, path)
            self.fsJob._restore(fileObj,
                                fullPath,
                                trvInfo,
                                "restoring %s from RPM",
                                restoreFile=False,
                                fileId=fileId)
Exemplo n.º 21
0
    def _addPhantomContents(self, changeSet, trv, header):
        """Fabricate files for the given RPM header"""
        for (path, owner, group, mode, size, rdev, flags, vflags, linkto,
             mtime) in itertools.izip(
                 header[rpmhelper.OLDFILENAMES],
                 header[rpmhelper.FILEUSERNAME],
                 header[rpmhelper.FILEGROUPNAME],
                 header[rpmhelper.FILEMODES],
                 header[rpmhelper.FILESIZES],
                 header[rpmhelper.FILERDEVS],
                 header[rpmhelper.FILEFLAGS],
                 header[rpmhelper.FILEVERIFYFLAGS],
                 header[rpmhelper.FILELINKTOS],
                 header[rpmhelper.FILEMTIMES],
             ):
            fullPath = util.joinPaths(self.root, path)
            fakestat = FakeStat(mode,
                                0,
                                None,
                                1,
                                owner,
                                group,
                                size,
                                mtime,
                                mtime,
                                mtime,
                                st_rdev=rdev,
                                linkto=linkto)
            pathId = os.urandom(16)

            # Adapted from conary.build.source.addCapsule.doRPM
            kind = 'regular'
            if flags & rpmhelper.RPMFILE_GHOST:
                kind = 'initial'
            elif flags & (rpmhelper.RPMFILE_CONFIG
                          | rpmhelper.RPMFILE_MISSINGOK
                          | rpmhelper.RPMFILE_NOREPLACE):
                if size:
                    kind = 'config'
                else:
                    kind = 'initial'
            elif vflags:
                if (stat.S_ISREG(mode)
                        and not (vflags & rpmhelper.RPMVERIFY_FILEDIGEST)
                        or (stat.S_ISLNK(mode)
                            and not (vflags & rpmhelper.RPMVERIFY_LINKTO))):
                    kind = 'initial'
            # Ignore failures trying to sha1 missing/inaccessible files as long
            # as those files are flagged initial contents (ghost)
            fileStream = files.FileFromFilesystem(fullPath,
                                                  pathId,
                                                  statBuf=fakestat,
                                                  sha1FailOk=True)
            if kind == 'config':
                fileStream.flags.isConfig(set=True)
            elif kind == 'initial':
                fileStream.flags.isInitialContents(set=True)
            else:
                assert kind == 'regular'

            # From conary.build.capsulepolicy.Payload
            if (isinstance(fileStream, files.RegularFile)
                    and not fileStream.flags.isConfig()
                    and not (fileStream.flags.isInitialContents()
                             and not fileStream.contents.size())):
                fileStream.flags.isEncapsulatedContent(set=True)

            fileId = fileStream.fileId()
            trv.addFile(pathId, path, trv.getVersion(), fileId)
            changeSet.addFile(None, fileId, fileStream.freeze())
            # Config file contents have to go into the database, so snag the
            # contents from the filesystem and put them in the changeset.
            if (fileStream.hasContents
                    and not fileStream.flags.isEncapsulatedContent()):
                if fileStream.contents.sha1() == sha1helper.sha1Empty:
                    # Missing/ghost config file. Hopefully it is supposed to be
                    # empty, but even if not then the fake SHA-1 will be the
                    # SHA-1 of the empty string since there's no hint of what
                    # it was supposed to be.
                    contents = filecontents.FromString('')
                else:
                    contents = filecontents.FromFilesystem(fullPath)
                changeSet.addFileContents(
                    pathId,
                    fileId,
                    contType=changeset.ChangedFileTypes.file,
                    contents=contents,
                    cfgFile=fileStream.flags.isConfig(),
                )
Exemplo n.º 22
0
    def testRemoval(self):
        threshold = 60 * 5
        # 5 minutes

        def _dbStatus(db):
            stat = {}
            cu = db.cursor()

            for table in db.tables:
                cu.execute("SELECT * FROM %s" % table)
                l = cu.fetchall()
                # throw away anything which looks a timestamp; this will
                # break if the test case takes more than 5 minutes to run
                stat[table] = set()
                for row in l:
                    thisRow = []
                    for item in row:
                        if not isinstance(item, (float, decimal.Decimal)) or \
                                    abs(item - now) > threshold:
                            thisRow.append(item)

                    stat[table].add(tuple(thisRow))

            return stat

        def _checkStateDiff(one, two):
            if one != two:
                assert (one.keys() == two.keys())
                for key in one:
                    if one[key] != two[key]:
                        print "table %s has changed" % key
                raise AssertionError, "\n%s\n!=\n%s" % (one, two)

        store = self._connect()

        # get the current timestamp from the database
        cu = store.db.cursor()
        cu.execute('''create table timestamp(
                      foo     INTEGER,
                      changed NUMERIC(14,0) NOT NULL DEFAULT 0)''')
        store.db.loadSchema()
        store.db.createTrigger('timestamp', 'changed', "INSERT")
        cu.execute('insert into timestamp values(0, 0)')
        cu.execute('select changed from timestamp')
        now = cu.fetchall()[0][0]

        emptyState = _dbStatus(store.db)

        v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10")
        v20 = ThawVersion("/conary.rpath.com@test:trunk/20:1.2-20")
        vB = ThawVersion("/conary.rpath.com@test:branch/1:0-0")
        vOtherRepo = ThawVersion("/other.repos.com@some:label/1:0-0")
        branch = v10.branch()

        flavor = deps.parseFlavor('is:x86')
        flavor64 = deps.parseFlavor('is:x86_64')

        store.createTroveBranch("trv:comp", branch)

        f1 = files.FileFromFilesystem("/etc/passwd", self.id1)
        f2 = files.FileFromFilesystem("/etc/services", self.id2)
        # add a file that has no contents sha1
        try:
            d = tempfile.mkdtemp()
            os.symlink('foo', d + '/foo')
            f5 = files.FileFromFilesystem(d + '/foo', self.id5)
        finally:
            shutil.rmtree(d)

        req = deps.parseDep("file: /bin/bash file: /bin/awk")

        dirNames = set(['/bin', ''])
        baseNames = set(['1', '2', 'distributed', 'foo', 'group-foo.recipe'])

        cl = changelog.ChangeLog("test", "*****@*****.**", "changelog\n")

        trv = trove.Trove('trv:comp', v10, flavor, cl)
        trv.addFile(f1.pathId(), "/bin/1", v10, f1.fileId())
        trv.addFile(f2.pathId(), "/bin/2", v10, f2.fileId())
        trv.addFile(self.id4, "/bin/distributed", v10, self.fid4)
        trv.addFile(f5.pathId(), "/bin/foo", v10, f5.fileId())
        trv.troveInfo.size.set(1234)
        trv.setRequires(req)

        store.db.transaction()
        store.addTroveSetStart([], dirNames, baseNames)
        troveInfo = store.addTrove(trv, trv.diff(None)[0])
        troveInfo.addFile(f1.pathId(),
                          "/bin/1",
                          f1.fileId(),
                          v10,
                          fileStream=f1.freeze())
        troveInfo.addFile(f2.pathId(),
                          "/bin/2",
                          f2.fileId(),
                          v10,
                          fileStream=f2.freeze())
        troveInfo.addFile(f5.pathId(),
                          "/bin/foo",
                          f5.fileId(),
                          v10,
                          fileStream=f5.freeze())
        store.addTroveDone(troveInfo)
        store.addTroveSetDone()
        store.db.commit()
        oneTroveState = _dbStatus(store.db)

        rc = store._removeTrove("trv:comp", v10, flavor)
        self.assertEqual(set(rc), set([f1.contents.sha1(),
                                       f2.contents.sha1()]))
        state = _dbStatus(store.db)
        _checkStateDiff(state, emptyState)
        store.db.rollback()

        # the redir itself doesn't overlap with trv:comp; this makes sure
        # that the tables which the redir target needs are preserved
        redir = trove.Trove('redir:comp',
                            vB,
                            flavor64,
                            cl,
                            type=trove.TROVE_TYPE_REDIRECT)
        redir.addRedirect('trv:comp', v10.branch(), flavor)
        store.addTroveSetStart([], dirNames, baseNames)
        troveInfo = store.addTrove(redir, redir.diff(None)[0])
        store.addTroveDone(troveInfo)
        store.addTroveSetDone()
        rc = store._removeTrove("trv:comp", v10, flavor)
        redir2 = store.getTrove('redir:comp', vB, flavor64)
        assert (redir == redir2)
        rc = store._removeTrove("redir:comp", vB, flavor64)
        state = _dbStatus(store.db)
        _checkStateDiff(state, emptyState)

        store.db.rollback()

        trv2 = trv.copy()
        trv2.changeVersion(v20)

        store.db.transaction()
        store.addTroveSetStart([], dirNames, baseNames)
        troveInfo = store.addTrove(trv2, trv2.diff(None)[0])
        troveInfo.addFile(f1.pathId(),
                          "/bin/1",
                          f1.fileId(),
                          v10,
                          fileStream=f1.freeze())
        troveInfo.addFile(f2.pathId(),
                          "/bin/2",
                          f2.fileId(),
                          v10,
                          fileStream=f2.freeze())
        store.addTroveDone(troveInfo)
        store.addTroveSetDone()
        store.db.commit()
        twoTroveState = _dbStatus(store.db)

        rc = store._removeTrove("trv:comp", v20, flavor)
        assert (not rc)
        state = _dbStatus(store.db)
        _checkStateDiff(state, oneTroveState)
        rc = store._removeTrove("trv:comp", v10, flavor)
        assert (set(rc) == set([f1.contents.sha1(), f2.contents.sha1()]))
        state = _dbStatus(store.db)
        _checkStateDiff(state, emptyState)

        store.db.rollback()

        # add a trove which shares a file with trv:comp and make sure removing
        # it doesn't remove the sha1s (make sure the fileIds are different)
        anotherTrove = trove.Trove('another:comp', v10, flavor, cl)
        anotherF = f1.copy()
        anotherF.inode.owner.set('unowned')
        anotherTrove.addFile(f1.pathId(), "/bin/1", v10, anotherF.fileId())
        store.addTroveSetStart([], dirNames, baseNames)
        troveInfo = store.addTrove(anotherTrove, anotherTrove.diff(None)[0])
        troveInfo.addFile(f1.pathId(),
                          "/bin/1",
                          anotherF.fileId(),
                          v10,
                          fileStream=f1.freeze())
        store.addTroveDone(troveInfo)
        rc = store._removeTrove("another:comp", v10, flavor)
        assert (not rc)
        state = _dbStatus(store.db)
        _checkStateDiff(state, twoTroveState)

        store.db.rollback()

        # now try just marking something as removed
        rc = store.markTroveRemoved("trv:comp", v20, flavor)
        assert (not rc)
        removedTrove = store.getTrove("trv:comp", v20, flavor)
        assert (removedTrove.type() == trove.TROVE_TYPE_REMOVED)

        rc = store.markTroveRemoved("trv:comp", v10, flavor)
        assert (set(rc) == set([f1.contents.sha1(), f2.contents.sha1()]))
        removedTrove = store.getTrove("trv:comp", v10, flavor)
        assert (removedTrove.type() == trove.TROVE_TYPE_REMOVED)

        store.db.rollback()

        # test removing group-*:source
        anotherTrove = trove.Trove('group-foo:source', v10, flavor, cl)
        anotherF = f1.copy()
        anotherF.inode.owner.set('unowned')
        anotherTrove.addFile(f1.pathId(), "group-foo.recipe", v10,
                             anotherF.fileId())
        troveInfo = store.addTrove(anotherTrove, anotherTrove.diff(None)[0])
        troveInfo.addFile(f1.pathId(),
                          "group-foo.recipe",
                          anotherF.fileId(),
                          v10,
                          fileStream=anotherF.freeze())
        store.addTroveDone(troveInfo)
        rc = store._removeTrove("group-foo:source", v10, flavor)
        assert (not rc)
        state = _dbStatus(store.db)
        _checkStateDiff(state, twoTroveState)

        store.db.rollback()

        groupTrove = trove.Trove('group-foo', v10, flavor, cl)
        groupTrove.addTrove('foo', vOtherRepo, flavor)
        troveInfo = store.addTrove(groupTrove, groupTrove.diff(None)[0])
        store.addTroveDone(troveInfo)
        rc = store._removeTrove("group-foo", v10, flavor)
        state = _dbStatus(store.db)
        _checkStateDiff(state, twoTroveState)
        store.db.rollback()
Exemplo n.º 23
0
    def testTroves(self, flavor=None):
        if flavor is None:
            flavor = deps.Flavor()

        store = self._connect()

        dirSet = set(['/etc', '/bin'])
        baseSet = set(
            ['passwd', 'services', 'group', '1', '2', '3', 'distributed'])

        v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10")

        branch = v10.branch()
        store.createTroveBranch("testtrove", branch)

        f1 = files.FileFromFilesystem("/etc/passwd", self.id1)
        f2 = files.FileFromFilesystem("/etc/services", self.id2)
        f3 = files.FileFromFilesystem("/etc/group", self.id3)
        # make a really huge dependency, thus a very large file stream
        req = deps.DependencySet()
        for x in xrange(10000):
            req.addDep(deps.SonameDependencies,
                       deps.Dependency("libtest.so.%d" % x))
        f3.requires.set(req)
        # make sure it's way too big for a blob in mysql
        assert (len(f3.freeze()) >= 50000)

        cl = changelog.ChangeLog(
            "test", "*****@*****.**", """\
Some changes are good.
Some changes are bad.
Some changes just are.
""")

        trv = trove.Trove('testcomp', v10, flavor, cl)
        trv.addFile(f1.pathId(), "/bin/1", v10, f1.fileId())
        trv.addFile(f2.pathId(), "/bin/2", v10, f2.fileId())
        trv.addFile(f3.pathId(), "/bin/3", v10, f3.fileId())
        trv.addFile(self.id4, "/bin/distributed", v10, self.fid4)
        trv.troveInfo.size.set(1234)
        trv.troveInfo.sourceName.set('somesource')

        req = deps.DependencySet()
        req.addDep(deps.FileDependencies, deps.Dependency("/bin/bash"))
        req.addDep(deps.TroveDependencies, deps.Dependency("foo:runtime"))
        req.addDep(deps.SonameDependencies, deps.Dependency("libtest.so.1"))
        trv.setRequires(req)

        # this also lets us peek at the database to make sure libtest.so.1
        # is only in the dep table once
        prv = deps.DependencySet()
        prv.addDep(deps.SonameDependencies, deps.Dependency("libtest.so.1"))
        trv.setProvides(prv)
        trv.computeDigests()

        store.db.transaction()
        store.addTroveSetStart([], dirSet, baseSet)
        troveInfo = store.addTrove(trv, trv.diff(None)[0])
        troveInfo.addFile(f1.pathId(),
                          "/bin/1",
                          f1.fileId(),
                          v10,
                          fileStream=f1.freeze())
        troveInfo.addFile(f2.pathId(),
                          "/bin/2",
                          f2.fileId(),
                          v10,
                          fileStream=f2.freeze())
        troveInfo.addFile(f3.pathId(),
                          "/bin/3",
                          f3.fileId(),
                          v10,
                          fileStream=f3.freeze())
        troveInfo.addFile(self.id4, "/bin/distributed", self.fid4, v10)
        store.addTroveDone(troveInfo)
        store.addTroveSetDone()
        store.db.commit()

        cu = store.db.cursor()
        cu.execute("SELECT count(*) FROM Dependencies WHERE "
                   "name = 'libtest.so.1'")
        self.assertEqual(cu.next(), (1, ))

        # make sure the sha1s were stored
        cu.execute("""
        SELECT dirname, basename, sha1
        FROM TroveFiles
        JOIN FileStreams USING (streamId)
        JOIN FilePaths ON TroveFiles.filePathId = FilePaths.filePathId
        JOIN Dirnames ON FilePaths.dirnameId = Dirnames.dirnameId
        JOIN Basenames ON FilePaths.basenameId = Basenames.basenameId
        ORDER BY dirname,basename""")
        items = [(os.path.join(cu.frombinary(x[0]),
                               cu.frombinary(x[1])), cu.frombinary(x[2]))
                 for x in cu.fetchall()]
        self.assertEqual(items, [("/bin/1", f1.contents.sha1()),
                                 ("/bin/2", f2.contents.sha1()),
                                 ("/bin/3", f3.contents.sha1()),
                                 ("/bin/distributed", None)])

        cl = changelog.ChangeLog("test", "*****@*****.**", "another log\n")

        fromRepos = store.getTrove("testcomp", v10, flavor, cl)
        self.assertEqual(fromRepos, trv)
        self.assertEqual(fromRepos.getVersion().timeStamps(),
                         trv.getVersion().timeStamps())
        self.assertEqual(fromRepos.getChangeLog(), trv.getChangeLog())

        self.assertEqual([
            x for x in store.getTrove("testcomp", v10, flavor,
                                      withFiles=False).iterFileList()
        ], [])

        l = store.iterFilesInTrove("testcomp", v10, flavor, sortByPath=True)
        l = [x for x in l]
        self.assertEqual(l, [(f1.pathId(), "/bin/1", f1.fileId(), v10),
                             (f2.pathId(), "/bin/2", f2.fileId(), v10),
                             (f3.pathId(), "/bin/3", f3.fileId(), v10),
                             (self.id4, "/bin/distributed", self.fid4, v10)])

        cl = changelog.ChangeLog("test", "*****@*****.**", "log for testpkg\n")
        trv2 = trove.Trove("testpkg", v10, flavor, cl)
        trv2.addTrove(trv.getName(), v10, flavor)
        trv2.addTrove("weakref", v10, flavor, weakRef=True)
        trv2.computeDigests()
        store.addTroveSetStart([], dirSet, baseSet)
        troveInfo = store.addTrove(trv2, trv2.diff(None)[0])
        store.addTroveDone(troveInfo)
        store.addTroveSetDone()
        self.assertEqual(store.getTrove("testpkg", v10, flavor), trv2)

        self.assertEqual([
            x for x in store.iterTroves([("testcomp", v10,
                                          flavor), ("testpkg", v10, flavor)])
        ], [trv, trv2])
        self.assertEqual([
            x for x in store.iterTroves([("testpkg", v10,
                                          flavor), ("testcomp", v10, flavor)])
        ], [trv2, trv])
        self.assertEqual([
            x for x in store.iterTroves([("testpkg", v10,
                                          flavor), ("testpkg", v10, flavor)])
        ], [trv2, trv2])
        self.assertEqual([
            x for x in store.iterTroves([("testpkg", v10,
                                          flavor), ("blah", v10, flavor)])
        ], [trv2, None])
        self.assertEqual([
            x for x in store.iterTroves([("blah", v10,
                                          flavor), ("testpkg", v10, flavor)])
        ], [None, trv2])
        self.assertEqual(
            [x for x in store.iterTroves([("blah", v10, flavor)])], [None])
        self.assertEqual([
            x for x in store.iterTroves([(
                "testcomp", v10, flavor), ("blah", v10,
                                           flavor), ("testpkg", v10, flavor)])
        ], [trv, None, trv2])

        # erasing doesn't work
        #store.eraseTrove("testcomp", v10, None)
        #store.commit()
        self.assertEqual(store.getTrove("testpkg", v10, flavor), trv2)

        map = {'testpkg': [v10]}
        flavors = store.getTroveFlavors(map)
        if flavor is not None:
            flavorStr = flavor.freeze()
        else:
            flavorStr = ''
        self.assertEqual(flavors, {'testpkg': {v10: [flavorStr]}})

        map = {'testpkg3': [v10]}
        flavors = store.getTroveFlavors(map)
        self.assertEqual(flavors, {'testpkg3': {v10: []}})

        # test getFiles
        fileObjs = store.getFiles([(f1.pathId(), f1.fileId()),
                                   (f2.pathId(), f2.fileId())])
        self.assertEqual(fileObjs[(f1.pathId(), f1.fileId())], f1)
        self.assertEqual(fileObjs[(f2.pathId(), f2.fileId())], f2)

        # test that asking for an invalid fileid/pathid pair results
        # in no entry for the (pathid, fileid) in the returned dict
        invalidPathId = md5FromString('9' * 32)
        invalidFileId = sha1FromString('9' * 40)
        fileObjs = store.getFiles([(invalidPathId, invalidFileId)])
        # make sure fileObjs is empty
        assert (not fileObjs)

        # test that asking for contents that have to come from
        # a different repository works - we should get None
        # back
        fileObjs = store.getFiles([(self.id4, self.fid4)])
        self.assertEqual(fileObjs, {(self.id4, self.fid4): None})
Exemplo n.º 24
0
    def testDatabase1(self):
        db = sqldb.Database(':memory:')

        f1 = files.FileFromFilesystem("/etc/passwd", self.id1)
        f2 = files.FileFromFilesystem("/etc/services", self.id2)
        f3 = files.FileFromFilesystem("/etc/group", self.id3)

        trv = trove.Trove("testcomp", self.v10, self.emptyFlavor, None)
        trv.addFile(self.id1, "/bin/1", self.v10, f1.fileId())
        trv.addFile(self.id2, "/bin/2", self.v10, f2.fileId())
        trv.addFile(self.id3, "/bin/3", self.v10, f3.fileId())
        trv.troveInfo.size.set(1234)
        trv.troveInfo.sourceName.set('thesource')

        req = deps.DependencySet()
        req.addDep(deps.FileDependencies, deps.Dependency("/bin/bash"))
        req.addDep(deps.TroveDependencies, deps.Dependency("foo:runtime"))
        req.addDep(deps.SonameDependencies, deps.Dependency("libtest.so.1"))
        trv.setRequires(req)

        trvInfo = db.addTrove(trv)

        db.addFile(trvInfo,
                   f1.pathId(),
                   "/bin/1",
                   f1.fileId(),
                   self.v10,
                   fileStream=f1.freeze())
        db.addFile(trvInfo,
                   f2.pathId(),
                   "/bin/2",
                   f2.fileId(),
                   self.v10,
                   fileStream=f2.freeze())
        db.addFile(trvInfo,
                   f3.pathId(),
                   "/bin/3",
                   f3.fileId(),
                   self.v10,
                   fileStream=f3.freeze())

        db.addTroveDone(trvInfo)

        dbTrv = db.getTroves([("testcomp", self.v10, self.emptyFlavor)])[0]
        assert (dbTrv == trv)
        assert (dbTrv.__class__ == trove.Trove)
        assert (db.trovesArePinned([("testcomp", self.v10, self.emptyFlavor)
                                    ]) == [False])
        dbTrv = db.getTroves([("testcomp", self.v10, self.emptyFlavor)],
                             withFileObjects=True)[0]
        assert (dbTrv == trv)
        assert (dbTrv.__class__ == trove.TroveWithFileObjects)
        for f in (f1, f2, f3):
            assert (dbTrv.getFileObject(f.fileId()) == f)

        trv2 = trove.Trove("testpkg", self.v10, self.emptyFlavor, None)
        ti = trv2.addTrove(trv.getName(), self.v10, trv.getFlavor())
        trv2.addTrove("weakref", self.v10, trv.getFlavor(), weakRef=True)
        ti = db.addTrove(trv2, pin=True)
        db.addTroveDone(ti)
        assert (db.trovesArePinned([("testpkg", self.v10, self.emptyFlavor)
                                    ]) == [True])
        assert (db.getTroves([("testpkg", self.v10, self.emptyFlavor)
                              ])[0] == trv2)
        assert (db.getTroves([
            ("testpkg", self.v10, self.emptyFlavor)
        ])[0].getVersion().timeStamps() == trv2.getVersion().timeStamps())

        assert (db.getTroves([("testpkg", self.v10, self.emptyFlavor),
                              ("testcomp", self.v10, self.emptyFlavor),
                              ("testitem", self.v10, self.emptyFlavor)],
                             True) == [trv2, trv, None])

        assert (db.getTroves([("testpkg", self.v10, self.emptyFlavor),
                              ("testcomp", self.v10, req)],
                             True) == [trv2, None])

        assert (db.findTroveContainers(["testpkg",
                                        "testcomp"]) == [[],
                                                         [("testpkg", self.v10,
                                                           self.emptyFlavor)]])

        assert (db.getTroveContainers([
            ("testpkg", self.v10, self.emptyFlavor),
            ("testcomp", self.v10, self.emptyFlavor)
        ]) == [[], [("testpkg", self.v10, self.emptyFlavor)]])

        res = db.findTroveReferences(["testpkg", "testcomp"])

        assert (db.findTroveReferences(["testpkg", "testcomp"
                                        ]) == [[],
                                               [("testcomp", self.v10,
                                                 self.emptyFlavor)]])

        v10new = VersionFromString("/conary.rpath.com@test:trunk/1.2-10")
        assert (db.getTroves([("testpkg", v10new, self.emptyFlavor)
                              ])[0] == trv2)
        assert (db.getTroves([
            ("testpkg", v10new, self.emptyFlavor)
        ])[0].getVersion().timeStamps() == trv2.getVersion().timeStamps())

        assert (set(db.findByNames(['testpkg', 'testcomp'])) == set([
            ("testpkg", self.v10, self.emptyFlavor),
            ("testcomp", self.v10, self.emptyFlavor)
        ]))

        db.eraseTrove("testcomp", self.v10, None)
        assert (db.getTroves([("testpkg", self.v10, self.emptyFlavor)
                              ])[0] == trv2)

        trv.computePathHashes()
        trvInfo = db.addTrove(trv)
        db.addFile(trvInfo,
                   f1.pathId(),
                   "/bin/1",
                   f1.fileId(),
                   self.v10,
                   fileStream=f1.freeze())
        db.addFile(trvInfo,
                   f2.pathId(),
                   "/bin/2",
                   f2.fileId(),
                   self.v10,
                   fileStream=f1.freeze())
        db.addFile(trvInfo,
                   f3.pathId(),
                   "/bin/3",
                   f3.fileId(),
                   self.v10,
                   fileStream=f1.freeze())
        db.addTroveDone(trvInfo)

        assert (db.getTroves([("testcomp", self.v10, self.emptyFlavor)
                              ])[0] == trv)
        db.removeFileFromTrove(trv, "/bin/1")
        changedTrv = db.getTroves([trv.getNameVersionFlavor()],
                                  pristine=False)[0]
        otherChangedTrv = db.getTroves([trv.getNameVersionFlavor()],
                                       withFiles=False,
                                       pristine=False)[0]
        assert (len(changedTrv.idMap) + 1 == len(trv.idMap))
        assert (len(changedTrv.troveInfo.pathHashes) + 1 == len(
            trv.troveInfo.pathHashes))
        assert (changedTrv.troveInfo.pathHashes ==
                otherChangedTrv.troveInfo.pathHashes)
        assert (len(otherChangedTrv.idMap) == 0)
        changedTrv.addFile(self.id1, "/bin/1", self.v10, f1.fileId())
        assert (changedTrv.idMap == trv.idMap)
        changedTrv.computePathHashes()
        assert (changedTrv.troveInfo.pathHashes == trv.troveInfo.pathHashes)

        assert (db.getTroves([("testcomp", self.v10, self.emptyFlavor)],
                             pristine=True)[0] == trv)
        db.eraseTrove("testpkg", self.v10, None)
        assert (db.getTroves([("testpkg", self.v10, self.emptyFlavor)
                              ]) == [None])
        self.assertRaises(KeyError, db.instances.getVersion, 100)

        db.eraseTrove("testcomp", self.v10, None)
        db.commit()
        cu = db.db.cursor()

        # make sure the versions got removed; the None entry is still there
        cu.execute("SELECT count(*) FROM Versions")
        assert (cu.next()[0] == 1)

        # make sure the dependency table got cleaned up
        cu.execute("SELECT count(*) FROM Dependencies")
        assert (cu.next()[0] == 0)

        # make sure the instances table got cleaned up
        cu.execute("SELECT count(*) FROM Instances")
        assert (cu.next()[0] == 0)

        # make sure the troveInfo table got cleaned up
        cu.execute("SELECT count(*) FROM TroveInfo")
        assert (cu.next()[0] == 0)
Exemplo n.º 25
0
    def testDatabaseVersionCleanup(self):
        flavor1 = deps.parseFlavor('is:x86(cmov)')
        db = sqldb.Database(':memory:')
        cu = db.db.cursor()
        v10 = ThawVersion('/conary.rpath.com@test:trunk/10:1.2-10')
        v20 = ThawVersion('/conary.rpath.com@test:trunk/10:1.2-20')
        v30 = ThawVersion('/conary.rpath.com@test:trunk/10:1.2-30')

        # test file version cleanup
        trv = trove.Trove('testcomp:runtime', v10, flavor1, None)
        f1 = files.FileFromFilesystem('/etc/passwd', self.id1)
        f2 = files.FileFromFilesystem('/etc/services', self.id2)
        f3 = files.FileFromFilesystem('/etc/group', self.id3)
        trv.addFile(self.id1, '/bin/1', v10, f1.fileId())
        trv.addFile(self.id2, '/bin/2', v20, f2.fileId())
        trv.addFile(self.id3, '/bin/3', v30, f3.fileId())
        trvInfo = db.addTrove(trv)
        db.addFile(trvInfo,
                   f1.pathId(),
                   '/bin/1',
                   f1.fileId(),
                   v10,
                   fileStream=f1.freeze())
        db.addFile(trvInfo,
                   f2.pathId(),
                   '/bin/2',
                   f2.fileId(),
                   v20,
                   fileStream=f2.freeze())
        db.addFile(trvInfo,
                   f3.pathId(),
                   '/bin/3',
                   f3.fileId(),
                   v30,
                   fileStream=f3.freeze())
        db.addTroveDone(trvInfo)
        # check to see how many versions we have
        cu.execute('select count(*) from Versions')
        count = cu.fetchall()[0][0]
        # should have only 0|NULL
        self.assertEqual(count, 4)
        # now erase
        db.eraseTrove('testcomp:runtime', v10, flavor1)
        db.commit()
        cu.execute('select count(*) from Versions')
        count = cu.fetchall()[0][0]
        # should have only 0|NULL
        self.assertEqual(count, 1)

        # test trove version cleanup
        trv1 = trove.Trove('testcomp:runtime', v10, flavor1, None)
        trv2 = trove.Trove('group-test', v20, flavor1, None)
        trv2.addTrove(trv1.getName(),
                      trv1.getVersion(),
                      trv1.getFlavor(),
                      weakRef=True)
        trvInfo = db.addTrove(trv2)
        db.addTroveDone(trvInfo)
        db.commit()
        cu.execute('select count(*) from Versions')
        count = cu.fetchall()[0][0]
        self.assertEqual(count, 3)

        db.eraseTrove('group-test', v20, flavor1)
        db.commit()
        cu.execute('select count(*) from Versions')
        count = cu.fetchall()[0][0]
        # should have only 0|NULL
        self.assertEqual(count, 1)