Rev 2570: (Kent Gibson) 'bzr log --verbose' shows deltas for merged revisions. in http://bzr.arbash-meinel.com/branches/bzr/jam-integration
John Arbash Meinel
john at arbash-meinel.com
Mon Jul 2 16:01:32 BST 2007
At http://bzr.arbash-meinel.com/branches/bzr/jam-integration
------------------------------------------------------------
revno: 2570
revision-id: john at arbash-meinel.com-20070702150118-ypa1als5c0dx61ll
parent: john at arbash-meinel.com-20070702142427-egq5thf8lj6fh9ls
parent: warthog618 at gmail.com-20070619134630-c72ge100z6nmy21l
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: jam-integration
timestamp: Mon 2007-07-02 10:01:18 -0500
message:
(Kent Gibson) 'bzr log --verbose' shows deltas for merged revisions.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/delta.py delta.py-20050729221636-54cf14ef94783d0a
bzrlib/log.py log.py-20050505065812-c40ce11702fe5fb1
bzrlib/tests/blackbox/test_log.py test_log.py-20060112090212-78f6ea560c868e24
bzrlib/tests/test_log.py testlog.py-20050728115707-1a514809d7d49309
------------------------------------------------------------
revno: 2466.8.1.2.2
revision-id: warthog618 at gmail.com-20070619134630-c72ge100z6nmy21l
parent: warthog618 at gmail.com-20070502110246-05zkgmrv5vm807ms
committer: Kent Gibson <warthog618 at gmail.com>
branch nick: merge_deltas
timestamp: Tue 2007-06-19 21:46:30 +0800
message:
Add tests for deltas in merge revisions
------------------------------------------------------------
revno: 2466.8.1.2.1
revision-id: warthog618 at gmail.com-20070502110246-05zkgmrv5vm807ms
parent: warthog618 at gmail.com-20070429034630-p3xbitz2xyl6pbie
committer: Kent Gibson <warthog618 at gmail.com>
branch nick: merge_deltas
timestamp: Wed 2007-05-02 19:02:46 +0800
message:
Long log format reports deltas on merge revisions.
-------------- next part --------------
=== modified file 'NEWS'
--- a/NEWS 2007-07-02 06:11:47 +0000
+++ b/NEWS 2007-07-02 15:01:18 +0000
@@ -60,6 +60,9 @@
* ``bzrtracefilename --version`` now shows the location of the bzr log file, which
is especially useful on Windows. (Martin Pool)
+ * Long log format reports deltas on merge revisions.
+ (John Arbash Meinel, Kent Gibson)
+
LIBRARY API BREAKS:
* Testing cleanups -
=== modified file 'bzrlib/delta.py'
--- a/bzrlib/delta.py 2007-04-16 01:00:20 +0000
+++ b/bzrlib/delta.py 2007-05-02 11:02:46 +0000
@@ -107,7 +107,7 @@
def show(self, to_file, show_ids=False, show_unchanged=False,
- short_status=False):
+ short_status=False, indent=''):
"""output this delta in status-like form to to_file."""
def show_list(files, short_status_letter=''):
for item in files:
@@ -122,21 +122,21 @@
path += '*'
if show_ids:
- print >>to_file, '%s %-30s %s' % (short_status_letter,
+ print >>to_file, indent + '%s %-30s %s' % (short_status_letter,
path, fid)
else:
- print >>to_file, '%s %s' % (short_status_letter, path)
+ print >>to_file, indent + '%s %s' % (short_status_letter, path)
if self.removed:
if not short_status:
- print >>to_file, 'removed:'
+ print >>to_file, indent + 'removed:'
show_list(self.removed)
else:
show_list(self.removed, 'D')
if self.added:
if not short_status:
- print >>to_file, 'added:'
+ print >>to_file, indent + 'added:'
show_list(self.added)
else:
show_list(self.added, 'A')
@@ -146,7 +146,7 @@
if self.renamed:
short_status_letter = 'R'
if not short_status:
- print >>to_file, 'renamed:'
+ print >>to_file, indent + 'renamed:'
short_status_letter = ''
for (oldpath, newpath, fid, kind,
text_modified, meta_modified) in self.renamed:
@@ -156,43 +156,43 @@
if meta_modified:
newpath += '*'
if show_ids:
- print >>to_file, '%s %s => %s %s' % (
+ print >>to_file, indent + '%s %s => %s %s' % (
short_status_letter, oldpath, newpath, fid)
else:
- print >>to_file, '%s %s => %s' % (
+ print >>to_file, indent + '%s %s => %s' % (
short_status_letter, oldpath, newpath)
if self.kind_changed:
if short_status:
short_status_letter = 'K'
else:
- print >>to_file, 'kind changed:'
+ print >>to_file, indent + 'kind changed:'
short_status_letter = ''
for (path, fid, old_kind, new_kind) in self.kind_changed:
if show_ids:
suffix = ' '+fid
else:
suffix = ''
- print >>to_file, '%s %s (%s => %s)%s' % (
+ print >>to_file, indent + '%s %s (%s => %s)%s' % (
short_status_letter, path, old_kind, new_kind, suffix)
if self.modified or extra_modified:
short_status_letter = 'M'
if not short_status:
- print >>to_file, 'modified:'
+ print >>to_file, indent + 'modified:'
short_status_letter = ''
show_list(self.modified, short_status_letter)
show_list(extra_modified, short_status_letter)
if show_unchanged and self.unchanged:
if not short_status:
- print >>to_file, 'unchanged:'
+ print >>to_file, indent + 'unchanged:'
show_list(self.unchanged)
else:
show_list(self.unchanged, 'S')
if self.unversioned:
- print >>to_file, 'unknown:'
+ print >>to_file, indent + 'unknown:'
show_list(self.unversioned)
def get_changes_as_text(self, show_ids=False, show_unchanged=False,
=== modified file 'bzrlib/log.py'
--- a/bzrlib/log.py 2007-06-01 21:40:45 +0000
+++ b/bzrlib/log.py 2007-07-02 15:01:18 +0000
@@ -269,22 +269,16 @@
def iter_revisions():
# r = revision, n = revno, d = merge depth
revision_ids = [r for r, n, d in view_revisions]
- zeros = set(r for r, n, d in view_revisions if d == 0)
num = 9
repository = branch.repository
while revision_ids:
cur_deltas = {}
revisions = repository.get_revisions(revision_ids[:num])
if generate_delta:
- delta_revisions = [r for r in revisions if
- r.revision_id in zeros]
- deltas = repository.get_deltas_for_revisions(delta_revisions)
- cur_deltas = dict(izip((r.revision_id for r in
- delta_revisions), deltas))
+ deltas = repository.get_deltas_for_revisions(revisions)
+ cur_deltas = dict(izip((r.revision_id for r in revisions),
+ deltas))
for revision in revisions:
- # The delta value will be None unless
- # 1. verbose is specified, and
- # 2. the revision is a mainline revision
yield revision, cur_deltas.get(revision.revision_id)
revision_ids = revision_ids[num:]
num = min(int(num * 1.5), 200)
@@ -551,7 +545,7 @@
for l in message.split('\n'):
print >>to_file, indent+' ' + l
if revision.delta is not None:
- revision.delta.show(to_file, self.show_ids)
+ revision.delta.show(to_file, self.show_ids, indent=indent)
class ShortLogFormatter(LogFormatter):
=== modified file 'bzrlib/tests/blackbox/test_log.py'
--- a/bzrlib/tests/blackbox/test_log.py 2007-06-26 10:12:33 +0000
+++ b/bzrlib/tests/blackbox/test_log.py 2007-07-02 15:01:18 +0000
@@ -51,27 +51,28 @@
self.assertTrue('message:\n message3\n' in self.full_log)
log = self.run_bzr("log -r 1..")[0]
- self.assertEquals(log, self.full_log)
+ self.assertEqualDiff(log, self.full_log)
def test_log_null_begin_revspec(self):
self._prepare()
log = self.run_bzr("log -r ..3")[0]
- self.assertEquals(self.full_log, log)
+ self.assertEqualDiff(self.full_log, log)
def test_log_null_both_revspecs(self):
self._prepare()
log = self.run_bzr("log -r ..")[0]
self.assertEquals(self.full_log, log)
+ self.assertEqualDiff(self.full_log, log)
def test_log_negative_begin_revspec_full_log(self):
self._prepare()
log = self.run_bzr("log -r -3..")[0]
- self.assertEquals(self.full_log, log)
+ self.assertEqualDiff(self.full_log, log)
def test_log_negative_both_revspec_full_log(self):
self._prepare()
log = self.run_bzr("log -r -3..-1")[0]
- self.assertEquals(self.full_log, log)
+ self.assertEqualDiff(self.full_log, log)
def test_log_negative_both_revspec_partial(self):
self._prepare()
@@ -90,7 +91,7 @@
def test_log_postive_revspecs(self):
self._prepare()
log = self.run_bzr("log -r 1..3")[0]
- self.assertEquals(self.full_log, log)
+ self.assertEqualDiff(self.full_log, log)
def test_log_revno_n_path(self):
os.mkdir('branch1')
@@ -104,7 +105,7 @@
log = self.run_bzr("log -r revno:2:branch1..revno:3:branch2",
retcode=3)[0]
log = self.run_bzr("log -r revno:1:branch2..revno:3:branch2")[0]
- self.assertEquals(self.full_log, log)
+ self.assertEqualDiff(self.full_log, log)
log = self.run_bzr("log -r revno:1:branch2")[0]
self.assertTrue('revno: 1\n' in log)
self.assertTrue('revno: 2\n' not in log)
@@ -156,80 +157,6 @@
self.assertTrue('revno: 3\n' in log)
-class TestLogMerges(ExternalBase):
-
- def test_merges_are_indented_by_level(self):
- self.build_tree(['parent/'])
- self.run_bzr('init', 'parent')
- self.run_bzr('commit', '-m', 'first post', '--unchanged', 'parent')
- self.run_bzr('branch', 'parent', 'child')
- self.run_bzr('commit', '-m', 'branch 1', '--unchanged', 'child')
- self.run_bzr('branch', 'child', 'smallerchild')
- self.run_bzr('commit', '-m', 'branch 2', '--unchanged', 'smallerchild')
- os.chdir('child')
- self.run_bzr('merge', '../smallerchild')
- self.run_bzr('commit', '-m', 'merge branch 2')
- os.chdir('../parent')
- self.run_bzr('merge', '../child')
- self.run_bzr('commit', '-m', 'merge branch 1')
- out,err = self.run_bzr('log')
- # the log will look something like:
-# self.assertEqual("""\
-#------------------------------------------------------------
-#revno: 2
-#committer: Robert Collins <foo at example.com>
-#branch nick: parent
-#timestamp: Tue 2006-03-28 22:31:40 +1100
-#message:
-# merge branch 1
-# ------------------------------------------------------------
-# revno: 1.1.2
-# merged: foo at example.com-20060328113140-91f43cfb46dc2863
-# committer: Robert Collins <foo at example.com>
-# branch nick: child
-# timestamp: Tue 2006-03-28 22:31:40 +1100
-# message:
-# merge branch 2
-# ------------------------------------------------------------
-# revno: 1.1.1.1
-# merged: foo at example.com-20060328113140-1ba24f850a0ef573
-# committer: Robert Collins <foo at example.com>
-# branch nick: smallerchild
-# timestamp: Tue 2006-03-28 22:31:40 +1100
-# message:
-# branch 2
-# ------------------------------------------------------------
-# revno: 1.1.1
-# merged: foo at example.com-20060328113140-5749a4757a8ac792
-# committer: Robert Collins <foo at example.com>
-# branch nick: child
-# timestamp: Tue 2006-03-28 22:31:40 +1100
-# message:
-# branch 1
-#------------------------------------------------------------
-#revno: 1
-#committer: Robert Collins <foo at example.com>
-#branch nick: parent
-#timestamp: Tue 2006-03-28 22:31:39 +1100
-#message:
-# first post
-#""", out)
- # but we dont have a nice pattern matcher hooked up yet, so:
- # we check for the indenting of the commit message and the
- # revision numbers
- self.assertTrue('revno: 2' in out)
- self.assertTrue(' merge branch 1' in out)
- self.assertTrue(' revno: 1.1.2' in out)
- self.assertTrue(' merge branch 2' in out)
- self.assertTrue(' revno: 1.1.1.1' in out)
- self.assertTrue(' branch 2' in out)
- self.assertTrue(' revno: 1.1.1' in out)
- self.assertTrue(' branch 1' in out)
- self.assertTrue('revno: 1' in out)
- self.assertTrue(' first post' in out)
- self.assertEqual('', err)
-
-
class TestLogEncodings(TestCaseInTempDir):
_mu = u'\xb5'
=== modified file 'bzrlib/tests/test_log.py'
--- a/bzrlib/tests/test_log.py 2007-06-26 10:15:29 +0000
+++ b/bzrlib/tests/test_log.py 2007-07-02 15:01:18 +0000
@@ -50,17 +50,12 @@
self.logs.append(revision)
-class SimpleLogTest(TestCaseWithTransport):
+class TestShowLog(TestCaseWithTransport):
def checkDelta(self, delta, **kw):
"""Check the filenames touched by a delta are as expected."""
for n in 'added', 'removed', 'renamed', 'modified', 'unchanged':
expected = kw.get(n, [])
-
- # tests are written with unix paths; fix them up for windows
- #if os.sep != '/':
- # expected = [x.replace('/', os.sep) for x in expected]
-
# strip out only the path components
got = [x[0] for x in getattr(delta, n)]
self.assertEquals(expected, got)
@@ -131,7 +126,7 @@
eq(logentry.rev.message, 'add one file')
d = logentry.delta
self.log('log 2 delta: %r' % d)
- # self.checkDelta(d, added=['hello'])
+ self.checkDelta(d, added=['hello'])
# commit a log message with control characters
msg = "All 8-bit chars: " + ''.join([unichr(x) for x in range(256)])
@@ -158,27 +153,72 @@
self.log("escaped commit message: %r", committed_msg)
self.assert_(msg == committed_msg)
+ def test_deltas_in_merge_revisions(self):
+ """Check deltas created for both mainline and merge revisions"""
+ eq = self.assertEquals
+ wt = self.make_branch_and_tree('parent')
+ self.build_tree(['parent/file1', 'parent/file2', 'parent/file3'])
+ wt.add('file1')
+ wt.add('file2')
+ wt.commit(message='add file1 and file2')
+ self.run_bzr('branch', 'parent', 'child')
+ os.unlink('child/file1')
+ print >> file('child/file2', 'wb'), 'hello'
+ self.run_bzr('commit', '-m', 'remove file1 and modify file2', 'child')
+ os.chdir('parent')
+ self.run_bzr('merge', '../child')
+ wt.commit('merge child branch')
+ os.chdir('..')
+ b = wt.branch
+ lf = LogCatcher()
+ lf.supports_merge_revisions = True
+ show_log(b, lf, verbose=True)
+ eq(len(lf.logs),3)
+ logentry = lf.logs[0]
+ eq(logentry.revno, '2')
+ eq(logentry.rev.message, 'merge child branch')
+ d = logentry.delta
+ self.checkDelta(d, removed=['file1'], modified=['file2'])
+ logentry = lf.logs[1]
+ eq(logentry.revno, '1.1.1')
+ eq(logentry.rev.message, 'remove file1 and modify file2')
+ d = logentry.delta
+ self.checkDelta(d, removed=['file1'], modified=['file2'])
+ logentry = lf.logs[2]
+ eq(logentry.revno, '1')
+ eq(logentry.rev.message, 'add file1 and file2')
+ d = logentry.delta
+ self.checkDelta(d, added=['file1', 'file2'])
+
+
+def make_commits_with_trailing_newlines(wt):
+ """Helper method for LogFormatter tests"""
+ b = wt.branch
+ b.nick='test'
+ open('a', 'wb').write('hello moto\n')
+ wt.add('a')
+ wt.commit('simple log message', rev_id='a1'
+ , timestamp=1132586655.459960938, timezone=-6*3600
+ , committer='Joe Foo <joe at foo.com>')
+ open('b', 'wb').write('goodbye\n')
+ wt.add('b')
+ wt.commit('multiline\nlog\nmessage\n', rev_id='a2'
+ , timestamp=1132586842.411175966, timezone=-6*3600
+ , committer='Joe Foo <joe at foo.com>')
+
+ open('c', 'wb').write('just another manic monday\n')
+ wt.add('c')
+ wt.commit('single line with trailing newline\n', rev_id='a3'
+ , timestamp=1132587176.835228920, timezone=-6*3600
+ , committer = 'Joe Foo <joe at foo.com>')
+ return b
+
+
+class TestShortLogFormatter(TestCaseWithTransport):
+
def test_trailing_newlines(self):
wt = self.make_branch_and_tree('.')
- b = wt.branch
- b.nick='test'
- open('a', 'wb').write('hello moto\n')
- wt.add('a')
- wt.commit('simple log message', rev_id='a1'
- , timestamp=1132586655.459960938, timezone=-6*3600
- , committer='Joe Foo <joe at foo.com>')
- open('b', 'wb').write('goodbye\n')
- wt.add('b')
- wt.commit('multiline\nlog\nmessage\n', rev_id='a2'
- , timestamp=1132586842.411175966, timezone=-6*3600
- , committer='Joe Foo <joe at foo.com>')
-
- open('c', 'wb').write('just another manic monday\n')
- wt.add('c')
- wt.commit('single line with trailing newline\n', rev_id='a3'
- , timestamp=1132587176.835228920, timezone=-6*3600
- , committer = 'Joe Foo <joe at foo.com>')
-
+ b = make_commits_with_trailing_newlines(wt)
sio = StringIO()
lf = ShortLogFormatter(to_file=sio)
show_log(b, lf)
@@ -196,35 +236,22 @@
""")
- sio = StringIO()
- lf = LongLogFormatter(to_file=sio)
- show_log(b, lf)
- self.assertEquals(sio.getvalue(), """\
-------------------------------------------------------------
-revno: 3
-committer: Joe Foo <joe at foo.com>
-branch nick: test
-timestamp: Mon 2005-11-21 09:32:56 -0600
-message:
- single line with trailing newline
-------------------------------------------------------------
-revno: 2
-committer: Joe Foo <joe at foo.com>
-branch nick: test
-timestamp: Mon 2005-11-21 09:27:22 -0600
-message:
- multiline
- log
- message
-------------------------------------------------------------
-revno: 1
-committer: Joe Foo <joe at foo.com>
-branch nick: test
-timestamp: Mon 2005-11-21 09:24:15 -0600
-message:
- simple log message
-""")
-
+
+class TestLongLogFormatter(TestCaseWithTransport):
+
+ def normalize_log(self,log):
+ """Replaces the variable lines of logs with fixed lines"""
+ committer = 'committer: Lorem Ipsum <test at example.com>'
+ lines = log.splitlines(True)
+ for idx,line in enumerate(lines):
+ stripped_line = line.lstrip()
+ indent = ' ' * (len(line) - len(stripped_line))
+ if stripped_line.startswith('committer:'):
+ lines[idx] = indent + committer + '\n'
+ if stripped_line.startswith('timestamp:'):
+ lines[idx] = indent + 'timestamp: Just now\n'
+ return ''.join(lines)
+
def test_verbose_log(self):
"""Verbose log includes changed files
@@ -258,6 +285,149 @@
a
''')
+ def test_merges_are_indented_by_level(self):
+ wt = self.make_branch_and_tree('parent')
+ wt.commit('first post')
+ self.run_bzr('branch', 'parent', 'child')
+ self.run_bzr('commit', '-m', 'branch 1', '--unchanged', 'child')
+ self.run_bzr('branch', 'child', 'smallerchild')
+ self.run_bzr('commit', '-m', 'branch 2', '--unchanged', 'smallerchild')
+ os.chdir('child')
+ self.run_bzr('merge', '../smallerchild')
+ self.run_bzr('commit', '-m', 'merge branch 2')
+ os.chdir('../parent')
+ self.run_bzr('merge', '../child')
+ wt.commit('merge branch 1')
+ b = wt.branch
+ sio = StringIO()
+ lf = LongLogFormatter(to_file=sio)
+ show_log(b, lf, verbose=True)
+ log = self.normalize_log(sio.getvalue())
+ self.assertEqualDiff("""\
+------------------------------------------------------------
+revno: 2
+committer: Lorem Ipsum <test at example.com>
+branch nick: parent
+timestamp: Just now
+message:
+ merge branch 1
+ ------------------------------------------------------------
+ revno: 1.1.2
+ committer: Lorem Ipsum <test at example.com>
+ branch nick: child
+ timestamp: Just now
+ message:
+ merge branch 2
+ ------------------------------------------------------------
+ revno: 1.1.1.1.1
+ committer: Lorem Ipsum <test at example.com>
+ branch nick: smallerchild
+ timestamp: Just now
+ message:
+ branch 2
+ ------------------------------------------------------------
+ revno: 1.1.1
+ committer: Lorem Ipsum <test at example.com>
+ branch nick: child
+ timestamp: Just now
+ message:
+ branch 1
+------------------------------------------------------------
+revno: 1
+committer: Lorem Ipsum <test at example.com>
+branch nick: parent
+timestamp: Just now
+message:
+ first post
+""", log)
+
+ def test_verbose_merge_revisions_contain_deltas(self):
+ wt = self.make_branch_and_tree('parent')
+ self.build_tree(['parent/f1', 'parent/f2'])
+ wt.add(['f1','f2'])
+ wt.commit('first post')
+ self.run_bzr('branch', 'parent', 'child')
+ os.unlink('child/f1')
+ print >> file('child/f2', 'wb'), 'hello'
+ self.run_bzr('commit', '-m', 'removed f1 and modified f2', 'child')
+ os.chdir('parent')
+ self.run_bzr('merge', '../child')
+ wt.commit('merge branch 1')
+ b = wt.branch
+ sio = StringIO()
+ lf = LongLogFormatter(to_file=sio)
+ show_log(b, lf, verbose=True)
+ log = self.normalize_log(sio.getvalue())
+ self.assertEqualDiff("""\
+------------------------------------------------------------
+revno: 2
+committer: Lorem Ipsum <test at example.com>
+branch nick: parent
+timestamp: Just now
+message:
+ merge branch 1
+removed:
+ f1
+modified:
+ f2
+ ------------------------------------------------------------
+ revno: 1.1.1
+ committer: Lorem Ipsum <test at example.com>
+ branch nick: child
+ timestamp: Just now
+ message:
+ removed f1 and modified f2
+ removed:
+ f1
+ modified:
+ f2
+------------------------------------------------------------
+revno: 1
+committer: Lorem Ipsum <test at example.com>
+branch nick: parent
+timestamp: Just now
+message:
+ first post
+added:
+ f1
+ f2
+""", log)
+
+ def test_trailing_newlines(self):
+ wt = self.make_branch_and_tree('.')
+ b = make_commits_with_trailing_newlines(wt)
+ sio = StringIO()
+ lf = LongLogFormatter(to_file=sio)
+ show_log(b, lf)
+ self.assertEqualDiff(sio.getvalue(), """\
+------------------------------------------------------------
+revno: 3
+committer: Joe Foo <joe at foo.com>
+branch nick: test
+timestamp: Mon 2005-11-21 09:32:56 -0600
+message:
+ single line with trailing newline
+------------------------------------------------------------
+revno: 2
+committer: Joe Foo <joe at foo.com>
+branch nick: test
+timestamp: Mon 2005-11-21 09:27:22 -0600
+message:
+ multiline
+ log
+ message
+------------------------------------------------------------
+revno: 1
+committer: Joe Foo <joe at foo.com>
+branch nick: test
+timestamp: Mon 2005-11-21 09:24:15 -0600
+message:
+ simple log message
+""")
+
+
+class TestLineLogFormatter(TestCaseWithTransport):
+
def test_line_log(self):
"""Line log should show revno
@@ -311,6 +481,21 @@
finally:
wt.unlock()
+ def test_trailing_newlines(self):
+ wt = self.make_branch_and_tree('.')
+ b = make_commits_with_trailing_newlines(wt)
+ sio = StringIO()
+ lf = LineLogFormatter(to_file=sio)
+ show_log(b, lf)
+ self.assertEqualDiff(sio.getvalue(), """\
+3: Joe Foo 2005-11-21 single line with trailing newline
+2: Joe Foo 2005-11-21 multiline
+1: Joe Foo 2005-11-21 simple log message
+""")
+
+
+class TestGetViewRevisions(TestCaseWithTransport):
+
def make_tree_with_commits(self):
"""Create a tree with well-known revision ids"""
wt = self.make_branch_and_tree('tree1')
More information about the bazaar-commits
mailing list