11use std:: collections:: { BTreeSet , HashMap } ;
22
3- use forge_domain:: { FileHash , FileNode , FileStatus , SyncProgress , SyncStatus } ;
3+ use forge_domain:: { FileHash , FileStatus , SyncProgress , SyncStatus } ;
44
55/// Result of comparing local and server files
66///
7- /// This struct stores local and remote file information and provides methods
7+ /// This struct stores remote file information and provides methods
88/// to compute synchronization operations on-demand. It can derive file statuses
99/// and identify which files need to be uploaded, deleted, or modified.
1010pub struct WorkspaceStatus {
11- /// Local files with their content and hashes
12- local_files : Vec < FileNode > ,
1311 /// Remote file hashes from the server
1412 remote_files : Vec < FileHash > ,
1513}
1614
1715impl WorkspaceStatus {
18- /// Creates a sync plan from local files and remote file hashes.
16+ /// Creates a sync plan from remote file hashes.
1917 ///
2018 /// # Arguments
2119 ///
22- /// * `local_files` - Vector of local files with their content and hashes
2320 /// * `remote_files` - Vector of remote file hashes from the server
24- pub fn new ( local_files : Vec < FileNode > , remote_files : Vec < FileHash > ) -> Self {
25- Self { local_files , remote_files }
21+ pub fn new ( remote_files : Vec < FileHash > ) -> Self {
22+ Self { remote_files }
2623 }
2724
2825 /// Derives file sync statuses by comparing local and remote files.
@@ -34,12 +31,11 @@ impl WorkspaceStatus {
3431 /// - `Modified`: File exists in both but with different hashes
3532 /// - `New`: File exists only locally
3633 /// - `Deleted`: File exists only remotely
37- pub fn file_statuses ( & self ) -> Vec < FileStatus > {
34+ pub fn file_statuses ( & self , local_files : Vec < FileHash > ) -> Vec < FileStatus > {
3835 // Build hash maps for efficient lookup
39- let local_hashes: HashMap < & str , & str > = self
40- . local_files
36+ let local_hashes: HashMap < & str , & str > = local_files
4137 . iter ( )
42- . map ( |f| ( f. file_path . as_str ( ) , f. hash . as_str ( ) ) )
38+ . map ( |f| ( f. path . as_str ( ) , f. hash . as_str ( ) ) )
4339 . collect ( ) ;
4440 let remote_hashes: HashMap < & str , & str > = self
4541 . remote_files
@@ -78,38 +74,16 @@ impl WorkspaceStatus {
7874 ///
7975 /// A tuple of (files_to_delete, files_to_upload) where:
8076 /// - `files_to_delete`: Vector of file paths to delete from remote
81- /// - `files_to_upload`: Vector of files to upload to remote
82- pub fn get_operations ( & self ) -> ( Vec < String > , Vec < forge_domain :: FileRead > ) {
83- let statuses = self . file_statuses ( ) ;
77+ /// - `files_to_upload`: Vector of file paths to upload to remote
78+ pub fn get_operations ( & self , local_files : Vec < FileHash > ) -> ( Vec < String > , Vec < String > ) {
79+ let statuses = self . file_statuses ( local_files ) ;
8480 let mut files_to_delete = Vec :: new ( ) ;
8581 let mut files_to_upload = Vec :: new ( ) ;
8682
87- // Create a map for quick lookup of local files
88- let local_files_map: HashMap < & str , & FileNode > = self
89- . local_files
90- . iter ( )
91- . map ( |f| ( f. file_path . as_str ( ) , f) )
92- . collect ( ) ;
93-
9483 for status in statuses {
9584 match status. status {
96- SyncStatus :: Modified => {
97- // Note: Modified files already exist in the database and will be
98- // automatically deleted by the backend.
99- if let Some ( file) = local_files_map. get ( status. path . as_str ( ) ) {
100- files_to_upload. push ( forge_domain:: FileRead :: new (
101- file. file_path . clone ( ) ,
102- file. content . clone ( ) ,
103- ) ) ;
104- }
105- }
106- SyncStatus :: New => {
107- if let Some ( file) = local_files_map. get ( status. path . as_str ( ) ) {
108- files_to_upload. push ( forge_domain:: FileRead :: new (
109- file. file_path . clone ( ) ,
110- file. content . clone ( ) ,
111- ) ) ;
112- }
85+ SyncStatus :: Modified | SyncStatus :: New => {
86+ files_to_upload. push ( status. path ) ;
11387 }
11488 SyncStatus :: Deleted => {
11589 files_to_delete. push ( status. path ) ;
@@ -123,7 +97,6 @@ impl WorkspaceStatus {
12397 ( files_to_delete, files_to_upload)
12498 }
12599}
126-
127100/// Tracks progress of sync operations
128101pub struct SyncProgressCounter {
129102 total_files : usize ,
@@ -162,30 +135,18 @@ mod tests {
162135 #[ test]
163136 fn test_file_statuses ( ) {
164137 let local = vec ! [
165- FileNode {
166- file_path: "a.rs" . into( ) ,
167- content: "content_a" . into( ) ,
168- hash: "hash_a" . into( ) ,
169- } ,
170- FileNode {
171- file_path: "b.rs" . into( ) ,
172- content: "modified_content" . into( ) ,
173- hash: "new_hash" . into( ) ,
174- } ,
175- FileNode {
176- file_path: "d.rs" . into( ) ,
177- content: "content_d" . into( ) ,
178- hash: "hash_d" . into( ) ,
179- } ,
138+ FileHash { path: "a.rs" . into( ) , hash: "hash_a" . into( ) } ,
139+ FileHash { path: "b.rs" . into( ) , hash: "new_hash" . into( ) } ,
140+ FileHash { path: "d.rs" . into( ) , hash: "hash_d" . into( ) } ,
180141 ] ;
181142 let remote = vec ! [
182143 FileHash { path: "a.rs" . into( ) , hash: "hash_a" . into( ) } ,
183144 FileHash { path: "b.rs" . into( ) , hash: "old_hash" . into( ) } ,
184145 FileHash { path: "c.rs" . into( ) , hash: "hash_c" . into( ) } ,
185146 ] ;
186147
187- let plan = WorkspaceStatus :: new ( local , remote) ;
188- let actual = plan. file_statuses ( ) ;
148+ let plan = WorkspaceStatus :: new ( remote) ;
149+ let actual = plan. file_statuses ( local ) ;
189150
190151 let expected = vec ! [
191152 forge_domain:: FileStatus :: new( "a.rs" . to_string( ) , forge_domain:: SyncStatus :: InSync ) ,
0 commit comments