13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
42
43
from bzrlib.symbol_versioning import (
46
from bzrlib.trace import warning
46
from bzrlib.trace import mutter, note, warning
49
49
# TODO: Rather than building a changeset object, we should probably
78
78
# both sequences are empty.
79
79
if not oldlines and not newlines:
82
82
if allow_binary is False:
83
83
textfile.check_text_lines(oldlines)
84
84
textfile.check_text_lines(newlines)
201
201
diffcmd.append('-u')
204
204
diffcmd.extend(diff_opts)
206
206
pipe = _spawn_external_diff(diffcmd, capture_errors=True)
207
207
out,err = pipe.communicate()
208
208
rc = pipe.returncode
210
210
# internal_diff() adds a trailing newline, add one here for consistency
275
def _get_trees_to_diff(path_list, revision_specs, old_url, new_url):
275
def _get_trees_to_diff(path_list, revision_specs, old_url, new_url,
276
277
"""Get the trees and specific files to diff given a list of paths.
278
279
This method works out the trees to be diff'ed and the files of
290
291
The url of the new branch or tree. If None, the tree to use is
291
292
taken from the first path, if any, or the current working tree.
294
if True and a view is set, apply the view or check that the paths
293
297
a tuple of (old_tree, new_tree, specific_files, extra_trees) where
294
298
extra_trees is a sequence of additional trees to search in for
328
332
working_tree, branch, relpath = \
329
333
bzrdir.BzrDir.open_containing_tree_or_branch(old_url)
330
334
if consider_relpath and relpath != '':
335
if working_tree is not None and apply_view:
336
views.check_path_in_view(working_tree, relpath)
331
337
specific_files.append(relpath)
332
338
old_tree = _get_tree_to_diff(old_revision_spec, working_tree, branch)
338
344
working_tree, branch, relpath = \
339
345
bzrdir.BzrDir.open_containing_tree_or_branch(new_url)
340
346
if consider_relpath and relpath != '':
347
if working_tree is not None and apply_view:
348
views.check_path_in_view(working_tree, relpath)
341
349
specific_files.append(relpath)
342
350
new_tree = _get_tree_to_diff(new_revision_spec, working_tree, branch,
343
351
basis_is_default=working_tree is None)
345
353
# Get the specific files (all files is None, no files is [])
346
354
if make_paths_wt_relative and working_tree is not None:
347
other_paths = _relative_paths_in_tree(working_tree, other_paths)
356
from bzrlib.builtins import safe_relpath_files
357
other_paths = safe_relpath_files(working_tree, other_paths,
358
apply_view=apply_view)
359
except errors.FileInWrongBranch:
360
raise errors.BzrCommandError("Files are in different branches")
348
361
specific_files.extend(other_paths)
349
362
if len(specific_files) == 0:
350
363
specific_files = None
364
if (working_tree is not None and working_tree.supports_views()
366
view_files = working_tree.views.lookup_view()
368
specific_files = view_files
369
view_str = views.view_display_str(view_files)
370
note("*** Ignoring files outside view. View is %s" % view_str)
352
372
# Get extra trees that ought to be searched for file-ids
353
373
extra_trees = None
355
375
extra_trees = (working_tree,)
356
376
return old_tree, new_tree, specific_files, extra_trees
359
378
def _get_tree_to_diff(spec, tree=None, branch=None, basis_is_default=True):
360
379
if branch is None and tree is not None:
361
380
branch = tree.branch
370
389
return spec.as_tree(branch)
373
def _relative_paths_in_tree(tree, paths):
374
"""Get the relative paths within a working tree.
376
Each path may be either an absolute path or a path relative to the
377
current working directory.
380
for filename in paths:
382
result.append(tree.relpath(osutils.dereference_path(filename)))
383
except errors.PathNotChild:
384
raise errors.BzrCommandError("Files are in different branches")
388
392
def show_diff_trees(old_tree, new_tree, to_file, specific_files=None,
389
393
external_diff_options=None,
390
394
old_label='a/', new_label='b/',
436
440
return timestamp.format_patch_date(mtime)
439
@deprecated_function(one_three)
440
def get_prop_change(meta_modified):
442
return " (properties changed)"
446
443
def get_executable_change(old_is_x, new_is_x):
447
444
descr = { True:"+x", False:"-x", None:"??" }
448
445
if old_is_x != new_is_x:
623
620
return self.CANNOT_DIFF
624
621
from_label = '%s%s\t%s' % (self.old_label, old_path, old_date)
625
622
to_label = '%s%s\t%s' % (self.new_label, new_path, new_date)
626
return self.diff_text(from_file_id, to_file_id, from_label, to_label)
623
return self.diff_text(from_file_id, to_file_id, from_label, to_label,
628
def diff_text(self, from_file_id, to_file_id, from_label, to_label):
626
def diff_text(self, from_file_id, to_file_id, from_label, to_label,
627
from_path=None, to_path=None):
629
628
"""Diff the content of given files in two trees
631
630
:param from_file_id: The id of the file in the from tree. If None,
633
632
:param to_file_id: The id of the file in the to tree. This may refer
634
633
to a different file from from_file_id. If None,
635
634
the file is not present in the to tree.
635
:param from_path: The path in the from tree or None if unknown.
636
:param to_path: The path in the to tree or None if unknown.
637
def _get_text(tree, file_id):
638
def _get_text(tree, file_id, path):
638
639
if file_id is not None:
639
return tree.get_file(file_id).readlines()
640
return tree.get_file(file_id, path).readlines()
643
from_text = _get_text(self.old_tree, from_file_id)
644
to_text = _get_text(self.new_tree, to_file_id)
644
from_text = _get_text(self.old_tree, from_file_id, from_path)
645
to_text = _get_text(self.new_tree, to_file_id, to_path)
645
646
self.text_differ(from_label, from_text, to_label, to_text,
647
648
except errors.BinaryFile:
734
735
return old_disk_path, new_disk_path
736
737
def finish(self):
737
osutils.rmtree(self._root)
739
osutils.rmtree(self._root)
741
if e.errno != errno.ENOENT:
742
mutter("The temporary directory \"%s\" was not "
743
"cleanly removed: %s." % (self._root, e))
739
745
def diff(self, file_id, old_path, new_path, old_kind, new_kind):
740
746
if (old_kind, new_kind) != ('file', 'file'):
885
891
self.to_file.write("=== modified %s '%s'%s\n" % (kind[0],
886
892
newpath_encoded, prop_str))
887
893
if changed_content:
888
self.diff(file_id, oldpath, newpath)
894
self._diff(file_id, oldpath, newpath, kind[0], kind[1])
906
912
new_kind = self.new_tree.kind(file_id)
907
913
except (errors.NoSuchId, errors.NoSuchFile):
915
self._diff(file_id, old_path, new_path, old_kind, new_kind)
918
def _diff(self, file_id, old_path, new_path, old_kind, new_kind):
910
919
result = DiffPath._diff_many(self.differs, file_id, old_path,
911
920
new_path, old_kind, new_kind)
912
921
if result is DiffPath.CANNOT_DIFF: