def testPathIdLookupShortcut(self): # CNY-1911 self.openRepository(1) self.openRepository(2) label2 = Label('localhost2@rpl:devel') label1 = Label('localhost1@rpl:devel') shadowLabel = Label('localhost@rpl:shadow') self.makeSourceTrove('test', simpleRecipe, buildLabel = label2) built = self.cookFromRepository('test', buildLabel = label2) self.assertEqual(built[0][1], '/localhost2@rpl:devel/1.0-1-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-1.1-1') # Now shadow again self.mkbranch(['test:source=' + label1.asString()], shadowLabel, shadow=True) # And build in the repo built = self.cookFromRepository('test', buildLabel = shadowLabel) # Stop the ancestor repo self.stopRepository(2) # We should still be able to cook built = self.cookFromRepository('test', buildLabel = shadowLabel)
def testLabel(self): self.assertRaises(ParseError, Label, "1.2-1") self.assertRaises(ParseError, Label, "foo@bar@bang") self.assertRaises(ParseError, Label, "foo@bar@bang:bash") self.assertRaises(ParseError, Label, "foo:bar@bang") self.assertRaises(ParseError, Label, "bar@bang") self.assertRaises(ParseError, Label, "bang") self.assertRaises(ParseError, Label, "foo:bang") self.assertRaises(ParseError, Label, "foo@bar:ba:ng") self.assertRaises(ParseError, Label, "1/2@foo:bar") self.assertRaises(ParseError, Label, "1'2@foo:bar") self.assertRaises(ParseError, Label, '1"2@foo:bar') self.assertRaises(ParseError, Label, "1\\2@foo:bar") self.assertRaises(ParseError, Label, "1(2@foo:bar") self.assertRaises(ParseError, Label, "1)2@foo:bar") self.assertRaises(ParseError, Label, "1[2@foo:bar") self.assertRaises(ParseError, Label, "1]2@foo:bar") self.assertRaises(ParseError, Label, "foo@bar:") self.assertRaises(ParseError, Label, "foo@:bar") self.assertRaises(ParseError, Label, "foo=bar@bang:baz") b = Label("this@nm:that") assert b.getHost() == "this" b2 = Label("this@nm:that") assert b == b2 assert b2 == b b2 = Label("this@nm:tha") assert not b == b2 assert not b2 == b self.assertRaises(AttributeError, b.__setattr__, "foo", 1)
def testLabel(self): self.assertRaises(ParseError, Label, "1.2-1") self.assertRaises(ParseError, Label, "foo@bar@bang") self.assertRaises(ParseError, Label, "foo@bar@bang:bash") self.assertRaises(ParseError, Label, "foo:bar@bang") self.assertRaises(ParseError, Label, "bar@bang") self.assertRaises(ParseError, Label, "bang") self.assertRaises(ParseError, Label, "foo:bang") self.assertRaises(ParseError, Label, "foo@bar:ba:ng") self.assertRaises(ParseError, Label, "1/2@foo:bar") self.assertRaises(ParseError, Label, "1'2@foo:bar") self.assertRaises(ParseError, Label, '1"2@foo:bar') self.assertRaises(ParseError, Label, '1\\2@foo:bar') self.assertRaises(ParseError, Label, '1(2@foo:bar') self.assertRaises(ParseError, Label, '1)2@foo:bar') self.assertRaises(ParseError, Label, '1[2@foo:bar') self.assertRaises(ParseError, Label, '1]2@foo:bar') self.assertRaises(ParseError, Label, "foo@bar:") self.assertRaises(ParseError, Label, "foo@:bar") self.assertRaises(ParseError, Label, "foo=bar@bang:baz") b = Label("this@nm:that") assert (b.getHost() == "this") b2 = Label("this@nm:that") assert (b == b2) assert (b2 == b) b2 = Label("this@nm:tha") assert (not b == b2) assert (not b2 == b) self.assertRaises(AttributeError, b.__setattr__, "foo", 1)
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)
def testShadowOpts(self): self.repos = self.openRepository() cfg = self.cfg self.addTestPkg(1) self.cookTestPkg(1) self.addTestPkg(2) self.cookTestPkg(2) oldLabel = cfg.installLabelPath shadowLabel = Label('localhost@rpl:shadow') try: self.mkbranch(["test1", "test2:source"], 'localhost@rpl:shadow', shadow=True, sourceOnly=True) cfg.installLabelPath = conarycfg.CfgLabelList([shadowLabel]) query = [('test1:source', None, None), ('test1', None, None), ('test2:source', None, None), ('test2', None, None)] results = self.repos.findTroves(cfg.installLabelPath, query, allowMissing=True) assert (('test1:source', None, None) in results) assert (('test2:source', None, None) in results) assert (('test1', None, None) not in results) self.mkbranch(['test1:source', 'test2'], 'localhost@rpl:shadow', shadow=True, binaryOnly=True) results = self.repos.findTroves(cfg.installLabelPath, query, allowMissing=True) assert (('test1:source', None, None) in results) assert (('test2:source', None, None) in results) assert (('test2', None, None) in results) assert (('test1', None, None) not in results) # now shadow both binary and source shadowLabel2 = Label('localhost@rpl:shadow2') self.mkbranch("1.0-1-1", 'localhost@rpl:shadow2', "test1", shadow=True) cfg.installLabelPath = conarycfg.CfgLabelList([shadowLabel2]) results = self.repos.findTroves(cfg.installLabelPath, query, allowMissing=True) assert (('test1:source', None, None) in results) assert (('test1', None, None) in results) finally: cfg.installLabelPath = oldLabel
def testMerge2(self): # a file is added on both the source and the shadow, then a merge # is attempted # create the original and the shadow shadowLabel = Label('localhost@rpl:branch') self.makeSourceTrove('test', simpleRecipe) self.mkbranch(['test:source'], shadowLabel, shadow=True) # update the original with the new file 'extra' os.chdir(self.workDir) self.checkout('test') self.checkout('test', str(shadowLabel), dir='test-shadow') os.chdir('test') self.writeFile('extra', 'Contents1\nContents2\n') self.addfile('extra', text=True) self.commit() # update the shadow with a conflicting version of the new file 'extra' # (but by adding it, not by merging) os.chdir('../test-shadow') self.writeFile('extra', 'Contents1\nContents3\n') self.addfile('extra', text=True) self.commit() # Now try to merge, there's a file conflict self.logCheck( self.merge, [], 'error: path extra added both locally and in repository') self.writeFile('extra', 'Contents1\nContents2\n') self.commit() self.logCheck( self.merge, [], 'error: path extra added both locally and in repository')
def testMergeWithRevision(self): recipe1 = simpleRecipe recipe2 = (simpleRecipe + '\n\t#extra line\n').replace('1.0', '2.0') recipe3 = (simpleRecipe + '\n\t#extra line\n\t#extra line 2\n').replace('1.0', '3.0') self.addComponent('test:source', '1.0-1', '', [('test.recipe', recipe1)]) self.addComponent('test:source', '2.0-1', '', [('test.recipe', recipe2)]) self.addComponent('test:source', '3.0-1', '', [('test.recipe', recipe3)]) self.mkbranch(['test:source=1.0'], 'localhost@rpl:shadow', shadow=True) os.chdir(self.workDir) self.cfg.buildLabel = Label('localhost@rpl:shadow') self.checkout('test') os.chdir('test') self.merge('2.0') self.verifyFile('test.recipe', recipe2) self.commit() self.merge('3.0-1') self.verifyFile('test.recipe', recipe3) self.commit() self.logFilter.add() self.merge('2.0') # raise an error self.logFilter.compare([ 'error: Cannot merge: version specified is before the last merge point, would be merging backwards' ]) self.logFilter.add() self.merge('localhost@rpl:linux') # raise an error self.logFilter.compare([ 'error: Can only specify upstream version, upstream version + source count or full versions to merge' ])
def testResolveAgainstTipFirst(self): self.addComponent('foo:run', '1', filePrimer=0, requires='trove:bar:run(1.0)') self.addComponent('bar:run', '1-1-1', provides='trove:bar:run(1.0)', filePrimer=1) self.addComponent('bar:run', '1-1-2', provides='trove:bar:run', filePrimer=1) branchBar = self.addComponent('bar:run', ':branch/1', provides='trove:bar:run(1.0)', filePrimer=1) self.cfg.installLabelPath.append(Label('localhost@rpl:branch')) self.checkUpdate('foo:run', ['foo:run', 'bar:run=:branch'], resolve=True) # make the thing on :branch that provides the dep not be on tip either branchBar = self.addComponent('bar:run', ':branch/1-1-2', filePrimer=1) self.checkUpdate('foo:run', ['foo:run', 'bar:run=:linux'], resolve=True) # now check when they're both on tip self.addComponent('bar:run', '1-1-3', provides='trove:bar:run(1.0)', filePrimer=1) branchBar = self.addComponent('bar:run', ':branch/3', provides='trove:bar:run(1.0)', filePrimer=1) self.checkUpdate('foo:run', ['foo:run', 'bar:run=:linux'], resolve=True)
def testLocalLabel(self): l = LocalLabel() l2 = LocalLabel() assert (l == l2) b = Label("this@some:that") assert (not l == b) self.assertRaises(AttributeError, b.__setattr__, "foo", 1)
def label(self, installLabel=None): """ Get label from config or custom installLabel or convert the installLabel to LabelObject @return (object) Label("label1") """ if installLabel: return Label(installLabel) return self.default_label
def testLabelTable(self): db = self.getDB() schema.createIdTables(db) tbl = versionops.LabelTable(db) l1 = Label("conary.rpath.com@test:trunk") l2 = Label("conary.rpath.com@test:branch") tbl.addId(l1) tbl.addId(l2) assert (tbl[l1] == 1) assert (tbl[l2] == 2) assert (tbl.get(l1, "foo") == 1) del tbl[l1] assert (tbl.get(l1, "foo") == "foo") tbl.delId(2) self.assertRaises(KeyError, tbl.__getitem__, l2)
def testCompareVersionSequence(self): # CNY-2020 v1 = VersionSequence([Label('foo@bar:baz')]) v2 = VersionSequence([Label('foo@bar:beep')]) self.assertEqual(v1, v1) self.assertTrue(cmp(v1, v2) in [-1, 1]) self.assertTrue(cmp(v2, v1) in [-1, 1]) self.assertEqual(cmp(v1, v2) + cmp(v2, v1), 0) # This should work, even if we return NotImplemented v3 = VersionSequence([Revision('1-1-1')]) self.assertTrue(cmp(v1, v3) in [-1, 1]) self.assertTrue(cmp(v3, v1) in [-1, 1]) self.assertEqual(cmp(v1, v3) + cmp(v3, v1), 0) # Compare with a random string, and make sure it's stable too v3 = 'abc' self.assertTrue(cmp(v1, v3) in [-1, 1]) self.assertTrue(cmp(v3, v1) in [-1, 1]) self.assertEqual(cmp(v1, v3) + cmp(v3, v1), 0)
def testLoadRecipeWithTwoTroves(self): # in the case when two recipes have been shadowed onto the same # label via different paths, we filter which one of the two to load # based on the labels included in the version strings (its shadow # history) repos = self.openRepository() branch = versions.VersionFromString('/localhost@rpl:devel//branch/') self.addTestPkg(1, version='1.0') self.mkbranch(self.cfg.buildLabel, "@rpl:test11", "test1:source") self.mkbranch(Label('localhost@rpl:test11'), "@rpl:branch", 'test1:source') self.addTestPkg(1, version='2.0') self.mkbranch(self.cfg.buildLabel, "@rpl:branch", "test1:source") oldLabel = self.cfg.buildLabel self.cfg.buildLabel = Label('localhost@rpl:branch') loader = self._testSubload(repos, "loadSuperClass('test1')", branch=branch) self.cfg.buildLabel = oldLabel assert (loader.module.TestRecipe1.version == '2.0')
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 testCreateSearchSourceStack(self): ss = self.getSearchSource() path = searchsource.createSearchPathFromStrings(['foo', 'conary.rpath.com@rpl:1', 'foo=:1', 'foo=@rpl:1', 'foo=conary.rpath.com@rpl:1']) assert(path == ((('foo', None, None),), (Label('conary.rpath.com@rpl:1'),), (('foo', ':1', None),), (('foo', '@rpl:1', None),), (('foo', 'conary.rpath.com@rpl:1', None),))) self.assertRaises(baseerrors.ParseError, searchsource.createSearchPathFromStrings, ['/f!oo@']) self.assertRaises(baseerrors.ParseError, searchsource.createSearchPathFromStrings, ['foo==']) trv = self.addComponent('foo:run') stack = searchsource.createSearchSourceStackFromStrings(ss, ['foo:run'], self.cfg.flavor, fallBackToRepos=False) assert(len(stack.sources) == 1) assert(isinstance(stack.sources[0], searchsource.TroveSearchSource)) stack = searchsource.createSearchSourceStack(ss, [trv], self.cfg.flavor, fallBackToRepos=False) assert(len(stack.sources) == 1) assert(isinstance(stack.sources[0], searchsource.TroveSearchSource)) stack = searchsource.createSearchSourceStackFromStrings(ss, ['localhost@rpl:1', 'localhost@rpl:1', 'localhost@rpl:3'], self.cfg.flavor, fallBackToRepos=False) assert(len(stack.sources) == 1) assert(isinstance(stack.sources[0], searchsource.NetworkSearchSource)) assert(len(stack.sources[0].installLabelPath) == 3) stack = searchsource.createSearchSourceStackFromStrings(ss, [self.cfg.installLabelPath], self.cfg.flavor, fallBackToRepos=False) assert(stack.sources[0].installLabelPath == tuple(self.cfg.installLabelPath)) stack = searchsource.createSearchSourceStackFromStrings(ss, self.cfg.installLabelPath[0], self.cfg.flavor, fallBackToRepos=False) assert(stack.sources[0].installLabelPath == tuple(self.cfg.installLabelPath)) self.assertRaises(baseerrors.ParseError, searchsource.createSearchPathFromStrings, [None]) self.assertRaises(baseerrors.ParseError, searchsource.createSearchSourceStack, ss, [None], self.cfg.flavor)
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 testPathIdLookupShortcut(self): # CNY-1911 self.openRepository(1) self.openRepository(2) label2 = Label('localhost2@rpl:devel') label1 = Label('localhost1@rpl:devel') shadowLabel = Label('localhost@rpl:shadow') self.makeSourceTrove('test', simpleRecipe, buildLabel=label2) built = self.cookFromRepository('test', buildLabel=label2) self.assertEqual(built[0][1], '/localhost2@rpl:devel/1.0-1-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-1.1-1') # Now shadow again self.mkbranch(['test:source=' + label1.asString()], shadowLabel, shadow=True) # And build in the repo built = self.cookFromRepository('test', buildLabel=shadowLabel) # Stop the ancestor repo self.stopRepository(2) # We should still be able to cook built = self.cookFromRepository('test', buildLabel=shadowLabel)
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 _testSourceShadow(self, shadow): 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() shadowPrefix = self._shadowPrefix(shadow) # 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') rc = self.rdiff('testcase', '-1', shadowPrefix + '1.0-1') rdiffShadowOutput = '\n'.join(( 'New shadow:', ' %s1.0-1' % shadowPrefix, ' of', ' /localhost@rpl:linux/1.0-1', '', )) assert (rc == rdiffShadowOutput) # build directly off the shadowed sources, the build count should # be 0.1 self.cfg.buildLabel = Label(shadow) built = self.cookFromRepository('testcase') assert (built[0][1] == shadowPrefix + '1.0-1-0.1') # check out the shadowed source and make a local change. source # count should become 1.1 os.chdir("..") shutil.rmtree("testcase") self.checkout("testcase", shadow) os.chdir("testcase") f = open("testcase.recipe", "a") f.write("\n\n") del f self.commit() self._checkLatest('testcase:source', shadow, shadowPrefix + '1.0-1.1') # check build count, should start at 1 built = self.cookFromRepository('testcase') assert (built[0][1] == shadowPrefix + '1.0-1.1-1') # test that changing the upstream version to 1.1 (from 1.0) results # in the correct source count (0.1) self.writeFile("testcase.recipe", recipes.testTransientRecipe2) self.commit() self._checkLatest('testcase:source', shadow, shadowPrefix + '1.1-0.1') # check build count, should start at 1 built = self.cookFromRepository('testcase') assert (built[0][1] == shadowPrefix + '1.1-0.1-1') # build again, build count should be 2 built = self.cookFromRepository('testcase') assert (built[0][1] == shadowPrefix + '1.1-0.1-2') # test that changing the upstream version back to 1.0 results in the # correct source count (1.2) self.writeFile("testcase.recipe", recipes.testTransientRecipe1) self.commit() self._checkLatest('testcase:source', shadow, shadowPrefix + '1.0-1.2') # and check that the build count becomes 1 built = self.cookFromRepository('testcase') assert (built[0][1] == shadowPrefix + '1.0-1.2-1')
def getTargetLabel(self): return Label(self.targetLabel % self.getMacros())
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])
def testDependencies(self): self.resetRepository() self.resetRoot() (built, d) = self.buildRecipe(recipes.libhelloRecipe, "Libhello") version = built[0][1] # XXX need more keepExisting tests (rc, str) = self.captureOutput(self.updatePkg, self.rootDir, "libhello:user", version, tagScript='/dev/null', keepExisting=True) assert (str == '1 additional trove is needed:\n' ' libhello:runtime=0-1-1 is required by:\n' ' libhello:user=0-1-1\n') (rc, str) = self.captureOutput(self.updatePkg, self.rootDir, "libhello:user", version, tagScript='/dev/null') assert (str == "1 additional trove is needed:\n" " libhello:runtime=0-1-1 is required by:\n" " libhello:user=0-1-1\n") self.cfg.fullVersions = self.cfg.fullFlavors = True (rc, str) = self.captureOutput(self.updatePkg, self.rootDir, "libhello:user", version, tagScript='/dev/null') self.assertEqual( str, "1 additional trove is needed:\n" " libhello:runtime=/localhost@rpl:linux/0-1-1[%(is)s]" " is required by:\n" " libhello:user=/localhost@rpl:linux/0-1-1[%(is)s]\n" % self.buildIs) self.cfg.fullVersions = self.cfg.fullFlavors = False self.cfg.showLabels = True (rc, str) = self.captureOutput(self.updatePkg, self.rootDir, "libhello:user", version, tagScript='/dev/null') assert (str == "1 additional trove is needed:\n" " libhello:runtime=localhost@rpl:linux/0-1-1" " is required by:\n" " libhello:user=localhost@rpl:linux/0-1-1\n") self.cfg.showLabels = False (rc, str) = self.captureOutput(self.updatePkg, self.rootDir, "libhello:runtime", version, tagScript='/dev/null') assert (not str) (rc, str) = self.captureOutput(self.updatePkg, self.rootDir, "libhello:user", version, tagScript='/dev/null') assert (not str) self.resetRoot() (rc, str) = self.captureOutput(self.updatePkg, self.rootDir, "libhello", version, tagScript='/dev/null') self.assertEquals(str, '') self.resetRoot() (rc, str) = self.captureOutput(self.updatePkg, self.rootDir, "libhello:user", version, tagScript='/dev/null', resolve=True) assert (str == "Including extra troves to resolve dependencies:\n" " libhello:runtime=0-1-1\n") self.resetRoot() self.cfg.fullFlavors = self.cfg.fullVersions = True (rc, str) = self.captureOutput(self.updatePkg, self.rootDir, "libhello:user", version, tagScript='/dev/null', resolve=True) assert ( str == "Including extra troves to resolve dependencies:\n" " libhello:runtime=/localhost@rpl:linux/0-1-1[%(flavor)s]\n" % self.getFlavor()) self.cfg.fullFlavors = self.cfg.fullVersions = False self.resetRoot() # add an extra bogus value at the front of the installLabelPath # this ensures that conary searches the whole installLabelPath oldPath = self.cfg.installLabelPath[:] self.cfg.installLabelPath.insert(0, Label('localhost@foo:bar')) # :script needs :user, which needs :runtime -- this makes sure # multilevel (well, 2 level) dependency resolution works (rc, str) = self.captureOutput(self.updatePkg, self.rootDir, "libhello:script", version, tagScript='/dev/null', resolve=True) assert (str == "Including extra troves to resolve dependencies:\n" " libhello:runtime=0-1-1 libhello:user=0-1-1\n") self.cfg.installLabelPath = oldPath (rc, str) = self.captureOutput(self.erasePkg, self.rootDir, "libhello:user") self.assertEquals( str, """\ The following dependencies would not be met after this update: libhello:script=0-1-1 (Already installed) requires: file: /sbin/user which is provided by: libhello:user=0-1-1 (Would be erased) """) self.cfg.showLabels = self.cfg.fullFlavors = True (rc, str) = self.captureOutput(self.erasePkg, self.rootDir, "libhello:user") assert (str == """\ The following dependencies would not be met after this update: libhello:script=localhost@rpl:linux/0-1-1[%(flavor)s] (Already installed) requires: file: /sbin/user which is provided by: libhello:user=localhost@rpl:linux/0-1-1[%(flavor)s] (Would be erased) """ % self.getFlavor()) self.cfg.showLabels = self.cfg.fullFlavors = False (rc, str) = self.captureOutput(self.erasePkg, self.rootDir, "libhello:user", depCheck=False) assert (not str) # test erase breaking a dependency w/ flags (since getting the flags # set has caused problems before) self.resetRoot() self.updatePkg(self.rootDir, "libhello:runtime", version, tagScript='/dev/null') self.updatePkg(self.rootDir, "libhello:user", version, tagScript='/dev/null') (rc, str) = self.captureOutput(self.erasePkg, self.rootDir, "libhello:runtime", depCheck=True) if use.Arch.x86: assert (str == """\ The following dependencies would not be met after this update: libhello:user=0-1-1 (Already installed) requires: soname: ELF32/libhello.so.0(SysV x86) which is provided by: libhello:runtime=0-1-1 (Would be erased) """) elif use.Arch.x86_64: assert (str == """\ The following dependencies would not be met after this update: libhello:user=0-1-1 (Already installed) requires: soname: ELF64/libhello.so.0(SysV x86_64) which is provided by: libhello:runtime=0-1-1 (Would be erased) """) else: raise NotImplementedError, 'modify test for this arch'
def testVersion(self): self.assertRaises(ParseError, VersionFromString, '0.50.1') verStr = "/foo.com@spc:bar/1.000:1.2-3/bang.com@spc:branch/10.000:2.4-5" verStr2 = "/foo.com@spc:bar/1.000:1.2-3/bang.com@spc:branch/15.000:2.4-6" v = ThawVersion(verStr) assert (v.freeze() == verStr) assert (v.asString(VersionFromString("/foo.com@spc:bar")) == "1.2-3/bang.com@spc:branch/2.4-5") assert (v.timeStamps() == [1, 10]) v = v.copy() v.incrementSourceCount() assert (v.asString() == ThawVersion(verStr2).asString()) assert (v.getHost() == 'bang.com') # test that cPickle works on a Version object (the changeset cache # database pickles versions) vpickled = cPickle.dumps(v) vunpickled = cPickle.loads(vpickled) assert (vunpickled.asString() == v.asString()) v2 = VersionFromString( "/foo.com@spc:bar/1.2-3/bang.com@spc:branch/2.4-5", timeStamps=[1.000, 10.000]) assert (v2.freeze() == verStr) assert ([x.asString() for x in v2.iterLabels() ] == ['foo.com@spc:bar', 'bang.com@spc:branch']) last = v.trailingRevision() assert (last.asString() == "2.4-6") assert (not v.onLocalLabel()) assert (not v.isInLocalNamespace()) assert (not v.onEmergeLabel()) assert (not v.onLocalCookLabel()) assert (v2.getHost() == 'bang.com') assert (v.trailingLabel() == Label('bang.com@spc:branch')) branch = v.branch() assert (branch.getHost() == 'bang.com') strrep = branch.asString() assert (strrep == "/foo.com@spc:bar/1.2-3/bang.com@spc:branch") branch2 = VersionFromString(branch.asString()) assert (branch == branch2) frozen = branch.freeze() branch2 = ThawVersion(frozen) assert (branch2 == branch) newVer = branch2.createVersion(Revision("1.1-2")) assert (newVer.asString() == "/foo.com@spc:bar/1.2-3/bang.com@spc:branch/1.1-2") assert (not newVer.onLocalLabel()) assert (not newVer.isInLocalNamespace()) assert (not newVer.onEmergeLabel()) assert (not newVer.onLocalCookLabel()) assert (not newVer.isOnLocalHost()) assert (newVer.canonicalVersion() == newVer) assert (v.hasParentVersion()) parent = v.parentVersion() assert (not parent.hasParentVersion()) assert (parent.asString() == "/foo.com@spc:bar/1.2-3") # check emerge label emerge = parent.createBranch(EmergeLabel(), withVerRel=1) assert (emerge.getHost() == 'local') assert ( emerge.asString() == "/foo.com@spc:bar/1.2-3/local@local:EMERGE/3") assert (not emerge.onLocalLabel()) assert (emerge.onEmergeLabel()) assert (not emerge.onRollbackLabel()) assert (not emerge.onLocalCookLabel()) assert (emerge.isOnLocalHost()) assert (emerge.isInLocalNamespace()) # check local cook label cook = parent.createBranch(CookLabel(), withVerRel=1) assert (cook.asString() == "/foo.com@spc:bar/1.2-3/local@local:COOK/3") assert (not cook.onLocalLabel()) assert (not cook.onEmergeLabel()) assert (not cook.onRollbackLabel()) assert (cook.onLocalCookLabel()) assert (cook.isOnLocalHost()) assert (cook.isInLocalNamespace()) # check local rollback label branch2 = parent.createBranch(RollbackLabel(), withVerRel=1) assert (branch2.asString() == "/foo.com@spc:bar/1.2-3/local@local:ROLLBACK/3") assert (not branch2.onLocalLabel()) assert (not branch2.onEmergeLabel()) assert (branch2.onRollbackLabel()) assert (not branch2.onLocalCookLabel()) assert (branch2.isOnLocalHost()) assert (branch2.isInLocalNamespace()) # check local branch label branch2 = parent.createBranch(LocalLabel(), withVerRel=1) assert ( branch2.asString() == "/foo.com@spc:bar/1.2-3/local@local:LOCAL/3") assert (branch2.onLocalLabel()) assert (not branch2.onEmergeLabel()) assert (not branch2.onRollbackLabel()) assert (not branch2.onLocalCookLabel()) assert (branch2.isOnLocalHost()) assert (branch2.isInLocalNamespace()) branch3 = VersionFromString(branch2.asString()) assert (branch2 == branch3) branch2 = branch2.branch() assert ( branch2.asString() == "/foo.com@spc:bar/1.2-3/local@local:LOCAL") parent = v.parentVersion() assert (parent.asString() == "/foo.com@spc:bar/1.2-3") branch2 = parent.createBranch(LocalLabel()) assert ( branch2.asString() == "/foo.com@spc:bar/1.2-3/local@local:LOCAL") shadow = parent.branch().createShadow(Label('foo.com@spc:shadow')) assert (shadow.asString() == "/foo.com@spc:bar//shadow") assert (shadow.getHost() == 'foo.com') branch = VersionFromString("/foo.com@spc:bar") v = VersionFromString("1.2-3", branch) assert (v.asString() == "/foo.com@spc:bar/1.2-3") # test getBinaryVersion and getSourceVersion v = ThawVersion(verStr) b = v.getBinaryVersion() assert (b.asString() == "/foo.com@spc:bar/1.2-3-0/bang.com@spc:branch/2.4-5") # make sure slots are working v = ThawVersion("/foo.com@spec:bar/10:1.2-3") self.assertRaises(AttributeError, v.__setattr__, "foo", 1) v = ThawVersion(v.freeze()) self.assertRaises(AttributeError, v.__setattr__, "foo", 1) v = VersionFromString('/localhost@rpl:linux/1.0-1-0/' 'local@local:EMERGE/1/COOK/2') assert (VersionFromString(v.asString()) == v)
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])
def derive(repos, cfg, targetLabel, troveSpec, checkoutDir=None, extract=False, info=False, callback=None): """ Performs all the commands necessary to create a derived recipe. First it shadows the package, then it creates a checkout of the shadow and converts the checkout to a derived recipe package. Finally if extract = True, it installs an version of the binary package into a root. @param repos: trovesource to search for and derive packages from @param cfg: configuration to use when deriving the package @type cfg: ConaryConfiguration object @param targetLabel: label to derive from @type targetLabel: versions.Label @param checkoutDir: directory to create the checkout in. If None, defaults to currentDir + packageName. @param extract: If True, creates a subdirectory of the checkout named _ROOT_ with the contents of the binary of the derived package. @param info: If true, only display the information about the shadow that would be performed if the derive command were completed. @param callback: """ origDir = os.getcwd() try: if callback is None: callback = DeriveCallback() if isinstance(troveSpec, tuple): troveName, versionSpec, flavor = troveSpec versionSpec = str(versionSpec) troveSpec = cmdline.toTroveSpec(troveName, versionSpec, flavor) else: troveName, versionSpec, flavor = cmdline.parseTroveSpec(troveSpec) if isinstance(targetLabel, str): targetLabel = Label(targetLabel) troveName, versionSpec, flavor = cmdline.parseTroveSpec(troveSpec) result = repos.findTrove(cfg.buildLabel, (troveName, versionSpec, flavor), cfg.flavor) # findTrove shouldn't return multiple items for one package anymore # when a flavor is specified. troveToDerive, = result # displaying output along the screen allows there to be a record # of what operations were performed. Since this command is # an aggregate of several commands I think that is appropriate, # rather than simply using a progress callback. log.info('Shadowing %s=%s[%s] onto %s' % (troveToDerive[0], troveToDerive[1], troveToDerive[2], targetLabel)) if info: cfg.interactive = False error = branch.branch(repos, cfg, str(targetLabel), ['%s=%s[%s]' % troveToDerive], makeShadow=True, sourceOnly=True, binaryOnly=False, allowEmptyShadow=True, info=info) if info or error: return shadowedVersion = troveToDerive[1].createShadow(targetLabel) shadowedVersion = shadowedVersion.getSourceVersion(False) troveName = troveName.split(':')[0] checkoutDir = checkoutDir or troveName checkin.checkout(repos, cfg, checkoutDir, ["%s=%s" % (troveName, shadowedVersion)], callback=callback) os.chdir(checkoutDir) nvfs = repos.getTrovesBySource(troveToDerive[0] + ':source', troveToDerive[1].getSourceVersion()) trvs = repos.getTroves(nvfs) hasCapsule = [x for x in trvs if x.troveInfo.capsule.type()] if hasCapsule: derivedRecipeType = 'DerivedCapsuleRecipe' removeText = '' else: derivedRecipeType = 'DerivedPackageRecipe' removeText = \ """ # This appliance uses PHP as a command interpreter but does # not include a web server, so remove the file that creates # a dependency on the web server r.Remove('/etc/httpd/conf.d/php.conf') """ log.info('Rewriting recipe file') recipeName = troveName + '.recipe' className = util.convertPackageNameToClassName(troveName) derivedRecipe = """ class %(className)sRecipe(%(recipeBaseClass)s): name = '%(name)s' version = '%(version)s' def setup(r): ''' In this recipe, you can make modifications to the package. Examples: # This appliance has high-memory-use PHP scripts r.Replace('memory_limit = 8M', 'memory_limit = 32M', '/etc/php.ini') %(removeText)s # This appliance requires that a few binaries be replaced # with binaries built from a custom archive that includes # a Makefile that honors the DESTDIR variable for its # install target. r.addArchive('foo.tar.gz') r.Make() r.MakeInstall() # This appliance requires an extra configuration file r.Create('/etc/myconfigfile', contents='some data') ''' """ % dict(className=className, name=troveName, version=shadowedVersion.trailingRevision().getVersion(), recipeBaseClass=derivedRecipeType, removeText=removeText) open(recipeName, 'w').write(derivedRecipe) log.info('Removing extra files from checkout') conaryState = state.ConaryStateFromFile('CONARY', repos) sourceState = conaryState.getSourceState() # clear the factory since we don't care about how the parent trove was # created sourceState.setFactory('') addRecipe = True for (pathId, path, fileId, version) in list(sourceState.iterFileList()): if path == recipeName: addRecipe = False continue sourceState.removeFile(pathId) if util.exists(path): statInfo = os.lstat(path) try: if statInfo.st_mode & stat.S_IFDIR: os.rmdir(path) else: os.unlink(path) except OSError, e: log.warning("cannot remove %s: %s" % (path, e.strerror)) conaryState.write('CONARY') if addRecipe: checkin.addFiles([recipeName]) if extract: log.info('extracting files from %s=%s[%s]' % (troveToDerive)) # extract to _ROOT_ extractDir = os.path.join(os.getcwd(), '_ROOT_') ts = [(troveToDerive[0], (None, None), (troveToDerive[1], troveToDerive[2]), True)] cs = repos.createChangeSet(ts, recurse=True) ChangesetExploder(cs, extractDir) # extract to _OLD_ROOT_ secondDir = os.path.join(os.getcwd(), '_OLD_ROOT_') cs = repos.createChangeSet(ts, recurse=True) ChangesetExploder(cs, secondDir)
def label(self, installLabel = None): """ get label from config or custom installLabel """ if installLabel: return Label(installLabel) return self.default_label
def testSqlVersioning(self): db = self.getDB() schema.createSchema(db) vTbl = versiontable.VersionTable(db) bTbl = versionops.BranchTable(db) sv = versionops.SqlVersioning(db, vTbl, bTbl) i = items.Items(db) # we need the FileStreams table for eraseVersion to work # properly. It is created as part of the createTroves() call v5 = ThawVersion("/conary.rpath.com@test:trunk/5:1.2-5") v10 = ThawVersion("/conary.rpath.com@test:trunk/10:1.2-10") v15 = ThawVersion("/conary.rpath.com@test:trunk/15:1.2-15") v20 = ThawVersion("/conary.rpath.com@test:trunk/20:1.2-20") branch = v10.branch() itemId = i.addId('foo') sv.createBranch(itemId, branch) sv.createVersion(itemId, v10, 0, "foo:source") assert (bTbl.has_key(branch)) assert (vTbl.has_key(v10)) assert (sv.hasVersion(itemId, vTbl[v10])) assert (i.has_key("foo:source")) assert (not sv.hasVersion(2, vTbl[v10])) branchId = bTbl[branch] itemId2 = i.addId('bar') sv.createBranch(itemId2, branch) sv.createVersion(itemId2, v10, 0, None) self.assertRaises(versionops.DuplicateVersionError, sv.createVersion, itemId2, v10, 0, None) assert ([vTbl.getId(x) for x in sv.versionsOnBranch(1, branchId)] == [str(v10)]) sv.createVersion(1, v20, 0, None) assert ([vTbl.getId(x) for x in sv.versionsOnBranch(1, branchId) ] == [str(v20), str(v10)]) sv.createVersion(1, v15, 0, None) db.commit() assert ([vTbl.getId(x) for x in sv.versionsOnBranch(1, branchId) ] == [str(v20), str(v15), str(v10)]) sv.createVersion(1, v5, 0, None) assert ([vTbl.getId(x) for x in sv.versionsOnBranch(1, branchId) ] == [str(v20), str(v15), str(v10), str(v5)]) label = Label("conary.rpath.com@test:trunk") assert [bTbl.getId(x) for x in sv.branchesOfLabel(1, label) ]\ == [ branch ] brLabel = Label("conary.rpath.com@test:br1") branch1 = v10.createBranch(brLabel, withVerRel=False) branch2 = v20.createBranch(brLabel, withVerRel=False) sv.createBranch(1, branch1) sv.createBranch(1, branch2) assert([bTbl.getId(x) for x in sv.branchesOfLabel(1, brLabel)] == \ [branch1, branch2]) assert ([bTbl.getId(x) for x in sv.branchesOfItem(1)] == [branch, branch1, branch2])
def testShadows(self): self.doTestVersion('/foo@spc:linux//shadow/1-1.2') self.doTestVersion('/foo@spc:linux//shadow/1-1-1.2') self.doTestVersion('/foo@spc:linux//shadow/1-1-1/branch//shadow2/1.1') self.doTestVersion('/foo@spc:linux//shadow/1-1-1/branch//shadow2/' '/shadow3/1.1.1') self.assertRaises(ParseError, VersionFromString, '/foo@spc:linux//shadow/1-1.2.3') self.assertRaises(ParseError, VersionFromString, '/foo@spc:linux//shadow/1-1-1.2.3') self.assertRaises(ParseError, VersionFromString, '/foo@spc:linux//shadow/1-1-1/branch/1.1') self.assertRaises( ParseError, VersionFromString, '/foo@spc:linux//shadow/1-1-1/branch//shadow2/1.1.1') self.assertRaises( ParseError, VersionFromString, '/foo@spc:linux//shadow/1-1-1/branch//shadow2/' '/shadow3/1.1.1.1') trunk = VersionFromString('/foo@spc:linux') assert (not trunk.isShadow()) assert (not trunk.hasParentBranch()) shadow = trunk.createShadow(Label('foo@spc:shadow')) assert (shadow.isShadow()) assert (shadow.asString() == '/foo@spc:linux//shadow') assert (shadow.hasParentBranch()) assert (shadow.parentBranch() == trunk) version = shadow.createVersion(Revision('1.1-1')) assert (version.isShadow()) assert (not version.isModifiedShadow()) assert (version.asString() == '/foo@spc:linux//shadow/1.1-1') assert ( version.canonicalVersion().asString() == '/foo@spc:linux/1.1-1') assert (version.shadowLength() == 1) newVer = version.createShadow(Label("foo@spc:shadow2")) assert (newVer.asString() == '/foo@spc:linux//shadow//shadow2/1.1-1') assert (newVer.shadowLength() == 2) assert (newVer.parentVersion().asString() == '/foo@spc:linux//shadow/1.1-1') assert (newVer.parentVersion().parentVersion().asString() == '/foo@spc:linux/1.1-1') assert (newVer.canonicalVersion().asString() == '/foo@spc:linux/1.1-1') assert (newVer.isShadow()) assert (not newVer.canonicalVersion().isShadow()) assert (not newVer.canonicalVersion().isModifiedShadow()) self.assertRaises(AssertionError, newVer.createBranch, Label("foo@spc:shadow2")) self.assertRaises(VersionStringError, newVer.createShadow, Label("foo@spc:shadow2")) branch = newVer.createBranch(Label("foo@spc:branch")) assert (branch.asString() == '/foo@spc:linux//shadow//shadow2/1.1-1/branch') branchVer = newVer.createBranch(Label("foo@spc:branch"), withVerRel=True) assert (branchVer.asString() == '/foo@spc:linux//shadow//shadow2/1.1-1/branch/1') assert (branchVer.shadowLength() == 0) assert (not branchVer.isShadow()) newVer.incrementSourceCount() assert ( newVer.asString() == '/foo@spc:linux//shadow//shadow2/1.1-1.0.1') assert (newVer.isModifiedShadow()) branchVer.incrementSourceCount() assert (branchVer.asString() == '/foo@spc:linux//shadow//shadow2/1.1-1/branch/2') assert (ThawVersion(branchVer.freeze()) == branchVer) newShadow = branchVer.createShadow(Label('foo@spc:shadow3')) assert (newShadow.asString() == '/foo@spc:linux//shadow//shadow2/1.1-1/branch//shadow3/2') assert (newShadow.parentVersion().asString() == '/foo@spc:linux//shadow//shadow2/1.1-1/branch/2') assert (newShadow.parentVersion().parentVersion().asString() == '/foo@spc:linux//shadow//shadow2/1.1-1') assert (newShadow.parentVersion().parentVersion().parentVersion(). asString() == '/foo@spc:linux//shadow/1.1-1') assert (newShadow.parentVersion().parentVersion().parentVersion(). parentVersion().asString() == '/foo@spc:linux/1.1-1') assert (newShadow.canonicalVersion().asString() == '/foo@spc:linux//shadow//shadow2/1.1-1/branch/2') # shadowed binary has a parent version v = VersionFromString("/foo@spc:linux//shadow/1.2-1-1") assert (v.hasParentVersion()) # shadowed source has a parent version v = VersionFromString("/foo@spc:linux//shadow/1.2-1") assert (v.hasParentVersion()) # cooked shadowed binary doesn't has a parent version v = VersionFromString("/foo@spc:linux//shadow/1.2-1-0.1") assert (not v.hasParentVersion()) v = VersionFromString("/foo@spc:linux//shadow/1.2-1").copy() assert (v.hasParentVersion()) v.incrementBuildCount() assert (v.asString() == "/foo@spc:linux//shadow/1.2-1-0.1") assert (not v.hasParentVersion()) v2 = v.createBranch(LocalLabel(), withVerRel=True) assert (v2.asString() == "/foo@spc:linux//shadow/1.2-1-0.1/local@local:LOCAL/1") v = VersionFromString("/foo@spc:linux//shadow/1.2-1.1").copy() v.incrementBuildCount() assert (v.asString() == "/foo@spc:linux//shadow/1.2-1.1-1") assert (not v.hasParentVersion()) # test to make sure versions don't count -0 having a build count v = VersionFromString('/a@b:c/4.1.25-18-0/d//e/22.3-1') assert (not v.hasParentVersion()) # If you create a pristine shadow of a modified shadow, # that version should NOT be a modifiedShadow v = VersionFromString("/foo@spc:linux//shadow//shadow2/1.2-1.1") assert (v.isShadow() and not v.isModifiedShadow()) v = v.parentVersion() assert (v.isShadow() and v.isModifiedShadow()) v = VersionFromString("/foo@spc:linux//shadow//shadow2/1.2-1.0.1") assert (v.isShadow() and v.isModifiedShadow())
def setUpGroupOddities(self): def _commitRecipe(name, recipe, new=True): oldDir = os.getcwd() os.chdir(self.workDir) if new: self.newpkg(name) else: self.checkout(name) os.chdir(name) self.writeFile('%s.recipe' % name, recipe) if new: self.addfile('%s.recipe' % name) self.commit() os.chdir(oldDir) groupTrove = """ class GroupFoo(GroupRecipe): name = 'group-foo' version = '1.0' checkPathConflicts = False clearBuildRequires() imageGroup = False def setup(r): r.setLabelPath('localhost@rpl:linux', 'localhost@rpl:branch1') r.createGroup('group-bam') r.addTrove('test1') r.addTrove('test2:runtime', None, '!readline') r.addTrove('test2:runtime', None, 'readline') r.addTrove('test3', None, 'is:x86_64') r.addTrove('test4-on-branch', source='test4') r.addNewGroup('group-bam') r.addTrove('group-bar', ':branch2', groupName='group-bam') Use.readline.setPlatform(True) """ groupTrove2 = """ class GroupBar(GroupRecipe): name = 'group-bar' version = '1.0' clearBuildRequires() imageGroup = False def setup(r): r.createGroup('group-bar2') r.addTrove('test5') r.addNewGroup('group-bar2') r.addTrove('test1:runtime', ':linux', groupName='group-bar2') Use.readline.setPlatform(True) """ self.addTestPkg(1) self.cookTestPkg(1) self.addTestPkg(1, content="#changed") self.addTestPkg(2, flags='Use.readline') self.overrideBuildFlavor('!readline') self.cookTestPkg(2) self.overrideBuildFlavor('readline') self.cookTestPkg(2) self.addTestPkg(3, flags='Arch.x86') self.overrideBuildFlavor('is:x86_64') self.cookTestPkg(3) self.overrideBuildFlavor('is:x86') self.cfg.buildLabel = Label('localhost@rpl:branch1') self.addTestPkg(4, content='r.PackageSpec("test4-on-branch", ".*")') self.cookTestPkg(4) self.cfg.buildLabel = Label('localhost@rpl:branch2') self.addTestPkg(5) self.cookTestPkg(5) _commitRecipe('group-bar', groupTrove2) self.cookFromRepository('group-bar') self.cfg.buildLabel = Label('localhost@rpl:linux') _commitRecipe('group-foo', groupTrove) self.cookFromRepository('group-foo') # add a trove with just a source version # and one with neither source nor binary groupTrove += ''' r.addTrove('test6') r.addTrove('test7') ''' self.addTestPkg(6) _commitRecipe('group-foo', groupTrove, new=False)
def testDistributedBranch(self): origDir = os.getcwd() try: self.resetAllRepositories() self.resetWork() self.openRepository(0) repos = self.openRepository(1) repos.deleteUserByName(Label('localhost@foo:bar'), 'anonymous') repos.deleteUserByName(Label('localhost1@foo:bar'), 'anonymous') # create initial source component in the first repository srcdir = os.sep.join((self.workDir, 'src')) os.mkdir(srcdir) os.chdir(srcdir) self.newpkg('testcase') os.chdir('testcase') self.writeFile('testcase.recipe', recipes.testRecipe1) self.addfile('testcase.recipe') self.commit() # build testcase binary components built, out = self.captureOutput(self.cookItem, repos, self.cfg, 'testcase') flavor = use.Arch.getCurrentArch()._toDependency() assert(built == ((('testcase:runtime', '/localhost@rpl:linux/1.0-1-1', flavor),), None)) # branch testcase:source on second repository newLabel = versions.Label("localhost1@rpl:linux") self.mkbranch(self.cfg.buildLabel, newLabel, 'testcase:source') # check out branched source component origBuildLabel = self.cfg.buildLabel self.cfg.buildLabel = newLabel os.chdir(srcdir) shutil.rmtree('testcase') self.checkout('testcase') os.chdir('testcase') # make a modification on the branch f = open('testcase.recipe', 'a') f.write(' self.Create("/newfile", contents="hello, world")\n') f.close() os.system("sed -i 's/fileText = .*/initialFileText = initialFileText.replace(\"4\", \"5\"); &/' testcase.recipe") self.commit() # build testcase binary components built, out = self.captureOutput(self.cookItem, repos, self.cfg, 'testcase') branchedVersion = versions.VersionFromString( '/localhost@rpl:linux/1.0-1-0/localhost1@rpl:linux/2-1') assert(built == ((('testcase:runtime', '/localhost@rpl:linux/1.0-1-0/localhost1@rpl:linux/2-1', flavor),), None)) # see if we can create a changeset repos = self.openRepository() (fd, path) = tempfile.mkstemp() os.close(fd) repos.createChangeSetFile( [('testcase', (None, None), (branchedVersion, flavor), 0)], path) os.unlink(path) # install the branched testcase:runtime component self.updatePkg(self.cfg.root, 'testcase:runtime', 'localhost1@rpl:linux') self.verifyFile(os.sep.join((self.cfg.root, 'newfile')), "hello, world\n") # try flipping from one version to another while changing the config # file self.resetRoot() self.updatePkg(self.cfg.root, 'testcase', 'localhost@rpl:linux') f = open(self.cfg.root + "/etc/changedconfig", "a") f.write("new line\n") f.close() self.updatePkg(self.cfg.root, 'testcase', 'localhost1@rpl:linux') # try flipping from one version to another self.resetRoot() self.updatePkg(self.cfg.root, 'testcase', 'localhost@rpl:linux') self.updatePkg(self.cfg.root, 'testcase', 'localhost1@rpl:linux') self.verifyFile(os.sep.join((self.cfg.root, 'newfile')), "hello, world\n") # and back again, though this doesn even need repository 1 anymore self.servers.stopServer(1) self.updatePkg(self.cfg.root, 'testcase', 'localhost@rpl:linux') assert(not os.path.exists(os.sep.join((self.cfg.root, 'newfile')))) finally: os.chdir(origDir)