File size: 3,979 Bytes
2f99641
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ea8e878
2f99641
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25d2e66
2f99641
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25d2e66
2f99641
 
25d2e66
2f99641
25d2e66
ea8e878
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import os
import shutil
import re
import difflib
from pathlib import Path
from typing import List, Dict, Union
import fnmatch

class FilesystemAccess:
    def __init__(self, root_path: str):
        self.root = Path(root_path).resolve()
        if not self.root.is_dir():
            raise ValueError("Root path must be an existing directory.")

    def _resolve_path(self, path: str) -> Path:
        full_path = (self.root / path).resolve()
        if not str(full_path).startswith(str(self.root)):
            raise PermissionError("Access outside root path is not allowed.")
        return full_path


    def read_file(self, path: str) -> str:
        full_path = self._resolve_path(path)
        try:
            with open(full_path, 'r', encoding='utf-8') as f:
                return f.read()
        except Exception as e:
            return "Could not read file"

    def read_multiple_files(self, paths: List[str]) -> Dict[str, Union[str, Exception]]:
        results = {}
        for path in paths:
            results[path] = self.read_file(path)
        return results

    def write_file(self, path: str, content: str):
        full_path = self._resolve_path(path)
        full_path.parent.mkdir(parents=True, exist_ok=True)
        with open(full_path, 'w', encoding='utf-8') as f:
            f.write(content)

    def create_directory(self, path: str):
        full_path = self._resolve_path(path)
        full_path.mkdir(parents=True, exist_ok=True)

    def list_directory(self, path: str) -> List[str]:
        full_path = self._resolve_path(path)
        if not full_path.is_dir():
            raise NotADirectoryError("Path is not a directory.")
        return  [("[D] " if p.is_dir() else "[F] ") + p.name for p in full_path.iterdir()]

    def move_file(self, source: str, destination: str):
        src_path = self._resolve_path(source)
        dst_path = self._resolve_path(destination)
        dst_path.parent.mkdir(parents=True, exist_ok=True)

        if dst_path.exists():
            raise FileExistsError("Destination already exists.")
        shutil.move(str(src_path), str(dst_path))

    def search_files(self, path: str, pattern: str, excludePatterns: List[str]) -> List[str]:
        start_path = self._resolve_path(path)
        matches = []

        for root, dirs, files in os.walk(start_path):
            for name in dirs + files:
                full_path = Path(root) / name
                rel_path = full_path.relative_to(self.root)
                str_path = str(rel_path)

                if fnmatch.fnmatchcase(name.lower(), pattern.lower()):
                    if not any(fnmatch.fnmatchcase(str_path, excl) for excl in excludePatterns):
                        matches.append(str(rel_path))

        return matches

    def directory_tree(self, path: str) -> str:
        full_path = self._resolve_path(path)
        return "\n".join(self._directory_subtree(full_path))

    def _directory_subtree(self, path: Path) -> List[str]:
        tree = []
        for item in path.iterdir():
            if item.is_dir():
                tree.append(f"[D] {item.name}")
                subtree = self._directory_subtree(item.resolve())
                for line in subtree:
                    tree.append("   " + line)
            else:
                tree.append(f"[F] {item.name}")
        return tree

    def recursive_list(self, path: str) -> str:
        full_path = self._resolve_path(path)
        return "\n".join(self._recursive_list(full_path))
    
    def _recursive_list(self, path: Path) -> List[str]:
        recursive_list = []
        for item in path.iterdir():
            if item.is_dir():
                recursive_list.append(f"{item.name}/")
                sublist = self._recursive_list(item.resolve())
                for line in sublist:
                    recursive_list.append(f"{item.name}/" + line)
            else:
                recursive_list.append(f"{item.name}")
        return recursive_list