1
# Copyright (C) 2004, 2005, 2006 Canonical Ltd.
1
# Copyright (C) 2005-2010 Canonical Ltd.
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
293
@deprecated_function(deprecated_in((2, 2, 0)))
287
294
def get_trees_and_branches_to_diff(path_list, revision_specs, old_url, new_url,
288
295
apply_view=True):
289
296
"""Get the trees and specific files to diff given a list of paths.
309
316
a tuple of (old_tree, new_tree, old_branch, new_branch,
310
317
specific_files, extra_trees) where extra_trees is a sequence of
311
additional trees to search in for file-ids.
318
additional trees to search in for file-ids. The trees and branches
321
op = cleanup.OperationWithCleanups(get_trees_and_branches_to_diff_locked)
322
return op.run_simple(path_list, revision_specs, old_url, new_url,
323
op.add_cleanup, apply_view=apply_view)
326
def get_trees_and_branches_to_diff_locked(
327
path_list, revision_specs, old_url, new_url, add_cleanup, apply_view=True):
328
"""Get the trees and specific files to diff given a list of paths.
330
This method works out the trees to be diff'ed and the files of
331
interest within those trees.
334
the list of arguments passed to the diff command
335
:param revision_specs:
336
Zero, one or two RevisionSpecs from the diff command line,
337
saying what revisions to compare.
339
The url of the old branch or tree. If None, the tree to use is
340
taken from the first path, if any, or the current working tree.
342
The url of the new branch or tree. If None, the tree to use is
343
taken from the first path, if any, or the current working tree.
345
a callable like Command.add_cleanup. get_trees_and_branches_to_diff
346
will register cleanups that must be run to unlock the trees, etc.
348
if True and a view is set, apply the view or check that the paths
351
a tuple of (old_tree, new_tree, old_branch, new_branch,
352
specific_files, extra_trees) where extra_trees is a sequence of
353
additional trees to search in for file-ids. The trees and branches
354
will be read-locked until the cleanups registered via the add_cleanup
313
357
# Get the old and new revision specs
314
358
old_revision_spec = None
337
381
default_location = path_list[0]
338
382
other_paths = path_list[1:]
384
def lock_tree_or_branch(wt, br):
387
add_cleanup(wt.unlock)
390
add_cleanup(br.unlock)
340
392
# Get the old location
341
393
specific_files = []
342
394
if old_url is None:
343
395
old_url = default_location
344
396
working_tree, branch, relpath = \
345
397
bzrdir.BzrDir.open_containing_tree_or_branch(old_url)
398
lock_tree_or_branch(working_tree, branch)
346
399
if consider_relpath and relpath != '':
347
400
if working_tree is not None and apply_view:
348
401
views.check_path_in_view(working_tree, relpath)
356
409
if new_url != old_url:
357
410
working_tree, branch, relpath = \
358
411
bzrdir.BzrDir.open_containing_tree_or_branch(new_url)
412
lock_tree_or_branch(working_tree, branch)
359
413
if consider_relpath and relpath != '':
360
414
if working_tree is not None and apply_view:
361
415
views.check_path_in_view(working_tree, relpath)
409
463
old_label='a/', new_label='b/',
410
464
extra_trees=None,
411
465
path_encoding='utf8',
413
468
"""Show in text form the changes from one tree to another.
419
Include only changes to these files - None for all changes.
421
external_diff_options
422
If set, use an external GNU diff and pass these options.
425
If set, more Trees to use for looking up file ids
428
If set, the path will be encoded as specified, otherwise is supposed
470
:param to_file: The output stream.
471
:param specific_files:Include only changes to these files - None for all
473
:param external_diff_options: If set, use an external GNU diff and pass
475
:param extra_trees: If set, more Trees to use for looking up file ids
476
:param path_encoding: If set, the path will be encoded as specified,
477
otherwise is supposed to be utf8
478
:param format_cls: Formatter class (DiffTree subclass)
480
if format_cls is None:
481
format_cls = DiffTree
431
482
old_tree.lock_read()
433
484
if extra_trees is not None:
436
487
new_tree.lock_read()
438
differ = DiffTree.from_trees_options(old_tree, new_tree, to_file,
440
external_diff_options,
441
old_label, new_label, using)
489
differ = format_cls.from_trees_options(old_tree, new_tree, to_file,
491
external_diff_options,
492
old_label, new_label, using)
442
493
return differ.show_diff(specific_files, extra_trees)
444
495
new_tree.unlock()
452
503
def _patch_header_date(tree, file_id, path):
453
504
"""Returns a timestamp suitable for use in a patch header."""
454
mtime = tree.get_file_mtime(file_id, path)
506
mtime = tree.get_file_mtime(file_id, path)
507
except errors.FileTimestampUnavailable:
455
509
return timestamp.format_patch_date(mtime)
679
733
def from_string(klass, command_string, old_tree, new_tree, to_file,
680
734
path_encoding='utf-8'):
681
command_template = commands.shlex_split_unicode(command_string)
735
command_template = cmdline.split(command_string)
682
736
if '@' not in command_string:
683
737
command_template.extend(['@old_path', '@new_path'])
684
738
return klass(command_template, old_tree, new_tree, to_file,
723
777
def _write_file(self, file_id, tree, prefix, relpath, force_temp=False,
724
778
allow_write=False):
779
if not force_temp and isinstance(tree, WorkingTree):
780
return tree.abspath(tree.id2path(file_id))
725
782
full_path = osutils.pathjoin(self._root, prefix, relpath)
726
783
if not force_temp and self._try_symlink_root(tree, prefix):
801
mtime = tree.get_file_mtime(file_id)
802
except errors.FileTimestampUnavailable:
805
os.utime(full_path, (mtime, mtime))
743
806
if not allow_write:
744
807
osutils.make_readonly(full_path)
745
mtime = tree.get_file_mtime(file_id)
746
os.utime(full_path, (mtime, mtime))
749
810
def _prepare_files(self, file_id, old_path, new_path, force_temp=False,
766
827
def diff(self, file_id, old_path, new_path, old_kind, new_kind):
767
828
if (old_kind, new_kind) != ('file', 'file'):
768
829
return DiffPath.CANNOT_DIFF
769
self._prepare_files(file_id, old_path, new_path)
770
self._execute(osutils.pathjoin('old', old_path),
771
osutils.pathjoin('new', new_path))
830
(old_disk_path, new_disk_path) = self._prepare_files(
831
file_id, old_path, new_path)
832
self._execute(old_disk_path, new_disk_path)
773
834
def edit_file(self, file_id):
774
835
"""Use this tool to edit a file.
871
932
def show_diff(self, specific_files, extra_trees=None):
872
933
"""Write tree diff to self.to_file
874
:param sepecific_files: the specific files to compare (recursive)
935
:param specific_files: the specific files to compare (recursive)
875
936
:param extra_trees: extra trees to use for mapping paths to file_ids