Files
MIT/src/commands/status.rs
mrbeanc a459a0922e fix:去除current_head()返回值中的\n
\n会导致文件写入失败
2023-12-21 14:25:40 +08:00

136 lines
4.3 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 std::path::PathBuf;
use crate::{
head,
models::{blob, index},
utils::util,
};
/** 获取需要commit的更改(staged) */
#[derive(Debug)]
pub struct Changes {
pub new: Vec<String>,
pub modified: Vec<String>,
pub deleted: Vec<String>,
}
fn __file_string(path: &PathBuf) -> String {
util::to_root_relative_path(&path) //todo: to_string_lossy()
.as_os_str()
.to_str()
.unwrap()
.to_string()
}
pub fn changes_to_be_committed() -> Changes {
let mut change = Changes { //todo: Changes::default()
new: vec![],
modified: vec![],
deleted: vec![],
};
let index = index::Index::new();
let head_hash = head::current_head_commit();
if head_hash == "".to_string() { //todo: head_hash.is_empty() or head_hash == ""
// 初始提交
change.new = index
.get_tracked_files()
.iter()
.map(|f| __file_string(f))
.collect();
return change;
}
let commit = crate::models::commit::Commit::load(&head_hash);
let tree = commit.get_tree();
let tree_files = tree.get_recursive_blobs();
let index_files: Vec<PathBuf> = index
.get_tracked_files()
.iter()
.map(|f| util::to_root_relative_path(f))
.collect();
for tree_item in tree_files.iter() {
let index_file = index_files.iter().find(|f| **f == tree_item.0);
if index_file.is_none() {
change.deleted.push(__file_string(&tree_item.0)); //todo: abs_path?
} else {
let index_blob = blob::Blob::new( //todo: index有函数可以获取blob_hash 不需要new
util::get_working_dir() //todo: 优化:提取为变量
.unwrap()
.join(index_file.unwrap())
.as_path(),
);
// XXX @mrbeanc 我看到Blob的new被改成调用save了。这里的实现希望比较Blob内容不然就得读取文件内容。
if index_blob.get_hash() != tree_item.1.get_hash() {
change.modified.push(__file_string(&tree_item.0));
}
}
}
for index_file in index_files.iter() {
let tree_item = tree_files.iter().find(|f| f.0 == **index_file);
if tree_item.is_none() {
change.new.push(__file_string(&index_file));
}
}
change
}
/** 分为两个部分
1. unstaged: 暂存区与工作区比较
2. staged to be committed: 暂存区与HEAD(最后一次Commit::Tree)比较,即上次的暂存区
*/
pub fn status() {
unimplemented!()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{commands::commit, utils::util};
use std::{fs, path::Path};
#[test]
fn test_changes_to_be_committed() {
util::setup_test_with_clean_mit();
let test_file = "a.txt";
util::ensure_test_file(Path::new(test_file), None);
commit::commit("test commit".to_string(), true);
let mut index = index::Index::new();
index.add( //todo 可以直接调用add函数
PathBuf::from(test_file),
index::FileMetaData::new(&blob::Blob::new(Path::new(test_file)), Path::new(test_file)),
);
index.save();
let change = changes_to_be_committed();
assert_eq!(change.new.len(), 1);
assert_eq!(change.modified.len(), 0);
assert_eq!(change.deleted.len(), 0);
commit::commit("test commit".to_string(), true);
util::ensure_test_file(Path::new(test_file), Some("new content"));
index.add(
PathBuf::from(test_file),
index::FileMetaData::new(&blob::Blob::new(Path::new(test_file)), Path::new(test_file)),
);
index.save();
let change = changes_to_be_committed();
assert_eq!(change.new.len(), 0);
assert_eq!(change.modified.len(), 1);
assert_eq!(change.deleted.len(), 0);
commit::commit("test commit".to_string(), true);
index.remove(
util::get_working_dir()
.unwrap()
.join(Path::new(test_file))
.as_path(),
);
index.save();
let change = changes_to_be_committed();
assert_eq!(change.new.len(), 0);
assert_eq!(change.modified.len(), 0);
assert_eq!(change.deleted.len(), 1);
}
}