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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
use std::process::Command;

use anyhow::{anyhow, Error, Result};
use regex::Regex;

use crate::{
    cli::{CheckoutToPrefix, DryRunAndCopyFlag, UseTemplate},
    git_config::GitConfig,
    run_mode::{get_run_mode_from_options, run_copy, RunMode},
    template::{interpolate, validate_interpolation_places_count},
};

pub fn checkout_to_branch_with_prefix(options: CheckoutToPrefix, config: GitConfig) -> Result<()> {
    let checkout_regex = Regex::new(r"^git checkout -b [a-zA-Z0-9_.-]+$").unwrap();
    let paste_command = &config.data.clipboard_commands.paste;

    let clipboard_value = Command::new(paste_command)
        .output()
        .expect("Couldn't run paste_command");

    let output_as_string = String::from_utf8(clipboard_value.stdout).unwrap();

    if !checkout_regex.is_match(&output_as_string) {
        return Err(anyhow!(
            "What you have in your clipboard is not a valid git checkout command \n
        valid one looks like this: \n
        git checkout -b name-of-your-branch
        "
        ));
    }
    let prefix_found = match config.data.branch_prefix_variants.get(&options.prefix_key) {
        None => {
            return Err(anyhow!(
                "There was no prefix for key {} \n You should add it prior to trying to use",
                options.prefix_key
            ))
        }
        Some(prefix) => prefix,
    };

    let split_on_space: Vec<String> = output_as_string.split(" ").map(|s| s.to_string()).collect();

    let after_prefix = &split_on_space[3..].join("");

    let full_branch_name = prefix_found.to_owned() + after_prefix;

    let run_mode = get_run_mode_from_options(DryRunAndCopyFlag {
        dry_run: options.dry_run,

        copy: options.copy,
    });

    return match run_mode {
        RunMode::Normal => {
            let result = Command::new("git")
                .arg("checkout")
                .arg("-b")
                .arg(full_branch_name)
                .output()
                .unwrap();

            println!("git output: \n {:?}", String::from_utf8(result.stdout));
            Ok(())
        }
        RunMode::DryRun => {
            println!(
                "Going to run: \n \
                    git checkout -b {}",
                full_branch_name
            );
            Ok(())
        }
        RunMode::Copy => run_copy(&config, format!("git checkout -b {}", full_branch_name)),
        RunMode::DryRunAndCopy => {
            let copy_command = config.data.clipboard_commands.copy;

            println!(
                "Going to run: \n \
        echo 'git checkout -b {}' > {}",
                full_branch_name, copy_command
            );
            Ok(())
        }
    };
}

pub fn checkout_to_branch_with_template(
    options: UseTemplate,
    config: GitConfig,
) -> Result<(), Error> {
    let selected_branch_format = options.key;

    let picked_branch_format = config
        .data
        .branch_template_variants
        .get(&selected_branch_format)
        .unwrap_or_else(|| {
            panic!(
                "No branch template under given key {} \n \
       You should add it prior to trying to use 
        ",
                selected_branch_format
            )
        });

    let is_valid =
        validate_interpolation_places_count(picked_branch_format, options.interpolate_values.len());

    if is_valid.is_err() {
        let err: Error = is_valid.err().unwrap();
        return Err(err);
    };

    let interpolate_values = options
        .interpolate_values
        .iter()
        .map(|val| val.replace(" ", "-"))
        .collect();

    // Had to figure out around closure that couldn't move value
    let interpolate_values_for_debugging = format!("{:?}", interpolate_values);
    let interpolated_branch =
        interpolate(picked_branch_format, interpolate_values).unwrap_or_else(|_err| {
            panic!(
                "Couldn't interpolate branch format \n \
                Trying to interpolate template: \n \
                {} \n \
                with: \n \
                {:?}
                ",
                picked_branch_format, interpolate_values_for_debugging
            )
        });

    let run_mode = get_run_mode_from_options(DryRunAndCopyFlag {
        dry_run: options.dry_run,
        copy: options.copy,
    });

    match run_mode {
        RunMode::Normal => {
            let output = Command::new("git")
                .arg("checkout")
                .arg("-b")
                .arg(interpolated_branch)
                .output()
                .unwrap()
                .stdout;

            println!("{}", String::from_utf8_lossy(&output));
            Ok(())
        }
        RunMode::DryRun => {
            let command_to_print = format!("git checkout -b {}", interpolated_branch);
            println!("Command to be executed: \n {}", command_to_print);
            Ok(())
        }
        RunMode::DryRunAndCopy => {
            let copy_command = config.data.clipboard_commands.copy;

            let command_to_print = format!(
                "echo 'git checkout -b {}' > {}",
                interpolated_branch, copy_command
            );
            let message_to_print =
                format!("command that's going to be run: \n {}", command_to_print);
            println!("{}", message_to_print);
            Ok(())
        }
        RunMode::Copy => {
            let value_to_copy = format!("git checkout -b {}", interpolated_branch);
            run_copy(&config, value_to_copy)
        }
    }
}