Rev 3965: Optionally show diff in log (Ian Clatworthy) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Wed Jan 28 09:41:18 GMT 2009
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 3965
revision-id: pqm at pqm.ubuntu.com-20090128094113-ze5jnburw91g2e4n
parent: pqm at pqm.ubuntu.com-20090127202443-ty2bu1hh91dumasz
parent: ian.clatworthy at canonical.com-20090127230635-70o18gj41uukrrzx
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2009-01-28 09:41:13 +0000
message:
Optionally show diff in log (Ian Clatworthy)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/log.py log.py-20050505065812-c40ce11702fe5fb1
bzrlib/tests/blackbox/test_log.py test_log.py-20060112090212-78f6ea560c868e24
------------------------------------------------------------
revno: 3964.1.1
revision-id: ian.clatworthy at canonical.com-20090127230635-70o18gj41uukrrzx
parent: pqm at pqm.ubuntu.com-20090127202443-ty2bu1hh91dumasz
parent: ian.clatworthy at canonical.com-20090127230221-mqumav0ghxkpybba
committer: Ian Clatworthy <ian.clatworthy at canonical.com>
branch nick: ianc-integration
timestamp: Wed 2009-01-28 09:06:35 +1000
message:
Optionally show diff in log (Ian Clatworthy)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/log.py log.py-20050505065812-c40ce11702fe5fb1
bzrlib/tests/blackbox/test_log.py test_log.py-20060112090212-78f6ea560c868e24
------------------------------------------------------------
revno: 3943.5.6
revision-id: ian.clatworthy at canonical.com-20090127230221-mqumav0ghxkpybba
parent: ian.clatworthy at canonical.com-20090118033218-y15x0aja8awnjog3
committer: Ian Clatworthy <ian.clatworthy at canonical.com>
branch nick: bzr.log-show-diff
timestamp: Wed 2009-01-28 09:02:21 +1000
message:
feedback from jam's review
modified:
bzrlib/log.py log.py-20050505065812-c40ce11702fe5fb1
bzrlib/tests/blackbox/test_log.py test_log.py-20060112090212-78f6ea560c868e24
------------------------------------------------------------
revno: 3943.5.5
revision-id: ian.clatworthy at canonical.com-20090118033218-y15x0aja8awnjog3
parent: ian.clatworthy at canonical.com-20090118031815-gb1m2e7p7ar4ayv1
committer: Ian Clatworthy <ian.clatworthy at canonical.com>
branch nick: bzr.log-show-diff
timestamp: Sun 2009-01-18 13:32:18 +1000
message:
tweak option name as requested in bug report
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/tests/blackbox/test_log.py test_log.py-20060112090212-78f6ea560c868e24
------------------------------------------------------------
revno: 3943.5.4
revision-id: ian.clatworthy at canonical.com-20090118031815-gb1m2e7p7ar4ayv1
parent: ian.clatworthy at canonical.com-20090118023732-adg1rvlk94cw7wup
committer: Ian Clatworthy <ian.clatworthy at canonical.com>
branch nick: bzr.log-show-diff
timestamp: Sun 2009-01-18 13:18:15 +1000
message:
filter diff by file
modified:
bzrlib/log.py log.py-20050505065812-c40ce11702fe5fb1
bzrlib/tests/blackbox/test_log.py test_log.py-20060112090212-78f6ea560c868e24
------------------------------------------------------------
revno: 3943.5.3
revision-id: ian.clatworthy at canonical.com-20090118023732-adg1rvlk94cw7wup
parent: ian.clatworthy at canonical.com-20090118013701-ogz42t2c8611fwx4
committer: Ian Clatworthy <ian.clatworthy at canonical.com>
branch nick: bzr.log-show-diff
timestamp: Sun 2009-01-18 12:37:32 +1000
message:
add tests
modified:
bzrlib/log.py log.py-20050505065812-c40ce11702fe5fb1
bzrlib/tests/blackbox/test_log.py test_log.py-20060112090212-78f6ea560c868e24
------------------------------------------------------------
revno: 3943.5.2
revision-id: ian.clatworthy at canonical.com-20090118013701-ogz42t2c8611fwx4
parent: ian.clatworthy at canonical.com-20090118005224-rkr66k4s31mgwy0z
committer: Ian Clatworthy <ian.clatworthy at canonical.com>
branch nick: bzr.log-show-diff
timestamp: Sun 2009-01-18 11:37:01 +1000
message:
hand control of diff formatting to the log formatter
modified:
bzrlib/log.py log.py-20050505065812-c40ce11702fe5fb1
------------------------------------------------------------
revno: 3943.5.1
revision-id: ian.clatworthy at canonical.com-20090118005224-rkr66k4s31mgwy0z
parent: pqm at pqm.ubuntu.com-20090115233242-4bxyn4zcj2a0ksfk
committer: Ian Clatworthy <ian.clatworthy at canonical.com>
branch nick: bzr.log-show-diff
timestamp: Sun 2009-01-18 10:52:24 +1000
message:
first cut at log --show-diff
modified:
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/log.py log.py-20050505065812-c40ce11702fe5fb1
=== modified file 'NEWS'
--- a/NEWS 2009-01-27 18:43:45 +0000
+++ b/NEWS 2009-01-27 23:06:35 +0000
@@ -37,6 +37,10 @@
NEW FEATURES:
+ * ``bzr log -p`` displays the patch diff for each revision.
+ When logging a file, the diff only includes changes to that file.
+ (Ian Clatworthy, #202331, #227335)
+
IMPROVEMENTS:
* ``bzr init`` will now print a little less verbose output.
=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py 2009-01-23 22:36:22 +0000
+++ b/bzrlib/builtins.py 2009-01-27 23:06:35 +0000
@@ -1862,6 +1862,9 @@
help='Limit the output to the first N revisions.',
argname='N',
type=_parse_limit),
+ Option('show-diff',
+ short_name='p',
+ help='Show changes made in each revision as a patch.'),
]
encoding_type = 'replace'
@@ -1874,7 +1877,8 @@
change=None,
log_format=None,
message=None,
- limit=None):
+ limit=None,
+ show_diff=False):
from bzrlib.log import show_log
direction = (forward and 'forward') or 'reverse'
@@ -1931,7 +1935,8 @@
start_revision=rev1,
end_revision=rev2,
search=message,
- limit=limit)
+ limit=limit,
+ show_diff=show_diff)
finally:
b.unlock()
=== modified file 'bzrlib/log.py'
--- a/bzrlib/log.py 2009-01-23 02:29:42 +0000
+++ b/bzrlib/log.py 2009-01-27 23:06:35 +0000
@@ -50,6 +50,7 @@
"""
import codecs
+from cStringIO import StringIO
from itertools import (
izip,
)
@@ -64,6 +65,7 @@
from bzrlib import (
config,
+ diff,
errors,
repository as _mod_repository,
revision as _mod_revision,
@@ -144,7 +146,8 @@
start_revision=None,
end_revision=None,
search=None,
- limit=None):
+ limit=None,
+ show_diff=False):
"""Write out human-readable log of commits to this branch.
:param lf: The LogFormatter object showing the output.
@@ -166,6 +169,8 @@
:param limit: If set, shows only 'limit' revisions, all revisions are shown
if None or 0.
+
+ :param show_diff: If True, output a diff after each revision.
"""
branch.lock_read()
try:
@@ -173,7 +178,7 @@
lf.begin_log()
_show_log(branch, lf, specific_fileid, verbose, direction,
- start_revision, end_revision, search, limit)
+ start_revision, end_revision, search, limit, show_diff)
if getattr(lf, 'end_log', None):
lf.end_log()
@@ -189,7 +194,8 @@
start_revision=None,
end_revision=None,
search=None,
- limit=None):
+ limit=None,
+ show_diff=False):
"""Worker function for show_log - see show_log."""
if not isinstance(lf, LogFormatter):
warn("not a LogFormatter instance: %r" % lf)
@@ -211,15 +217,21 @@
rev_tag_dict = branch.tags.get_reverse_tag_dict()
generate_delta = verbose and getattr(lf, 'supports_delta', False)
+ generate_diff = show_diff and getattr(lf, 'supports_diff', False)
# now we just print all the revisions
+ repo = branch.repository
log_count = 0
revision_iterator = make_log_rev_iterator(branch, view_revisions,
generate_delta, search)
for revs in revision_iterator:
for (rev_id, revno, merge_depth), rev, delta in revs:
+ if generate_diff:
+ diff = _format_diff(repo, rev, rev_id, specific_fileid)
+ else:
+ diff = None
lr = LogRevision(rev, revno, merge_depth, delta,
- rev_tag_dict.get(rev_id))
+ rev_tag_dict.get(rev_id), diff)
lf.log_revision(lr)
if limit:
log_count += 1
@@ -227,6 +239,23 @@
return
+def _format_diff(repo, rev, rev_id, specific_fileid):
+ if len(rev.parent_ids) == 0:
+ ancestor_id = _mod_revision.NULL_REVISION
+ else:
+ ancestor_id = rev.parent_ids[0]
+ tree_1 = repo.revision_tree(ancestor_id)
+ tree_2 = repo.revision_tree(rev_id)
+ if specific_fileid:
+ specific_files = [tree_2.id2path(specific_fileid)]
+ else:
+ specific_files = None
+ s = StringIO()
+ diff.show_diff_trees(tree_1, tree_2, s, specific_files, old_label='',
+ new_label='')
+ return s.getvalue()
+
+
def calculate_view_revisions(branch, start_revision, end_revision, direction,
specific_fileid, generate_merge_revisions,
allow_single_merge_revision):
@@ -694,12 +723,13 @@
"""
def __init__(self, rev=None, revno=None, merge_depth=0, delta=None,
- tags=None):
+ tags=None, diff=None):
self.rev = rev
self.revno = revno
self.merge_depth = merge_depth
self.delta = delta
self.tags = tags
+ self.diff = diff
class LogFormatter(object):
@@ -722,12 +752,17 @@
merge revisions. If not, and if supports_single_merge_revisions is
also not True, then only mainline revisions will be passed to the
formatter.
+
- supports_single_merge_revision must be True if this log formatter
supports logging only a single merge revision. This flag is
only relevant if supports_merge_revisions is not True.
+
- supports_tags must be True if this log formatter supports tags.
Otherwise the tags attribute may not be populated.
+ - supports_diff must be True if this log formatter supports diffs.
+ Otherwise the diff attribute may not be populated.
+
Plugins can register functions to show custom revision properties using
the properties_handler_registry. The registered function
must respect the following interface description:
@@ -777,12 +812,17 @@
for key, value in handler(revision).items():
self.to_file.write(indent + key + ': ' + value + '\n')
+ def show_diff(self, to_file, diff, indent):
+ for l in diff.rstrip().split('\n'):
+ to_file.write(indent + '%s\n' % (l,))
+
class LongLogFormatter(LogFormatter):
supports_merge_revisions = True
supports_delta = True
supports_tags = True
+ supports_diff = True
def log_revision(self, revision):
"""Log a revision, either merged or not."""
@@ -825,6 +865,11 @@
# We don't respect delta_format for compatibility
revision.delta.show(to_file, self.show_ids, indent=indent,
short_status=False)
+ if revision.diff is not None:
+ to_file.write(indent + 'diff:\n')
+ # Note: we explicitly don't indent the diff (relative to the
+ # revision information) so that the output can be fed to patch -p0
+ self.show_diff(to_file, revision.diff, indent)
class ShortLogFormatter(LogFormatter):
@@ -832,6 +877,7 @@
supports_delta = True
supports_tags = True
supports_single_merge_revision = True
+ supports_diff = True
def log_revision(self, revision):
to_file = self.to_file
@@ -862,6 +908,8 @@
if revision.delta is not None:
revision.delta.show(to_file, self.show_ids,
short_status=self.delta_format==1)
+ if revision.diff is not None:
+ self.show_diff(to_file, revision.diff, ' ')
to_file.write('\n')
=== modified file 'bzrlib/tests/blackbox/test_log.py'
--- a/bzrlib/tests/blackbox/test_log.py 2009-01-15 14:05:13 +0000
+++ b/bzrlib/tests/blackbox/test_log.py 2009-01-27 23:02:21 +0000
@@ -403,6 +403,170 @@
self.assertContainsRe(err, err_msg)
+def subst_dates(string):
+ """Replace date strings with constant values."""
+ return re.sub(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-\+]\d{4}',
+ 'YYYY-MM-DD HH:MM:SS +ZZZZ', string)
+
+
+class TestLogDiff(TestCaseWithoutPropsHandler):
+
+ def _prepare(self):
+ parent_tree = self.make_branch_and_tree('parent')
+ self.build_tree(['parent/file1', 'parent/file2'])
+ parent_tree.add('file1')
+ parent_tree.add('file2')
+ parent_tree.commit(message='first post',
+ timestamp=1132586655, timezone=36000,
+ committer='Lorem Ipsum <test at example.com>')
+ child_tree = parent_tree.bzrdir.sprout('child').open_workingtree()
+ self.build_tree_contents([('child/file2', 'hello\n')])
+ child_tree.commit(message='branch 1',
+ timestamp=1132586700, timezone=36000,
+ committer='Lorem Ipsum <test at example.com>')
+ parent_tree.merge_from_branch(child_tree.branch)
+ parent_tree.commit(message='merge branch 1',
+ timestamp=1132586800, timezone=36000,
+ committer='Lorem Ipsum <test at example.com>')
+ os.chdir('parent')
+
+ def test_log_show_diff_long(self):
+ self._prepare()
+ out,err = self.run_bzr('log -p')
+ self.assertEqual('', err)
+ log = normalize_log(out)
+ self.assertEqualDiff(subst_dates(log), """\
+------------------------------------------------------------
+revno: 2
+committer: Lorem Ipsum <test at example.com>
+branch nick: parent
+timestamp: Just now
+message:
+ merge branch 1
+diff:
+=== modified file 'file2'
+--- file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
++++ file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
+@@ -1,1 +1,1 @@
+-contents of parent/file2
++hello
+ ------------------------------------------------------------
+ revno: 1.1.1
+ committer: Lorem Ipsum <test at example.com>
+ branch nick: child
+ timestamp: Just now
+ message:
+ branch 1
+ diff:
+ === modified file 'file2'
+ --- file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
+ +++ file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
+ @@ -1,1 +1,1 @@
+ -contents of parent/file2
+ +hello
+------------------------------------------------------------
+revno: 1
+committer: Lorem Ipsum <test at example.com>
+branch nick: parent
+timestamp: Just now
+message:
+ first post
+diff:
+=== added file 'file1'
+--- file1\tYYYY-MM-DD HH:MM:SS +ZZZZ
++++ file1\tYYYY-MM-DD HH:MM:SS +ZZZZ
+@@ -0,0 +1,1 @@
++contents of parent/file1
+
+=== added file 'file2'
+--- file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
++++ file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
+@@ -0,0 +1,1 @@
++contents of parent/file2
+""")
+
+ def test_log_show_diff_short(self):
+ self._prepare()
+ out,err = self.run_bzr('log -p --short')
+ self.assertEqual('', err)
+ log = normalize_log(out)
+ self.assertEqualDiff(subst_dates(log), """\
+ 2 Lorem Ipsum\t2005-11-22 [merge]
+ merge branch 1
+ === modified file 'file2'
+ --- file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
+ +++ file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
+ @@ -1,1 +1,1 @@
+ -contents of parent/file2
+ +hello
+
+ 1 Lorem Ipsum\t2005-11-22
+ first post
+ === added file 'file1'
+ --- file1\tYYYY-MM-DD HH:MM:SS +ZZZZ
+ +++ file1\tYYYY-MM-DD HH:MM:SS +ZZZZ
+ @@ -0,0 +1,1 @@
+ +contents of parent/file1
+
+ === added file 'file2'
+ --- file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
+ +++ file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
+ @@ -0,0 +1,1 @@
+ +contents of parent/file2
+
+""")
+
+ def test_log_show_diff_line(self):
+ self._prepare()
+ out,err = self.run_bzr('log -p --line')
+ self.assertEqual('', err)
+ log = normalize_log(out)
+ # Not supported by this formatter so expect plain output
+ self.assertEqualDiff(subst_dates(log), """\
+2: Lorem Ipsum 2005-11-22 merge branch 1
+1: Lorem Ipsum 2005-11-22 first post
+""")
+
+ def test_log_show_diff_file(self):
+ """Only the diffs for the given file are to be shown"""
+ self._prepare()
+ out,err = self.run_bzr('log -p --short file2')
+ self.assertEqual('', err)
+ log = normalize_log(out)
+ self.assertEqualDiff(subst_dates(log), """\
+ 2 Lorem Ipsum\t2005-11-22 [merge]
+ merge branch 1
+ === modified file 'file2'
+ --- file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
+ +++ file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
+ @@ -1,1 +1,1 @@
+ -contents of parent/file2
+ +hello
+
+ 1 Lorem Ipsum\t2005-11-22
+ first post
+ === added file 'file2'
+ --- file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
+ +++ file2\tYYYY-MM-DD HH:MM:SS +ZZZZ
+ @@ -0,0 +1,1 @@
+ +contents of parent/file2
+
+""")
+ out,err = self.run_bzr('log -p --short file1')
+ self.assertEqual('', err)
+ log = normalize_log(out)
+ self.assertEqualDiff(subst_dates(log), """\
+ 1 Lorem Ipsum\t2005-11-22
+ first post
+ === added file 'file1'
+ --- file1\tYYYY-MM-DD HH:MM:SS +ZZZZ
+ +++ file1\tYYYY-MM-DD HH:MM:SS +ZZZZ
+ @@ -0,0 +1,1 @@
+ +contents of parent/file1
+
+""")
+
+
class TestLogEncodings(TestCaseInTempDir):
_mu = u'\xb5'
More information about the bazaar-commits
mailing list