@@ -106,25 +106,58 @@ pub trait ApiHandler: Send + Sync {
106106 }
107107
108108 async fn get_latest_commit ( & self , path : PathBuf ) -> Result < LatestCommitInfo , GitError > {
109- let tree = if let Some ( tree) = self . search_tree_by_path ( & path) . await ? {
110- tree
111- } else {
109+ // 1) Try as directory path first
110+ if let Some ( tree) = self . search_tree_by_path ( & path) . await ? {
111+ let commit = self . get_tree_relate_commit ( tree. id , path) . await ?;
112+ let mut commit_info: LatestCommitInfo = commit. into ( ) ;
113+
114+ if let Some ( binding) = self . build_commit_binding_info ( & commit_info. oid ) . await ? {
115+ let display = binding. display_name . clone ( ) ;
116+ let avatar = binding. avatar_url . clone ( ) . unwrap_or_default ( ) ;
117+ commit_info. author . display_name = display;
118+ commit_info. author . avatar_url = avatar;
119+ }
120+
121+ return Ok ( commit_info) ;
122+ }
123+
124+ // 2) If not a directory, try as file path: lookup parent directory and map blob -> commit
125+ let file_name = path
126+ . file_name ( )
127+ . and_then ( |n| n. to_str ( ) )
128+ . ok_or_else ( || GitError :: CustomError ( "Invalid file path" . to_string ( ) ) ) ?;
129+ let parent = path
130+ . parent ( )
131+ . ok_or_else ( || GitError :: CustomError ( "Invalid file path" . to_string ( ) ) ) ?;
132+
133+ // parent must be a directory tree that exists
134+ if self . search_tree_by_path ( parent) . await ?. is_none ( ) {
112135 return Err ( GitError :: CustomError (
113136 "can't find target parent tree under latest commit" . to_string ( ) ,
114137 ) ) ;
115138 } ;
116- let commit = self . get_tree_relate_commit ( tree. id , path) . await ?;
117- let mut commit_info: LatestCommitInfo = commit. into ( ) ;
118139
140+ // Use directory item -> commit mapping to find the file's latest commit
141+ let map = self . item_to_commit_map ( parent. to_path_buf ( ) ) . await ?;
142+ // Find matching blob item in the directory
143+ let matched_commit = map. into_iter ( ) . find_map ( |( item, commit_opt) | {
144+ if item. mode == TreeItemMode :: Blob && item. name == file_name {
145+ commit_opt
146+ } else {
147+ None
148+ }
149+ } ) ;
150+
151+ let commit = matched_commit
152+ . ok_or_else ( || GitError :: CustomError ( "[code:404] File not found" . to_string ( ) ) ) ?;
153+
154+ let mut commit_info: LatestCommitInfo = commit. into ( ) ;
119155 if let Some ( binding) = self . build_commit_binding_info ( & commit_info. oid ) . await ? {
120156 let display = binding. display_name . clone ( ) ;
121157 let avatar = binding. avatar_url . clone ( ) . unwrap_or_default ( ) ;
122-
123- // Fill both author for UI consumption
124- commit_info. author . display_name = display. clone ( ) ;
125- commit_info. author . avatar_url = avatar. clone ( ) ;
158+ commit_info. author . display_name = display;
159+ commit_info. author . avatar_url = avatar;
126160 }
127-
128161 Ok ( commit_info)
129162 }
130163
0 commit comments