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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43
42
from bzrlib.symbol_versioning import (
46
from bzrlib.trace import mutter, note, warning
46
from bzrlib.trace import mutter, 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'
104
107
to_file.write(line)
172
175
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')
179
177
diffcmd = ['diff',
180
178
'--label', old_filename,
206
204
diffcmd.append('-u')
209
207
diffcmd.extend(diff_opts)
211
209
pipe = _spawn_external_diff(diffcmd, capture_errors=True)
212
210
out,err = pipe.communicate()
213
211
rc = pipe.returncode
215
213
# internal_diff() adds a trailing newline, add one here for consistency
280
def _get_trees_to_diff(path_list, revision_specs, old_url, new_url,
278
def _get_trees_to_diff(path_list, revision_specs, old_url, new_url):
282
279
"""Get the trees and specific files to diff given a list of paths.
284
281
This method works out the trees to be diff'ed and the files of
296
293
The url of the new branch or tree. If None, the tree to use is
297
294
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
302
296
a tuple of (old_tree, new_tree, specific_files, extra_trees) where
303
297
extra_trees is a sequence of additional trees to search in for
337
331
working_tree, branch, relpath = \
338
332
bzrdir.BzrDir.open_containing_tree_or_branch(old_url)
339
333
if consider_relpath and relpath != '':
340
if working_tree is not None and apply_view:
341
views.check_path_in_view(working_tree, relpath)
342
334
specific_files.append(relpath)
343
335
old_tree = _get_tree_to_diff(old_revision_spec, working_tree, branch)
349
341
working_tree, branch, relpath = \
350
342
bzrdir.BzrDir.open_containing_tree_or_branch(new_url)
351
343
if consider_relpath and relpath != '':
352
if working_tree is not None and apply_view:
353
views.check_path_in_view(working_tree, relpath)
354
344
specific_files.append(relpath)
355
345
new_tree = _get_tree_to_diff(new_revision_spec, working_tree, branch,
356
346
basis_is_default=working_tree is None)
358
348
# Get the specific files (all files is None, no files is [])
359
349
if make_paths_wt_relative and working_tree is not None:
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")
350
other_paths = _relative_paths_in_tree(working_tree, other_paths)
366
351
specific_files.extend(other_paths)
367
352
if len(specific_files) == 0:
368
353
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)
377
355
# Get extra trees that ought to be searched for file-ids
378
356
extra_trees = None
380
358
extra_trees = (working_tree,)
381
359
return old_tree, new_tree, specific_files, extra_trees
383
362
def _get_tree_to_diff(spec, tree=None, branch=None, basis_is_default=True):
384
363
if branch is None and tree is not None:
385
364
branch = tree.branch
391
370
return branch.basis_tree()
394
return spec.as_tree(branch)
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")
397
394
def show_diff_trees(old_tree, new_tree, to_file, specific_files=None,
445
442
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)"
448
471
def get_executable_change(old_is_x, new_is_x):
449
472
descr = { True:"+x", False:"-x", None:"??" }
450
473
if old_is_x != new_is_x:
625
648
return self.CANNOT_DIFF
626
649
from_label = '%s%s\t%s' % (self.old_label, old_path, old_date)
627
650
to_label = '%s%s\t%s' % (self.new_label, new_path, new_date)
628
return self.diff_text(from_file_id, to_file_id, from_label, to_label,
651
return self.diff_text(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):
653
def diff_text(self, from_file_id, to_file_id, from_label, to_label):
633
654
"""Diff the content of given files in two trees
635
656
:param from_file_id: The id of the file in the from tree. If None,
637
658
:param to_file_id: The id of the file in the to tree. This may refer
638
659
to a different file from from_file_id. If None,
639
660
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.
643
def _get_text(tree, file_id, path):
662
def _get_text(tree, file_id):
644
663
if file_id is not None:
645
return tree.get_file(file_id, path).readlines()
664
return tree.get_file(file_id).readlines()
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)
668
from_text = _get_text(self.old_tree, from_file_id)
669
to_text = _get_text(self.new_tree, to_file_id)
651
670
self.text_differ(from_label, from_text, to_label, to_text,
653
672
except errors.BinaryFile:
740
759
return old_disk_path, new_disk_path
742
761
def finish(self):
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))
762
osutils.rmtree(self._root)
750
764
def diff(self, file_id, old_path, new_path, old_kind, new_kind):
751
765
if (old_kind, new_kind) != ('file', 'file'):
896
910
self.to_file.write("=== modified %s '%s'%s\n" % (kind[0],
897
911
newpath_encoded, prop_str))
898
912
if changed_content:
899
self._diff(file_id, oldpath, newpath, kind[0], kind[1])
913
self.diff(file_id, oldpath, newpath)
917
931
new_kind = self.new_tree.kind(file_id)
918
932
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):
924
935
result = DiffPath._diff_many(self.differs, file_id, old_path,
925
936
new_path, old_kind, new_kind)
926
937
if result is DiffPath.CANNOT_DIFF: