~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/diff.py

  • Committer: John Arbash Meinel
  • Date: 2005-11-08 18:36:26 UTC
  • mto: This revision was merged to the branch mainline in revision 1727.
  • Revision ID: john@arbash-meinel.com-20051108183626-71f8414338043265
Updating unified_diff to take a factory, using the new diff algorithm in the code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
# invoke callbacks on an object.  That object can either accumulate a
23
23
# list, write them out directly, etc etc.
24
24
 
25
 
def internal_diff(old_label, oldlines, new_label, newlines, to_file):
26
 
    import difflib
 
25
def internal_diff(old_label, oldlines, new_label, newlines, to_file,
 
26
        sequence_matcher=None):
 
27
    from bzrlib.cdvdifflib import unified_diff
 
28
    from bzrlib.cdvdifflib import SequenceMatcher
27
29
    
28
30
    # FIXME: difflib is wrong if there is no trailing newline.
29
31
    # The syntax used by patch seems to be "\ No newline at
41
43
    if not oldlines and not newlines:
42
44
        return
43
45
 
44
 
    ud = difflib.unified_diff(oldlines, newlines,
45
 
                              fromfile=old_label, tofile=new_label)
 
46
    if sequence_matcher is None:
 
47
        sequence_matcher = SequenceMatcher
 
48
    ud = unified_diff(oldlines, newlines,
 
49
                      fromfile=old_label, tofile=new_label,
 
50
                      sequencematcher=sequence_matcher)
46
51
 
47
52
    ud = list(ud)
48
53
    # work-around for difflib being too smart for its own good
62
67
    print >>to_file
63
68
 
64
69
 
65
 
 
66
 
 
67
70
def external_diff(old_label, oldlines, new_label, newlines, to_file,
68
71
                  diff_opts):
69
72
    """Display a diff by calling out to the external diff program."""
141
144
    finally:
142
145
        oldtmpf.close()                 # and delete
143
146
        newtmpf.close()
144
 
    
145
 
 
146
 
 
147
 
def show_diff(b, revision, specific_files, external_diff_options=None,
 
147
 
 
148
def show_diff(b, from_spec, specific_files, external_diff_options=None,
148
149
              revision2=None, output=None):
149
150
    """Shortcut for showing the diff to the working tree.
150
151
 
152
153
        Branch.
153
154
 
154
155
    revision
155
 
        None for each, or otherwise the old revision to compare against.
 
156
        None for 'basis tree', or otherwise the old revision to compare against.
156
157
    
157
158
    The more general form is show_diff_trees(), where the caller
158
159
    supplies any two trees.
161
162
        import sys
162
163
        output = sys.stdout
163
164
 
164
 
    if revision == None:
 
165
    if from_spec is None:
165
166
        old_tree = b.basis_tree()
166
167
    else:
167
 
        old_tree = b.revision_tree(b.lookup_revision(revision))
 
168
        old_tree = b.revision_tree(from_spec.in_history(b).rev_id)
168
169
 
169
 
    if revision2 == None:
 
170
    if revision2 is None:
170
171
        new_tree = b.working_tree()
171
172
    else:
172
 
        new_tree = b.revision_tree(b.lookup_revision(revision2))
 
173
        new_tree = b.revision_tree(revision2.in_history(b).rev_id)
173
174
 
174
 
    show_diff_trees(old_tree, new_tree, output, specific_files,
175
 
                    external_diff_options)
 
175
    return show_diff_trees(old_tree, new_tree, output, specific_files,
 
176
                           external_diff_options)
176
177
 
177
178
 
178
179
 
211
212
    delta = compare_trees(old_tree, new_tree, want_unchanged=False,
212
213
                          specific_files=specific_files)
213
214
 
 
215
    has_changes = 0
214
216
    for path, file_id, kind in delta.removed:
 
217
        has_changes = 1
215
218
        print >>to_file, '=== removed %s %r' % (kind, path)
216
 
        if kind == 'file':
217
 
            diff_file(old_label + path,
218
 
                      old_tree.get_file(file_id).readlines(),
219
 
                      DEVNULL, 
220
 
                      [],
221
 
                      to_file)
222
 
 
 
219
        old_tree.inventory[file_id].diff(diff_file, old_label + path, old_tree,
 
220
                                         DEVNULL, None, None, to_file)
223
221
    for path, file_id, kind in delta.added:
 
222
        has_changes = 1
224
223
        print >>to_file, '=== added %s %r' % (kind, path)
225
 
        if kind == 'file':
226
 
            diff_file(DEVNULL,
227
 
                      [],
228
 
                      new_label + path,
229
 
                      new_tree.get_file(file_id).readlines(),
230
 
                      to_file)
231
 
 
232
 
    for old_path, new_path, file_id, kind, text_modified in delta.renamed:
233
 
        print >>to_file, '=== renamed %s %r => %r' % (kind, old_path, new_path)
 
224
        new_tree.inventory[file_id].diff(diff_file, new_label + path, new_tree,
 
225
                                         DEVNULL, None, None, to_file, 
 
226
                                         reverse=True)
 
227
    for (old_path, new_path, file_id, kind,
 
228
         text_modified, meta_modified) in delta.renamed:
 
229
        has_changes = 1
 
230
        prop_str = get_prop_change(meta_modified)
 
231
        print >>to_file, '=== renamed %s %r => %r%s' % (
 
232
                          kind, old_path, new_path, prop_str)
 
233
        _maybe_diff_file_or_symlink(old_label, old_path, old_tree, file_id,
 
234
                                    new_label, new_path, new_tree,
 
235
                                    text_modified, kind, to_file, diff_file)
 
236
    for path, file_id, kind, text_modified, meta_modified in delta.modified:
 
237
        has_changes = 1
 
238
        prop_str = get_prop_change(meta_modified)
 
239
        print >>to_file, '=== modified %s %r%s' % (kind, path, prop_str)
234
240
        if text_modified:
235
 
            diff_file(old_label + old_path,
236
 
                      old_tree.get_file(file_id).readlines(),
237
 
                      new_label + new_path,
238
 
                      new_tree.get_file(file_id).readlines(),
239
 
                      to_file)
240
 
 
241
 
    for path, file_id, kind in delta.modified:
242
 
        print >>to_file, '=== modified %s %r' % (kind, path)
243
 
        if kind == 'file':
244
 
            diff_file(old_label + path,
245
 
                      old_tree.get_file(file_id).readlines(),
246
 
                      new_label + path,
247
 
                      new_tree.get_file(file_id).readlines(),
248
 
                      to_file)
249
 
 
250
 
 
251
 
 
252
 
 
253
 
 
 
241
            _maybe_diff_file_or_symlink(old_label, path, old_tree, file_id,
 
242
                                        new_label, path, new_tree,
 
243
                                        True, kind, to_file, diff_file)
 
244
    return has_changes
 
245
    
 
246
 
 
247
def get_prop_change(meta_modified):
 
248
    if meta_modified:
 
249
        return " (properties changed)"
 
250
    else:
 
251
        return  ""
 
252
 
 
253
 
 
254
def _maybe_diff_file_or_symlink(old_label, old_path, old_tree, file_id,
 
255
                                new_label, new_path, new_tree, text_modified,
 
256
                                kind, to_file, diff_file):
 
257
    if text_modified:
 
258
        new_entry = new_tree.inventory[file_id]
 
259
        old_tree.inventory[file_id].diff(diff_file,
 
260
                                         old_label + old_path, old_tree,
 
261
                                         new_label + new_path, new_entry, 
 
262
                                         new_tree, to_file)