Rev 2259: Move info branch statistics gathering into the repository to allow smart server optimisation (Robert Collins). in http://bazaar.launchpad.net/~bzr/bzr/bzr.dev.hpss.api.changes

Robert Collins robertc at robertcollins.net
Sat Feb 3 10:02:25 GMT 2007


------------------------------------------------------------
revno: 2259
revision-id: robertc at robertcollins.net-20070203100211-bf9qwy73gh40nszi
parent: pqm at pqm.ubuntu.com-20070202204950-910381483d737306
committer: Robert Collins <robertc at robertcollins.net>
branch nick: hpss.api.changes
timestamp: Sat 2007-02-03 21:02:11 +1100
message:
  Move info branch statistics gathering into the repository to allow smart server optimisation (Robert Collins).
added:
  bzrlib/tests/repository_implementations/test_statistics.py test_statistics.py-20070203082432-6738e8fl0mm7ikre-1
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/branch.py               branch.py-20050309040759-e4baf4e0d046576e
  bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
  bzrlib/info.py                 info.py-20050323235939-6bbfe7d9700b0b9b
  bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
  bzrlib/tests/repository_implementations/__init__.py __init__.py-20060131092037-9564957a7d4a841b
=== added file 'bzrlib/tests/repository_implementations/test_statistics.py'
--- a/bzrlib/tests/repository_implementations/test_statistics.py	1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/repository_implementations/test_statistics.py	2007-02-03 10:02:11 +0000
@@ -0,0 +1,50 @@
+# Copyright (C) 2007 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""Tests for repository statistic-gathering apis."""
+
+from bzrlib.tests.repository_implementations.test_repository import TestCaseWithRepository
+
+
+class TestGatherStats(TestCaseWithRepository):
+
+    def test_gather_stats(self):
+        """First smoke test covering the refactoring into the Repository api."""
+        tree = self.make_branch_and_memory_tree('.')
+        tree.lock_write()
+        tree.add('')
+        # three commits: one to be included by reference, one to be 
+        # requested, and one to be in the repository but [mostly] ignored.
+        rev1 = tree.commit('first post', committer='person 1',
+            timestamp=1170491381, timezone=0)
+        rev2 = tree.commit('second post', committer='person 2',
+            timestamp=1171491381, timezone=0)
+        rev3 = tree.commit('third post', committer='person 3',
+            timestamp=1172491381, timezone=0)
+        tree.unlock()
+        # now, in the same repository, asking for stats with/without the 
+        # committers flag generates the same date information
+        stats = tree.branch.repository.gather_stats(rev2, committers=False)
+        self.assertEqual({
+            'firstrev': (1170491381.0, 0),
+            'latestrev': (1171491381.0, 0)},
+            stats)
+        stats = tree.branch.repository.gather_stats(rev2, committers=True)
+        self.assertEqual({
+            'committers': 2,
+            'firstrev': (1170491381.0, 0),
+            'latestrev': (1171491381.0, 0)},
+            stats)

=== modified file 'NEWS'
--- a/NEWS	2007-02-02 20:30:28 +0000
+++ b/NEWS	2007-02-03 10:02:11 +0000
@@ -44,6 +44,10 @@
       other for code reuse without requiring users to perform file-renaming
       gymnastics. (Robert Collins)
 
+    * New Repository method 'gather_stats' for statistic data collection.
+      This is expected to grow to cover a number of related uses mainly
+      related to bzr info. (Robert Collins)
+
   BUGFIXES:
 
     * ``bzr annotate`` now uses dotted revnos from the viewpoint of the

=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py	2007-02-02 09:17:23 +0000
+++ b/bzrlib/branch.py	2007-02-03 10:02:11 +0000
@@ -696,7 +696,7 @@
 
     def get_format_description(self):
         """Return the short format description for this format."""
-        raise NotImplementedError(self.get_format_string)
+        raise NotImplementedError(self.get_format_description)
 
     def initialize(self, a_bzrdir):
         """Create a branch of this format in a_bzrdir."""

=== modified file 'bzrlib/errors.py'
--- a/bzrlib/errors.py	2007-01-30 11:52:30 +0000
+++ b/bzrlib/errors.py	2007-02-03 10:02:11 +0000
@@ -1677,6 +1677,7 @@
 class NoSmartMedium(BzrError):
 
     _fmt = "The transport '%(transport)s' cannot tunnel the smart protocol."
+    internal_error = True
 
     def __init__(self, transport):
         self.transport = transport

=== modified file 'bzrlib/info.py'
--- a/bzrlib/info.py	2007-02-01 14:47:47 +0000
+++ b/bzrlib/info.py	2007-02-03 10:02:11 +0000
@@ -27,7 +27,7 @@
 from bzrlib.errors import (NoWorkingTree, NotBranchError,
                            NoRepositoryPresent, NotLocalUrl)
 from bzrlib.missing import find_unmerged
-from bzrlib.symbol_versioning import (deprecated_function, 
+from bzrlib.symbol_versioning import (deprecated_function,
         zero_eight)
 
 
@@ -225,40 +225,23 @@
 
 def _show_branch_stats(branch, verbose):
     """Show statistics about a branch."""
-    repository = branch.repository
-    history = branch.revision_history()
-
+    revno, head = branch.last_revision_info()
     print
     print 'Branch history:'
-    revno = len(history)
     print '  %8d revision%s' % (revno, plural(revno))
+    stats = branch.repository.gather_stats(head, committers=verbose)
     if verbose:
-        committers = {}
-        for rev in history:
-            committers[repository.get_revision(rev).committer] = True
-        print '  %8d committer%s' % (len(committers), plural(len(committers)))
-    if revno > 0:
-        firstrev = repository.get_revision(history[0])
-        age = int((time.time() - firstrev.timestamp) / 3600 / 24)
+        committers = stats['committers']
+        print '  %8d committer%s' % (committers, plural(committers))
+    if revno:
+        timestamp, timezone = stats['firstrev']
+        age = int((time.time() - timestamp) / 3600 / 24)
         print '  %8d day%s old' % (age, plural(age))
-        print '   first revision: %s' % osutils.format_date(firstrev.timestamp,
-                                                            firstrev.timezone)
-
-        lastrev = repository.get_revision(history[-1])
-        print '  latest revision: %s' % osutils.format_date(lastrev.timestamp,
-                                                            lastrev.timezone)
-
-#     print
-#     print 'Text store:'
-#     c, t = branch.text_store.total_size()
-#     print '  %8d file texts' % c
-#     print '  %8d KiB' % (t/1024)
-
-#     print
-#     print 'Inventory store:'
-#     c, t = branch.inventory_store.total_size()
-#     print '  %8d inventories' % c
-#     print '  %8d KiB' % (t/1024)
+        print '   first revision: %s' % osutils.format_date(timestamp,
+            timezone)
+        timestamp, timezone = stats['latestrev']
+        print '  latest revision: %s' % osutils.format_date(timestamp,
+            timezone)
 
 
 def _show_repository_info(repository):

=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py	2007-01-26 21:56:16 +0000
+++ b/bzrlib/repository.py	2007-02-03 10:02:11 +0000
@@ -243,6 +243,45 @@
         return self.control_files.get_physical_lock_status()
 
     @needs_read_lock
+    def gather_stats(self, revid, committers=None):
+        """Gather statistics from a revision id.
+
+        :param revid: The revision id to gather statistics from.
+        :param committers: Optional parameter controlling whether to grab
+            a count of committers.
+        :return: A dictionary of statistics. Currently this contains:
+            committers: The number of committers if requested.
+            firstrev: A tuple with timestamp, timezone for the penultimate left
+                most ancestor of revid, if revid is not the NULL_REVISION.
+            latestrev: A tuple with timestamp, timezone for revid, if revid is
+                not the NULL_REVISION.
+        """
+        result = {}
+        if committers:
+            result['committers'] = 0
+        if revid == _mod_revision.NULL_REVISION:
+            return result
+        all_committers = set()
+        revisions = self.get_ancestry(revid)
+        # pop the leading None
+        revisions.pop(0)
+        first_revision = None
+        if not committers:
+            # ignore the revisions in the middle - just grab first and last
+            revisions = revisions[0], revisions[-1]
+        for revision in self.get_revisions(revisions):
+            if not first_revision:
+                first_revision = revision
+            if committers:
+                all_committers.add(revision.committer)
+        last_revision = revision
+        if committers:
+            result['committers'] = len(all_committers)
+        result['firstrev'] = first_revision.timestamp, first_revision.timezone
+        result['latestrev'] = last_revision.timestamp, last_revision.timezone
+        return result
+
+    @needs_read_lock
     def missing_revision_ids(self, other, revision_id=None):
         """Return the revision ids that other has that this does not.
         

=== modified file 'bzrlib/tests/repository_implementations/__init__.py'
--- a/bzrlib/tests/repository_implementations/__init__.py	2007-01-25 00:35:22 +0000
+++ b/bzrlib/tests/repository_implementations/__init__.py	2007-02-03 10:02:11 +0000
@@ -48,6 +48,7 @@
         'bzrlib.tests.repository_implementations.test_reconcile',
         'bzrlib.tests.repository_implementations.test_repository',
         'bzrlib.tests.repository_implementations.test_revision',
+        'bzrlib.tests.repository_implementations.test_statistics',
         ]
     all_formats = [v for (k, v) in repository.format_registry.iteritems()]
     all_formats.extend(_legacy_formats)



More information about the bazaar-commits mailing list