From f9e7ef493a22d06e312954ee47a90ac8f1f2157c Mon Sep 17 00:00:00 2001 From: HouXiaoxuan Date: Thu, 21 Dec 2023 23:01:05 +0800 Subject: [PATCH] =?UTF-8?q?git=20log=E5=AE=9E=E7=8E=B0=E4=B8=8E=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/cli.rs | 12 ++++++ src/commands/log.rs | 97 +++++++++++++++++++++++++++++++++++++++++++++ src/commands/mod.rs | 1 + src/head.rs | 4 +- 4 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 src/commands/log.rs diff --git a/src/cli.rs b/src/cli.rs index 9e08840..67216cd 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -2,6 +2,7 @@ use clap::{Parser, Subcommand}; use mit::commands::add::add; use mit::commands::commit::commit; use mit::commands::init::init; +use mit::commands::log::log; use mit::commands::remove::remove; /// Rust实现的简易版本的Git,用于学习Rust语言 @@ -50,6 +51,14 @@ enum Command { #[clap(long, action)] allow_empty: bool, }, + /// log 现实提交历史 + Log { + #[clap(short = 'A', long)] + all: bool, + + #[clap(short, long)] + number: Option, + }, } pub fn handle_command() { let cli = Cli::parse(); @@ -66,5 +75,8 @@ pub fn handle_command() { Command::Commit { message, allow_empty } => { commit(message, allow_empty); } + Command::Log { all, number } => { + log(all, number); + } } } diff --git a/src/commands/log.rs b/src/commands/log.rs new file mode 100644 index 0000000..e0dcd35 --- /dev/null +++ b/src/commands/log.rs @@ -0,0 +1,97 @@ +use crate::{head, models::commit::Commit}; +use colored::Colorize; +use core::num; +use std::option; + +const DEFAULT_LOG_NUMBER: usize = 10; + +pub fn log(all: bool, number: Option) { + println!("log all: {:?}, number: {:?}", all, number); + let _ = __log(all, number); +} + +pub fn __log(all: bool, number: Option) -> usize { + let mut log_count = 0usize; + + let head = head::current_head(); + let mut branch_name: Option = None; + let mut head_commit = match head { + head::Head::Branch(_branch_name) => { + let commit = head::get_branch_head(&_branch_name); + branch_name = Some(_branch_name.clone()); + if commit.is_empty() { + println!("当前分支{:?}没有任何提交", _branch_name); + return 0; + } + commit + } + head::Head::Detached(commit_hash) => commit_hash, + }; + + let mut number = match number { + Some(number) => number, + None => DEFAULT_LOG_NUMBER, + }; + + let mut first = true; + loop { + log_count += 1; + let commit = Commit::load(&head_commit); + if first { + first = false; + print!( + "{}{}{}{}", + "commit ".yellow(), + commit.get_hash().yellow(), + "(".yellow(), + "HEAD".blue() + ); + if let Some(ref branch_name) = branch_name { + print!("{}", format!(" -> {}", branch_name).blue()); + } + println!("{}", ")".yellow()); + } else { + println!( + "{}{}{}{}{}", + "commit ".yellow(), + head_commit.yellow(), + "(".yellow(), + "HEAD".blue(), + ")".yellow() + ); + } + println!("Author: {}", commit.get_author()); + println!("Date: {}", commit.get_date()); + println!(); + println!(" {}", commit.get_message()); + println!(); + + if all == false { + if number > 1 { + number -= 1; + } else { + break; + } + } + if commit.get_parent_hash().len() == 0 { + break; + } + head_commit = commit.get_parent_hash().first().unwrap().clone(); + } + log_count +} + +#[cfg(test)] +mod test { + use super::super::super::commands; + use crate::utils::util; + #[test] + fn test_log() { + util::setup_test_with_clean_mit(); + assert_eq!(super::__log(false, None), 0); + commands::commit::commit("test commit 2".into(), true); + assert_eq!(super::__log(false, Some(1)), 1); + commands::commit::commit("test commit 3".into(), true); + assert_eq!(super::__log(false, None), 2); + } +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 6732aa1..fc651b0 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -3,3 +3,4 @@ pub mod commit; pub mod init; pub mod remove; pub mod status; +pub mod log; \ No newline at end of file diff --git a/src/head.rs b/src/head.rs index f0e54b1..a0c6506 100644 --- a/src/head.rs +++ b/src/head.rs @@ -19,7 +19,7 @@ pub fn current_head() -> Head { Head::Detached(head_content) } } -fn update_branch(branch_name: &String, commit_hash: &String) { +pub fn update_branch(branch_name: &String, commit_hash: &String) { // 更新分支head let mut branch = util::get_storage_path().unwrap(); branch.push("refs"); @@ -28,7 +28,7 @@ fn update_branch(branch_name: &String, commit_hash: &String) { std::fs::write(&branch, commit_hash).expect(&format!("无法写入branch in {:?} with {}", branch, commit_hash)); } -fn get_branch_head(branch_name: &String) -> String { +pub fn get_branch_head(branch_name: &String) -> String { // 返回当前分支的commit hash let mut branch = util::get_storage_path().unwrap(); branch.push("refs");