diff options
| -rw-r--r-- | Omni/Jr.hs | 92 |
1 files changed, 90 insertions, 2 deletions
@@ -208,7 +208,7 @@ runLoop delaySec = do Nothing -> do autoReview tid task commitSha --- | Handle merge conflict during review +-- | Handle merge conflict during review (Gerrit-style: provide rich context) handleConflict :: Text -> [Text] -> String -> IO () handleConflict tid conflictFiles commitSha = do maybeCtx <- TaskCore.getRetryContext tid @@ -219,17 +219,105 @@ handleConflict tid conflictFiles commitSha = do putText "[review] Task has failed 3 times. Needs human intervention." TaskCore.updateTaskStatus tid TaskCore.Open [] else do + conflictDetails <- gatherConflictContext commitSha conflictFiles TaskCore.setRetryContext TaskCore.RetryContext { TaskCore.retryTaskId = tid, TaskCore.retryOriginalCommit = Text.pack commitSha, TaskCore.retryConflictFiles = conflictFiles, TaskCore.retryAttempt = attempt, - TaskCore.retryReason = "merge_conflict" + TaskCore.retryReason = conflictDetails } TaskCore.updateTaskStatus tid TaskCore.Open [] putText ("[review] Task " <> tid <> " returned to queue (attempt " <> tshow attempt <> "/3).") +-- | Gather Gerrit-style conflict context for the coder +gatherConflictContext :: String -> [Text] -> IO Text +gatherConflictContext commitSha conflictFiles = do + commitInfo <- getCommitInfo commitSha + currentHeadInfo <- getCurrentHeadInfo + fileDiffs <- traverse (getFileConflictInfo commitSha <. Text.unpack) conflictFiles + + pure + <| Text.unlines + [ "MERGE CONFLICT - Your changes could not be cleanly applied", + "", + "== Your Commit ==", + commitInfo, + "", + "== Current HEAD ==", + currentHeadInfo, + "", + "== Conflicting Files ==", + Text.unlines fileDiffs, + "", + "== Resolution Instructions ==", + "1. The codebase has been updated since your work", + "2. Review the current state of conflicting files", + "3. Re-implement your changes on top of the current code", + "4. Ensure your changes still make sense given the updates" + ] + +-- | Get info about the commit that caused the conflict +getCommitInfo :: String -> IO Text +getCommitInfo sha = do + (_, out, _) <- + Process.readProcessWithExitCode + "git" + ["log", "-1", "--format=%h %s%n%b", sha] + "" + pure <| Text.pack out + +-- | Get info about current HEAD +getCurrentHeadInfo :: IO Text +getCurrentHeadInfo = do + (_, out, _) <- + Process.readProcessWithExitCode + "git" + ["log", "-1", "--format=%h %s (%cr)"] + "" + pure <| Text.pack out + +-- | Get file-level conflict context showing what changed in both branches +getFileConflictInfo :: String -> FilePath -> IO Text +getFileConflictInfo commitSha filePath = do + yourChanges <- getYourChangesToFile commitSha filePath + recentChanges <- getRecentChangesToFile filePath + pure + <| Text.unlines + [ "--- " <> Text.pack filePath <> " ---", + "", + "Your changes to this file:", + yourChanges, + "", + "Recent changes by others:", + recentChanges + ] + +-- | Get a summary of changes in a specific commit to a file +getYourChangesToFile :: String -> FilePath -> IO Text +getYourChangesToFile commitSha filePath = do + (code, out, _) <- + Process.readProcessWithExitCode + "git" + ["show", "--stat", commitSha, "--", filePath] + "" + case code of + Exit.ExitSuccess -> pure <| Text.pack (take 500 out) + Exit.ExitFailure _ -> pure "(unable to get diff)" + +-- | Get recent changes to a file (last few commits) +getRecentChangesToFile :: FilePath -> IO Text +getRecentChangesToFile filePath = do + (code, out, _) <- + Process.readProcessWithExitCode + "git" + ["log", "-3", "--oneline", "--", filePath] + "" + case code of + Exit.ExitSuccess -> pure <| Text.pack out + Exit.ExitFailure _ -> pure "(unable to get history)" + -- | Interactive review command (jr review <task-id>) reviewTask :: Text -> Bool -> IO () reviewTask tid autoMode = do |
