/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

  • Committer: Martin
  • Date: 2010-05-03 20:57:39 UTC
  • mto: This revision was merged to the branch mainline in revision 5204.
  • Revision ID: gzlist@googlemail.com-20100503205739-n326zdvevv0rmruh
Retain original stack and error message when translating to ValueError in bencode

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005, 2006 Canonical Ltd.
 
1
# Copyright (C) 2005-2010 Canonical Ltd.
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
17
17
import difflib
18
18
import os
19
19
import re
20
 
import shutil
21
20
import string
22
21
import sys
23
22
 
31
30
from bzrlib import (
32
31
    branch as _mod_branch,
33
32
    bzrdir,
34
 
    commands,
 
33
    cmdline,
 
34
    cleanup,
35
35
    errors,
36
36
    osutils,
37
37
    patiencediff,
39
39
    timestamp,
40
40
    views,
41
41
    )
 
42
 
 
43
from bzrlib.workingtree import WorkingTree
42
44
""")
43
45
 
 
46
from bzrlib.registry import (
 
47
    Registry,
 
48
    )
44
49
from bzrlib.symbol_versioning import (
45
50
    deprecated_function,
 
51
    deprecated_in,
46
52
    )
47
53
from bzrlib.trace import mutter, note, warning
48
54
 
284
290
                        new_abspath, e)
285
291
 
286
292
 
 
293
@deprecated_function(deprecated_in((2, 2, 0)))
287
294
def get_trees_and_branches_to_diff(path_list, revision_specs, old_url, new_url,
288
295
                                   apply_view=True):
289
296
    """Get the trees and specific files to diff given a list of paths.
308
315
    :returns:
309
316
        a tuple of (old_tree, new_tree, old_branch, new_branch,
310
317
        specific_files, extra_trees) where extra_trees is a sequence of
311
 
        additional trees to search in for file-ids.
 
318
        additional trees to search in for file-ids.  The trees and branches
 
319
        are not locked.
 
320
    """
 
321
    op = cleanup.OperationWithCleanups(get_trees_and_branches_to_diff_locked)
 
322
    return op.run_simple(path_list, revision_specs, old_url, new_url,
 
323
            op.add_cleanup, apply_view=apply_view)
 
324
    
 
325
 
 
326
def get_trees_and_branches_to_diff_locked(
 
327
    path_list, revision_specs, old_url, new_url, add_cleanup, apply_view=True):
 
328
    """Get the trees and specific files to diff given a list of paths.
 
329
 
 
330
    This method works out the trees to be diff'ed and the files of
 
331
    interest within those trees.
 
332
 
 
333
    :param path_list:
 
334
        the list of arguments passed to the diff command
 
335
    :param revision_specs:
 
336
        Zero, one or two RevisionSpecs from the diff command line,
 
337
        saying what revisions to compare.
 
338
    :param old_url:
 
339
        The url of the old branch or tree. If None, the tree to use is
 
340
        taken from the first path, if any, or the current working tree.
 
341
    :param new_url:
 
342
        The url of the new branch or tree. If None, the tree to use is
 
343
        taken from the first path, if any, or the current working tree.
 
344
    :param add_cleanup:
 
345
        a callable like Command.add_cleanup.  get_trees_and_branches_to_diff
 
346
        will register cleanups that must be run to unlock the trees, etc.
 
347
    :param apply_view:
 
348
        if True and a view is set, apply the view or check that the paths
 
349
        are within it
 
350
    :returns:
 
351
        a tuple of (old_tree, new_tree, old_branch, new_branch,
 
352
        specific_files, extra_trees) where extra_trees is a sequence of
 
353
        additional trees to search in for file-ids.  The trees and branches
 
354
        will be read-locked until the cleanups registered via the add_cleanup
 
355
        param are run.
312
356
    """
313
357
    # Get the old and new revision specs
314
358
    old_revision_spec = None
337
381
        default_location = path_list[0]
338
382
        other_paths = path_list[1:]
339
383
 
 
384
    def lock_tree_or_branch(wt, br):
 
385
        if wt is not None:
 
386
            wt.lock_read()
 
387
            add_cleanup(wt.unlock)
 
388
        elif br is not None:
 
389
            br.lock_read()
 
390
            add_cleanup(br.unlock)
 
391
 
340
392
    # Get the old location
341
393
    specific_files = []
342
394
    if old_url is None:
343
395
        old_url = default_location
344
396
    working_tree, branch, relpath = \
345
397
        bzrdir.BzrDir.open_containing_tree_or_branch(old_url)
 
398
    lock_tree_or_branch(working_tree, branch)
346
399
    if consider_relpath and relpath != '':
347
400
        if working_tree is not None and apply_view:
348
401
            views.check_path_in_view(working_tree, relpath)
356
409
    if new_url != old_url:
357
410
        working_tree, branch, relpath = \
358
411
            bzrdir.BzrDir.open_containing_tree_or_branch(new_url)
 
412
        lock_tree_or_branch(working_tree, branch)
359
413
        if consider_relpath and relpath != '':
360
414
            if working_tree is not None and apply_view:
361
415
                views.check_path_in_view(working_tree, relpath)
409
463
                    old_label='a/', new_label='b/',
410
464
                    extra_trees=None,
411
465
                    path_encoding='utf8',
412
 
                    using=None):
 
466
                    using=None,
 
467
                    format_cls=None):
413
468
    """Show in text form the changes from one tree to another.
414
469
 
415
 
    to_file
416
 
        The output stream.
417
 
 
418
 
    specific_files
419
 
        Include only changes to these files - None for all changes.
420
 
 
421
 
    external_diff_options
422
 
        If set, use an external GNU diff and pass these options.
423
 
 
424
 
    extra_trees
425
 
        If set, more Trees to use for looking up file ids
426
 
 
427
 
    path_encoding
428
 
        If set, the path will be encoded as specified, otherwise is supposed
429
 
        to be utf8
 
470
    :param to_file: The output stream.
 
471
    :param specific_files:Include only changes to these files - None for all
 
472
        changes.
 
473
    :param external_diff_options: If set, use an external GNU diff and pass 
 
474
        these options.
 
475
    :param extra_trees: If set, more Trees to use for looking up file ids
 
476
    :param path_encoding: If set, the path will be encoded as specified, 
 
477
        otherwise is supposed to be utf8
 
478
    :param format_cls: Formatter class (DiffTree subclass)
430
479
    """
 
480
    if format_cls is None:
 
481
        format_cls = DiffTree
431
482
    old_tree.lock_read()
432
483
    try:
433
484
        if extra_trees is not None:
435
486
                tree.lock_read()
436
487
        new_tree.lock_read()
437
488
        try:
438
 
            differ = DiffTree.from_trees_options(old_tree, new_tree, to_file,
439
 
                                                 path_encoding,
440
 
                                                 external_diff_options,
441
 
                                                 old_label, new_label, using)
 
489
            differ = format_cls.from_trees_options(old_tree, new_tree, to_file,
 
490
                                                   path_encoding,
 
491
                                                   external_diff_options,
 
492
                                                   old_label, new_label, using)
442
493
            return differ.show_diff(specific_files, extra_trees)
443
494
        finally:
444
495
            new_tree.unlock()
451
502
 
452
503
def _patch_header_date(tree, file_id, path):
453
504
    """Returns a timestamp suitable for use in a patch header."""
454
 
    mtime = tree.get_file_mtime(file_id, path)
 
505
    try:
 
506
        mtime = tree.get_file_mtime(file_id, path)
 
507
    except errors.FileTimestampUnavailable:
 
508
        mtime = 0
455
509
    return timestamp.format_patch_date(mtime)
456
510
 
457
511
 
678
732
    @classmethod
679
733
    def from_string(klass, command_string, old_tree, new_tree, to_file,
680
734
                    path_encoding='utf-8'):
681
 
        command_template = commands.shlex_split_unicode(command_string)
 
735
        command_template = cmdline.split(command_string)
682
736
        if '@' not in command_string:
683
737
            command_template.extend(['@old_path', '@new_path'])
684
738
        return klass(command_template, old_tree, new_tree, to_file,
722
776
 
723
777
    def _write_file(self, file_id, tree, prefix, relpath, force_temp=False,
724
778
                    allow_write=False):
 
779
        if not force_temp and isinstance(tree, WorkingTree):
 
780
            return tree.abspath(tree.id2path(file_id))
 
781
        
725
782
        full_path = osutils.pathjoin(self._root, prefix, relpath)
726
783
        if not force_temp and self._try_symlink_root(tree, prefix):
727
784
            return full_path
740
797
                target.close()
741
798
        finally:
742
799
            source.close()
 
800
        try:
 
801
            mtime = tree.get_file_mtime(file_id)
 
802
        except errors.FileTimestampUnavailable:
 
803
            pass
 
804
        else:
 
805
            os.utime(full_path, (mtime, mtime))
743
806
        if not allow_write:
744
807
            osutils.make_readonly(full_path)
745
 
        mtime = tree.get_file_mtime(file_id)
746
 
        os.utime(full_path, (mtime, mtime))
747
808
        return full_path
748
809
 
749
810
    def _prepare_files(self, file_id, old_path, new_path, force_temp=False,
766
827
    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
767
828
        if (old_kind, new_kind) != ('file', 'file'):
768
829
            return DiffPath.CANNOT_DIFF
769
 
        self._prepare_files(file_id, old_path, new_path)
770
 
        self._execute(osutils.pathjoin('old', old_path),
771
 
                      osutils.pathjoin('new', new_path))
 
830
        (old_disk_path, new_disk_path) = self._prepare_files(
 
831
                                                file_id, old_path, new_path)
 
832
        self._execute(old_disk_path, new_disk_path)
772
833
 
773
834
    def edit_file(self, file_id):
774
835
        """Use this tool to edit a file.
871
932
    def show_diff(self, specific_files, extra_trees=None):
872
933
        """Write tree diff to self.to_file
873
934
 
874
 
        :param sepecific_files: the specific files to compare (recursive)
 
935
        :param specific_files: the specific files to compare (recursive)
875
936
        :param extra_trees: extra trees to use for mapping paths to file_ids
876
937
        """
877
938
        try:
967
1028
            if error_path is None:
968
1029
                error_path = old_path
969
1030
            raise errors.NoDiffFound(error_path)
 
1031
 
 
1032
 
 
1033
format_registry = Registry()
 
1034
format_registry.register('default', DiffTree)