291
@deprecated_function(deprecated_in((2, 2, 0)))
292
def get_trees_and_branches_to_diff(path_list, revision_specs, old_url, new_url,
294
"""Get the trees and specific files to diff given a list of paths.
296
This method works out the trees to be diff'ed and the files of
297
interest within those trees.
300
the list of arguments passed to the diff command
301
:param revision_specs:
302
Zero, one or two RevisionSpecs from the diff command line,
303
saying what revisions to compare.
305
The url of the old branch or tree. If None, the tree to use is
306
taken from the first path, if any, or the current working tree.
308
The url of the new branch or tree. If None, the tree to use is
309
taken from the first path, if any, or the current working tree.
311
if True and a view is set, apply the view or check that the paths
314
a tuple of (old_tree, new_tree, old_branch, new_branch,
315
specific_files, extra_trees) where extra_trees is a sequence of
316
additional trees to search in for file-ids. The trees and branches
319
op = cleanup.OperationWithCleanups(get_trees_and_branches_to_diff_locked)
320
return op.run_simple(path_list, revision_specs, old_url, new_url,
321
op.add_cleanup, apply_view=apply_view)
287
324
def get_trees_and_branches_to_diff_locked(
288
325
path_list, revision_specs, old_url, new_url, add_cleanup, apply_view=True):
289
326
"""Get the trees and specific files to diff given a list of paths.
399
436
extra_trees = None
400
437
if working_tree is not None and working_tree not in (old_tree, new_tree):
401
438
extra_trees = (working_tree,)
402
return (old_tree, new_tree, old_branch, new_branch,
403
specific_files, extra_trees)
439
return old_tree, new_tree, old_branch, new_branch, specific_files, extra_trees
406
442
def _get_tree_to_diff(spec, tree=None, branch=None, basis_is_default=True):
427
463
"""Show in text form the changes from one tree to another.
429
465
:param to_file: The output stream.
430
:param specific_files: Include only changes to these files - None for all
466
:param specific_files:Include only changes to these files - None for all
432
468
:param external_diff_options: If set, use an external GNU diff and pass
710
746
def _get_command(self, old_path, new_path):
711
747
my_map = {'old_path': old_path, 'new_path': new_path}
712
command = [AtTemplate(t).substitute(my_map) for t in
713
self.command_template]
714
if sys.platform == 'win32': # Popen doesn't accept unicode on win32
717
if isinstance(c, unicode):
718
command_encoded.append(c.encode('mbcs'))
720
command_encoded.append(c)
721
return command_encoded
748
return [AtTemplate(t).substitute(my_map) for t in
749
self.command_template]
725
751
def _execute(self, old_path, new_path):
726
752
command = self._get_command(old_path, new_path)
751
"""Returns safe encoding for passing file path to diff tool"""
752
if sys.platform == 'win32':
755
# Don't fallback to 'utf-8' because subprocess may not be able to
756
# handle utf-8 correctly when locale is not utf-8.
757
return sys.getfilesystemencoding() or 'ascii'
759
def _is_safepath(self, path):
760
"""Return true if `path` may be able to pass to subprocess."""
763
return path == path.encode(fenc).decode(fenc)
767
def _safe_filename(self, prefix, relpath):
768
"""Replace unsafe character in `relpath` then join `self._root`,
769
`prefix` and `relpath`."""
771
# encoded_str.replace('?', '_') may break multibyte char.
772
# So we should encode, decode, then replace(u'?', u'_')
773
relpath_tmp = relpath.encode(fenc, 'replace').decode(fenc, 'replace')
774
relpath_tmp = relpath_tmp.replace(u'?', u'_')
775
return osutils.pathjoin(self._root, prefix, relpath_tmp)
777
775
def _write_file(self, file_id, tree, prefix, relpath, force_temp=False,
778
776
allow_write=False):
779
777
if not force_temp and isinstance(tree, WorkingTree):
780
full_path = tree.abspath(tree.id2path(file_id))
781
if self._is_safepath(full_path):
784
full_path = self._safe_filename(prefix, relpath)
778
return tree.abspath(tree.id2path(file_id))
780
full_path = osutils.pathjoin(self._root, prefix, relpath)
785
781
if not force_temp and self._try_symlink_root(tree, prefix):
787
783
parent_dir = osutils.dirname(full_path)
845
841
old_path = self.old_tree.id2path(file_id)
846
842
new_path = self.new_tree.id2path(file_id)
847
old_abs_path, new_abs_path = self._prepare_files(
848
file_id, old_path, new_path,
849
allow_write_new=True,
851
command = self._get_command(old_abs_path, new_abs_path)
843
new_abs_path = self._prepare_files(file_id, old_path, new_path,
844
allow_write_new=True,
846
command = self._get_command(osutils.pathjoin('old', old_path),
847
osutils.pathjoin('new', new_path))
852
848
subprocess.call(command, cwd=self._root)
853
new_file = open(new_abs_path, 'rb')
849
new_file = open(new_abs_path, 'r')
855
851
return new_file.read()
906
902
"""Factory for producing a DiffTree.
908
904
Designed to accept options used by show_diff_trees.
910
905
:param old_tree: The tree to show as old in the comparison
911
906
:param new_tree: The tree to show as new in the comparison
912
907
:param to_file: File to write comparisons to