{-# LANGUAGE CPP #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Darcs.Patch.Prim.V1.Commute
    ( Perhaps(..)
    , toPerhaps
    , CommuteFunction
    , speedyCommute
    , cleverCommute
    , commuteFiledir
    , commuteFilepatches
    ) where

import Prelude ()
import Darcs.Prelude

import Prelude hiding ( pi, Applicative(..) )
import Control.Monad ( MonadPlus, msum, mzero, mplus )
import Control.Applicative ( Alternative(..) )

import qualified Data.ByteString as B ( ByteString )
import qualified Data.ByteString.Char8 as BC ( pack )

import Darcs.Util.Path ( FileName, fn2fp, movedirfilename )
import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP )
import Darcs.Patch.Witnesses.Ordered ( (:>)(..) )
import Darcs.Patch.Prim.V1.Core
     ( Prim(..), FilePatchType(..) )
import Darcs.Patch.Invert ( Invert(..) )
import Darcs.Patch.Commute ( Commute(..) )
import Darcs.Patch.Permutations () -- for Invert instance of FL
import Darcs.Patch.TokenReplace ( tryTokReplace )

isInDirectory :: FileName -> FileName -> Bool
isInDirectory :: FileName -> FileName -> Bool
isInDirectory d :: FileName
d f :: FileName
f = [Char] -> [Char] -> Bool
iid (FileName -> [Char]
fn2fp FileName
d) (FileName -> [Char]
fn2fp FileName
f)
    where iid :: [Char] -> [Char] -> Bool
iid (cd :: Char
cd:cds :: [Char]
cds) (cf :: Char
cf:cfs :: [Char]
cfs)
              | Char
cd Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
cf = Bool
False
              | Bool
otherwise = [Char] -> [Char] -> Bool
iid [Char]
cds [Char]
cfs
          iid [] ('/':_) = Bool
True
          iid [] [] = Bool
True -- Count directory itself as being in directory...
          iid _ _ = Bool
False

data Perhaps a = Unknown | Failed | Succeeded a

instance Functor Perhaps where
    fmap :: (a -> b) -> Perhaps a -> Perhaps b
fmap _ Unknown = Perhaps b
forall a. Perhaps a
Unknown
    fmap _ Failed = Perhaps b
forall a. Perhaps a
Failed
    fmap f :: a -> b
f (Succeeded x :: a
x) = b -> Perhaps b
forall a. a -> Perhaps a
Succeeded (a -> b
f a
x)

instance Applicative Perhaps where
    pure :: a -> Perhaps a
pure = a -> Perhaps a
forall a. a -> Perhaps a
Succeeded
    _ <*> :: Perhaps (a -> b) -> Perhaps a -> Perhaps b
<*> Failed = Perhaps b
forall a. Perhaps a
Failed
    _ <*> Unknown = Perhaps b
forall a. Perhaps a
Unknown
    Failed <*> _ = Perhaps b
forall a. Perhaps a
Failed
    Unknown <*> _ = Perhaps b
forall a. Perhaps a
Unknown
    Succeeded f :: a -> b
f <*> Succeeded x :: a
x = b -> Perhaps b
forall a. a -> Perhaps a
Succeeded (a -> b
f a
x)

instance  Monad Perhaps where
    (Succeeded x :: a
x) >>= :: Perhaps a -> (a -> Perhaps b) -> Perhaps b
>>= k :: a -> Perhaps b
k =  a -> Perhaps b
k a
x
    Failed   >>= _      =  Perhaps b
forall a. Perhaps a
Failed
    Unknown  >>= _      =  Perhaps b
forall a. Perhaps a
Unknown
    return :: a -> Perhaps a
return              =  a -> Perhaps a
forall a. a -> Perhaps a
Succeeded
#if MIN_VERSION_base(4,13,0)
instance MonadFail Perhaps where
#endif
    fail :: [Char] -> Perhaps a
fail _              =  Perhaps a
forall a. Perhaps a
Unknown

instance Alternative Perhaps where
    empty :: Perhaps a
empty = Perhaps a
forall a. Perhaps a
Unknown
    Unknown <|> :: Perhaps a -> Perhaps a -> Perhaps a
<|> ys :: Perhaps a
ys    = Perhaps a
ys
    Failed  <|> _     = Perhaps a
forall a. Perhaps a
Failed
    (Succeeded x :: a
x) <|> _ = a -> Perhaps a
forall a. a -> Perhaps a
Succeeded a
x

instance  MonadPlus Perhaps where
    mzero :: Perhaps a
mzero = Perhaps a
forall a. Perhaps a
Unknown
    mplus :: Perhaps a -> Perhaps a -> Perhaps a
mplus = Perhaps a -> Perhaps a -> Perhaps a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
(<|>)

toMaybe :: Perhaps a -> Maybe a
toMaybe :: Perhaps a -> Maybe a
toMaybe (Succeeded x :: a
x) = a -> Maybe a
forall a. a -> Maybe a
Just a
x
toMaybe _ = Maybe a
forall a. Maybe a
Nothing

toPerhaps :: Maybe a -> Perhaps a
toPerhaps :: Maybe a -> Perhaps a
toPerhaps (Just x :: a
x) = a -> Perhaps a
forall a. a -> Perhaps a
Succeeded a
x
toPerhaps Nothing = Perhaps a
forall a. Perhaps a
Failed

cleverCommute :: CommuteFunction -> CommuteFunction
cleverCommute :: CommuteFunction -> CommuteFunction
cleverCommute c :: CommuteFunction
c (p1 :: Prim wX wZ
p1:>p2 :: Prim wZ wY
p2) =
    case (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
CommuteFunction
c (Prim wX wZ
p1 Prim wX wZ -> Prim wZ wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> Prim wZ wY
p2) of
    Succeeded x :: (:>) Prim Prim wX wY
x -> (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded (:>) Prim Prim wX wY
x
    Failed -> Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
    Unknown -> case (:>) Prim Prim wY wX -> Perhaps ((:>) Prim Prim wY wX)
CommuteFunction
c (Prim wZ wY -> Prim wY wZ
forall (p :: * -> * -> *) wX wY. Invert p => p wX wY -> p wY wX
invert Prim wZ wY
p2 Prim wY wZ -> Prim wZ wX -> (:>) Prim Prim wY wX
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> Prim wX wZ -> Prim wZ wX
forall (p :: * -> * -> *) wX wY. Invert p => p wX wY -> p wY wX
invert Prim wX wZ
p1) of
               Succeeded (p1' :: Prim wY wZ
p1' :> p2' :: Prim wZ wX
p2') -> (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded (Prim wZ wX -> Prim wX wZ
forall (p :: * -> * -> *) wX wY. Invert p => p wX wY -> p wY wX
invert Prim wZ wX
p2' Prim wX wZ -> Prim wZ wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> Prim wY wZ -> Prim wZ wY
forall (p :: * -> * -> *) wX wY. Invert p => p wX wY -> p wY wX
invert Prim wY wZ
p1')
               Failed -> Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
               Unknown -> Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Unknown
--cleverCommute c (p1,p2) = c (p1,p2) `mplus`
--    (case c (invert p2,invert p1) of
--     Succeeded (p1', p2') -> Succeeded (invert p2', invert p1')
--     Failed -> Failed
--     Unknown -> Unknown)

speedyCommute :: CommuteFunction  -- Deal with common cases quickly!
    -- Two file-patches modifying different files trivially commute.
speedyCommute :: (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
speedyCommute (p1 :: Prim wX wZ
p1@(FP f1 :: FileName
f1 _) :> p2 :: Prim wZ wY
p2@(FP f2 :: FileName
f2 _))
  | FileName
f1 FileName -> FileName -> Bool
forall a. Eq a => a -> a -> Bool
/= FileName
f2 = (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded (Prim wZ wY -> Prim wX Any
forall (a :: * -> * -> *) wX wY wB wC. a wX wY -> a wB wC
unsafeCoerceP Prim wZ wY
p2 Prim wX Any -> Prim Any wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> Prim wX wZ -> Prim Any wY
forall (a :: * -> * -> *) wX wY wB wC. a wX wY -> a wB wC
unsafeCoerceP Prim wX wZ
p1)
speedyCommute _other :: (:>) Prim Prim wX wY
_other = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Unknown

everythingElseCommute :: CommuteFunction
everythingElseCommute :: (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
everythingElseCommute = (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
CommuteFunction
eec
  where
    eec :: CommuteFunction
    eec :: (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
eec (p1 :: Prim wX wZ
p1 :> ChangePref p :: [Char]
p f :: [Char]
f t :: [Char]
t) = (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded ([Char] -> [Char] -> [Char] -> Prim wX Any
forall wX wY. [Char] -> [Char] -> [Char] -> Prim wX wY
ChangePref [Char]
p [Char]
f [Char]
t Prim wX Any -> Prim Any wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> Prim wX wZ -> Prim Any wY
forall (a :: * -> * -> *) wX wY wB wC. a wX wY -> a wB wC
unsafeCoerceP Prim wX wZ
p1)
    eec (ChangePref p :: [Char]
p f :: [Char]
f t :: [Char]
t :> p2 :: Prim wZ wY
p2) = (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded (Prim wZ wY -> Prim wX Any
forall (a :: * -> * -> *) wX wY wB wC. a wX wY -> a wB wC
unsafeCoerceP Prim wZ wY
p2 Prim wX Any -> Prim Any wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> [Char] -> [Char] -> [Char] -> Prim Any wY
forall wX wY. [Char] -> [Char] -> [Char] -> Prim wX wY
ChangePref [Char]
p [Char]
f [Char]
t)
    eec xx :: (:>) Prim Prim wX wY
xx = CommuteFunction
-> (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
CommuteFunction -> CommuteFunction
cleverCommute CommuteFunction
commuteFiledir (:>) Prim Prim wX wY
xx

{-
Note that it must be true that

commutex (A^-1 A, P) = Just (P, A'^-1 A')

and

if commutex (A, B) == Just (B', A')
then commutex (B^-1, A^-1) == Just (A'^-1, B'^-1)
-}

instance Commute Prim where
    commute :: (:>) Prim Prim wX wY -> Maybe ((:>) Prim Prim wX wY)
commute x :: (:>) Prim Prim wX wY
x = Perhaps ((:>) Prim Prim wX wY) -> Maybe ((:>) Prim Prim wX wY)
forall a. Perhaps a -> Maybe a
toMaybe (Perhaps ((:>) Prim Prim wX wY) -> Maybe ((:>) Prim Prim wX wY))
-> Perhaps ((:>) Prim Prim wX wY) -> Maybe ((:>) Prim Prim wX wY)
forall a b. (a -> b) -> a -> b
$ [Perhaps ((:>) Prim Prim wX wY)] -> Perhaps ((:>) Prim Prim wX wY)
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, MonadPlus m) =>
t (m a) -> m a
msum [(:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
CommuteFunction
speedyCommute (:>) Prim Prim wX wY
x,
                                (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
CommuteFunction
everythingElseCommute (:>) Prim Prim wX wY
x
                               ]

isSuperdir :: FileName -> FileName -> Bool
isSuperdir :: FileName -> FileName -> Bool
isSuperdir d1 :: FileName
d1 d2 :: FileName
d2 = [Char] -> [Char] -> Bool
isd (FileName -> [Char]
fn2fp FileName
d1) (FileName -> [Char]
fn2fp FileName
d2)
    where isd :: [Char] -> [Char] -> Bool
isd s1 :: [Char]
s1 s2 :: [Char]
s2 =
              [Char] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Char]
s2 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= [Char] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Char]
s1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 1 Bool -> Bool -> Bool
&& Int -> [Char] -> [Char]
forall a. Int -> [a] -> [a]
take ([Char] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Char]
s1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 1) [Char]
s2 [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
s1 [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ "/"

commuteFiledir :: CommuteFunction
commuteFiledir :: (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
commuteFiledir (FP f1 :: FileName
f1 p1 :: FilePatchType wX wZ
p1 :> FP f2 :: FileName
f2 p2 :: FilePatchType wZ wY
p2) =
  if FileName
f1 FileName -> FileName -> Bool
forall a. Eq a => a -> a -> Bool
/= FileName
f2 then (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded ( FileName -> FilePatchType wX Any -> Prim wX Any
forall wX wY. FileName -> FilePatchType wX wY -> Prim wX wY
FP FileName
f2 (FilePatchType wZ wY -> FilePatchType wX Any
forall (a :: * -> * -> *) wX wY wB wC. a wX wY -> a wB wC
unsafeCoerceP FilePatchType wZ wY
p2) Prim wX Any -> Prim Any wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> FileName -> FilePatchType Any wY -> Prim Any wY
forall wX wY. FileName -> FilePatchType wX wY -> Prim wX wY
FP FileName
f1 (FilePatchType wX wZ -> FilePatchType Any wY
forall (a :: * -> * -> *) wX wY wB wC. a wX wY -> a wB wC
unsafeCoerceP FilePatchType wX wZ
p1) )
  else FileName
-> (:>) FilePatchType FilePatchType wX wY
-> Perhaps ((:>) Prim Prim wX wY)
forall wX wY.
FileName
-> (:>) FilePatchType FilePatchType wX wY
-> Perhaps ((:>) Prim Prim wX wY)
commuteFP FileName
f1 (FilePatchType wX wZ
p1 FilePatchType wX wZ
-> FilePatchType wZ wY -> (:>) FilePatchType FilePatchType wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> FilePatchType wZ wY
p2)
commuteFiledir (DP d1 :: FileName
d1 p1 :: DirPatchType wX wZ
p1 :> DP d2 :: FileName
d2 p2 :: DirPatchType wZ wY
p2) =
  if Bool -> Bool
not (FileName -> FileName -> Bool
isInDirectory FileName
d1 FileName
d2 Bool -> Bool -> Bool
|| FileName -> FileName -> Bool
isInDirectory FileName
d2 FileName
d1) Bool -> Bool -> Bool
&& FileName
d1 FileName -> FileName -> Bool
forall a. Eq a => a -> a -> Bool
/= FileName
d2
  then (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded ( FileName -> DirPatchType wX Any -> Prim wX Any
forall wX wY. FileName -> DirPatchType wX wY -> Prim wX wY
DP FileName
d2 (DirPatchType wZ wY -> DirPatchType wX Any
forall (a :: * -> * -> *) wX wY wB wC. a wX wY -> a wB wC
unsafeCoerceP DirPatchType wZ wY
p2) Prim wX Any -> Prim Any wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> FileName -> DirPatchType Any wY -> Prim Any wY
forall wX wY. FileName -> DirPatchType wX wY -> Prim wX wY
DP FileName
d1 (DirPatchType wX wZ -> DirPatchType Any wY
forall (a :: * -> * -> *) wX wY wB wC. a wX wY -> a wB wC
unsafeCoerceP DirPatchType wX wZ
p1) )
  else Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
commuteFiledir (FP f :: FileName
f fp :: FilePatchType wX wZ
fp :> DP d :: FileName
d dp :: DirPatchType wZ wY
dp) =
    if Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ FileName -> FileName -> Bool
isInDirectory FileName
d FileName
f
    then (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded (FileName -> DirPatchType wX Any -> Prim wX Any
forall wX wY. FileName -> DirPatchType wX wY -> Prim wX wY
DP FileName
d (DirPatchType wZ wY -> DirPatchType wX Any
forall (a :: * -> * -> *) wX wY wB wC. a wX wY -> a wB wC
unsafeCoerceP DirPatchType wZ wY
dp) Prim wX Any -> Prim Any wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> FileName -> FilePatchType Any wY -> Prim Any wY
forall wX wY. FileName -> FilePatchType wX wY -> Prim wX wY
FP FileName
f (FilePatchType wX wZ -> FilePatchType Any wY
forall (a :: * -> * -> *) wX wY wB wC. a wX wY -> a wB wC
unsafeCoerceP FilePatchType wX wZ
fp))
    else Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed

commuteFiledir (FP f1 :: FileName
f1 p1 :: FilePatchType wX wZ
p1 :> Move d :: FileName
d d' :: FileName
d')
    | FileName
f1 FileName -> FileName -> Bool
forall a. Eq a => a -> a -> Bool
== FileName
d' = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
    | (FilePatchType wX wZ
p1 FilePatchType wX wZ -> FilePatchType wX wZ -> Bool
forall a. Eq a => a -> a -> Bool
== FilePatchType wX wZ
forall wX wY. FilePatchType wX wY
AddFile Bool -> Bool -> Bool
|| FilePatchType wX wZ
p1 FilePatchType wX wZ -> FilePatchType wX wZ -> Bool
forall a. Eq a => a -> a -> Bool
== FilePatchType wX wZ
forall wX wY. FilePatchType wX wY
RmFile) Bool -> Bool -> Bool
&& FileName
d FileName -> FileName -> Bool
forall a. Eq a => a -> a -> Bool
== FileName
f1 = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
    | Bool
otherwise = (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded (FileName -> FileName -> Prim wX Any
forall wX wY. FileName -> FileName -> Prim wX wY
Move FileName
d FileName
d' Prim wX Any -> Prim Any wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> FileName -> FilePatchType Any wY -> Prim Any wY
forall wX wY. FileName -> FilePatchType wX wY -> Prim wX wY
FP (FileName -> FileName -> FileName -> FileName
movedirfilename FileName
d FileName
d' FileName
f1) (FilePatchType wX wZ -> FilePatchType Any wY
forall (a :: * -> * -> *) wX wY wB wC. a wX wY -> a wB wC
unsafeCoerceP FilePatchType wX wZ
p1))
commuteFiledir (DP d1 :: FileName
d1 p1 :: DirPatchType wX wZ
p1 :> Move d :: FileName
d d' :: FileName
d')
    | FileName -> FileName -> Bool
isSuperdir FileName
d1 FileName
d' Bool -> Bool -> Bool
|| FileName -> FileName -> Bool
isSuperdir FileName
d1 FileName
d = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
    | FileName
d FileName -> FileName -> Bool
forall a. Eq a => a -> a -> Bool
== FileName
d1 = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed  -- The exact guard is p1 == AddDir && d == d1
                        -- but note d == d1 suffices because we know p1 != RmDir
                        -- (and hence p1 == AddDir) since patches must be sequential.
    | FileName
d1 FileName -> FileName -> Bool
forall a. Eq a => a -> a -> Bool
== FileName
d' = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
    | Bool
otherwise = (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded (FileName -> FileName -> Prim wX Any
forall wX wY. FileName -> FileName -> Prim wX wY
Move FileName
d FileName
d' Prim wX Any -> Prim Any wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> FileName -> DirPatchType Any wY -> Prim Any wY
forall wX wY. FileName -> DirPatchType wX wY -> Prim wX wY
DP (FileName -> FileName -> FileName -> FileName
movedirfilename FileName
d FileName
d' FileName
d1) (DirPatchType wX wZ -> DirPatchType Any wY
forall (a :: * -> * -> *) wX wY wB wC. a wX wY -> a wB wC
unsafeCoerceP DirPatchType wX wZ
p1))
commuteFiledir (Move f :: FileName
f f' :: FileName
f' :> Move d :: FileName
d d' :: FileName
d')
    | FileName
f FileName -> FileName -> Bool
forall a. Eq a => a -> a -> Bool
== FileName
d' Bool -> Bool -> Bool
|| FileName
f' FileName -> FileName -> Bool
forall a. Eq a => a -> a -> Bool
== FileName
d = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
    | FileName
f FileName -> FileName -> Bool
forall a. Eq a => a -> a -> Bool
== FileName
d Bool -> Bool -> Bool
|| FileName
f' FileName -> FileName -> Bool
forall a. Eq a => a -> a -> Bool
== FileName
d' = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
    | FileName
d FileName -> FileName -> Bool
`isSuperdir` FileName
f Bool -> Bool -> Bool
&& FileName
f' FileName -> FileName -> Bool
`isSuperdir` FileName
d' = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
    | Bool
otherwise =
        (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded (FileName -> FileName -> Prim wX Any
forall wX wY. FileName -> FileName -> Prim wX wY
Move (FileName -> FileName -> FileName -> FileName
movedirfilename FileName
f' FileName
f FileName
d) (FileName -> FileName -> FileName -> FileName
movedirfilename FileName
f' FileName
f FileName
d') Prim wX Any -> Prim Any wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:>
                   FileName -> FileName -> Prim Any wY
forall wX wY. FileName -> FileName -> Prim wX wY
Move (FileName -> FileName -> FileName -> FileName
movedirfilename FileName
d FileName
d' FileName
f) (FileName -> FileName -> FileName -> FileName
movedirfilename FileName
d FileName
d' FileName
f'))

commuteFiledir _ = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Unknown

type CommuteFunction = forall wX wY . (Prim :> Prim) wX wY -> Perhaps ((Prim :> Prim) wX wY)

commuteFilepatches :: CommuteFunction
commuteFilepatches :: (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
commuteFilepatches (FP f1 :: FileName
f1 p1 :: FilePatchType wX wZ
p1 :> FP f2 :: FileName
f2 p2 :: FilePatchType wZ wY
p2) | FileName
f1 FileName -> FileName -> Bool
forall a. Eq a => a -> a -> Bool
== FileName
f2 = FileName
-> (:>) FilePatchType FilePatchType wX wY
-> Perhaps ((:>) Prim Prim wX wY)
forall wX wY.
FileName
-> (:>) FilePatchType FilePatchType wX wY
-> Perhaps ((:>) Prim Prim wX wY)
commuteFP FileName
f1 (FilePatchType wX wZ
p1 FilePatchType wX wZ
-> FilePatchType wZ wY -> (:>) FilePatchType FilePatchType wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> FilePatchType wZ wY
p2)
commuteFilepatches _ = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Unknown

commuteFP :: FileName -> (FilePatchType :> FilePatchType) wX wY
          -> Perhaps ((Prim :> Prim) wX wY)
commuteFP :: FileName
-> (:>) FilePatchType FilePatchType wX wY
-> Perhaps ((:>) Prim Prim wX wY)
commuteFP f :: FileName
f (p1 :: FilePatchType wX wZ
p1 :> Hunk line1 :: Int
line1 [] []) =
    (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded (FileName -> FilePatchType wX Any -> Prim wX Any
forall wX wY. FileName -> FilePatchType wX wY -> Prim wX wY
FP FileName
f (Int -> [ByteString] -> [ByteString] -> FilePatchType wX Any
forall wX wY.
Int -> [ByteString] -> [ByteString] -> FilePatchType wX wY
Hunk Int
line1 [] []) Prim wX Any -> Prim Any wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> FileName -> FilePatchType Any wY -> Prim Any wY
forall wX wY. FileName -> FilePatchType wX wY -> Prim wX wY
FP FileName
f (FilePatchType wX wZ -> FilePatchType Any wY
forall (a :: * -> * -> *) wX wY wB wC. a wX wY -> a wB wC
unsafeCoerceP FilePatchType wX wZ
p1))
commuteFP f :: FileName
f (Hunk line1 :: Int
line1 [] [] :> p2 :: FilePatchType wZ wY
p2) =
    (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded (FileName -> FilePatchType wX Any -> Prim wX Any
forall wX wY. FileName -> FilePatchType wX wY -> Prim wX wY
FP FileName
f (FilePatchType wZ wY -> FilePatchType wX Any
forall (a :: * -> * -> *) wX wY wB wC. a wX wY -> a wB wC
unsafeCoerceP FilePatchType wZ wY
p2) Prim wX Any -> Prim Any wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> FileName -> FilePatchType Any wY -> Prim Any wY
forall wX wY. FileName -> FilePatchType wX wY -> Prim wX wY
FP FileName
f (Int -> [ByteString] -> [ByteString] -> FilePatchType Any wY
forall wX wY.
Int -> [ByteString] -> [ByteString] -> FilePatchType wX wY
Hunk Int
line1 [] []))
commuteFP f :: FileName
f (Hunk line1 :: Int
line1 old1 :: [ByteString]
old1 new1 :: [ByteString]
new1 :> Hunk line2 :: Int
line2 old2 :: [ByteString]
old2 new2 :: [ByteString]
new2) =
    case Int -> Int -> Int -> Int -> Int -> Int -> Maybe (Int, Int)
commuteHunkLines Int
line1 ([ByteString] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ByteString]
old1) ([ByteString] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ByteString]
new1) Int
line2 ([ByteString] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ByteString]
old2) ([ByteString] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ByteString]
new2) of
      Just (line2' :: Int
line2', line1' :: Int
line1') ->
        (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded (FileName -> FilePatchType wX Any -> Prim wX Any
forall wX wY. FileName -> FilePatchType wX wY -> Prim wX wY
FP FileName
f (Int -> [ByteString] -> [ByteString] -> FilePatchType wX Any
forall wX wY.
Int -> [ByteString] -> [ByteString] -> FilePatchType wX wY
Hunk Int
line2' [ByteString]
old2 [ByteString]
new2) Prim wX Any -> Prim Any wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:> FileName -> FilePatchType Any wY -> Prim Any wY
forall wX wY. FileName -> FilePatchType wX wY -> Prim wX wY
FP FileName
f (Int -> [ByteString] -> [ByteString] -> FilePatchType Any wY
forall wX wY.
Int -> [ByteString] -> [ByteString] -> FilePatchType wX wY
Hunk Int
line1' [ByteString]
old1 [ByteString]
new1))
      Nothing -> Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
commuteFP f :: FileName
f (Hunk line1 :: Int
line1 old1 :: [ByteString]
old1 new1 :: [ByteString]
new1 :> TokReplace t :: [Char]
t o :: [Char]
o n :: [Char]
n) =
    let po :: ByteString
po = [Char] -> ByteString
BC.pack [Char]
o; pn :: ByteString
pn = [Char] -> ByteString
BC.pack [Char]
n in
    case [Char]
-> ByteString -> ByteString -> [ByteString] -> Maybe [ByteString]
tryTokReplaces [Char]
t ByteString
po ByteString
pn [ByteString]
old1 of
    Nothing -> Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
    Just old1' :: [ByteString]
old1' ->
      case [Char]
-> ByteString -> ByteString -> [ByteString] -> Maybe [ByteString]
tryTokReplaces [Char]
t ByteString
po ByteString
pn [ByteString]
new1 of
        Nothing -> Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
        Just new1' :: [ByteString]
new1' -> (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded (FileName -> FilePatchType wX Any -> Prim wX Any
forall wX wY. FileName -> FilePatchType wX wY -> Prim wX wY
FP FileName
f ([Char] -> [Char] -> [Char] -> FilePatchType wX Any
forall wX wY. [Char] -> [Char] -> [Char] -> FilePatchType wX wY
TokReplace [Char]
t [Char]
o [Char]
n) Prim wX Any -> Prim Any wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:>
                                 FileName -> FilePatchType Any wY -> Prim Any wY
forall wX wY. FileName -> FilePatchType wX wY -> Prim wX wY
FP FileName
f (Int -> [ByteString] -> [ByteString] -> FilePatchType Any wY
forall wX wY.
Int -> [ByteString] -> [ByteString] -> FilePatchType wX wY
Hunk Int
line1 [ByteString]
old1' [ByteString]
new1'))
commuteFP f :: FileName
f (TokReplace t1 :: [Char]
t1 o1 :: [Char]
o1 n1 :: [Char]
n1 :> TokReplace t2 :: [Char]
t2 o2 :: [Char]
o2 n2 :: [Char]
n2)
    | [Char]
t1 [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
/= [Char]
t2 = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
    | [Char]
o1 [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
o2 = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
    | [Char]
n1 [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
o2 = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
    | [Char]
o1 [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
n2 = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
    | [Char]
n1 [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
n2 = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Failed
    | Bool
otherwise = (:>) Prim Prim wX wY -> Perhaps ((:>) Prim Prim wX wY)
forall a. a -> Perhaps a
Succeeded (FileName -> FilePatchType wX Any -> Prim wX Any
forall wX wY. FileName -> FilePatchType wX wY -> Prim wX wY
FP FileName
f ([Char] -> [Char] -> [Char] -> FilePatchType wX Any
forall wX wY. [Char] -> [Char] -> [Char] -> FilePatchType wX wY
TokReplace [Char]
t2 [Char]
o2 [Char]
n2) Prim wX Any -> Prim Any wY -> (:>) Prim Prim wX wY
forall (a1 :: * -> * -> *) (a2 :: * -> * -> *) wX wY wZ.
a1 wX wZ -> a2 wZ wY -> (:>) a1 a2 wX wY
:>
                             FileName -> FilePatchType Any wY -> Prim Any wY
forall wX wY. FileName -> FilePatchType wX wY -> Prim wX wY
FP FileName
f ([Char] -> [Char] -> [Char] -> FilePatchType Any wY
forall wX wY. [Char] -> [Char] -> [Char] -> FilePatchType wX wY
TokReplace [Char]
t1 [Char]
o1 [Char]
n1))
commuteFP _ _ = Perhaps ((:>) Prim Prim wX wY)
forall a. Perhaps a
Unknown

commuteHunkLines :: Int -> Int -> Int -> Int -> Int -> Int
                 -> Maybe (Int, Int)
commuteHunkLines :: Int -> Int -> Int -> Int -> Int -> Int -> Maybe (Int, Int)
commuteHunkLines line1 :: Int
line1 len_old1 :: Int
len_old1 len_new1 :: Int
len_new1 line2 :: Int
line2 len_old2 :: Int
len_old2 len_new2 :: Int
len_new2
  | Int
line1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len_new1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
line2  = (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
line2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
len_new1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len_old1, Int
line1)
  | Int
line2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len_old2 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
line1  = (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
line2, Int
line1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len_new2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
len_old2)
  | Int
len_old2 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= 0
  , Int
len_old1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= 0
  , Int
len_new2 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= 0
  , Int
len_new1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= 0
  , Int
line1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len_new1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
line2 = (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
line2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
len_new1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len_old1, Int
line1)
  | Int
len_old2 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= 0
  , Int
len_old1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= 0
  , Int
len_new2 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= 0
  , Int
len_new1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= 0
  , Int
line2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len_old2 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
line1 = (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
line2, Int
line1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len_new2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
len_old2)
  | Bool
otherwise                 = Maybe (Int, Int)
forall a. Maybe a
Nothing

tryTokReplaces :: String -> B.ByteString -> B.ByteString
               -> [B.ByteString] -> Maybe [B.ByteString]
tryTokReplaces :: [Char]
-> ByteString -> ByteString -> [ByteString] -> Maybe [ByteString]
tryTokReplaces t :: [Char]
t o :: ByteString
o n :: ByteString
n = (ByteString -> Maybe ByteString)
-> [ByteString] -> Maybe [ByteString]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ([Char]
-> ByteString -> ByteString -> ByteString -> Maybe ByteString
tryTokReplace [Char]
t ByteString
o ByteString
n)