git_switch_branch/
lib.rs

1use std::{
2    env,
3    io::{stdout, Write},
4};
5
6pub use commands::*;
7use menu::{run_menu, Menu};
8use repo::{checkout, current_branch, get_branches, root_repo_path, Branch};
9
10mod commands;
11mod config;
12mod menu;
13mod repo;
14mod util;
15
16pub fn help(version: &str) {
17    println!("git-switch-branch v{}", version);
18    println!("Usage: git-switch-branch [options]");
19    println!("  help           Show this help message");
20    println!("  version        Show the version number");
21    println!("");
22    println!("  r, remote      Show only remote branches");
23    println!("  a, all         Show all branches (local and remote)");
24    println!("");
25    println!("  alias add      Add a git alias for this command");
26    println!("  alias remove   Remove the git alias (if set)");
27    println!("  alias          Show the current alias");
28}
29
30pub fn list_alias() {
31    let alias = config::get_current_alias().unwrap_or_else(|_| fatal!("Could not read alias file"));
32
33    match alias {
34        Some(alias) => println!("{}", alias),
35        None => println!("No alias set"),
36    }
37}
38
39pub fn add_alias() {
40    let alias = config::get_current_alias().unwrap_or_else(|_| fatal!("Could not read alias file"));
41
42    if alias.is_some() {
43        println!("Current alias: {}", alias.as_ref().unwrap());
44    }
45
46    let mut input = String::new();
47
48    let new_alias = loop {
49        print!("Enter new alias: ");
50        stdout().flush().unwrap();
51
52        let stdin = std::io::stdin();
53        stdin.read_line(&mut input).unwrap();
54        let alias = input.trim();
55
56        if alias.is_empty() {
57            println!("Alias cannot be empty");
58            input.clear();
59            continue;
60        }
61
62        break alias;
63    };
64
65    config::update_alias(new_alias, alias.as_deref())
66        .unwrap_or_else(|_| fatal!("Could not update alias"));
67
68    println!("Alias updated");
69}
70
71pub fn remove_alias() {
72    let alias = config::get_current_alias().unwrap_or_else(|_| fatal!("Could not read alias file"));
73    if alias.is_none() {
74        println!("No alias set");
75        return;
76    }
77
78    config::remove_alias(alias.as_deref()).unwrap_or_else(|_| fatal!("Could not remove alias"));
79    println!("Alias removed");
80}
81
82pub fn switch_branch(local: bool, remote: bool) {
83    let repo_path = env::current_dir()
84        .map(|mut path| root_repo_path(&mut path))
85        .expect("Can't access current directory")
86        .unwrap_or_else(|| fatal!("Could not find git repository"));
87
88    let branches = get_branches(&repo_path, local, remote)
89        .unwrap_or_else(|_| fatal!("Could not read branches"));
90
91    let current_branch = current_branch(&repo_path)
92        .map(|res| branches.iter().position(|branch| branch.to_string() == res))
93        .unwrap_or_default();
94
95    if branches.len() == 0 {
96        println!("No branches found");
97        return;
98    }
99
100    let menu = Menu {
101        items: &branches,
102        current: current_branch,
103        ..Default::default()
104    };
105
106    let selected = run_menu(&menu).map(|i| &branches[i]).unwrap_or_else(|err| {
107        fatal!("Could not run menu: {}", err);
108    });
109
110    let branch = match &selected {
111        Branch::Remote(_, branch) => {
112            let opts = vec![
113                format!("Create local branch '{}'", branch),
114                "Checkout remote branch (detached HEAD)".to_owned(),
115            ];
116            let menu = Menu {
117                items: &opts,
118                ..Default::default()
119            };
120
121            let opt = run_menu(&menu).unwrap_or_else(|err| fatal!("Could not run menu: {}", err));
122
123            match opt {
124                0 => branch,
125                _ => &selected.to_string(),
126            }
127        }
128        Branch::Local(branch) => branch,
129    };
130
131    checkout(branch).unwrap_or_else(|_| fatal!("Could not checkout branch"));
132}