1
1
"""File operations for manipulating the codebase."""
2
2
3
- import os
4
3
from typing import Any , Literal
5
4
6
5
from codegen import Codebase
@@ -36,17 +35,31 @@ def view_file(codebase: Codebase, filepath: str) -> dict[str, Any]:
36
35
def list_directory (codebase : Codebase , dirpath : str = "./" , depth : int = 1 ) -> dict [str , Any ]:
37
36
"""List contents of a directory.
38
37
39
- TODO(CG-10729): add support for directories that only including non-SourceFiles (code files). At the moment,
40
- only files and directories that have SourceFile objects are included.
41
-
42
38
Args:
43
39
codebase: The codebase to operate on
44
40
dirpath: Path to directory relative to workspace root
45
41
depth: How deep to traverse the directory tree. Default is 1 (immediate children only).
46
42
Use -1 for unlimited depth.
47
43
44
+ TODO(CG-10729): add support for directories that only including non-SourceFiles (code files). At the moment,
45
+ only files and directories that have SourceFile objects are included.
46
+
48
47
Returns:
49
- Dict containing directory contents and metadata, or error information if directory not found
48
+ Dict containing directory contents and metadata in a nested structure:
49
+ {
50
+ "path": str,
51
+ "name": str,
52
+ "files": list[str],
53
+ "subdirectories": [
54
+ {
55
+ "path": str,
56
+ "name": str,
57
+ "files": list[str],
58
+ "subdirectories": [...],
59
+ },
60
+ ...
61
+ ]
62
+ }
50
63
"""
51
64
try :
52
65
directory = codebase .get_directory (dirpath )
@@ -56,33 +69,33 @@ def list_directory(codebase: Codebase, dirpath: str = "./", depth: int = 1) -> d
56
69
if not directory :
57
70
return {"error" : f"Directory not found: { dirpath } " }
58
71
59
- # Get immediate files
60
- files = []
61
- subdirs = []
62
-
63
- for item in directory .items .values ():
64
- if isinstance (item , Directory ):
65
- subdirs .append (item .name )
66
- else :
67
- # Get full filename with extension from filepath
68
- files .append (os .path .basename (item .filepath ))
69
-
70
- # If depth > 1 or unlimited (-1), recursively get subdirectories
71
- if depth != 1 :
72
- new_depth = depth - 1 if depth > 1 else - 1
73
- for item in directory .items .values ():
74
- if isinstance (item , Directory ):
75
- subdir_result = list_directory (codebase , os .path .join (dirpath , item .name ), depth = new_depth )
76
- if "error" not in subdir_result :
77
- files .extend (subdir_result ["files" ])
78
- subdirs .extend (subdir_result ["subdirectories" ])
72
+ def get_directory_info (dir_obj : Directory , current_depth : int ) -> dict [str , Any ]:
73
+ """Helper function to get directory info recursively."""
74
+ # Get direct files
75
+ all_files = []
76
+ for file in dir_obj .files :
77
+ if file .directory == dir_obj :
78
+ all_files .append (file .filepath .split ("/" )[- 1 ])
79
+
80
+ # Get direct subdirectories
81
+ subdirs = []
82
+ for subdir in dir_obj .subdirectories :
83
+ # Only include direct descendants
84
+ if subdir .parent == dir_obj :
85
+ if current_depth != 1 :
86
+ new_depth = current_depth - 1 if current_depth > 1 else - 1
87
+ subdirs .append (get_directory_info (subdir , new_depth ))
88
+ else :
89
+ # At max depth, just include name
90
+ subdirs .append (subdir .name )
91
+ return {
92
+ "name" : dir_obj .name ,
93
+ "path" : dir_obj .dirpath ,
94
+ "files" : all_files ,
95
+ "subdirectories" : subdirs ,
96
+ }
79
97
80
- return {
81
- "path" : str (directory .path ), # Convert PosixPath to string
82
- "name" : directory .name ,
83
- "files" : files ,
84
- "subdirectories" : subdirs ,
85
- }
98
+ return get_directory_info (directory , depth )
86
99
87
100
88
101
def edit_file (codebase : Codebase , filepath : str , content : str ) -> dict [str , Any ]:
0 commit comments