Skip to content

Instantly share code, notes, and snippets.

@aleperaltabazas
Last active September 20, 2019 13:22
Show Gist options
  • Select an option

  • Save aleperaltabazas/fe74dfce95fe82610ae6bdbc38699182 to your computer and use it in GitHub Desktop.

Select an option

Save aleperaltabazas/fe74dfce95fe82610ae6bdbc38699182 to your computer and use it in GitHub Desktop.
Delete local branches that are no longer on the remote
#!/usr/bin/runhaskell
import System.Process
import System.Exit
import Data.List.Split
import Data.List
import Control.Exception
main :: IO ()
main = do
fetch
local <- readLocal
remote <- readRemote
unused <- unusedBranches local remote
askRemove unused
putStrLn "Done!"
fetch :: IO ()
fetch = do
putStrLn "Fetching from remote..."
runShell "git fetch --prune"
putStrLn "Done"
readLocal :: IO [String]
readLocal = readBranches "Local branches:" "git branch"
readRemote :: IO [String]
readRemote = (\branches -> map cleanOrigin branches) <$> (readBranches "Remote branches:" "git branch -r")
readBranches :: String -> String -> IO [String]
readBranches toPrint command = do
putStrLn toPrint
branches <- runShell command
let asList = map clean . lines $ branches
showBranches asList
return asList
showBranches :: [String] -> IO ()
showBranches = mapM_ putStrLn
unusedBranches :: [String] -> [String] -> IO [String]
unusedBranches local remote = return . filter (\branch -> not . elem branch $ remote) $ local
runShell :: String -> IO String
runShell command = readCreateProcess (shell command) ""
ioFst :: IO (ExitCode, String, String) -> IO String
ioFst io = do
(exitCode, stdout, stderr) <- io
return stdout
runShellWithExitCode :: String -> IO (ExitCode, String, String)
runShellWithExitCode command = readCreateProcessWithExitCode (shell command) ""
replace :: Eq a => [a] -> [a] -> [a] -> [a]
replace old new = intercalate new . splitOn old
clean :: String -> String
clean = replace " " "" . replace "*" ""
cleanOrigin :: String -> String
cleanOrigin = replace "origin/" ""
ioUnit :: IO ()
ioUnit = return ()
safeToDelete = ["y", "Y", "ye", "Ye", "yes", "Yes"]
askRemove :: [String] -> IO ()
askRemove [] = do
putStrLn "No unused branches found"
askRemove branches = do
putStrLn "Unused branches:"
showBranches branches
mapM_ askDelete branches
askDelete :: String -> IO ()
askDelete branch = do
putStr ("Delete branch " ++ branch ++ "? (Y/n) ")
answer <- getLine
if elem answer safeToDelete
then do
catch (deleteBranch branch) (errorDeletingBranch branch)
else do
putStrLn ("Branch " ++ branch ++ " will be kept")
deleteBranch :: String -> IO ()
deleteBranch branch = do
_ <- runShell ("git branch -d " ++ branch)
putStrLn ("Branch " ++ branch ++ " was deleted")
keepBranch :: String -> IO ()
keepBranch branch = putStrLn ("Branch " ++ branch ++ " will be kept")
errorDeletingBranch :: String -> IOException -> IO ()
errorDeletingBranch branch e = putStrLn ("Error deleting branch " ++ branch ++ ", with error: " ++ (displayException e))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment