Commit and push uncommitted changes on startup
- watchRepo: call syncRepo at startup to commit any pre-existing uncommitted changes before entering the file watcher - Add gitPush function for git push <remote> <branch> - Add push step to syncRepo after successful pull (with failure notification via notifyUser) - Export syncRepo and gitPush for testing - Test: startup sync commits and pushes uncommitted changes
This commit is contained in:
+23
-1
@@ -14,6 +14,7 @@ module Converge (
|
|||||||
|
|
||||||
-- * Running
|
-- * Running
|
||||||
runConverge,
|
runConverge,
|
||||||
|
syncRepo,
|
||||||
|
|
||||||
-- * Logger
|
-- * Logger
|
||||||
Logger (..),
|
Logger (..),
|
||||||
@@ -22,6 +23,7 @@ module Converge (
|
|||||||
-- * Git operations
|
-- * Git operations
|
||||||
gitCommitAll,
|
gitCommitAll,
|
||||||
gitPull,
|
gitPull,
|
||||||
|
gitPush,
|
||||||
runGitIn,
|
runGitIn,
|
||||||
hasConflicts,
|
hasConflicts,
|
||||||
isInMiddleOfOperation,
|
isInMiddleOfOperation,
|
||||||
@@ -190,6 +192,8 @@ watchRepo opts logger repo = do
|
|||||||
-- Drain any events that arrived during the debounce window
|
-- Drain any events that arrived during the debounce window
|
||||||
void $ tryTakeMVar pending
|
void $ tryTakeMVar pending
|
||||||
syncRepo opts logger repo
|
syncRepo opts logger repo
|
||||||
|
-- Sync any uncommitted changes that exist on startup
|
||||||
|
syncRepo opts logger repo
|
||||||
bracket
|
bracket
|
||||||
(startManagerConf defaultConfig)
|
(startManagerConf defaultConfig)
|
||||||
stopManager
|
stopManager
|
||||||
@@ -293,7 +297,18 @@ syncRepo opts logger repo = do
|
|||||||
notifyUser opts
|
notifyUser opts
|
||||||
"Converge: Merge Conflict"
|
"Converge: Merge Conflict"
|
||||||
("A merge conflict occurred in " <> rcPath repo <> ". Manual resolution required.")
|
("A merge conflict occurred in " <> rcPath repo <> ". Manual resolution required.")
|
||||||
else logRepo logger repo "sync complete, no conflicts"
|
else do
|
||||||
|
logRepo logger repo "sync complete, no conflicts"
|
||||||
|
-- Push local commits to remote
|
||||||
|
(pushCode, pushOut, pushErr) <- gitPush repo
|
||||||
|
case pushCode of
|
||||||
|
ExitSuccess ->
|
||||||
|
logRepo logger repo "push succeeded"
|
||||||
|
_ -> do
|
||||||
|
logRepo logger repo ("push FAILED (exit " <> T.pack (show pushCode) <> "): " <> T.strip (pushOut <> pushErr))
|
||||||
|
notifyUser opts
|
||||||
|
"Converge: Push Failed"
|
||||||
|
("Push failed in " <> rcPath repo <> " (exit " <> show pushCode <> ")")
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
-- Git operations
|
-- Git operations
|
||||||
@@ -315,6 +330,13 @@ gitPull repo =
|
|||||||
(rcPath repo)
|
(rcPath repo)
|
||||||
["pull", "--rebase", T.unpack (rcRemote repo), T.unpack (rcBranch repo)]
|
["pull", "--rebase", T.unpack (rcRemote repo), T.unpack (rcBranch repo)]
|
||||||
|
|
||||||
|
-- | Push to the configured remote and branch.
|
||||||
|
gitPush :: RepoConfig -> IO (ExitCode, Text, Text)
|
||||||
|
gitPush repo =
|
||||||
|
runGitIn
|
||||||
|
(rcPath repo)
|
||||||
|
["push", T.unpack (rcRemote repo), T.unpack (rcBranch repo)]
|
||||||
|
|
||||||
-- | Check if the repository currently has merge conflicts.
|
-- | Check if the repository currently has merge conflicts.
|
||||||
hasConflicts :: FilePath -> IO Bool
|
hasConflicts :: FilePath -> IO Bool
|
||||||
hasConflicts repoPath = do
|
hasConflicts repoPath = do
|
||||||
|
|||||||
+26
-1
@@ -1,6 +1,6 @@
|
|||||||
module GitCommitSpec (spec) where
|
module GitCommitSpec (spec) where
|
||||||
|
|
||||||
import Converge (gitCommitAll)
|
import Converge (Options (..), RepoConfig (..), defaultOptions, defaultRepoConfig, gitCommitAll, syncRepo)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import System.Exit (ExitCode (..))
|
import System.Exit (ExitCode (..))
|
||||||
import System.FilePath ((</>))
|
import System.FilePath ((</>))
|
||||||
@@ -55,3 +55,28 @@ spec = do
|
|||||||
code2 `shouldSatisfy` (/= ExitSuccess)
|
code2 `shouldSatisfy` (/= ExitSuccess)
|
||||||
countAfter2 <- commitCount repo
|
countAfter2 <- commitCount repo
|
||||||
countAfter2 `shouldBe` countBefore2
|
countAfter2 `shouldBe` countBefore2
|
||||||
|
|
||||||
|
describe "startup sync" $ do
|
||||||
|
|
||||||
|
it "commits and pushes uncommitted changes on startup" $ do
|
||||||
|
logger <- testLogger
|
||||||
|
withTempGitRepoWithRemote $ \repo -> do
|
||||||
|
-- Leave a file uncommitted (simulating state before converge starts)
|
||||||
|
writeFile (repo </> "uncommitted.txt") "pending change"
|
||||||
|
|
||||||
|
countBefore <- commitCount repo
|
||||||
|
countBefore `shouldBe` 1
|
||||||
|
|
||||||
|
let cfg = defaultRepoConfig {rcPath = repo}
|
||||||
|
let opts = defaultOptions
|
||||||
|
{ optRepos = [cfg]
|
||||||
|
, optNotifyCmd = "true" -- avoid firing notify-send
|
||||||
|
}
|
||||||
|
syncRepo opts logger cfg
|
||||||
|
|
||||||
|
countAfter <- commitCount repo
|
||||||
|
countAfter `shouldBe` 2
|
||||||
|
|
||||||
|
-- Verify the commit was pushed to remote
|
||||||
|
(_, remoteLog, _) <- runGitIn repo ["log", "origin/main", "--oneline", "--name-only"]
|
||||||
|
remoteLog `shouldSatisfy` ("uncommitted.txt" `T.isInfixOf`)
|
||||||
|
|||||||
Reference in New Issue
Block a user