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 mutter, 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)
99
99
ud[2] = ud[2].replace('-1,0', '-0,0')
100
100
elif not newlines:
101
101
ud[2] = ud[2].replace('+1,0', '+0,0')
102
# work around for difflib emitting random spaces after the label
103
ud[0] = ud[0][:-2] + '\n'
104
ud[1] = ud[1][:-2] + '\n'
107
104
to_file.write(line)
175
172
if not diff_opts:
174
if sys.platform == 'win32':
175
# Popen doesn't do the proper encoding for external commands
176
# Since we are dealing with an ANSI api, use mbcs encoding
177
old_filename = old_filename.encode('mbcs')
178
new_filename = new_filename.encode('mbcs')
177
179
diffcmd = ['diff',
178
180
'--label', old_filename,
204
206
diffcmd.append('-u')
207
209
diffcmd.extend(diff_opts)
209
211
pipe = _spawn_external_diff(diffcmd, capture_errors=True)
210
212
out,err = pipe.communicate()
211
213
rc = pipe.returncode
213
215
# internal_diff() adds a trailing newline, add one here for consistency
278
def _get_trees_to_diff(path_list, revision_specs, old_url, new_url):
280
def _get_trees_to_diff(path_list, revision_specs, old_url, new_url,
279
282
"""Get the trees and specific files to diff given a list of paths.
281
284
This method works out the trees to be diff'ed and the files of
293
296
The url of the new branch or tree. If None, the tree to use is
294
297
taken from the first path, if any, or the current working tree.
299
if True and a view is set, apply the view or check that the paths
296
302
a tuple of (old_tree, new_tree, specific_files, extra_trees) where
297
303
extra_trees is a sequence of additional trees to search in for
331
337
working_tree, branch, relpath = \
332
338
bzrdir.BzrDir.open_containing_tree_or_branch(old_url)
333
339
if consider_relpath and relpath != '':
340
if working_tree is not None and apply_view:
341
views.check_path_in_view(working_tree, relpath)
334
342
specific_files.append(relpath)
335
343
old_tree = _get_tree_to_diff(old_revision_spec, working_tree, branch)
341
349
working_tree, branch, relpath = \
342
350
bzrdir.BzrDir.open_containing_tree_or_branch(new_url)
343
351
if consider_relpath and relpath != '':
352
if working_tree is not None and apply_view:
353
views.check_path_in_view(working_tree, relpath)
344
354
specific_files.append(relpath)
345
355
new_tree = _get_tree_to_diff(new_revision_spec, working_tree, branch,
346
356
basis_is_default=working_tree is None)
348
358
# Get the specific files (all files is None, no files is [])
349
359
if make_paths_wt_relative and working_tree is not None:
350
other_paths = _relative_paths_in_tree(working_tree, other_paths)
361
from bzrlib.builtins import safe_relpath_files
362
other_paths = safe_relpath_files(working_tree, other_paths,
363
apply_view=apply_view)
364
except errors.FileInWrongBranch:
365
raise errors.BzrCommandError("Files are in different branches")
351
366
specific_files.extend(other_paths)
352
367
if len(specific_files) == 0:
353
368
specific_files = None
369
if (working_tree is not None and working_tree.supports_views()
371
view_files = working_tree.views.lookup_view()
373
specific_files = view_files
374
view_str = views.view_display_str(view_files)
375
note("*** Ignoring files outside view. View is %s" % view_str)
355
377
# Get extra trees that ought to be searched for file-ids
356
378
extra_trees = None
358
380
extra_trees = (working_tree,)
359
381
return old_tree, new_tree, specific_files, extra_trees
362
383
def _get_tree_to_diff(spec, tree=None, branch=None, basis_is_default=True):
363
384
if branch is None and tree is not None:
364
385
branch = tree.branch
370
391
return branch.basis_tree()
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)
379
def _relative_paths_in_tree(tree, paths):
380
"""Get the relative paths within a working tree.
382
Each path may be either an absolute path or a path relative to the
383
current working directory.
386
for filename in paths:
388
result.append(tree.relpath(osutils.dereference_path(filename)))
389
except errors.PathNotChild:
390
raise errors.BzrCommandError("Files are in different branches")
394
return spec.as_tree(branch)
394
397
def show_diff_trees(old_tree, new_tree, to_file, specific_files=None,
442
445
return timestamp.format_patch_date(mtime)
445
def _raise_if_nonexistent(paths, old_tree, new_tree):
446
"""Complain if paths are not in either inventory or tree.
448
It's OK with the files exist in either tree's inventory, or
449
if they exist in the tree but are not versioned.
451
This can be used by operations such as bzr status that can accept
452
unknown or ignored files.
454
mutter("check paths: %r", paths)
457
s = old_tree.filter_unversioned_files(paths)
458
s = new_tree.filter_unversioned_files(s)
459
s = [path for path in s if not new_tree.has_filename(path)]
461
raise errors.PathsDoNotExist(sorted(s))
464
@deprecated_function(one_three)
465
def get_prop_change(meta_modified):
467
return " (properties changed)"
471
448
def get_executable_change(old_is_x, new_is_x):
472
449
descr = { True:"+x", False:"-x", None:"??" }
473
450
if old_is_x != new_is_x:
648
625
return self.CANNOT_DIFF
649
626
from_label = '%s%s\t%s' % (self.old_label, old_path, old_date)
650
627
to_label = '%s%s\t%s' % (self.new_label, new_path, new_date)
651
return self.diff_text(from_file_id, to_file_id, from_label, to_label)
628
return self.diff_text(from_file_id, to_file_id, from_label, to_label,
653
def diff_text(self, from_file_id, to_file_id, from_label, to_label):
631
def diff_text(self, from_file_id, to_file_id, from_label, to_label,
632
from_path=None, to_path=None):
654
633
"""Diff the content of given files in two trees
656
635
:param from_file_id: The id of the file in the from tree. If None,
658
637
:param to_file_id: The id of the file in the to tree. This may refer
659
638
to a different file from from_file_id. If None,
660
639
the file is not present in the to tree.
640
:param from_path: The path in the from tree or None if unknown.
641
:param to_path: The path in the to tree or None if unknown.
662
def _get_text(tree, file_id):
643
def _get_text(tree, file_id, path):
663
644
if file_id is not None:
664
return tree.get_file(file_id).readlines()
645
return tree.get_file(file_id, path).readlines()
668
from_text = _get_text(self.old_tree, from_file_id)
669
to_text = _get_text(self.new_tree, to_file_id)
649
from_text = _get_text(self.old_tree, from_file_id, from_path)
650
to_text = _get_text(self.new_tree, to_file_id, to_path)
670
651
self.text_differ(from_label, from_text, to_label, to_text,
672
653
except errors.BinaryFile:
759
740
return old_disk_path, new_disk_path
761
742
def finish(self):
762
osutils.rmtree(self._root)
744
osutils.rmtree(self._root)
746
if e.errno != errno.ENOENT:
747
mutter("The temporary directory \"%s\" was not "
748
"cleanly removed: %s." % (self._root, e))
764
750
def diff(self, file_id, old_path, new_path, old_kind, new_kind):
765
751
if (old_kind, new_kind) != ('file', 'file'):
910
896
self.to_file.write("=== modified %s '%s'%s\n" % (kind[0],
911
897
newpath_encoded, prop_str))
912
898
if changed_content:
913
self.diff(file_id, oldpath, newpath)
899
self._diff(file_id, oldpath, newpath, kind[0], kind[1])
931
917
new_kind = self.new_tree.kind(file_id)
932
918
except (errors.NoSuchId, errors.NoSuchFile):
920
self._diff(file_id, old_path, new_path, old_kind, new_kind)
923
def _diff(self, file_id, old_path, new_path, old_kind, new_kind):
935
924
result = DiffPath._diff_many(self.differs, file_id, old_path,
936
925
new_path, old_kind, new_kind)
937
926
if result is DiffPath.CANNOT_DIFF: