|
| 1 | +{-# LANGUAGE ConstraintKinds #-} |
| 2 | +{-# LANGUAGE DataKinds #-} |
| 3 | +{-# LANGUAGE FunctionalDependencies #-} |
| 4 | +{-# LANGUAGE OverloadedStrings #-} |
| 5 | +{-# LANGUAGE TypeApplications #-} |
| 6 | +module HaskellCI.Config.Diff where |
| 7 | + |
| 8 | +import HaskellCI.Prelude |
| 9 | + |
| 10 | +import Distribution.Fields.Field (FieldName) |
| 11 | +import Distribution.Utils.ShortText (fromShortText) |
| 12 | + |
| 13 | +import qualified Distribution.Compat.Lens as L |
| 14 | +import qualified Distribution.Compat.CharParsing as C |
| 15 | +import qualified Distribution.FieldGrammar as C |
| 16 | +import qualified Distribution.Parsec as C |
| 17 | +import qualified Distribution.Pretty as C |
| 18 | +import qualified Text.PrettyPrint as PP |
| 19 | + |
| 20 | +import HaskellCI.OptionsGrammar |
| 21 | +import HaskellCI.Config.Empty (runEG) |
| 22 | + |
| 23 | +data ShowDiffOptions = ShowAllOptions | ShowChangedOptions |
| 24 | + deriving (Eq, Show, Generic, Binary) |
| 25 | + |
| 26 | +instance C.Parsec ShowDiffOptions where |
| 27 | + parsec = ShowAllOptions <$ C.string "all" |
| 28 | + <|> ShowChangedOptions <$ C.string "changed" |
| 29 | + |
| 30 | +instance C.Pretty ShowDiffOptions where |
| 31 | + pretty ShowAllOptions = PP.text "all" |
| 32 | + pretty ShowChangedOptions = PP.text "changed" |
| 33 | + |
| 34 | +data DiffConfig = DiffConfig |
| 35 | + { diffShowOptions :: ShowDiffOptions |
| 36 | + , diffShowOld :: Bool |
| 37 | + } deriving (Show, Generic, Binary) |
| 38 | + |
| 39 | +diffConfigGrammar |
| 40 | + :: ( OptionsGrammar c g |
| 41 | + , Applicative (g DiffConfig) |
| 42 | + , c (Identity ShowDiffOptions)) |
| 43 | + => g DiffConfig DiffConfig |
| 44 | +diffConfigGrammar = DiffConfig |
| 45 | + <$> C.optionalFieldDef "diff-show-options" (field @"diffShowOptions") ShowChangedOptions |
| 46 | + ^^^ help "Which fields to show" |
| 47 | + <*> C.booleanFieldDef "diff-show-old" (field @"diffShowOld") False |
| 48 | + ^^^ help "Show the old values for every field" |
| 49 | + |
| 50 | +defaultDiffConfig :: DiffConfig |
| 51 | +defaultDiffConfig = case runEG diffConfigGrammar of |
| 52 | + Left xs -> error $ "Required fields: " ++ show xs |
| 53 | + Right x -> x |
| 54 | + |
| 55 | +newtype DiffOptions s a = |
| 56 | + DiffOptions { runDiffOptions :: (s, s) -> DiffConfig -> [String] } |
| 57 | + deriving Functor |
| 58 | + |
| 59 | +instance Applicative (DiffOptions s) where |
| 60 | + pure _ = DiffOptions $ \_ _ -> [] |
| 61 | + DiffOptions f <*> DiffOptions x = DiffOptions (f <> x) |
| 62 | + |
| 63 | +diffConfigs :: DiffConfig -> DiffOptions a a -> a -> a -> [String] |
| 64 | +diffConfigs config grammar oldVal newVal = |
| 65 | + runDiffOptions grammar (oldVal, newVal) config |
| 66 | + |
| 67 | +diffUnique |
| 68 | + :: Eq b |
| 69 | + => (a -> b) |
| 70 | + -> (a -> String) |
| 71 | + -> FieldName |
| 72 | + -> L.ALens' s a |
| 73 | + -> (s, s) |
| 74 | + -> DiffConfig |
| 75 | + -> [String] |
| 76 | +diffUnique project render fn lens (diffOld, diffNew) opts = |
| 77 | + case diffShowOptions opts of |
| 78 | + ShowChangedOptions | notEqual -> [] |
| 79 | + ShowAllOptions | notEqual -> newLine |
| 80 | + _ -> oldLine ++ newLine |
| 81 | + where |
| 82 | + notEqual = project oldValue == project newValue |
| 83 | + oldValue = L.aview lens $ diffOld |
| 84 | + newValue = L.aview lens $ diffNew |
| 85 | + |
| 86 | + oldLine |
| 87 | + | diffShowOld opts = ["-- " ++ fromUTF8BS fn ++ ": " ++ render oldValue] |
| 88 | + | otherwise = [] |
| 89 | + |
| 90 | + newLine = [ fromUTF8BS fn ++ ": " ++ render newValue, ""] |
| 91 | + |
| 92 | + |
| 93 | +instance C.FieldGrammar C.Pretty DiffOptions where |
| 94 | + blurFieldGrammar lens (DiffOptions diff) = |
| 95 | + DiffOptions $ diff . bimap (L.aview lens) (L.aview lens) |
| 96 | + |
| 97 | + uniqueFieldAla fn pack valueLens = DiffOptions $ |
| 98 | + diffUnique (C.prettyShow . pack) (C.prettyShow . pack) fn valueLens |
| 99 | + |
| 100 | + booleanFieldDef fn valueLens _ = DiffOptions $ |
| 101 | + diffUnique id C.prettyShow fn valueLens |
| 102 | + |
| 103 | + optionalFieldAla fn pack valueLens = DiffOptions $ |
| 104 | + diffUnique toPretty toPretty fn valueLens |
| 105 | + where |
| 106 | + toPretty = maybe "" (C.prettyShow . pack) |
| 107 | + |
| 108 | + optionalFieldDefAla fn pack valueLens _ = DiffOptions $ |
| 109 | + diffUnique id (C.prettyShow . pack) fn valueLens |
| 110 | + |
| 111 | + monoidalFieldAla fn pack valueLens = DiffOptions $ |
| 112 | + diffUnique (C.prettyShow . pack) (C.prettyShow . pack) fn valueLens |
| 113 | + |
| 114 | + freeTextField fn valueLens = DiffOptions $ |
| 115 | + diffUnique id (fromMaybe "") fn valueLens |
| 116 | + |
| 117 | + freeTextFieldDef fn valueLens = DiffOptions $ |
| 118 | + diffUnique id id fn valueLens |
| 119 | + |
| 120 | + freeTextFieldDefST fn valueLens = DiffOptions $ |
| 121 | + diffUnique id fromShortText fn valueLens |
| 122 | + |
| 123 | + prefixedFields _ _ = pure [] |
| 124 | + knownField _ = pure () |
| 125 | + deprecatedSince _ _ = id |
| 126 | + availableSince _ _ = id |
| 127 | + removedIn _ _ = id |
| 128 | + hiddenField = id |
| 129 | + |
| 130 | +instance OptionsGrammar C.Pretty DiffOptions where |
| 131 | + metahelp _ = help |
| 132 | + |
| 133 | + help h (DiffOptions xs) = DiffOptions $ \vals config -> |
| 134 | + case xs vals config of |
| 135 | + [] -> [] |
| 136 | + diffString -> ("-- " ++ h) : diffString |
0 commit comments