Skip to content

Commit 0df31d2

Browse files
committed
Dump the project JSON respecting field order.
1 parent e978207 commit 0df31d2

File tree

2 files changed

+36
-19
lines changed

2 files changed

+36
-19
lines changed

src/Stack/ConfigCmd.hs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ import Stack.Prelude
4848
import Data.Coerce (coerce)
4949
import Pantry.Internal.AesonExtended
5050
(ToJSON(..), FromJSON, (.=), WithJSONWarnings (WithJSONWarnings), object)
51-
import Data.Aeson.Encode.Pretty (encodePretty)
51+
import Data.Aeson.Encode.Pretty (encodePretty, encodePretty', confCompare)
52+
import qualified Data.Aeson.Encode.Pretty as Aeson (defConfig)
5253
import qualified Data.Aeson.Key as Key
5354
import Data.Aeson.KeyMap (KeyMap)
5455
import qualified Data.Aeson.KeyMap as KeyMap
@@ -128,10 +129,16 @@ configCmdSetScope (ConfigCmdSetSystemGhc scope _) = scope
128129
configCmdSetScope (ConfigCmdSetInstallGhc scope _) = scope
129130

130131
encodeDumpProject :: RawYaml -> ConfigDumpFormat -> Project -> ByteString
131-
encodeDumpProject _ ConfigDumpJson = toStrictBytes . encodePretty
132-
encodeDumpProject rawConfig ConfigDumpYaml = \p -> let e = Yaml.encode p in
132+
encodeDumpProject rawConfig ConfigDumpYaml p = let e = Yaml.encode p in
133133
Yaml.decodeEither' e & either (const e) (\(d :: KeyMap Yaml.Value) ->
134134
either (const e) encodeUtf8 (cfgRedress rawConfig d ""))
135+
encodeDumpProject rawConfig ConfigDumpJson p = let e = Yaml.encode p in
136+
Yaml.decodeEither' e & either (const e) (\(d :: KeyMap Yaml.Value) ->
137+
toStrictBytes $ encodePretty' (Aeson.defConfig{confCompare = cfgKeyCompare rawConfig d ""}) d)
138+
139+
cfgKeyCompare :: RawYaml -> KeyMap Yaml.Value -> Text -> (Text -> Text -> Ordering)
140+
cfgKeyCompare (yamlLines -> configLines) (fmap Key.toText . KeyMap.keys -> keys) cmdKey =
141+
compareInOrder configLines (coerce keys) (coerce cmdKey)
135142

136143
encodeDumpStackBy :: ToJSON a => (Config -> a) -> ConfigCmdDumpStack -> (Config -> ByteString)
137144
encodeDumpStackBy f (ConfigCmdDumpStack _ ConfigDumpYaml) = Yaml.encode . f

src/Stack/YamlUpdate.hs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
--
1515
-- Use yamlLines to transform 'RawYaml' to ['RawYamlLine'].
1616
module Stack.YamlUpdate
17-
( encodeInOrder
17+
( compareInOrder
18+
, encodeInOrder
1819
, redress
1920
, mkRaw
2021
, unmkRaw
@@ -131,28 +132,37 @@ fetchInRange YamlLines{blanks, wholeLineComments, partLineComments} p =
131132
ps = filterLineNumber partLineComments
132133
in (ps, L.sortOn commentLineNumber $ ls ++ cs)
133134

135+
-- | From an ordered list of keys constructs a comparison respecting that order.
136+
preservingCompare :: Ord a => Map Text a -> [Text] -> Text -> Text -> Text -> Ordering
137+
preservingCompare ixMap keysFound k x y =
138+
-- If updating then preserve order but if inserting then put last.
139+
if | k `L.elem` keysFound -> Map.lookup x ixMap `compare` Map.lookup y ixMap
140+
| k == x, k == y -> EQ
141+
| k == x -> GT
142+
| k == y -> LT
143+
| otherwise -> Map.lookup x ixMap `compare` Map.lookup y ixMap
144+
145+
-- | From an ordered list of YAML lines constructs a comparison respecting that order.
146+
compareInOrder :: [RawYamlLine]
147+
-> [YamlKey]
148+
-> YamlKey
149+
-> (Text -> Text -> Ordering)
150+
compareInOrder rawLines keysFound (YamlKey k) =
151+
let keyLine = findKeyLine rawLines
152+
ixMap = Map.fromList $ (\yk@(YamlKey x) -> (x, keyLine yk)) <$> keysFound
153+
154+
in preservingCompare ixMap (coerce <$> keysFound) k
155+
134156
-- | Uses the order of the keys in the original to preserve the order in the
135157
-- update except that inserting a key orders it last.
136158
encodeInOrder :: [RawYamlLine]
137159
-> [YamlKey]
138160
-> YamlKey
139161
-> Yaml.Object
140162
-> Either UnicodeException RawYaml
141-
encodeInOrder rawLines keysFound upsertKey@(YamlKey k) yObject =
142-
let keyLine = findKeyLine rawLines
143-
ixMap = Map.fromList $ (\yk@(YamlKey x) -> (x, keyLine yk)) <$> keysFound
144-
preservingCompare x y =
145-
-- If updating then preserve order but if inserting then put last.
146-
if | upsertKey `L.elem` keysFound ->
147-
Map.lookup x ixMap `compare` Map.lookup y ixMap
148-
| k == x, k == y -> EQ
149-
| k == x -> GT
150-
| k == y -> LT
151-
| otherwise -> Map.lookup x ixMap `compare` Map.lookup y ixMap
152-
153-
keyCmp = Yaml.setConfCompare preservingCompare Yaml.defConfig
154-
155-
in RawYaml <$> decodeUtf8' (Yaml.encodePretty keyCmp yObject)
163+
encodeInOrder rawLines keysFound key yObject =
164+
let keyCmp = Yaml.setConfCompare (compareInOrder rawLines keysFound key) Yaml.defConfig
165+
in RawYaml <$> decodeUtf8' (Yaml.encodePretty keyCmp yObject)
156166

157167
endSentinel :: Text
158168
endSentinel =

0 commit comments

Comments
 (0)