Rev 3712: Hack together a simple file-log that doesn't need to access the rest of the ancestry. in http://bzr.arbash-meinel.com/branches/bzr/1.8-dev/lighter_log_file

John Arbash Meinel john at arbash-meinel.com
Thu Sep 18 16:10:45 BST 2008


At http://bzr.arbash-meinel.com/branches/bzr/1.8-dev/lighter_log_file

------------------------------------------------------------
revno: 3712
revision-id: john at arbash-meinel.com-20080918151043-8d6eptfynutalmz0
parent: pqm at pqm.ubuntu.com-20080917230446-p0wippqwikt511sp
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: lighter_log_file
timestamp: Thu 2008-09-18 10:10:43 -0500
message:
  Hack together a simple file-log that doesn't need to access the rest of the ancestry.
-------------- next part --------------
=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py	2008-09-17 07:18:20 +0000
+++ b/bzrlib/builtins.py	2008-09-18 15:10:43 +0000
@@ -1626,6 +1626,47 @@
         raise errors.BzrCommandError(msg)
 
 
+class cmd_file_log(Command):
+    """Show the log of a single file.
+
+    This is not quite the same as "bzr log file", as it only shows revisions
+    which modified the file, and not revisions which then merged those changes.
+    It also does not yet support revision ranges, etc.
+    """
+
+    takes_args = ['filename']
+    takes_options = ['log-format']
+
+    def run(self, filename, log_format=None):
+        tree, relpath = WorkingTree.open_containing(filename)
+        tree.lock_read()
+        try:
+            file_id = tree.path2id(relpath)
+            if file_id is None:
+                raise BzrCommandError('"%s" is not a versioned file'
+                                      % (filename,))
+
+            # XXX: There should be a more direct way of just grabbing the
+            #      last-modified revision from a tree
+            base_tree = tree.basis_tree()
+            base_tree.lock_read()
+            try:
+                if file_id not in base_tree.inventory:
+                    raise BzrCommandError('"%s" is a newly added file'
+                                          % (filename,))
+                revision_id = base_tree.inventory[file_id].revision
+            finally:
+                base_tree.unlock()
+
+            if log_format is None:
+                log_format = log.log_formatter_registry.get_default(tree.branch)
+            lf = log_format(show_ids=False, to_file=self.outf,
+                            show_timezone='original')
+            log.log_one_file(tree, file_id, revision_id, lf)
+        finally:
+            tree.unlock()
+
+
 class cmd_log(Command):
     """Show log of a branch, file, or directory.
 

=== modified file 'bzrlib/log.py'
--- a/bzrlib/log.py	2008-09-11 17:13:46 +0000
+++ b/bzrlib/log.py	2008-09-18 15:10:43 +0000
@@ -669,6 +669,45 @@
     return result
 
 
+def log_one_file(tree, file_id, revision_id, log_formatter):
+    """Print out the revision graph for a single file.
+
+    :param tree: A WorkingTree with the given file_id present.
+        The tree should already be locked.
+    :param file_id: The file to log
+    :param revision_id: The tip revision to start from. Typically this is
+        tree.basis_tree().inventory[file_id].revision
+    :param log_formatter: An instance of LogFormatter, which we will use to
+        print out the revision information.
+    """
+    from bzrlib import graph
+
+    file_graph = graph.Graph(tree.branch.repository.texts)
+    tip_key = (file_id, revision_id)
+    # TODO: Topological sorting?
+    # file_ancestry = dict(file_graph.iter_ancestry([tip_key]))
+    # TODO: Remove nodes which are ghosts, and references to ghosts
+    # ghosts = set(key for key, parents in file_ancestry.iteritems()
+    #                   if parents is None)
+    # TODO: Batch up revision_ids to be logged to grab them multiples at a
+    #       time.
+
+    # This iterates the per-file graph, and collects the revisions which are
+    # not considered ghosts.
+    # TODO: Use the whole-tree graph to compute dotted revnos, etc.
+    revisions = [(key[1], None, 0)
+                 for key, parents in file_graph.iter_ancestry([tip_key])
+                  if parents is not None]
+    revision_iterator = make_log_rev_iterator(tree.branch, revisions,
+        generate_delta=False, search=None)
+    rev_tag_dict = {}
+    for revs in revision_iterator:
+        for (rev_id, revno, merge_depth), rev, delta in revs:
+            lr = LogRevision(rev, revno, merge_depth, delta,
+                             rev_tag_dict.get(rev_id))
+            log_formatter.log_revision(lr)
+
+
 class LogRevision(object):
     """A revision to be logged (by LogFormatter.log_revision).
 



More information about the bazaar-commits mailing list