From 25b8f24906fa2cfcc3e50aac3b6300e2947a8c0c Mon Sep 17 00:00:00 2001 From: James Brechtel Date: Wed, 13 May 2026 22:51:09 -0400 Subject: [PATCH] Fix two git operation bugs - gitCommitAll: abort commit when staging (git add -A) fails, e.g. due to a stale .git/index.lock. Previously the failure was ignored and commit proceeded on an empty or partial index. - gitPull: remove explicit branch argument from git pull --rebase. Passing both remote and branch can conflict with the branch's configured tracking ref, causing 'Cannot rebase onto multiple branches'. Now uses just --rebase , letting git resolve the tracking branch from config. - Test: index.lock scenario verifies commit is aborted on staging failure. --- src/Converge.hs | 17 ++++++++++------- test/GitCommitSpec.hs | 13 +++++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/Converge.hs b/src/Converge.hs index 1626984..686ffe4 100644 --- a/src/Converge.hs +++ b/src/Converge.hs @@ -321,17 +321,20 @@ syncRepo opts logger repo = do -- | Stage all changes and commit with an auto-generated message. gitCommitAll :: Logger -> FilePath -> IO (ExitCode, Text, Text) gitCommitAll logger repoPath = do - (_, _, stageErr) <- loggedGit logger repoPath ["add", "-A"] - unless (T.null stageErr) $ - logInfo logger ("git add stderr: " <> stageErr) - hostname <- init <$> readProcess "hostname" [] "" - loggedGit logger repoPath ["commit", "-m", "converge: auto-commit from " <> hostname] + addResult@(addCode, _, addErr) <- loggedGit logger repoPath ["add", "-A"] + unless (T.null addErr) $ + logInfo logger ("git add stderr: " <> addErr) + if addCode /= ExitSuccess + then pure addResult + else do + hostname <- init <$> readProcess "hostname" [] "" + loggedGit logger repoPath ["commit", "-m", "converge: auto-commit from " <> hostname] --- | Pull from the configured remote and branch. +-- | Pull from the configured remote, rebasing onto the tracked upstream branch. gitPull :: Logger -> RepoConfig -> IO (ExitCode, Text, Text) gitPull logger repo = loggedGit logger (rcPath repo) - ["pull", "--rebase", T.unpack (rcRemote repo), T.unpack (rcBranch repo)] + ["pull", "--rebase", T.unpack (rcRemote repo)] -- | Push to the configured remote and branch. gitPush :: Logger -> RepoConfig -> IO (ExitCode, Text, Text) diff --git a/test/GitCommitSpec.hs b/test/GitCommitSpec.hs index 57cbea1..aeeb510 100644 --- a/test/GitCommitSpec.hs +++ b/test/GitCommitSpec.hs @@ -54,6 +54,19 @@ spec = do countAfter2 <- commitCount repo countAfter2 `shouldBe` countBefore2 + it "aborts commit when staging fails (e.g. index.lock exists)" $ do + logger <- testLogger + withTempGitRepo $ \repo -> do + -- Create a lock file to make git add -A fail + writeFile (repo ".git" "index.lock") "locked" + writeFile (repo "new.txt") "new file" + countBefore <- commitCount repo + (code, _, err) <- gitCommitAll logger repo + -- Staging fails, so commit should not happen + code `shouldSatisfy` (/= ExitSuccess) + err `shouldSatisfy` ("index.lock" `T.isInfixOf`) + commitCount repo `shouldReturn` countBefore + describe "startup sync" $ do it "commits and pushes uncommitted changes on startup" $ do logger <- testLogger