~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/diff.py

  • Committer: Martin Pool
  • Date: 2005-05-27 01:49:33 UTC
  • Revision ID: mbp@sourcefrog.net-20050527014933-6fedad7023903605
- start adding support for showing diffs by calling out to 
  an external program rather than using difflib

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
from errors import BzrError
20
20
 
21
21
 
22
 
 
23
 
def _diff_one(oldlines, newlines, to_file, **kw):
 
22
def internal_diff(old_label, oldlines, new_label, newlines, to_file):
24
23
    import difflib
25
24
    
26
25
    # FIXME: difflib is wrong if there is no trailing newline.
48
47
        newlines[-1] += '\n'
49
48
        nonl = True
50
49
 
51
 
    ud = difflib.unified_diff(oldlines, newlines, **kw)
 
50
    ud = difflib.unified_diff(oldlines, newlines,
 
51
                              fromfile=old_label, tofile=new_label)
52
52
 
53
53
    # work-around for difflib being too smart for its own good
54
54
    # if /dev/null is "1,0", patch won't recognize it as /dev/null
66
66
 
67
67
 
68
68
 
 
69
 
 
70
def external_diff(old_label, oldlines, new_label, newlines, to_file):
 
71
    """Display a diff by calling out to the external diff program."""
 
72
    import sys
 
73
    
 
74
    if to_file != sys.stdout:
 
75
        raise NotImplementedError("sorry, can't send external diff other than to stdout yet",
 
76
                                  to_file)
 
77
 
 
78
    from tempfile import NamedTemporaryFile
 
79
    from os import system
 
80
 
 
81
    oldtmpf = NamedTemporaryFile()
 
82
    newtmpf = NamedTemporaryFile()
 
83
 
 
84
    try:
 
85
        # TODO: perhaps a special case for comparing to or from the empty
 
86
        # sequence; can just use /dev/null on Unix
 
87
 
 
88
        # TODO: if either of the files being compared already exists as a
 
89
        # regular named file (e.g. in the working directory) then we can
 
90
        # compare directly to that, rather than copying it.
 
91
 
 
92
        # TODO: Set the labels appropriately
 
93
 
 
94
        oldtmpf.writelines(oldlines)
 
95
        newtmpf.writelines(newlines)
 
96
 
 
97
        oldtmpf.flush()
 
98
        newtmpf.flush()
 
99
 
 
100
        system('diff -u --label %s %s --label %s %s' % (old_label, oldtmpf.name, new_label, newtmpf.name))
 
101
    finally:
 
102
        oldtmpf.close()                 # and delete
 
103
        newtmpf.close()
 
104
    
 
105
 
 
106
 
 
107
def diff_file(old_label, oldlines, new_label, newlines, to_file):
 
108
    if True:
 
109
        differ = external_diff
 
110
    else:
 
111
        differ = internal_diff
 
112
 
 
113
    differ(old_label, oldlines, new_label, newlines, to_file)
 
114
 
 
115
 
 
116
 
69
117
def show_diff(b, revision, specific_files):
70
118
    import sys
71
119
 
105
153
    for path, file_id, kind in delta.removed:
106
154
        print '*** removed %s %r' % (kind, path)
107
155
        if kind == 'file':
108
 
            _diff_one(old_tree.get_file(file_id).readlines(),
109
 
                   [],
110
 
                   to_file,
111
 
                   fromfile=old_label + path,
112
 
                   tofile=DEVNULL)
 
156
            diff_file(old_label + path,
 
157
                      old_tree.get_file(file_id).readlines(),
 
158
                      DEVNULL, 
 
159
                      [],
 
160
                      to_file)
113
161
 
114
162
    for path, file_id, kind in delta.added:
115
163
        print '*** added %s %r' % (kind, path)
116
164
        if kind == 'file':
117
 
            _diff_one([],
118
 
                   new_tree.get_file(file_id).readlines(),
119
 
                   to_file,
120
 
                   fromfile=DEVNULL,
121
 
                   tofile=new_label + path)
 
165
            diff_file(DEVNULL,
 
166
                      [],
 
167
                      new_label + path,
 
168
                      new_tree.get_file(file_id).readlines(),
 
169
                      to_file)
122
170
 
123
171
    for old_path, new_path, file_id, kind, text_modified in delta.renamed:
124
172
        print '*** renamed %s %r => %r' % (kind, old_path, new_path)
125
173
        if text_modified:
126
 
            _diff_one(old_tree.get_file(file_id).readlines(),
127
 
                   new_tree.get_file(file_id).readlines(),
128
 
                   to_file,
129
 
                   fromfile=old_label + old_path,
130
 
                   tofile=new_label + new_path)
 
174
            diff_file(old_label + old_path,
 
175
                      old_tree.get_file(file_id).readlines(),
 
176
                      new_label + new_path,
 
177
                      new_tree.get_file(file_id).readlines(),
 
178
                      to_file)
131
179
 
132
180
    for path, file_id, kind in delta.modified:
133
181
        print '*** modified %s %r' % (kind, path)
134
182
        if kind == 'file':
135
 
            _diff_one(old_tree.get_file(file_id).readlines(),
136
 
                   new_tree.get_file(file_id).readlines(),
137
 
                   to_file,
138
 
                   fromfile=old_label + path,
139
 
                   tofile=new_label + path)
 
183
            diff_file(old_label + path,
 
184
                      old_tree.get_file(file_id).readlines(),
 
185
                      new_label + path,
 
186
                      new_tree.get_file(file_id).readlines(),
 
187
                      to_file)
140
188
 
141
189
 
142
190