def test_branch_renaming(self): """ Branches should be able to be renamed in the Launchpad webapp, and those renames should be immediately reflected in subsequent SFTP connections. Changing the owner or product, or changing the name of the owner, product or branch can change the URL of the branch, so we change everything in this test. """ # Push the local branch to the server remote_url = self.getTransportURL('~testuser/+junk/test-branch') self.push(self.local_branch_path, remote_url) # Rename owner, product and branch in the database ZopelessAppServerLayer.txn.begin() branch = self.getDatabaseBranch('testuser', None, 'test-branch') branch.owner.name = 'renamed-user' branch.setTarget(user=branch.owner, project=Product.byName('firefox')) branch.name = 'renamed-branch' ZopelessAppServerLayer.txn.commit() # Check that it's not at the old location. self.assertNotBranch( self.getTransportURL( '~testuser/+junk/test-branch', username='******')) # Check that it *is* at the new location. self.assertBranchesMatch( self.local_branch_path, self.getTransportURL( '~renamed-user/firefox/renamed-branch', username='******'))
def _updateMaloneStatistics(self, ztm): self.update('bug_count', Bug.select().count()) ztm.commit() self.update('bugtask_count', BugTask.select().count()) ztm.commit() self.update( 'products_using_malone', Product.selectBy(official_malone=True).count()) ztm.commit() cur = cursor() cur.execute( "SELECT COUNT(DISTINCT product) + COUNT(DISTINCT distribution) " "FROM BugTask") self.update("projects_with_bugs", cur.fetchone()[0] or 0) ztm.commit() cur = cursor() cur.execute( "SELECT COUNT(*) FROM (SELECT COUNT(distinct product) + " " COUNT(distinct distribution) " " AS places " " FROM BugTask GROUP BY bug) " " AS temp WHERE places > 1") self.update("shared_bug_count", cur.fetchone()[0] or 0) ztm.commit()
def getDatabaseBranch(self, personName, productName, branchName): """Look up and return the specified branch from the database.""" owner = Person.byName(personName) if productName is None: product = None else: product = Product.selectOneBy(name=productName) namespace = get_branch_namespace(owner, product) return namespace.getByName(branchName)
def test_push_to_new_short_branch_alias(self): # We can also push branches to URLs like /+branch/firefox # Hack 'firefox' so we have permission to do this. ZopelessAppServerLayer.txn.begin() firefox = Product.selectOneBy(name='firefox') testuser = Person.selectOneBy(name='testuser') firefox.development_focus.owner = testuser ZopelessAppServerLayer.txn.commit() remote_url = self.getTransportURL('+branch/firefox') self.push(self.local_branch_path, remote_url) self.assertBranchesMatch(self.local_branch_path, remote_url)
def _get_locals(): if len(sys.argv) > 1: dbuser = sys.argv[1] else: dbuser = None dbconfig.override(dbuser=dbuser) execute_zcml_for_scripts() readline.parse_and_bind('tab: complete') # Mimic the real interactive interpreter's loading of any # $PYTHONSTARTUP file. startup = os.environ.get('PYTHONSTARTUP') if startup: execfile(startup) store = IMasterStore(Person) if dbuser == 'launchpad': # Create a few variables "in case they come in handy." # Do we really use these? Are they worth carrying around? d = Distribution.get(1) p = Person.get(1) ds = DistroSeries.get(1) prod = Product.get(1) proj = ProjectGroup.get(1) b2 = Bug.get(2) b1 = Bug.get(1) s = Specification.get(1) q = Question.get(1) # Silence unused name warnings d, p, ds, prod, proj, b2, b1, s, q # Having a factory instance is handy. factory = LaunchpadObjectFactory() def browser_open(obj, *args, **kwargs): """Open a (possibly newly-created) object's view in a web browser. Accepts the same parameters as canonical_url. Performs a commit before invoking the browser, so "browser_open(factory.makeFoo())" works. """ transaction.commit() webbrowser.open(canonical_url(obj, *args, **kwargs)) # Silence unused name warnings factory, store res = {} res.update(locals()) res.update(globals()) del res['_get_locals'] return res
def makeDatabaseBranch(self, owner_name, product_name, branch_name, branch_type=BranchType.HOSTED): """Create a new branch in the database.""" owner = Person.selectOneBy(name=owner_name) if product_name == '+junk': product = None else: product = Product.selectOneBy(name=product_name) if branch_type == BranchType.MIRRORED: url = 'http://example.com' else: url = None namespace = get_branch_namespace(owner, product) return namespace.createBranch( branch_type=branch_type, name=branch_name, registrant=owner, url=url)
def _updateRosettaStatistics(self, ztm): self.update( 'products_using_rosetta', Product.selectBy( translations_usage=ServiceUsage.LAUNCHPAD).count()) self.update('potemplate_count', POTemplate.select().count()) ztm.commit() self.update('pofile_count', POFile.select().count()) ztm.commit() self.update('pomsgid_count', POMsgID.select().count()) ztm.commit() self.update('language_count', Language.select( "POFile.language=Language.id", clauseTables=['POFile'], distinct=True).count()) ztm.commit() cur = cursor() cur.execute( "SELECT COUNT(DISTINCT submitter) FROM TranslationMessage") self.update('translator_count', cur.fetchone()[0] or 0) ztm.commit() cur = cursor() cur.execute(""" SELECT COUNT(DISTINCT submitter) FROM TranslationMessage WHERE origin=2 """) self.update('rosetta_translator_count', cur.fetchone()[0] or 0) ztm.commit() cur = cursor() cur.execute(""" SELECT COUNT(DISTINCT product) FROM ProductSeries,POTemplate WHERE ProductSeries.id = POTemplate.productseries """) self.update('products_with_potemplates', cur.fetchone()[0] or 0) ztm.commit()
def _updateRegistryStatistics(self, ztm): self.update('active_products', Product.select("active IS TRUE", distinct=True).count()) self.update( 'products_with_translations', Product.select(''' POTemplate.productseries = ProductSeries.id AND Product.id = ProductSeries.product AND Product.active = TRUE ''', clauseTables=['ProductSeries', 'POTemplate'], distinct=True).count()) self.update( 'products_with_blueprints', Product.select( "Specification.product=Product.id AND Product.active IS TRUE", distinct=True, clauseTables=['Specification']).count()) self.update( 'products_with_branches', Product.select( "Branch.product=Product.id AND Product.active IS TRUE", distinct=True, clauseTables=['Branch']).count()) self.update( 'products_with_bugs', Product.select( "BugTask.product=Product.id AND Product.active IS TRUE", distinct=True, clauseTables=['BugTask']).count()) self.update( 'products_with_questions', Product.select( "Question.product=Product.id AND Product.active IS TRUE", distinct=True, clauseTables=['Question']).count()) self.update( 'reviewed_products', Product.selectBy(project_reviewed=True, active=True).count())
def _updateRegistryStatistics(self, ztm): self.update( 'active_products', Product.select("active IS TRUE", distinct=True).count()) self.update( 'products_with_translations', Product.select(''' POTemplate.productseries = ProductSeries.id AND Product.id = ProductSeries.product AND Product.active = TRUE ''', clauseTables=['ProductSeries', 'POTemplate'], distinct=True).count()) self.update( 'products_with_blueprints', Product.select( "Specification.product=Product.id AND Product.active IS TRUE", distinct=True, clauseTables=['Specification']).count()) self.update( 'products_with_branches', Product.select( "Branch.product=Product.id AND Product.active IS TRUE", distinct=True, clauseTables=['Branch']).count()) self.update( 'products_with_bugs', Product.select( "BugTask.product=Product.id AND Product.active IS TRUE", distinct=True, clauseTables=['BugTask']).count()) self.update( 'products_with_questions', Product.select( "Question.product=Product.id AND Product.active IS TRUE", distinct=True, clauseTables=['Question']).count()) self.update( 'reviewed_products', Product.selectBy(project_reviewed=True, active=True).count())
def products(self): """See `ITranslationGroup`.""" # Avoid circular imports. from lp.registry.model.product import Product return Product.selectBy(translationgroup=self.id, active=True)
def getMostTranslatedPillars(self, limit=50): """See `ITranslationsOverview`.""" # XXX Abel Deuring 2012-10-26 bug=1071751 # The expression product.information_type IS NULL can be # removed once we have the DB constraint # "Product.information_type IS NULL". query = """ SELECT LOWER(COALESCE(product_name, distro_name)) AS name, product_id, distro_id, LN(total_karma)/LN(2) AS karma FROM ( SELECT product.displayname AS product_name, product.id AS product_id, distribution.displayname AS distro_name, distribution.id AS distro_id, SUM(karmavalue) AS total_karma FROM karmacache LEFT JOIN product ON product=product.id LEFT JOIN distribution ON distribution=distribution.id WHERE category=3 AND (product IS NOT NULL OR distribution IS NOT NULL) AND (product.translations_usage = %s AND (product.information_type = %s OR product.information_type IS NULL) OR distribution.translations_usage = %s) GROUP BY product.displayname, product.id, distribution.displayname, distribution.id HAVING SUM(karmavalue) > 0 ORDER BY total_karma DESC LIMIT %s) AS something ORDER BY name""" % sqlvalues(ServiceUsage.LAUNCHPAD, InformationType.PUBLIC, ServiceUsage.LAUNCHPAD, limit) cur = cursor() cur.execute(query) all_pillars = [] # Get minimum and maximum relative karma value to be able to normalize # them to appropriate font size values. minimum = None maximum = None for (name, product_id, distro_id, relative_karma) in cur.fetchall(): if minimum is None or relative_karma < minimum: minimum = relative_karma if maximum is None or relative_karma > maximum: maximum = relative_karma if product_id is not None: pillar = Product.get(product_id) elif distro_id is not None: pillar = Distribution.get(distro_id) else: raise MalformedKarmaCacheData( "Lots of karma for non-existing product or distribution.") all_pillars.append((pillar, relative_karma)) # Normalize the relative karma values between MINIMUM_SIZE and # MAXIMUM_SIZE. return self._normalizeSizes(all_pillars, minimum, maximum)
def getProduct(self, name): return Product.selectOneBy(project=self, name=name)
def getProduct(self, name): return Product.selectOneBy(projectgroup=self, name=name)