59
59
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
62
def tree_files(file_list, default_branch=u'.'):
62
def tree_files(file_list, default_branch=u'.', canonicalize=True):
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]))
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.
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)
110
def safe_relpath_files(tree, file_list):
107
return tree, safe_relpath_files(tree, file_list, canonicalize)
110
def safe_relpath_files(tree, file_list, canonicalize=True):
111
111
"""Convert file_list into a list of relpaths in tree.
113
113
:param tree: A tree to operate on.
119
119
if file_list is None:
122
# tree.relpath exists as a "thunk" to osutils, but canonical_relpath
123
# doesn't - fix that up here before we enter the loop.
125
fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
122
128
for filename in file_list:
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)
172
178
files or directories is reported. If a directory is given, status
173
179
is reported for everything inside that directory.
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.
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.
179
190
# TODO: --no-recurse, --recurse options
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.',
185
196
Option('versioned', help='Only show versioned files.',
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
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)
220
231
class cmd_cat_revision(Command):
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()
661
672
self._run(tree, names_list, rel_names, after)
675
686
into_existing = False
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
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)
689
705
raise errors.BzrCommandError('to mv multiple files the'
690
706
' destination must be a versioned'
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]))
709
# for cicp file-systems: the src references an existing inventory
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
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
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.
732
# If 'after' is specified, the tail must refer to a file on disk.
734
dest_parent_fq = osutils.pathjoin(tree.basedir, dest_parent)
736
# pathjoin with an empty tail adds a slash, which breaks
738
dest_parent_fq = tree.basedir
740
dest_tail = osutils.canonical_relpath(
742
osutils.pathjoin(dest_parent_fq, spec_tail))
744
# not 'after', so case as specified is used
745
dest_tail = spec_tail
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))
696
755
class cmd_pull(Command):