Skip to content

Commit

Permalink
Add no-detach option
Browse files Browse the repository at this point in the history
  • Loading branch information
foriequal0 committed Feb 12, 2020
1 parent f6bb54b commit 6e5e036
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 3 deletions.
3 changes: 3 additions & 0 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ pub struct Args {
#[structopt(long)]
pub no_confirm: bool,

#[structopt(long)]
pub no_detach: bool,

/// Comma separated values of [all, merged, gone, local, remote, merged-local, merged-remote, gone-local, gone-remote].
/// 'all' is equivalent to 'merged-local,merged-remote,gone-local,gone-remote'.
/// 'merged' is equivalent to 'merged-local,merged-remote'.
Expand Down
53 changes: 51 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,34 @@ pub struct MergedOrGone {
pub merged_locals: HashSet<String>,
pub gone_locals: HashSet<String>,

pub kept_back_locals: HashSet<String>,

/// remote refs
pub merged_remotes: HashSet<String>,
pub gone_remotes: HashSet<String>,
}

impl MergedOrGone {
pub fn adjust_not_to_detach(&mut self, repo: &Repository) -> Result<()> {
if repo.head_detached()? {
return Ok(());
}
let head = repo.head()?;
let head_name = head.name().ok_or("non-utf8 head ref name")?;
assert!(head_name.starts_with("refs/heads/"));
let head_name = &head_name["refs/heads/".len()..];

if self.merged_locals.contains(head_name) {
self.merged_locals.remove(head_name);
self.kept_back_locals.insert(head_name.to_string());
}
if self.gone_locals.contains(head_name) {
self.gone_locals.remove(head_name);
self.kept_back_locals.insert(head_name.to_string());
}
Ok(())
}

pub fn print_summary(&self, filter: &DeleteFilter) {
fn print(branches: &HashSet<String>, filter: &DeleteFilter, category: Category) {
if filter.contains(&category) && !branches.is_empty() {
Expand All @@ -78,6 +100,14 @@ impl MergedOrGone {
}
print(&self.merged_locals, filter, Category::MergedLocal);
print(&self.merged_remotes, filter, Category::MergedRemote);

if !self.kept_back_locals.is_empty() {
println!("Kept back not to become detached HEAD:");
for branch in &self.kept_back_locals {
println!(" {}", branch);
}
}

print(&self.gone_locals, filter, Category::GoneLocal);
print(&self.gone_remotes, filter, Category::GoneRemote);
}
Expand Down Expand Up @@ -370,17 +400,36 @@ fn resolve_config_base_ref(repo: &Repository, base: &str) -> Result<String> {
.to_string())
}

pub fn delete_local_branches(branches: &[&str], dry_run: bool) -> Result<()> {
pub fn delete_local_branches(repo: &Repository, branches: &[&str], dry_run: bool) -> Result<()> {
if branches.is_empty() {
return Ok(());
}
let mut args = vec!["branch", "--delete", "--force"];
args.extend(branches);

let detach_to = if repo.head_detached()? {
None
} else {
let head = repo.head()?;
let head_name = head.name().ok_or("non-utf8 head ref name")?;
if branches.contains(&head_name) {
Some(head_name.to_string())
} else {
None
}
};

if dry_run {
if let Some(detach_to) = detach_to {
println!("Note: switching to '{}' (dry run)", detach_to);
}
for branch in branches {
println!("Delete branch {} (dry run).", branch);
}
} else {
if let Some(detach_to) = detach_to {
git(&["checkout", &detach_to])?;
}
git(&args)?;
}
Ok(())
Expand Down Expand Up @@ -422,7 +471,7 @@ fn get_remote_name_and_ref_on_remote(
let remote_name = remote_name.ok_or("non-utf8 remote name")?;
let remote = repo.find_remote(&remote_name)?;
for refspec in remote.refspecs() {
if let Direction::Fetch = refspec.direction() {
if let Direction::Push = refspec.direction() {
continue;
}
let src = refspec.src().ok_or("non-utf8 src dst")?;
Expand Down
7 changes: 6 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ fn main(args: Args) -> ::std::result::Result<(), Box<dyn std::error::Error>> {

let repo = Repository::open_from_env()?;
let base = get_config_base(&repo, args.base)?;
let branches = get_merged_or_gone(&repo, &base)?;
let mut branches = get_merged_or_gone(&repo, &base)?;

if args.no_detach {
branches.adjust_not_to_detach(&repo)?;
}

branches.print_summary(&args.delete);

Expand All @@ -36,6 +40,7 @@ fn main(args: Args) -> ::std::result::Result<(), Box<dyn std::error::Error>> {
}

delete_local_branches(
&repo,
&branches.get_local_branches_to_delete(&args.delete),
args.dry_run,
)?;
Expand Down

0 comments on commit 6e5e036

Please sign in to comment.