2015-01-27 21:38:06 +00:00
|
|
|
{- git-annex repository differences
|
|
|
|
-
|
|
|
|
- Copyright 2015 Joey Hess <id@joeyh.name>
|
|
|
|
-
|
2019-03-13 19:48:14 +00:00
|
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
2015-01-27 21:38:06 +00:00
|
|
|
-}
|
|
|
|
|
2019-11-27 20:54:11 +00:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
|
2015-01-27 21:38:06 +00:00
|
|
|
module Types.Difference (
|
|
|
|
Difference(..),
|
|
|
|
Differences(..),
|
2015-01-28 17:55:46 +00:00
|
|
|
readDifferences,
|
2015-06-11 20:25:37 +00:00
|
|
|
showDifferences,
|
2015-01-27 21:38:06 +00:00
|
|
|
getDifferences,
|
|
|
|
differenceConfigKey,
|
|
|
|
differenceConfigVal,
|
|
|
|
hasDifference,
|
2015-01-28 22:17:10 +00:00
|
|
|
listDifferences,
|
2015-01-27 21:38:06 +00:00
|
|
|
) where
|
|
|
|
|
2015-01-28 17:55:46 +00:00
|
|
|
import Utility.PartialPrelude
|
2015-01-27 21:38:06 +00:00
|
|
|
import qualified Git
|
|
|
|
import qualified Git.Config
|
2019-12-02 14:57:09 +00:00
|
|
|
import Git.Types
|
2015-01-27 21:38:06 +00:00
|
|
|
|
|
|
|
import Data.Maybe
|
|
|
|
import Data.Monoid
|
2019-11-27 20:54:11 +00:00
|
|
|
import qualified Data.ByteString as B
|
2015-06-11 20:25:37 +00:00
|
|
|
import qualified Data.Set as S
|
Fix build with ghc 8.4+, which broke due to the Semigroup Monoid change
https://prime.haskell.org/wiki/Libraries/Proposals/SemigroupMonoid
I am not happy with the fragile pile of CPP boilerplate required to support
ghc back to 7.0, which git-annex still targets for both the android build
and the standalone build targeting old linux kernels. It makes me unlikely
to want to use Semigroup more in git-annex, because the benefit of the
abstraction is swamped by the ugliness. I actually considered ripping out
all the Semigroup instances, but some are needed to use
optparse-applicative.
The problem, I think, is they made this transaction on too fast a timeline.
(Although ironically, work on it started in 2015 or earlier!)
In particular, Debian oldstable is not out of security support, and it's
not possible to follow the simpler workarounds documented on the wiki and
have it build on oldstable (because the semigroups package in it is too
old).
I have only tested this build with ghc 8.2.2, not the newer and older
versions that branches of the CPP support. So there could be typoes, we'll
see.
This commit was sponsored by Brock Spratlen on Patreon.
2018-05-30 16:28:43 +00:00
|
|
|
import qualified Data.Semigroup as Sem
|
|
|
|
import Prelude
|
2015-01-27 21:38:06 +00:00
|
|
|
|
|
|
|
-- Describes differences from the v5 repository format.
|
|
|
|
--
|
2015-01-28 17:47:41 +00:00
|
|
|
-- The serialization is stored in difference.log, so avoid changes that
|
2023-03-14 02:39:16 +00:00
|
|
|
-- would break compatibility.
|
2015-01-27 21:38:06 +00:00
|
|
|
--
|
2023-03-14 02:39:16 +00:00
|
|
|
-- Not breaking compatibility is why a list of Differences is used, rather
|
2015-06-11 20:25:37 +00:00
|
|
|
-- than a record type. With a record type, adding a new field for some future
|
2015-01-27 21:38:06 +00:00
|
|
|
-- difference would serialize to a value that an older version could not
|
|
|
|
-- parse, even if that new field was not used. With the Differences list,
|
|
|
|
-- old versions can still parse it, unless the new Difference constructor
|
|
|
|
-- is used.
|
2015-01-28 17:47:41 +00:00
|
|
|
--
|
|
|
|
-- The constructors intentionally do not have parameters; this is to
|
|
|
|
-- ensure that any Difference that can be expressed is supported.
|
|
|
|
-- So, a new repository version would be Version6, rather than Version Int.
|
2015-01-27 21:38:06 +00:00
|
|
|
data Difference
|
2015-01-28 17:47:41 +00:00
|
|
|
= ObjectHashLower
|
|
|
|
| OneLevelObjectHash
|
|
|
|
| OneLevelBranchHash
|
2015-06-11 20:25:37 +00:00
|
|
|
deriving (Show, Read, Eq, Ord, Enum, Bounded)
|
2015-01-27 21:38:06 +00:00
|
|
|
|
2015-06-11 20:25:37 +00:00
|
|
|
-- This type is used internally for efficient checking for differences,
|
|
|
|
-- but converted to S.Set Difference for serialization.
|
2015-01-27 21:38:06 +00:00
|
|
|
data Differences
|
2015-06-11 20:25:37 +00:00
|
|
|
= Differences
|
|
|
|
{ objectHashLower :: Bool
|
|
|
|
, oneLevelObjectHash :: Bool
|
|
|
|
, oneLevelBranchHash :: Bool
|
|
|
|
}
|
2015-01-27 21:38:06 +00:00
|
|
|
| UnknownDifferences
|
|
|
|
|
2015-06-11 20:25:37 +00:00
|
|
|
-- UnknownDifferences cannot be equal
|
2015-01-27 21:38:06 +00:00
|
|
|
instance Eq Differences where
|
2015-06-11 20:25:37 +00:00
|
|
|
UnknownDifferences == _ = False
|
|
|
|
_ == UnknownDifferences = False
|
|
|
|
a == b = all (\f -> f a == f b)
|
|
|
|
[ objectHashLower
|
|
|
|
, oneLevelObjectHash
|
|
|
|
, oneLevelBranchHash
|
|
|
|
]
|
2015-01-27 21:38:06 +00:00
|
|
|
|
Fix build with ghc 8.4+, which broke due to the Semigroup Monoid change
https://prime.haskell.org/wiki/Libraries/Proposals/SemigroupMonoid
I am not happy with the fragile pile of CPP boilerplate required to support
ghc back to 7.0, which git-annex still targets for both the android build
and the standalone build targeting old linux kernels. It makes me unlikely
to want to use Semigroup more in git-annex, because the benefit of the
abstraction is swamped by the ugliness. I actually considered ripping out
all the Semigroup instances, but some are needed to use
optparse-applicative.
The problem, I think, is they made this transaction on too fast a timeline.
(Although ironically, work on it started in 2015 or earlier!)
In particular, Debian oldstable is not out of security support, and it's
not possible to follow the simpler workarounds documented on the wiki and
have it build on oldstable (because the semigroups package in it is too
old).
I have only tested this build with ghc 8.2.2, not the newer and older
versions that branches of the CPP support. So there could be typoes, we'll
see.
This commit was sponsored by Brock Spratlen on Patreon.
2018-05-30 16:28:43 +00:00
|
|
|
appendDifferences :: Differences -> Differences -> Differences
|
|
|
|
appendDifferences a@(Differences {}) b@(Differences {}) = a
|
|
|
|
{ objectHashLower = objectHashLower a || objectHashLower b
|
|
|
|
, oneLevelObjectHash = oneLevelObjectHash a || oneLevelObjectHash b
|
|
|
|
, oneLevelBranchHash = oneLevelBranchHash a || oneLevelBranchHash b
|
|
|
|
}
|
|
|
|
appendDifferences _ _ = UnknownDifferences
|
|
|
|
|
|
|
|
instance Sem.Semigroup Differences where
|
|
|
|
(<>) = appendDifferences
|
|
|
|
|
2015-01-27 21:38:06 +00:00
|
|
|
instance Monoid Differences where
|
2015-06-11 20:25:37 +00:00
|
|
|
mempty = Differences False False False
|
2015-01-27 21:38:06 +00:00
|
|
|
|
2015-01-28 17:55:46 +00:00
|
|
|
readDifferences :: String -> Differences
|
2015-06-11 20:25:37 +00:00
|
|
|
readDifferences = maybe UnknownDifferences mkDifferences . readish
|
|
|
|
|
|
|
|
showDifferences :: Differences -> String
|
|
|
|
showDifferences = show . S.fromList . listDifferences
|
2015-01-28 17:55:46 +00:00
|
|
|
|
2015-01-27 21:38:06 +00:00
|
|
|
getDifferences :: Git.Repo -> Differences
|
2015-06-11 20:25:37 +00:00
|
|
|
getDifferences r = mkDifferences $ S.fromList $
|
2015-04-11 04:10:34 +00:00
|
|
|
mapMaybe getmaybe [minBound .. maxBound]
|
2015-01-27 21:38:06 +00:00
|
|
|
where
|
2019-12-20 19:01:34 +00:00
|
|
|
getmaybe d = case Git.Config.isTrueFalse' =<< Git.Config.getMaybe (differenceConfigKey d) r of
|
2015-01-28 17:47:41 +00:00
|
|
|
Just True -> Just d
|
|
|
|
_ -> Nothing
|
2015-01-27 21:38:06 +00:00
|
|
|
|
2019-12-02 14:57:09 +00:00
|
|
|
differenceConfigKey :: Difference -> ConfigKey
|
2015-01-28 17:47:41 +00:00
|
|
|
differenceConfigKey ObjectHashLower = tunable "objecthashlower"
|
|
|
|
differenceConfigKey OneLevelObjectHash = tunable "objecthash1"
|
|
|
|
differenceConfigKey OneLevelBranchHash = tunable "branchhash1"
|
2015-01-27 21:38:06 +00:00
|
|
|
|
|
|
|
differenceConfigVal :: Difference -> String
|
2015-01-28 17:47:41 +00:00
|
|
|
differenceConfigVal _ = Git.Config.boolConfig True
|
2015-01-27 21:38:06 +00:00
|
|
|
|
2019-12-02 14:57:09 +00:00
|
|
|
tunable :: B.ByteString -> ConfigKey
|
|
|
|
tunable k = ConfigKey ("annex.tune." <> k)
|
2015-01-27 21:38:06 +00:00
|
|
|
|
2015-01-28 22:17:10 +00:00
|
|
|
hasDifference :: Difference -> Differences -> Bool
|
2015-01-27 21:38:06 +00:00
|
|
|
hasDifference _ UnknownDifferences = False
|
2015-06-11 20:25:37 +00:00
|
|
|
hasDifference ObjectHashLower ds = objectHashLower ds
|
|
|
|
hasDifference OneLevelObjectHash ds = oneLevelObjectHash ds
|
|
|
|
hasDifference OneLevelBranchHash ds = oneLevelBranchHash ds
|
2015-01-28 22:17:10 +00:00
|
|
|
|
|
|
|
listDifferences :: Differences -> [Difference]
|
2015-06-11 20:25:37 +00:00
|
|
|
listDifferences d@(Differences {}) = map snd $
|
|
|
|
filter (\(f, _) -> f d)
|
|
|
|
[ (objectHashLower, ObjectHashLower)
|
|
|
|
, (oneLevelObjectHash, OneLevelObjectHash)
|
|
|
|
, (oneLevelBranchHash, OneLevelBranchHash)
|
|
|
|
]
|
2015-01-28 22:17:10 +00:00
|
|
|
listDifferences UnknownDifferences = []
|
2015-06-11 20:25:37 +00:00
|
|
|
|
|
|
|
mkDifferences :: S.Set Difference -> Differences
|
|
|
|
mkDifferences s = Differences
|
|
|
|
{ objectHashLower = check ObjectHashLower
|
|
|
|
, oneLevelObjectHash = check OneLevelObjectHash
|
|
|
|
, oneLevelBranchHash = check OneLevelBranchHash
|
|
|
|
}
|
|
|
|
where
|
|
|
|
check f = f `S.member` s
|