530
530
return os.path.getsize(self.id2abspath(file_id))
533
def get_file_sha1(self, file_id):
534
path = self._inventory.id2path(file_id)
533
def get_file_sha1(self, file_id, path=None):
535
path = self._inventory.id2path(file_id)
535
536
return self._hashcache.get_sha1(path)
537
def is_executable(self, file_id):
538
if not supports_executable():
538
if not supports_executable():
539
def is_executable(self, file_id, path=None):
539
540
return self._inventory[file_id].executable
541
path = self._inventory.id2path(file_id)
542
def is_executable(self, file_id, path=None):
544
path = self._inventory.id2path(file_id)
542
545
mode = os.lstat(self.abspath(path)).st_mode
543
546
return bool(stat.S_ISREG(mode) and stat.S_IEXEC&mode)
692
695
def list_files(self):
693
"""Recursively list all files as (path, class, kind, id).
696
"""Recursively list all files as (path, class, kind, id, entry).
695
698
Lists, but does not descend into unversioned directories.
700
703
Skips the control directory.
702
705
inv = self._inventory
704
def descend(from_dir_relpath, from_dir_id, dp):
706
# Convert these into local objects to save lookup times
707
pathjoin = bzrlib.osutils.pathjoin
708
file_kind = bzrlib.osutils.file_kind
710
# transport.base ends in a slash, we want the piece
711
# between the last two slashes
712
transport_base_dir = self.bzrdir.transport.base.rsplit('/', 2)[1]
714
fk_entries = {'directory':TreeDirectory, 'file':TreeFile, 'symlink':TreeLink}
716
# directory file_id, relative path, absolute path, reverse sorted children
717
children = os.listdir(self.basedir)
719
# jam 20060527 The kernel sized tree seems equivalent whether we
720
# use a deque and popleft to keep them sorted, or if we use a plain
721
# list and just reverse() them.
722
children = collections.deque(children)
723
stack = [(inv.root.file_id, u'', self.basedir, children)]
725
from_dir_id, from_dir_relpath, from_dir_abspath, children = stack[-1]
728
f = children.popleft()
708
729
## TODO: If we find a subdirectory with its own .bzr
709
730
## directory, then that is a separate tree and we
710
731
## should exclude it.
712
733
# the bzrdir for this tree
713
if self.bzrdir.transport.base.endswith(f + '/'):
734
if transport_base_dir == f:
717
fp = appendpath(from_dir_relpath, f)
737
# we know that from_dir_relpath and from_dir_abspath never end in a slash
738
# and 'f' doesn't begin with one, we can do a string op, rather
739
# than the checks of pathjoin(), all relative paths will have an extra slash
741
fp = from_dir_relpath + '/' + f
720
fap = appendpath(dp, f)
744
fap = from_dir_abspath + '/' + f
722
746
f_ie = inv.get_child(from_dir_id, f)
725
elif self.is_ignored(fp):
749
elif self.is_ignored(fp[1:]):
738
762
# make a last minute entry
764
yield fp[1:], c, fk, f_ie.file_id, f_ie
742
if fk == 'directory':
743
entry = TreeDirectory()
746
elif fk == 'symlink':
767
yield fp[1:], c, fk, None, fk_entries[fk]()
769
yield fp[1:], c, fk, None, TreeEntry()
751
yield fp, c, fk, (f_ie and f_ie.file_id), entry
753
772
if fk != 'directory':
757
# don't descend unversioned directories
760
for ff in descend(fp, f_ie.file_id, fap):
775
# But do this child first
776
new_children = os.listdir(fap)
778
new_children = collections.deque(new_children)
779
stack.append((f_ie.file_id, fp, fap, new_children))
780
# Break out of inner loop, so that we start outer loop with child
783
# if we finished all children, pop it off the stack
763
for f in descend(u'', inv.root.file_id, self.basedir):
766
787
@needs_write_lock
767
788
def move(self, from_paths, to_name):
804
825
raise BzrError("%r is not versioned" % f)
805
826
name_tail = splitpath(f)[-1]
806
dest_path = appendpath(to_name, name_tail)
827
dest_path = pathjoin(to_name, name_tail)
807
828
if self.has_filename(dest_path):
808
829
raise BzrError("destination %r already exists" % dest_path)
809
830
if f_id in to_idpath:
817
838
for f in from_paths:
818
839
name_tail = splitpath(f)[-1]
819
dest_path = appendpath(to_name, name_tail)
840
dest_path = pathjoin(to_name, name_tail)
820
841
result.append((f, dest_path))
821
842
inv.rename(inv.path2id(f), to_dir_id, name_tail)