/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/diff.py

  • Committer: Jelmer Vernooij
  • Date: 2019-08-11 13:33:45 UTC
  • mfrom: (7379 work)
  • mto: This revision was merged to the branch mainline in revision 7389.
  • Revision ID: jelmer@jelmer.uk-20190811133345-dp9j3c569vxj4l9y
merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
import difflib
20
20
import os
21
21
import re
22
 
import string
23
22
import sys
24
23
 
25
24
from .lazy_import import lazy_import
30
29
import tempfile
31
30
 
32
31
from breezy import (
33
 
    cmdline,
 
32
    cleanup,
34
33
    controldir,
35
34
    errors,
36
35
    osutils,
54
53
DEFAULT_CONTEXT_AMOUNT = 3
55
54
 
56
55
 
57
 
class AtTemplate(string.Template):
58
 
    """Templating class that uses @ instead of $."""
59
 
 
60
 
    delimiter = '@'
61
 
 
62
 
 
63
56
# TODO: Rather than building a changeset object, we should probably
64
57
# invoke callbacks on an object.  That object can either accumulate a
65
58
# list, write them out directly, etc etc.
370
363
 
371
364
 
372
365
def get_trees_and_branches_to_diff_locked(
373
 
        path_list, revision_specs, old_url, new_url, add_cleanup, apply_view=True):
 
366
        path_list, revision_specs, old_url, new_url, exit_stack, apply_view=True):
374
367
    """Get the trees and specific files to diff given a list of paths.
375
368
 
376
369
    This method works out the trees to be diff'ed and the files of
387
380
    :param new_url:
388
381
        The url of the new branch or tree. If None, the tree to use is
389
382
        taken from the first path, if any, or the current working tree.
390
 
    :param add_cleanup:
391
 
        a callable like Command.add_cleanup.  get_trees_and_branches_to_diff
 
383
    :param exit_stack:
 
384
        an ExitStack object. get_trees_and_branches_to_diff
392
385
        will register cleanups that must be run to unlock the trees, etc.
393
386
    :param apply_view:
394
387
        if True and a view is set, apply the view or check that the paths
397
390
        a tuple of (old_tree, new_tree, old_branch, new_branch,
398
391
        specific_files, extra_trees) where extra_trees is a sequence of
399
392
        additional trees to search in for file-ids.  The trees and branches
400
 
        will be read-locked until the cleanups registered via the add_cleanup
 
393
        will be read-locked until the cleanups registered via the exit_stack
401
394
        param are run.
402
395
    """
403
396
    # Get the old and new revision specs
429
422
 
430
423
    def lock_tree_or_branch(wt, br):
431
424
        if wt is not None:
432
 
            wt.lock_read()
433
 
            add_cleanup(wt.unlock)
 
425
            exit_stack.enter_context(wt.lock_read())
434
426
        elif br is not None:
435
 
            br.lock_read()
436
 
            add_cleanup(br.unlock)
 
427
            exit_stack.enter_context(br.lock_read())
437
428
 
438
429
    # Get the old location
439
430
    specific_files = []
526
517
        context = DEFAULT_CONTEXT_AMOUNT
527
518
    if format_cls is None:
528
519
        format_cls = DiffTree
529
 
    with old_tree.lock_read():
 
520
    with cleanup.ExitStack() as exit_stack:
 
521
        exit_stack.enter_context(old_tree.lock_read())
530
522
        if extra_trees is not None:
531
523
            for tree in extra_trees:
532
 
                tree.lock_read()
533
 
        new_tree.lock_read()
534
 
        try:
535
 
            differ = format_cls.from_trees_options(old_tree, new_tree, to_file,
536
 
                                                   path_encoding,
537
 
                                                   external_diff_options,
538
 
                                                   old_label, new_label, using,
539
 
                                                   context_lines=context)
540
 
            return differ.show_diff(specific_files, extra_trees)
541
 
        finally:
542
 
            new_tree.unlock()
543
 
            if extra_trees is not None:
544
 
                for tree in extra_trees:
545
 
                    tree.unlock()
 
524
                exit_stack.enter_context(tree.lock_read())
 
525
        exit_stack.enter_context(new_tree.lock_read())
 
526
        differ = format_cls.from_trees_options(old_tree, new_tree, to_file,
 
527
                                               path_encoding,
 
528
                                               external_diff_options,
 
529
                                               old_label, new_label, using,
 
530
                                               context_lines=context)
 
531
        return differ.show_diff(specific_files, extra_trees)
546
532
 
547
533
 
548
534
def _patch_header_date(tree, path):
776
762
                             context_lines=self.context_lines)
777
763
        except errors.BinaryFile:
778
764
            self.to_file.write(
779
 
                ("Binary files %s and %s differ\n" %
780
 
                 (from_label, to_label)).encode(self.path_encoding, 'replace'))
 
765
                ("Binary files %s%s and %s%s differ\n" %
 
766
                 (self.old_label, from_path, self.new_label, to_path)).encode(self.path_encoding, 'replace'))
781
767
        return self.CHANGED
782
768
 
783
769
 
790
776
        self._root = osutils.mkdtemp(prefix='brz-diff-')
791
777
 
792
778
    @classmethod
793
 
    def from_string(klass, command_string, old_tree, new_tree, to_file,
 
779
    def from_string(klass, command_template, old_tree, new_tree, to_file,
794
780
                    path_encoding='utf-8'):
795
 
        command_template = cmdline.split(command_string)
796
 
        if '@' not in command_string:
797
 
            command_template.extend(['@old_path', '@new_path'])
798
781
        return klass(command_template, old_tree, new_tree, to_file,
799
782
                     path_encoding)
800
783
 
810
793
 
811
794
    def _get_command(self, old_path, new_path):
812
795
        my_map = {'old_path': old_path, 'new_path': new_path}
813
 
        command = [AtTemplate(t).substitute(my_map) for t in
 
796
        command = [t.format(**my_map) for t in
814
797
                   self.command_template]
815
798
        if sys.platform == 'win32':  # Popen doesn't accept unicode on win32
816
799
            command_encoded = []
892
875
        except OSError as e:
893
876
            if e.errno != errno.EEXIST:
894
877
                raise
895
 
        source = tree.get_file(relpath)
896
 
        try:
897
 
            with open(full_path, 'wb') as target:
898
 
                osutils.pumpfile(source, target)
899
 
        finally:
900
 
            source.close()
 
878
        with tree.get_file(relpath) as source, \
 
879
                open(full_path, 'wb') as target:
 
880
            osutils.pumpfile(source, target)
901
881
        try:
902
882
            mtime = tree.get_file_mtime(relpath)
903
883
        except FileTimestampUnavailable: