Rev 2448: (Ian Clatworthy) Bugs #102679, #102686. Add --exclude and --randomize to 'bzr selftest' in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Tue Apr 24 04:12:10 BST 2007
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 2448
revision-id: pqm at pqm.ubuntu.com-20070424031208-9y04a1j0yx3fjte5
parent: pqm at pqm.ubuntu.com-20070423170758-qd512ltqglzfo6w9
parent: john at arbash-meinel.com-20070424024356-nffcxmkfaigudmrp
committer: Canonical.com Patch Queue Manager<pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2007-04-24 04:12:08 +0100
message:
(Ian Clatworthy) Bugs #102679, #102686. Add --exclude and --randomize to 'bzr selftest'
modified:
HACKING HACKING-20050805200004-2a5dc975d870f78c
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/commands.py bzr.py-20050309040720-d10f4714595cf8c3
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/blackbox/test_selftest.py test_selftest.py-20060123024542-01c5f1bbcb596d78
bzrlib/tests/test_selftest.py test_selftest.py-20051202044319-c110a115d8c0456a
------------------------------------------------------------
revno: 2418.4.2
merged: john at arbash-meinel.com-20070424024356-nffcxmkfaigudmrp
parent: john at arbash-meinel.com-20070413201949-ay6r5nh3bgsxfogw
parent: pqm at pqm.ubuntu.com-20070423170758-qd512ltqglzfo6w9
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: jam-integration
timestamp: Mon 2007-04-23 21:43:56 -0500
message:
[merge] bzr.dev 2447
------------------------------------------------------------
revno: 2418.4.1
merged: john at arbash-meinel.com-20070413201949-ay6r5nh3bgsxfogw
parent: pqm at pqm.ubuntu.com-20070413174100-zpfqleaf5ph9ycx4
parent: ian.clatworthy at internode.on.net-20070413004631-nkdsnpcuy8xb0x62
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: jam-integration
timestamp: Fri 2007-04-13 15:19:49 -0500
message:
(Ian Clatworthy) Bugs #102679, #102686. Add --exclude and --randomize to 'bzr selftest'
------------------------------------------------------------
revno: 2394.2.10
merged: ian.clatworthy at internode.on.net-20070413004631-nkdsnpcuy8xb0x62
parent: ian.clatworthy at internode.on.net-20070413004053-y5wr76o3512rjawk
committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
branch nick: bzr.selftest-not
timestamp: Fri 2007-04-13 10:46:31 +1000
message:
another doc fix and whitespace fixes
------------------------------------------------------------
revno: 2394.2.9
merged: ian.clatworthy at internode.on.net-20070413004053-y5wr76o3512rjawk
parent: ian.clatworthy at internode.on.net-20070413003033-k3nc1zq02qlkb8cj
committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
branch nick: bzr.selftest-not
timestamp: Fri 2007-04-13 10:40:53 +1000
message:
update NEWS and help to reflect removal of comma support
------------------------------------------------------------
revno: 2394.2.8
merged: ian.clatworthy at internode.on.net-20070413003033-k3nc1zq02qlkb8cj
parent: ian.clatworthy at internode.on.net-20070411021409-im2b7jkohfnb5boq
committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
branch nick: bzr.selftest-not
timestamp: Fri 2007-04-13 10:30:33 +1000
message:
incorporate feedback from jam
------------------------------------------------------------
revno: 2394.2.7
merged: ian.clatworthy at internode.on.net-20070411021409-im2b7jkohfnb5boq
parent: ian.clatworthy at internode.on.net-20070410142343-6bfz9k67b8tvrz6x
committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
branch nick: bzr.selftest-not
timestamp: Wed 2007-04-11 12:14:09 +1000
message:
Added whitebox tests - filter_suite_by_re and sort_suite_by_re
------------------------------------------------------------
revno: 2394.2.6
merged: ian.clatworthy at internode.on.net-20070410142343-6bfz9k67b8tvrz6x
parent: ian.clatworthy at internode.on.net-20070410090806-d9pkgwomcpbkizj2
committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
branch nick: bzr.selftest-not
timestamp: Wed 2007-04-11 00:23:43 +1000
message:
completed blackbox tests
------------------------------------------------------------
revno: 2394.2.5
merged: ian.clatworthy at internode.on.net-20070410090806-d9pkgwomcpbkizj2
parent: ian.clatworthy at internode.on.net-20070404131351-xqdiyfvwohs96ecs
committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
branch nick: bzr.selftest-not
timestamp: Tue 2007-04-10 19:08:06 +1000
message:
list-only working, include test not
------------------------------------------------------------
revno: 2394.2.4
merged: ian.clatworthy at internode.on.net-20070404131351-xqdiyfvwohs96ecs
parent: ian.clatworthy at internode.on.net-20070404131147-r9dp5hu8166xhb8u
committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
branch nick: bzr.selftest-not
timestamp: Wed 2007-04-04 23:13:51 +1000
message:
Clean up whitespace
------------------------------------------------------------
revno: 2394.2.3
merged: ian.clatworthy at internode.on.net-20070404131147-r9dp5hu8166xhb8u
parent: ian.clatworthy at internode.on.net-20070404125915-w0m76xc9tjxhbo42
committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
branch nick: bzr.selftest-not
timestamp: Wed 2007-04-04 23:11:47 +1000
message:
Backed out test junk
------------------------------------------------------------
revno: 2394.2.2
merged: ian.clatworthy at internode.on.net-20070404125915-w0m76xc9tjxhbo42
parent: ian.clatworthy at internode.on.net-20070404091010-1j1sdngh8t77ef9v
committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
branch nick: bzr.selftest-not
timestamp: Wed 2007-04-04 22:59:15 +1000
message:
Add --randomize and update help
------------------------------------------------------------
revno: 2394.2.1
merged: ian.clatworthy at internode.on.net-20070404091010-1j1sdngh8t77ef9v
parent: pqm at pqm.ubuntu.com-20070404005411-46c388fbf2acf940
committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
branch nick: bzr.selftest-not
timestamp: Wed 2007-04-04 19:10:10 +1000
message:
--list and --exclude first cut
=== modified file 'HACKING'
--- a/HACKING 2007-04-23 02:29:35 +0000
+++ b/HACKING 2007-04-24 02:43:56 +0000
@@ -442,10 +442,17 @@
./bzr selftest -v blackbox
-To skip a particular test (or set of tests), you need to use a negative
-match, like so::
-
- ./bzr selftest '^(?!.*blackbox)'
+To skip a particular test (or set of tests), use the --exclude option
+(shorthand -x) like so::
+
+ ./bzr selftest -v -x blackbox
+
+To list tests without running them, use the --list-only option like so::
+
+ ./bzr selftest --list-only
+
+This option can be combined with other selftest options (like -x) and
+filter patterns to understand their effect.
Errors and exceptions
=== modified file 'NEWS'
--- a/NEWS 2007-04-23 07:50:15 +0000
+++ b/NEWS 2007-04-24 02:43:56 +0000
@@ -5,6 +5,17 @@
* Merge directives can now be supplied as input to `merge` and `pull`,
like bundles can. (Aaron Bentley)
+ * selftest now supports --list-only to list tests instead of running
+ them. (Ian Clatworthy)
+
+ * selftest now supports --exclude PATTERN (or -x PATTERN) to exclude
+ tests with names that match that regular expression.
+ (Ian Clatworthy, #102679)
+
+ * selftest now supports --randomize SEED to run tests in a random order.
+ SEED is typically the value 'now' meaning 'use the current time'.
+ (Ian Clatworthy, #102686)
+
* New option ``--fixes`` to commit, which stores bug fixing annotations as
revision properties. Built-in support for Launchpad, Debian, Trac and
Bugzilla bug trackers. (Jonathan Lange, James Henstridge, Robert Collins)
=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py 2007-04-23 07:50:15 +0000
+++ b/bzrlib/builtins.py 2007-04-24 02:43:56 +0000
@@ -2326,7 +2326,7 @@
class cmd_selftest(Command):
"""Run internal test suite.
- This creates temporary test directories in the working directory, but not
+ This creates temporary test directories in the working directory, but no
existing data is affected. These directories are deleted if the tests
pass, or left behind to help in debugging if they fail and --keep-output
is specified.
@@ -2339,6 +2339,21 @@
all other tests are run. This is useful if you have been working in a
particular area, but want to make sure nothing else was broken.
+ If --exclude is given, tests that match that regular expression are
+ excluded, regardless of whether they match --first or not.
+
+ To help catch accidential dependencies between tests, the --randomize
+ option is useful. In most cases, the argument used is the word 'now'.
+ Note that the seed used for the random number generator is displayed
+ when this option is used. The seed can be explicitly passed as the
+ argument to this option if required. This enables reproduction of the
+ actual ordering used if and when an order sensitive problem is encountered.
+
+ If --list-only is given, the tests that would be run are listed. This is
+ useful when combined with --first, --exclude and/or --randomize to
+ understand their impact. The test harness reports "Listed nn tests in ..."
+ instead of "Ran nn tests in ..." when list mode is enabled.
+
If the global option '--no-plugins' is given, plugins are not loaded
before running the selftests. This has two effects: features provided or
modified by plugins will not be tested, and tests provided by plugins will
@@ -2357,8 +2372,6 @@
of running tests to create such subdirectories. This is default behavior
on Windows because of path length limitation.
"""
- # TODO: --list should give a list of all available tests
-
# NB: this is used from the class without creating an instance, which is
# why it does not have a self parameter.
def get_transport_type(typestring):
@@ -2405,13 +2418,23 @@
),
Option('numbered-dirs',
help='use numbered dirs for TestCaseInTempDir'),
+ Option('list-only',
+ help='list the tests instead of running them'),
+ Option('randomize', type=str, argname="SEED",
+ help='randomize the order of tests using the given'
+ ' seed or "now" for the current time'),
+ Option('exclude', type=str, argname="PATTERN",
+ short_name='x',
+ help='exclude tests that match this regular'
+ ' expression'),
]
encoding_type = 'replace'
def run(self, testspecs_list=None, verbose=None, one=False,
keep_output=False, transport=None, benchmark=None,
lsprof_timed=None, cache_dir=None, clean_output=False,
- first=False, numbered_dirs=None):
+ first=False, numbered_dirs=None, list_only=False,
+ randomize=None, exclude=None):
import bzrlib.ui
from bzrlib.tests import selftest
import bzrlib.benchmarks as benchmarks
@@ -2456,6 +2479,9 @@
bench_history=benchfile,
matching_tests_first=first,
numbered_dirs=numbered_dirs,
+ list_only=list_only,
+ random_seed=randomize,
+ exclude_pattern=exclude
)
finally:
if benchfile is not None:
=== modified file 'bzrlib/commands.py'
--- a/bzrlib/commands.py 2007-04-23 00:28:58 +0000
+++ b/bzrlib/commands.py 2007-04-24 02:43:56 +0000
@@ -714,9 +714,11 @@
def run_bzr_catch_errors(argv):
try:
- return run_bzr(argv)
- # do this here inside the exception wrappers to catch EPIPE
- sys.stdout.flush()
+ try:
+ return run_bzr(argv)
+ finally:
+ # do this here inside the exception wrappers to catch EPIPE
+ sys.stdout.flush()
except (KeyboardInterrupt, Exception), e:
# used to handle AssertionError and KeyboardInterrupt
# specially here, but hopefully they're handled ok by the logger now
=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py 2007-04-23 06:55:58 +0000
+++ b/bzrlib/tests/__init__.py 2007-04-24 02:43:56 +0000
@@ -34,6 +34,7 @@
import logging
import os
from pprint import pformat
+import random
import re
import shlex
import stat
@@ -501,6 +502,7 @@
keep_output=False,
bench_history=None,
use_numbered_dirs=False,
+ list_only=False
):
self.stream = unittest._WritelnDecorator(stream)
self.descriptions = descriptions
@@ -508,6 +510,7 @@
self.keep_output = keep_output
self._bench_history = bench_history
self.use_numbered_dirs = use_numbered_dirs
+ self.list_only = list_only
def run(self, test):
"Run the given test case or test suite."
@@ -525,14 +528,24 @@
)
result.stop_early = self.stop_on_failure
result.report_starting()
- test.run(result)
+ if self.list_only:
+ if self.verbosity >= 2:
+ self.stream.writeln("Listing tests only ...\n")
+ run = 0
+ for t in iter_suite_tests(test):
+ self.stream.writeln("%s" % (t.id()))
+ run += 1
+ actionTaken = "Listed"
+ else:
+ test.run(result)
+ run = result.testsRun
+ actionTaken = "Ran"
stopTime = time.time()
timeTaken = stopTime - startTime
result.printErrors()
self.stream.writeln(result.separator2)
- run = result.testsRun
- self.stream.writeln("Ran %d test%s in %.3fs" %
- (run, run != 1 and "s" or "", timeTaken))
+ self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
+ run, run != 1 and "s" or "", timeTaken))
self.stream.writeln()
if not result.wasSuccessful():
self.stream.write("FAILED (")
@@ -2053,24 +2066,50 @@
self.transport_readonly_server = HttpServer
-def filter_suite_by_re(suite, pattern):
- result = TestUtil.TestSuite()
- filter_re = re.compile(pattern)
- for test in iter_suite_tests(suite):
- if filter_re.search(test.id()):
- result.addTest(test)
- return result
-
-
-def sort_suite_by_re(suite, pattern):
+def filter_suite_by_re(suite, pattern, exclude_pattern=None,
+ random_order=False):
+ """Create a test suite by filtering another one.
+
+ :param suite: the source suite
+ :param pattern: pattern that names must match
+ :param exclude_pattern: pattern that names must not match, if any
+ :param random_order: if True, tests in the new suite will be put in
+ random order
+ :returns: the newly created suite
+ """
+ return sort_suite_by_re(suite, pattern, exclude_pattern,
+ random_order, False)
+
+
+def sort_suite_by_re(suite, pattern, exclude_pattern=None,
+ random_order=False, append_rest=True):
+ """Create a test suite by sorting another one.
+
+ :param suite: the source suite
+ :param pattern: pattern that names must match in order to go
+ first in the new suite
+ :param exclude_pattern: pattern that names must not match, if any
+ :param random_order: if True, tests in the new suite will be put in
+ random order
+ :param append_rest: if False, pattern is a strict filter and not
+ just an ordering directive
+ :returns: the newly created suite
+ """
first = []
second = []
filter_re = re.compile(pattern)
+ if exclude_pattern is not None:
+ exclude_re = re.compile(exclude_pattern)
for test in iter_suite_tests(suite):
- if filter_re.search(test.id()):
- first.append(test)
- else:
- second.append(test)
+ test_id = test.id()
+ if exclude_pattern is None or not exclude_re.search(test_id):
+ if filter_re.search(test_id):
+ first.append(test)
+ elif append_rest:
+ second.append(test)
+ if random_order:
+ random.shuffle(first)
+ random.shuffle(second)
return TestUtil.TestSuite(first + second)
@@ -2078,7 +2117,11 @@
stop_on_failure=False, keep_output=False,
transport=None, lsprof_timed=None, bench_history=None,
matching_tests_first=None,
- numbered_dirs=None):
+ numbered_dirs=None,
+ list_only=False,
+ random_seed=None,
+ exclude_pattern=None,
+ ):
use_numbered_dirs = bool(numbered_dirs)
TestCase._gather_lsprof_in_benchmarks = lsprof_timed
@@ -2094,13 +2137,33 @@
keep_output=keep_output,
bench_history=bench_history,
use_numbered_dirs=use_numbered_dirs,
+ list_only=list_only,
)
runner.stop_on_failure=stop_on_failure
- if pattern != '.*':
+ # Initialise the random number generator and display the seed used.
+ # We convert the seed to a long to make it reuseable across invocations.
+ random_order = False
+ if random_seed is not None:
+ random_order = True
+ if random_seed == "now":
+ random_seed = long(time.time())
+ else:
+ # Convert the seed to a long if we can
+ try:
+ random_seed = long(random_seed)
+ except:
+ pass
+ runner.stream.writeln("Randomizing test order using seed %s\n" %
+ (random_seed))
+ random.seed(random_seed)
+ # Customise the list of tests if requested
+ if pattern != '.*' or exclude_pattern is not None or random_order:
if matching_tests_first:
- suite = sort_suite_by_re(suite, pattern)
+ suite = sort_suite_by_re(suite, pattern, exclude_pattern,
+ random_order)
else:
- suite = filter_suite_by_re(suite, pattern)
+ suite = filter_suite_by_re(suite, pattern, exclude_pattern,
+ random_order)
result = runner.run(suite)
return result.wasSuccessful()
@@ -2112,7 +2175,10 @@
lsprof_timed=None,
bench_history=None,
matching_tests_first=None,
- numbered_dirs=None):
+ numbered_dirs=None,
+ list_only=False,
+ random_seed=None,
+ exclude_pattern=None):
"""Run the whole test suite under the enhanced runner"""
# XXX: Very ugly way to do this...
# Disable warning about old formats because we don't want it to disturb
@@ -2136,7 +2202,10 @@
lsprof_timed=lsprof_timed,
bench_history=bench_history,
matching_tests_first=matching_tests_first,
- numbered_dirs=numbered_dirs)
+ numbered_dirs=numbered_dirs,
+ list_only=list_only,
+ random_seed=random_seed,
+ exclude_pattern=exclude_pattern)
finally:
default_transport = old_transport
=== modified file 'bzrlib/tests/blackbox/test_selftest.py'
--- a/bzrlib/tests/blackbox/test_selftest.py 2007-03-08 22:08:08 +0000
+++ b/bzrlib/tests/blackbox/test_selftest.py 2007-04-13 00:30:33 +0000
@@ -17,6 +17,7 @@
"""UI tests for the test framework."""
import os
+import re
import signal
import sys
@@ -491,3 +492,85 @@
self.assertEquals(['bzr','bzrlib','setup.py',
'test9999.tmp','tests'],
after)
+
+
+class TestSelftestListOnly(TestCase):
+
+ @staticmethod
+ def _parse_test_list(lines, newlines_in_header=1):
+ "Parse a list of lines into a tuple of 3 lists (header,body,footer)."
+
+ in_header = True
+ in_footer = False
+ header = []
+ body = []
+ footer = []
+ header_newlines_found = 0
+ for line in lines:
+ if in_header:
+ if line == '':
+ header_newlines_found += 1
+ if header_newlines_found >= newlines_in_header:
+ in_header = False
+ continue
+ header.append(line)
+ elif not in_footer:
+ if line.startswith('-------'):
+ in_footer = True
+ else:
+ body.append(line)
+ else:
+ footer.append(line)
+ # If the last body line is blank, drop it off the list
+ if len(body) > 0 and body[-1] == '':
+ body.pop()
+ return (header,body,footer)
+
+ def test_list_only(self):
+ # check that bzr selftest --list-only works correctly
+ out,err = self.run_bzr_captured(['selftest', 'selftest',
+ '--list-only'])
+ self.assertEndsWith(err, 'tests passed\n')
+ (header,body,footer) = self._parse_test_list(out.splitlines())
+ num_tests = len(body)
+ self.assertContainsRe(footer[0], 'Listed %s tests in' % num_tests)
+
+ def test_list_only_filtered(self):
+ # check that a filtered --list-only works, both include and exclude
+ out_all,err_all = self.run_bzr_captured(['selftest', '--list-only'])
+ tests_all = self._parse_test_list(out_all.splitlines())[1]
+ out_incl,err_incl = self.run_bzr_captured(['selftest', '--list-only',
+ 'selftest'])
+ tests_incl = self._parse_test_list(out_incl.splitlines())[1]
+ self.assertSubset(tests_incl, tests_all)
+ out_excl,err_excl = self.run_bzr_captured(['selftest', '--list-only',
+ '--exclude', 'selftest'])
+ tests_excl = self._parse_test_list(out_excl.splitlines())[1]
+ self.assertSubset(tests_excl, tests_all)
+ set_incl = set(tests_incl)
+ set_excl = set(tests_excl)
+ intersection = set_incl.intersection(set_excl)
+ self.assertEquals(0, len(intersection))
+ self.assertEquals(len(tests_all), len(tests_incl) + len(tests_excl))
+
+ def test_list_only_random(self):
+ # check that --randomize works correctly
+ out_all,err_all = self.run_bzr_captured(['selftest', '--list-only',
+ 'selftest'])
+ tests_all = self._parse_test_list(out_all.splitlines())[1]
+ out_rand,err_rand = self.run_bzr_captured(['selftest', '--list-only',
+ 'selftest', '--randomize', 'now'])
+ (header_rand,tests_rand,dummy) = self._parse_test_list(
+ out_rand.splitlines(), 2)
+ self.assertNotEqual(tests_all, tests_rand)
+ self.assertEqual(sorted(tests_all), sorted(tests_rand))
+ # Check that the seed can be reused to get the exact same order
+ seed_re = re.compile('Randomizing test order using seed (\w+)')
+ match_obj = seed_re.search(header_rand[-1])
+ seed = match_obj.group(1)
+ out_rand2,err_rand2 = self.run_bzr_captured(['selftest', '--list-only',
+ 'selftest', '--randomize', seed])
+ (header_rand2,tests_rand2,dummy) = self._parse_test_list(
+ out_rand2.splitlines(), 2)
+ self.assertEqual(tests_rand, tests_rand2)
+
=== modified file 'bzrlib/tests/test_selftest.py'
--- a/bzrlib/tests/test_selftest.py 2007-04-20 03:00:57 +0000
+++ b/bzrlib/tests/test_selftest.py 2007-04-24 02:43:56 +0000
@@ -47,9 +47,14 @@
TestCaseWithTransport,
TestSkipped,
TestSuite,
+ TestUtil,
TextTestRunner,
UnavailableFeature,
clean_selftest_output,
+ iter_suite_tests,
+ filter_suite_by_re,
+ sort_suite_by_re,
+ test_suite
)
from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
from bzrlib.tests.TestUtil import _load_module_by_name
@@ -1506,3 +1511,27 @@
feature = Feature()
exception = UnavailableFeature(feature)
self.assertIs(feature, exception.args[0])
+
+
+class TestSelftestFiltering(TestCase):
+
+ def setUp(self):
+ self.suite = TestUtil.TestSuite()
+ self.loader = TestUtil.TestLoader()
+ self.suite.addTest(self.loader.loadTestsFromModuleNames([
+ 'bzrlib.tests.test_selftest']))
+ self.all_names = [t.id() for t in iter_suite_tests(self.suite)]
+
+ def test_filter_suite_by_re(self):
+ filtered_suite = filter_suite_by_re(self.suite, 'test_filter')
+ filtered_names = [t.id() for t in iter_suite_tests(filtered_suite)]
+ self.assertEqual(filtered_names, ['bzrlib.tests.test_selftest.'
+ 'TestSelftestFiltering.test_filter_suite_by_re'])
+
+ def test_sort_suite_by_re(self):
+ sorted_suite = sort_suite_by_re(self.suite, 'test_filter')
+ sorted_names = [t.id() for t in iter_suite_tests(sorted_suite)]
+ self.assertEqual(sorted_names[0], 'bzrlib.tests.test_selftest.'
+ 'TestSelftestFiltering.test_filter_suite_by_re')
+ self.assertEquals(sorted(self.all_names), sorted(sorted_names))
+
More information about the bazaar-commits
mailing list