1use git2 as git;
2
3#[derive(clap::Args, Clone)]
8pub struct TreeArgs {
9 #[arg(default_value = "HEAD")]
11 pub treeish: String,
12
13 #[arg(long = "only", required = true)]
15 pub patterns: Vec<String>,
16
17 #[arg(long)]
19 pub allow_dirty: bool,
20}
21
22pub fn tree(args: &TreeArgs) -> Result<(), Box<dyn std::error::Error>> {
23 let repo = git::Repository::open_from_env()?;
24
25 if !args.allow_dirty {
26 let statuses = repo.statuses(Some(
27 git::StatusOptions::new()
28 .include_untracked(false)
29 .include_ignored(false),
30 ))?;
31 if !statuses.is_empty() {
32 return Err(
33 "working tree has uncommitted changes; use --allow-dirty to override".into(),
34 );
35 }
36 }
37
38 let tree_oid = git_filter_tree::exe::filter_tree(&repo, &args.treeish, &args.patterns)?;
39 let filtered = repo.find_tree(tree_oid)?;
40
41 let mut index = repo.index()?;
42 index.read_tree(&filtered)?;
43 index.write()?;
44
45 let pattern_list: String = args
46 .patterns
47 .iter()
48 .map(|p| format!("'{}'", p))
49 .collect::<Vec<_>>()
50 .join(", ");
51
52 println!(
53 "Rewrote {} keeping only {} and updated the index ({} entries).",
54 args.treeish,
55 pattern_list,
56 filtered.len(),
57 );
58
59 Ok(())
60}