bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 1658.1.9
by Martin Pool Give an error for bzr diff on an nonexistent file (Malone #3619) | 1 | # Copyright (C) 2004, 2005, 2006 Canonical Ltd.
 | 
| 1711.2.54
by John Arbash Meinel Use mkstemp instead of NamedTemporary file for external diff. | 2 | #
 | 
| 1
by mbp at sourcefrog import from baz patch-364 | 3 | # This program is free software; you can redistribute it and/or modify
 | 
| 4 | # it under the terms of the GNU General Public License as published by
 | |
| 5 | # the Free Software Foundation; either version 2 of the License, or
 | |
| 6 | # (at your option) any later version.
 | |
| 1711.2.54
by John Arbash Meinel Use mkstemp instead of NamedTemporary file for external diff. | 7 | #
 | 
| 1
by mbp at sourcefrog import from baz patch-364 | 8 | # This program is distributed in the hope that it will be useful,
 | 
| 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| 11 | # GNU General Public License for more details.
 | |
| 1711.2.54
by John Arbash Meinel Use mkstemp instead of NamedTemporary file for external diff. | 12 | #
 | 
| 1
by mbp at sourcefrog import from baz patch-364 | 13 | # You should have received a copy of the GNU General Public License
 | 
| 14 | # along with this program; if not, write to the Free Software
 | |
| 15 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | |
| 16 | ||
| 2520.4.140
by Aaron Bentley Use matching blocks from mpdiff for knit delta creation | 17 | import difflib | 
| 1711.2.54
by John Arbash Meinel Use mkstemp instead of NamedTemporary file for external diff. | 18 | import os | 
| 1899.1.5
by John Arbash Meinel Always buffer the output of diff, so we can check if retcode==2 is because of Binary files | 19 | import re | 
| 1996.3.9
by John Arbash Meinel lazy_import diff.py | 20 | import sys | 
| 21 | ||
| 22 | from bzrlib.lazy_import import lazy_import | |
| 23 | lazy_import(globals(), """ | |
| 24 | import errno
 | |
| 1692.8.7
by James Henstridge changes suggested by John Meinel | 25 | import subprocess
 | 
| 1711.2.54
by John Arbash Meinel Use mkstemp instead of NamedTemporary file for external diff. | 26 | import tempfile
 | 
| 1740.2.5
by Aaron Bentley Merge from bzr.dev | 27 | import time
 | 
| 28 | ||
| 1955.2.10
by John Arbash Meinel Unset a few other LANG type variables when spawning diff | 29 | from bzrlib import (
 | 
| 30 |     errors,
 | |
| 31 |     osutils,
 | |
| 1996.3.9
by John Arbash Meinel lazy_import diff.py | 32 |     patiencediff,
 | 
| 33 |     textfile,
 | |
| 1551.12.29
by Aaron Bentley Copy and extend patch date formatting code, add patch-date parsing | 34 |     timestamp,
 | 
| 1955.2.10
by John Arbash Meinel Unset a few other LANG type variables when spawning diff | 35 |     )
 | 
| 1996.3.9
by John Arbash Meinel lazy_import diff.py | 36 | """) | 
| 37 | ||
| 38 | from bzrlib.symbol_versioning import ( | |
| 39 | deprecated_function, | |
| 40 |         )
 | |
| 1711.2.54
by John Arbash Meinel Use mkstemp instead of NamedTemporary file for external diff. | 41 | from bzrlib.trace import mutter, warning | 
| 1
by mbp at sourcefrog import from baz patch-364 | 42 | |
| 1711.2.24
by John Arbash Meinel Late bind to PatienceSequenceMatcher to allow plugin to override. | 43 | |
| 767
by Martin Pool - files are only reported as modified if their name or parent has changed, | 44 | # TODO: Rather than building a changeset object, we should probably
 | 
| 45 | # invoke callbacks on an object.  That object can either accumulate a
 | |
| 46 | # list, write them out directly, etc etc.
 | |
| 47 | ||
| 2520.4.140
by Aaron Bentley Use matching blocks from mpdiff for knit delta creation | 48 | |
| 49 | class _PrematchedMatcher(difflib.SequenceMatcher): | |
| 50 | """Allow SequenceMatcher operations to use predetermined blocks""" | |
| 51 | ||
| 52 | def __init__(self, matching_blocks): | |
| 53 | difflib.SequenceMatcher(self, None, None) | |
| 54 | self.matching_blocks = matching_blocks | |
| 55 | self.opcodes = None | |
| 56 | ||
| 57 | ||
| 1558.15.11
by Aaron Bentley Apply merge review suggestions | 58 | def internal_diff(old_filename, oldlines, new_filename, newlines, to_file, | 
| 1711.2.30
by John Arbash Meinel Fix bug in internal_diff handling of unicode paths | 59 | allow_binary=False, sequence_matcher=None, | 
| 60 | path_encoding='utf8'): | |
| 475
by Martin Pool - rewrite diff using compare_trees() | 61 |     # FIXME: difflib is wrong if there is no trailing newline.
 | 
| 62 |     # The syntax used by patch seems to be "\ No newline at
 | |
| 63 |     # end of file" following the last diff line from that
 | |
| 64 |     # file.  This is not trivial to insert into the
 | |
| 65 |     # unified_diff output and it might be better to just fix
 | |
| 66 |     # or replace that function.
 | |
| 67 | ||
| 68 |     # In the meantime we at least make sure the patch isn't
 | |
| 69 |     # mangled.
 | |
| 70 | ||
| 71 | ||
| 72 |     # Special workaround for Python2.3, where difflib fails if
 | |
| 73 |     # both sequences are empty.
 | |
| 74 | if not oldlines and not newlines: | |
| 75 |         return
 | |
| 1558.15.2
by Aaron Bentley Implemented binary file handling for diff | 76 | |
| 1558.15.11
by Aaron Bentley Apply merge review suggestions | 77 | if allow_binary is False: | 
| 1996.3.9
by John Arbash Meinel lazy_import diff.py | 78 | textfile.check_text_lines(oldlines) | 
| 79 | textfile.check_text_lines(newlines) | |
| 475
by Martin Pool - rewrite diff using compare_trees() | 80 | |
| 1185.81.8
by John Arbash Meinel Updating unified_diff to take a factory, using the new diff algorithm in the code. | 81 | if sequence_matcher is None: | 
| 1996.3.9
by John Arbash Meinel lazy_import diff.py | 82 | sequence_matcher = patiencediff.PatienceSequenceMatcher | 
| 83 | ud = patiencediff.unified_diff(oldlines, newlines, | |
| 1740.2.5
by Aaron Bentley Merge from bzr.dev | 84 | fromfile=old_filename.encode(path_encoding), | 
| 85 | tofile=new_filename.encode(path_encoding), | |
| 1185.81.8
by John Arbash Meinel Updating unified_diff to take a factory, using the new diff algorithm in the code. | 86 | sequencematcher=sequence_matcher) | 
| 475
by Martin Pool - rewrite diff using compare_trees() | 87 | |
| 1092.1.50
by Robert Collins make diff lsdiff/filterdiff friendly | 88 | ud = list(ud) | 
| 3085.1.1
by John Arbash Meinel Fix internal_diff to not fail when the texts are identical. | 89 | if len(ud) == 0: # Identical contents, nothing to do | 
| 90 |         return
 | |
| 475
by Martin Pool - rewrite diff using compare_trees() | 91 |     # work-around for difflib being too smart for its own good
 | 
| 92 |     # if /dev/null is "1,0", patch won't recognize it as /dev/null
 | |
| 93 | if not oldlines: | |
| 94 | ud[2] = ud[2].replace('-1,0', '-0,0') | |
| 95 | elif not newlines: | |
| 96 | ud[2] = ud[2].replace('+1,0', '+0,0') | |
| 1092.1.50
by Robert Collins make diff lsdiff/filterdiff friendly | 97 |     # work around for difflib emitting random spaces after the label
 | 
| 98 | ud[0] = ud[0][:-2] + '\n' | |
| 99 | ud[1] = ud[1][:-2] + '\n' | |
| 475
by Martin Pool - rewrite diff using compare_trees() | 100 | |
| 804
by Martin Pool Patch from John: | 101 | for line in ud: | 
| 102 | to_file.write(line) | |
| 974.1.5
by Aaron Bentley Fixed handling of missing newlines in udiffs | 103 | if not line.endswith('\n'): | 
| 104 | to_file.write("\n\\ No newline at end of file\n") | |
| 2911.6.1
by Blake Winton Change 'print >> f,'s to 'f.write('s. | 105 | to_file.write('\n') | 
| 475
by Martin Pool - rewrite diff using compare_trees() | 106 | |
| 107 | ||
| 1920.1.1
by John Arbash Meinel fix bug #56307, handle binary files even when LANG is not english | 108 | def _spawn_external_diff(diffcmd, capture_errors=True): | 
| 109 | """Spawn the externall diff process, and return the child handle. | |
| 110 | ||
| 111 |     :param diffcmd: The command list to spawn
 | |
| 2138.1.1
by Wouter van Heyst Robuster external diff output handling. | 112 |     :param capture_errors: Capture stderr as well as setting LANG=C
 | 
| 113 |         and LC_ALL=C. This lets us read and understand the output of diff,
 | |
| 114 |         and respond to any errors.
 | |
| 1920.1.1
by John Arbash Meinel fix bug #56307, handle binary files even when LANG is not english | 115 |     :return: A Popen object.
 | 
| 116 |     """
 | |
| 117 | if capture_errors: | |
| 2321.2.2
by Alexander Belchenko win32 fixes for test_external_diff_binary (gettext on win32 rely on $LANGUAGE) | 118 |         # construct minimal environment
 | 
| 119 | env = {} | |
| 120 | path = os.environ.get('PATH') | |
| 121 | if path is not None: | |
| 122 | env['PATH'] = path | |
| 2321.2.5
by Alexander Belchenko external diff: no need for special code path for win32 (suggested by John Meinel) | 123 | env['LANGUAGE'] = 'C' # on win32 only LANGUAGE has effect | 
| 124 | env['LANG'] = 'C' | |
| 125 | env['LC_ALL'] = 'C' | |
| 1920.1.1
by John Arbash Meinel fix bug #56307, handle binary files even when LANG is not english | 126 | stderr = subprocess.PIPE | 
| 127 | else: | |
| 2321.2.2
by Alexander Belchenko win32 fixes for test_external_diff_binary (gettext on win32 rely on $LANGUAGE) | 128 | env = None | 
| 1920.1.1
by John Arbash Meinel fix bug #56307, handle binary files even when LANG is not english | 129 | stderr = None | 
| 130 | ||
| 131 | try: | |
| 132 | pipe = subprocess.Popen(diffcmd, | |
| 133 | stdin=subprocess.PIPE, | |
| 134 | stdout=subprocess.PIPE, | |
| 135 | stderr=stderr, | |
| 2321.2.2
by Alexander Belchenko win32 fixes for test_external_diff_binary (gettext on win32 rely on $LANGUAGE) | 136 | env=env) | 
| 1920.1.1
by John Arbash Meinel fix bug #56307, handle binary files even when LANG is not english | 137 | except OSError, e: | 
| 138 | if e.errno == errno.ENOENT: | |
| 139 | raise errors.NoDiff(str(e)) | |
| 140 |         raise
 | |
| 141 | ||
| 142 | return pipe | |
| 143 | ||
| 144 | ||
| 1185.35.29
by Aaron Bentley Support whitespace in diff filenames | 145 | def external_diff(old_filename, oldlines, new_filename, newlines, to_file, | 
| 571
by Martin Pool - new --diff-options to pass options through to external | 146 | diff_opts): | 
| 568
by Martin Pool - start adding support for showing diffs by calling out to | 147 | """Display a diff by calling out to the external diff program.""" | 
| 581
by Martin Pool - make sure any bzr output is flushed before | 148 |     # make sure our own output is properly ordered before the diff
 | 
| 149 | to_file.flush() | |
| 150 | ||
| 1711.2.54
by John Arbash Meinel Use mkstemp instead of NamedTemporary file for external diff. | 151 | oldtmp_fd, old_abspath = tempfile.mkstemp(prefix='bzr-diff-old-') | 
| 152 | newtmp_fd, new_abspath = tempfile.mkstemp(prefix='bzr-diff-new-') | |
| 153 | oldtmpf = os.fdopen(oldtmp_fd, 'wb') | |
| 154 | newtmpf = os.fdopen(newtmp_fd, 'wb') | |
| 568
by Martin Pool - start adding support for showing diffs by calling out to | 155 | |
| 156 | try: | |
| 157 |         # TODO: perhaps a special case for comparing to or from the empty
 | |
| 158 |         # sequence; can just use /dev/null on Unix
 | |
| 159 | ||
| 160 |         # TODO: if either of the files being compared already exists as a
 | |
| 161 |         # regular named file (e.g. in the working directory) then we can
 | |
| 162 |         # compare directly to that, rather than copying it.
 | |
| 163 | ||
| 164 | oldtmpf.writelines(oldlines) | |
| 165 | newtmpf.writelines(newlines) | |
| 166 | ||
| 1711.2.54
by John Arbash Meinel Use mkstemp instead of NamedTemporary file for external diff. | 167 | oldtmpf.close() | 
| 168 | newtmpf.close() | |
| 568
by Martin Pool - start adding support for showing diffs by calling out to | 169 | |
| 571
by Martin Pool - new --diff-options to pass options through to external | 170 | if not diff_opts: | 
| 171 | diff_opts = [] | |
| 172 | diffcmd = ['diff', | |
| 1740.2.5
by Aaron Bentley Merge from bzr.dev | 173 | '--label', old_filename, | 
| 1711.2.54
by John Arbash Meinel Use mkstemp instead of NamedTemporary file for external diff. | 174 | old_abspath, | 
| 1740.2.5
by Aaron Bentley Merge from bzr.dev | 175 | '--label', new_filename, | 
| 1711.2.56
by John Arbash Meinel Raise NoDiff if 'diff' not present. | 176 | new_abspath, | 
| 177 | '--binary', | |
| 178 |                   ]
 | |
| 571
by Martin Pool - new --diff-options to pass options through to external | 179 | |
| 180 |         # diff only allows one style to be specified; they don't override.
 | |
| 181 |         # note that some of these take optargs, and the optargs can be
 | |
| 182 |         # directly appended to the options.
 | |
| 183 |         # this is only an approximate parser; it doesn't properly understand
 | |
| 184 |         # the grammar.
 | |
| 185 | for s in ['-c', '-u', '-C', '-U', | |
| 186 | '-e', '--ed', | |
| 187 | '-q', '--brief', | |
| 188 | '--normal', | |
| 189 | '-n', '--rcs', | |
| 190 | '-y', '--side-by-side', | |
| 191 | '-D', '--ifdef']: | |
| 192 | for j in diff_opts: | |
| 193 | if j.startswith(s): | |
| 194 |                     break
 | |
| 195 | else: | |
| 196 |                 continue
 | |
| 197 |             break
 | |
| 198 | else: | |
| 199 | diffcmd.append('-u') | |
| 200 | ||
| 201 | if diff_opts: | |
| 202 | diffcmd.extend(diff_opts) | |
| 203 | ||
| 1920.1.1
by John Arbash Meinel fix bug #56307, handle binary files even when LANG is not english | 204 | pipe = _spawn_external_diff(diffcmd, capture_errors=True) | 
| 205 | out,err = pipe.communicate() | |
| 206 | rc = pipe.returncode | |
| 571
by Martin Pool - new --diff-options to pass options through to external | 207 | |
| 1920.1.1
by John Arbash Meinel fix bug #56307, handle binary files even when LANG is not english | 208 |         # internal_diff() adds a trailing newline, add one here for consistency
 | 
| 209 | out += '\n' | |
| 1899.1.5
by John Arbash Meinel Always buffer the output of diff, so we can check if retcode==2 is because of Binary files | 210 | if rc == 2: | 
| 211 |             # 'diff' gives retcode == 2 for all sorts of errors
 | |
| 212 |             # one of those is 'Binary files differ'.
 | |
| 213 |             # Bad options could also be the problem.
 | |
| 1904.1.4
by Marien Zwart Make external diff in binary mode work with recent versions of diffutils. | 214 |             # 'Binary files' is not a real error, so we suppress that error.
 | 
| 1920.1.1
by John Arbash Meinel fix bug #56307, handle binary files even when LANG is not english | 215 | lang_c_out = out | 
| 216 | ||
| 217 |             # Since we got here, we want to make sure to give an i18n error
 | |
| 218 | pipe = _spawn_external_diff(diffcmd, capture_errors=False) | |
| 219 | out, err = pipe.communicate() | |
| 220 | ||
| 221 |             # Write out the new i18n diff response
 | |
| 222 | to_file.write(out+'\n') | |
| 223 | if pipe.returncode != 2: | |
| 1996.3.9
by John Arbash Meinel lazy_import diff.py | 224 | raise errors.BzrError( | 
| 225 |                                'external diff failed with exit code 2'
 | |
| 2138.1.1
by Wouter van Heyst Robuster external diff output handling. | 226 |                                ' when run with LANG=C and LC_ALL=C,'
 | 
| 227 | ' but not when run natively: %r' % (diffcmd,)) | |
| 1920.1.1
by John Arbash Meinel fix bug #56307, handle binary files even when LANG is not english | 228 | |
| 229 | first_line = lang_c_out.split('\n', 1)[0] | |
| 1904.1.4
by Marien Zwart Make external diff in binary mode work with recent versions of diffutils. | 230 |             # Starting with diffutils 2.8.4 the word "binary" was dropped.
 | 
| 231 | m = re.match('^(binary )?files.*differ$', first_line, re.I) | |
| 1920.1.1
by John Arbash Meinel fix bug #56307, handle binary files even when LANG is not english | 232 | if m is None: | 
| 1996.3.9
by John Arbash Meinel lazy_import diff.py | 233 | raise errors.BzrError('external diff failed with exit code 2;' | 
| 234 | ' command: %r' % (diffcmd,)) | |
| 1920.1.1
by John Arbash Meinel fix bug #56307, handle binary files even when LANG is not english | 235 | else: | 
| 236 |                 # Binary files differ, just return
 | |
| 237 |                 return
 | |
| 238 | ||
| 239 |         # If we got to here, we haven't written out the output of diff
 | |
| 240 |         # do so now
 | |
| 241 | to_file.write(out) | |
| 242 | if rc not in (0, 1): | |
| 571
by Martin Pool - new --diff-options to pass options through to external | 243 |             # returns 1 if files differ; that's OK
 | 
| 244 | if rc < 0: | |
| 245 | msg = 'signal %d' % (-rc) | |
| 246 | else: | |
| 247 | msg = 'exit code %d' % rc | |
| 248 | ||
| 1996.3.9
by John Arbash Meinel lazy_import diff.py | 249 | raise errors.BzrError('external diff failed with %s; command: %r' | 
| 250 | % (rc, diffcmd)) | |
| 1899.1.6
by John Arbash Meinel internal_diff always adds a trailing \n, make sure external_diff does too | 251 | |
| 252 | ||
| 568
by Martin Pool - start adding support for showing diffs by calling out to | 253 | finally: | 
| 254 | oldtmpf.close() # and delete | |
| 255 | newtmpf.close() | |
| 1711.2.54
by John Arbash Meinel Use mkstemp instead of NamedTemporary file for external diff. | 256 |         # Clean up. Warn in case the files couldn't be deleted
 | 
| 257 |         # (in case windows still holds the file open, but not
 | |
| 258 |         # if the files have already been deleted)
 | |
| 259 | try: | |
| 260 | os.remove(old_abspath) | |
| 261 | except OSError, e: | |
| 262 | if e.errno not in (errno.ENOENT,): | |
| 263 | warning('Failed to delete temporary file: %s %s', | |
| 264 | old_abspath, e) | |
| 265 | try: | |
| 266 | os.remove(new_abspath) | |
| 267 | except OSError: | |
| 268 | if e.errno not in (errno.ENOENT,): | |
| 269 | warning('Failed to delete temporary file: %s %s', | |
| 270 | new_abspath, e) | |
| 568
by Martin Pool - start adding support for showing diffs by calling out to | 271 | |
| 1551.2.13
by Aaron Bentley Got diff working properly with checkouts | 272 | |
| 1551.2.15
by Aaron Bentley Rename cmd_show_diff to diff_cmd_helper | 273 | def diff_cmd_helper(tree, specific_files, external_diff_options, | 
| 1684.1.6
by Martin Pool (patch) --diff-prefix option (goffredo, alexander) | 274 | old_revision_spec=None, new_revision_spec=None, | 
| 2197.2.1
by Martin Pool Refactor cmd_diff | 275 | revision_specs=None, | 
| 1684.1.6
by Martin Pool (patch) --diff-prefix option (goffredo, alexander) | 276 | old_label='a/', new_label='b/'): | 
| 1551.2.13
by Aaron Bentley Got diff working properly with checkouts | 277 | """Helper for cmd_diff. | 
| 278 | ||
| 2197.2.1
by Martin Pool Refactor cmd_diff | 279 |     :param tree:
 | 
| 1551.2.13
by Aaron Bentley Got diff working properly with checkouts | 280 |         A WorkingTree
 | 
| 281 | ||
| 2197.2.1
by Martin Pool Refactor cmd_diff | 282 |     :param specific_files:
 | 
| 1551.2.13
by Aaron Bentley Got diff working properly with checkouts | 283 |         The specific files to compare, or None
 | 
| 284 | ||
| 2197.2.1
by Martin Pool Refactor cmd_diff | 285 |     :param external_diff_options:
 | 
| 1551.2.13
by Aaron Bentley Got diff working properly with checkouts | 286 |         If non-None, run an external diff, and pass it these options
 | 
| 287 | ||
| 2197.2.1
by Martin Pool Refactor cmd_diff | 288 |     :param old_revision_spec:
 | 
| 1551.2.13
by Aaron Bentley Got diff working properly with checkouts | 289 |         If None, use basis tree as old revision, otherwise use the tree for
 | 
| 290 |         the specified revision. 
 | |
| 291 | ||
| 2197.2.1
by Martin Pool Refactor cmd_diff | 292 |     :param new_revision_spec:
 | 
| 1551.2.13
by Aaron Bentley Got diff working properly with checkouts | 293 |         If None, use working tree as new revision, otherwise use the tree for
 | 
| 294 |         the specified revision.
 | |
| 295 |     
 | |
| 2197.2.1
by Martin Pool Refactor cmd_diff | 296 |     :param revision_specs: 
 | 
| 297 |         Zero, one or two RevisionSpecs from the command line, saying what revisions 
 | |
| 298 |         to compare.  This can be passed as an alternative to the old_revision_spec 
 | |
| 299 |         and new_revision_spec parameters.
 | |
| 300 | ||
| 1551.2.13
by Aaron Bentley Got diff working properly with checkouts | 301 |     The more general form is show_diff_trees(), where the caller
 | 
| 302 |     supplies any two trees.
 | |
| 303 |     """
 | |
| 2197.2.2
by Martin Pool merge bzr.dev, reconcile with option changes | 304 | |
| 305 |     # TODO: perhaps remove the old parameters old_revision_spec and
 | |
| 306 |     # new_revision_spec, since this is only really for use from cmd_diff and
 | |
| 307 |     # it now always passes through a sequence of revision_specs -- mbp
 | |
| 308 |     # 20061221
 | |
| 309 | ||
| 1551.2.14
by Aaron Bentley Updated argument names, DRY fixes. | 310 | def spec_tree(spec): | 
| 1732.3.1
by Matthieu Moy Implementation of -r revno:N:/path/to/branch | 311 | if tree: | 
| 312 | revision = spec.in_store(tree.branch) | |
| 313 | else: | |
| 314 | revision = spec.in_store(None) | |
| 315 | revision_id = revision.rev_id | |
| 316 | branch = revision.branch | |
| 317 | return branch.repository.revision_tree(revision_id) | |
| 2197.2.1
by Martin Pool Refactor cmd_diff | 318 | |
| 319 | if revision_specs is not None: | |
| 320 | assert (old_revision_spec is None | |
| 321 | and new_revision_spec is None) | |
| 322 | if len(revision_specs) > 0: | |
| 323 | old_revision_spec = revision_specs[0] | |
| 324 | if len(revision_specs) > 1: | |
| 325 | new_revision_spec = revision_specs[1] | |
| 326 | ||
| 1551.2.14
by Aaron Bentley Updated argument names, DRY fixes. | 327 | if old_revision_spec is None: | 
| 1551.2.13
by Aaron Bentley Got diff working properly with checkouts | 328 | old_tree = tree.basis_tree() | 
| 329 | else: | |
| 1551.2.14
by Aaron Bentley Updated argument names, DRY fixes. | 330 | old_tree = spec_tree(old_revision_spec) | 
| 1551.2.13
by Aaron Bentley Got diff working properly with checkouts | 331 | |
| 2197.2.1
by Martin Pool Refactor cmd_diff | 332 | if (new_revision_spec is None | 
| 333 | or new_revision_spec.spec is None): | |
| 1551.2.13
by Aaron Bentley Got diff working properly with checkouts | 334 | new_tree = tree | 
| 335 | else: | |
| 1551.2.14
by Aaron Bentley Updated argument names, DRY fixes. | 336 | new_tree = spec_tree(new_revision_spec) | 
| 2197.2.1
by Martin Pool Refactor cmd_diff | 337 | |
| 1551.7.19
by Aaron Bentley Always include working tree when calculating file ids for diff | 338 | if new_tree is not tree: | 
| 339 | extra_trees = (tree,) | |
| 340 | else: | |
| 341 | extra_trees = None | |
| 1551.2.13
by Aaron Bentley Got diff working properly with checkouts | 342 | |
| 1551.2.14
by Aaron Bentley Updated argument names, DRY fixes. | 343 | return show_diff_trees(old_tree, new_tree, sys.stdout, specific_files, | 
| 1684.1.6
by Martin Pool (patch) --diff-prefix option (goffredo, alexander) | 344 | external_diff_options, | 
| 1551.7.19
by Aaron Bentley Always include working tree when calculating file ids for diff | 345 | old_label=old_label, new_label=new_label, | 
| 346 | extra_trees=extra_trees) | |
| 1551.2.13
by Aaron Bentley Got diff working properly with checkouts | 347 | |
| 571
by Martin Pool - new --diff-options to pass options through to external | 348 | |
| 349 | def show_diff_trees(old_tree, new_tree, to_file, specific_files=None, | |
| 1684.1.6
by Martin Pool (patch) --diff-prefix option (goffredo, alexander) | 350 | external_diff_options=None, | 
| 1551.7.17
by Aaron Bentley Switch to PathsNotVersioned, accept extra_trees | 351 | old_label='a/', new_label='b/', | 
| 2598.6.12
by ghigo Move the encoding of the commit message at the command line level | 352 | extra_trees=None, | 
| 2598.6.16
by ghigo Add the "replace" option to the encodeing of the path | 353 | path_encoding='utf8'): | 
| 550
by Martin Pool - Refactor diff code into one that works purely on | 354 | """Show in text form the changes from one tree to another. | 
| 355 | ||
| 356 |     to_files
 | |
| 357 |         If set, include only changes to these files.
 | |
| 571
by Martin Pool - new --diff-options to pass options through to external | 358 | |
| 359 |     external_diff_options
 | |
| 360 |         If set, use an external GNU diff and pass these options.
 | |
| 1551.7.18
by Aaron Bentley Indentation and documentation fixes | 361 | |
| 362 |     extra_trees
 | |
| 363 |         If set, more Trees to use for looking up file ids
 | |
| 2598.6.12
by ghigo Move the encoding of the commit message at the command line level | 364 | |
| 365 |     path_encoding
 | |
| 2598.6.24
by ghigo update on the basis of Aaron suggestions | 366 |         If set, the path will be encoded as specified, otherwise is supposed
 | 
| 367 |         to be utf8
 | |
| 550
by Martin Pool - Refactor diff code into one that works purely on | 368 |     """
 | 
| 1543.1.1
by Denys Duchier lock operations for trees - use them for diff | 369 | old_tree.lock_read() | 
| 370 | try: | |
| 2255.7.38
by John Arbash Meinel show_diff_trees() should lock any extra trees it is passed. | 371 | if extra_trees is not None: | 
| 372 | for tree in extra_trees: | |
| 373 | tree.lock_read() | |
| 1543.1.1
by Denys Duchier lock operations for trees - use them for diff | 374 | new_tree.lock_read() | 
| 375 | try: | |
| 3009.2.22
by Aaron Bentley Update names & docstring | 376 | differ = DiffTree.from_trees_options(old_tree, new_tree, to_file, | 
| 3009.2.19
by Aaron Bentley Implement directory diffing | 377 | path_encoding, | 
| 378 | external_diff_options, | |
| 379 | old_label, new_label) | |
| 3009.2.12
by Aaron Bentley Associate labels with text diffing only | 380 | return differ.show_diff(specific_files, extra_trees) | 
| 1543.1.1
by Denys Duchier lock operations for trees - use them for diff | 381 | finally: | 
| 382 | new_tree.unlock() | |
| 2255.7.38
by John Arbash Meinel show_diff_trees() should lock any extra trees it is passed. | 383 | if extra_trees is not None: | 
| 384 | for tree in extra_trees: | |
| 385 | tree.unlock() | |
| 1543.1.1
by Denys Duchier lock operations for trees - use them for diff | 386 | finally: | 
| 387 | old_tree.unlock() | |
| 388 | ||
| 389 | ||
| 1740.2.5
by Aaron Bentley Merge from bzr.dev | 390 | def _patch_header_date(tree, file_id, path): | 
| 391 | """Returns a timestamp suitable for use in a patch header.""" | |
| 2405.1.2
by John Arbash Meinel Fix bug #103870 by passing None instead of a (sometimes wrong) path | 392 | mtime = tree.get_file_mtime(file_id, path) | 
| 393 | assert mtime is not None, \ | |
| 394 | "got an mtime of None for file-id %s, path %s in tree %s" % ( | |
| 395 | file_id, path, tree) | |
| 396 | return timestamp.format_patch_date(mtime) | |
| 1740.2.5
by Aaron Bentley Merge from bzr.dev | 397 | |
| 398 | ||
| 1662.1.9
by Martin Pool Give a clear error for bzr status of an unversioned, nonexistent file. (Malone #3619) | 399 | def _raise_if_nonexistent(paths, old_tree, new_tree): | 
| 400 | """Complain if paths are not in either inventory or tree. | |
| 401 | ||
| 402 |     It's OK with the files exist in either tree's inventory, or 
 | |
| 403 |     if they exist in the tree but are not versioned.
 | |
| 404 |     
 | |
| 405 |     This can be used by operations such as bzr status that can accept
 | |
| 406 |     unknown or ignored files.
 | |
| 407 |     """
 | |
| 408 | mutter("check paths: %r", paths) | |
| 409 | if not paths: | |
| 410 |         return
 | |
| 411 | s = old_tree.filter_unversioned_files(paths) | |
| 412 | s = new_tree.filter_unversioned_files(s) | |
| 413 | s = [path for path in s if not new_tree.has_filename(path)] | |
| 414 | if s: | |
| 415 | raise errors.PathsDoNotExist(sorted(s)) | |
| 416 | ||
| 417 | ||
| 1398
by Robert Collins integrate in Gustavos x-bit patch | 418 | def get_prop_change(meta_modified): | 
| 419 | if meta_modified: | |
| 420 | return " (properties changed)" | |
| 421 | else: | |
| 422 | return "" | |
| 423 | ||
| 424 | ||
| 3009.2.22
by Aaron Bentley Update names & docstring | 425 | class DiffPath(object): | 
| 3009.2.14
by Aaron Bentley Update return type handling | 426 | """Base type for command object that compare files""" | 
| 3009.2.17
by Aaron Bentley Update docs | 427 | |
| 3009.2.14
by Aaron Bentley Update return type handling | 428 |     # The type or contents of the file were unsuitable for diffing
 | 
| 3009.2.29
by Aaron Bentley Change constants to strings | 429 | CANNOT_DIFF = 'CANNOT_DIFF' | 
| 3009.2.14
by Aaron Bentley Update return type handling | 430 |     # The file has changed in a semantic way
 | 
| 3009.2.29
by Aaron Bentley Change constants to strings | 431 | CHANGED = 'CHANGED' | 
| 432 |     # The file content may have changed, but there is no semantic change
 | |
| 433 | UNCHANGED = 'UNCHANGED' | |
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 434 | |
| 3009.2.13
by Aaron Bentley Refactor differ to support registering differ factories | 435 | def __init__(self, old_tree, new_tree, to_file, path_encoding='utf-8'): | 
| 3009.2.17
by Aaron Bentley Update docs | 436 | """Constructor. | 
| 437 | ||
| 438 |         :param old_tree: The tree to show as the old tree in the comparison
 | |
| 439 |         :param new_tree: The tree to show as new in the comparison
 | |
| 440 |         :param to_file: The file to write comparison data to
 | |
| 441 |         :param path_encoding: The character encoding to write paths in
 | |
| 442 |         """
 | |
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 443 | self.old_tree = old_tree | 
| 444 | self.new_tree = new_tree | |
| 445 | self.to_file = to_file | |
| 3009.2.13
by Aaron Bentley Refactor differ to support registering differ factories | 446 | self.path_encoding = path_encoding | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 447 | |
| 3009.2.28
by Aaron Bentley Add from_diff_tree factories | 448 |     @classmethod
 | 
| 449 | def from_diff_tree(klass, diff_tree): | |
| 450 | return klass(diff_tree.old_tree, diff_tree.new_tree, | |
| 451 | diff_tree.to_file, diff_tree.path_encoding) | |
| 452 | ||
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 453 |     @staticmethod
 | 
| 454 | def _diff_many(differs, file_id, old_path, new_path, old_kind, new_kind): | |
| 455 | for file_differ in differs: | |
| 456 | result = file_differ.diff(file_id, old_path, new_path, old_kind, | |
| 457 | new_kind) | |
| 3009.2.22
by Aaron Bentley Update names & docstring | 458 | if result is not DiffPath.CANNOT_DIFF: | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 459 | return result | 
| 460 | else: | |
| 3009.2.22
by Aaron Bentley Update names & docstring | 461 | return DiffPath.CANNOT_DIFF | 
| 462 | ||
| 463 | ||
| 464 | class DiffKindChange(object): | |
| 3009.2.17
by Aaron Bentley Update docs | 465 | """Special differ for file kind changes. | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 466 | |
| 3009.2.17
by Aaron Bentley Update docs | 467 |     Represents kind change as deletion + creation.  Uses the other differs
 | 
| 468 |     to do this.
 | |
| 469 |     """
 | |
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 470 | def __init__(self, differs): | 
| 471 | self.differs = differs | |
| 472 | ||
| 3009.2.28
by Aaron Bentley Add from_diff_tree factories | 473 |     @classmethod
 | 
| 474 | def from_diff_tree(klass, diff_tree): | |
| 475 | return klass(diff_tree.differs) | |
| 476 | ||
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 477 | def diff(self, file_id, old_path, new_path, old_kind, new_kind): | 
| 3009.2.17
by Aaron Bentley Update docs | 478 | """Perform comparison | 
| 479 | ||
| 480 |         :param file_id: The file_id of the file to compare
 | |
| 481 |         :param old_path: Path of the file in the old tree
 | |
| 482 |         :param new_path: Path of the file in the new tree
 | |
| 483 |         :param old_kind: Old file-kind of the file
 | |
| 484 |         :param new_kind: New file-kind of the file
 | |
| 485 |         """
 | |
| 3009.2.18
by Aaron Bentley Change KindChangeDiffer's anti-recursion to avoid kind pairs with None | 486 | if None in (old_kind, new_kind): | 
| 3009.2.22
by Aaron Bentley Update names & docstring | 487 | return DiffPath.CANNOT_DIFF | 
| 488 | result = DiffPath._diff_many(self.differs, file_id, old_path, | |
| 3009.2.18
by Aaron Bentley Change KindChangeDiffer's anti-recursion to avoid kind pairs with None | 489 | new_path, old_kind, None) | 
| 3009.2.22
by Aaron Bentley Update names & docstring | 490 | if result is DiffPath.CANNOT_DIFF: | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 491 | return result | 
| 3009.2.22
by Aaron Bentley Update names & docstring | 492 | return DiffPath._diff_many(self.differs, file_id, old_path, new_path, | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 493 | None, new_kind) | 
| 494 | ||
| 495 | ||
| 3009.2.22
by Aaron Bentley Update names & docstring | 496 | class DiffDirectory(DiffPath): | 
| 3009.2.19
by Aaron Bentley Implement directory diffing | 497 | |
| 498 | def diff(self, file_id, old_path, new_path, old_kind, new_kind): | |
| 499 | """Perform comparison between two directories. (dummy) | |
| 500 | ||
| 501 |         """
 | |
| 502 | if 'directory' not in (old_kind, new_kind): | |
| 503 | return self.CANNOT_DIFF | |
| 504 | if old_kind not in ('directory', None): | |
| 505 | return self.CANNOT_DIFF | |
| 506 | if new_kind not in ('directory', None): | |
| 507 | return self.CANNOT_DIFF | |
| 508 | return self.CHANGED | |
| 509 | ||
| 3009.2.20
by Aaron Bentley PEP8 | 510 | |
| 3009.2.22
by Aaron Bentley Update names & docstring | 511 | class DiffSymlink(DiffPath): | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 512 | |
| 513 | def diff(self, file_id, old_path, new_path, old_kind, new_kind): | |
| 3009.2.17
by Aaron Bentley Update docs | 514 | """Perform comparison between two symlinks | 
| 515 | ||
| 516 |         :param file_id: The file_id of the file to compare
 | |
| 517 |         :param old_path: Path of the file in the old tree
 | |
| 518 |         :param new_path: Path of the file in the new tree
 | |
| 519 |         :param old_kind: Old file-kind of the file
 | |
| 520 |         :param new_kind: New file-kind of the file
 | |
| 521 |         """
 | |
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 522 | if 'symlink' not in (old_kind, new_kind): | 
| 3009.2.14
by Aaron Bentley Update return type handling | 523 | return self.CANNOT_DIFF | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 524 | if old_kind == 'symlink': | 
| 525 | old_target = self.old_tree.get_symlink_target(file_id) | |
| 526 | elif old_kind is None: | |
| 527 | old_target = None | |
| 528 | else: | |
| 3009.2.14
by Aaron Bentley Update return type handling | 529 | return self.CANNOT_DIFF | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 530 | if new_kind == 'symlink': | 
| 531 | new_target = self.new_tree.get_symlink_target(file_id) | |
| 532 | elif new_kind is None: | |
| 533 | new_target = None | |
| 534 | else: | |
| 3009.2.14
by Aaron Bentley Update return type handling | 535 | return self.CANNOT_DIFF | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 536 | return self.diff_symlink(old_target, new_target) | 
| 537 | ||
| 538 | def diff_symlink(self, old_target, new_target): | |
| 539 | if old_target is None: | |
| 540 | self.to_file.write('=== target is %r\n' % new_target) | |
| 541 | elif new_target is None: | |
| 542 | self.to_file.write('=== target was %r\n' % old_target) | |
| 543 | else: | |
| 544 | self.to_file.write('=== target changed %r => %r\n' % | |
| 545 | (old_target, new_target)) | |
| 3009.2.14
by Aaron Bentley Update return type handling | 546 | return self.CHANGED | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 547 | |
| 548 | ||
| 3009.2.22
by Aaron Bentley Update names & docstring | 549 | class DiffText(DiffPath): | 
| 3009.2.2
by Aaron Bentley Implement Differ object for abstracting diffing | 550 | |
| 3009.2.7
by Aaron Bentley Move responsibility for generating diff labels into Differ.diff | 551 |     # GNU Patch uses the epoch date to detect files that are being added
 | 
| 552 |     # or removed in a diff.
 | |
| 553 | EPOCH_DATE = '1970-01-01 00:00:00 +0000' | |
| 554 | ||
| 3009.2.13
by Aaron Bentley Refactor differ to support registering differ factories | 555 | def __init__(self, old_tree, new_tree, to_file, path_encoding='utf-8', | 
| 556 | old_label='', new_label='', text_differ=internal_diff): | |
| 3009.2.22
by Aaron Bentley Update names & docstring | 557 | DiffPath.__init__(self, old_tree, new_tree, to_file, path_encoding) | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 558 | self.text_differ = text_differ | 
| 559 | self.old_label = old_label | |
| 560 | self.new_label = new_label | |
| 3009.2.12
by Aaron Bentley Associate labels with text diffing only | 561 | self.path_encoding = path_encoding | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 562 | |
| 563 | def diff(self, file_id, old_path, new_path, old_kind, new_kind): | |
| 3009.2.17
by Aaron Bentley Update docs | 564 | """Compare two files in unified diff format | 
| 565 | ||
| 566 |         :param file_id: The file_id of the file to compare
 | |
| 567 |         :param old_path: Path of the file in the old tree
 | |
| 568 |         :param new_path: Path of the file in the new tree
 | |
| 569 |         :param old_kind: Old file-kind of the file
 | |
| 570 |         :param new_kind: New file-kind of the file
 | |
| 571 |         """
 | |
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 572 | if 'file' not in (old_kind, new_kind): | 
| 3009.2.14
by Aaron Bentley Update return type handling | 573 | return self.CANNOT_DIFF | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 574 | from_file_id = to_file_id = file_id | 
| 575 | if old_kind == 'file': | |
| 576 | old_date = _patch_header_date(self.old_tree, file_id, old_path) | |
| 577 | elif old_kind is None: | |
| 578 | old_date = self.EPOCH_DATE | |
| 3009.2.12
by Aaron Bentley Associate labels with text diffing only | 579 | from_file_id = None | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 580 | else: | 
| 3009.2.14
by Aaron Bentley Update return type handling | 581 | return self.CANNOT_DIFF | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 582 | if new_kind == 'file': | 
| 583 | new_date = _patch_header_date(self.new_tree, file_id, new_path) | |
| 584 | elif new_kind is None: | |
| 585 | new_date = self.EPOCH_DATE | |
| 586 | to_file_id = None | |
| 587 | else: | |
| 3009.2.14
by Aaron Bentley Update return type handling | 588 | return self.CANNOT_DIFF | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 589 | from_label = '%s%s\t%s' % (self.old_label, old_path, old_date) | 
| 590 | to_label = '%s%s\t%s' % (self.new_label, new_path, new_date) | |
| 591 | return self.diff_text(from_file_id, to_file_id, from_label, to_label) | |
| 592 | ||
| 593 | def diff_text(self, from_file_id, to_file_id, from_label, to_label): | |
| 594 | """Diff the content of given files in two trees | |
| 595 | ||
| 596 |         :param from_file_id: The id of the file in the from tree.  If None,
 | |
| 597 |             the file is not present in the from tree.
 | |
| 598 |         :param to_file_id: The id of the file in the to tree.  This may refer
 | |
| 599 |             to a different file from from_file_id.  If None,
 | |
| 600 |             the file is not present in the to tree.
 | |
| 601 |         """
 | |
| 602 | def _get_text(tree, file_id): | |
| 603 | if file_id is not None: | |
| 604 | return tree.get_file(file_id).readlines() | |
| 605 | else: | |
| 606 | return [] | |
| 607 | try: | |
| 608 | from_text = _get_text(self.old_tree, from_file_id) | |
| 609 | to_text = _get_text(self.new_tree, to_file_id) | |
| 610 | self.text_differ(from_label, from_text, to_label, to_text, | |
| 611 | self.to_file) | |
| 612 | except errors.BinaryFile: | |
| 613 | self.to_file.write( | |
| 614 | ("Binary files %s and %s differ\n" % | |
| 615 | (from_label, to_label)).encode(self.path_encoding)) | |
| 3009.2.14
by Aaron Bentley Update return type handling | 616 | return self.CHANGED | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 617 | |
| 618 | ||
| 3009.2.22
by Aaron Bentley Update names & docstring | 619 | class DiffTree(object): | 
| 620 | """Provides textual representations of the difference between two trees. | |
| 621 | ||
| 622 |     A DiffTree examines two trees and where a file-id has altered
 | |
| 623 |     between them, generates a textual representation of the difference.
 | |
| 624 |     DiffTree uses a sequence of DiffPath objects which are each
 | |
| 625 |     given the opportunity to handle a given altered fileid. The list
 | |
| 626 |     of DiffPath objects can be extended globally by appending to
 | |
| 627 |     DiffTree.diff_factories, or for a specific diff operation by
 | |
| 3009.2.27
by Aaron Bentley Use extra_factories instead of extra_diffs | 628 |     supplying the extra_factories option to the appropriate method.
 | 
| 3009.2.22
by Aaron Bentley Update names & docstring | 629 |     """
 | 
| 630 | ||
| 631 |     # list of factories that can provide instances of DiffPath objects
 | |
| 3009.2.17
by Aaron Bentley Update docs | 632 |     # may be extended by plugins.
 | 
| 3009.2.28
by Aaron Bentley Add from_diff_tree factories | 633 | diff_factories = [DiffSymlink.from_diff_tree, | 
| 634 | DiffDirectory.from_diff_tree] | |
| 3009.2.13
by Aaron Bentley Refactor differ to support registering differ factories | 635 | |
| 3009.2.12
by Aaron Bentley Associate labels with text diffing only | 636 | def __init__(self, old_tree, new_tree, to_file, path_encoding='utf-8', | 
| 3009.2.28
by Aaron Bentley Add from_diff_tree factories | 637 | diff_text=None, extra_factories=None): | 
| 3009.2.17
by Aaron Bentley Update docs | 638 | """Constructor | 
| 639 | ||
| 640 |         :param old_tree: Tree to show as old in the comparison
 | |
| 641 |         :param new_tree: Tree to show as new in the comparison
 | |
| 642 |         :param to_file: File to write comparision to
 | |
| 643 |         :param path_encoding: Character encoding to write paths in
 | |
| 3009.2.28
by Aaron Bentley Add from_diff_tree factories | 644 |         :param diff_text: DiffPath-type object to use as a last resort for
 | 
| 3009.2.17
by Aaron Bentley Update docs | 645 |             diffing text files.
 | 
| 3009.2.27
by Aaron Bentley Use extra_factories instead of extra_diffs | 646 |         :param extra_factories: Factories of DiffPaths to try before any other
 | 
| 647 |             DiffPaths"""
 | |
| 3009.2.28
by Aaron Bentley Add from_diff_tree factories | 648 | if diff_text is None: | 
| 649 | diff_text = DiffText(old_tree, new_tree, to_file, path_encoding, | |
| 650 | '', '', internal_diff) | |
| 3009.2.4
by Aaron Bentley Make old_tree/new_tree construction parameters of Differ | 651 | self.old_tree = old_tree | 
| 652 | self.new_tree = new_tree | |
| 3009.2.2
by Aaron Bentley Implement Differ object for abstracting diffing | 653 | self.to_file = to_file | 
| 3009.2.28
by Aaron Bentley Add from_diff_tree factories | 654 | self.path_encoding = path_encoding | 
| 3009.2.13
by Aaron Bentley Refactor differ to support registering differ factories | 655 | self.differs = [] | 
| 3009.2.27
by Aaron Bentley Use extra_factories instead of extra_diffs | 656 | if extra_factories is not None: | 
| 3009.2.28
by Aaron Bentley Add from_diff_tree factories | 657 | self.differs.extend(f(self) for f in extra_factories) | 
| 658 | self.differs.extend(f(self) for f in self.diff_factories) | |
| 659 | self.differs.extend([diff_text, DiffKindChange.from_diff_tree(self)]) | |
| 3009.2.6
by Aaron Bentley Convert show_diff_trees into a Differ method | 660 | |
| 661 |     @classmethod
 | |
| 662 | def from_trees_options(klass, old_tree, new_tree, to_file, | |
| 3009.2.17
by Aaron Bentley Update docs | 663 | path_encoding, external_diff_options, old_label, | 
| 664 | new_label): | |
| 3009.2.22
by Aaron Bentley Update names & docstring | 665 | """Factory for producing a DiffTree. | 
| 3009.2.17
by Aaron Bentley Update docs | 666 | |
| 667 |         Designed to accept options used by show_diff_trees.
 | |
| 668 |         :param old_tree: The tree to show as old in the comparison
 | |
| 669 |         :param new_tree: The tree to show as new in the comparison
 | |
| 670 |         :param to_file: File to write comparisons to
 | |
| 671 |         :param path_encoding: Character encoding to use for writing paths
 | |
| 672 |         :param external_diff_options: If supplied, use the installed diff
 | |
| 673 |             binary to perform file comparison, using supplied options.
 | |
| 674 |         :param old_label: Prefix to use for old file labels
 | |
| 675 |         :param new_label: Prefix to use for new file labels
 | |
| 676 |         """
 | |
| 3009.2.6
by Aaron Bentley Convert show_diff_trees into a Differ method | 677 | if external_diff_options: | 
| 678 | assert isinstance(external_diff_options, basestring) | |
| 679 | opts = external_diff_options.split() | |
| 680 | def diff_file(olab, olines, nlab, nlines, to_file): | |
| 681 | external_diff(olab, olines, nlab, nlines, to_file, opts) | |
| 682 | else: | |
| 683 | diff_file = internal_diff | |
| 3009.2.28
by Aaron Bentley Add from_diff_tree factories | 684 | diff_text = DiffText(old_tree, new_tree, to_file, path_encoding, | 
| 685 | old_label, new_label, diff_file) | |
| 686 | return klass(old_tree, new_tree, to_file, path_encoding, diff_text) | |
| 3009.2.6
by Aaron Bentley Convert show_diff_trees into a Differ method | 687 | |
| 3009.2.12
by Aaron Bentley Associate labels with text diffing only | 688 | def show_diff(self, specific_files, extra_trees=None): | 
| 3009.2.17
by Aaron Bentley Update docs | 689 | """Write tree diff to self.to_file | 
| 690 | ||
| 691 |         :param sepecific_files: the specific files to compare (recursive)
 | |
| 692 |         :param extra_trees: extra trees to use for mapping paths to file_ids
 | |
| 693 |         """
 | |
| 3009.2.6
by Aaron Bentley Convert show_diff_trees into a Differ method | 694 |         # TODO: Generation of pseudo-diffs for added/deleted files could
 | 
| 695 |         # be usefully made into a much faster special case.
 | |
| 696 | ||
| 697 | delta = self.new_tree.changes_from(self.old_tree, | |
| 698 | specific_files=specific_files, | |
| 699 | extra_trees=extra_trees, require_versioned=True) | |
| 700 | ||
| 701 | has_changes = 0 | |
| 702 | for path, file_id, kind in delta.removed: | |
| 703 | has_changes = 1 | |
| 704 | path_encoded = path.encode(self.path_encoding, "replace") | |
| 705 | self.to_file.write("=== removed %s '%s'\n" % (kind, path_encoded)) | |
| 3009.2.12
by Aaron Bentley Associate labels with text diffing only | 706 | self.diff(file_id, path, path) | 
| 3009.2.6
by Aaron Bentley Convert show_diff_trees into a Differ method | 707 | |
| 708 | for path, file_id, kind in delta.added: | |
| 709 | has_changes = 1 | |
| 710 | path_encoded = path.encode(self.path_encoding, "replace") | |
| 711 | self.to_file.write("=== added %s '%s'\n" % (kind, path_encoded)) | |
| 3009.2.12
by Aaron Bentley Associate labels with text diffing only | 712 | self.diff(file_id, path, path) | 
| 3009.2.6
by Aaron Bentley Convert show_diff_trees into a Differ method | 713 | for (old_path, new_path, file_id, kind, | 
| 714 | text_modified, meta_modified) in delta.renamed: | |
| 715 | has_changes = 1 | |
| 716 | prop_str = get_prop_change(meta_modified) | |
| 717 | oldpath_encoded = old_path.encode(self.path_encoding, "replace") | |
| 718 | newpath_encoded = new_path.encode(self.path_encoding, "replace") | |
| 719 | self.to_file.write("=== renamed %s '%s' => '%s'%s\n" % (kind, | |
| 720 | oldpath_encoded, newpath_encoded, prop_str)) | |
| 3009.2.7
by Aaron Bentley Move responsibility for generating diff labels into Differ.diff | 721 | if text_modified: | 
| 3009.2.12
by Aaron Bentley Associate labels with text diffing only | 722 | self.diff(file_id, old_path, new_path) | 
| 3009.2.6
by Aaron Bentley Convert show_diff_trees into a Differ method | 723 | for path, file_id, kind, text_modified, meta_modified in\ | 
| 724 | delta.modified: | |
| 725 | has_changes = 1 | |
| 726 | prop_str = get_prop_change(meta_modified) | |
| 727 | path_encoded = path.encode(self.path_encoding, "replace") | |
| 728 | self.to_file.write("=== modified %s '%s'%s\n" % (kind, | |
| 729 | path_encoded, prop_str)) | |
| 730 |             # The file may be in a different location in the old tree (because
 | |
| 731 |             # the containing dir was renamed, but the file itself was not)
 | |
| 732 | if text_modified: | |
| 3009.2.7
by Aaron Bentley Move responsibility for generating diff labels into Differ.diff | 733 | old_path = self.old_tree.id2path(file_id) | 
| 3009.2.12
by Aaron Bentley Associate labels with text diffing only | 734 | self.diff(file_id, old_path, path) | 
| 3009.2.6
by Aaron Bentley Convert show_diff_trees into a Differ method | 735 | return has_changes | 
| 3009.2.2
by Aaron Bentley Implement Differ object for abstracting diffing | 736 | |
| 3009.2.12
by Aaron Bentley Associate labels with text diffing only | 737 | def diff(self, file_id, old_path, new_path): | 
| 3009.2.17
by Aaron Bentley Update docs | 738 | """Perform a diff of a single file | 
| 739 | ||
| 740 |         :param file_id: file-id of the file
 | |
| 741 |         :param old_path: The path of the file in the old tree
 | |
| 742 |         :param new_path: The path of the file in the new tree
 | |
| 743 |         """
 | |
| 3009.2.2
by Aaron Bentley Implement Differ object for abstracting diffing | 744 | try: | 
| 3009.2.8
by Aaron Bentley Support diffing without indirecting through inventory entries | 745 | old_kind = self.old_tree.kind(file_id) | 
| 3087.1.1
by Aaron Bentley Diff handles missing files correctly, with no tracebacks | 746 | except (errors.NoSuchId, errors.NoSuchFile): | 
| 3009.2.8
by Aaron Bentley Support diffing without indirecting through inventory entries | 747 | old_kind = None | 
| 3009.2.3
by Aaron Bentley Detect missing files from inv operation | 748 | try: | 
| 3009.2.8
by Aaron Bentley Support diffing without indirecting through inventory entries | 749 | new_kind = self.new_tree.kind(file_id) | 
| 3087.1.1
by Aaron Bentley Diff handles missing files correctly, with no tracebacks | 750 | except (errors.NoSuchId, errors.NoSuchFile): | 
| 3009.2.8
by Aaron Bentley Support diffing without indirecting through inventory entries | 751 | new_kind = None | 
| 3009.2.7
by Aaron Bentley Move responsibility for generating diff labels into Differ.diff | 752 | |
| 3009.2.22
by Aaron Bentley Update names & docstring | 753 | result = DiffPath._diff_many(self.differs, file_id, old_path, | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 754 | new_path, old_kind, new_kind) | 
| 3009.2.22
by Aaron Bentley Update names & docstring | 755 | if result is DiffPath.CANNOT_DIFF: | 
| 3009.2.11
by Aaron Bentley Refactor diff to be more pluggable | 756 | error_path = new_path | 
| 757 | if error_path is None: | |
| 758 | error_path = old_path | |
| 3009.2.22
by Aaron Bentley Update names & docstring | 759 | raise errors.NoDiffFound(error_path) |