life-sync-1.0: src/Life/Main/Init.hs
{-# LANGUAGE TemplateHaskell #-}
-- | Contains function to create repository.
module Life.Main.Init
( lifeInit
, lifeInitQuestion
) where
import Path (mkRelFile)
import Path.IO (doesDirExist, doesFileExist)
import Life.Configuration (LifeConfiguration (..), parseHomeLife, renderLifeConfiguration,
singleFileConfig, writeGlobalLife)
import Life.Github (CopyDirection (..), Owner (..), Repo (Repo), copyLife, createRepository,
insideRepo)
import Life.Message (abortCmd, chooseYesNo, infoMessage, promptNonEmpty, skipMessage,
successMessage, warningMessage)
import Life.Shell (LifeExistence (..), createDirInHome, lifePath, relativeToHome, repoName,
whatIsLife)
import qualified Data.Set as Set
predefinedLifeConfig :: LifeConfiguration
predefinedLifeConfig = mempty
{ lifeConfigurationFiles = Set.fromList
[ $(mkRelFile ".bash_profile")
, $(mkRelFile ".profile")
, $(mkRelFile ".vimrc")
, $(mkRelFile ".emacs")
, $(mkRelFile ".spacemacs")
, $(mkRelFile ".gitconfig")
, $(mkRelFile ".ghc/ghci.conf")
, $(mkRelFile ".stylish-haskell.yaml")
]
}
lifeInit :: Owner -> IO ()
lifeInit owner = whatIsLife >>= \case
NoLife -> createLifeFile >>= createDotfilesDir
OnlyLife _ -> askCreateLife >>= createDotfilesDir
OnlyRepo _ -> abortCmd "init" "'~/dotfiles' directory already exist" -- TODO: initialize .life from repo? :thinking_suicide:
Both _ _ -> abortCmd "init" "'~/.life' file and '~/.dotfiles' directory are already initialized"
where
askCreateLife :: IO LifeConfiguration
askCreateLife = do
warningMessage ".life file is already exist."
useIt <- chooseYesNo "Would you like to use it?"
if useIt then parseHomeLife else createLifeFile
createLifeFile :: IO LifeConfiguration
createLifeFile = do
infoMessage "Checking existence of some commonly used predefined files..."
(exist, noExist) <- scanConfig predefinedLifeConfig
unless (noExist == mempty) $ do
infoMessage "The following files and directories weren't found; they won't be added to '~/.life' file:"
skipMessage $ renderLifeConfiguration False noExist
unless (exist == mempty) $ do
infoMessage "Found the following files and directories:"
successMessage $ renderLifeConfiguration False exist
useDiscovered <- chooseYesNo "Would you like to add all discovered existing files and directories to .life configuration?"
let lifeConfig = singleFileConfig lifePath <> (if useDiscovered then exist else mempty)
infoMessage "Initializing global .life configuration file..."
writeGlobalLife lifeConfig
pure lifeConfig
createDotfilesDir :: LifeConfiguration -> IO ()
createDotfilesDir lifeConfig = do
() <$ createDirInHome repoName
insideRepo $ do
copyLife FromHomeToRepo lifeConfig
createRepository owner (Repo "dotfiles")
{- | Split given configuration into two:
1. All files and directories which exist on machine.
2. Other non-existing files and dirs.
-}
scanConfig :: LifeConfiguration -> IO (LifeConfiguration, LifeConfiguration)
scanConfig LifeConfiguration{..} = do
(existingFiles, nonExistingFiles) <- partitionM (relativeToHome >=> doesFileExist) lifeConfigurationFiles
(existingDirs, nonExistingDirs) <- partitionM (relativeToHome >=> doesDirExist) lifeConfigurationDirectories
pure ( LifeConfiguration (Set.fromList existingFiles) (Set.fromList existingDirs)
, LifeConfiguration (Set.fromList nonExistingFiles) (Set.fromList nonExistingDirs)
)
partitionM :: forall f m a . (Monad m, Foldable f) => (a -> m Bool) -> f a -> m ([a], [a])
partitionM check = foldM partitionAction ([], [])
where
partitionAction :: ([a], [a]) -> a -> m ([a], [a])
partitionAction (ifTrue, ifFalse) a = check a >>= \case
True -> pure (a : ifTrue, ifFalse)
False -> pure (ifTrue, a : ifFalse)
-- | If @.life@ and @dotfiles@ are not present you could want
-- to ask one if it needed to be initialised.
lifeInitQuestion :: Text -- ^ Command name
-> IO () -- ^ Process to do
-> IO ()
lifeInitQuestion cmd process = do
warningMessage ".life file and dotfiles/ do not exist"
toInit <- chooseYesNo "Would you like to proceed initialization process?"
if toInit then do
infoMessage "Initialization process starts.."
skipMessage "Insert your GitHub username:"
owner <- promptNonEmpty
lifeInit $ Owner owner
process
else abortCmd cmd "'~/.life' file is not initialized"