def getRevisionMessage(self, revision_id, revno): """Return the log message for a revision. :param revision_id: The revision-id of the revision. :param revno: The revno of the revision in the branch. :return: The log message entered for this revision. """ self.bzr_branch.lock_read() try: graph = self.bzr_branch.repository.get_graph() merged_revisions = self.getMergedRevisionIDs(revision_id, graph) authors = self.getAuthors(merged_revisions, graph) revision_set = RevisionSet() rev_authors = revision_set.acquireRevisionAuthors(authors) outf = StringIO() pretty_authors = [] for rev_author in rev_authors.values(): if rev_author.person is None: displayname = rev_author.name else: displayname = rev_author.person.unique_displayname pretty_authors.append(' %s' % displayname) if len(pretty_authors) > 0: outf.write('Merge authors:\n') pretty_authors.sort(key=lambda x: x.lower()) outf.write('\n'.join(pretty_authors[:5])) if len(pretty_authors) > 5: outf.write('...\n') outf.write('\n') bmps = self.findRelatedBMP(merged_revisions) if len(bmps) > 0: outf.write('Related merge proposals:\n') for bmp in bmps: outf.write(' %s\n' % canonical_url(bmp)) proposer = bmp.registrant outf.write(' proposed by: %s\n' % proposer.unique_displayname) for review in bmp.votes: # If comment is None, this is a request for a review, not # a completed review. if review.comment is None: continue outf.write(' review: %s - %s\n' % (review.comment.vote.title, review.reviewer.unique_displayname)) info = RevisionInfo(self.bzr_branch, revno, revision_id) lf = log_formatter('long', to_file=outf) show_log(self.bzr_branch, lf, start_revision=info, end_revision=info, verbose=True) finally: self.bzr_branch.unlock() return outf.getvalue()
def test_revisions_for_public_branch_marked_public(self): # If the branch is public, then the revisions in the cache will be # marked public too. branch = self.factory.makeAnyBranch() revision = self.factory.makeRevision() branch.createBranchRevision(1, revision) RevisionSet.updateRevisionCacheForBranch(branch) [cached] = self._getRevisionCache() self.assertFalse(branch.private) self.assertFalse(cached.private)
def test_adds_revisions(self): # A branch with revisions should add the new revisions. branch = self.factory.makeAnyBranch() revision = self.factory.makeRevision() branch.createBranchRevision(1, revision) RevisionSet.updateRevisionCacheForBranch(branch) [cached] = self._getRevisionCache() self.assertEqual(cached.revision, revision) self.assertEqual(cached.revision_author, revision.revision_author) self.assertEqual(cached.revision_date, revision.revision_date)
def test_package_branch_revisions(self): # The revision cache stores the distroseries and sourcepackagename for # package branches. branch = self.factory.makePackageBranch() revision = self.factory.makeRevision() branch.createBranchRevision(1, revision) RevisionSet.updateRevisionCacheForBranch(branch) [cached] = self._getRevisionCache() self.assertIs(None, cached.product) self.assertEqual(branch.distroseries, cached.distroseries) self.assertEqual(branch.sourcepackagename, cached.sourcepackagename)
def test_personal_branch_revisions(self): # If the branch is a personal branch, the revision cache stores NULL # for the product, distroseries and sourcepackagename. branch = self.factory.makePersonalBranch() revision = self.factory.makeRevision() branch.createBranchRevision(1, revision) RevisionSet.updateRevisionCacheForBranch(branch) [cached] = self._getRevisionCache() self.assertIs(None, cached.product) self.assertIs(None, cached.distroseries) self.assertIs(None, cached.sourcepackagename)
def test_revisions_for_private_branch_marked_private(self): # If the branch is private, then the revisions in the cache will be # marked private too. branch = self.factory.makeAnyBranch( information_type=InformationType.USERDATA) revision = self.factory.makeRevision() branch.createBranchRevision(1, revision) RevisionSet.updateRevisionCacheForBranch(branch) [cached] = self._getRevisionCache() self.assertTrue(branch.private) self.assertTrue(cached.private)
def test_product_branch_revisions(self): # The revision cache knows the product for revisions in product # branches. branch = self.factory.makeProductBranch() revision = self.factory.makeRevision() branch.createBranchRevision(1, revision) RevisionSet.updateRevisionCacheForBranch(branch) [cached] = self._getRevisionCache() self.assertEqual(cached.product, branch.product) self.assertIs(None, cached.distroseries) self.assertIs(None, cached.sourcepackagename)
def test_old_revisions_removed(self): # Revisions older than 30 days are removed. date_generator = time_counter(datetime.now(pytz.UTC) - timedelta(days=33), delta=timedelta(days=2)) for i in range(4): revision = self.factory.makeRevision( revision_date=date_generator.next()) cache = RevisionCache(revision) self.store.add(cache) RevisionSet.pruneRevisionCache(5) self.assertEqual(2, len(self._getRevisionCache()))
def test_old_revisions_removed(self): # Revisions older than 30 days are removed. date_generator = time_counter( datetime.now(pytz.UTC) - timedelta(days=33), delta=timedelta(days=2)) for i in range(4): revision = self.factory.makeRevision( revision_date=date_generator.next()) cache = RevisionCache(revision) self.store.add(cache) RevisionSet.pruneRevisionCache(5) self.assertEqual(2, len(self._getRevisionCache()))
def test_pruning_limit(self): # The prune will only remove at most the parameter rows. date_generator = time_counter(datetime.now(pytz.UTC) - timedelta(days=33), delta=timedelta(days=2)) for i in range(4): revision = self.factory.makeRevision( revision_date=date_generator.next()) cache = RevisionCache(revision) self.store.add(cache) RevisionSet.pruneRevisionCache(1) self.assertEqual(3, len(self._getRevisionCache()))
def test_pruning_limit(self): # The prune will only remove at most the parameter rows. date_generator = time_counter( datetime.now(pytz.UTC) - timedelta(days=33), delta=timedelta(days=2)) for i in range(4): revision = self.factory.makeRevision( revision_date=date_generator.next()) cache = RevisionCache(revision) self.store.add(cache) RevisionSet.pruneRevisionCache(1) self.assertEqual(3, len(self._getRevisionCache()))
def test_email_extracted_from_name_alternate(self): # Check that a valid email address is extracted from the name. name = '[email protected] (Harry Potter)' author = RevisionSet()._createRevisionAuthor(name) self.assertEqual(name, author.name) self.assertEqual('*****@*****.**', author.email) self.assertEqual(None, author.person)
def test_bad_email_not_set(self): # Check that a name that doesn't have an email address, doesn't set # one. name = 'Harry Potter' author = RevisionSet()._createRevisionAuthor(name) self.assertEqual(name, author.name) self.assertEqual(None, author.email) self.assertEqual(None, author.person)
def test_existing_private_revisions_with_public_branch(self): # If a revision is in both public and private branches, there is a # revision cache row for both public and private. private_branch = self.factory.makeAnyBranch( information_type=InformationType.USERDATA) public_branch = self.factory.makeAnyBranch() revision = self.factory.makeRevision() private_branch.createBranchRevision(1, revision) RevisionSet.updateRevisionCacheForBranch(private_branch) public_branch.createBranchRevision(1, revision) RevisionSet.updateRevisionCacheForBranch(public_branch) [rev1, rev2] = self._getRevisionCache() # Both revisions point to the same underlying revision. self.assertEqual(rev1.revision, revision) self.assertEqual(rev2.revision, revision) # But the privacy flags are different. self.assertNotEqual(rev1.private, rev2.private)
def setUp(self): # Create a revision author that doesn't have a user yet. super(TestNewlyValidatedEmailsLinkRevisionAuthors, self).setUp() with dbuser("branchscanner"): self.author = RevisionSet()._createRevisionAuthor( '"Harry Potter" <*****@*****.**>') # Reget the revision author as we have crossed a transaction boundary. self.author = RevisionAuthor.byName(self.author.name)
def test_new_future_revision_date(self): # A revision with a future date gets the revision date set to # date_created. now = datetime.now(pytz.UTC) future_date = now + timedelta(days=1) revision = RevisionSet().new('rev_id', 'log body', future_date, 'author', [], {}) self.assertEqual(revision.date_created, revision.revision_date) self.assertTrue(revision.revision_date <= now)
def test_old_revisions_not_added(self): # Revisions older than the 30 day epoch are not added to the cache. # Start 33 days ago. epoch = datetime.now(pytz.UTC) - timedelta(days=30) date_generator = time_counter( epoch - timedelta(days=3), delta=timedelta(days=2)) # And add 4 revisions at 33, 31, 29, and 27 days ago branch = self.factory.makeAnyBranch() self.factory.makeRevisionsForBranch( branch, count=4, date_generator=date_generator) RevisionSet.updateRevisionCacheForBranch(branch) cached = self._getRevisionCache() # Only two revisions are within the 30 day cutoff. self.assertEqual(2, len(cached)) # And both the revisions stored are a date create after the epoch. for rev in cached: self.assertTrue(rev.revision_date > epoch)
def test_new_revisions_added(self): # If there are already revisions in the cache for the branch, updating # the branch again will only add the new revisions. date_generator = time_counter( datetime.now(pytz.UTC) - timedelta(days=29), delta=timedelta(days=1)) # Initially add in 4 revisions. branch = self.factory.makeAnyBranch() self.factory.makeRevisionsForBranch( branch, count=4, date_generator=date_generator) RevisionSet.updateRevisionCacheForBranch(branch) # Now add two more revisions. self.factory.makeRevisionsForBranch( branch, count=2, date_generator=date_generator) RevisionSet.updateRevisionCacheForBranch(branch) # There will be only six revisions cached. cached = self._getRevisionCache() self.assertEqual(6, len(cached))
def test_old_revisions_not_added(self): # Revisions older than the 30 day epoch are not added to the cache. # Start 33 days ago. epoch = datetime.now(pytz.UTC) - timedelta(days=30) date_generator = time_counter(epoch - timedelta(days=3), delta=timedelta(days=2)) # And add 4 revisions at 33, 31, 29, and 27 days ago branch = self.factory.makeAnyBranch() self.factory.makeRevisionsForBranch(branch, count=4, date_generator=date_generator) RevisionSet.updateRevisionCacheForBranch(branch) cached = self._getRevisionCache() # Only two revisions are within the 30 day cutoff. self.assertEqual(2, len(cached)) # And both the revisions stored are a date create after the epoch. for rev in cached: self.assertTrue(rev.revision_date > epoch)
def test_new_revisions_added(self): # If there are already revisions in the cache for the branch, updating # the branch again will only add the new revisions. date_generator = time_counter(datetime.now(pytz.UTC) - timedelta(days=29), delta=timedelta(days=1)) # Initially add in 4 revisions. branch = self.factory.makeAnyBranch() self.factory.makeRevisionsForBranch(branch, count=4, date_generator=date_generator) RevisionSet.updateRevisionCacheForBranch(branch) # Now add two more revisions. self.factory.makeRevisionsForBranch(branch, count=2, date_generator=date_generator) RevisionSet.updateRevisionCacheForBranch(branch) # There will be only six revisions cached. cached = self._getRevisionCache() self.assertEqual(6, len(cached))
def test_noKarmaForJunk(self): # Revisions only associated with junk branches don't get karma, # and Lp records that karma_allocated was done. author = self.factory.makePerson() rev = self.factory.makeRevision(author=author.preferredemail.email) branch = self.factory.makePersonalBranch() branch.createBranchRevision(1, rev) self.assertTrue(rev.karma_allocated) self.assertEqual(0, rev.revision_author.person.karma) # Nor is this revision identified as needing karma allocated. self.assertEqual([], list(RevisionSet.getRevisionsNeedingKarmaAllocated()))
def testTeamRevisions(self): # Revisions owned by all members of a team are returned. team = self.factory.makeTeam(self.author) team_member = self.factory.makePerson() team.addMember(team_member, self.author) rev1 = self._makeRevision() rev2 = self._makeRevision(team_member) rev3 = self._makeRevision(self.factory.makePerson()) branch = self.factory.makeAnyBranch() self._addRevisionsToBranch(branch, rev1, rev2, rev3) self.assertEqual([rev2, rev1], list(RevisionSet.getPublicRevisionsForPerson(team)))
def test_noKarmaForJunk(self): # Revisions only associated with junk branches don't get karma, # and Lp records that karma_allocated was done. author = self.factory.makePerson() rev = self.factory.makeRevision( author=author.preferredemail.email) branch = self.factory.makePersonalBranch() branch.createBranchRevision(1, rev) self.assertTrue(rev.karma_allocated) self.assertEqual(0, rev.revision_author.person.karma) # Nor is this revision identified as needing karma allocated. self.assertEqual( [], list(RevisionSet.getRevisionsNeedingKarmaAllocated()))
def test_same_revision_multiple_targets(self): # If there are branches that have different targets that contain the # same revision, the revision appears in the revision cache once for # each different target. b1 = self.factory.makeProductBranch() b2 = self.factory.makePackageBranch() revision = self.factory.makeRevision() b1.createBranchRevision(1, revision) RevisionSet.updateRevisionCacheForBranch(b1) b2.createBranchRevision(1, revision) RevisionSet.updateRevisionCacheForBranch(b2) [rev1, rev2] = self._getRevisionCache() # Both cached revisions point to the same underlying revisions, but # for different targets. self.assertEqual(rev1.revision, revision) self.assertEqual(rev2.revision, revision) # Make rev1 be the cached revision for the product branch. if rev1.product is None: rev1, rev2 = rev2, rev1 self.assertEqual(b1.product, rev1.product) self.assertEqual(b2.distroseries, rev2.distroseries) self.assertEqual(b2.sourcepackagename, rev2.sourcepackagename)
def test_karmaNotAllocatedForKnownAuthorWithInactiveAccount(self): # If the revision author is known, but the account is not active, # don't allocate karma, and record that karma_allocated was done. author = self.factory.makePerson() rev = self.factory.makeRevision(author=author.preferredemail.email) author.setAccountStatus(AccountStatus.SUSPENDED, None, 'spammer!') branch = self.factory.makeProductBranch() branch.createBranchRevision(1, rev) self.assertTrue(rev.karma_allocated) self.assertEqual(0, rev.revision_author.person.karma) # Even though the revision author is connected to the person, since # the account status is suspended, the person is not "valid", and so # the revisions are not returned as needing karma allocated. self.assertEqual([], list(RevisionSet.getRevisionsNeedingKarmaAllocated()))
def test_karmaNotAllocatedForKnownAuthorWithInactiveAccount(self): # If the revision author is known, but the account is not active, # don't allocate karma, and record that karma_allocated was done. author = self.factory.makePerson() rev = self.factory.makeRevision( author=author.preferredemail.email) author.account.status = AccountStatus.SUSPENDED branch = self.factory.makeProductBranch() branch.createBranchRevision(1, rev) self.assertTrue(rev.karma_allocated) self.assertEqual(0, rev.revision_author.person.karma) # Even though the revision author is connected to the person, since # the account status is suspended, the person is not "valid", and so # the revisions are not returned as needing karma allocated. self.assertEqual( [], list(RevisionSet.getRevisionsNeedingKarmaAllocated()))
def test_karmaAllocatedForKnownAuthor(self): # If the revision author is known, allocate karma. author = self.factory.makePerson() rev = self.factory.makeRevision(author=author.preferredemail.email, revision_date=datetime.now(pytz.UTC) - timedelta(days=5)) branch = self.factory.makeProductBranch() branch.createBranchRevision(1, rev) self.assertTrue(rev.karma_allocated) # Get the karma event. [karma] = list( Store.of(author).find(Karma, Karma.person == author, Karma.product == branch.product)) self.assertEqual(karma.datecreated, rev.revision_date) self.assertEqual(karma.product, branch.product) # Since karma has been allocated, the revision isn't in our list. self.assertEqual([], list(RevisionSet.getRevisionsNeedingKarmaAllocated()))
def test_karmaAllocatedForKnownAuthor(self): # If the revision author is known, allocate karma. author = self.factory.makePerson() rev = self.factory.makeRevision( author=author.preferredemail.email, revision_date=datetime.now(pytz.UTC) - timedelta(days=5)) branch = self.factory.makeProductBranch() branch.createBranchRevision(1, rev) self.assertTrue(rev.karma_allocated) # Get the karma event. [karma] = list(Store.of(author).find( Karma, Karma.person == author, Karma.product == branch.product)) self.assertEqual(karma.datecreated, rev.revision_date) self.assertEqual(karma.product, branch.product) # Since karma has been allocated, the revision isn't in our list. self.assertEqual( [], list(RevisionSet.getRevisionsNeedingKarmaAllocated()))
def _createRevisionAuthor(self): switch_dbuser("branchscanner") return RevisionSet()._createRevisionAuthor( '"Harry Potter" <*****@*****.**>')
def _getRevisions(self, day_limit=30): # Returns the revisions for the person. return list(RevisionSet.getPublicRevisionsForProjectGroup( self.project, day_limit))
def _getRevisions(self, day_limit=30): # Returns the revisions for the person. return list(RevisionSet.getPublicRevisionsForPerson( self.author, day_limit))
def test_noRevisionsNeedingAllocation(self): # There are no outstanding revisions needing karma allocated. self.assertEqual([], list(RevisionSet.getRevisionsNeedingKarmaAllocated()))
def _getRecentRevisions(self, day_limit=30): # Return a list of the recent revisions and revision authors. return list(RevisionSet.getRecentRevisionsForProduct( self.product, day_limit))
def test_empty_branch(self): # A branch with no revisions should add no revisions to the cache. branch = self.factory.makeAnyBranch() RevisionSet.updateRevisionCacheForBranch(branch) self.assertEqual(0, len(self._getRevisionCache()))
def _getRevisions(self, day_limit=30): # Returns the revisions for the person. return list( RevisionSet.getPublicRevisionsForProjectGroup( self.projectgroup, day_limit))
def _getRecentRevisions(self, day_limit=30): # Return a list of the recent revisions and revision authors. return list( RevisionSet.getRecentRevisionsForProduct(self.product, day_limit))
def test_new_past_revision_date(self): # A revision created with a revision date in the past works fine. past_date = datetime(2009, 1, 1, tzinfo=pytz.UTC) revision = RevisionSet().new('rev_id', 'log body', past_date, 'author', [], {}) self.assertEqual(past_date, revision.revision_date)
def _getRevisions(self, day_limit=30): # Returns the revisions for the person. return list( RevisionSet.getPublicRevisionsForPerson(self.author, day_limit))
def test_noRevisionsNeedingAllocation(self): # There are no outstanding revisions needing karma allocated. self.assertEqual( [], list(RevisionSet.getRevisionsNeedingKarmaAllocated()))