예제 #1
0
    def getmtime(self, cpath: CPath):
        inside_cpath = self.__cdir_tree.get(cpath)
        if inside_cpath is None:
            raise CFSException(
                f'File System Error (occurred during getmtime on cpath: {cpath}):\n'
                f'X Path does not exist')

        if inside_cpath.is_dir() or cpath.is_dir():
            raise CFSException(
                f'File System Error (occurred during getmtime on cpath: {cpath}):\n'
                f'X gmtime on dir')

        return inside_cpath.mtime
예제 #2
0
    def __list(self, parent: CDirTree, do_hash=False):
        assert isinstance(parent, CDirTree)
        path_names: List[str] = self.__fs.listdir(parent)
        parent_names: Tuple[str, ...] = parent.names

        # transform path into cpath, but don't do hash because: the file might already be ignored by a fs matcher
        #   config file. hash in listing block
        child_cpaths = []
        for path_name in path_names:
            names = (*parent_names, path_name)
            child_cpath = CPath(names)
            if self.__fs.is_file(child_cpath):
                mtime = self.__fs.getmtime(child_cpath)
                size = self.__fs.getsize(child_cpath)
                child_cpath = CFile(names, mtime, size)
            else:
                child_cpath = CDir(names)
            child_cpaths.append(child_cpath)

        # matcher file finding block
        # search for fs matcher config files
        for child_cpath in child_cpaths:
            if self.__fs.is_real_fs() and child_cpath.is_file():
                if FsMatcherMapper.exists(child_cpath.name):
                    matcher_cfile = child_cpath
                    # check includer or excluder
                    # TODO: read content of fs matcher files (e.g. gitignore) and then match further relative to that.
                    # make a fs matcher and attache it to the parent.
                    content = ""
                    with self.__fs.open(matcher_cfile, "r", encoding="utf-8") as f:
                        content = f.read()
                    fs_matcher: AbcFsMatcher
                    fs_matcher = FsMatcherMapper.get(matcher_cfile.name)(content)
                    # group will decide where to place includer and where excluder.
                    # root group will forward to appropriate matcher group
                    self.__fs_matcher_root_group.add(fs_matcher, parent)

        # now list & hash if not ignored
        for child_cpath in child_cpaths:
            if not self.__fs_matcher_root_group.should_include(child_cpath):
                continue

            if child_cpath.is_file() and do_hash:
                hash_value = self.__fs.gethash(child_cpath)
                child_cpath = CFileHashed(child_cpath.names, child_cpath.mtime, child_cpath.size, hash_value)

            if child_cpath.is_dir():
                last_subtree = parent.add(child_cpath)
                self.__list(last_subtree, do_hash=do_hash)
            else:
                parent.add(child_cpath)
예제 #3
0
    def getsize(self, cpath: CPath):
        inside_cpath = self.__cdir_tree.get(cpath)

        if inside_cpath is None:
            raise CFSException(
                f'File System Error (occurred during gethash on cpath: {cpath}):\n'
                f'X Path not found')

        if cpath.is_dir() or inside_cpath.is_dir():
            raise CFSException(
                f'File System Error (occurred during getsize on cpath: {cpath}):\n'
            )

        return inside_cpath.size
예제 #4
0
    def is_ancestor(candidate_ancestor: CPath,
                    candidate_descendant: CPath) -> bool:
        if not candidate_ancestor.is_dir():
            raise CFSException(
                f"Candidate ancestor/parent must pass is_dir: {candidate_ancestor}"
            )  # TODO: create more specific exception
        if candidate_ancestor.names_count >= candidate_descendant.names_count:
            return False

        ancestor_names = candidate_ancestor.names
        descendant_names = candidate_descendant.names
        for idx, ancestor_name in enumerate(ancestor_names):
            descendant_name = descendant_names[idx]
            if ancestor_name != descendant_name:
                return False
        return True
예제 #5
0
    def add(self, cpath: CPath) -> 'CDirTree':
        """
        Add any level of descendents
        :returns: last sub tree
        """
        assert isinstance(cpath, CPath)
        assert not isinstance(cpath, CDirTree)
        assert cpath.is_rel, "Cannot add absolute path to a tree"
        if cpath.is_dir():
            cdir: CDir = cpath
            assert not cdir.is_root(
            ), f"Programmer's Error - cannot add root dir to a tree or sub tree: {cdir.to_dict()}"
        assert cpath.names_count > self.names_count
        if not self.is_root():
            assert cpath.names[:self.
                               names_count] == self.names, f"cpath.names {cpath.names} cpath.names[:self.names_count] {cpath.names[:self.names_count]}, self.names {self.names}"
        # assert cpath.name not in self._child_map, "Cannot add a child twice" TODO: think later whether this old check will be added in the new add check

        comp_left_names = tuple(cpath.names[:self.names_count])
        comp_right_names = tuple(cpath.names[self.names_count:])
        assert comp_left_names == self.names, f"Root didn't match: {comp_left_names} <-> {self.names}"
        self_own_names = comp_left_names

        target_tree = self  # target tree is the tree where the cpath will be added as child
        _inc_right_names = [
        ]  # adding right names one by one for testing existence and adding to the tree.
        for dir_comp_name in comp_right_names[:-1]:
            _inc_right_names.append(dir_comp_name)
            new_target = target_tree._get_child_tree(dir_comp_name)

            if new_target is None:
                new_target = target_tree._add_child(
                    CDir([*self_own_names, *_inc_right_names]))
            target_tree = new_target  # After the first time of writing this line I indented this one level forward and
            # there was bugs of duplicate dir in visit, I remember when I indented this one. First time ok,
            # second time wrong, now okay
        last_tree = target_tree._add_child(cpath)

        return last_tree
예제 #6
0
 def test_is_dir__empty_path_string__is_dir(self):
     cpath = CPath("")
     self.assertTrue(cpath.is_dir())
     self.assertEqual(tuple([]), cpath.names)