reorganize numcopies code (no behavior changes)

Move stuff into Logs.NumCopies. Add a NumCopies newtype.

Better names for various serialization classes that are specific to one
thing or another.
This commit is contained in:
Joey Hess 2014-01-21 16:08:19 -04:00
parent e38a21a768
commit b40df4f0d0
20 changed files with 137 additions and 98 deletions

View file

@ -56,6 +56,7 @@ import Types.Group
import Types.Messages import Types.Messages
import Types.UUID import Types.UUID
import Types.FileMatcher import Types.FileMatcher
import Types.NumCopies
import qualified Utility.Matcher import qualified Utility.Matcher
import qualified Data.Map as M import qualified Data.Map as M
import qualified Data.Set as S import qualified Data.Set as S
@ -94,7 +95,7 @@ data AnnexState = AnnexState
, checkattrhandle :: Maybe CheckAttrHandle , checkattrhandle :: Maybe CheckAttrHandle
, checkignorehandle :: Maybe (Maybe CheckIgnoreHandle) , checkignorehandle :: Maybe (Maybe CheckIgnoreHandle)
, forcebackend :: Maybe String , forcebackend :: Maybe String
, globalnumcopies :: Maybe Int , globalnumcopies :: Maybe NumCopies
, limit :: Matcher (MatchInfo -> Annex Bool) , limit :: Matcher (MatchInfo -> Annex Bool)
, uuidmap :: Maybe UUIDMap , uuidmap :: Maybe UUIDMap
, preferredcontentmap :: Maybe PreferredContentMap , preferredcontentmap :: Maybe PreferredContentMap

View file

@ -9,6 +9,7 @@ module Annex.Drop where
import Common.Annex import Common.Annex
import Logs.Trust import Logs.Trust
import Logs.NumCopies
import Types.Remote (uuid) import Types.Remote (uuid)
import qualified Remote import qualified Remote
import qualified Command.Drop import qualified Command.Drop
@ -59,8 +60,9 @@ handleDropsFrom locs rs reason fromhere key (Just afile) knownpresentremote runn
where where
getcopies fs = do getcopies fs = do
(untrusted, have) <- trustPartition UnTrusted locs (untrusted, have) <- trustPartition UnTrusted locs
numcopies <- maximum <$> mapM (getNumCopies <=< numCopies) fs numcopies <- maximum
return (length have, numcopies, S.fromList untrusted) <$> mapM (getNumCopies <=< getFileNumCopies) fs
return (NumCopies (length have), numcopies, S.fromList untrusted)
{- Check that we have enough copies still to drop the content. {- Check that we have enough copies still to drop the content.
- When the remote being dropped from is untrusted, it was not - When the remote being dropped from is untrusted, it was not
@ -72,7 +74,7 @@ handleDropsFrom locs rs reason fromhere key (Just afile) knownpresentremote runn
| otherwise = have > numcopies | otherwise = have > numcopies
decrcopies (have, numcopies, untrusted) Nothing = decrcopies (have, numcopies, untrusted) Nothing =
(have - 1, numcopies, untrusted) (NumCopies (fromNumCopies have - 1), numcopies, untrusted)
decrcopies v@(_have, _numcopies, untrusted) (Just u) decrcopies v@(_have, _numcopies, untrusted) (Just u)
| S.member u untrusted = v | S.member u untrusted = v
| otherwise = decrcopies v Nothing | otherwise = decrcopies v Nothing
@ -92,7 +94,7 @@ handleDropsFrom locs rs reason fromhere key (Just afile) knownpresentremote runn
[ "dropped" [ "dropped"
, afile , afile
, "(from " ++ maybe "here" show u ++ ")" , "(from " ++ maybe "here" show u ++ ")"
, "(copies now " ++ show (have - 1) ++ ")" , "(copies now " ++ show (fromNumCopies have - 1) ++ ")"
, ": " ++ reason , ": " ++ reason
] ]
return $ decrcopies n u return $ decrcopies n u

View file

@ -60,7 +60,7 @@ configFilesActions =
, (remoteLog, void $ liftAnnex remoteListRefresh) , (remoteLog, void $ liftAnnex remoteListRefresh)
, (trustLog, void $ liftAnnex trustMapLoad) , (trustLog, void $ liftAnnex trustMapLoad)
, (groupLog, void $ liftAnnex groupMapLoad) , (groupLog, void $ liftAnnex groupMapLoad)
, (numcopiesLog, void $ liftAnnex numCopiesLoad) , (numcopiesLog, void $ liftAnnex globalNumCopiesLoad)
, (scheduleLog, void updateScheduleLog) , (scheduleLog, void updateScheduleLog)
-- Preferred content settings depend on most of the other configs, -- Preferred content settings depend on most of the other configs,
-- so will be reloaded whenever any configs change. -- so will be reloaded whenever any configs change.

View file

@ -82,7 +82,7 @@ prefsAForm def = PrefsForm
getPrefs :: Annex PrefsForm getPrefs :: Annex PrefsForm
getPrefs = PrefsForm getPrefs = PrefsForm
<$> (T.pack . roughSize storageUnits False . annexDiskReserve <$> Annex.getGitConfig) <$> (T.pack . roughSize storageUnits False . annexDiskReserve <$> Annex.getGitConfig)
<*> (maybe deprecatedNumCopies return =<< getGlobalNumCopies) <*> (fromNumCopies <$> (maybe deprecatedNumCopies return =<< getGlobalNumCopies))
<*> inAutoStartFile <*> inAutoStartFile
<*> (annexAutoUpgrade <$> Annex.getGitConfig) <*> (annexAutoUpgrade <$> Annex.getGitConfig)
<*> (annexDebug <$> Annex.getGitConfig) <*> (annexDebug <$> Annex.getGitConfig)
@ -90,7 +90,7 @@ getPrefs = PrefsForm
storePrefs :: PrefsForm -> Annex () storePrefs :: PrefsForm -> Annex ()
storePrefs p = do storePrefs p = do
setConfig (annexConfig "diskreserve") (T.unpack $ diskReserve p) setConfig (annexConfig "diskreserve") (T.unpack $ diskReserve p)
setGlobalNumCopies (numCopies p) setGlobalNumCopies (NumCopies $ numCopies p)
unsetConfig (annexConfig "numcopies") -- deprecated unsetConfig (annexConfig "numcopies") -- deprecated
setConfig (annexConfig "autoupgrade") (fromAutoUpgrade $ autoUpgrade p) setConfig (annexConfig "autoupgrade") (fromAutoUpgrade $ autoUpgrade p)
unlessM ((==) <$> pure (autoStart p) <*> inAutoStartFile) $ do unlessM ((==) <$> pure (autoStart p) <*> inAutoStartFile) $ do

View file

@ -19,8 +19,6 @@ module Command (
whenAnnexed, whenAnnexed,
ifAnnexed, ifAnnexed,
isBareRepo, isBareRepo,
numCopies,
numCopiesCheck,
checkAuto, checkAuto,
module ReExported module ReExported
) where ) where
@ -29,17 +27,12 @@ import Common.Annex
import qualified Backend import qualified Backend
import qualified Annex import qualified Annex
import qualified Git import qualified Git
import qualified Remote
import Types.Command as ReExported import Types.Command as ReExported
import Types.Option as ReExported import Types.Option as ReExported
import Seek as ReExported import Seek as ReExported
import Checks as ReExported import Checks as ReExported
import Usage as ReExported import Usage as ReExported
import RunCommand as ReExported import RunCommand as ReExported
import Logs.Trust
import Logs.NumCopies
import Config
import Annex.CheckAttr
{- Generates a normal command -} {- Generates a normal command -}
command :: String -> String -> CommandSeek -> CommandSection -> String -> Command command :: String -> String -> CommandSeek -> CommandSection -> String -> Command
@ -87,20 +80,6 @@ ifAnnexed file yes no = maybe no yes =<< Backend.lookupFile file
isBareRepo :: Annex Bool isBareRepo :: Annex Bool
isBareRepo = fromRepo Git.repoIsLocalBare isBareRepo = fromRepo Git.repoIsLocalBare
numCopies :: FilePath -> Annex (Maybe Int)
numCopies file = do
global <- getGlobalNumCopies
case global of
Just n -> return $ Just n
Nothing -> readish <$> checkAttr "annex.numcopies" file
numCopiesCheck :: FilePath -> Key -> (Int -> Int -> v) -> Annex v
numCopiesCheck file key vs = do
numcopiesattr <- numCopies file
needed <- getNumCopies numcopiesattr
have <- trustExclude UnTrusted =<< Remote.keyLocations key
return $ length have `vs` needed
checkAuto :: Annex Bool -> Annex Bool checkAuto :: Annex Bool -> Annex Bool
checkAuto checker = ifM (Annex.getState Annex.auto) checkAuto checker = ifM (Annex.getState Annex.auto)
( checker , return True ) ( checker , return True )

View file

@ -13,6 +13,7 @@ import GitAnnex.Options
import qualified Command.Move import qualified Command.Move
import qualified Remote import qualified Remote
import Annex.Wanted import Annex.Wanted
import Logs.NumCopies
def :: [Command] def :: [Command]
def = [withOptions Command.Move.moveOptions $ command "copy" paramPaths seek def = [withOptions Command.Move.moveOptions $ command "copy" paramPaths seek

View file

@ -14,8 +14,8 @@ import qualified Annex
import Annex.UUID import Annex.UUID
import Logs.Location import Logs.Location
import Logs.Trust import Logs.Trust
import Logs.NumCopies
import Annex.Content import Annex.Content
import Config
import qualified Option import qualified Option
import Annex.Wanted import Annex.Wanted
import Types.Key import Types.Key
@ -43,17 +43,17 @@ start from file (key, _) = checkDropAuto from file key $ \numcopies ->
then startLocal (Just file) numcopies key Nothing then startLocal (Just file) numcopies key Nothing
else startRemote (Just file) numcopies key remote else startRemote (Just file) numcopies key remote
startLocal :: AssociatedFile -> Maybe Int -> Key -> Maybe Remote -> CommandStart startLocal :: AssociatedFile -> Maybe NumCopies -> Key -> Maybe Remote -> CommandStart
startLocal afile numcopies key knownpresentremote = stopUnless (inAnnex key) $ do startLocal afile numcopies key knownpresentremote = stopUnless (inAnnex key) $ do
showStart "drop" (fromMaybe (key2file key) afile) showStart "drop" (fromMaybe (key2file key) afile)
next $ performLocal key numcopies knownpresentremote next $ performLocal key numcopies knownpresentremote
startRemote :: AssociatedFile -> Maybe Int -> Key -> Remote -> CommandStart startRemote :: AssociatedFile -> Maybe NumCopies -> Key -> Remote -> CommandStart
startRemote afile numcopies key remote = do startRemote afile numcopies key remote = do
showStart ("drop " ++ Remote.name remote) (fromMaybe (key2file key) afile) showStart ("drop " ++ Remote.name remote) (fromMaybe (key2file key) afile)
next $ performRemote key numcopies remote next $ performRemote key numcopies remote
performLocal :: Key -> Maybe Int -> Maybe Remote -> CommandPerform performLocal :: Key -> Maybe NumCopies -> Maybe Remote -> CommandPerform
performLocal key numcopies knownpresentremote = lockContent key $ do performLocal key numcopies knownpresentremote = lockContent key $ do
(remotes, trusteduuids) <- Remote.keyPossibilitiesTrusted key (remotes, trusteduuids) <- Remote.keyPossibilitiesTrusted key
let trusteduuids' = case knownpresentremote of let trusteduuids' = case knownpresentremote of
@ -65,7 +65,7 @@ performLocal key numcopies knownpresentremote = lockContent key $ do
removeAnnex key removeAnnex key
next $ cleanupLocal key next $ cleanupLocal key
performRemote :: Key -> Maybe Int -> Remote -> CommandPerform performRemote :: Key -> Maybe NumCopies -> Remote -> CommandPerform
performRemote key numcopies remote = lockContent key $ do performRemote key numcopies remote = lockContent key $ do
-- Filter the remote it's being dropped from out of the lists of -- Filter the remote it's being dropped from out of the lists of
-- places assumed to have the key, and places to check. -- places assumed to have the key, and places to check.
@ -98,23 +98,23 @@ cleanupRemote key remote ok = do
{- Checks specified remotes to verify that enough copies of a key exist to {- Checks specified remotes to verify that enough copies of a key exist to
- allow it to be safely removed (with no data loss). Can be provided with - allow it to be safely removed (with no data loss). Can be provided with
- some locations where the key is known/assumed to be present. -} - some locations where the key is known/assumed to be present. -}
canDropKey :: Key -> Maybe Int -> [UUID] -> [Remote] -> [UUID] -> Annex Bool canDropKey :: Key -> Maybe NumCopies -> [UUID] -> [Remote] -> [UUID] -> Annex Bool
canDropKey key numcopiesM have check skip = do canDropKey key numcopiesM have check skip = do
force <- Annex.getState Annex.force force <- Annex.getState Annex.force
if force || numcopiesM == Just 0 if force || numcopiesM == Just (NumCopies 0)
then return True then return True
else do else do
need <- getNumCopies numcopiesM need <- getNumCopies numcopiesM
findCopies key need skip have check findCopies key need skip have check
findCopies :: Key -> Int -> [UUID] -> [UUID] -> [Remote] -> Annex Bool findCopies :: Key -> NumCopies -> [UUID] -> [UUID] -> [Remote] -> Annex Bool
findCopies key need skip = helper [] [] findCopies key need skip = helper [] []
where where
helper bad missing have [] helper bad missing have []
| length have >= need = return True | NumCopies (length have) >= need = return True
| otherwise = notEnoughCopies key need have (skip++missing) bad | otherwise = notEnoughCopies key need have (skip++missing) bad
helper bad missing have (r:rs) helper bad missing have (r:rs)
| length have >= need = return True | NumCopies (length have) >= need = return True
| otherwise = do | otherwise = do
let u = Remote.uuid r let u = Remote.uuid r
let duplicate = u `elem` have let duplicate = u `elem` have
@ -125,12 +125,12 @@ findCopies key need skip = helper [] []
(False, Right False) -> helper bad (u:missing) have rs (False, Right False) -> helper bad (u:missing) have rs
_ -> helper bad missing have rs _ -> helper bad missing have rs
notEnoughCopies :: Key -> Int -> [UUID] -> [UUID] -> [Remote] -> Annex Bool notEnoughCopies :: Key -> NumCopies -> [UUID] -> [UUID] -> [Remote] -> Annex Bool
notEnoughCopies key need have skip bad = do notEnoughCopies key need have skip bad = do
unsafe unsafe
showLongNote $ showLongNote $
"Could only verify the existence of " ++ "Could only verify the existence of " ++
show (length have) ++ " out of " ++ show need ++ show (length have) ++ " out of " ++ show (fromNumCopies need) ++
" necessary copies" " necessary copies"
Remote.showTriedRemotes bad Remote.showTriedRemotes bad
Remote.showLocations key (have++skip) Remote.showLocations key (have++skip)
@ -146,9 +146,9 @@ notEnoughCopies key need have skip bad = do
- -
- Passes any numcopies attribute of the file on to the action as an - Passes any numcopies attribute of the file on to the action as an
- optimisation. -} - optimisation. -}
checkDropAuto :: Maybe Remote -> FilePath -> Key -> (Maybe Int -> CommandStart) -> CommandStart checkDropAuto :: Maybe Remote -> FilePath -> Key -> (Maybe NumCopies -> CommandStart) -> CommandStart
checkDropAuto mremote file key a = do checkDropAuto mremote file key a = do
numcopiesattr <- numCopies file numcopiesattr <- getFileNumCopies file
Annex.getState Annex.auto >>= auto numcopiesattr Annex.getState Annex.auto >>= auto numcopiesattr
where where
auto numcopiesattr False = a numcopiesattr auto numcopiesattr False = a numcopiesattr
@ -158,6 +158,6 @@ checkDropAuto mremote file key a = do
uuid <- getUUID uuid <- getUUID
let remoteuuid = fromMaybe uuid $ Remote.uuid <$> mremote let remoteuuid = fromMaybe uuid $ Remote.uuid <$> mremote
locs' <- trustExclude UnTrusted $ filter (/= remoteuuid) locs locs' <- trustExclude UnTrusted $ filter (/= remoteuuid) locs
if length locs' >= needed if NumCopies (length locs') >= needed
then a numcopiesattr then a numcopiesattr
else stop else stop

View file

@ -25,6 +25,7 @@ import Annex.Perms
import Annex.Link import Annex.Link
import Logs.Location import Logs.Location
import Logs.Trust import Logs.Trust
import Logs.NumCopies
import Annex.UUID import Annex.UUID
import Utility.DataUnits import Utility.DataUnits
import Utility.FileMode import Utility.FileMode
@ -111,14 +112,14 @@ getIncremental = do
start :: Maybe Remote -> Incremental -> FilePath -> (Key, Backend) -> CommandStart start :: Maybe Remote -> Incremental -> FilePath -> (Key, Backend) -> CommandStart
start from inc file (key, backend) = do start from inc file (key, backend) = do
numcopies <- numCopies file numcopies <- getFileNumCopies file
case from of case from of
Nothing -> go $ perform key file backend numcopies Nothing -> go $ perform key file backend numcopies
Just r -> go $ performRemote key file backend numcopies r Just r -> go $ performRemote key file backend numcopies r
where where
go = runFsck inc file key go = runFsck inc file key
perform :: Key -> FilePath -> Backend -> Maybe Int -> Annex Bool perform :: Key -> FilePath -> Backend -> Maybe NumCopies -> Annex Bool
perform key file backend numcopies = check perform key file backend numcopies = check
-- order matters -- order matters
[ fixLink key file [ fixLink key file
@ -132,7 +133,7 @@ perform key file backend numcopies = check
{- To fsck a remote, the content is retrieved to a tmp file, {- To fsck a remote, the content is retrieved to a tmp file,
- and checked locally. -} - and checked locally. -}
performRemote :: Key -> FilePath -> Backend -> Maybe Int -> Remote -> Annex Bool performRemote :: Key -> FilePath -> Backend -> Maybe NumCopies -> Remote -> Annex Bool
performRemote key file backend numcopies remote = performRemote key file backend numcopies remote =
dispatch =<< Remote.hasKey remote key dispatch =<< Remote.hasKey remote key
where where
@ -368,11 +369,11 @@ checkBackendOr' bad backend key file postcheck =
, return True , return True
) )
checkKeyNumCopies :: Key -> FilePath -> Maybe Int -> Annex Bool checkKeyNumCopies :: Key -> FilePath -> Maybe NumCopies -> Annex Bool
checkKeyNumCopies key file numcopies = do checkKeyNumCopies key file numcopies = do
needed <- getNumCopies numcopies needed <- getNumCopies numcopies
(untrustedlocations, safelocations) <- trustPartition UnTrusted =<< Remote.keyLocations key (untrustedlocations, safelocations) <- trustPartition UnTrusted =<< Remote.keyLocations key
let present = length safelocations let present = NumCopies (length safelocations)
if present < needed if present < needed
then do then do
ppuuids <- Remote.prettyPrintUUIDs "untrusted" untrustedlocations ppuuids <- Remote.prettyPrintUUIDs "untrusted" untrustedlocations
@ -380,15 +381,15 @@ checkKeyNumCopies key file numcopies = do
return False return False
else return True else return True
missingNote :: String -> Int -> Int -> String -> String missingNote :: String -> NumCopies -> NumCopies -> String -> String
missingNote file 0 _ [] = missingNote file (NumCopies 0) _ [] =
"** No known copies exist of " ++ file "** No known copies exist of " ++ file
missingNote file 0 _ untrusted = missingNote file (NumCopies 0) _ untrusted =
"Only these untrusted locations may have copies of " ++ file ++ "Only these untrusted locations may have copies of " ++ file ++
"\n" ++ untrusted ++ "\n" ++ untrusted ++
"Back it up to trusted locations with git-annex copy." "Back it up to trusted locations with git-annex copy."
missingNote file present needed [] = missingNote file present needed [] =
"Only " ++ show present ++ " of " ++ show needed ++ "Only " ++ show (fromNumCopies present) ++ " of " ++ show (fromNumCopies needed) ++
" trustworthy copies exist of " ++ file ++ " trustworthy copies exist of " ++ file ++
"\nBack it up with git-annex copy." "\nBack it up with git-annex copy."
missingNote file present needed untrusted = missingNote file present needed untrusted =

View file

@ -12,6 +12,7 @@ import Command
import qualified Remote import qualified Remote
import Annex.Content import Annex.Content
import Logs.Transfer import Logs.Transfer
import Logs.NumCopies
import Annex.Wanted import Annex.Wanted
import GitAnnex.Options import GitAnnex.Options
import qualified Command.Move import qualified Command.Move

View file

@ -29,6 +29,7 @@ import Annex.Content
import Types.Key import Types.Key
import Logs.UUID import Logs.UUID
import Logs.Trust import Logs.Trust
import Logs.NumCopies
import Remote import Remote
import Config import Config
import Utility.Percentage import Utility.Percentage

View file

@ -16,6 +16,7 @@ import qualified Command.Get
import qualified Remote import qualified Remote
import Annex.Content import Annex.Content
import qualified Annex import qualified Annex
import Logs.NumCopies
def :: [Command] def :: [Command]
def = [withOptions (fromToOptions ++ keyOptions) $ def = [withOptions (fromToOptions ++ keyOptions) $
@ -33,10 +34,10 @@ seek ps = do
start :: Maybe Remote -> Maybe Remote -> FilePath -> (Key, Backend) -> CommandStart start :: Maybe Remote -> Maybe Remote -> FilePath -> (Key, Backend) -> CommandStart
start to from file (key, _backend) = do start to from file (key, _backend) = do
numcopies <- numCopies file numcopies <- getFileNumCopies file
startKey numcopies to from (Just file) key startKey numcopies to from (Just file) key
startKey :: Maybe Int -> Maybe Remote -> Maybe Remote -> Maybe FilePath -> Key -> CommandStart startKey :: Maybe NumCopies -> Maybe Remote -> Maybe Remote -> Maybe FilePath -> Key -> CommandStart
startKey numcopies to from afile key = do startKey numcopies to from afile key = do
noAuto noAuto
case (from, to) of case (from, to) of

View file

@ -39,7 +39,7 @@ startGet = next $ next $ do
Annex.setOutput QuietOutput Annex.setOutput QuietOutput
v <- getGlobalNumCopies v <- getGlobalNumCopies
case v of case v of
Just n -> liftIO $ putStrLn $ show n Just n -> liftIO $ putStrLn $ show $ fromNumCopies n
Nothing -> do Nothing -> do
liftIO $ putStrLn $ "global numcopies is not set" liftIO $ putStrLn $ "global numcopies is not set"
old <- annexNumCopies <$> Annex.getGitConfig old <- annexNumCopies <$> Annex.getGitConfig
@ -52,5 +52,5 @@ startSet :: Int -> CommandStart
startSet n = do startSet n = do
showStart "numcopies" (show n) showStart "numcopies" (show n)
next $ next $ do next $ next $ do
setGlobalNumCopies n setGlobalNumCopies $ NumCopies n
return True return True

View file

@ -106,34 +106,34 @@ readResponse h = fromMaybe False . deserialize <$> hGetLine h
fieldSep :: String fieldSep :: String
fieldSep = "\0" fieldSep = "\0"
class Serialized a where class TCSerialized a where
serialize :: a -> String serialize :: a -> String
deserialize :: String -> Maybe a deserialize :: String -> Maybe a
instance Serialized Bool where instance TCSerialized Bool where
serialize True = "1" serialize True = "1"
serialize False = "0" serialize False = "0"
deserialize "1" = Just True deserialize "1" = Just True
deserialize "0" = Just False deserialize "0" = Just False
deserialize _ = Nothing deserialize _ = Nothing
instance Serialized Direction where instance TCSerialized Direction where
serialize Upload = "u" serialize Upload = "u"
serialize Download = "d" serialize Download = "d"
deserialize "u" = Just Upload deserialize "u" = Just Upload
deserialize "d" = Just Download deserialize "d" = Just Download
deserialize _ = Nothing deserialize _ = Nothing
instance Serialized AssociatedFile where instance TCSerialized AssociatedFile where
serialize (Just f) = f serialize (Just f) = f
serialize Nothing = "" serialize Nothing = ""
deserialize "" = Just Nothing deserialize "" = Just Nothing
deserialize f = Just $ Just f deserialize f = Just $ Just f
instance Serialized UUID where instance TCSerialized UUID where
serialize = fromUUID serialize = fromUUID
deserialize = Just . toUUID deserialize = Just . toUUID
instance Serialized Key where instance TCSerialized Key where
serialize = key2file serialize = key2file
deserialize = file2key deserialize = file2key

View file

@ -69,13 +69,6 @@ setRemoteCost r c = setConfig (remoteConfig r "cost") (show c)
setRemoteAvailability :: Git.Repo -> Availability -> Annex () setRemoteAvailability :: Git.Repo -> Availability -> Annex ()
setRemoteAvailability r c = setConfig (remoteConfig r "availability") (show c) setRemoteAvailability r c = setConfig (remoteConfig r "availability") (show c)
getNumCopies :: Maybe Int -> Annex Int
getNumCopies (Just v) = return v
getNumCopies Nothing = deprecatedNumCopies
deprecatedNumCopies :: Annex Int
deprecatedNumCopies = fromMaybe 1 . annexNumCopies <$> Annex.getGitConfig
isDirect :: Annex Bool isDirect :: Annex Bool
isDirect = annexDirect <$> Annex.getGitConfig isDirect = annexDirect <$> Annex.getGitConfig

View file

@ -14,6 +14,7 @@ import qualified Git.Config
import Git.Types import Git.Types
import Command import Command
import Types.TrustLevel import Types.TrustLevel
import Types.NumCopies
import Types.Messages import Types.Messages
import qualified Annex import qualified Annex
import qualified Remote import qualified Remote
@ -65,7 +66,7 @@ options = Option.common ++
where where
trustArg t = ReqArg (Remote.forceTrust t) paramRemote trustArg t = ReqArg (Remote.forceTrust t) paramRemote
setnumcopies v = maybe noop setnumcopies v = maybe noop
(\n -> Annex.changeState $ \s -> s { Annex.globalnumcopies = Just n }) (\n -> Annex.changeState $ \s -> s { Annex.globalnumcopies = Just $ NumCopies n })
(readish v) (readish v)
setuseragent v = Annex.changeState $ \s -> s { Annex.useragent = Just v } setuseragent v = Annex.changeState $ \s -> s { Annex.useragent = Just v }
setgitconfig v = inRepo (Git.Config.store v) setgitconfig v = inRepo (Git.Config.store v)

View file

@ -197,7 +197,7 @@ limitNumCopiesNeeded want = case readish want of
gv <- getGlobalNumCopies gv <- getGlobalNumCopies
case gv of case gv of
Nothing -> return False Nothing -> return False
Just numcopies -> do Just (NumCopies numcopies) -> do
us <- filter (`S.notMember` notpresent) us <- filter (`S.notMember` notpresent)
<$> (trustExclude UnTrusted =<< Remote.keyLocations key) <$> (trustExclude UnTrusted =<< Remote.keyLocations key)
return $ numcopies - length us >= needed return $ numcopies - length us >= needed

View file

@ -7,27 +7,71 @@
{-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_GHC -fno-warn-orphans #-}
module Logs.NumCopies where module Logs.NumCopies (
module Types.NumCopies,
setGlobalNumCopies,
getGlobalNumCopies,
globalNumCopiesLoad,
getFileNumCopies,
numCopiesCheck,
getNumCopies,
deprecatedNumCopies,
) where
import Common.Annex import Common.Annex
import qualified Annex import qualified Annex
import Types.NumCopies
import Logs import Logs
import Logs.SingleValue import Logs.SingleValue
import Logs.Trust
import Annex.CheckAttr
import qualified Remote
instance Serializable Int where instance SingleValueSerializable NumCopies where
serialize = show serialize (NumCopies n) = show n
deserialize = readish deserialize = NumCopies <$$> readish
setGlobalNumCopies :: Int -> Annex () setGlobalNumCopies :: NumCopies -> Annex ()
setGlobalNumCopies = setLog numcopiesLog setGlobalNumCopies = setLog numcopiesLog
{- Cached for speed. -} {- Cached for speed. -}
getGlobalNumCopies :: Annex (Maybe Int) getGlobalNumCopies :: Annex (Maybe NumCopies)
getGlobalNumCopies = maybe numCopiesLoad (return . Just) getGlobalNumCopies = maybe globalNumCopiesLoad (return . Just)
=<< Annex.getState Annex.globalnumcopies =<< Annex.getState Annex.globalnumcopies
numCopiesLoad :: Annex (Maybe Int) globalNumCopiesLoad :: Annex (Maybe NumCopies)
numCopiesLoad = do globalNumCopiesLoad = do
v <- getLog numcopiesLog v <- getLog numcopiesLog
Annex.changeState $ \s -> s { Annex.globalnumcopies = v } Annex.changeState $ \s -> s { Annex.globalnumcopies = v }
return v return v
{- Numcopies value for a file, from .gitattributes or global,
- but not the deprecated git config. -}
getFileNumCopies :: FilePath -> Annex (Maybe NumCopies)
getFileNumCopies file = do
global <- getGlobalNumCopies
case global of
Just n -> return $ Just n
Nothing -> (NumCopies <$$> readish)
<$> checkAttr "annex.numcopies" file
deprecatedNumCopies :: Annex NumCopies
deprecatedNumCopies = NumCopies . fromMaybe 1 . annexNumCopies
<$> Annex.getGitConfig
{- Checks if numcopies are satisfied by running a comparison
- between the number of (not untrusted) copies that are
- belived to exist, and the configured value.
-
- Includes the deprecated annex.numcopies git config if
- nothing else specifies a numcopies value. -}
numCopiesCheck :: FilePath -> Key -> (Int -> Int -> v) -> Annex v
numCopiesCheck file key vs = do
numcopiesattr <- getFileNumCopies file
NumCopies needed <- getNumCopies numcopiesattr
have <- trustExclude UnTrusted =<< Remote.keyLocations key
return $ length have `vs` needed
getNumCopies :: Maybe NumCopies -> Annex NumCopies
getNumCopies (Just v) = return v
getNumCopies Nothing = deprecatedNumCopies

View file

@ -21,7 +21,7 @@ import Data.Time.Clock.POSIX
import Data.Time import Data.Time
import System.Locale import System.Locale
class Serializable v where class SingleValueSerializable v where
serialize :: v -> String serialize :: v -> String
deserialize :: String -> Maybe v deserialize :: String -> Maybe v
@ -32,12 +32,12 @@ data LogEntry v = LogEntry
type Log v = S.Set (LogEntry v) type Log v = S.Set (LogEntry v)
showLog :: (Serializable v) => Log v -> String showLog :: (SingleValueSerializable v) => Log v -> String
showLog = unlines . map showline . S.toList showLog = unlines . map showline . S.toList
where where
showline (LogEntry t v) = unwords [show t, serialize v] showline (LogEntry t v) = unwords [show t, serialize v]
parseLog :: (Ord v, Serializable v) => String -> Log v parseLog :: (Ord v, SingleValueSerializable v) => String -> Log v
parseLog = S.fromList . mapMaybe parse . lines parseLog = S.fromList . mapMaybe parse . lines
where where
parse line = do parse line = do
@ -52,13 +52,13 @@ newestValue s
| S.null s = Nothing | S.null s = Nothing
| otherwise = Just (value $ S.findMax s) | otherwise = Just (value $ S.findMax s)
readLog :: (Ord v, Serializable v) => FilePath -> Annex (Log v) readLog :: (Ord v, SingleValueSerializable v) => FilePath -> Annex (Log v)
readLog = parseLog <$$> Annex.Branch.get readLog = parseLog <$$> Annex.Branch.get
getLog :: (Ord v, Serializable v) => FilePath -> Annex (Maybe v) getLog :: (Ord v, SingleValueSerializable v) => FilePath -> Annex (Maybe v)
getLog = newestValue <$$> readLog getLog = newestValue <$$> readLog
setLog :: (Serializable v) => FilePath -> v -> Annex () setLog :: (SingleValueSerializable v) => FilePath -> v -> Annex ()
setLog f v = do setLog f v = do
now <- liftIO getPOSIXTime now <- liftIO getPOSIXTime
let ent = LogEntry now v let ent = LogEntry now v

View file

@ -229,11 +229,11 @@ type ProtocolVersion = Int
supportedProtocolVersions :: [ProtocolVersion] supportedProtocolVersions :: [ProtocolVersion]
supportedProtocolVersions = [1] supportedProtocolVersions = [1]
class Serializable a where class ExternalSerializable a where
serialize :: a -> String serialize :: a -> String
deserialize :: String -> Maybe a deserialize :: String -> Maybe a
instance Serializable Direction where instance ExternalSerializable Direction where
serialize Upload = "STORE" serialize Upload = "STORE"
serialize Download = "RETRIEVE" serialize Download = "RETRIEVE"
@ -241,23 +241,23 @@ instance Serializable Direction where
deserialize "RETRIEVE" = Just Download deserialize "RETRIEVE" = Just Download
deserialize _ = Nothing deserialize _ = Nothing
instance Serializable Key where instance ExternalSerializable Key where
serialize = key2file serialize = key2file
deserialize = file2key deserialize = file2key
instance Serializable [Char] where instance ExternalSerializable [Char] where
serialize = id serialize = id
deserialize = Just deserialize = Just
instance Serializable ProtocolVersion where instance ExternalSerializable ProtocolVersion where
serialize = show serialize = show
deserialize = readish deserialize = readish
instance Serializable Cost where instance ExternalSerializable Cost where
serialize = show serialize = show
deserialize = readish deserialize = readish
instance Serializable Availability where instance ExternalSerializable Availability where
serialize GloballyAvailable = "GLOBAL" serialize GloballyAvailable = "GLOBAL"
serialize LocallyAvailable = "LOCAL" serialize LocallyAvailable = "LOCAL"
@ -265,7 +265,7 @@ instance Serializable Availability where
deserialize "LOCAL" = Just LocallyAvailable deserialize "LOCAL" = Just LocallyAvailable
deserialize _ = Nothing deserialize _ = Nothing
instance Serializable BytesProcessed where instance ExternalSerializable BytesProcessed where
serialize (BytesProcessed n) = show n serialize (BytesProcessed n) = show n
deserialize = BytesProcessed <$$> readish deserialize = BytesProcessed <$$> readish
@ -283,15 +283,15 @@ parse0 :: a -> Parser a
parse0 mk "" = Just mk parse0 mk "" = Just mk
parse0 _ _ = Nothing parse0 _ _ = Nothing
parse1 :: Serializable p1 => (p1 -> a) -> Parser a parse1 :: ExternalSerializable p1 => (p1 -> a) -> Parser a
parse1 mk p1 = mk <$> deserialize p1 parse1 mk p1 = mk <$> deserialize p1
parse2 :: (Serializable p1, Serializable p2) => (p1 -> p2 -> a) -> Parser a parse2 :: (ExternalSerializable p1, ExternalSerializable p2) => (p1 -> p2 -> a) -> Parser a
parse2 mk s = mk <$> deserialize p1 <*> deserialize p2 parse2 mk s = mk <$> deserialize p1 <*> deserialize p2
where where
(p1, p2) = splitWord s (p1, p2) = splitWord s
parse3 :: (Serializable p1, Serializable p2, Serializable p3) => (p1 -> p2 -> p3 -> a) -> Parser a parse3 :: (ExternalSerializable p1, ExternalSerializable p2, ExternalSerializable p3) => (p1 -> p2 -> p3 -> a) -> Parser a
parse3 mk s = mk <$> deserialize p1 <*> deserialize p2 <*> deserialize p3 parse3 mk s = mk <$> deserialize p1 <*> deserialize p2 <*> deserialize p3
where where
(p1, rest) = splitWord s (p1, rest) = splitWord s

14
Types/NumCopies.hs Normal file
View file

@ -0,0 +1,14 @@
{- git-annex numcopies type
-
- Copyright 2014 Joey Hess <joey@kitenet.net>
-
- Licensed under the GNU GPL version 3 or higher.
-}
module Types.NumCopies where
newtype NumCopies = NumCopies Int
deriving (Ord, Eq)
fromNumCopies :: NumCopies -> Int
fromNumCopies (NumCopies n) = n