Beispiel #1
0
    def testPrintDirectoryStatus(self):
        handle = self.getRbuildHandle()
        from rbuild_plugins import status
        mock.mockMethod(handle.Status._printOneDirectoryStatus)
        mock.mock(dirstore, 'CheckoutProductStore')
        dirstore.CheckoutProductStore(
        ).getProductDefinitionDirectory._mock.setDefaultReturn(
            '/full/path/.rbuild/product-definition')
        dirstore.CheckoutProductStore(
        ).getBaseDirectory._mock.setDefaultReturn('/full/path')

        handle.Status._printOneDirectoryStatus._mock.setDefaultReturn(None)
        self.mock(
            os, 'walk',
            lambda x: [('/full/path', ['Development', '.rbuild'], False)])
        handle.Status.printDirectoryStatus('/full/path', product=True)
        self.unmock()
        handle.Status._printOneDirectoryStatus._mock.assertCalled(
            '/full/path/.rbuild/product-definition',
            'Product Definition',
            status.DEFAULT,
            proddef=True,
            local=True,
            repository=True)
        handle.Status._printOneDirectoryStatus._mock.assertCalled(
            '/full/path',
            '/full/path',
            status.DEFAULT,
            '',
            local=True,
            repository=True)
        handle.Status._printOneDirectoryStatus._mock.assertCalled(
            '/full/path/Development',
            'Development',
            status.DEFAULT,
            None,
            local=True,
            repository=True)
        self.mock(os, 'walk', lambda x: [])
        handle.Status.printDirectoryStatus('bogus', product=True)
        self.unmock()
        handle.Status._printOneDirectoryStatus._mock.assertCalled(
            '/full/path/.rbuild/product-definition',
            'Product Definition',
            status.DEFAULT,
            proddef=True,
            local=True,
            repository=True)
        handle.Status._printOneDirectoryStatus._mock.assertCalled(
            'bogus', 'bogus', status.DEFAULT, '', local=True, repository=True)

        self.assertRaises(ValueError,
                          handle.Status.printDirectoryStatus,
                          'bogus',
                          product=True,
                          local=False,
                          repository=False)
Beispiel #2
0
 def testCheckoutProductStore(self):
     self._prepProductStore()
     util.mkdirChain('foo/stable/package')
     os.chdir('foo/stable/package')
     handle = self.getRbuildHandle(productStore=mock.MockObject())
     productStore = dirstore.CheckoutProductStore(handle)
     self.assertEquals(productStore.getBaseDirectory(),
                       self.workDir + '/foo')
     self.assertEquals(productStore.getActiveStageName(), 'stable')
     productStore = dirstore.CheckoutProductStore(
         handle, baseDirectory=self.workDir + '/foo')
     self.assertEquals(productStore.getBaseDirectory(),
                       self.workDir + '/foo')
Beispiel #3
0
 def testSaveProduct(self):
     self._prepProductStore()
     os.chdir('foo/stable')
     handle = self.getRbuildHandle(productStore=mock.MockObject())
     productStore = dirstore.CheckoutProductStore(handle)
     mock.mockMethod(productStore._getSourceTroveVersion,
         returnValue='cny.tv@ns:1/2-3')
     prodDef = productStore.getProduct()
     self.assertEqual(prodDef.getProductDescription(), 'More foo')
     # Update the product definition, and make sure save will persist it
     prodDef.setProductDescription("Even more foo")
     productStore.save(prodDef)
     prodDef = productStore.getProduct()
     self.assertEqual(prodDef.getProductDescription(), 'Even more foo')
Beispiel #4
0
    def testCore(self):
        handle = self.getRbuildHandle()
        productClass = mock.MockObject(stableReturnValues=True)
        stage = mock.MockObject(label='localhost@rpl:1')
        productClass().getStage._mock.setReturn(stage, 'foo')
        productClass._mock.popCall()
        self.mock(proddef, 'ProductDefinition', productClass)
        os.chdir(self.workDir)
        util.mkdirChain('foo/.rbuild/product-definition')
        self.writeFile('foo/.rbuild/product-definition/product-definition.xml',
                       '')

        p = dirstore.CheckoutProductStore(handle, 'foo')
        err = self.assertRaises(errors.RbuildError, p.getActiveStageName)
        self.assertEquals(str(err), 'No current stage (setActiveStageName)')
        mock.mock(dirstore.CheckoutProductStore, 'checkStageIsValid')
        p.setActiveStageName('foo')
        assert(p.getActiveStageName() == 'foo')

        mock.mockMethod(p._getSourceTroveVersion,
            returnValue='cny.tv@ns:1/2-3')

        proddefObj = p.getProduct()
        _, kw = productClass._mock.popCall()
        kw = dict(kw)
        kw.pop('fromStream')

        configPath = self.workDir + '/foo/.rbuild/product-definition/rmakerc'
        self.assertEquals(p.getRmakeConfigPath(), configPath)
        mock.mockMethod(handle.facade.conary.updateCheckout)
        p.update()
        rbuildDir = p.getProductDefinitionDirectory()
        platformDir = p.getPlatformDefinitionDirectory()
        assert(platformDir == self.workDir + '/foo/.rbuild/platform-definition')
        handle.facade.conary.updateCheckout._mock.assertCalled(rbuildDir)

        proddefObj.getStages._mock.setDefaultReturn(
                                                [mock.MockObject(name='a'),
                                                 mock.MockObject(name='b'),
                                                 mock.MockObject(name='c')])
        stageNames = [x for x in p.iterStageNames()]
        self.assertEquals(stageNames, ['a', 'b', 'c'])
Beispiel #5
0
def getHandle(dirName=None, prodDefLabel=None):
    """
        Initializes an rBuild handle object, with a product definition
        as defined by the C{dirName} parameter (which provides a
        C{dirstore.CheckoutProductStore} product store) or the
        C{prodDefLabel} parameter (which provides a more limited
        C{abstract.ProductStore} product store that is insufficient
        for many plugin operations).  If no parameter is specified,
        a  C{dirstore.CheckoutProductStore} product store is provided
        based on the current directory.

        @param dirName: (None) directory for product store
        @param prodDefLabel: (None) label for product definition.
        @return: C{handle} instance
        """
    cfg = handle.RbuildHandle.configClass(readConfigFiles=True)

    if prodDefLabel:
        productStore = None
    else:
        # note that if dirName is None, this defaults to current directory
        productStore = dirstore.CheckoutProductStore(baseDirectory=dirName)

    plugins = pluginloader.getPlugins([], cfg.pluginDirs)
    h = handle.RbuildHandle(cfg=cfg,
                            pluginManager=plugins,
                            productStore=productStore)

    if prodDefLabel:
        productStore = abstract.ProductStore()
        product = productStore.getProduct()
        client = h.facade.conary._getConaryClient()
        stream, _ = product._getStreamFromRepository(client, prodDefLabel)
        stream.seek(0)
        product.parseStream(stream)

    return h
Beispiel #6
0
    def testEditProductDefinition(self):
        proddef = self.newProductDefinition()
        projDir = os.path.join(self.workDir, 'myproject')
        prodDefDir = os.path.join(projDir, '.rbuild/product-definition')
        prodDefPath = os.path.join(prodDefDir, 'product-definition.xml')
        os.makedirs(prodDefDir)
        proddef.serialize(file(prodDefPath, "w"))

        productStore = dirstore.CheckoutProductStore(baseDirectory=projDir)
        handle = self.getRbuildHandle(productStore=productStore)
        mock.mock(handle.facade, 'conary')
        facade = handle.facade.conary

        message = "commit message"

        # Return a consistent temp file
        tmpf = handle.Edit._makeTemporaryFile()
        mock.mockMethod(handle.Edit._makeTemporaryFile, tmpf)

        class MockMethod(object):
            def __init__(self):
                self.retval = None
                self.callList = []
                self.realFunction = None
                self._idx = 0

            def __call__(self, *args, **kwargs):
                self.callList.append((args, kwargs))
                if self.realFunction is None:
                    return self.retval
                if isinstance(self.realFunction, list):
                    func = self.realFunction[self._idx]
                    self._idx += 1
                else:
                    func = self.realFunction
                return func(*args, **kwargs)

            def reset(self):
                self._idx = 0
                del self.callList[:]

        invEditor = MockMethod()
        self.mock(handle.Edit, '_invokeEditor', invEditor)

        # Simulate edit error
        invEditor.retval = 1
        self.assertEquals(handle.Edit.editProductDefinition(message), 1)

        tmpf.seek(0)
        tmpf.truncate()
        invEditor.reset()

        # Simulate no change (mtime of file doesn't change)
        invEditor.retval = 0
        self.assertEquals(handle.Edit.editProductDefinition(message), 0)

        tmpf.seek(0)
        tmpf.truncate()
        invEditor.reset()

        def _changedProdDef(stream):
            # Change the proddef
            prod = self.newProductDefinition()
            prod.setProductName('awesome name, changed')
            stream.seek(0)
            stream.truncate()
            prod.serialize(stream)
            return 0

        invEditor.realFunction = _changedProdDef
        self.assertEquals(handle.Edit.editProductDefinition(message), 0)
        self.assertEquals(len(invEditor.callList), 1)

        facade.commit._mock.assertCalled(prodDefDir, message=message)

        # Test some of the more possible errors

        tmpf.seek(0)
        tmpf.truncate()
        invEditor.reset()

        def _invalidXml(stream):
            stream.seek(0)
            stream.truncate()
            stream.write("<invalid xml")
            stream.flush()
            return 0

        invEditor.realFunction = _invalidXml

        uiInput = mock.mockMethod(handle.ui.input)
        uiInput._mock.setReturn('n', 'Do you want to retry? (Y/n) ')
        self.assertEquals(handle.Edit.editProductDefinition(message), 3)

        # Invalid xml first, then correct one
        tmpf.seek(0)
        tmpf.truncate()
        invEditor.reset()
        invEditor.realFunction = [_invalidXml, _invalidXml, _changedProdDef]
        uiInput._mock.setReturn('y', 'Do you want to retry? (Y/n) ')
        self.assertEquals(handle.Edit.editProductDefinition(message), 0)
        facade.commit._mock.assertCalled(prodDefDir, message=message)

        def _xmlNoNamespace(stream):
            stream.seek(0)
            stream.truncate()
            stream.write("<productDefinition/>")
            stream.flush()
            return 0

        tmpf.seek(0)
        tmpf.truncate()
        invEditor.reset()
        invEditor.realFunction = _xmlNoNamespace
        uiInput._mock.setReturn('n', 'Do you want to retry? (Y/n) ')
        self.assertEquals(handle.Edit.editProductDefinition(message), 1)

        def _xmlNamespacedNoVersion(stream):
            stream.seek(0)
            stream.truncate()
            stream.write("<productDefinition xmlns='http://dummy'/>")
            stream.flush()
            return 0

        tmpf.seek(0)
        tmpf.truncate()
        invEditor.reset()
        invEditor.realFunction = _xmlNamespacedNoVersion
        uiInput._mock.setReturn('n', 'Do you want to retry? (Y/n) ')
        self.assertEquals(handle.Edit.editProductDefinition(message), 2)
Beispiel #7
0
    def printDirectoryStatus(self,
                             directory,
                             verbosity=DEFAULT,
                             product=False,
                             local=True,
                             repository=True):
        #pylint: disable-msg=R0913,R0914
        # conflating arguments would just make this harder to understand
        # not amenable to refactoring to split up local variables
        '''
        Prints status of various things based on the current
        working directory.  The default output displays what
        packages and files have changed, but not the contents
        of the changes to the files.
        @param directory: name of directory to print status of
        @param verbosity: level of change to display
        @param product: Display changes to product similar to packages
        @param local: Display local filesystem changes not yet committed
        @param repository: Display changes committed to the repository
        but not yet applied locally

        At least one of C{local} and C{repository} must be set.
        '''

        if not local and not repository:
            raise ValueError(
                'At least one of local and repository must be True')

        productStore = dirstore.CheckoutProductStore(self.handle, directory)
        proddefDir = productStore.getProductDefinitionDirectory()
        if product:
            self._printOneDirectoryStatus(proddefDir,
                                          'Product Definition',
                                          verbosity,
                                          proddef=True,
                                          local=local,
                                          repository=repository)

        baseDir = productStore.getBaseDirectory()
        baseDirLen = len(baseDir)

        def stripPrefix(dirName):
            # Get the name relative to the checkout, not the current
            # working directory.  This is like most version control
            # systems -- see "hg stat" for one of many examples
            if dirName == baseDir:
                # no empty baseDir
                return baseDir
            if dirName.startswith(baseDir):
                # make relative to baseDir
                return dirName[baseDirLen + 1:]
            return dirName

        pendingAnnounce = self._printOneDirectoryStatus(directory,
                                                        stripPrefix(directory),
                                                        verbosity,
                                                        '',
                                                        local=local,
                                                        repository=repository)

        for dirpath, dirnames, _ in os.walk(directory):
            for oneDir in sorted(dirnames):
                if oneDir == '.rbuild':
                    # product store already handled separately if
                    # appropriate, stop from recursing
                    dirnames.remove('.rbuild')
                    continue
                dirName = os.path.join(dirpath, oneDir)
                pendingAnnounce = self._printOneDirectoryStatus(
                    dirName,
                    stripPrefix(dirName),
                    verbosity,
                    pendingAnnounce,
                    local=local,
                    repository=repository)
Beispiel #8
0
    def createProductDirectory(self, version, productDir=None):
        handle = self.handle
        if productDir is None:
            productDir = tempfile.mkdtemp(dir=os.getcwd())
            tempDir = productDir
        else:
            tempDir = None

        try:
            util.mkdirChain(productDir + '/.rbuild')
            os.mkdir(productDir + '/.rbuild/tracebacks', 0700)

            targetDir = productDir + '/.rbuild/product-definition'
            handle.facade.conary.checkout('product-definition', version,
                                          targetDir=targetDir)
            productStore = dirstore.CheckoutProductStore(handle, productDir)
            product = productStore.getProduct()
            if tempDir:
                productDir = '%s-%s' % (product.getProductShortname(),
                                        product.getProductVersion())
                if os.path.exists(productDir):
                    raise errors.PluginError(
                                    'Directory %s already exists.' % productDir)
                os.rename(tempDir, productDir)
                tempDir = None
                targetDir = productDir + '/.rbuild/product-definition'
        finally:
            if tempDir:
                util.rmtree(tempDir)

        logRoot = productDir + '/.rbuild'
        handle.ui.resetLogFile(logRoot)
        # This redundant log entry is the first entry in the new log,
        # corresponding to a similar entry in the toplevel log
        handle.ui._log('rBuild %s initialized %s-%s in %s',
            rbuild.constants.VERSION,
            product.getProductShortname(),
            product.getProductVersion(),
            productDir)

        stages = product.getStages()
        for stage in stages:
            stageDir = productDir + '/' + stage.name
            os.mkdir(stageDir)
            open(stageDir + '/.stage', 'w').write(stage.name + '\n')
            stageLabel = product.getLabelForStage(stage.name)
            open(stageDir + '/conaryrc', 'w').write(
                '# This file may be automatically overwritten by rbuild\n'
                'buildLabel %s\n'
                'installLabelPath %s\n' %(stageLabel, stageLabel))
        oldumask = os.umask(077)
        try:
            handle.getConfig().writeCheckoutFile(
                productDir + '/.rbuild/rbuildrc')
        finally:
            os.umask(oldumask)
        handle.ui.info('Created checkout for %s at %s', 
                        product.getProductDefinitionLabel(),
                        productDir)
        # get the versions that point to the real checkout now
        handle.productStore = dirstore.CheckoutProductStore(None, productDir)
        handle.product = handle.productStore.getProduct()
        return handle.productStore
Beispiel #9
0
    def __init__(self,
                 cfg=None,
                 pluginManager=None,
                 productStore=None,
                 userInterface=None,
                 logRoot=None):
        super(RbuildHandle, self).__init__()

        self.product = None
        if cfg is None:
            cfg = self.configClass(readConfigFiles=True)

        if pluginManager is None:
            pluginManager = pluginloader.getPlugins([], cfg.pluginDirs)

        # Unknown sections are initially stashed aside by the config object
        # After the plugins are loaded we try to process their data

        pluginManager.addPluginConfigurationClasses(cfg)
        cfg.setIgnoreErrors(False)
        cfg.processPluginSections()
        pluginManager.setPluginConfigurations(cfg)

        self._cfg = cfg
        self._pluginManager = pluginManager
        for plugin in pluginManager.plugins:
            pluginName = plugin.__class__.__name__
            self[pluginName] = plugin
            plugin.setHandle(self)

        # Provide access to facades
        self.facade = _PluginProxy(self._getFacades())

        # Provide the command manager as if it were a plugin
        self['Commands'] = CommandManager()

        if userInterface is not None:
            self.ui = userInterface
        else:
            if logRoot is not False:
                if not logRoot:
                    logRoot = errors._findCheckoutRoot()
                    if logRoot:
                        logRoot += '/.rbuild'
            #pylint: disable-msg=C0103
            # this name is intentional
            self.ui = ui.UserInterface(self._cfg, logRoot=logRoot)

        if productStore is None:
            # default product store is directory-based
            # Note: will still be None for some cases, such as rbuild init
            proddir = dirstore.getDefaultProductDirectory()
            if proddir is not None:
                productStore = dirstore.CheckoutProductStore(None, proddir)
        self.productStore = productStore

        if productStore:
            self.product = productStore.getProduct()

            if hasattr(productStore, 'getRbuildConfigPath'):
                rBuildConfigPath = productStore.getRbuildConfigPath()
                if rBuildConfigPath is not None:
                    self._cfg.read(rBuildConfigPath, exception=False)
            elif hasattr(productStore, 'getRbuildConfigData'):
                RbuildConfigData = productStore.getRbuildConfigData()
                if RbuildConfigData is not None:
                    self._cfg.readObject('INTERNAL', RbuildConfigData)