def testNextVersionMultipleBranchesWithDepth2(self): self.addCollection('foo=/localhost@rpl:1//2//3/2:1-2-0.1', [':run']) repos = self.openRepository() sourceList = [(VFS('/localhost@rpl:2//3/1-2'), ['foo'], deps.Flavor())] nextVersions = nextversion.nextVersions(repos, self.openDatabase(), sourceList) assert(nextVersions == [VFS('/localhost@rpl:2//3/1-2-0.2')])
def testNextVersionLatestDevelOnThisBranch(self): # depth 3 self.addCollection('foo=/localhost@rpl:1//2//3/1:1-2-0.0.1', [':run']) # depth 2 and latest self.addCollection('foo=/localhost@rpl:1//3/2:1-2-0.1[is:x86]', [':run']) sourceList = [(VFS('/localhost@rpl:1//3/1-2'), ['foo'], deps.Flavor())] nextVersions = nextversion.nextVersions(self.openRepository(), self.openDatabase(), sourceList) assert(nextVersions == [VFS('/localhost@rpl:1//3/1-2-0.1')])
def testNextVersionMultipleBranchesWithDepth(self): # this has depth 3, but the trove we're building has depth 2. # so we can't consider it the "latest" and just increment its source # count. self.addCollection('foo=/localhost@rpl:1//2//3/2:1-2-0.0.1', [':run']) repos = self.openRepository() sourceList = [(VFS('/localhost@rpl:2//3/1-2'), ['foo'], deps.Flavor())] nextVersions = nextversion.nextVersions(repos, self.openDatabase(), sourceList) assert(nextVersions == [VFS('/localhost@rpl:2//3/1-2-0.1')])
def testNextVersions(self): trv = self.addComponent('foo:source', '1') self.addComponent('foo:run', '1') self.addCollection('foo', '1', [':run']) localVersion = VFS('/local@local:COOK/1.0-1') sourceList = [(trv.getVersion(), ['foo'], deps.Flavor()), (localVersion, ['bar'], deps.Flavor())] repos = self.openRepository() nextVersions = nextversion.nextVersions(repos, self.openDatabase(), sourceList) assert(nextVersions == [VFS('/localhost@rpl:linux/1-1-2'), VFS('/local@local:COOK/1.0-1-1')])
def testLoadInstalledInRoot(self): # make sure that we find this autoconf213 trove even though it's # been built. (RMK-371) self.openRepository() repos = self.openRmakeRepository() sourceV = VFS('/localhost@rpl:1//autoconf213/2.13-1.1') binV = sourceV.createShadow(versions.Label('rmakehost@rpl:1')) binV.incrementBuildCount() loadInstalledRecipe = fixtures.loadInstalledRecipe.replace( "loadInstalled('loaded')", "loadInstalled('loaded=:autoconf213')") self.addComponent('loaded:runtime', str(binV)) trv = self.addCollection('loaded', str(binV), [':runtime']) self.updatePkg('loaded=rmakehost@rpl:1') self.addComponent('loaded:source', str(sourceV), [('loaded.recipe', fixtures.loadedRecipe.replace('@@', '2.13'))]) trv = self.addComponent('loadinstalled:source', '1', [('loadinstalled.recipe', loadInstalledRecipe)]) n,v,f = trv.getNameVersionFlavor() db = self.openDatabase() source = recipeutil.RemoveHostSource(db, 'rmakehost') (loader, recipeClass, localFlags, usedFlags) = \ recipeutil.loadRecipeClass(repos, n, v, f, ignoreInstalled=False, root=self.cfg.root, loadInstalledSource=source) assert(recipeClass.loadedVersion == '2.13')
def testAffinity(self): self.addComponent('foo:r', '/localhost@rpl:branch/1.0-1-1', '!readline', ['/usr/bin/foo']) self.addComponent('foo:r', '/localhost@rpl:branch/2.0-1-1', 'readline,~!ssl', ['/usr/bin/foo']) self.addComponent('foo:r', '/localhost@rpl:branch/2.0-1-1', 'readline,~ssl', ['/usr/bin/foo']) self.addComponent('foo:r', '/localhost@rpl:branch/2.0-1-1', '!readline,~ssl', ['/usr/bin/foo']) self.addComponent('foo:r', '/localhost@rpl:branch/2.0-1-1', '!readline,~!ssl', ['/usr/bin/foo']) # orig branch - found by very few queries self.addComponent('foo:r', '/localhost@rpl:linux/1.0-1-1', 'readline') self.updatePkg('foo:r=:branch/1.0[!readline]') repos = self.openRepository() def _get(affinityDb, versionFilter, flavorFilter, troveSpec): return queryrep.getTrovesToDisplay(repos, troveSpec, [], [], versionFilter, flavorFilter, self.cfg.installLabelPath, self.cfg.flavor, affinityDb) db = self.openDatabase() troveTups = _get(db, VERSION_FILTER_LATEST, FLAVOR_FILTER_BEST, ['foo:r']) assert (len(troveTups) == 1) assert (troveTups[0][1].branch() == VFS('/localhost@rpl:branch')) assert (str(troveTups[0][2]) == '!readline,~ssl') troveTups = _get(db, VERSION_FILTER_LATEST, FLAVOR_FILTER_AVAIL, ['foo:r']) assert (len(troveTups) == 2) flavors = set(str(x[2]) for x in troveTups) assert ('readline,~ssl' in flavors) assert ('!readline,~ssl' in flavors) # system compatible, should ignore db troveTups = _get(None, VERSION_FILTER_LATEST, FLAVOR_FILTER_AVAIL, ['foo:r']) assert (len(troveTups) == 1) assert (troveTups[0][1].branch() == VFS('/localhost@rpl:linux')) flavors = set(str(x[2]) for x in troveTups) assert ('readline' in flavors)
def testShadowBinaryGroup(self): basicSplitGroup = """ class splitGroup(GroupRecipe): name = 'group-first' version = '1.0' checkPathConflicts = False clearBuildRequires() def setup(self): self.addTrove("testcase", ":linux", byDefault=False) self.createGroup('group-second') self.addTrove("testcase", ":test1", groupName = 'group-second') # add group-second to group-first self.addNewGroup('group-second') """ repos = self.openRepository() (built, d) = self.buildRecipe(recipes.testRecipe1, "TestRecipe1") origBuildLabel = self.cfg.buildLabel self.cfg.buildLabel = Label('localhost@rpl:test1') (built, d) = self.buildRecipe(recipes.testRecipe1, "TestRecipe1") self.cfg.buildLabel = origBuildLabel (built, d) = self.buildRecipe(basicSplitGroup, "splitGroup") n, v, f = [x for x in built if x[0] == 'group-first'][0] v = VFS(v) shadowVerStr = '/localhost@rpl:linux//shadow/1.0-1-1' shadowVer = VFS(shadowVerStr) flavor = use.Arch.getCurrentArch()._toDependency() group = repos.getTrove(n, v, f) self.verifyTroves( group, [('testcase', '/localhost@rpl:linux/1.0-1-1', flavor), ('group-second', '/localhost@rpl:linux/1.0-1-1', flavor)]) self.mkbranch("1.0-1-1", 'localhost@rpl:shadow', "group-first", shadow=True, binaryOnly=True) group = repos.getTrove('group-first', shadowVer, flavor) assert (not group.includeTroveByDefault('testcase', shadowVer, flavor)) self.verifyTroves(group, [('testcase', shadowVerStr, flavor), ('group-second', shadowVerStr, flavor)]) group = repos.getTrove('group-second', shadowVer, flavor) self.verifyTroves( group, [('testcase', '/localhost@rpl:test1//shadow/1.0-1-1', flavor)])
def testLoadRecipeUsingInternalRepos(self): self.openRepository() repos = self.openRmakeRepository() upstreamV = VFS('/localhost@rpl:1/1.0-1') sourceV = VFS('/localhost@rpl:1//rmakehost@rpl:1/1.0-1') self.addComponent('loaded:source', str(sourceV), [('loaded.recipe', fixtures.loadedRecipe.replace('@@', '1.0'))]) self.addComponent('loaded:source', str(upstreamV).replace('1.0', '2.0'), [('loaded.recipe', fixtures.loadedRecipe.replace('@@', '2.0'))]) trv = self.addComponent('load:source', str(sourceV), [('load.recipe', fixtures.loadRecipe)]) job = self.newJob(trv) results = recipeutil.getSourceTrovesFromJob(job, repos=repos) self.assertEqual(results.values()[0].packages, set(['load', 'loaded-2.0']))
def testChecksumMissingError(self): try: raise errors.TroveChecksumMissing('foo', VFS('/localhost@rpl:1/1.0-1-1'), deps.parseFlavor('~!foo')) except Exception, err: assert ( str(err) == 'Checksum Missing Error: Trove foo=/localhost@rpl:1/1.0-1-1[~!foo] has no sha1 checksum calculated, so it was rejected. Please upgrade conary.' )
def testIntegrityError(self): try: raise errors.TroveIntegrityError('foo', VFS('/localhost@rpl:1/1.0-1-1'), deps.parseFlavor('~!foo')) except Exception, err: assert ( str(err) == 'Trove Integrity Error: foo=/localhost@rpl:1/1.0-1-1[~!foo] checksum does not match precalculated value' )
def testTroveSchemaError(self): try: raise errors.TroveSchemaError('foo', VFS('/localhost@rpl:1/1.0-1-1'), deps.parseFlavor('~!foo'), 10, 5) except Exception, err: assert ( str(err) == 'Trove Schema Error: attempted to commit foo=/localhost@rpl:1/1.0-1-1[~!foo] with version 10, but repository only supports 5' )
def testJobTupFormatter(self): # CNY-1742 repos = self.openRepository() db = self.openDatabase() dcfg = display.JobDisplayConfig(repos, db) formatter = display.JobTupFormatter(dcfg) v1 = VFS('/localhost@rpl:devel/1.0-1-1') v2 = VFS('/localhost@rpl:devel/1.0-1-2') f = Flavor('') jobs = [('foo', (None, None), (v1, f), False), ('foo', (None, None), (v2, f), False)] formatter.prepareJobs(jobs) result = ''.join(x for x in formatter.formatJobTups(jobs)) self.assertEqual(result, 'Install foo=1.0-1-1Install foo=1.0-1-2') formatter = display.JobFormatter(dcfg) (rc, txt) = self.captureOutput(display.displayJobs, dcfg, formatter, jobs) self.assertEqual(txt, 'Install foo=1.0-1-1\nInstall foo=1.0-1-2\n')
def testGetProductStoreByLabel(self): from rbuild_plugins import init co = init.Init('init', None, None) co.setHandle(mock.MockObject()) returnTuple = ('product-definition:source', VFS('/foo.rpath.org@rpl:proddef-1/1.0-1'), deps.Flavor()) co.handle.facade.conary._findTrove._mock.setReturn(returnTuple, 'product-definition:source', 'foo.rpath.org@rpl:proddef-1') assert(co.getProductVersionByLabel('foo.rpath.org@rpl:proddef-1') == '/foo.rpath.org@rpl:proddef-1/1.0-1')
def testPromoteGroups(self): _, facade = self.prep() client = mock.MockObject() mock.mockMethod(facade._getConaryClient, client) success = True cs = mock.MockObject() groupList = [('group-dist', '/localhost@rpl:devel/1.0-1-1', '')], trv = mock.MockObject() trv.getNewNameVersionFlavor._mock.setReturn( ('group-dist', VFS('/localhost@rpl:qa/1.0-1-1'), '')) cs.iterNewTroveList()._mock.setList([trv]) client.createSiblingCloneChangeSet._mock.setReturn( (success, cs), { Label('localhost@rpl:devel'): Label('localhost@rpl:qa'), Label('other@somewhere:else'): Label('localhost@rpl:qa'), Label('yetanother@somewhere:else'): VFS('/localhost@rpl:qa') }, groupList, cloneSources=True) mock.mockMethod(facade._getRepositoryClient) repos = facade._getRepositoryClient() rc = facade.promoteGroups( groupList, { 'localhost@rpl:devel': 'localhost@rpl:qa', 'other@somewhere:else': facade._getLabel('localhost@rpl:qa'), 'yetanother@somewhere:else': '/localhost@rpl:qa' }) # RBLD-91 assert (rc == [('group-dist', '/localhost@rpl:qa/1.0-1-1', '')]) repos.commitChangeSet._mock.assertCalled(cs) # failureCase success = False client.createSiblingCloneChangeSet._mock.setReturn( (success, None), {Label('localhost@rpl:devel'): Label('localhost@rpl:qa')}, groupList, cloneSources=True) err = self.assertRaises(errors.RbuildError, facade.promoteGroups, groupList, {'localhost@rpl:devel': 'localhost@rpl:qa'}) assert (str(err) == 'Promote failed.')
def testFindTroves(self): _, facade = self.prep() repos = MockRepositoryClient() mock.mockMethod(facade._getRepositoryClient, repos) results = facade._findTroves([('foo', None, None)], ['localhost@rpl:1', 'localhost@rpl:2']) assert (results == { ('foo', None, None): [('foo', VFS('/localhost@rpl:1/1.0-1-1'), Flavor(''))] }) results = facade._findTrovesFlattened( [('foo', None, None)], ['localhost@rpl:1', 'localhost@rpl:2']) assert (results == [('foo', VFS('/localhost@rpl:1/1.0-1-1'), Flavor(''))]) results = facade._findTroves(['foo[ssl]'], 'localhost@rpl:1') assert (results == { ('foo[ssl]'): [('foo', VFS('/localhost@rpl:1/1.0-1-1'), Flavor('ssl'))] }) results = facade._findTrovesFlattened(['foo[ssl]'], 'localhost@rpl:1') assert (results == [('foo', VFS('/localhost@rpl:1/1.0-1-1'), Flavor('ssl'))])
def _checkLatest(self, trove, verType, ver): repos = self.openRepository() if verType[0] == '/': verDict = repos.getTroveLeavesByBranch( {trove: { VFS(verType): None }}) else: verDict = repos.getTroveLeavesByLabel( {trove: { Label(verType): None }}) assert (len(verDict) == 1) assert (verDict[trove].keys()[0].asString() == ver)
def testFindTroves(self): self.repos = self.openRepository() self.setUpGroupOddities() ts = TroveListTroveSource( self.repos, [('group-foo', VFS('/localhost@rpl:linux/1.0-1-1'), deps.parseFlavor('readline is: x86_64'))]) assert (len(ts.trovesByName('test4-on-branch')) == 1) assert (len(ts.trovesByName('test4-on-branch:runtime')) == 1) assert (len(ts.findTrove(None, ('test4-on-branch', None, None))) == 1) ts.searchAsDatabase() assert (len( ts.findTrove( None, ('test4-on-branch', '/localhost@rpl:branch1', None))) == 1)
def testFlavorDisplayed(self): repos = self.openRepository() db = self.openDatabase() foobar = Flavor('~foo,~bar') nofoobar = Flavor('~!foo,~!bar') v1 = VFS('/localhost@rpl:devel/1.0-1-1') dcfg = display.DisplayConfig(repos, db) dcfg.setTroveDisplay(baseFlavors=[Flavor('~foo')]) formatter = display.TroveTupFormatter(dcfg) formatter.prepareTuples([('foo', v1, foobar), ('foo', v1, nofoobar)]) vStr, flv = formatter.getTupleStrings('foo', v1, foobar) assert (str(flv) == '~bar,~foo') vStr, flv = formatter.getTupleStrings('foo', v1, nofoobar) assert (str(flv) == '~!bar,~!foo')
def testPathIdLookupPermissions(self): # CNY-1911 label2 = Label('localhost2@rpl:devel') label1 = Label('localhost1@rpl:devel') shadowLabel = Label('localhost@rpl:shadow') self.openRepository(0) self.openRepository(1) # Remove anonymous user repos = self.openRepository(2) repos.deleteUserByName(label2.asString(), "anonymous") # Add a file that disappears recipe1 = simpleRecipe + " r.Create('/usr/blip', contents='abc\\n')\n" self.makeSourceTrove('test', recipe1, buildLabel=label2) built = self.cookFromRepository('test', buildLabel=label2) # Extra file goes away self.updateSourceTrove('test', simpleRecipe, versionStr=label2.asString()) built = self.cookFromRepository('test', buildLabel=label2) self.assertEqual(built[0][1], '/localhost2@rpl:devel/1.0-2-1') # Now shadow self.mkbranch(['test:source=' + label2.asString()], label1, shadow=True) # Noop change newRecipe = simpleRecipe.replace("mode=0755", "contents='foobar\\n', mode=0755") self.updateSourceTrove('test', newRecipe, versionStr=label1.asString()) # And build in the repo built = self.cookFromRepository('test', buildLabel=label1) self.assertEqual( built[0][1], '/localhost2@rpl:devel//localhost1@rpl:devel/1.0-2.1-1') # Now shadow again self.mkbranch(['test:source=' + label1.asString()], shadowLabel, shadow=True) # Add the original file back self.updateSourceTrove('test', recipe1, versionStr=shadowLabel.asString()) # Reset users, client-side self.cfg.user.addServerGlob('localhost2', ('test', 'wrongpass')) client = conaryclient.ConaryClient(self.cfg) repos = client.getRepos() # And build in the repo built = self.cookFromRepository('test', buildLabel=shadowLabel, repos=repos) self.assertEqual( built[0][1], '/localhost2@rpl:devel//localhost1@rpl:devel//localhost@rpl:shadow/1.0-2.1.1-1' ) trvList = repos.getTroves([(x[0], VFS(x[1]), x[2]) for x in built]) trv = trvList[0] # Iterate over all files for _, _, _, vr in trv.iterFileList(): # Make sure the file version is the same as the trove version. If # the originating repo didn't reject the request (and the client # didn't ignore the reject), then we'd see the file version be on # the /localhost2 branch. self.assertEqual(vr.asString(), built[0][1])
assert ( str(err) == 'Trove Schema Error: attempted to commit foo=/localhost@rpl:1/1.0-1-1[~!foo] with version 100000, but repository only supports %s' % trove.TROVE_VERSION) else: assert (0) t.troveInfo.troveVersion.set(trove.TROVE_VERSION) t.computeDigests() cs = changeset.ChangeSet() cs.newTrove(t.diff(None)[0]) # let's make sure that there are no other problems with this # changeset repos.commitChangeSet(cs) # access the server with a bad name repos.c.map['badserver'] = repos.c.map.values()[0] try: repos.createChangeSet([('foo', (None, None), (VFS('/badserver@rpl:devel/1.0-1-1'), deps.parseFlavor('')), 0)]) except: pass # FIXME: Proxies report error differently from direct connections to # the server, and it's hard to fix :-( #except errors.RepositoryMismatch, err: # assert(str(err) == # 'Repository name mismatch. The correct repository name ' # 'is "localhost", but it was accessed as "badserver". Check for ' # 'incorrect repositoryMap configuration entries.')
def _testMerge(self, shadow, switchUsers=False): def _assertExists(repos, ver): repos.findTrove(None, ('testcase:source', ver, None)) def checkMetadata(ver, shortDesc): md = self.findAndGetTrove('testcase:source=%s' % ver).getMetadata() self.assertEquals(md['shortDesc'], shortDesc) def updateMetadata(ver, shortDesc): repos = self.openRepository() mi = self.createMetadataItem(shortDesc=shortDesc) trv = repos.findTrove(self.cfg.buildLabel, ('testcase:source', ver, None))[0] repos.addMetadataItems([(trv, mi)]) def verifyCONARY(ver, verMap, lastMerged=None): conaryState = ConaryStateFromFile("CONARY", None) sourceState = conaryState.getSourceState() assert (sourceState.getVersion().asString() == ver) if lastMerged: assert (sourceState.getLastMerged().asString() == lastMerged) else: assert (sourceState.getLastMerged() is None) for pathId, path, fileId, version in sourceState.iterFileList(): foo = verMap.pop(path) assert (version.asString() == foo) # there should be no paths remaining in the vermap assert (not verMap) repos = self.openRepository() shadowPrefix = self._shadowPrefix(shadow) parentPrefix = '/%s/' % (self.cfg.buildLabel.asString()) self.resetWork() os.chdir(self.workDir) self.newpkg("testcase") os.chdir("testcase") # 1.0-1 self.writeFile("testcase.recipe", recipes.testTransientRecipe1) self.writeFile('notChangedOnShadow', 'hello, world\n') self.writeFile('removedOnShadow', 'goodbye, world\n') self.writeFile('converging', '1\n2\n3\n4\n') self.addfile("testcase.recipe") self.addfile("notChangedOnShadow", text=True) self.addfile("removedOnShadow", text=True) self.addfile("converging", text=True) self.commit() updateMetadata('1.0', 'foo') self.mkbranch("1.0-1", shadow, "testcase:source", shadow=True) self._checkLatest('testcase:source', shadow, shadowPrefix + '1.0-1') # metadata should have transfered with the shadow checkMetadata(shadow, 'foo') # do shadow operations as the daemon user, so there is always if switchUsers: origstat = os.stat origlstat = os.lstat otheruser = StatWrapper(origstat, origlstat, 1, 1) # 1.0-1.1 if switchUsers: os.stat = otheruser.stat os.lstat = otheruser.lstat os.chdir("..") shutil.rmtree("testcase") self.checkout("testcase", shadow) os.chdir("testcase") f = open("testcase.recipe", "a") f.write("\n# extra comment\n") f.close() self.writeFile('addedOnShadow', 'hello, world\n') self.writeFile('converging', '1\n2\n3\n4\n5\n') self.addfile('addedOnShadow', text=True) self.remove('removedOnShadow') self.commit() # 1.1 (upstream change) if switchUsers: os.stat = origstat os.lstat = origlstat os.chdir("..") shutil.rmtree("testcase") self.checkout("testcase") os.chdir("testcase") self.writeFile("testcase.recipe", recipes.testTransientRecipe2) self.writeFile('notChangedOnShadow', 'hello 2\n') self.writeFile('removedOnShadow', 'changed\n') self.writeFile('converging', '1\n2\n3\n4\n5\n') self.commit() checkMetadata('1.1', 'foo') updateMetadata('1.1', 'upstream change') # 1.1-1.1 (merge) if switchUsers: os.stat = otheruser.stat os.lstat = otheruser.lstat os.chdir("..") shutil.rmtree("testcase") self.checkout("testcase", shadow) os.chdir("testcase") self.merge() assert (not os.path.exists('removedOnShadow')) # make sure that all the versions are correct verifyCONARY(shadowPrefix + '1.0-1.1', { 'testcase.recipe': parentPrefix + '1.1-1', 'notChangedOnShadow': parentPrefix + '1.1-1', 'addedOnShadow': shadowPrefix + '1.0-1.1', 'converging': parentPrefix + '1.1-1' }, lastMerged=parentPrefix + '1.1-1') self.commit() # the merge doesn't override the metadata, metadata doesn't get # transferred via merge. checkMetadata(shadow, 'foo') # after the commit, the source count should be 1.1 verifyCONARY( shadowPrefix + '1.1-1.1', { 'testcase.recipe': shadowPrefix + '1.1-1.1', # XXX it would be nice if this was reset to be from # the parent instead of a change on the shadow 'notChangedOnShadow': shadowPrefix + '1.1-1.1', 'addedOnShadow': shadowPrefix + '1.0-1.1', 'converging': parentPrefix + '1.1-1' }) self._checkLatest('testcase:source', shadow, shadowPrefix + '1.1-1.1') # make sure the intermediate version appears shadowed assert (repos.hasTrove('testcase:source', VFS(shadowPrefix + '1.1-1'), deps.Flavor())) # check out the latest version on the shadow os.chdir("..") shutil.rmtree("testcase") self.checkout("testcase", shadow) os.chdir('testcase') verifyCONARY( shadowPrefix + '1.1-1.1', { 'testcase.recipe': shadowPrefix + '1.1-1.1', # XXX it would be nice if this was reset to be from # the parent instead of a change on the shadow 'notChangedOnShadow': shadowPrefix + '1.1-1.1', 'addedOnShadow': shadowPrefix + '1.0-1.1', 'converging': parentPrefix + '1.1-1' }) # change shadowed version to 1.1-1.2 recipeText = open('testcase.recipe', 'r').read() newText = recipeText + '\n#comment bottom\n' self.writeFile("testcase.recipe", newText) self.commit() verifyCONARY( shadowPrefix + '1.1-1.2', { 'testcase.recipe': shadowPrefix + '1.1-1.2', 'notChangedOnShadow': shadowPrefix + '1.1-1.1', 'addedOnShadow': shadowPrefix + '1.0-1.1', 'converging': parentPrefix + '1.1-1' }) # change shadowed version to 2.0-0.1 newText = recipeText.replace("version = '1.1'", "version = '2.0'") self.writeFile("testcase.recipe", newText) self.commit() verifyCONARY( shadowPrefix + '2.0-0.1', { 'testcase.recipe': shadowPrefix + '2.0-0.1', 'notChangedOnShadow': shadowPrefix + '1.1-1.1', 'addedOnShadow': shadowPrefix + '1.0-1.1', 'converging': parentPrefix + '1.1-1' }) # make two minor revisions upstream to get 1.1-3 if switchUsers: os.stat = origstat os.lstat = origlstat os.chdir("..") shutil.rmtree("testcase") self.checkout("testcase") os.chdir("testcase") newText = open('testcase.recipe', 'r').read() + '\n#minor comment\n' self.writeFile("testcase.recipe", newText) self.commit() newText = '\n#minor comment \n' + newText self.writeFile("testcase.recipe", newText) self.commit() # merge to get 2.0-0.2 if switchUsers: os.stat = otheruser.stat os.lstat = otheruser.lstat os.chdir("..") shutil.rmtree("testcase") self.checkout("testcase", shadow) os.chdir("testcase") verifyCONARY(shadowPrefix + '2.0-0.1', { 'testcase.recipe': shadowPrefix + '2.0-0.1', 'notChangedOnShadow': shadowPrefix + '1.1-1.1', 'addedOnShadow': shadowPrefix + '1.0-1.1', 'converging': parentPrefix + '1.1-1' }, lastMerged=None) self.merge() assert (not os.path.exists('removedOnShadow')) # make sure that all the versions are correct verifyCONARY(shadowPrefix + '2.0-0.1', { 'testcase.recipe': parentPrefix + '1.1-3', 'notChangedOnShadow': shadowPrefix + '1.1-1.1', 'addedOnShadow': shadowPrefix + '1.0-1.1', 'converging': parentPrefix + '1.1-1' }, lastMerged=parentPrefix + '1.1-3') self.commit() # after the commit, the source count should be 2.0-0.2 verifyCONARY( shadowPrefix + '2.0-0.2', { 'testcase.recipe': shadowPrefix + '2.0-0.2', 'notChangedOnShadow': shadowPrefix + '1.1-1.1', 'addedOnShadow': shadowPrefix + '1.0-1.1', 'converging': parentPrefix + '1.1-1' }) self._checkLatest('testcase:source', shadow, shadowPrefix + '2.0-0.2') assert (not repos.hasTrove('testcase:source', VFS(shadowPrefix + '1.1-2'), deps.Flavor())) assert (repos.hasTrove('testcase:source', VFS(shadowPrefix + '1.1-3'), deps.Flavor())) if switchUsers: os.stat = origstat os.lstat = origlstat
def testShadowSourceDisappears(self): # CNY-462 class CustomError(Exception): errorIsUncatchable = True class MFCheckinCallbackFailure(CheckinCallback): def missingFiles(self, files): raise CustomError(files) class MFCheckinCallbackFailure2(CheckinCallback): def missingFiles(self, files): return False class MFCheckinCallbackSuccess(CheckinCallback): def missingFiles(self, files): return True shadow = 'localhost1@rpl:shadow' shadowPrefix = self._shadowPrefix(shadow) self.openRepository(0) self.resetRepository(1) repos1 = self.openRepository(1) self.resetWork() os.chdir(self.workDir) self.newpkg("testcase") os.chdir("testcase") # the origional version, 1.0-1 self.writeFile("testcase.recipe", recipes.testTransientRecipe1) self.addfile("testcase.recipe") self.commit() # create a shadow of 1.0-1 self.mkbranch("1.0-1", shadow, "testcase:source", shadow=True) self._checkLatest('testcase:source', shadow, shadowPrefix + '1.0-1') self.resetWork() os.chdir(self.workDir) # Source goes away self.stopRepository(0) # This should be in a different test case: repository is not even # available self.openRepository(0) callbackF = MFCheckinCallbackFailure() callbackF2 = MFCheckinCallbackFailure2() callbackS = MFCheckinCallbackSuccess() os.chdir(self.workDir) # This should fail period. (no callback) self.assertRaises(repository.errors.FileStreamMissing, self.checkout, "testcase", versionStr=shadow) # This call will fail because the callback throws an exception self.assertRaises(CustomError, self.checkout, "testcase", versionStr=shadow, callback=callbackF) # This call will fail because the callback returns False self.assertRaises(repository.errors.FileStreamMissing, self.checkout, "testcase", versionStr=shadow, callback=callbackF2) self.stopRepository(0) # This should fail period. (no callback) self.assertRaises(repository.errors.OpenError, self.checkout, "testcase", versionStr=shadow) # In passing, test CNY-1415 (missing files while writing a changeset to # a file) jobList = [ ('testcase:source', (None, None), (VFS(shadowPrefix + '1.0-1'), deps.parseFlavor('')), True), ] csfile = os.path.join(self.workDir, "changeset-file.ccs") # fix up the proxy cfg repos1 = self.openRepository(1) repos1.createChangeSetFile(jobList, csfile, callback=callbackS) cs = repository.changeset.ChangeSetFromFile(csfile) self.assertEqual(['testcase:source'], [t.getName() for t in cs.iterNewTroveList()]) # This call succeeds self.checkout("testcase", versionStr=shadow, callback=callbackS) # Test the callback shutil.rmtree('testcase') c = cvccmd.CvcMain() cmd = c._supportedCommands['checkout'] expOutput = """\ Warning: The following files are missing: testcase.recipe """ (ret, strng) = self.captureOutput(c.runCommand, cmd, self.cfg, {}, ['cvc', 'checkout', 'testcase=' + shadow]) self.assertEqual(strng, expOutput) os.chdir("testcase") dest = "localhost2@rpl:shadow" open("testcase.recipe", "w+").write(simpleRedirectRecipe % dest) self.addfile("testcase.recipe") self.commit(callback=callbackS) os.chdir(self.workDir) shutil.rmtree('testcase')