142
139
old_item = next(old_it)
143
def show_diff(b, revision, file_list):
144
import difflib, sys, types
147
old_tree = b.basis_tree()
149
old_tree = b.revision_tree(b.lookup_revision(revision))
151
new_tree = b.working_tree()
153
# TODO: Options to control putting on a prefix or suffix, perhaps as a format string
157
DEVNULL = '/dev/null'
158
# Windows users, don't panic about this filename -- it is a
159
# special signal to GNU patch that the file should be created or
160
# deleted respectively.
162
# TODO: Generation of pseudo-diffs for added/deleted files could
163
# be usefully made into a much faster special case.
165
# TODO: Better to return them in sorted order I think.
168
file_list = [b.relpath(f) for f in file_list]
170
# FIXME: If given a file list, compare only those files rather
171
# than comparing everything and then throwing stuff away.
173
for file_state, fid, old_name, new_name, kind in diff_trees(old_tree, new_tree):
175
if file_list and (new_name not in file_list):
178
# Don't show this by default; maybe do it if an option is passed
179
# idlabel = ' {%s}' % fid
182
def diffit(oldlines, newlines, **kw):
184
# FIXME: difflib is wrong if there is no trailing newline.
185
# The syntax used by patch seems to be "\ No newline at
186
# end of file" following the last diff line from that
187
# file. This is not trivial to insert into the
188
# unified_diff output and it might be better to just fix
189
# or replace that function.
191
# In the meantime we at least make sure the patch isn't
195
# Special workaround for Python2.3, where difflib fails if
196
# both sequences are empty.
197
if not oldlines and not newlines:
202
if oldlines and (oldlines[-1][-1] != '\n'):
205
if newlines and (newlines[-1][-1] != '\n'):
209
ud = difflib.unified_diff(oldlines, newlines, **kw)
211
# work-around for difflib being too smart for its own good
212
# if /dev/null is "1,0", patch won't recognize it as /dev/null
215
ud[2] = ud[2].replace('-1,0', '-0,0')
218
ud[2] = ud[2].replace('+1,0', '+0,0')
220
sys.stdout.writelines(ud)
222
print "\\ No newline at end of file"
223
sys.stdout.write('\n')
225
if file_state in ['.', '?', 'I']:
227
elif file_state == 'A':
228
print '*** added %s %r' % (kind, new_name)
231
new_tree.get_file(fid).readlines(),
233
tofile=new_label + new_name + idlabel)
234
elif file_state == 'D':
235
assert isinstance(old_name, types.StringTypes)
236
print '*** deleted %s %r' % (kind, old_name)
238
diffit(old_tree.get_file(fid).readlines(), [],
239
fromfile=old_label + old_name + idlabel,
241
elif file_state in ['M', 'R']:
242
if file_state == 'M':
243
assert kind == 'file'
244
assert old_name == new_name
245
print '*** modified %s %r' % (kind, new_name)
246
elif file_state == 'R':
247
print '*** renamed %s %r => %r' % (kind, old_name, new_name)
250
diffit(old_tree.get_file(fid).readlines(),
251
new_tree.get_file(fid).readlines(),
252
fromfile=old_label + old_name + idlabel,
253
tofile=new_label + new_name)
255
raise BzrError("can't represent state %s {%s}" % (file_state, fid))
260
"""Describes changes from one tree to another.
269
(oldpath, newpath, id)
273
A path may occur in more than one list if it was e.g. deleted
274
under an old id and renamed into place in a new id.
276
Files are listed in either modified or renamed, not both. In
277
other words, renamed files may also be modified.
286
def compare_inventories(old_inv, new_inv):
287
"""Return a TreeDelta object describing changes between inventories.
289
This only describes changes in the shape of the tree, not the
292
This is an alternative to diff_trees() and should probably
293
eventually replace it.
295
old_ids = old_inv.id_set()
296
new_ids = new_inv.id_set()
299
delta.removed = [(old_inv.id2path(fid), fid) for fid in (old_ids - new_ids)]
302
delta.added = [(new_inv.id2path(fid), fid) for fid in (new_ids - old_ids)]
305
for fid in old_ids & new_ids:
306
old_ie = old_inv[fid]
307
new_ie = new_inv[fid]
308
old_path = old_inv.id2path(fid)
309
new_path = new_inv.id2path(fid)
311
if old_path != new_path:
312
delta.renamed.append((old_path, new_path, fid))
313
elif old_ie.text_sha1 != new_ie.text_sha1:
314
delta.modified.append((new_path, fid))
316
delta.modified.sort()