{-# LANGUAGE OverloadedStrings #-}
module Darcs.Repository.Format
( RepoFormat(..)
, RepoProperty(..)
, identifyRepoFormat
, tryIdentifyRepoFormat
, createRepoFormat
, writeRepoFormat
, writeProblem
, readProblem
, transferProblem
, formatHas
, addToFormat
, removeFromFormat
) where
import Darcs.Prelude
import Control.Monad ( mplus, (<=<) )
import qualified Data.ByteString.Char8 as BC ( split, pack, unpack, elem )
import qualified Data.ByteString as B ( ByteString, null, empty, stripPrefix )
import Data.List ( partition, intercalate, (\\) )
import Data.Maybe ( mapMaybe )
import Data.String ( IsString )
import System.FilePath.Posix( (</>) )
import Darcs.Util.External
( fetchFilePS
, Cachable( Cachable )
)
import Darcs.Util.Lock ( writeBinFile )
import qualified Darcs.Repository.Flags as F
( WithWorkingDir (..), PatchFormat (..) )
import Darcs.Repository.Paths ( formatPath, oldInventoryPath )
import Darcs.Util.SignalHandler ( catchNonSignal )
import Darcs.Util.Exception ( catchall, prettyException )
import Darcs.Util.ByteString ( linesPS )
import Darcs.Util.Progress ( beginTedious, endTedious, finishedOneIO )
data RepoProperty = Darcs1
| Darcs2
| Darcs3
| HashedInventory
| NoWorkingDir
| RebaseInProgress
| RebaseInProgress_2_16
| UnknownFormat B.ByteString
deriving ( RepoProperty -> RepoProperty -> Bool
(RepoProperty -> RepoProperty -> Bool)
-> (RepoProperty -> RepoProperty -> Bool) -> Eq RepoProperty
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RepoProperty -> RepoProperty -> Bool
$c/= :: RepoProperty -> RepoProperty -> Bool
== :: RepoProperty -> RepoProperty -> Bool
$c== :: RepoProperty -> RepoProperty -> Bool
Eq )
darcs1Format, darcs2Format, darcs3Format,
hashedInventoryFormat, noWorkingDirFormat,
rebaseInProgressFormat, rebaseInProgress_2_16,
newStyleRebaseInProgress :: IsString s => s
darcs1Format :: s
darcs1Format = s
"darcs-1.0"
darcs2Format :: s
darcs2Format = s
"darcs-2"
darcs3Format :: s
darcs3Format = s
"darcs-3"
hashedInventoryFormat :: s
hashedInventoryFormat = s
"hashed"
noWorkingDirFormat :: s
noWorkingDirFormat = s
"no-working-dir"
rebaseInProgressFormat :: s
rebaseInProgressFormat = s
"rebase-in-progress"
rebaseInProgress_2_16 :: s
rebaseInProgress_2_16 = s
"rebase-in-progress-2-16"
newStyleRebaseInProgress :: s
newStyleRebaseInProgress = s
"new-style-rebase-in-progress"
instance Show RepoProperty where
show :: RepoProperty -> String
show RepoProperty
Darcs1 = String
forall s. IsString s => s
darcs1Format
show RepoProperty
Darcs2 = String
forall s. IsString s => s
darcs2Format
show RepoProperty
Darcs3 = String
forall s. IsString s => s
darcs3Format
show RepoProperty
HashedInventory = String
forall s. IsString s => s
hashedInventoryFormat
show RepoProperty
NoWorkingDir = String
forall s. IsString s => s
noWorkingDirFormat
show RepoProperty
RebaseInProgress = String
forall s. IsString s => s
rebaseInProgressFormat
show RepoProperty
RebaseInProgress_2_16 = String
forall s. IsString s => s
rebaseInProgress_2_16
show (UnknownFormat ByteString
f) = ByteString -> String
BC.unpack ByteString
f
readRepoProperty :: B.ByteString -> RepoProperty
readRepoProperty :: ByteString -> RepoProperty
readRepoProperty ByteString
input
| ByteString
input ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
forall s. IsString s => s
darcs1Format = RepoProperty
Darcs1
| ByteString
input ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
forall s. IsString s => s
darcs2Format = RepoProperty
Darcs2
| ByteString
input ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
forall s. IsString s => s
darcs3Format = RepoProperty
Darcs3
| ByteString
input ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
forall s. IsString s => s
hashedInventoryFormat = RepoProperty
HashedInventory
| ByteString
input ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
forall s. IsString s => s
noWorkingDirFormat = RepoProperty
NoWorkingDir
| ByteString
input ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
forall s. IsString s => s
rebaseInProgressFormat = RepoProperty
RebaseInProgress
| ByteString
input ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
forall s. IsString s => s
newStyleRebaseInProgress = RepoProperty
RebaseInProgress_2_16
| ByteString
input ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
forall s. IsString s => s
rebaseInProgress_2_16 = RepoProperty
RebaseInProgress_2_16
| Bool
otherwise = ByteString -> RepoProperty
UnknownFormat ByteString
input
newtype RepoFormat = RF [[RepoProperty]]
formatHas :: RepoProperty -> RepoFormat -> Bool
formatHas :: RepoProperty -> RepoFormat -> Bool
formatHas RepoProperty
f (RF [[RepoProperty]]
rps) = RepoProperty
f RepoProperty -> [RepoProperty] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[RepoProperty]] -> [RepoProperty]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[RepoProperty]]
rps
addToFormat :: RepoProperty -> RepoFormat -> RepoFormat
addToFormat :: RepoProperty -> RepoFormat -> RepoFormat
addToFormat RepoProperty
f (RF [[RepoProperty]]
rps) = [[RepoProperty]] -> RepoFormat
RF ([[RepoProperty]]
rps [[RepoProperty]] -> [[RepoProperty]] -> [[RepoProperty]]
forall a. [a] -> [a] -> [a]
++ [[RepoProperty
f]])
removeFromFormat :: RepoProperty -> RepoFormat -> RepoFormat
removeFromFormat :: RepoProperty -> RepoFormat -> RepoFormat
removeFromFormat RepoProperty
f (RF [[RepoProperty]]
rps) = [[RepoProperty]] -> RepoFormat
RF ([[RepoProperty]]
rps [[RepoProperty]] -> [[RepoProperty]] -> [[RepoProperty]]
forall a. Eq a => [a] -> [a] -> [a]
\\ [[RepoProperty
f]])
instance Show RepoFormat where
show :: RepoFormat -> String
show (RF [[RepoProperty]]
rf) = [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ ([RepoProperty] -> String) -> [[RepoProperty]] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"|" ([String] -> String)
-> ([RepoProperty] -> [String]) -> [RepoProperty] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (RepoProperty -> String) -> [RepoProperty] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map RepoProperty -> String
forall a. Show a => a -> String
show) [[RepoProperty]]
rf
identifyRepoFormat :: String -> IO RepoFormat
identifyRepoFormat :: String -> IO RepoFormat
identifyRepoFormat = (String -> IO RepoFormat)
-> (RepoFormat -> IO RepoFormat)
-> Either String RepoFormat
-> IO RepoFormat
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> IO RepoFormat
forall (m :: * -> *) a. MonadFail m => String -> m a
fail RepoFormat -> IO RepoFormat
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String RepoFormat -> IO RepoFormat)
-> (String -> IO (Either String RepoFormat))
-> String
-> IO RepoFormat
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< String -> IO (Either String RepoFormat)
tryIdentifyRepoFormat
tryIdentifyRepoFormat :: String -> IO (Either String RepoFormat)
tryIdentifyRepoFormat :: String -> IO (Either String RepoFormat)
tryIdentifyRepoFormat String
repo = do
let k :: String
k = String
"Identifying repository " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
repo
String -> IO ()
beginTedious String
k
String -> String -> IO ()
finishedOneIO String
k String
"format"
ByteString
formatInfo <- (String -> Cachable -> IO ByteString
fetchFilePS (String
repo String -> ShowS
</> String
formatPath) Cachable
Cachable)
IO ByteString -> IO ByteString -> IO ByteString
forall a. IO a -> IO a -> IO a
`catchall` (ByteString -> IO ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
B.empty)
Either String RepoFormat
format <-
if ByteString -> Bool
B.null ByteString
formatInfo Bool -> Bool -> Bool
|| Char -> ByteString -> Bool
BC.elem Char
'<' ByteString
formatInfo then do
String -> String -> IO ()
finishedOneIO String
k String
"inventory"
Maybe String
missingInvErr <- String -> IO (Maybe String)
checkFile (String
repo String -> ShowS
</> String
oldInventoryPath)
case Maybe String
missingInvErr of
Maybe String
Nothing -> Either String RepoFormat -> IO (Either String RepoFormat)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String RepoFormat -> IO (Either String RepoFormat))
-> (RepoFormat -> Either String RepoFormat)
-> RepoFormat
-> IO (Either String RepoFormat)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RepoFormat -> Either String RepoFormat
forall a b. b -> Either a b
Right (RepoFormat -> IO (Either String RepoFormat))
-> RepoFormat -> IO (Either String RepoFormat)
forall a b. (a -> b) -> a -> b
$ [[RepoProperty]] -> RepoFormat
RF [[RepoProperty
Darcs1]]
Just String
e -> Either String RepoFormat -> IO (Either String RepoFormat)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String RepoFormat -> IO (Either String RepoFormat))
-> (String -> Either String RepoFormat)
-> String
-> IO (Either String RepoFormat)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Either String RepoFormat
forall a b. a -> Either a b
Left (String -> IO (Either String RepoFormat))
-> String -> IO (Either String RepoFormat)
forall a b. (a -> b) -> a -> b
$ ShowS
makeErrorMsg String
e
else Either String RepoFormat -> IO (Either String RepoFormat)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String RepoFormat -> IO (Either String RepoFormat))
-> (RepoFormat -> Either String RepoFormat)
-> RepoFormat
-> IO (Either String RepoFormat)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RepoFormat -> Either String RepoFormat
forall a b. b -> Either a b
Right (RepoFormat -> IO (Either String RepoFormat))
-> RepoFormat -> IO (Either String RepoFormat)
forall a b. (a -> b) -> a -> b
$ ByteString -> RepoFormat
readFormat ByteString
formatInfo
String -> IO ()
endTedious String
k
Either String RepoFormat -> IO (Either String RepoFormat)
forall (m :: * -> *) a. Monad m => a -> m a
return Either String RepoFormat
format
where
readFormat :: ByteString -> RepoFormat
readFormat =
[[RepoProperty]] -> RepoFormat
RF ([[RepoProperty]] -> RepoFormat)
-> (ByteString -> [[RepoProperty]]) -> ByteString -> RepoFormat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([ByteString] -> [RepoProperty])
-> [[ByteString]] -> [[RepoProperty]]
forall a b. (a -> b) -> [a] -> [b]
map ((ByteString -> RepoProperty) -> [ByteString] -> [RepoProperty]
forall a b. (a -> b) -> [a] -> [b]
map (ByteString -> RepoProperty
readRepoProperty (ByteString -> RepoProperty)
-> (ByteString -> ByteString) -> ByteString -> RepoProperty
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
fixupUnknownFormat)) ([[ByteString]] -> [[RepoProperty]])
-> (ByteString -> [[ByteString]]) -> ByteString -> [[RepoProperty]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [[ByteString]]
splitFormat
fixupUnknownFormat :: ByteString -> ByteString
fixupUnknownFormat ByteString
s =
case ByteString -> ByteString -> Maybe ByteString
B.stripPrefix ByteString
"Unknown format: " ByteString
s of
Maybe ByteString
Nothing -> ByteString
s
Just ByteString
s' -> ByteString -> ByteString
fixupUnknownFormat ByteString
s'
splitFormat :: ByteString -> [[ByteString]]
splitFormat = (ByteString -> [ByteString]) -> [ByteString] -> [[ByteString]]
forall a b. (a -> b) -> [a] -> [b]
map (Char -> ByteString -> [ByteString]
BC.split Char
'|') ([ByteString] -> [[ByteString]])
-> (ByteString -> [ByteString]) -> ByteString -> [[ByteString]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> Bool) -> [ByteString] -> [ByteString]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (ByteString -> Bool) -> ByteString -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Bool
B.null) ([ByteString] -> [ByteString])
-> (ByteString -> [ByteString]) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
linesPS
checkFile :: String -> IO (Maybe String)
checkFile String
path = (String -> Cachable -> IO ByteString
fetchFilePS String
path Cachable
Cachable IO ByteString -> IO (Maybe String) -> IO (Maybe String)
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe String -> IO (Maybe String)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe String
forall a. Maybe a
Nothing)
IO (Maybe String)
-> (SomeException -> IO (Maybe String)) -> IO (Maybe String)
forall a. IO a -> (SomeException -> IO a) -> IO a
`catchNonSignal`
(Maybe String -> IO (Maybe String)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe String -> IO (Maybe String))
-> (SomeException -> Maybe String)
-> SomeException
-> IO (Maybe String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String)
-> (SomeException -> String) -> SomeException -> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SomeException -> String
prettyException)
makeErrorMsg :: ShowS
makeErrorMsg String
e = String
"Not a repository: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
repo String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
e String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
writeRepoFormat :: RepoFormat -> FilePath -> IO ()
writeRepoFormat :: RepoFormat -> String -> IO ()
writeRepoFormat RepoFormat
rf String
loc = String -> ByteString -> IO ()
forall p. FilePathLike p => p -> ByteString -> IO ()
writeBinFile String
loc (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> ByteString
BC.pack (String -> ByteString) -> String -> ByteString
forall a b. (a -> b) -> a -> b
$ RepoFormat -> String
forall a. Show a => a -> String
show RepoFormat
rf
createRepoFormat :: F.PatchFormat -> F.WithWorkingDir -> RepoFormat
createRepoFormat :: PatchFormat -> WithWorkingDir -> RepoFormat
createRepoFormat PatchFormat
fmt WithWorkingDir
wwd = [[RepoProperty]] -> RepoFormat
RF ([[RepoProperty]] -> RepoFormat) -> [[RepoProperty]] -> RepoFormat
forall a b. (a -> b) -> a -> b
$ (RepoProperty
HashedInventory RepoProperty -> [RepoProperty] -> [RepoProperty]
forall a. a -> [a] -> [a]
: WithWorkingDir -> [RepoProperty]
flags2wd WithWorkingDir
wwd) [RepoProperty] -> [[RepoProperty]] -> [[RepoProperty]]
forall a. a -> [a] -> [a]
: PatchFormat -> [[RepoProperty]]
flags2format PatchFormat
fmt
where
flags2format :: PatchFormat -> [[RepoProperty]]
flags2format PatchFormat
F.PatchFormat1 = []
flags2format PatchFormat
F.PatchFormat2 = [[RepoProperty
Darcs2]]
flags2format PatchFormat
F.PatchFormat3 = [[RepoProperty
Darcs3]]
flags2wd :: WithWorkingDir -> [RepoProperty]
flags2wd WithWorkingDir
F.NoWorkingDir = [RepoProperty
NoWorkingDir]
flags2wd WithWorkingDir
F.WithWorkingDir = []
writeProblem :: RepoFormat -> Maybe String
writeProblem :: RepoFormat -> Maybe String
writeProblem RepoFormat
target = RepoFormat -> Maybe String
readProblem RepoFormat
target Maybe String -> Maybe String -> Maybe String
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` RepoFormat -> ([RepoProperty] -> Maybe String) -> Maybe String
findProblems RepoFormat
target [RepoProperty] -> Maybe String
wp
where
wp :: [RepoProperty] -> Maybe String
wp [] = String -> Maybe String
forall a. HasCallStack => String -> a
error String
"impossible case"
wp [RepoProperty]
x = case (RepoProperty -> Bool)
-> [RepoProperty] -> ([RepoProperty], [RepoProperty])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition RepoProperty -> Bool
isKnown [RepoProperty]
x of
([RepoProperty]
_, []) -> Maybe String
forall a. Maybe a
Nothing
([RepoProperty]
_, [RepoProperty]
unknowns) -> String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String)
-> ([String] -> String) -> [String] -> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unwords ([String] -> Maybe String) -> [String] -> Maybe String
forall a b. (a -> b) -> a -> b
$
String
"Can't write repository: unknown formats:" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: (RepoProperty -> String) -> [RepoProperty] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map RepoProperty -> String
forall a. Show a => a -> String
show [RepoProperty]
unknowns
transferProblem :: RepoFormat -> RepoFormat -> Maybe String
transferProblem :: RepoFormat -> RepoFormat -> Maybe String
transferProblem RepoFormat
source RepoFormat
target
| RepoProperty -> RepoFormat -> Bool
formatHas RepoProperty
Darcs3 RepoFormat
source Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
/= RepoProperty -> RepoFormat -> Bool
formatHas RepoProperty
Darcs3 RepoFormat
target =
String -> Maybe String
forall a. a -> Maybe a
Just String
"Cannot mix darcs-3 repositories with older formats"
| RepoProperty -> RepoFormat -> Bool
formatHas RepoProperty
Darcs2 RepoFormat
source Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
/= RepoProperty -> RepoFormat -> Bool
formatHas RepoProperty
Darcs2 RepoFormat
target =
String -> Maybe String
forall a. a -> Maybe a
Just String
"Cannot mix darcs-2 repositories with older formats"
| RepoProperty -> RepoFormat -> Bool
formatHas RepoProperty
RebaseInProgress RepoFormat
source =
String -> Maybe String
forall a. a -> Maybe a
Just String
"Cannot transfer patches from a repository \
\where an old-style rebase is in progress"
| Bool
otherwise = RepoFormat -> Maybe String
readProblem RepoFormat
source Maybe String -> Maybe String -> Maybe String
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` RepoFormat -> Maybe String
writeProblem RepoFormat
target
readProblem :: RepoFormat -> Maybe String
readProblem :: RepoFormat -> Maybe String
readProblem RepoFormat
source
| RepoProperty -> RepoFormat -> Bool
formatHas RepoProperty
Darcs1 RepoFormat
source Bool -> Bool -> Bool
&& RepoProperty -> RepoFormat -> Bool
formatHas RepoProperty
Darcs2 RepoFormat
source =
String -> Maybe String
forall a. a -> Maybe a
Just String
"Invalid repository format: format 2 is incompatible with format 1"
| RepoProperty -> RepoFormat -> Bool
formatHas RepoProperty
RebaseInProgress RepoFormat
source Bool -> Bool -> Bool
&& RepoProperty -> RepoFormat -> Bool
formatHas RepoProperty
RebaseInProgress_2_16 RepoFormat
source =
String -> Maybe String
forall a. a -> Maybe a
Just String
"Invalid repository format: \
\cannot have both old-style and new-style rebase in progress"
readProblem RepoFormat
source = RepoFormat -> ([RepoProperty] -> Maybe String) -> Maybe String
findProblems RepoFormat
source [RepoProperty] -> Maybe String
rp
where
rp :: [RepoProperty] -> Maybe String
rp [RepoProperty]
x | (RepoProperty -> Bool) -> [RepoProperty] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any RepoProperty -> Bool
isKnown [RepoProperty]
x = Maybe String
forall a. Maybe a
Nothing
rp [] = String -> Maybe String
forall a. HasCallStack => String -> a
error String
"impossible case"
rp [RepoProperty]
x = String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String)
-> ([String] -> String) -> [String] -> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unwords ([String] -> Maybe String) -> [String] -> Maybe String
forall a b. (a -> b) -> a -> b
$ String
"Can't read repository: unknown formats:" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: (RepoProperty -> String) -> [RepoProperty] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map RepoProperty -> String
forall a. Show a => a -> String
show [RepoProperty]
x
findProblems :: RepoFormat -> ([RepoProperty] -> Maybe String) -> Maybe String
findProblems :: RepoFormat -> ([RepoProperty] -> Maybe String) -> Maybe String
findProblems (RF [[RepoProperty]]
ks) [RepoProperty] -> Maybe String
formatHasProblem = case ([RepoProperty] -> Maybe String) -> [[RepoProperty]] -> [String]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe [RepoProperty] -> Maybe String
formatHasProblem [[RepoProperty]]
ks of
[] -> Maybe String
forall a. Maybe a
Nothing
[String]
xs -> String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines [String]
xs
isKnown :: RepoProperty -> Bool
isKnown :: RepoProperty -> Bool
isKnown RepoProperty
p = RepoProperty
p RepoProperty -> [RepoProperty] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [RepoProperty]
knownProperties
where
knownProperties :: [RepoProperty]
knownProperties :: [RepoProperty]
knownProperties = [ RepoProperty
Darcs1
, RepoProperty
Darcs2
, RepoProperty
Darcs3
, RepoProperty
HashedInventory
, RepoProperty
NoWorkingDir
, RepoProperty
RebaseInProgress
, RepoProperty
RebaseInProgress_2_16
]