1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use crate::{repo, Config, Exec, Location};
use git2::Repository;
use std::io;
use structopt::StructOpt;

#[derive(StructOpt, Debug)]
#[structopt(aliases = &["mv", "move"], about = "Relocate repository")]
pub struct Opt {
    #[structopt(short, long, help = "Use regular expressions")]
    pub regex: bool,
    #[structopt(short, long, help = "Show detailed output")]
    pub verbose: bool,
    #[structopt(help = Location::about())]
    pub target: Location,
    #[structopt(help = Location::about())]
    pub destination: Location,
}

impl Exec for Opt {
    fn exec(self, config: Config) -> i32 {
        let mut errors = 0;
        let Self {
            regex,
            verbose,
            mut target,
            destination,
        } = self;

        match repo::unique(&config.src, target.clone(), regex) {
            Ok(path) => {
                let dest_path = config.src.join(destination.id());
                let rename_res = repo::rename(&path, &dest_path);
                if rename_res
                    .as_ref()
                    .err()
                    .map(|err| {
                        err.kind() == io::ErrorKind::AlreadyExists
                            && match regex {
                                true => target.matches_re(&path),
                                false => target.matches(&path),
                            }
                    })
                    .unwrap_or(true)
                {
                    if let Err(err) = Repository::open(&dest_path).map(|repo| {
                        repo.remote_set_url("origin", &destination.url())
                            .and_then(|_| Ok(info!("origin: {}", &destination.url())))
                    }) {
                        errors += 1;
                        info!("could not set remote: {}", err);
                    }
                    if rename_res.is_ok() && verbose {
                        info!(
                            "renamed '{}' to '{}'",
                            path.strip_prefix(config.src).unwrap().display(),
                            destination.id()
                        );
                    }
                } else {
                    errors += 1;
                    info!("rename failed: {}", rename_res.err().unwrap())
                }
            }
            Err(err) => {
                errors += 1;
                info!("{}", err)
            }
        }

        errors
    }
}