Skip to main content

git_spawn/command/
mv.rs

1//! `git mv` — move or rename a file, directory, or symlink.
2
3use crate::command::{CommandExecutor, CommandOutput, GitCommand};
4use crate::error::{Error, Result};
5use async_trait::async_trait;
6
7/// Builder for `git mv`.
8#[derive(Debug, Clone, Default)]
9pub struct MvCommand {
10    /// Shared executor.
11    pub executor: CommandExecutor,
12    /// Source path.
13    pub source: Option<String>,
14    /// Destination path.
15    pub destination: Option<String>,
16    /// `--force` / `-f`.
17    pub force: bool,
18    /// `-k` skip missing.
19    pub skip_missing: bool,
20    /// `--dry-run`.
21    pub dry_run: bool,
22    /// `--verbose`.
23    pub verbose: bool,
24}
25
26impl MvCommand {
27    /// Move `src` to `dst`.
28    pub fn new(src: impl Into<String>, dst: impl Into<String>) -> Self {
29        Self {
30            source: Some(src.into()),
31            destination: Some(dst.into()),
32            ..Self::default()
33        }
34    }
35    /// `--force`.
36    pub fn force(&mut self) -> &mut Self {
37        self.force = true;
38        self
39    }
40    /// `-k`.
41    pub fn skip_missing(&mut self) -> &mut Self {
42        self.skip_missing = true;
43        self
44    }
45    /// `--dry-run`.
46    pub fn dry_run(&mut self) -> &mut Self {
47        self.dry_run = true;
48        self
49    }
50    /// `--verbose`.
51    pub fn verbose(&mut self) -> &mut Self {
52        self.verbose = true;
53        self
54    }
55}
56
57#[async_trait]
58impl GitCommand for MvCommand {
59    type Output = CommandOutput;
60    fn get_executor(&self) -> &CommandExecutor {
61        &self.executor
62    }
63    fn get_executor_mut(&mut self) -> &mut CommandExecutor {
64        &mut self.executor
65    }
66    fn build_command_args(&self) -> Vec<String> {
67        let mut args = vec!["mv".to_string()];
68        if self.force {
69            args.push("--force".into());
70        }
71        if self.skip_missing {
72            args.push("-k".into());
73        }
74        if self.dry_run {
75            args.push("--dry-run".into());
76        }
77        if self.verbose {
78            args.push("--verbose".into());
79        }
80        if let Some(s) = &self.source {
81            args.push(s.clone());
82        }
83        if let Some(d) = &self.destination {
84            args.push(d.clone());
85        }
86        args
87    }
88    async fn execute(&self) -> Result<CommandOutput> {
89        if self.source.is_none() || self.destination.is_none() {
90            return Err(Error::invalid_config("mv requires source and destination"));
91        }
92        self.execute_raw().await
93    }
94}