Files
MIT/src/head.rs
2023-12-21 02:14:59 +08:00

173 lines
5.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use crate::utils::util;
pub enum Head {
Detached(String),
Branch(String),
}
pub fn current_head() -> Head {
let mut head = util::get_storage_path().unwrap();
head.push("HEAD");
let head_content = std::fs::read_to_string(head).expect("HEAD文件损坏");
if head_content.starts_with("ref: refs/heads/") {
let branch_name = head_content.trim_start_matches("ref: refs/heads/");
Head::Branch(branch_name.to_string())
} else {
Head::Detached(head_content)
}
}
fn update_branch_head(branch_name: &String, commit_hash: &String) {
// 更新分支head
let mut branch = util::get_storage_path().unwrap();
branch.push("refs");
branch.push("heads");
branch.push(branch_name);
std::fs::write(branch, commit_hash).expect("无法写入branch");
}
fn get_branch_head(branch_name: &String) -> String {
// 返回当前分支的commit hash
let mut branch = util::get_storage_path().unwrap();
branch.push("refs");
branch.push("heads");
branch.push(branch_name);
if branch.exists() {
let commit_hash = std::fs::read_to_string(branch).expect("无法读取branch");
commit_hash
} else {
"".to_string() // 分支不存在或者没有commit
}
}
/**返回当前head指向的commit hash如果是分支则返回分支的commit hash*/
pub fn current_head_commit() -> String {
let head = current_head();
match head {
Head::Branch(branch_name) => {
let commit_hash = get_branch_head(&branch_name);
commit_hash
}
Head::Detached(commit_hash) => commit_hash,
}
}
/** 将当前的head指向commit_hash根据当前的head类型更新不同的文件 */
pub fn update_head_commit(commit_hash: &String) {
let head = current_head();
match head {
Head::Branch(branch_name) => {
update_branch_head(&branch_name, commit_hash);
}
Head::Detached(_) => {
let mut head = util::get_storage_path().unwrap();
head.push("HEAD");
std::fs::write(head, commit_hash).expect("无法写入HEAD");
}
}
}
/** 列出本地的branch */
pub fn list_local_branches() -> Vec<String> {
let mut branches = Vec::new();
let mut branch_dir = util::get_storage_path().unwrap();
branch_dir.push("refs");
branch_dir.push("heads");
if branch_dir.exists() {
let entries = std::fs::read_dir(branch_dir).expect("无法读取branch");
for entry in entries {
let entry = entry.unwrap();
let branch_name = entry.file_name().into_string().unwrap();
branches.push(branch_name);
}
}
branches
}
/** 切换head到branch */
pub fn change_head_to_branch(branch_name: &String) {
let mut head = util::get_storage_path().unwrap();
head.push("HEAD");
let branch_head = get_branch_head(branch_name);
std::fs::write(head, format!("ref: refs/heads/{}", branch_name)).expect("无法写入HEAD");
update_head_commit(&branch_head);
}
/** 切换head到非branchcommit */
pub fn change_head_to_commit(commit_hash: &String) {
let mut head = util::get_storage_path().unwrap();
head.push("HEAD");
std::fs::write(head, commit_hash).expect("无法写入HEAD");
}
#[cfg(test)]
mod test {
use crate::{head::update_branch_head, utils::util};
#[test]
fn test_edit_branch() {
util::setup_test_with_mit();
let branch_name = "test_branch".to_string() + &rand::random::<u32>().to_string();
let branch_head = super::get_branch_head(&branch_name);
assert!(branch_head.is_empty());
let commit_hash = "1234567890".to_string();
super::update_branch_head(&branch_name, &commit_hash);
let branch_head = super::get_branch_head(&branch_name);
assert!(!branch_head.is_empty());
assert!(branch_head == commit_hash);
}
#[test]
fn test_list_local_branches() {
util::setup_test_with_mit();
let branch_one = "test_branch".to_string() + &rand::random::<u32>().to_string();
let branch_two = "test_branch".to_string() + &rand::random::<u32>().to_string();
update_branch_head(&branch_one, &"1234567890".to_string());
update_branch_head(&branch_two, &"1234567890".to_string());
let branches = super::list_local_branches();
assert!(branches.contains(&branch_one));
assert!(branches.contains(&branch_two));
}
#[test]
fn test_change_head_to_branch() {
util::setup_test_with_mit();
let branch_name = "test_branch".to_string() + &rand::random::<u32>().to_string();
update_branch_head(&branch_name, &"1234567890".to_string());
super::change_head_to_branch(&branch_name);
assert!(
match super::current_head() {
super::Head::Branch(head_commit) => head_commit == branch_name,
_ => false,
},
"当前不在分支上"
);
}
#[test]
fn test_change_head_to_commit() {
util::setup_test_with_mit();
let commit_hash = "1234567890".to_string();
super::change_head_to_commit(&commit_hash);
assert!(
match super::current_head() {
super::Head::Detached(head_commit) => head_commit == commit_hash,
_ => false,
},
"当前不在分支上"
);
}
#[test]
fn test_update_branch_head() {
util::setup_test_with_mit();
let branch_name = "test_branch".to_string() + &rand::random::<u32>().to_string();
let commit_hash = "1234567890".to_string();
super::update_branch_head(&branch_name, &commit_hash);
let branch_head = super::get_branch_head(&branch_name);
assert!(!branch_head.is_empty());
assert!(branch_head == commit_hash);
}
}