344
347
extra_trees=extra_trees)
350
def _get_trees_to_diff(path_list, revision_specs, old_url, new_url):
351
"""Get the trees and specific files to diff given a list of paths.
353
This method works out the trees to be diff'ed and the files of
354
interest within those trees.
357
the list of arguments passed to the diff command
358
:param revision_specs:
359
Zero, one or two RevisionSpecs from the diff command line,
360
saying what revisions to compare.
362
The url of the old branch or tree. If None, the tree to use is
363
taken from the first path, if any, or the current working tree.
365
The url of the new branch or tree. If None, the tree to use is
366
taken from the first path, if any, or the current working tree.
368
a tuple of (old_tree, new_tree, specific_files, extra_trees) where
369
extra_trees is a sequence of additional trees to search in for
372
# Get the old and new revision specs
373
old_revision_spec = None
374
new_revision_spec = None
375
if revision_specs is not None:
376
if len(revision_specs) > 0:
377
old_revision_spec = revision_specs[0]
378
if len(revision_specs) > 1:
379
new_revision_spec = revision_specs[1]
380
# If both revision specs include a branch, we can diff them
381
# without needing to look further for the details
382
if (old_revision_spec is not None and
383
new_revision_spec is not None and
384
not old_revision_spec.needs_branch() and
385
not new_revision_spec.needs_branch()):
386
old_tree = _get_tree_to_diff(old_revision_spec)
387
new_tree = _get_tree_to_diff(new_revision_spec)
388
specific_files = path_list or None
389
return old_tree, new_tree, specific_files, None
391
# If no path is given, assume the current directory
392
if path_list is None or len(path_list) == 0:
393
default_location = u'.'
396
elif old_url is not None and new_url is not None:
397
default_location = None # don't care - not required
398
other_paths = path_list
401
default_location = path_list[0]
402
other_paths = path_list[1:]
405
# Get the old location
407
old_url = default_location
408
working_tree, branch, relpath = \
409
bzrdir.BzrDir.open_containing_tree_or_branch(old_url)
410
old_tree = _get_tree_to_diff(old_revision_spec, working_tree, branch)
412
# Get the new location
414
new_url = default_location
415
if new_url != old_url:
416
working_tree, branch, relpath = \
417
bzrdir.BzrDir.open_containing_tree_or_branch(new_url)
418
new_tree = _get_tree_to_diff(new_revision_spec, working_tree, branch,
419
basis_is_default=working_tree is None)
421
# Get the specific files and extra trees
422
specific_files = _relative_files_for_diff(working_tree, relpath,
423
other_paths, check_paths)
425
if new_tree != working_tree and working_tree is not None:
426
extra_trees = (working_tree,)
427
return old_tree, new_tree, specific_files, extra_trees
430
def _get_tree_to_diff(spec, tree=None, branch=None, basis_is_default=True):
431
if branch is None and tree is not None:
433
if spec is None or spec.spec is None:
435
return branch.basis_tree()
438
revision = spec.in_store(branch)
439
revision_id = revision.rev_id
440
rev_branch = revision.branch
441
return rev_branch.repository.revision_tree(revision_id)
444
def _relative_files_for_diff(tree, first_relpath, other_paths, check_paths):
445
"""Get the specific files for diff.
447
This method converts path arguments to relative paths in a tree.
448
If the tree is None or check_paths is False, other_paths are assumed
449
to be relative already. Otherwise, all arguments must be paths in
453
if first_relpath != '':
454
specific_files.append(first_relpath)
455
if not check_paths or tree is None:
456
specific_files.extend(other_paths)
458
for filename in other_paths:
460
specific_files.append(tree.relpath(osutils.dereference_path(
462
except errors.PathNotChild:
463
raise errors.BzrCommandError("Files are in different branches")
464
if len(specific_files) == 0:
465
specific_files = None
466
return specific_files
347
469
def show_diff_trees(old_tree, new_tree, to_file, specific_files=None,
348
470
external_diff_options=None,
349
471
old_label='a/', new_label='b/',