Unserializable default field is a default field which will be serialized
only if it's value differs from the default one.

This field is introduced in order to fix a bug of inconsistency between
haskell and python config modules which leads to inconsistent config
after ganeti updgrade.

Signed-off-by: Oleg Ponomarev <[email protected]>
---
 src/Ganeti/THH.hs | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/Ganeti/THH.hs b/src/Ganeti/THH.hs
index fd7857e..7323add 100644
--- a/src/Ganeti/THH.hs
+++ b/src/Ganeti/THH.hs
@@ -61,6 +61,7 @@ module Ganeti.THH ( declareSADT
                   , andRestArguments
                   , withDoc
                   , defaultField
+                  , unserializableDefaultField
                   , presentInForthcoming
                   , optionalField
                   , optionalNullSerField
@@ -186,6 +187,9 @@ data Field = Field { fieldName        :: String
                      -- ^ a list of extra keys added by 'fieldShow'
                    , fieldDefault     :: Maybe (Q Exp)
                      -- ^ an optional default value of type @t@
+                   , fieldSerializeDefault :: Bool
+                     -- ^ whether not presented default value will be
+                     -- serialized
                    , fieldConstr      :: Maybe String
                    , fieldIsOptional  :: OptionalType
                      -- ^ determines if a field is optional, and if yes,
@@ -203,6 +207,7 @@ simpleField fname ftype =
         , fieldShow        = Nothing
         , fieldExtraKeys   = []
         , fieldDefault     = Nothing
+        , fieldSerializeDefault = True
         , fieldConstr      = Nothing
         , fieldIsOptional  = NotOptional
         , fieldDoc         = ""
@@ -218,6 +223,7 @@ andRestArguments fname =
         , fieldShow        = Nothing
         , fieldExtraKeys   = []
         , fieldDefault     = Nothing
+        , fieldSerializeDefault = True
         , fieldConstr      = Nothing
         , fieldIsOptional  = AndRestArguments
         , fieldDoc         = ""
@@ -237,6 +243,13 @@ renameField constrName field = field { fieldConstr = Just 
constrName }
 defaultField :: Q Exp -> Field -> Field
 defaultField defval field = field { fieldDefault = Just defval }
 
+-- | A defaultField which will be serialized only if it's value differs from
+-- a default value.
+unserializableDefaultField :: Q Exp -> Field -> Field
+unserializableDefaultField defval field =
+  field { fieldDefault = Just defval
+        , fieldSerializeDefault = False }
+
 -- | Mark a field as present in the forthcoming variant.
 presentInForthcoming :: Field -> Field
 presentInForthcoming field = field { fieldPresentInForthcoming = True }
@@ -1236,7 +1249,14 @@ saveObjectField fvar field = do
                                    Nothing -> [( $nameE, JSON.JSNull )]
                                    Just v  -> $(formatCode [| v |])
                               |]
-    NotOptional ->            formatCode fvarE
+    NotOptional -> case (fieldDefault field, fieldSerializeDefault field) of
+                     (Just v, False) -> [| if $v /= $fvarE
+                                             then $(formatCode fvarE)
+                                             else [] |]
+                     -- If a default value exists and we shouldn't serialize
+                     -- default fields - serialize only if the value differs
+                     -- from the default one.
+                     _ -> formatCode fvarE
     AndRestArguments -> [| M.toList $(varE fvar) |]
   where nameE = stringE (fieldName field)
         fvarE = varE fvar
-- 
2.6.0.rc2.230.g3dd15c0

Reply via email to