/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 bzrlib/diff.py

Merge cleanup into shell-like-tests

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
import os
19
19
import re
20
20
import shutil
 
21
import string
21
22
import sys
22
23
 
23
24
from bzrlib.lazy_import import lazy_import
38
39
    timestamp,
39
40
    views,
40
41
    )
 
42
 
 
43
from bzrlib.workingtree import WorkingTree
41
44
""")
42
45
 
43
46
from bzrlib.symbol_versioning import (
46
49
from bzrlib.trace import mutter, note, warning
47
50
 
48
51
 
 
52
class AtTemplate(string.Template):
 
53
    """Templating class that uses @ instead of $."""
 
54
 
 
55
    delimiter = '@'
 
56
 
 
57
 
49
58
# TODO: Rather than building a changeset object, we should probably
50
59
# invoke callbacks on an object.  That object can either accumulate a
51
60
# list, write them out directly, etc etc.
672
681
    def from_string(klass, command_string, old_tree, new_tree, to_file,
673
682
                    path_encoding='utf-8'):
674
683
        command_template = commands.shlex_split_unicode(command_string)
675
 
        command_template.extend(['%(old_path)s', '%(new_path)s'])
 
684
        if '@' not in command_string:
 
685
            command_template.extend(['@old_path', '@new_path'])
676
686
        return klass(command_template, old_tree, new_tree, to_file,
677
687
                     path_encoding)
678
688
 
685
695
 
686
696
    def _get_command(self, old_path, new_path):
687
697
        my_map = {'old_path': old_path, 'new_path': new_path}
688
 
        return [t % my_map for t in self.command_template]
 
698
        return [AtTemplate(t).substitute(my_map) for t in
 
699
                self.command_template]
689
700
 
690
701
    def _execute(self, old_path, new_path):
691
702
        command = self._get_command(old_path, new_path)
711
722
                raise
712
723
        return True
713
724
 
714
 
    def _write_file(self, file_id, tree, prefix, relpath):
 
725
    def _write_file(self, file_id, tree, prefix, relpath, force_temp=False,
 
726
                    allow_write=False):
 
727
        if not force_temp and isinstance(tree, WorkingTree):
 
728
            return tree.abspath(tree.id2path(file_id))
 
729
        
715
730
        full_path = osutils.pathjoin(self._root, prefix, relpath)
716
 
        if self._try_symlink_root(tree, prefix):
 
731
        if not force_temp and self._try_symlink_root(tree, prefix):
717
732
            return full_path
718
733
        parent_dir = osutils.dirname(full_path)
719
734
        try:
730
745
                target.close()
731
746
        finally:
732
747
            source.close()
733
 
        osutils.make_readonly(full_path)
 
748
        if not allow_write:
 
749
            osutils.make_readonly(full_path)
734
750
        mtime = tree.get_file_mtime(file_id)
735
751
        os.utime(full_path, (mtime, mtime))
736
752
        return full_path
737
753
 
738
 
    def _prepare_files(self, file_id, old_path, new_path):
 
754
    def _prepare_files(self, file_id, old_path, new_path, force_temp=False,
 
755
                       allow_write_new=False):
739
756
        old_disk_path = self._write_file(file_id, self.old_tree, 'old',
740
 
                                         old_path)
 
757
                                         old_path, force_temp)
741
758
        new_disk_path = self._write_file(file_id, self.new_tree, 'new',
742
 
                                         new_path)
 
759
                                         new_path, force_temp,
 
760
                                         allow_write=allow_write_new)
743
761
        return old_disk_path, new_disk_path
744
762
 
745
763
    def finish(self):
753
771
    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
754
772
        if (old_kind, new_kind) != ('file', 'file'):
755
773
            return DiffPath.CANNOT_DIFF
756
 
        self._prepare_files(file_id, old_path, new_path)
757
 
        self._execute(osutils.pathjoin('old', old_path),
758
 
                      osutils.pathjoin('new', new_path))
 
774
        (old_disk_path, new_disk_path) = self._prepare_files(
 
775
                                                file_id, old_path, new_path)
 
776
        self._execute(old_disk_path, new_disk_path)
 
777
 
 
778
    def edit_file(self, file_id):
 
779
        """Use this tool to edit a file.
 
780
 
 
781
        A temporary copy will be edited, and the new contents will be
 
782
        returned.
 
783
 
 
784
        :param file_id: The id of the file to edit.
 
785
        :return: The new contents of the file.
 
786
        """
 
787
        old_path = self.old_tree.id2path(file_id)
 
788
        new_path = self.new_tree.id2path(file_id)
 
789
        new_abs_path = self._prepare_files(file_id, old_path, new_path,
 
790
                                           allow_write_new=True,
 
791
                                           force_temp=True)[1]
 
792
        command = self._get_command(osutils.pathjoin('old', old_path),
 
793
                                    osutils.pathjoin('new', new_path))
 
794
        subprocess.call(command, cwd=self._root)
 
795
        new_file = open(new_abs_path, 'r')
 
796
        try:
 
797
            return new_file.read()
 
798
        finally:
 
799
            new_file.close()
759
800
 
760
801
 
761
802
class DiffTree(object):