packages feed

git-brunch 1.7.2.0 → 1.8.0

raw patch · 6 files changed

+109/−13 lines, 6 filesdep +containersdep +directory

Dependencies added: containers, directory

Files

README.md view
@@ -11,6 +11,7 @@ - Search for a branch - Delete a branch - Fetch / Update+- Worktree support  ## Usage @@ -42,6 +43,22 @@ ```sh yay -S git-brunch pamac install git-brunch+```++### Homebrew (macOS)++You can install `git-brunch` via a Homebrew tap. This uses a prebuilt macOS binary.++```sh+brew tap andys8/tap+brew install git-brunch+```++#### macOS Security Note+Since the binary is not signed with an Apple Developer certificate, macOS might block it initially. After installation, you can run this command to allow the binary to execute:++```sh+xattr -d com.apple.quarantine $(which git-brunch) ```  ### FreeBSD
app/Git.hs view
@@ -7,27 +7,35 @@   isCommonBranch,   isRemoteBranch,   listBranches,+  getWorktreePath,   rebaseInteractive,   merge,   toBranches, ) where  import Data.Char (isSpace)+import Data.Map (Map)+import Data.Map qualified as Map+import Data.Maybe (fromMaybe) import Data.Text (Text) import Data.Text qualified as T import Data.Text.IO qualified as T+import System.Directory (setCurrentDirectory)+import System.Environment (lookupEnv) import System.Exit import System.Process  data Branch   = BranchLocal Text   | BranchCurrent Text+  | BranchWorktree Text   | BranchRemote Text Text   deriving (Eq)  instance Show Branch where   show (BranchLocal n) = T.unpack n   show (BranchCurrent n) = T.unpack $ n <> "*"+  show (BranchWorktree n) = T.unpack $ n <> "+"   show (BranchRemote o n) = T.unpack $ o <> "/" <> n  fetch :: IO Text@@ -54,6 +62,7 @@ toBranch line = mkBranch $ T.words $ T.dropWhile isSpace line  where   mkBranch ("*" : name : _) = BranchCurrent name+  mkBranch ("+" : name : _) = BranchWorktree name   mkBranch (name : _) = case T.stripPrefix "remotes/" name of     Just rest -> parseRemoteBranch rest     Nothing -> BranchLocal name@@ -64,8 +73,20 @@     name = T.drop 1 rest  checkout :: Branch -> IO ExitCode+checkout (BranchWorktree n) = do+  mPath <- getWorktreePath n+  case mPath of+    Just path -> spawnShell path+    Nothing -> spawnGit ["checkout", n] checkout branch = spawnGit ["checkout", branchName branch] +spawnShell :: FilePath -> IO ExitCode+spawnShell path = do+  setCurrentDirectory path+  userShell <- fromMaybe "/bin/sh" <$> lookupEnv "SHELL"+  T.putStrLn $ "Worktree: " <> T.pack path+  waitForProcess =<< spawnProcess userShell []+ rebaseInteractive :: Branch -> IO ExitCode rebaseInteractive branch = do   T.putStrLn $ "Rebase onto " <> fullBranchName branch@@ -78,6 +99,7 @@  deleteBranch :: Branch -> IO ExitCode deleteBranch (BranchCurrent _) = error "Cannot delete current branch"+deleteBranch (BranchWorktree _) = error "Cannot delete branch checked out in another worktree" deleteBranch (BranchLocal n) = spawnGit ["branch", "-D", n] deleteBranch (BranchRemote o n) = spawnGit ["push", o, "--delete", n] @@ -87,6 +109,25 @@ readGit :: [Text] -> IO Text readGit args = T.pack <$> readProcess "git" (T.unpack <$> args) [] +getWorktreePath :: Text -> IO (Maybe FilePath)+getWorktreePath branch = do+  output <- readGit ["worktree", "list", "--porcelain"]+  let worktrees = parseWorktrees (T.lines output)+  pure $ Map.lookup branch worktrees++parseWorktrees :: [Text] -> Map Text FilePath+parseWorktrees lines' = go lines' Map.empty Nothing+ where+  go [] m _ = m+  go (l : ls) m currentPath+    | "worktree " `T.isPrefixOf` l = go ls m (Just $ T.unpack $ T.drop 9 l)+    | "branch " `T.isPrefixOf` l =+        let branch = fromMaybe (T.drop 13 l) (T.stripPrefix "refs/heads/" (T.drop 7 l))+         in case currentPath of+              Just p -> go ls (Map.insert branch p m) Nothing+              Nothing -> go ls m Nothing+    | otherwise = go ls m currentPath+ isCommonBranch :: Branch -> Bool isCommonBranch b = branchName b `elem` commonBranchNames  where@@ -109,11 +150,13 @@  branchName :: Branch -> Text branchName (BranchCurrent n) = n+branchName (BranchWorktree n) = n branchName (BranchLocal n) = n branchName (BranchRemote _ n) = n  fullBranchName :: Branch -> Text fullBranchName (BranchCurrent n) = n+fullBranchName (BranchWorktree n) = n fullBranchName (BranchLocal n) = n fullBranchName (BranchRemote r n) = r <> "/" <> n 
app/GitBrunch.hs view
@@ -75,14 +75,17 @@ main = do   branches <- Git.listBranches `catch` gitFailed   state <- M.defaultMain app $ syncBranchLists emptyState{_branches = branches}-  let execGit = gitFunction (_gitCommand state)-  exitCode <- maybe noBranchErr execGit (selectedBranch state)-  when (exitCode /= ExitSuccess)-    $ die ("Failed to " ++ show (_gitCommand state) ++ ".")+  case selectedBranch state of+    Nothing -> pure ()+    Just branch -> do+      let cmd = _gitCommand state+      let execGit = gitFunction cmd+      exitCode <- execGit branch+      when (exitCode /= ExitSuccess)+        $ die ("Failed to " ++ show cmd ++ ".")  where   gitFailed :: SomeException -> IO a   gitFailed _ = exitFailure-  noBranchErr = die "No branch selected."   gitFunction = \case     GitCheckout -> Git.checkout     GitRebase -> Git.rebaseInteractive@@ -181,6 +184,7 @@  where   maxPadding = if isListFocussed then padRight Max else id   highlight (BranchCurrent _) = withAttr attrBranchCurrent+  highlight (BranchWorktree _) = withAttr attrBranchWorktree   highlight b | Git.isCommonBranch b = withAttr attrBranchCommon   highlight _ = id @@ -221,7 +225,10 @@      confirmDelete :: Maybe Branch -> EventM Name State ()     confirmDelete (Just (BranchCurrent _)) = pure ()-    confirmDelete (Just _) = dialogL ?= createDialog GitDeleteBranch+    confirmDelete (Just (BranchWorktree _)) = pure ()+    confirmDelete (Just _) = do+      gitCommandL .= GitDeleteBranch+      dialogL ?= createDialog GitDeleteBranch     confirmDelete Nothing = pure ()      fetch = do@@ -270,10 +277,29 @@       dialogL .= Nothing       gitCommandL .= GitCheckout -    confirmDialog cmd = do-      dialogL .= Nothing-      gitCommandL .= cmd-      halt+    confirmDialog cmd =+      if cmd == GitDeleteBranch+        then do+          dialogL .= Nothing+          gitCommandL .= GitCheckout+          state <- get+          case selectedBranch state of+            Nothing -> pure ()+            Just branch -> M.suspendAndResume $ do+              exitCode <- Git.deleteBranch branch+              if exitCode == ExitSuccess+                then do+                  branches <- Git.listBranches+                  pure $ syncBranchLists state{_branches = branches}+                else do+                  T.putStrLn $ "Failed to delete branch " <> Git.fullBranchName branch+                  T.putStrLn "Press Enter to continue..."+                  void getLine+                  pure state+        else do+          dialogL .= Nothing+          gitCommandL .= cmd+          halt    in     case vimifiedKey e of       EvKey KEnter [] -> do@@ -325,7 +351,6 @@ updateBranches branches =   syncBranchLists     . (branchesL .~ branches)-    . (filterL .~ emptyFilter)  syncBranchLists :: State -> State syncBranchLists state =
app/Theme.hs view
@@ -27,6 +27,7 @@     , (attrTitle, withStyle (fg brightWhite) bold)     , (attrTitleFocus, withStyle (fg yellow) bold)     , (attrBranchCurrent, fg brightRed)+    , (attrBranchWorktree, fg brightCyan)     , (attrBranchCommon, fg brightBlue)     ] @@ -47,6 +48,9 @@  attrBranchCurrent :: AttrName attrBranchCurrent = attrName "current-branch"++attrBranchWorktree :: AttrName+attrBranchWorktree = attrName "worktree-branch"  attrBranchCommon :: AttrName attrBranchCommon = attrName "common-branch"
git-brunch.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.1.+-- This file has been generated from package.yaml by hpack version 0.38.1. -- -- see: https://github.com/sol/hpack  name:           git-brunch-version:        1.7.2.0+version:        1.8.0 synopsis:       git checkout command-line tool description:    Please see the README on GitHub at <https://github.com/andys8/git-brunch> category:       Git@@ -45,6 +45,8 @@   build-depends:       base >=4.7 && <5     , brick+    , containers+    , directory     , extra     , hspec     , microlens@@ -80,6 +82,8 @@   build-depends:       base >=4.7 && <5     , brick+    , containers+    , directory     , extra     , hspec     , microlens
test/Spec.hs view
@@ -14,6 +14,9 @@     it "detects current branch by asterik" $ do       toBranches "* master" `shouldBe` [BranchCurrent "master"] +    it "detects worktree branch by plus" $ do+      toBranches "+ master" `shouldBe` [BranchWorktree "master"]+     it "returns a local branch" $ do       toBranches "master" `shouldBe` [BranchLocal "master"]