<> help "match files the repository wants to drop"
<> hidden
)
- , globalSetter Limit.addAccessedWithin $ option (str >>= parseDuration)
+ , globalSetter Limit.addAccessedWithin $ option (eitherReader parseDuration)
( long "accessedwithin"
<> metavar paramTime
<> help "match files accessed within a time interval"
timeLimitOption :: [GlobalOption]
timeLimitOption =
- [ globalSetter Limit.addTimeLimit $ option (str >>= parseDuration)
+ [ globalSetter Limit.addTimeLimit $ option (eitherReader parseDuration)
( long "time-limit" <> short 'T' <> metavar paramTime
<> help "stop after the specified amount of time"
<> hidden
( long "autostart"
<> help "start in known repositories"
)
- <*> optional (option (str >>= parseDuration)
+ <*> optional (option (eitherReader parseDuration)
( long "startdelay" <> metavar paramNumber
<> help "delay before running startup scan"
))
return (Just r, parsetime now t)
parsetime _ "never" = Nothing
parsetime now s = case parseDuration s of
- Nothing -> giveup $ "bad expire time: " ++ s
- Just d -> Just (now - durationToPOSIXTime d)
+ Right d -> Just (now - durationToPOSIXTime d)
+ Left e -> giveup $ "bad expire time: " ++ e
parseActivity :: MonadFail m => String -> m Activity
parseActivity s = case readish s of
( long "more" <> short 'm'
<> help "continue an incremental fsck"
)
- <|> (ScheduleIncrementalO <$> option (str >>= parseDuration)
+ <|> (ScheduleIncrementalO <$> option (eitherReader parseDuration)
( long "incremental-schedule" <> metavar paramTime
<> help "schedule incremental fscking"
))
, annexFsckNudge = getbool (annexConfig "fscknudge") True
, annexAutoUpgrade = toAutoUpgrade $
getmaybe (annexConfig "autoupgrade")
- , annexExpireUnused = maybe Nothing Just . parseDuration
+ , annexExpireUnused = either (const Nothing) Just . parseDuration
<$> getmaybe (annexConfig "expireunused")
, annexSecureEraseCommand = getmaybe (annexConfig "secure-erase-command")
, annexGenMetaData = getbool (annexConfig "genmetadata") False
parseScheduledActivity s = case words s of
("fsck":"self":d:rest) -> qualified $ ScheduledSelfFsck
<$> parseSchedule (unwords rest)
- <*> getduration d
+ <*> parseDuration d
("fsck":u:d:rest) -> qualified $ ScheduledRemoteFsck
<$> pure (toUUID u)
<*> parseSchedule (unwords rest)
- <*> getduration d
+ <*> parseDuration d
_ -> qualified $ Left "unknown activity"
where
qualified (Left e) = Left $ e ++ " in \"" ++ s ++ "\""
qualified v = v
- getduration d = maybe (Left $ "failed to parse duration \""++d++"\"") Right (parseDuration d)
fromScheduledActivities :: [ScheduledActivity] -> String
fromScheduledActivities = intercalate "; " . map fromScheduledActivity
import Utility.PartialPrelude
import Utility.QuickCheck
-import Control.Monad.Fail as Fail (MonadFail(..))
import qualified Data.Map as M
import Data.Time.Clock
import Data.Time.Clock.POSIX (POSIXTime)
daysToDuration i = Duration $ i * dsecs
{- Parses a human-input time duration, of the form "5h", "1m", "5h1m", etc -}
-parseDuration :: MonadFail m => String -> m Duration
-parseDuration = maybe parsefail (return . Duration) . go 0
+parseDuration :: String -> Either String Duration
+parseDuration d = maybe parsefail (Right . Duration) $ go 0 d
where
go n [] = return n
go n s = do
u <- M.lookup c unitmap
go (n + num * u) rest
_ -> return $ n + num
- parsefail = Fail.fail "duration parse error; expected eg \"5m\" or \"1h5m\""
+ parsefail = Left $ "failed to parse duration \"" ++ d ++ "\" (expected eg \"5m\" or \"1h5m\")"
fromDuration :: Duration -> String
fromDuration Duration { durationSeconds = d }
arbitrary = Duration <$> nonNegative arbitrary
prop_duration_roundtrips :: Duration -> Bool
-prop_duration_roundtrips d = parseDuration (fromDuration d) == Just d
+prop_duration_roundtrips d = parseDuration (fromDuration d) == Right d