~jelmer/ubuntu/maverick/bzr/2.2.5

« back to all changes in this revision

Viewing changes to bzrlib/diff.py

ImportĀ upstreamĀ versionĀ 1.13~rc1

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
    patiencediff,
37
37
    textfile,
38
38
    timestamp,
 
39
    views,
39
40
    )
40
41
""")
41
42
 
43
44
        deprecated_function,
44
45
        one_three
45
46
        )
46
 
from bzrlib.trace import mutter, warning
 
47
from bzrlib.trace import mutter, note, warning
47
48
 
48
49
 
49
50
# TODO: Rather than building a changeset object, we should probably
78
79
    # both sequences are empty.
79
80
    if not oldlines and not newlines:
80
81
        return
81
 
    
 
82
 
82
83
    if allow_binary is False:
83
84
        textfile.check_text_lines(oldlines)
84
85
        textfile.check_text_lines(newlines)
99
100
        ud[2] = ud[2].replace('-1,0', '-0,0')
100
101
    elif not newlines:
101
102
        ud[2] = ud[2].replace('+1,0', '+0,0')
102
 
    # work around for difflib emitting random spaces after the label
103
 
    ud[0] = ud[0][:-2] + '\n'
104
 
    ud[1] = ud[1][:-2] + '\n'
105
103
 
106
104
    for line in ud:
107
105
        to_file.write(line)
202
200
            break
203
201
        else:
204
202
            diffcmd.append('-u')
205
 
                  
 
203
 
206
204
        if diff_opts:
207
205
            diffcmd.extend(diff_opts)
208
206
 
209
207
        pipe = _spawn_external_diff(diffcmd, capture_errors=True)
210
208
        out,err = pipe.communicate()
211
209
        rc = pipe.returncode
212
 
        
 
210
 
213
211
        # internal_diff() adds a trailing newline, add one here for consistency
214
212
        out += '\n'
215
213
        if rc == 2:
250
248
                msg = 'signal %d' % (-rc)
251
249
            else:
252
250
                msg = 'exit code %d' % rc
253
 
                
254
 
            raise errors.BzrError('external diff failed with %s; command: %r' 
 
251
 
 
252
            raise errors.BzrError('external diff failed with %s; command: %r'
255
253
                                  % (rc, diffcmd))
256
254
 
257
255
 
275
273
                        new_abspath, e)
276
274
 
277
275
 
278
 
def _get_trees_to_diff(path_list, revision_specs, old_url, new_url):
 
276
def _get_trees_to_diff(path_list, revision_specs, old_url, new_url,
 
277
    apply_view=True):
279
278
    """Get the trees and specific files to diff given a list of paths.
280
279
 
281
280
    This method works out the trees to be diff'ed and the files of
292
291
    :param new_url:
293
292
        The url of the new branch or tree. If None, the tree to use is
294
293
        taken from the first path, if any, or the current working tree.
 
294
    :param apply_view:
 
295
        if True and a view is set, apply the view or check that the paths
 
296
        are within it
295
297
    :returns:
296
298
        a tuple of (old_tree, new_tree, specific_files, extra_trees) where
297
299
        extra_trees is a sequence of additional trees to search in for
331
333
    working_tree, branch, relpath = \
332
334
        bzrdir.BzrDir.open_containing_tree_or_branch(old_url)
333
335
    if consider_relpath and relpath != '':
 
336
        if working_tree is not None and apply_view:
 
337
            views.check_path_in_view(working_tree, relpath)
334
338
        specific_files.append(relpath)
335
339
    old_tree = _get_tree_to_diff(old_revision_spec, working_tree, branch)
336
340
 
341
345
        working_tree, branch, relpath = \
342
346
            bzrdir.BzrDir.open_containing_tree_or_branch(new_url)
343
347
        if consider_relpath and relpath != '':
 
348
            if working_tree is not None and apply_view:
 
349
                views.check_path_in_view(working_tree, relpath)
344
350
            specific_files.append(relpath)
345
351
    new_tree = _get_tree_to_diff(new_revision_spec, working_tree, branch,
346
352
        basis_is_default=working_tree is None)
347
353
 
348
354
    # Get the specific files (all files is None, no files is [])
349
355
    if make_paths_wt_relative and working_tree is not None:
350
 
        other_paths = _relative_paths_in_tree(working_tree, other_paths)
 
356
        try:
 
357
            from bzrlib.builtins import safe_relpath_files
 
358
            other_paths = safe_relpath_files(working_tree, other_paths,
 
359
            apply_view=apply_view)
 
360
        except errors.FileInWrongBranch:
 
361
            raise errors.BzrCommandError("Files are in different branches")
351
362
    specific_files.extend(other_paths)
352
363
    if len(specific_files) == 0:
353
364
        specific_files = None
 
365
        if (working_tree is not None and working_tree.supports_views()
 
366
            and apply_view):
 
367
            view_files = working_tree.views.lookup_view()
 
368
            if view_files:
 
369
                specific_files = view_files
 
370
                view_str = views.view_display_str(view_files)
 
371
                note("*** ignoring files outside view: %s" % view_str)
354
372
 
355
373
    # Get extra trees that ought to be searched for file-ids
356
374
    extra_trees = None
358
376
        extra_trees = (working_tree,)
359
377
    return old_tree, new_tree, specific_files, extra_trees
360
378
 
361
 
 
362
379
def _get_tree_to_diff(spec, tree=None, branch=None, basis_is_default=True):
363
380
    if branch is None and tree is not None:
364
381
        branch = tree.branch
370
387
                return branch.basis_tree()
371
388
        else:
372
389
            return tree
373
 
    if not spec.needs_branch():
374
 
        branch = _mod_branch.Branch.open(spec.get_branch())
375
 
    revision_id = spec.as_revision_id(branch)
376
 
    return branch.repository.revision_tree(revision_id)
377
 
 
378
 
 
379
 
def _relative_paths_in_tree(tree, paths):
380
 
    """Get the relative paths within a working tree.
381
 
 
382
 
    Each path may be either an absolute path or a path relative to the
383
 
    current working directory.
384
 
    """
385
 
    result = []
386
 
    for filename in paths:
387
 
        try:
388
 
            result.append(tree.relpath(osutils.dereference_path(filename)))
389
 
        except errors.PathNotChild:
390
 
            raise errors.BzrCommandError("Files are in different branches")
391
 
    return result
 
390
    return spec.as_tree(branch)
392
391
 
393
392
 
394
393
def show_diff_trees(old_tree, new_tree, to_file, specific_files=None,
442
441
    return timestamp.format_patch_date(mtime)
443
442
 
444
443
 
445
 
def _raise_if_nonexistent(paths, old_tree, new_tree):
446
 
    """Complain if paths are not in either inventory or tree.
447
 
 
448
 
    It's OK with the files exist in either tree's inventory, or 
449
 
    if they exist in the tree but are not versioned.
450
 
    
451
 
    This can be used by operations such as bzr status that can accept
452
 
    unknown or ignored files.
453
 
    """
454
 
    mutter("check paths: %r", paths)
455
 
    if not paths:
456
 
        return
457
 
    s = old_tree.filter_unversioned_files(paths)
458
 
    s = new_tree.filter_unversioned_files(s)
459
 
    s = [path for path in s if not new_tree.has_filename(path)]
460
 
    if s:
461
 
        raise errors.PathsDoNotExist(sorted(s))
462
 
 
463
 
 
464
444
@deprecated_function(one_three)
465
445
def get_prop_change(meta_modified):
466
446
    if meta_modified:
682
662
                 path_encoding='utf-8'):
683
663
        DiffPath.__init__(self, old_tree, new_tree, to_file, path_encoding)
684
664
        self.command_template = command_template
685
 
        self._root = tempfile.mkdtemp(prefix='bzr-diff-')
 
665
        self._root = osutils.mkdtemp(prefix='bzr-diff-')
686
666
 
687
667
    @classmethod
688
668
    def from_string(klass, command_string, old_tree, new_tree, to_file,
717
697
        return proc.wait()
718
698
 
719
699
    def _try_symlink_root(self, tree, prefix):
720
 
        if not (getattr(tree, 'abspath', None) is not None
721
 
                and osutils.has_symlinks()):
 
700
        if (getattr(tree, 'abspath', None) is None
 
701
            or not osutils.host_os_dereferences_symlinks()):
722
702
            return False
723
703
        try:
724
704
            os.symlink(tree.abspath(''), osutils.pathjoin(self._root, prefix))
874
854
                return path.encode(self.path_encoding, "replace")
875
855
        for (file_id, paths, changed_content, versioned, parent, name, kind,
876
856
             executable) in sorted(iterator, key=changes_key):
877
 
            if parent == (None, None):
 
857
            # The root does not get diffed, and items with no known kind (that
 
858
            # is, missing) in both trees are skipped as well.
 
859
            if parent == (None, None) or kind == (None, None):
878
860
                continue
879
861
            oldpath, newpath = paths
880
862
            oldpath_encoded = get_encoded_path(paths[0])