[Pkg-bazaar-commits] ./bzr/unstable r475: - rewrite diff using compare_trees()

Martin Pool mbp at sourcefrog.net
Fri Apr 10 08:18:53 UTC 2009


------------------------------------------------------------
revno: 475
committer: Martin Pool <mbp at sourcefrog.net>
timestamp: Wed 2005-05-11 17:45:56 +1000
message:
  - rewrite diff using compare_trees()
  - include entry kind in TreeDelta
modified:
  bzrlib/branch.py
  bzrlib/diff.py
  bzrlib/tree.py
-------------- next part --------------
=== modified file 'bzrlib/branch.py'
--- a/bzrlib/branch.py	2005-05-11 05:55:27 +0000
+++ b/bzrlib/branch.py	2005-05-11 07:45:56 +0000
@@ -33,7 +33,6 @@
 from revision import Revision
 from errors import bailout, BzrError
 from textui import show_status
-from diff import diff_trees
 
 BZR_BRANCH_FORMAT = "Bazaar-NG branch, format 0.0.4\n"
 ## TODO: Maybe include checks for common corruption of newlines, etc?

=== modified file 'bzrlib/diff.py'
--- a/bzrlib/diff.py	2005-05-11 07:17:37 +0000
+++ b/bzrlib/diff.py	2005-05-11 07:45:56 +0000
@@ -130,8 +130,56 @@
 
 
 
+def _diff_one(oldlines, newlines, to_file, **kw):
+    import difflib
+    
+    # FIXME: difflib is wrong if there is no trailing newline.
+    # The syntax used by patch seems to be "\ No newline at
+    # end of file" following the last diff line from that
+    # file.  This is not trivial to insert into the
+    # unified_diff output and it might be better to just fix
+    # or replace that function.
+
+    # In the meantime we at least make sure the patch isn't
+    # mangled.
+
+
+    # Special workaround for Python2.3, where difflib fails if
+    # both sequences are empty.
+    if not oldlines and not newlines:
+        return
+
+    nonl = False
+
+    if oldlines and (oldlines[-1][-1] != '\n'):
+        oldlines[-1] += '\n'
+        nonl = True
+    if newlines and (newlines[-1][-1] != '\n'):
+        newlines[-1] += '\n'
+        nonl = True
+
+    ud = difflib.unified_diff(oldlines, newlines, **kw)
+
+    # work-around for difflib being too smart for its own good
+    # if /dev/null is "1,0", patch won't recognize it as /dev/null
+    if not oldlines:
+        ud = list(ud)
+        ud[2] = ud[2].replace('-1,0', '-0,0')
+    elif not newlines:
+        ud = list(ud)
+        ud[2] = ud[2].replace('+1,0', '+0,0')
+
+    to_file.writelines(ud)
+    if nonl:
+        print >>to_file, "\\ No newline at end of file"
+    print >>to_file
+
+
 def show_diff(b, revision, file_list):
-    import difflib, sys, types
+    import sys
+
+    if file_list:
+        raise NotImplementedError('diff on restricted files broken at the moment')
     
     if revision == None:
         old_tree = b.basis_tree()
@@ -152,97 +200,43 @@
     # TODO: Generation of pseudo-diffs for added/deleted files could
     # be usefully made into a much faster special case.
 
-    # TODO: Better to return them in sorted order I think.
-
-    if file_list:
-        file_list = [b.relpath(f) for f in file_list]
-
-    # FIXME: If given a file list, compare only those files rather
-    # than comparing everything and then throwing stuff away.
-    
-    for file_state, fid, old_name, new_name, kind in diff_trees(old_tree, new_tree):
-
-        if file_list and (new_name not in file_list):
-            continue
-        
-        # Don't show this by default; maybe do it if an option is passed
-        # idlabel = '      {%s}' % fid
-        idlabel = ''
-
-        def diffit(oldlines, newlines, **kw):
-            
-            # FIXME: difflib is wrong if there is no trailing newline.
-            # The syntax used by patch seems to be "\ No newline at
-            # end of file" following the last diff line from that
-            # file.  This is not trivial to insert into the
-            # unified_diff output and it might be better to just fix
-            # or replace that function.
-
-            # In the meantime we at least make sure the patch isn't
-            # mangled.
-            
-
-            # Special workaround for Python2.3, where difflib fails if
-            # both sequences are empty.
-            if not oldlines and not newlines:
-                return
-
-            nonl = False
-
-            if oldlines and (oldlines[-1][-1] != '\n'):
-                oldlines[-1] += '\n'
-                nonl = True
-            if newlines and (newlines[-1][-1] != '\n'):
-                newlines[-1] += '\n'
-                nonl = True
-
-            ud = difflib.unified_diff(oldlines, newlines, **kw)
-
-            # work-around for difflib being too smart for its own good
-            # if /dev/null is "1,0", patch won't recognize it as /dev/null
-            if not oldlines:
-                ud = list(ud)
-                ud[2] = ud[2].replace('-1,0', '-0,0')
-            elif not newlines:
-                ud = list(ud)
-                ud[2] = ud[2].replace('+1,0', '+0,0')
-            
-            sys.stdout.writelines(ud)
-            if nonl:
-                print "\\ No newline at end of file"
-            sys.stdout.write('\n')
-        
-        if file_state in ['.', '?', 'I']:
-            continue
-        elif file_state == 'A':
-            print '*** added %s %r' % (kind, new_name)
-            if kind == 'file':
-                diffit([],
-                       new_tree.get_file(fid).readlines(),
-                       fromfile=DEVNULL,
-                       tofile=new_label + new_name + idlabel)
-        elif file_state == 'D':
-            assert isinstance(old_name, types.StringTypes)
-            print '*** deleted %s %r' % (kind, old_name)
-            if kind == 'file':
-                diffit(old_tree.get_file(fid).readlines(), [],
-                       fromfile=old_label + old_name + idlabel,
-                       tofile=DEVNULL)
-        elif file_state in ['M', 'R']:
-            if file_state == 'M':
-                assert kind == 'file'
-                assert old_name == new_name
-                print '*** modified %s %r' % (kind, new_name)
-            elif file_state == 'R':
-                print '*** renamed %s %r => %r' % (kind, old_name, new_name)
-
-            if kind == 'file':
-                diffit(old_tree.get_file(fid).readlines(),
-                       new_tree.get_file(fid).readlines(),
-                       fromfile=old_label + old_name + idlabel,
-                       tofile=new_label + new_name)
-        else:
-            raise BzrError("can't represent state %s {%s}" % (file_state, fid))
+    delta = compare_trees(old_tree, new_tree, want_unchanged=False)
+
+    for path, file_id, kind in delta.removed:
+        print '*** removed %s %r' % (kind, path)
+        if kind == 'file':
+            _diff_one(old_tree.get_file(file_id).readlines(),
+                   [],
+                   sys.stdout,
+                   fromfile=old_label + path,
+                   tofile=DEVNULL)
+
+    for path, file_id, kind in delta.added:
+        print '*** added %s %r' % (kind, path)
+        if kind == 'file':
+            _diff_one([],
+                   new_tree.get_file(file_id).readlines(),
+                   sys.stdout,
+                   fromfile=DEVNULL,
+                   tofile=new_label + path)
+
+    for old_path, new_path, file_id, kind, text_modified in delta.renamed:
+        print '*** renamed %s %r => %r' % (kind, old_path, new_path)
+        if text_modified:
+            _diff_one(old_tree.get_file(file_id).readlines(),
+                   new_tree.get_file(file_id).readlines(),
+                   sys.stdout,
+                   fromfile=old_label + old_path,
+                   tofile=new_label + new_path)
+
+    for path, file_id, kind in delta.modified:
+        print '*** modified %s %r' % (kind, path)
+        if kind == 'file':
+            _diff_one(old_tree.get_file(file_id).readlines(),
+                   new_tree.get_file(file_id).readlines(),
+                   sys.stdout,
+                   fromfile=old_label + path,
+                   tofile=new_label + path)
 
 
 
@@ -252,15 +246,15 @@
     Contains four lists:
 
     added
-        (path, id)
+        (path, id, kind)
     removed
-        (path, id)
+        (path, id, kind)
     renamed
-        (oldpath, newpath, id, text_modified)
+        (oldpath, newpath, id, kind, text_modified)
     modified
-        (path, id)
+        (path, id, kind)
     unchanged
-        (path, id)
+        (path, id, kind)
 
     Each id is listed only once.
 
@@ -278,34 +272,39 @@
 
     def show(self, to_file, show_ids=False, show_unchanged=False):
         def show_list(files):
-            for path, fid in files:
+            for path, fid, kind in files:
+                if kind == 'directory':
+                    path += '/'
+                elif kind == 'symlink':
+                    path += '@'
+                    
                 if show_ids:
                     print >>to_file, '  %-30s %s' % (path, fid)
                 else:
                     print >>to_file, ' ', path
             
         if self.removed:
-            print >>to_file, 'removed files:'
+            print >>to_file, 'removed:'
             show_list(self.removed)
                 
         if self.added:
-            print >>to_file, 'added files:'
+            print >>to_file, 'added:'
             show_list(self.added)
 
         if self.renamed:
-            print >>to_file, 'renamed files:'
-            for oldpath, newpath, fid, text_modified in self.renamed:
+            print >>to_file, 'renamed:'
+            for oldpath, newpath, fid, kind, text_modified in self.renamed:
                 if show_ids:
                     print >>to_file, '  %s => %s %s' % (oldpath, newpath, fid)
                 else:
                     print >>to_file, '  %s => %s' % (oldpath, newpath)
                     
         if self.modified:
-            print >>to_file, 'modified files:'
+            print >>to_file, 'modified:'
             show_list(self.modified)
             
         if show_unchanged and self.unchanged:
-            print >>to_file, 'unchanged files:'
+            print >>to_file, 'unchanged:'
             show_list(self.unchanged)
 
 
@@ -314,12 +313,15 @@
     old_inv = old_tree.inventory
     new_inv = new_tree.inventory
     delta = TreeDelta()
+    mutter('start compare_trees')
     for file_id in old_tree:
         if file_id in new_tree:
             old_path = old_inv.id2path(file_id)
             new_path = new_inv.id2path(file_id)
 
             kind = old_inv.get_file_kind(file_id)
+            assert kind == new_inv.get_file_kind(file_id)
+            
             assert kind in ('file', 'directory', 'symlink', 'root_directory'), \
                    'invalid file kind %r' % kind
             if kind == 'file':
@@ -336,17 +338,21 @@
             # May not be worthwhile.
             
             if old_path != new_path:
-                delta.renamed.append((old_path, new_path, file_id, text_modified))
+                delta.renamed.append((old_path, new_path, file_id, kind,
+                                      text_modified))
             elif text_modified:
-                delta.modified.append((new_path, file_id))
+                delta.modified.append((new_path, file_id, kind))
             elif want_unchanged:
-                delta.unchanged.append((new_path, file_id))
+                delta.unchanged.append((new_path, file_id, kind))
         else:
-            delta.removed.append((old_inv.id2path(file_id), file_id))
+            delta.removed.append((old_inv.id2path(file_id), file_id, kind))
+
+    mutter('start looking for new files')
     for file_id in new_inv:
         if file_id in old_inv:
             continue
-        delta.added.append((new_inv.id2path(file_id), file_id))
+        kind = new_inv.get_file_kind(file_id)
+        delta.added.append((new_inv.id2path(file_id), file_id, kind))
             
     delta.removed.sort()
     delta.added.sort()

=== modified file 'bzrlib/tree.py'
--- a/bzrlib/tree.py	2005-05-11 04:57:13 +0000
+++ b/bzrlib/tree.py	2005-05-11 07:45:56 +0000
@@ -20,7 +20,7 @@
 from sets import Set
 import os.path, os, fnmatch
 
-from osutils import pumpfile, compare_files, filesize, quotefn, sha_file, \
+from osutils import pumpfile, filesize, quotefn, sha_file, \
      joinpath, splitpath, appendpath, isdir, isfile, file_kind, fingerprint_file
 import errno
 from stat import S_ISREG, S_ISDIR, ST_MODE, ST_SIZE



More information about the Pkg-bazaar-commits mailing list