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='******'))
Example #2
0
    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 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)
Example #6
0
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
Example #7
0
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
Example #8
0
    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)
Example #9
0
    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()
Example #10
0
    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()
Example #11
0
 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())
Example #12
0
 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 products(self):
        """See `ITranslationGroup`."""
        # Avoid circular imports.
        from lp.registry.model.product import Product

        return Product.selectBy(translationgroup=self.id, active=True)
 def getProduct(self, name):
     return Product.selectOneBy(project=self, name=name)
Example #17
0
 def getProduct(self, name):
     return Product.selectOneBy(projectgroup=self, name=name)
    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)