~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Aaron Bentley
  • Date: 2006-06-03 16:23:09 UTC
  • mfrom: (1736 +trunk)
  • mto: This revision was merged to the branch mainline in revision 1738.
  • Revision ID: aaron.bentley@utoronto.ca-20060603162309-c975ca9ea9fea344
Merge from bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
# memory.  (Now done? -- mbp 20060309)
41
41
 
42
42
from binascii import hexlify
 
43
import collections
43
44
from copy import deepcopy
44
45
from cStringIO import StringIO
45
46
import errno
73
74
from bzrlib.merge import merge_inner, transform_tree
74
75
from bzrlib.osutils import (
75
76
                            abspath,
76
 
                            appendpath,
77
77
                            compact_date,
78
78
                            file_kind,
79
79
                            isdir,
283
283
        hc = self._hashcache = HashCache(basedir, cache_filename, self._control_files._file_mode)
284
284
        hc.read()
285
285
        # is this scan needed ? it makes things kinda slow.
286
 
        hc.scan()
 
286
        #hc.scan()
287
287
 
288
288
        if hc.needs_write:
289
289
            mutter("write hc")
530
530
        return os.path.getsize(self.id2abspath(file_id))
531
531
 
532
532
    @needs_read_lock
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):
 
534
        if not path:
 
535
            path = self._inventory.id2path(file_id)
535
536
        return self._hashcache.get_sha1(path)
536
537
 
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
540
 
        else:
541
 
            path = self._inventory.id2path(file_id)
 
541
    else:
 
542
        def is_executable(self, file_id, path=None):
 
543
            if not path:
 
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)
544
547
 
690
693
            return '?'
691
694
 
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).
694
697
 
695
698
        Lists, but does not descend into unversioned directories.
696
699
 
700
703
        Skips the control directory.
701
704
        """
702
705
        inv = self._inventory
703
 
 
704
 
        def descend(from_dir_relpath, from_dir_id, dp):
705
 
            ls = os.listdir(dp)
706
 
            ls.sort()
707
 
            for f in ls:
 
706
        # Convert these into local objects to save lookup times
 
707
        pathjoin = bzrlib.osutils.pathjoin
 
708
        file_kind = bzrlib.osutils.file_kind
 
709
 
 
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]
 
713
 
 
714
        fk_entries = {'directory':TreeDirectory, 'file':TreeFile, 'symlink':TreeLink}
 
715
 
 
716
        # directory file_id, relative path, absolute path, reverse sorted children
 
717
        children = os.listdir(self.basedir)
 
718
        children.sort()
 
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)]
 
724
        while stack:
 
725
            from_dir_id, from_dir_relpath, from_dir_abspath, children = stack[-1]
 
726
 
 
727
            while children:
 
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.
711
732
 
712
733
                # the bzrdir for this tree
713
 
                if self.bzrdir.transport.base.endswith(f + '/'):
 
734
                if transport_base_dir == f:
714
735
                    continue
715
736
 
716
 
                # path within tree
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
 
740
                # at the beginning
 
741
                fp = from_dir_relpath + '/' + f
718
742
 
719
743
                # absolute path
720
 
                fap = appendpath(dp, f)
 
744
                fap = from_dir_abspath + '/' + f
721
745
                
722
746
                f_ie = inv.get_child(from_dir_id, f)
723
747
                if f_ie:
724
748
                    c = 'V'
725
 
                elif self.is_ignored(fp):
 
749
                elif self.is_ignored(fp[1:]):
726
750
                    c = 'I'
727
751
                else:
728
752
                    c = '?'
737
761
 
738
762
                # make a last minute entry
739
763
                if f_ie:
740
 
                    entry = f_ie
 
764
                    yield fp[1:], c, fk, f_ie.file_id, f_ie
741
765
                else:
742
 
                    if fk == 'directory':
743
 
                        entry = TreeDirectory()
744
 
                    elif fk == 'file':
745
 
                        entry = TreeFile()
746
 
                    elif fk == 'symlink':
747
 
                        entry = TreeLink()
748
 
                    else:
749
 
                        entry = TreeEntry()
 
766
                    try:
 
767
                        yield fp[1:], c, fk, None, fk_entries[fk]()
 
768
                    except KeyError:
 
769
                        yield fp[1:], c, fk, None, TreeEntry()
 
770
                    continue
750
771
                
751
 
                yield fp, c, fk, (f_ie and f_ie.file_id), entry
752
 
 
753
772
                if fk != 'directory':
754
773
                    continue
755
774
 
756
 
                if c != 'V':
757
 
                    # don't descend unversioned directories
758
 
                    continue
759
 
                
760
 
                for ff in descend(fp, f_ie.file_id, fap):
761
 
                    yield ff
 
775
                # But do this child first
 
776
                new_children = os.listdir(fap)
 
777
                new_children.sort()
 
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
 
781
                break
 
782
            else:
 
783
                # if we finished all children, pop it off the stack
 
784
                stack.pop()
762
785
 
763
 
        for f in descend(u'', inv.root.file_id, self.basedir):
764
 
            yield f
765
786
 
766
787
    @needs_write_lock
767
788
    def move(self, from_paths, to_name):
803
824
            if f_id == None:
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:
816
837
        try:
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)
822
843
                try:
912
933
 
913
934
    def _iter_conflicts(self):
914
935
        conflicted = set()
915
 
        for path in (s[0] for s in self.list_files()):
 
936
        for info in self.list_files():
 
937
            path = info[0]
916
938
            stem = get_conflicted_stem(path)
917
939
            if stem is None:
918
940
                continue
978
1000
            
979
1001
            fl.sort()
980
1002
            for subf in fl:
981
 
                subp = appendpath(path, subf)
 
1003
                subp = pathjoin(path, subf)
982
1004
                yield subp
983
1005
 
984
1006
    def _translate_ignore_rule(self, rule):