Skip to content

Commit

Permalink
feat(branch): support switch to remote branch (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
fioncat authored Aug 8, 2023
1 parent f3d6744 commit 649bf8b
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/cmd/run/branch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ pub struct BranchArgs {
/// Push change (create or delete) to remote
#[clap(long, short)]
pub push: bool,

/// Search and switch to remote branch
#[clap(long, short)]
pub remote: bool,
}

enum SyncBranchTask<'a> {
Expand All @@ -44,6 +48,9 @@ impl Run for BranchArgs {
shell::ensure_no_uncommitted()?;
self.fetch()?;
}
if self.remote {
return self.search_and_switch_remote();
}
let branches = GitBranch::list().context("List branch")?;
if self.sync {
return self.sync(&branches);
Expand Down Expand Up @@ -231,4 +238,18 @@ impl BranchArgs {
None => bail!("Could not find current branch"),
}
}

fn search_and_switch_remote(&self) -> Result<()> {
self.fetch()?;
let branches = GitBranch::list_remote("origin")?;
if branches.is_empty() {
println!("No remote branch to switch");
return Ok(());
}

let idx = shell::search(&branches)?;
let target = branches[idx].as_str();

Shell::git(&["checkout", target]).execute()?.check()
}
}
52 changes: 52 additions & 0 deletions src/shell.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::collections::HashSet;
use std::io::{ErrorKind, Read, Write};
use std::mem;
use std::path::PathBuf;
Expand Down Expand Up @@ -296,6 +297,57 @@ impl GitBranch {
Ok(branches)
}

pub fn list_remote(remote: &str) -> Result<Vec<String>> {
let lines = Shell::git(&["branch", "-al"])
.with_desc("List remote git branch")
.execute()?
.checked_lines()?;
let remote_prefix = format!("{remote}/");
let mut items = Vec::with_capacity(lines.len());
for line in lines {
let line = line.trim();
if line.is_empty() {
continue;
}
if !line.starts_with("remotes/") {
continue;
}
let item = line.strip_prefix("remotes/").unwrap();
if !item.starts_with(&remote_prefix) {
continue;
}
let item = item.strip_prefix(&remote_prefix).unwrap().trim();
if item.is_empty() {
continue;
}
if item.starts_with("HEAD ->") {
continue;
}
items.push(item.to_string());
}

let lines = Shell::git(&["branch"])
.with_desc("List local git branch")
.execute()?
.checked_lines()?;
let mut local_branch_map = HashSet::with_capacity(lines.len());
for line in lines {
let mut line = line.trim();
if line.is_empty() {
continue;
}
if line.starts_with("*") {
line = line.strip_prefix("*").unwrap().trim();
}
local_branch_map.insert(line.to_string());
}

Ok(items
.into_iter()
.filter(|item| !local_branch_map.contains(item))
.collect())
}

pub fn default() -> Result<String> {
Self::default_by_remote("origin")
}
Expand Down

0 comments on commit 649bf8b

Please sign in to comment.