Skip to content

Commit d26b97f

Browse files
committed
refactor: refactor commit-info API and GitHub history inconsistency
Signed-off-by: allure <[email protected]>
1 parent e2a9f1e commit d26b97f

File tree

6 files changed

+305
-502
lines changed

6 files changed

+305
-502
lines changed

ceres/src/api_service/commit_ops.rs

Lines changed: 47 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,59 @@ use std::{path::PathBuf, sync::Arc};
22

33
use git_internal::{
44
errors::GitError,
5-
hash::SHA1,
6-
internal::object::{
7-
commit::Commit,
8-
tree::{TreeItem, TreeItemMode},
9-
},
5+
internal::object::tree::{TreeItem, TreeItemMode},
106
};
117
use tokio::sync::Mutex;
128

139
use crate::api_service::{ApiHandler, cache::GitObjectCache, history, tree_ops};
1410
use crate::model::git::{CommitBindingInfo, LatestCommitInfo};
1511

12+
/// Get the latest commit that modified a file or directory.
13+
///
14+
/// This unified function handles both tag-based and commit-based browsing through
15+
/// the `refs` parameter, ensuring consistent behavior across all code paths.
16+
///
17+
/// # Arguments
18+
/// - `handler`: API handler for accessing Git data
19+
/// - `path`: File or directory path to check
20+
/// - `refs`: Optional reference (tag name or commit SHA). If None, uses default HEAD/root.
21+
///
22+
/// # Returns
23+
/// The commit information for the last modification of the specified path.
1624
pub async fn get_latest_commit<T: ApiHandler + ?Sized>(
1725
handler: &T,
1826
path: PathBuf,
27+
refs: Option<&str>,
1928
) -> Result<LatestCommitInfo, GitError> {
29+
// Resolve the starting commit from refs
30+
let start_commit = crate::api_service::resolve_start_commit(handler, refs).await?;
31+
2032
// 1) Try as directory path first
21-
if let Some(tree) = tree_ops::search_tree_by_path(handler, &path, None).await? {
22-
let commit = get_tree_relate_commit(handler, tree.id, path).await?;
33+
if let Some(tree) = tree_ops::search_tree_by_path(handler, &path, refs).await? {
34+
// Treat directory as a TreeItem and find its last modification
35+
let dir_name = path
36+
.file_name()
37+
.and_then(|n| n.to_str())
38+
.ok_or_else(|| GitError::CustomError("Invalid directory path".to_string()))?
39+
.to_string();
40+
41+
let parent = path
42+
.parent()
43+
.ok_or_else(|| GitError::CustomError("Directory has no parent".to_string()))?;
44+
45+
let dir_item = TreeItem::new(TreeItemMode::Tree, tree.id, dir_name);
46+
47+
let cache = Arc::new(Mutex::new(GitObjectCache::default()));
48+
49+
let commit = history::traverse_commit_history_for_last_modification(
50+
handler,
51+
parent,
52+
start_commit.clone(),
53+
&dir_item,
54+
cache,
55+
)
56+
.await?;
57+
2358
let mut commit_info: LatestCommitInfo = commit.clone().into();
2459

2560
// If commit has a username binding, prefer showing that username
@@ -38,25 +73,11 @@ pub async fn get_latest_commit<T: ApiHandler + ?Sized>(
3873
}
3974

4075
// 2) If not a directory, try as file path
41-
// basic validation for file path
42-
path.file_name()
43-
.and_then(|n| n.to_str())
44-
.ok_or_else(|| GitError::CustomError("Invalid file path".to_string()))?;
45-
let parent = path
46-
.parent()
47-
.ok_or_else(|| GitError::CustomError("Invalid file path".to_string()))?;
76+
// Use unified last-modification logic
77+
let cache = Arc::new(Mutex::new(GitObjectCache::default()));
4878

49-
// parent must be a directory tree that exists
50-
if tree_ops::search_tree_by_path(handler, parent, None)
51-
.await?
52-
.is_none()
53-
{
54-
return Err(GitError::CustomError(
55-
"can't find target parent tree under latest commit".to_string(),
56-
));
57-
};
58-
match history::resolve_latest_commit_for_file_path(handler, &path).await? {
59-
Some(commit) => {
79+
match history::resolve_last_modification_by_path(handler, &path, start_commit, cache).await {
80+
Ok(commit) => {
6081
let mut commit_info: LatestCommitInfo = commit.clone().into();
6182
// If commit has a username binding, prefer showing that username
6283
if let Ok(Some(binding)) = handler
@@ -71,35 +92,12 @@ pub async fn get_latest_commit<T: ApiHandler + ?Sized>(
7192
}
7293
Ok(commit_info)
7394
}
74-
None => Err(GitError::CustomError(
95+
Err(_) => Err(GitError::CustomError(
7596
"[code:404] File not found".to_string(),
7697
)),
7798
}
7899
}
79100

80-
pub async fn get_tree_relate_commit<T: ApiHandler + ?Sized>(
81-
handler: &T,
82-
t_hash: SHA1,
83-
path: PathBuf,
84-
) -> Result<Commit, GitError> {
85-
let file_name = match path.file_name() {
86-
Some(name) => name.to_string_lossy().to_string(),
87-
None => {
88-
return Err(GitError::CustomError("Invalid Path Input".to_string()));
89-
}
90-
};
91-
92-
let search_item = TreeItem::new(TreeItemMode::Tree, t_hash, file_name);
93-
let cache = Arc::new(Mutex::new(GitObjectCache::default()));
94-
let root_commit = Arc::new(handler.get_root_commit().await);
95-
96-
let parent = match path.parent() {
97-
Some(p) => p,
98-
None => return Err(GitError::CustomError("Invalid Path Input".to_string())),
99-
};
100-
history::traverse_commit_history(handler, parent, root_commit, &search_item, cache).await
101-
}
102-
103101
/// Build commit binding information for a given commit SHA
104102
pub async fn build_commit_binding_info<T: ApiHandler + ?Sized>(
105103
handler: &T,

0 commit comments

Comments
 (0)