a bit of finalization

This commit is contained in:
Mirek Kratochvil 2022-05-29 16:56:24 +02:00
parent c4c37405e9
commit bddf3063f9

View file

@ -3,10 +3,8 @@ module Patch
, pprPatchWarn , pprPatchWarn
) where ) where
import qualified Data.ByteString as B
import Data.Maybe (catMaybes) import Data.Maybe (catMaybes)
import qualified Data.Vector as V import qualified Data.Vector as V
import Format
import Merge import Merge
import Types import Types
@ -15,13 +13,6 @@ data PatchWarn
| HunkFailed Hunk (Int, Int) | HunkFailed Hunk (Int, Int)
deriving (Show) deriving (Show)
data PatchOpts =
PatchOpts
{ scanRange :: Int
, minContext :: Int
, mergeOpts :: MergeOpts
}
data PatchState = data PatchState =
PatchState PatchState
{ input :: TV { input :: TV
@ -50,9 +41,17 @@ patchToks ::
-> Int -> Int
-> MergeOpts -> MergeOpts
-> (TV, [Hunk], [PatchWarn]) -> (TV, [Hunk], [PatchWarn])
patchToks toks hunks revPatch scan ctxt mopt = patchToks toks hunks' revPatch scan ctxt mopt =
go hunks $ PatchState toks [] [] 0 0 0 0 go hunks $ PatchState toks [] [] 0 0 0 0
where where
hunks
| revPatch = map revHunk hunks'
| otherwise = hunks'
revHunk ((o, n), diff) = ((n, o), map revDiff diff)
revDiff (Add, t) = (Remove, t)
revDiff (Remove, t) = (Add, t)
revDiff (Keep, t) = (Keep, t)
revDiff _ = error "cannot reverse conflict diff"
go [] ps = go [] ps =
( V.concat (output ps ++ [V.drop (inOff ps) (input ps)]) ( V.concat (output ps ++ [V.drop (inOff ps) (input ps)])
, [rej | HunkFailed rej _ <- warns ps] , [rej | HunkFailed rej _ <- warns ps]
@ -106,12 +105,13 @@ patchHunkClean ps ((fromPos, toPos), diff) mopts
{ output = output ps ++ [skipped, V.fromList repl] { output = output ps ++ [skipped, V.fromList repl]
, inOff = expInOff + matchLen , inOff = expInOff + matchLen
, patchInOff = fromPos + matchLen , patchInOff = fromPos + matchLen
, outOff = expOutOff + length repl , outOff = expOutOff + replLen
, patchOutOff = toPos + length repl , patchOutOff = toPos + replLen
} }
| otherwise = Nothing | otherwise = Nothing
where where
matchLen = diffMatchLen diff matchLen = diffMatchLen diff
replLen = diffReplLen diff
advance = fromPos - patchInOff ps advance = fromPos - patchInOff ps
expInOff = advance + inOff ps expInOff = advance + inOff ps
expOutOff = advance + outOff ps expOutOff = advance + outOff ps
@ -134,6 +134,14 @@ diffMatchLen = sum . map (off . fst)
off Original = 1 off Original = 1
off _ = 0 off _ = 0
diffReplLen :: Diff -> Int
diffReplLen = sum . map (off . fst)
where
off Keep = 1
off Add = 1
off Original = 1
off _ = 0 -- tricky: the conflicts do not actually add to the diff counters
diffOffChange :: Diff -> Int diffOffChange :: Diff -> Int
diffOffChange = sum . map (off . fst) diffOffChange = sum . map (off . fst)
where where
@ -141,27 +149,58 @@ diffOffChange = sum . map (off . fst)
off Remove = -1 off Remove = -1
off _ = 0 off _ = 0
markToks :: MergeOpts -> Op -> Op -> [Tok]
markToks mopts x' y' = map (\s -> (True, s)) $ go x' y'
where
unmarked :: Op -> Bool
unmarked Keep = True
unmarked Add = True
unmarked Remove = True
unmarked _ = False
go :: Op -> Op -> [BS]
go x y
| x == y = []
| unmarked x = goUnmarked y
| x == MineChanged
, y /= Original = mergeYourSepStr mopts : go YourChanged y
| x == MineChanged = mergeMineSepStr mopts : go Original y
| x == Original = mergeYourSepStr mopts : go YourChanged y
| x == YourChanged = mergeCEndStr mopts : goUnmarked y
| otherwise = error "internal error in markToks"
goUnmarked :: Op -> [BS]
goUnmarked y
| unmarked y = []
| otherwise = mergeCStartStr mopts : go MineChanged y
matchDiff :: MergeOpts -> [Tok] -> Diff -> Maybe [Tok] matchDiff :: MergeOpts -> [Tok] -> Diff -> Maybe [Tok]
matchDiff mopt ts ds matchDiff mopt = go Keep
| null ts where
, null ds = return [] withMark :: Op -> Op -> [Tok] -> ([Tok] -> [Tok])
| ((op, tok):ds') <- ds withMark prev op toks = (++) (markToks mopt prev op ++ toks)
, op == Add {-, MineChanged, YourChanged -- TODO special treatment needed -} go :: Op -> [Tok] -> Diff -> Maybe [Tok]
= (tok :) <$> matchDiff mopt ts ds' go prev ts ds
| (intok:ts') <- ts | null ts
, ((op, tok):ds') <- ds , null ds = return $ markToks mopt prev Keep
, op == Keep {-, Original -- TODO special treatment needed-} | ((op, tok):ds') <- ds
, tokCmp' mopt intok tok = , op == Add || op == MineChanged || op == YourChanged =
(:) withMark prev op [tok] <$> go op ts ds'
(if mergeKeepWhitespace mopt && not (fst intok) | (intok:ts') <- ts
then intok , ((op, tok):ds') <- ds
else tok) <$> , op == Keep || op == Original
matchDiff mopt ts' ds' , tokCmp' mopt intok tok =
| (intok:ts') <- ts withMark
, ((op, tok):ds') <- ds prev
, op == Remove op
, tokCmp' mopt intok tok = matchDiff mopt ts' ds' [ if mergeKeepWhitespace mopt && not (fst intok)
| otherwise = Nothing then intok
else tok
] <$>
go op ts' ds'
| (intok:ts') <- ts
, ((op, tok):ds') <- ds
, op == Remove
, tokCmp' mopt intok tok = withMark prev op [] <$> go op ts' ds'
| otherwise = Nothing
tokCmp' :: MergeOpts -> Tok -> Tok -> Bool tokCmp' :: MergeOpts -> Tok -> Tok -> Bool
tokCmp' MergeOpts {mergeForceWhitespace = x} = tokCmp x tokCmp' MergeOpts {mergeForceWhitespace = x} = tokCmp x