1use cmd_lib::run_cmd;
2use std::path::{Path, PathBuf};
3
4pub fn repo(path: impl Into<String>) -> Downloader {
8 Downloader::new(path)
9}
10
11struct CopyRequest {
12 from: PathBuf,
13 to: PathBuf,
14}
15pub struct Downloader {
16 repo_path: String,
17 branch_name: String,
18 out_dir: PathBuf,
19 copy_requests: Vec<CopyRequest>,
20}
21impl Downloader {
22 fn new(repo: impl Into<String>) -> Self {
23 let cur_dir = std::env::current_dir().unwrap();
24 Self {
25 repo_path: repo.into(),
26 branch_name: "master".to_owned(),
27 out_dir: cur_dir,
28 copy_requests: vec![],
29 }
30 }
31 pub fn out_dir(mut self, path: impl AsRef<Path>) -> Self {
33 self.out_dir = path.as_ref().to_owned();
34 self
35 }
36 pub fn branch_name(mut self, name: impl Into<String>) -> Self {
38 self.branch_name = name.into();
39 self
40 }
41 pub fn add_file(mut self, src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Self {
45 let from = src.as_ref().to_owned();
46 let to = dst.as_ref().to_owned();
47 let req = CopyRequest { from, to };
48 self.copy_requests.push(req);
49 self
50 }
51 pub fn exec(self) -> anyhow::Result<()> {
53 let old_pwd = std::env::current_dir()?;
54
55 let dir = tempfile::tempdir()?;
56 let dir_path = dir.path();
57 std::env::set_current_dir(dir_path)?;
58
59 let repo = &self.repo_path;
60 run_cmd! {
61 git init .;
62 git config core.sparsecheckout true;
63 git remote add origin $repo;
64 }?;
65
66 for req in &self.copy_requests {
67 let from = &req.from;
68 run_cmd! {
69 echo $from >> .git/info/sparse-checkout;
70 }?;
71 }
72
73 let branch_name = &self.branch_name;
74 run_cmd! {
75 git pull origin $branch_name;
76 }?;
77
78 for req in &self.copy_requests {
79 let from = &req.from;
80 let to = &req.to;
81 let to = self.out_dir.join(to);
82 let to_dir = to.parent().unwrap();
83 if !to_dir.exists() {
84 std::fs::create_dir_all(to_dir)?;
85 }
86 run_cmd! {
87 mv $from $to;
88 }?;
89 }
90
91 std::env::set_current_dir(old_pwd)?;
92 Ok(())
93 }
94}