277
@deprecated_function(one_zero)
278
def diff_cmd_helper(tree, specific_files, external_diff_options,
279
old_revision_spec=None, new_revision_spec=None,
281
old_label='a/', new_label='b/'):
282
"""Helper for cmd_diff.
287
:param specific_files:
288
The specific files to compare, or None
290
:param external_diff_options:
291
If non-None, run an external diff, and pass it these options
293
:param old_revision_spec:
294
If None, use basis tree as old revision, otherwise use the tree for
295
the specified revision.
297
:param new_revision_spec:
298
If None, use working tree as new revision, otherwise use the tree for
299
the specified revision.
301
:param revision_specs:
302
Zero, one or two RevisionSpecs from the command line, saying what revisions
303
to compare. This can be passed as an alternative to the old_revision_spec
304
and new_revision_spec parameters.
306
The more general form is show_diff_trees(), where the caller
307
supplies any two trees.
310
# TODO: perhaps remove the old parameters old_revision_spec and
311
# new_revision_spec, since this is only really for use from cmd_diff and
312
# it now always passes through a sequence of revision_specs -- mbp
317
revision = spec.in_store(tree.branch)
319
revision = spec.in_store(None)
320
revision_id = revision.rev_id
321
branch = revision.branch
322
return branch.repository.revision_tree(revision_id)
324
if revision_specs is not None:
325
assert (old_revision_spec is None
326
and new_revision_spec is None)
327
if len(revision_specs) > 0:
328
old_revision_spec = revision_specs[0]
329
if len(revision_specs) > 1:
330
new_revision_spec = revision_specs[1]
332
if old_revision_spec is None:
333
old_tree = tree.basis_tree()
335
old_tree = spec_tree(old_revision_spec)
337
if (new_revision_spec is None
338
or new_revision_spec.spec is None):
341
new_tree = spec_tree(new_revision_spec)
343
if new_tree is not tree:
344
extra_trees = (tree,)
348
return show_diff_trees(old_tree, new_tree, sys.stdout, specific_files,
349
external_diff_options,
350
old_label=old_label, new_label=new_label,
351
extra_trees=extra_trees)
354
278
def _get_trees_to_diff(path_list, revision_specs, old_url, new_url):
355
279
"""Get the trees and specific files to diff given a list of paths.
446
370
return branch.basis_tree()
449
revision = spec.in_store(branch)
450
revision_id = revision.rev_id
451
rev_branch = revision.branch
452
return rev_branch.repository.revision_tree(revision_id)
373
if not spec.needs_branch():
374
branch = _mod_branch.Branch.open(spec.get_branch())
375
revision_id = spec.as_revision_id(branch)
376
return branch.repository.revision_tree(revision_id)
455
379
def _relative_paths_in_tree(tree, paths):
515
439
def _patch_header_date(tree, file_id, path):
516
440
"""Returns a timestamp suitable for use in a patch header."""
517
441
mtime = tree.get_file_mtime(file_id, path)
518
assert mtime is not None, \
519
"got an mtime of None for file-id %s, path %s in tree %s" % (
521
442
return timestamp.format_patch_date(mtime)
540
461
raise errors.PathsDoNotExist(sorted(s))
464
@deprecated_function(one_three)
543
465
def get_prop_change(meta_modified):
544
466
if meta_modified:
545
467
return " (properties changed)"
471
def get_executable_change(old_is_x, new_is_x):
472
descr = { True:"+x", False:"-x", None:"??" }
473
if old_is_x != new_is_x:
474
return ["%s to %s" % (descr[old_is_x], descr[new_is_x],)]
550
479
class DiffPath(object):
551
480
"""Base type for command object that compare files"""
905
834
extra_factories = []
906
835
if external_diff_options:
907
assert isinstance(external_diff_options, basestring)
908
836
opts = external_diff_options.split()
909
837
def diff_file(olab, olines, nlab, nlines, to_file):
910
838
external_diff(olab, olines, nlab, nlines, to_file, opts)
930
858
def _show_diff(self, specific_files, extra_trees):
931
859
# TODO: Generation of pseudo-diffs for added/deleted files could
932
860
# be usefully made into a much faster special case.
933
iterator = self.new_tree._iter_changes(self.old_tree,
861
iterator = self.new_tree.iter_changes(self.old_tree,
934
862
specific_files=specific_files,
935
863
extra_trees=extra_trees,
936
864
require_versioned=True)
954
882
old_present = (kind[0] is not None and versioned[0])
955
883
new_present = (kind[1] is not None and versioned[1])
956
884
renamed = (parent[0], name[0]) != (parent[1], name[1])
957
prop_str = get_prop_change(executable[0] != executable[1])
886
properties_changed = []
887
properties_changed.extend(get_executable_change(executable[0], executable[1]))
889
if properties_changed:
890
prop_str = " (properties changed: %s)" % (", ".join(properties_changed),)
958
894
if (old_present, new_present) == (True, False):
959
895
self.to_file.write("=== removed %s '%s'\n" %
960
896
(kind[0], oldpath_encoded))
967
903
self.to_file.write("=== renamed %s '%s' => '%s'%s\n" %
968
904
(kind[0], oldpath_encoded, newpath_encoded, prop_str))
970
# if it was produced by _iter_changes, it must be
906
# if it was produced by iter_changes, it must be
971
907
# modified *somehow*, either content or execute bit.
972
908
self.to_file.write("=== modified %s '%s'%s\n" % (kind[0],
973
909
newpath_encoded, prop_str))