/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: 2018-11-06 01:18:08 UTC
  • mfrom: (7143 work)
  • mto: This revision was merged to the branch mainline in revision 7151.
  • Revision ID: jelmer@jelmer.uk-20181106011808-y870f4vq0ork3ahu
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
47
47
from .registry import (
48
48
    Registry,
49
49
    )
 
50
from .sixish import text_type
50
51
from .trace import mutter, note, warning
51
52
from .tree import FileTimestampUnavailable
52
53
 
73
74
        self.opcodes = None
74
75
 
75
76
 
76
 
def internal_diff(old_filename, oldlines, new_filename, newlines, to_file,
 
77
def internal_diff(old_label, oldlines, new_label, newlines, to_file,
77
78
                  allow_binary=False, sequence_matcher=None,
78
79
                  path_encoding='utf8', context_lines=DEFAULT_CONTEXT_AMOUNT):
79
80
    # FIXME: difflib is wrong if there is no trailing newline.
86
87
    # In the meantime we at least make sure the patch isn't
87
88
    # mangled.
88
89
 
89
 
 
90
 
    # Special workaround for Python2.3, where difflib fails if
91
 
    # both sequences are empty.
92
 
    if not oldlines and not newlines:
93
 
        return
94
 
 
95
90
    if allow_binary is False:
96
91
        textfile.check_text_lines(oldlines)
97
92
        textfile.check_text_lines(newlines)
98
93
 
99
94
    if sequence_matcher is None:
100
95
        sequence_matcher = patiencediff.PatienceSequenceMatcher
101
 
    ud = patiencediff.unified_diff(oldlines, newlines,
102
 
                      fromfile=old_filename.encode(path_encoding, 'replace'),
103
 
                      tofile=new_filename.encode(path_encoding, 'replace'),
 
96
    ud = patiencediff.unified_diff_bytes(oldlines, newlines,
 
97
                      fromfile=old_label.encode(path_encoding, 'replace'),
 
98
                      tofile=new_label.encode(path_encoding, 'replace'),
104
99
                      n=context_lines, sequencematcher=sequence_matcher)
105
100
 
106
101
    ud = list(ud)
109
104
    # work-around for difflib being too smart for its own good
110
105
    # if /dev/null is "1,0", patch won't recognize it as /dev/null
111
106
    if not oldlines:
112
 
        ud[2] = ud[2].replace('-1,0', '-0,0')
 
107
        ud[2] = ud[2].replace(b'-1,0', b'-0,0')
113
108
    elif not newlines:
114
 
        ud[2] = ud[2].replace('+1,0', '+0,0')
 
109
        ud[2] = ud[2].replace(b'+1,0', b'+0,0')
115
110
 
116
111
    for line in ud:
117
112
        to_file.write(line)
118
 
        if not line.endswith('\n'):
119
 
            to_file.write("\n\\ No newline at end of file\n")
120
 
    to_file.write('\n')
 
113
        if not line.endswith(b'\n'):
 
114
            to_file.write(b"\n\\ No newline at end of file\n")
 
115
    to_file.write(b'\n')
121
116
 
122
117
 
123
118
def _spawn_external_diff(diffcmd, capture_errors=True):
191
186
    return diff_opts
192
187
 
193
188
 
194
 
def external_diff(old_filename, oldlines, new_filename, newlines, to_file,
 
189
def external_diff(old_label, oldlines, new_label, newlines, to_file,
195
190
                  diff_opts):
196
191
    """Display a diff by calling out to the external diff program."""
197
192
    # make sure our own output is properly ordered before the diff
221
216
        if sys.platform == 'win32':
222
217
            # Popen doesn't do the proper encoding for external commands
223
218
            # Since we are dealing with an ANSI api, use mbcs encoding
224
 
            old_filename = old_filename.encode('mbcs')
225
 
            new_filename = new_filename.encode('mbcs')
 
219
            old_label = old_label.encode('mbcs')
 
220
            new_label = new_label.encode('mbcs')
226
221
        diffcmd = ['diff',
227
 
                   '--label', old_filename,
 
222
                   '--label', old_label,
228
223
                   old_abspath,
229
 
                   '--label', new_filename,
 
224
                   '--label', new_label,
230
225
                   new_abspath,
231
226
                   '--binary',
232
227
                  ]
241
236
        rc = pipe.returncode
242
237
 
243
238
        # internal_diff() adds a trailing newline, add one here for consistency
244
 
        out += '\n'
 
239
        out += b'\n'
245
240
        if rc == 2:
246
241
            # 'diff' gives retcode == 2 for all sorts of errors
247
242
            # one of those is 'Binary files differ'.
254
249
            out, err = pipe.communicate()
255
250
 
256
251
            # Write out the new i18n diff response
257
 
            to_file.write(out+'\n')
 
252
            to_file.write(out+b'\n')
258
253
            if pipe.returncode != 2:
259
254
                raise errors.BzrError(
260
255
                               'external diff failed with exit code 2'
261
256
                               ' when run with LANG=C and LC_ALL=C,'
262
257
                               ' but not when run natively: %r' % (diffcmd,))
263
258
 
264
 
            first_line = lang_c_out.split('\n', 1)[0]
 
259
            first_line = lang_c_out.split(b'\n', 1)[0]
265
260
            # Starting with diffutils 2.8.4 the word "binary" was dropped.
266
 
            m = re.match('^(binary )?files.*differ$', first_line, re.I)
 
261
            m = re.match(b'^(binary )?files.*differ$', first_line, re.I)
267
262
            if m is None:
268
263
                raise errors.BzrError('external diff failed with exit code 2;'
269
264
                                      ' command: %r' % (diffcmd,))
489
484
 
490
485
 
491
486
def get_executable_change(old_is_x, new_is_x):
492
 
    descr = { True:"+x", False:"-x", None:"??" }
 
487
    descr = { True:b"+x", False:b"-x", None:b"??" }
493
488
    if old_is_x != new_is_x:
494
 
        return ["%s to %s" % (descr[old_is_x], descr[new_is_x],)]
 
489
        return [b"%s to %s" % (descr[old_is_x], descr[new_is_x],)]
495
490
    else:
496
491
        return []
497
492
 
617
612
 
618
613
    def diff_symlink(self, old_target, new_target):
619
614
        if old_target is None:
620
 
            self.to_file.write('=== target is %r\n' % new_target)
 
615
            self.to_file.write(b'=== target is \'%s\'\n' %
 
616
                new_target.encode(self.path_encoding, 'replace'))
621
617
        elif new_target is None:
622
 
            self.to_file.write('=== target was %r\n' % old_target)
 
618
            self.to_file.write(b'=== target was \'%s\'\n' %
 
619
                old_target.encode(self.path_encoding, 'replace'))
623
620
        else:
624
 
            self.to_file.write('=== target changed %r => %r\n' %
625
 
                              (old_target, new_target))
 
621
            self.to_file.write(b'=== target changed \'%s\' => \'%s\'\n' %
 
622
                              (old_target.encode(self.path_encoding, 'replace'),
 
623
                               new_target.encode(self.path_encoding, 'replace')))
626
624
        return self.CHANGED
627
625
 
628
626
 
668
666
            to_file_id = None
669
667
        else:
670
668
            return self.CANNOT_DIFF
671
 
        from_label = '%s%s\t%s' % (self.old_label, old_path, old_date)
672
 
        to_label = '%s%s\t%s' % (self.new_label, new_path, new_date)
 
669
        from_label = '%s%s\t%s' % (self.old_label, old_path,
 
670
                old_date)
 
671
        to_label = '%s%s\t%s' % (self.new_label, new_path,
 
672
                new_date)
673
673
        return self.diff_text(old_path, new_path, from_label, to_label,
674
674
            from_file_id, to_file_id)
675
675
 
738
738
        if sys.platform == 'win32': # Popen doesn't accept unicode on win32
739
739
            command_encoded = []
740
740
            for c in command:
741
 
                if isinstance(c, unicode):
 
741
                if isinstance(c, text_type):
742
742
                    command_encoded.append(c.encode('mbcs'))
743
743
                else:
744
744
                    command_encoded.append(c)
757
757
            else:
758
758
                raise
759
759
        self.to_file.write(proc.stdout.read())
 
760
        proc.stdout.close()
760
761
        return proc.wait()
761
762
 
762
763
    def _try_symlink_root(self, tree, prefix):
996
997
            properties_changed.extend(get_executable_change(executable[0], executable[1]))
997
998
 
998
999
            if properties_changed:
999
 
                prop_str = " (properties changed: %s)" % (", ".join(properties_changed),)
 
1000
                prop_str = b" (properties changed: %s)" % (
 
1001
                        b", ".join(properties_changed),)
1000
1002
            else:
1001
 
                prop_str = ""
 
1003
                prop_str = b""
1002
1004
 
1003
1005
            if (old_present, new_present) == (True, False):
1004
 
                self.to_file.write("=== removed %s '%s'\n" %
1005
 
                                   (kind[0], oldpath_encoded))
 
1006
                self.to_file.write(b"=== removed %s '%s'\n" %
 
1007
                                   (kind[0].encode('ascii'), oldpath_encoded))
1006
1008
                newpath = oldpath
1007
1009
            elif (old_present, new_present) == (False, True):
1008
 
                self.to_file.write("=== added %s '%s'\n" %
1009
 
                                   (kind[1], newpath_encoded))
 
1010
                self.to_file.write(b"=== added %s '%s'\n" %
 
1011
                                   (kind[1].encode('ascii'), newpath_encoded))
1010
1012
                oldpath = newpath
1011
1013
            elif renamed:
1012
 
                self.to_file.write("=== renamed %s '%s' => '%s'%s\n" %
1013
 
                    (kind[0], oldpath_encoded, newpath_encoded, prop_str))
 
1014
                self.to_file.write(b"=== renamed %s '%s' => '%s'%s\n" %
 
1015
                    (kind[0].encode('ascii'), oldpath_encoded, newpath_encoded, prop_str))
1014
1016
            else:
1015
1017
                # if it was produced by iter_changes, it must be
1016
1018
                # modified *somehow*, either content or execute bit.
1017
 
                self.to_file.write("=== modified %s '%s'%s\n" % (kind[0],
 
1019
                self.to_file.write(b"=== modified %s '%s'%s\n" % (kind[0].encode('ascii'),
1018
1020
                                   newpath_encoded, prop_str))
1019
1021
            if changed_content:
1020
1022
                self._diff(oldpath, newpath, kind[0], kind[1], file_id=file_id)
1042
1044
 
1043
1045
    def _diff(self, old_path, new_path, old_kind, new_kind, file_id):
1044
1046
        result = DiffPath._diff_many(self.differs, file_id, old_path,
1045
 
                                       new_path, old_kind, new_kind)
 
1047
                                     new_path, old_kind, new_kind)
1046
1048
        if result is DiffPath.CANNOT_DIFF:
1047
1049
            error_path = new_path
1048
1050
            if error_path is None: