~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Martin Pool
  • Date: 2009-01-13 03:06:36 UTC
  • mfrom: (3932.2.3 1.11)
  • mto: This revision was merged to the branch mainline in revision 3937.
  • Revision ID: mbp@sourcefrog.net-20090113030636-dqx4t8yaaqgdvam5
MergeĀ 1.11rc1

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
655
661
 
656
662
        if len(names_list) < 2:
657
663
            raise errors.BzrCommandError("missing file argument")
658
 
        tree, rel_names = tree_files(names_list)
 
664
        tree, rel_names = tree_files(names_list, canonicalize=False)
659
665
        tree.lock_write()
660
666
        try:
661
667
            self._run(tree, names_list, rel_names, after)
675
681
                into_existing = False
676
682
            else:
677
683
                inv = tree.inventory
678
 
                from_id = tree.path2id(rel_names[0])
 
684
                # 'fix' the case of a potential 'from'
 
685
                from_id = tree.path2id(
 
686
                            tree.get_canonical_inventory_path(rel_names[0]))
679
687
                if (not osutils.lexists(names_list[0]) and
680
688
                    from_id and inv.get_file_kind(from_id) == "directory"):
681
689
                    into_existing = False
682
690
        # move/rename
683
691
        if into_existing:
684
692
            # move into existing directory
 
693
            # All entries reference existing inventory items, so fix them up
 
694
            # for cicp file-systems.
 
695
            rel_names = tree.get_canonical_inventory_paths(rel_names)
685
696
            for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
686
697
                self.outf.write("%s => %s\n" % pair)
687
698
        else:
689
700
                raise errors.BzrCommandError('to mv multiple files the'
690
701
                                             ' destination must be a versioned'
691
702
                                             ' 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]))
 
703
 
 
704
            # for cicp file-systems: the src references an existing inventory
 
705
            # item:
 
706
            src = tree.get_canonical_inventory_path(rel_names[0])
 
707
            # Find the canonical version of the destination:  In all cases, the
 
708
            # parent of the target must be in the inventory, so we fetch the
 
709
            # canonical version from there (we do not always *use* the
 
710
            # canonicalized tail portion - we may be attempting to rename the
 
711
            # case of the tail)
 
712
            canon_dest = tree.get_canonical_inventory_path(rel_names[1])
 
713
            dest_parent = osutils.dirname(canon_dest)
 
714
            spec_tail = osutils.basename(rel_names[1])
 
715
            # For a CICP file-system, we need to avoid creating 2 inventory
 
716
            # entries that differ only by case.  So regardless of the case
 
717
            # we *want* to use (ie, specified by the user or the file-system),
 
718
            # we must always choose to use the case of any existing inventory
 
719
            # items.  The only exception to this is when we are attempting a
 
720
            # case-only rename (ie, canonical versions of src and dest are
 
721
            # the same)
 
722
            dest_id = tree.path2id(canon_dest)
 
723
            if dest_id is None or tree.path2id(src) == dest_id:
 
724
                # No existing item we care about, so work out what case we
 
725
                # are actually going to use.
 
726
                if after:
 
727
                    # If 'after' is specified, the tail must refer to a file on disk.
 
728
                    if dest_parent:
 
729
                        dest_parent_fq = osutils.pathjoin(tree.basedir, dest_parent)
 
730
                    else:
 
731
                        # pathjoin with an empty tail adds a slash, which breaks
 
732
                        # relpath :(
 
733
                        dest_parent_fq = tree.basedir
 
734
    
 
735
                    dest_tail = osutils.canonical_relpath(
 
736
                                    dest_parent_fq,
 
737
                                    osutils.pathjoin(dest_parent_fq, spec_tail))
 
738
                else:
 
739
                    # not 'after', so case as specified is used
 
740
                    dest_tail = spec_tail
 
741
            else:
 
742
                # Use the existing item so 'mv' fails with AlreadyVersioned.
 
743
                dest_tail = os.path.basename(canon_dest)
 
744
            dest = osutils.pathjoin(dest_parent, dest_tail)
 
745
            mutter("attempting to move %s => %s", src, dest)
 
746
            tree.rename_one(src, dest, after=after)
 
747
            self.outf.write("%s => %s\n" % (src, dest))
694
748
 
695
749
 
696
750
class cmd_pull(Command):