~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

Merge cleanups into refactor-delta-show

Show diffs side-by-side

added added

removed removed

Lines of Context:
59
59
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
60
60
 
61
61
 
62
 
def tree_files(file_list, default_branch=u'.'):
 
62
def tree_files(file_list, default_branch=u'.', canonicalize=True):
63
63
    try:
64
 
        return internal_tree_files(file_list, default_branch)
 
64
        return internal_tree_files(file_list, default_branch, canonicalize)
65
65
    except errors.FileInWrongBranch, e:
66
66
        raise errors.BzrCommandError("%s is not in the same branch as %s" %
67
67
                                     (e.path, file_list[0]))
86
86
 
87
87
# XXX: Bad function name; should possibly also be a class method of
88
88
# WorkingTree rather than a function.
89
 
def internal_tree_files(file_list, default_branch=u'.'):
 
89
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True):
90
90
    """Convert command-line paths to a WorkingTree and relative paths.
91
91
 
92
92
    This is typically used for command-line processors that take one or
104
104
    if file_list is None or len(file_list) == 0:
105
105
        return WorkingTree.open_containing(default_branch)[0], file_list
106
106
    tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
107
 
    return tree, safe_relpath_files(tree, file_list)
108
 
 
109
 
 
110
 
def safe_relpath_files(tree, file_list):
 
107
    return tree, safe_relpath_files(tree, file_list, canonicalize)
 
108
 
 
109
 
 
110
def safe_relpath_files(tree, file_list, canonicalize=True):
111
111
    """Convert file_list into a list of relpaths in tree.
112
112
 
113
113
    :param tree: A tree to operate on.
119
119
    if file_list is None:
120
120
        return None
121
121
    new_list = []
 
122
    # tree.relpath exists as a "thunk" to osutils, but canonical_relpath
 
123
    # doesn't - fix that up here before we enter the loop.
 
124
    if canonicalize:
 
125
        fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
 
126
    else:
 
127
        fixer = tree.relpath
122
128
    for filename in file_list:
123
129
        try:
124
 
            new_list.append(tree.relpath(osutils.dereference_path(filename)))
 
130
            new_list.append(fixer(osutils.dereference_path(filename)))
125
131
        except errors.PathNotChild:
126
132
            raise errors.FileInWrongBranch(tree.branch, filename)
127
133
    return new_list
172
178
    files or directories is reported.  If a directory is given, status
173
179
    is reported for everything inside that directory.
174
180
 
 
181
    Before merges are committed, the pending merge tip revisions are
 
182
    shown. To see all pending merge revisions, use the -v option.
 
183
    To skip the display of pending merge information altogether, use
 
184
    the no-pending option or specify a file/directory.
 
185
 
175
186
    If a revision argument is given, the status is calculated against
176
187
    that revision, or between two revisions if two are provided.
177
188
    """
179
190
    # TODO: --no-recurse, --recurse options
180
191
    
181
192
    takes_args = ['file*']
182
 
    takes_options = ['show-ids', 'revision', 'change',
 
193
    takes_options = ['show-ids', 'revision', 'change', 'verbose',
183
194
                     Option('short', help='Use short status indicators.',
184
195
                            short_name='S'),
185
196
                     Option('versioned', help='Only show versioned files.',
194
205
    
195
206
    @display_command
196
207
    def run(self, show_ids=False, file_list=None, revision=None, short=False,
197
 
            versioned=False, no_pending=False):
 
208
            versioned=False, no_pending=False, verbose=False):
198
209
        from bzrlib.status import show_tree_status
199
210
 
200
211
        if revision and len(revision) > 2:
214
225
        show_tree_status(tree, show_ids=show_ids,
215
226
                         specific_files=relfile_list, revision=revision,
216
227
                         to_file=self.outf, short=short, versioned=versioned,
217
 
                         show_pending=(not no_pending))
 
228
                         show_pending=(not no_pending), verbose=verbose)
218
229
 
219
230
 
220
231
class cmd_cat_revision(Command):
655
666
 
656
667
        if len(names_list) < 2:
657
668
            raise errors.BzrCommandError("missing file argument")
658
 
        tree, rel_names = tree_files(names_list)
 
669
        tree, rel_names = tree_files(names_list, canonicalize=False)
659
670
        tree.lock_write()
660
671
        try:
661
672
            self._run(tree, names_list, rel_names, after)
675
686
                into_existing = False
676
687
            else:
677
688
                inv = tree.inventory
678
 
                from_id = tree.path2id(rel_names[0])
 
689
                # 'fix' the case of a potential 'from'
 
690
                from_id = tree.path2id(
 
691
                            tree.get_canonical_inventory_path(rel_names[0]))
679
692
                if (not osutils.lexists(names_list[0]) and
680
693
                    from_id and inv.get_file_kind(from_id) == "directory"):
681
694
                    into_existing = False
682
695
        # move/rename
683
696
        if into_existing:
684
697
            # move into existing directory
 
698
            # All entries reference existing inventory items, so fix them up
 
699
            # for cicp file-systems.
 
700
            rel_names = tree.get_canonical_inventory_paths(rel_names)
685
701
            for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
686
702
                self.outf.write("%s => %s\n" % pair)
687
703
        else:
689
705
                raise errors.BzrCommandError('to mv multiple files the'
690
706
                                             ' destination must be a versioned'
691
707
                                             ' directory')
692
 
            tree.rename_one(rel_names[0], rel_names[1], after=after)
693
 
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
 
708
 
 
709
            # for cicp file-systems: the src references an existing inventory
 
710
            # item:
 
711
            src = tree.get_canonical_inventory_path(rel_names[0])
 
712
            # Find the canonical version of the destination:  In all cases, the
 
713
            # parent of the target must be in the inventory, so we fetch the
 
714
            # canonical version from there (we do not always *use* the
 
715
            # canonicalized tail portion - we may be attempting to rename the
 
716
            # case of the tail)
 
717
            canon_dest = tree.get_canonical_inventory_path(rel_names[1])
 
718
            dest_parent = osutils.dirname(canon_dest)
 
719
            spec_tail = osutils.basename(rel_names[1])
 
720
            # For a CICP file-system, we need to avoid creating 2 inventory
 
721
            # entries that differ only by case.  So regardless of the case
 
722
            # we *want* to use (ie, specified by the user or the file-system),
 
723
            # we must always choose to use the case of any existing inventory
 
724
            # items.  The only exception to this is when we are attempting a
 
725
            # case-only rename (ie, canonical versions of src and dest are
 
726
            # the same)
 
727
            dest_id = tree.path2id(canon_dest)
 
728
            if dest_id is None or tree.path2id(src) == dest_id:
 
729
                # No existing item we care about, so work out what case we
 
730
                # are actually going to use.
 
731
                if after:
 
732
                    # If 'after' is specified, the tail must refer to a file on disk.
 
733
                    if dest_parent:
 
734
                        dest_parent_fq = osutils.pathjoin(tree.basedir, dest_parent)
 
735
                    else:
 
736
                        # pathjoin with an empty tail adds a slash, which breaks
 
737
                        # relpath :(
 
738
                        dest_parent_fq = tree.basedir
 
739
    
 
740
                    dest_tail = osutils.canonical_relpath(
 
741
                                    dest_parent_fq,
 
742
                                    osutils.pathjoin(dest_parent_fq, spec_tail))
 
743
                else:
 
744
                    # not 'after', so case as specified is used
 
745
                    dest_tail = spec_tail
 
746
            else:
 
747
                # Use the existing item so 'mv' fails with AlreadyVersioned.
 
748
                dest_tail = os.path.basename(canon_dest)
 
749
            dest = osutils.pathjoin(dest_parent, dest_tail)
 
750
            mutter("attempting to move %s => %s", src, dest)
 
751
            tree.rename_one(src, dest, after=after)
 
752
            self.outf.write("%s => %s\n" % (src, dest))
694
753
 
695
754
 
696
755
class cmd_pull(Command):