Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#101] Support GHC-8.10 #102

Merged
merged 2 commits into from
May 21, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ jobs:
runs-on: ubuntu-16.04
strategy:
matrix:
ghc: ["8.8.3"]
cabal: ["3.0"]
ghc:
- "8.8.3"
- "8.10.1"

steps:
- uses: actions/checkout@v2
Expand All @@ -40,4 +42,4 @@ jobs:

- name: Test
run: |
cabal test --enable-tests
cabal test --enable-tests
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ matrix:

install:
# HLint check
- curl https://raw.githubusercontent.com/kowainik/relude/v0.6.0.0/.hlint.yaml -o .hlint-relude.yaml
- curl https://raw.githubusercontent.com/kowainik/relude/v0.7.0.0/.hlint.yaml -o .hlint-relude.yaml
- curl -sSL https://raw.github.com/ndmitchell/hlint/master/misc/run.sh | sh -s src/ test/ -h .hlint-relude.yaml

# install stack and build project
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@
`life-sync` uses [PVP Versioning][1].
The change log is available [on GitHub][2].

## 1.1.1.0 — May 21, 2020

* [#101](https://github.com/kowainik/life-sync/issues/101):
Support GHC-8.10.1.
* [#98](https://github.com/kowainik/life-sync/issues/98):
Use `relude-0.7.0.0`.
* [#100](https://github.com/kowainik/life-sync/issues/100):
Use `tomland-1.3.0.0`.
* [#97](https://github.com/kowainik/life-sync/issues/97):
Use `validation-selective-0.1.0.0`.
* [#96](https://github.com/kowainik/life-sync/issues/97):
Use `colourista-0.1.0.0`.
* Use `path-0.7.0`.

## 1.1.0.0 — Mar 25, 2020

* [#36](https://github.com/kowainik/life-sync/issues/36):
Expand Down
30 changes: 16 additions & 14 deletions life-sync.cabal
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
cabal-version: 2.4
name: life-sync
version: 1.1.0.0
version: 1.1.1.0
synopsis: Synchronize personal configs across multiple machines.
description: Synchronize personal configs across multiple machines.
See README for more details.
See [README](https://github.com/kowainik/life-sync#life-sync) for more details.
homepage: https://github.com/kowainik/life-sync
bug-reports: https://github.com/kowainik/life-sync/issues
license: MPL-2.0
Expand All @@ -17,19 +17,19 @@ build-type: Simple
extra-doc-files: README.md
CHANGELOG.md
tested-with: GHC == 8.8.3
GHC == 8.10.1

source-repository head
type: git
location: https://github.com/kowainik/life-sync.git

common common-options
build-depends: base ^>= 4.13.0.0
, relude ^>= 0.6.0.0
build-depends: base >= 4.13.0.0 && < 4.15
, relude ^>= 0.7.0.0

mixins: base hiding (Prelude)
, relude (Relude as Prelude
, Relude.Extra.Lens
, Relude.Unsafe
)

ghc-options: -Wall
Expand All @@ -44,6 +44,8 @@ common common-options
if impl(ghc >= 8.8.1)
ghc-options: -Wmissing-deriving-strategies
-Werror=missing-deriving-strategies
if impl(ghc >= 8.10)
ghc-options: -Wunused-packages

default-language: Haskell2010
default-extensions: ConstraintKinds
Expand Down Expand Up @@ -78,18 +80,17 @@ library
Life.Message
Life.Path

build-depends: bytestring
, colourista ^>= 0.0.0.0
, containers
, exceptions
build-depends: bytestring ^>= 0.10
, colourista ^>= 0.1.0.0
, containers ^>= 0.6
, exceptions ^>= 0.10.0
, optparse-applicative ^>= 0.15
, path
, path-io
, process
, path == 0.7.0
, path-io ^>= 1.6.0
, shellmet ^>= 0.0.3.0
, text ^>= 1.2
, tomland ^>= 1.2.1.0
, validation-selective ^>= 0.0.0.0
, tomland ^>= 1.3.0.0
, validation-selective ^>= 0.1.0.0

executable life
import: common-options
Expand All @@ -114,3 +115,4 @@ test-suite life-sync-test
, hspec-hedgehog ^>= 0.0.1.1
, path
, text
, tomland
39 changes: 16 additions & 23 deletions src/Life/Configuration.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ module Life.Configuration

, lifeConfigMinus

-- Config
, CorpseConfiguration (..)
, corpseConfiguationCodec
, resurrect

-- -- * Parsing exceptions
-- , ParseLifeException (..)

Expand All @@ -25,15 +30,14 @@ module Life.Configuration
-- * Parse 'LifeConfiguration' under @~/.life@
, parseHomeLife
, parseRepoLife
, parseLifeConfiguration

-- * Render 'LifeConfiguration' under @~/.life@
, renderLifeConfiguration
, writeGlobalLife
) where

import Control.Monad.Catch (MonadThrow (..))
import Path (Dir, File, Path, Rel, fromAbsFile, parseRelDir, parseRelFile, toFilePath, (</>))
import Path (Dir, File, Path, Rel, fromAbsFile, parseRelDir, parseRelFile, (</>))
import Relude.Extra.Lens (Lens', lens, (.~), (^.))
import Toml (TomlCodec, (.=))

Expand All @@ -42,7 +46,6 @@ import Life.Path (lifePath, relativeToHome, repoName)

import qualified Data.Set as Set
import qualified Data.Text as T
import qualified Text.Show as Show
import qualified Toml


Expand Down Expand Up @@ -124,8 +127,8 @@ data CorpseConfiguration = CorpseConfiguration
, corpseDirectories :: [FilePath]
}

corpseConfiguationT :: TomlCodec CorpseConfiguration
corpseConfiguationT = CorpseConfiguration
corpseConfiguationCodec :: TomlCodec CorpseConfiguration
corpseConfiguationCodec = CorpseConfiguration
<$> Toml.arrayOf Toml._String "files" .= corpseFiles
<*> Toml.arrayOf Toml._String "directories" .= corpseDirectories

Expand All @@ -142,9 +145,10 @@ resurrect CorpseConfiguration{..} = do

-- TODO: should tomland one day support this?...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. I guess we can create an issue in tomland for adding Boolean variable to print lists on each own line. And once this issue is implemented, we should be able to remove most of the logic from here. Do you think it's worth it to support such configuration in tomland?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've created: kowainik/tomland#325

-- | Converts 'LifeConfiguration' into TOML file.
renderLifeConfiguration :: Bool -- ^ True to see empty entries in output
-> LifeConfiguration
-> Text
renderLifeConfiguration
:: Bool -- ^ True to see empty entries in output
-> LifeConfiguration
-> Text
renderLifeConfiguration printIfEmpty LifeConfiguration{..} = mconcat $
maybeToList (render "directories" lifeConfigurationDirectories)
++ [ "\n" ]
Expand Down Expand Up @@ -177,15 +181,11 @@ writeGlobalLife config = do
-- Life configuration parsing
----------------------------------------------------------------------------

parseLifeConfiguration :: MonadThrow m => Text -> m LifeConfiguration
parseLifeConfiguration tomlText = case Toml.decode corpseConfiguationT tomlText of
Left err -> throwM $ LoadTomlException (toFilePath lifePath) $ Toml.prettyException err
Right cfg -> resurrect cfg

parseLife :: Path Rel File -> IO LifeConfiguration
parseLife path = relativeToHome path
>>= readFileText . fromAbsFile
>>= parseLifeConfiguration
parseLife path =
relativeToHome path
>>= Toml.decodeFile corpseConfiguationCodec . fromAbsFile
>>= resurrect

-- | Reads 'LifeConfiguration' from @~\/.life@ file.
parseHomeLife :: IO LifeConfiguration
Expand All @@ -194,10 +194,3 @@ parseHomeLife = parseLife lifePath
-- | Reads 'LifeConfiguration' from @~\/dotfiles\/.life@ file.
parseRepoLife :: IO LifeConfiguration
parseRepoLife = parseLife (repoName </> lifePath)

data LoadTomlException = LoadTomlException FilePath Text

instance Show.Show LoadTomlException where
show (LoadTomlException filePath msg) = "Couldnt parse file " ++ filePath ++ ": " ++ show msg

instance Exception LoadTomlException
3 changes: 2 additions & 1 deletion src/Life/Github.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module Life.Github
, getUserLogin
) where

import Colourista (errorMessage, infoMessage, warningMessage)
import Control.Exception (catch, throwIO)
import Path (Abs, Dir, File, Path, Rel, toFilePath, (</>))
import Path.IO (copyDirRecur, copyFile, getHomeDir, withCurrentDir)
Expand All @@ -35,7 +36,7 @@ import System.IO.Error (IOError, isDoesNotExistError)

import Life.Configuration (LifeConfiguration (..), lifeConfigMinus, parseRepoLife)
import Life.Core (Branch (..), CommitMsg (..), CopyDirection (..), Owner (..), Repo (..), master)
import Life.Message (chooseYesNo, errorMessage, infoMessage, warningMessage)
import Life.Message (chooseYesNo)
import Life.Path (lifePath, relativeToHome, repoName)

import qualified Data.Text as Text
Expand Down
3 changes: 2 additions & 1 deletion src/Life/Main/Add.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module Life.Main.Add
( lifeAdd
) where

import Colourista (errorMessage, infoMessage, warningMessage)
import Path (Abs, Dir, File, Path, Rel, parent, toFilePath, (</>))
import Path.IO (copyDirRecur, copyFile, doesDirExist, doesFileExist, ensureDir, getHomeDir,
makeRelative, resolveDir, resolveFile)
Expand All @@ -21,7 +22,7 @@ import Life.Configuration (LifeConfiguration, directoriesL, filesL, parseHomeLif
import Life.Core (LifePath (..), master)
import Life.Github (addToRepo, withSynced)
import Life.Main.Init (lifeInitQuestion)
import Life.Message (abortCmd, errorMessage, infoMessage, warningMessage)
import Life.Message (abortCmd)
import Life.Path (LifeExistence (..), relativeToHome, repoName, whatIsLife)

import qualified Data.Set as Set
Expand Down
5 changes: 3 additions & 2 deletions src/Life/Main/Init.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ module Life.Main.Init
, lifeInitQuestion
) where

import Colourista (infoMessage, skipMessage, successMessage, warningMessage)
import Path (mkRelFile)
import Path.IO (doesDirExist, doesFileExist)


import Life.Configuration (LifeConfiguration (..), parseHomeLife, renderLifeConfiguration,
singleFileConfig, writeGlobalLife)
import Life.Core (CopyDirection (..), Owner (..), Repo (..), master)
import Life.Github (copyLife, createRepository, insideRepo)
import Life.Message (abortCmd, chooseYesNo, infoMessage, promptNonEmpty, skipMessage,
successMessage, warningMessage)
import Life.Message (abortCmd, chooseYesNo, promptNonEmpty)
import Life.Path (LifeExistence (..), createDirInHome, lifePath, relativeToHome, repoName,
whatIsLife)

Expand Down
8 changes: 5 additions & 3 deletions src/Life/Main/Pull.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ module Life.Main.Pull
( lifePull
) where

import Colourista (warningMessage)
import Path (Dir, File, Path, Rel)

import Life.Configuration (LifeConfiguration (..), defaultLifeConfig)
import Life.Core (Owner)
import Life.Github (cloneRepo, pullUpdateFromRepo, updateFromRepo)
import Life.Main.Init (lifeInitQuestion)
import Life.Message (abortCmd, choose, warningMessage)
import Life.Message (abortCmd, choose)
import Life.Path (LifeExistence (..), whatIsLife)


Expand All @@ -30,8 +31,9 @@ lifePull owner withoutFiles withoutDirs = whatIsLife >>= \case
initOrPull :: IO ()
initOrPull = do
warningMessage ".life file and dotfiles repo not found"
action <- choose "Do you want to (F)etch existing repo, (I)nit from scratch or (A)bort operation?"
["f", "i", "a"]
action <- choose
"Do you want to (F)etch existing repo, (I)nit from scratch or (A)bort operation?"
("f" :| ["i", "a"])
case action of
"f" -> clone >> update
"i" -> lifeInitQuestion "pull" pass
Expand Down
3 changes: 2 additions & 1 deletion src/Life/Main/Remove.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ module Life.Main.Remove
( lifeRemove
) where

import Colourista (warningMessage)
import Path (Abs, Path, Rel)
import Path.IO (getHomeDir, makeRelative, removeDirRecur, removeFile, resolveDir, resolveFile)
import Relude.Extra.Lens (Lens', (%~))

import Life.Configuration (LifeConfiguration, directoriesL, filesL, parseHomeLife, writeGlobalLife)
import Life.Core (LifePath (..), master)
import Life.Github (removeFromRepo, withSynced)
import Life.Message (abortCmd, warningMessage)
import Life.Message (abortCmd)
import Life.Path (LifeExistence (..), whatIsLife)

import qualified Data.Set as Set
Expand Down
30 changes: 7 additions & 23 deletions src/Life/Message.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,17 @@ messages.
module Life.Message
( prompt
, promptNonEmpty
, errorMessage
, warningMessage
, successMessage
, infoMessage
, skipMessage
, abortCmd

-- * Questions
, choose
, chooseYesNo
) where

import Colourista (blue, bold, formatWith)
import Colourista (blue, bold, errorMessage, formatWith, warningMessage)
import System.IO (hFlush)

import qualified Colourista
import qualified Data.Text as T
import qualified Relude.Unsafe as Unsafe


----------------------------------------------------------------------------
Expand Down Expand Up @@ -60,17 +53,6 @@ promptNonEmpty = do
boldDefault :: Text -> Text
boldDefault message = formatWith [bold] $ " [" <> message <> "]"

errorMessage, warningMessage, successMessage, infoMessage, skipMessage :: Text -> IO ()
errorMessage = Colourista.errorMessage . indent
warningMessage = Colourista.warningMessage . indent
successMessage = Colourista.successMessage . indent
infoMessage = Colourista.infoMessage . indent
skipMessage = Colourista.skipMessage . indent

-- | Add 2 spaces in front.
indent :: Text -> Text
indent = (" " <>)

-- | Print message and abort current process.
abortCmd :: Text -> Text -> IO ()
abortCmd cmd msg = do
Expand All @@ -89,17 +71,19 @@ printQuestion question (def:rest) = do
putStrFlush $ question <> boldDefault def
putTextLn $ "/" <> restSlash

choose :: Text -> [Text] -> IO Text
choose :: Text -> NonEmpty Text -> IO Text
choose question choices = do
printQuestion question choices
printQuestion question $ toList choices
answer <- prompt
if | T.null answer -> pure (Unsafe.head choices)
if | T.null answer -> pure (head choices)
| T.toLower answer `elem` choices -> pure answer
| otherwise -> do
errorMessage "This wasn't a valid choice."
choose question choices

data Answer = Y | N
data Answer
= Y
| N

yesOrNo :: Text -> Maybe Answer
yesOrNo (T.toLower -> answer )
Expand Down
Loading