1use std::{env, ffi};
2
3use crate::{
4 error::{Error, Result},
5 git,
6};
7
8#[derive(Clone, Copy)]
9enum RemovalPolicy {
10 None,
12 Local,
14 Remote,
16}
17
18async fn archive_imp(branch: &ffi::OsStr, policy: RemovalPolicy) -> Result<()> {
22 let old = [ffi::OsStr::new("refs"), ffi::OsStr::new("heads"), branch]
23 .iter()
24 .collect::<std::path::PathBuf>();
25 let new = [ffi::OsStr::new("refs"), ffi::OsStr::new("archive"), branch]
26 .iter()
27 .collect::<std::path::PathBuf>();
28
29 println!("mk {}", new.display());
30 git::git([
31 ffi::OsStr::new("update-ref"),
32 new.as_os_str(),
33 old.as_os_str(),
34 ])
35 .await?;
36
37 if let RemovalPolicy::None = policy {
38 return Ok(());
39 }
40
41 if let RemovalPolicy::Remote = policy
45 && let Some(upstream) = git::upstream(branch).await
46 {
47 let (remote, name) = upstream.split_once('/').unwrap();
48 println!("rm {upstream}");
49 git::git(["push", remote, &format!(":{name}")]).await?;
50 }
51
52 println!("rm {}", branch.display());
55 git::git([ffi::OsStr::new("branch"), ffi::OsStr::new("-D"), branch]).await?;
56 Ok(())
57}
58
59pub async fn archive(args: env::ArgsOs) -> Result<()> {
65 let mut policy = RemovalPolicy::None;
66
67 let args = args
68 .filter(|arg| match arg.to_str() {
69 Some("-d") => {
70 policy = RemovalPolicy::Local;
71 false
72 }
73 Some("-D") => {
74 policy = RemovalPolicy::Remote;
75 false
76 }
77 _ => true,
78 })
79 .collect::<Vec<_>>();
80
81 if args.is_empty() {
82 return Err(Error::BranchName);
83 }
84
85 for arg in args {
86 archive_imp(&arg, policy).await?;
87 }
88
89 Ok(())
90}