22
33import os
44from collections import Counter , defaultdict
5- from concurrent .futures import ThreadPoolExecutor
65from contextlib import contextmanager
76from enum import IntEnum , auto , unique
87from functools import lru_cache
1615from codegen .sdk .codebase .config_parser import ConfigParser , get_config_parser_for_language
1716from codegen .sdk .codebase .diff_lite import ChangeType , DiffLite
1817from codegen .sdk .codebase .flagging .flags import Flags
18+ from codegen .sdk .codebase .io .file_io import FileIO
1919from codegen .sdk .codebase .transaction_manager import TransactionManager
2020from codegen .sdk .codebase .validation import get_edges , post_reset_validation
2121from codegen .sdk .core .autocommit import AutoCommit , commiter
2222from codegen .sdk .core .directory import Directory
2323from codegen .sdk .core .external .dependency_manager import DependencyManager , get_dependency_manager
2424from codegen .sdk .core .external .language_engine import LanguageEngine , get_language_engine
2525from codegen .sdk .enums import Edge , EdgeType , NodeType , ProgrammingLanguage
26- from codegen .sdk .extensions .io import write_changes
2726from codegen .sdk .extensions .sort import sort_editables
2827from codegen .sdk .extensions .utils import uncache_all
2928from codegen .sdk .typescript .external .ts_declassify .ts_declassify import TSDeclassify
3736 from git import Commit as GitCommit
3837
3938 from codegen .git .repo_operator .repo_operator import RepoOperator
39+ from codegen .sdk .codebase .io .io import IO
4040 from codegen .sdk .codebase .node_classes .node_classes import NodeClasses
4141 from codegen .sdk .core .dataclasses .usage import Usage
4242 from codegen .sdk .core .expressions import Expression
@@ -92,7 +92,6 @@ class CodebaseContext:
9292 pending_syncs : list [DiffLite ] # Diffs that have been applied to disk, but not the graph (to be used for sync graph)
9393 all_syncs : list [DiffLite ] # All diffs that have been applied to the graph (to be used for graph reset)
9494 _autocommit : AutoCommit
95- pending_files : set [SourceFile ]
9695 generation : int
9796 parser : Parser [Expression ]
9897 synced_commit : GitCommit | None
@@ -110,6 +109,7 @@ class CodebaseContext:
110109 session_options : SessionOptions = SessionOptions ()
111110 projects : list [ProjectConfig ]
112111 unapplied_diffs : list [DiffLite ]
112+ io : IO
113113
114114 def __init__ (
115115 self ,
@@ -134,6 +134,7 @@ def __init__(
134134
135135 # =====[ __init__ attributes ]=====
136136 self .projects = projects
137+ self .io = FileIO ()
137138 context = projects [0 ]
138139 self .node_classes = get_node_classes (context .programming_language )
139140 self .config = config
@@ -165,7 +166,6 @@ def __init__(
165166 self .pending_syncs = []
166167 self .all_syncs = []
167168 self .unapplied_diffs = []
168- self .pending_files = set ()
169169 self .flags = Flags ()
170170
171171 def __repr__ (self ):
@@ -259,7 +259,13 @@ def _reset_files(self, syncs: list[DiffLite]) -> None:
259259 files_to_remove .append (sync .path )
260260 modified_files .add (sync .path )
261261 logger .info (f"Writing { len (files_to_write )} files to disk and removing { len (files_to_remove )} files" )
262- write_changes (files_to_remove , files_to_write )
262+ for file in files_to_remove :
263+ self .io .delete_file (file )
264+ to_save = set ()
265+ for file , content in files_to_write :
266+ self .io .write_file (file , content )
267+ to_save .add (file )
268+ self .io .save_files (to_save )
263269
264270 @stopwatch
265271 def reset_codebase (self ) -> None :
@@ -270,7 +276,7 @@ def reset_codebase(self) -> None:
270276 def undo_applied_diffs (self ) -> None :
271277 self .transaction_manager .clear_transactions ()
272278 self .reset_codebase ()
273- self .check_changes ()
279+ self .io . check_changes ()
274280 self .pending_syncs .clear () # Discard pending changes
275281 if len (self .all_syncs ) > 0 :
276282 logger .info (f"Unapplying { len (self .all_syncs )} diffs to graph. Current graph commit: { self .synced_commit } " )
@@ -432,7 +438,7 @@ def _process_diff_files(self, files_to_sync: Mapping[SyncType, list[Path]], incr
432438
433439 # Step 5: Add new files as nodes to graph (does not yet add edges)
434440 for filepath in files_to_sync [SyncType .ADD ]:
435- content = filepath . read_text (errors = "ignore" )
441+ content = self . io . read_text (filepath )
436442 # TODO: this is wrong with context changes
437443 if filepath .suffix in self .extensions :
438444 file_cls = self .node_classes .file_cls
@@ -634,17 +640,6 @@ def remove_edge(self, u: NodeId, v: NodeId, *, edge_type: EdgeType | None = None
634640 continue
635641 self ._graph .remove_edge_from_index (edge )
636642
637- def check_changes (self ) -> None :
638- for file in self .pending_files :
639- file .check_changes ()
640- self .pending_files .clear ()
641-
642- def write_files (self , files : set [Path ] | None = None ) -> None :
643- to_write = set (filter (lambda f : f .filepath in files , self .pending_files )) if files is not None else self .pending_files
644- with ThreadPoolExecutor () as exec :
645- exec .map (lambda f : f .write_pending_content (), to_write )
646- self .pending_files .difference_update (to_write )
647-
648643 @lru_cache (maxsize = 10000 )
649644 def to_absolute (self , filepath : PathLike | str ) -> Path :
650645 path = Path (filepath )
@@ -684,7 +679,7 @@ def commit_transactions(self, sync_graph: bool = True, sync_file: bool = True, f
684679
685680 # Write files if requested
686681 if sync_file :
687- self .write_files (files )
682+ self .io . save_files (files )
688683
689684 # Sync the graph if requested
690685 if sync_graph and len (self .pending_syncs ) > 0 :
0 commit comments