diff --git a/src/cli.rs b/src/cli.rs index b8b19ad..f7c6f92 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,6 +1,7 @@ use clap::{ArgGroup, Parser, Subcommand}; use mit::commands::{ - add::add, branch::branch, commit::commit, init::init, log::log, remove::remove, status::status, switch::switch, + add::add, branch::branch, commit::commit, init::init, log::log, remove::remove, restore::restore, status::status, + switch::switch, }; /// Rust实现的简易版本的Git,用于学习Rust语言 @@ -90,19 +91,31 @@ enum Command { branch: Option, /// 创建并切换到新分支 - #[clap(long, short)] + #[clap(long, short, group = "sub")] create: Option, + + /// 是否允许切换到commit + #[clap(long, short, action, default_value = "false", group = "sub")] + detach: bool, }, /// restore Restore { // TODO 行为不确定 /// 要恢复的文件 #[clap(required = true)] - files: Vec, + path: Vec, /// source #[clap(long, short)] source: Option, + + /// worktree + #[clap(long, short, action)] + worktree: bool, + + /// staged + #[clap(long, short, action)] + staged: bool, }, } pub fn handle_command() { @@ -130,11 +143,19 @@ pub fn handle_command() { branch(new_branch, commit_hash, list, delete, show_current); } - Command::Switch { branch, create } => { - switch(branch, create); + Command::Switch { branch, create, detach } => { + switch(branch, create, detach); } - Command::Restore { files, source } => { - println!("files: {:?}, source: {:?}", files, source); + Command::Restore { path, mut source, mut worktree, staged } => { + // 未指定stage和worktree时,默认操作stage + if !staged { + worktree = true; + } + // 未指定source时,默认操作HEAD + if source.is_none() { + source = Some("HEAD".to_string()); + } + restore(path, source, worktree, staged); } } } diff --git a/src/commands/restore.rs b/src/commands/restore.rs index 8b13789..1594af7 100644 --- a/src/commands/restore.rs +++ b/src/commands/restore.rs @@ -1 +1,49 @@ +use std::path::PathBuf; +use crate::{ + head, + models::{commit::Commit, object::Hash}, + store::Store, +}; + +/** 根据filte restore workdir */ +pub fn restore_workdir_into_files(filter: Option, target_blobs: Vec<(PathBuf, Hash)>) { + // TODO + unimplemented!("TODO"); +} +/** 根据filte restore staged */ +pub fn restore_staged_into_files(filter: Option, target_blobs: Vec<(PathBuf, Hash)>) { + // TODO + unimplemented!("TODO"); +} + +pub fn restore(path: Vec, source: String, worktree: bool, staged: bool) { + // TODO + let target_commit = { + if source == "HEAD" { + head::current_head_commit() + } else if head::list_local_branches().contains(&source) { + head::get_branch_head(&source) + } else { + let store = Store::new(); + let commit = store.search(&source); + if commit.is_none() { + println!("fatal: 非法的 commit: '{}'", source); + return; + } + commit.unwrap() + } + }; + // TODO 处理筛选path的互相包含的情况 + + // 分别处理worktree和staged + let tree = Commit::load(&target_commit).get_tree(); + let target_blobs = tree.get_recursive_blobs(); + if worktree { + unimplemented!("TODO") + } + if staged { + unimplemented!("TODO") + } + unimplemented!("TODO"); +}