Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 16e20ed474 |
@@ -44,6 +44,7 @@ import Brick.Widgets.Center ( center, centerLayer )
|
|||||||
import qualified Brick.Widgets.List as L
|
import qualified Brick.Widgets.List as L
|
||||||
import Brick.Focus (FocusRing)
|
import Brick.Focus (FocusRing)
|
||||||
import qualified Brick.Focus as F
|
import qualified Brick.Focus as F
|
||||||
|
import Codec.Archive
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ packages: ./ghcup.cabal
|
|||||||
optional-packages: ./vendored/*/*.cabal
|
optional-packages: ./vendored/*/*.cabal
|
||||||
|
|
||||||
package ghcup
|
package ghcup
|
||||||
flags: +tui +tar
|
flags: +tui
|
||||||
|
|
||||||
constraints: http-io-streams -brotli,
|
constraints: http-io-streams -brotli,
|
||||||
any.aeson >= 2.0.1.0
|
any.aeson >= 2.0.1.0
|
||||||
@@ -13,11 +13,6 @@ source-repository-package
|
|||||||
location: https://github.com/fosskers/versions.git
|
location: https://github.com/fosskers/versions.git
|
||||||
tag: 7bc3355348aac3510771d4622aff09ac38c9924d
|
tag: 7bc3355348aac3510771d4622aff09ac38c9924d
|
||||||
|
|
||||||
source-repository-package
|
|
||||||
type: git
|
|
||||||
location: https://github.com/haskell/tar.git
|
|
||||||
tag: d94a988be4311b830149a9f8fc16739927e5fc1c
|
|
||||||
|
|
||||||
package libarchive
|
package libarchive
|
||||||
flags: -system-libarchive
|
flags: -system-libarchive
|
||||||
|
|
||||||
@@ -35,6 +30,3 @@ package streamly
|
|||||||
|
|
||||||
package *
|
package *
|
||||||
test-show-details: direct
|
test-show-details: direct
|
||||||
|
|
||||||
allow-newer: cabal-install-parsers:tar
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ optional-packages: ./vendored/*/*.cabal
|
|||||||
optimization: 2
|
optimization: 2
|
||||||
|
|
||||||
package ghcup
|
package ghcup
|
||||||
flags: +tui -tar
|
flags: +tui
|
||||||
|
|
||||||
if os(linux)
|
if os(linux)
|
||||||
if arch(x86_64) || arch(i386)
|
if arch(x86_64) || arch(i386)
|
||||||
|
|||||||
26
ghcup.cabal
26
ghcup.cabal
@@ -53,11 +53,6 @@ flag no-exe
|
|||||||
default: False
|
default: False
|
||||||
manual: True
|
manual: True
|
||||||
|
|
||||||
flag tar
|
|
||||||
description: Use haskell tar instead of libarchive.
|
|
||||||
default: False
|
|
||||||
manual: True
|
|
||||||
|
|
||||||
common app-common-depends
|
common app-common-depends
|
||||||
build-depends:
|
build-depends:
|
||||||
, aeson >=1.4
|
, aeson >=1.4
|
||||||
@@ -73,6 +68,7 @@ common app-common-depends
|
|||||||
, filepath ^>=1.4.2.1
|
, filepath ^>=1.4.2.1
|
||||||
, haskus-utils-types ^>=1.5
|
, haskus-utils-types ^>=1.5
|
||||||
, haskus-utils-variant ^>=3.2.1
|
, haskus-utils-variant ^>=3.2.1
|
||||||
|
, libarchive ^>=3.0.3.0
|
||||||
, megaparsec >=8.0.0 && <9.3
|
, megaparsec >=8.0.0 && <9.3
|
||||||
, mtl ^>=2.2
|
, mtl ^>=2.2
|
||||||
, optparse-applicative >=0.15.1.0 && <0.18
|
, optparse-applicative >=0.15.1.0 && <0.18
|
||||||
@@ -94,15 +90,6 @@ common app-common-depends
|
|||||||
, versions >=6.0.3 && <6.1
|
, versions >=6.0.3 && <6.1
|
||||||
, yaml-streamly ^>=0.12.0
|
, yaml-streamly ^>=0.12.0
|
||||||
|
|
||||||
if flag(tar)
|
|
||||||
cpp-options: -DTAR
|
|
||||||
build-depends:
|
|
||||||
tar ^>=0.6.0.0
|
|
||||||
, zip ^>=2.0.0
|
|
||||||
|
|
||||||
else
|
|
||||||
build-depends: libarchive ^>=3.0.3.0
|
|
||||||
|
|
||||||
library
|
library
|
||||||
exposed-modules:
|
exposed-modules:
|
||||||
GHCup
|
GHCup
|
||||||
@@ -135,7 +122,6 @@ library
|
|||||||
GHCup.Types.Stack
|
GHCup.Types.Stack
|
||||||
GHCup.Utils
|
GHCup.Utils
|
||||||
GHCup.Utils.Dirs
|
GHCup.Utils.Dirs
|
||||||
GHCup.Utils.Tar
|
|
||||||
GHCup.Version
|
GHCup.Version
|
||||||
|
|
||||||
hs-source-dirs: lib
|
hs-source-dirs: lib
|
||||||
@@ -180,6 +166,7 @@ library
|
|||||||
, filepath ^>=1.4.2.1
|
, filepath ^>=1.4.2.1
|
||||||
, haskus-utils-types ^>=1.5
|
, haskus-utils-types ^>=1.5
|
||||||
, haskus-utils-variant ^>=3.2.1
|
, haskus-utils-variant ^>=3.2.1
|
||||||
|
, libarchive ^>=3.0.3.0
|
||||||
, lzma-static ^>=5.2.5.3
|
, lzma-static ^>=5.2.5.3
|
||||||
, megaparsec >=8.0.0 && <9.3
|
, megaparsec >=8.0.0 && <9.3
|
||||||
, mtl ^>=2.2
|
, mtl ^>=2.2
|
||||||
@@ -209,15 +196,6 @@ library
|
|||||||
, yaml-streamly ^>=0.12.0
|
, yaml-streamly ^>=0.12.0
|
||||||
, zlib ^>=0.6.2.2
|
, zlib ^>=0.6.2.2
|
||||||
|
|
||||||
if flag(tar)
|
|
||||||
cpp-options: -DTAR
|
|
||||||
build-depends:
|
|
||||||
tar ^>=0.6.0.0
|
|
||||||
, zip ^>=2.0.0
|
|
||||||
|
|
||||||
else
|
|
||||||
build-depends: libarchive ^>=3.0.3.0
|
|
||||||
|
|
||||||
if (flag(internal-downloader) && !os(windows))
|
if (flag(internal-downloader) && !os(windows))
|
||||||
exposed-modules: GHCup.Download.IOStreams
|
exposed-modules: GHCup.Download.IOStreams
|
||||||
cpp-options: -DINTERNAL_DOWNLOADER
|
cpp-options: -DINTERNAL_DOWNLOADER
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import GHCup.OptParse.Common
|
|||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
#endif
|
#endif
|
||||||
|
import Codec.Archive ( ArchiveResult )
|
||||||
import Control.Concurrent (threadDelay)
|
import Control.Concurrent (threadDelay)
|
||||||
import Control.Monad.Reader
|
import Control.Monad.Reader
|
||||||
import Control.Monad.Trans.Resource
|
import Control.Monad.Trans.Resource
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import GHCup.Prelude
|
|||||||
import GHCup.Prelude.Logger
|
import GHCup.Prelude.Logger
|
||||||
import GHCup.Prelude.String.QQ
|
import GHCup.Prelude.String.QQ
|
||||||
|
|
||||||
|
import Codec.Archive
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import Control.Exception.Safe ( MonadMask, MonadCatch )
|
|||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
#endif
|
#endif
|
||||||
|
import Codec.Archive
|
||||||
import Control.Monad.Reader
|
import Control.Monad.Reader
|
||||||
import Control.Monad.Trans.Resource
|
import Control.Monad.Trans.Resource
|
||||||
import Data.Functor
|
import Data.Functor
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import GHCup.Utils.Dirs
|
|||||||
import GHCup.Prelude.Logger
|
import GHCup.Prelude.Logger
|
||||||
import GHCup.Prelude.String.QQ
|
import GHCup.Prelude.String.QQ
|
||||||
|
|
||||||
|
import Codec.Archive
|
||||||
#if !MIN_VERSION_base(4,13,0)
|
#if !MIN_VERSION_base(4,13,0)
|
||||||
import Control.Monad.Fail ( MonadFail )
|
import Control.Monad.Fail ( MonadFail )
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import GHCup.Prelude
|
|||||||
import GHCup.Prelude.File
|
import GHCup.Prelude.File
|
||||||
import GHCup.Prelude.Logger
|
import GHCup.Prelude.Logger
|
||||||
|
|
||||||
|
import Codec.Archive ( ArchiveResult )
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
|
|||||||
@@ -21,9 +21,7 @@ module GHCup.Errors where
|
|||||||
|
|
||||||
import GHCup.Types
|
import GHCup.Types
|
||||||
|
|
||||||
#if !defined(TAR)
|
|
||||||
import Codec.Archive
|
import Codec.Archive
|
||||||
#endif
|
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
import Data.ByteString ( ByteString )
|
import Data.ByteString ( ByteString )
|
||||||
import Data.CaseInsensitive ( CI )
|
import Data.CaseInsensitive ( CI )
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import GHCup.Prelude.String.QQ
|
|||||||
import GHCup.Prelude.Version.QQ
|
import GHCup.Prelude.Version.QQ
|
||||||
import GHCup.Prelude.MegaParsec
|
import GHCup.Prelude.MegaParsec
|
||||||
|
|
||||||
|
import Codec.Archive ( ArchiveResult )
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Control.Concurrent ( threadDelay )
|
import Control.Concurrent ( threadDelay )
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
@@ -448,13 +449,30 @@ installUnpackedGHC path inst tver forceInstall addConfArgs
|
|||||||
= []
|
= []
|
||||||
|
|
||||||
lift $ logInfo "Installing GHC (this may take a while)"
|
lift $ logInfo "Installing GHC (this may take a while)"
|
||||||
|
env <- case _rPlatform of
|
||||||
|
-- https://github.com/haskell/ghcup-hs/issues/967
|
||||||
|
Linux Alpine
|
||||||
|
-- lets not touch LD for cross targets
|
||||||
|
| Nothing <- _tvTarget tver -> do
|
||||||
|
cEnv <- liftIO getEnvironment
|
||||||
|
spaths <- liftIO getSearchPath
|
||||||
|
has_ld_bfd <- isJust <$> liftIO (searchPath spaths "ld.bfd")
|
||||||
|
let ldSet = isJust $ lookup "LD" cEnv
|
||||||
|
-- only set LD if ld.bfd exists in PATH and LD is not set
|
||||||
|
-- already
|
||||||
|
if has_ld_bfd && not ldSet
|
||||||
|
then do
|
||||||
|
lift $ logInfo "Detected alpine linux... setting LD=ld.bfd"
|
||||||
|
pure $ Just (("LD", "ld.bfd") : cEnv)
|
||||||
|
else pure Nothing
|
||||||
|
_ -> pure Nothing
|
||||||
lEM $ execLogged "sh"
|
lEM $ execLogged "sh"
|
||||||
("./configure" : ("--prefix=" <> fromInstallDir inst)
|
("./configure" : ("--prefix=" <> fromInstallDir inst)
|
||||||
: (maybe mempty (\x -> ["--target=" <> T.unpack x]) (_tvTarget tver) <> ldOverride <> (T.unpack <$> addConfArgs))
|
: (maybe mempty (\x -> ["--target=" <> T.unpack x]) (_tvTarget tver) <> ldOverride <> (T.unpack <$> addConfArgs))
|
||||||
)
|
)
|
||||||
(Just $ fromGHCupPath path)
|
(Just $ fromGHCupPath path)
|
||||||
"ghc-configure"
|
"ghc-configure"
|
||||||
Nothing
|
env
|
||||||
tmpInstallDest <- lift withGHCupTmpDir
|
tmpInstallDest <- lift withGHCupTmpDir
|
||||||
lEM $ make ["DESTDIR=" <> fromGHCupPath tmpInstallDest, "install"] (Just $ fromGHCupPath path)
|
lEM $ make ["DESTDIR=" <> fromGHCupPath tmpInstallDest, "install"] (Just $ fromGHCupPath path)
|
||||||
liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform (fromGHCupPath tmpInstallDest)
|
liftE $ catchWarn $ lEM @_ @'[ProcessError] $ darwinNotarization _rPlatform (fromGHCupPath tmpInstallDest)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import GHCup.Prelude.Logger
|
|||||||
import GHCup.Prelude.Process
|
import GHCup.Prelude.Process
|
||||||
import GHCup.Prelude.String.QQ
|
import GHCup.Prelude.String.QQ
|
||||||
|
|
||||||
|
import Codec.Archive ( ArchiveResult )
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import GHCup.Prelude
|
|||||||
import GHCup.Prelude.File
|
import GHCup.Prelude.File
|
||||||
import GHCup.Prelude.Logger
|
import GHCup.Prelude.Logger
|
||||||
|
|
||||||
|
import Codec.Archive ( ArchiveResult )
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ module GHCup.Types
|
|||||||
, Key(..)
|
, Key(..)
|
||||||
, Modifier(..)
|
, Modifier(..)
|
||||||
#endif
|
#endif
|
||||||
, ArchiveResult(..)
|
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
@@ -32,11 +31,6 @@ import GHCup.Types.Stack ( SetupInfo )
|
|||||||
import {-# SOURCE #-} GHCup.Utils.Dirs ( fromGHCupPath, GHCupPath )
|
import {-# SOURCE #-} GHCup.Utils.Dirs ( fromGHCupPath, GHCupPath )
|
||||||
|
|
||||||
import Control.DeepSeq ( NFData, rnf )
|
import Control.DeepSeq ( NFData, rnf )
|
||||||
#if defined(TAR)
|
|
||||||
import Control.Exception ( Exception )
|
|
||||||
#else
|
|
||||||
import Codec.Archive ( ArchiveResult(..) )
|
|
||||||
#endif
|
|
||||||
import Data.Map.Strict ( Map )
|
import Data.Map.Strict ( Map )
|
||||||
import Data.List.NonEmpty ( NonEmpty (..) )
|
import Data.List.NonEmpty ( NonEmpty (..) )
|
||||||
import Data.Time.Calendar ( Day )
|
import Data.Time.Calendar ( Day )
|
||||||
@@ -782,18 +776,3 @@ data BuildSystem = Hadrian
|
|||||||
| Make
|
| Make
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
#if defined(TAR)
|
|
||||||
data ArchiveResult = ArchiveFatal
|
|
||||||
| ArchiveFailed
|
|
||||||
| ArchiveWarn
|
|
||||||
| ArchiveRetry
|
|
||||||
| ArchiveOk
|
|
||||||
| ArchiveEOF
|
|
||||||
deriving (Eq, Show, GHC.Generic)
|
|
||||||
|
|
||||||
instance NFData ArchiveResult
|
|
||||||
|
|
||||||
instance Exception ArchiveResult
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ installation and introspection of files/versions etc.
|
|||||||
-}
|
-}
|
||||||
module GHCup.Utils
|
module GHCup.Utils
|
||||||
( module GHCup.Utils.Dirs
|
( module GHCup.Utils.Dirs
|
||||||
, module GHCup.Utils.Tar
|
|
||||||
, module GHCup.Utils
|
, module GHCup.Utils
|
||||||
#if defined(IS_WINDOWS)
|
#if defined(IS_WINDOWS)
|
||||||
, module GHCup.Prelude.Windows
|
, module GHCup.Prelude.Windows
|
||||||
@@ -43,7 +42,6 @@ import GHCup.Types
|
|||||||
import GHCup.Types.Optics
|
import GHCup.Types.Optics
|
||||||
import GHCup.Types.JSON ( )
|
import GHCup.Types.JSON ( )
|
||||||
import GHCup.Utils.Dirs
|
import GHCup.Utils.Dirs
|
||||||
import GHCup.Utils.Tar
|
|
||||||
import GHCup.Version
|
import GHCup.Version
|
||||||
import GHCup.Prelude
|
import GHCup.Prelude
|
||||||
import GHCup.Prelude.File
|
import GHCup.Prelude.File
|
||||||
@@ -51,6 +49,7 @@ import GHCup.Prelude.Logger.Internal
|
|||||||
import GHCup.Prelude.MegaParsec
|
import GHCup.Prelude.MegaParsec
|
||||||
import GHCup.Prelude.Process
|
import GHCup.Prelude.Process
|
||||||
import GHCup.Prelude.String.QQ
|
import GHCup.Prelude.String.QQ
|
||||||
|
import Codec.Archive hiding ( Directory )
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
@@ -80,6 +79,10 @@ import Text.Regex.Posix
|
|||||||
import Text.PrettyPrint.HughesPJClass (prettyShow)
|
import Text.PrettyPrint.HughesPJClass (prettyShow)
|
||||||
import URI.ByteString
|
import URI.ByteString
|
||||||
|
|
||||||
|
import qualified Codec.Compression.BZip as BZip
|
||||||
|
import qualified Codec.Compression.GZip as GZip
|
||||||
|
import qualified Codec.Compression.Lzma as Lzma
|
||||||
|
import qualified Data.ByteString.Lazy as BL
|
||||||
import qualified Data.Map.Strict as Map
|
import qualified Data.Map.Strict as Map
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.Encoding as E
|
import qualified Data.Text.Encoding as E
|
||||||
@@ -780,6 +783,99 @@ getLatestToolFor tool target pvpIn dls = do
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-----------------
|
||||||
|
--[ Unpacking ]--
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- | Unpack an archive to a temporary directory and return that path.
|
||||||
|
unpackToDir :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m)
|
||||||
|
=> FilePath -- ^ destination dir
|
||||||
|
-> FilePath -- ^ archive path
|
||||||
|
-> Excepts '[UnknownArchive
|
||||||
|
, ArchiveResult
|
||||||
|
] m ()
|
||||||
|
unpackToDir dfp av = do
|
||||||
|
let fn = takeFileName av
|
||||||
|
lift $ logInfo $ "Unpacking: " <> T.pack fn <> " to " <> T.pack dfp
|
||||||
|
|
||||||
|
let untar :: MonadIO m => BL.ByteString -> Excepts '[ArchiveResult] m ()
|
||||||
|
untar = lEM . liftIO . runArchiveM . unpackToDirLazy dfp
|
||||||
|
|
||||||
|
rf :: MonadIO m => FilePath -> Excepts '[ArchiveResult] m BL.ByteString
|
||||||
|
rf = liftIO . BL.readFile
|
||||||
|
|
||||||
|
-- extract, depending on file extension
|
||||||
|
if
|
||||||
|
| ".tar.gz" `isSuffixOf` fn -> liftE
|
||||||
|
(untar . GZip.decompress =<< rf av)
|
||||||
|
| ".tar.xz" `isSuffixOf` fn -> do
|
||||||
|
filecontents <- liftE $ rf av
|
||||||
|
let decompressed = Lzma.decompressWith (Lzma.defaultDecompressParams { Lzma.decompressAutoDecoder= True }) filecontents
|
||||||
|
liftE $ untar decompressed
|
||||||
|
| ".tar.bz2" `isSuffixOf` fn ->
|
||||||
|
liftE (untar . BZip.decompress =<< rf av)
|
||||||
|
| ".tar" `isSuffixOf` fn -> liftE (untar =<< rf av)
|
||||||
|
| ".zip" `isSuffixOf` fn -> liftE (untar =<< rf av)
|
||||||
|
| otherwise -> throwE $ UnknownArchive fn
|
||||||
|
|
||||||
|
|
||||||
|
getArchiveFiles :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m)
|
||||||
|
=> FilePath -- ^ archive path
|
||||||
|
-> Excepts '[UnknownArchive
|
||||||
|
, ArchiveResult
|
||||||
|
] m [FilePath]
|
||||||
|
getArchiveFiles av = do
|
||||||
|
let fn = takeFileName av
|
||||||
|
|
||||||
|
let entries :: Monad m => BL.ByteString -> Excepts '[ArchiveResult] m [FilePath]
|
||||||
|
entries = (fmap . fmap) filepath . lE . readArchiveBSL
|
||||||
|
|
||||||
|
rf :: MonadIO m => FilePath -> Excepts '[ArchiveResult] m BL.ByteString
|
||||||
|
rf = liftIO . BL.readFile
|
||||||
|
|
||||||
|
-- extract, depending on file extension
|
||||||
|
if
|
||||||
|
| ".tar.gz" `isSuffixOf` fn -> liftE
|
||||||
|
(entries . GZip.decompress =<< rf av)
|
||||||
|
| ".tar.xz" `isSuffixOf` fn -> do
|
||||||
|
filecontents <- liftE $ rf av
|
||||||
|
let decompressed = Lzma.decompressWith (Lzma.defaultDecompressParams { Lzma.decompressAutoDecoder= True }) filecontents
|
||||||
|
liftE $ entries decompressed
|
||||||
|
| ".tar.bz2" `isSuffixOf` fn ->
|
||||||
|
liftE (entries . BZip.decompress =<< rf av)
|
||||||
|
| ".tar" `isSuffixOf` fn -> liftE (entries =<< rf av)
|
||||||
|
| ".zip" `isSuffixOf` fn -> liftE (entries =<< rf av)
|
||||||
|
| otherwise -> throwE $ UnknownArchive fn
|
||||||
|
|
||||||
|
|
||||||
|
intoSubdir :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m, MonadCatch m)
|
||||||
|
=> GHCupPath -- ^ unpacked tar dir
|
||||||
|
-> TarDir -- ^ how to descend
|
||||||
|
-> Excepts '[TarDirDoesNotExist] m GHCupPath
|
||||||
|
intoSubdir bdir tardir = case tardir of
|
||||||
|
RealDir pr -> do
|
||||||
|
whenM (fmap not . liftIO . doesDirectoryExist $ fromGHCupPath (bdir `appendGHCupPath` pr))
|
||||||
|
(throwE $ TarDirDoesNotExist tardir)
|
||||||
|
pure (bdir `appendGHCupPath` pr)
|
||||||
|
RegexDir r -> do
|
||||||
|
let rs = split (`elem` pathSeparators) r
|
||||||
|
foldlM
|
||||||
|
(\y x ->
|
||||||
|
(handleIO (\_ -> pure []) . liftIO . findFiles (fromGHCupPath y) . regex $ x) >>= (\case
|
||||||
|
[] -> throwE $ TarDirDoesNotExist tardir
|
||||||
|
(p : _) -> pure (y `appendGHCupPath` p)) . sort
|
||||||
|
)
|
||||||
|
bdir
|
||||||
|
rs
|
||||||
|
where regex = makeRegexOpts compIgnoreCase execBlank
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
------------
|
------------
|
||||||
--[ Tags ]--
|
--[ Tags ]--
|
||||||
------------
|
------------
|
||||||
@@ -833,28 +929,6 @@ getLatestBaseVersion av pvpVer =
|
|||||||
--[ Other ]--
|
--[ Other ]--
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
||||||
intoSubdir :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m, MonadCatch m)
|
|
||||||
=> GHCupPath -- ^ unpacked tar dir
|
|
||||||
-> TarDir -- ^ how to descend
|
|
||||||
-> Excepts '[TarDirDoesNotExist] m GHCupPath
|
|
||||||
intoSubdir bdir tardir = case tardir of
|
|
||||||
RealDir pr -> do
|
|
||||||
whenM (fmap not . liftIO . doesDirectoryExist $ fromGHCupPath (bdir `appendGHCupPath` pr))
|
|
||||||
(throwE $ TarDirDoesNotExist tardir)
|
|
||||||
pure (bdir `appendGHCupPath` pr)
|
|
||||||
RegexDir r -> do
|
|
||||||
let rs = split (`elem` pathSeparators) r
|
|
||||||
foldlM
|
|
||||||
(\y x ->
|
|
||||||
(handleIO (\_ -> pure []) . liftIO . findFiles (fromGHCupPath y) . regex $ x) >>= (\case
|
|
||||||
[] -> throwE $ TarDirDoesNotExist tardir
|
|
||||||
(p : _) -> pure (y `appendGHCupPath` p)) . sort
|
|
||||||
)
|
|
||||||
bdir
|
|
||||||
rs
|
|
||||||
where regex = makeRegexOpts compIgnoreCase execBlank
|
|
||||||
|
|
||||||
-- | Usually @~\/.ghcup\/ghc\/\<ver\>\/bin\/@
|
-- | Usually @~\/.ghcup\/ghc\/\<ver\>\/bin\/@
|
||||||
ghcInternalBinDir :: (MonadReader env m, HasDirs env, MonadThrow m, MonadFail m, MonadIO m)
|
ghcInternalBinDir :: (MonadReader env m, HasDirs env, MonadThrow m, MonadFail m, MonadIO m)
|
||||||
=> GHCTargetVersion
|
=> GHCTargetVersion
|
||||||
|
|||||||
@@ -1,139 +0,0 @@
|
|||||||
{-# LANGUAGE CPP #-}
|
|
||||||
{-# LANGUAGE DataKinds #-}
|
|
||||||
{-# LANGUAGE FlexibleContexts #-}
|
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
|
||||||
|
|
||||||
{-|
|
|
||||||
Module : GHCup.Utils.Tar
|
|
||||||
Description : GHCup tar abstractions
|
|
||||||
Copyright : (c) Julian Ospald, 2024
|
|
||||||
License : LGPL-3.0
|
|
||||||
Maintainer : hasufell@hasufell.de
|
|
||||||
Stability : experimental
|
|
||||||
Portability : portable
|
|
||||||
-}
|
|
||||||
module GHCup.Utils.Tar where
|
|
||||||
|
|
||||||
import GHCup.Types
|
|
||||||
import GHCup.Errors
|
|
||||||
import GHCup.Prelude
|
|
||||||
import GHCup.Prelude.Logger.Internal
|
|
||||||
import GHCup.Types.Optics
|
|
||||||
|
|
||||||
import Control.Monad.Catch (MonadThrow)
|
|
||||||
import Control.Monad.Reader
|
|
||||||
import Data.List
|
|
||||||
import Haskus.Utils.Variant.Excepts
|
|
||||||
import System.FilePath
|
|
||||||
|
|
||||||
#if defined(TAR)
|
|
||||||
import Codec.Archive.Zip
|
|
||||||
import qualified Codec.Archive.Tar as Tar
|
|
||||||
import qualified Codec.Archive.Tar.Entry as Tar
|
|
||||||
#else
|
|
||||||
import Codec.Archive hiding ( Directory )
|
|
||||||
#endif
|
|
||||||
|
|
||||||
import qualified Codec.Compression.BZip as BZip
|
|
||||||
import qualified Codec.Compression.GZip as GZip
|
|
||||||
import qualified Codec.Compression.Lzma as Lzma
|
|
||||||
import qualified Data.ByteString.Lazy as BL
|
|
||||||
import qualified Data.Map.Strict as Map
|
|
||||||
import qualified Data.Text as T
|
|
||||||
|
|
||||||
|
|
||||||
-- | Unpack an archive to a given directory.
|
|
||||||
unpackToDir :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m)
|
|
||||||
=> FilePath -- ^ destination dir
|
|
||||||
-> FilePath -- ^ archive path
|
|
||||||
-> Excepts '[UnknownArchive
|
|
||||||
, ArchiveResult
|
|
||||||
] m ()
|
|
||||||
unpackToDir dfp av = do
|
|
||||||
let fn = takeFileName av
|
|
||||||
lift $ logInfo $ "Unpacking: " <> T.pack fn <> " to " <> T.pack dfp
|
|
||||||
|
|
||||||
#if defined(TAR)
|
|
||||||
let untar :: MonadIO m => BL.ByteString -> Excepts '[ArchiveResult] m ()
|
|
||||||
untar = liftIO . Tar.unpack dfp . Tar.read
|
|
||||||
|
|
||||||
rf :: MonadIO m => FilePath -> Excepts '[ArchiveResult] m BL.ByteString
|
|
||||||
rf = liftIO . BL.readFile
|
|
||||||
#else
|
|
||||||
let untar :: MonadIO m => BL.ByteString -> Excepts '[ArchiveResult] m ()
|
|
||||||
untar = lEM . liftIO . runArchiveM . unpackToDirLazy dfp
|
|
||||||
|
|
||||||
rf :: MonadIO m => FilePath -> Excepts '[ArchiveResult] m BL.ByteString
|
|
||||||
rf = liftIO . BL.readFile
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-- extract, depending on file extension
|
|
||||||
if
|
|
||||||
| ".tar.gz" `isSuffixOf` fn -> liftE
|
|
||||||
(untar . GZip.decompress =<< rf av)
|
|
||||||
| ".tar.xz" `isSuffixOf` fn -> do
|
|
||||||
filecontents <- liftE $ rf av
|
|
||||||
let decompressed = Lzma.decompressWith (Lzma.defaultDecompressParams { Lzma.decompressAutoDecoder= True }) filecontents
|
|
||||||
liftE $ untar decompressed
|
|
||||||
| ".tar.bz2" `isSuffixOf` fn ->
|
|
||||||
liftE (untar . BZip.decompress =<< rf av)
|
|
||||||
| ".tar" `isSuffixOf` fn -> liftE (untar =<< rf av)
|
|
||||||
#if defined(TAR)
|
|
||||||
| ".zip" `isSuffixOf` fn -> withArchive av (unpackInto dfp)
|
|
||||||
#else
|
|
||||||
-- libarchive supports zip
|
|
||||||
| ".zip" `isSuffixOf` fn -> liftE (untar =<< rf av)
|
|
||||||
#endif
|
|
||||||
| otherwise -> throwE $ UnknownArchive fn
|
|
||||||
|
|
||||||
|
|
||||||
-- | Get all files from an archive.
|
|
||||||
getArchiveFiles :: (MonadReader env m, HasLog env, MonadIO m, MonadThrow m)
|
|
||||||
=> FilePath -- ^ archive path
|
|
||||||
-> Excepts '[ UnknownArchive
|
|
||||||
, ArchiveResult
|
|
||||||
] m [FilePath]
|
|
||||||
getArchiveFiles av = do
|
|
||||||
let fn = takeFileName av
|
|
||||||
#if defined(TAR)
|
|
||||||
let entries :: Monad m => BL.ByteString -> Excepts '[ArchiveResult] m [FilePath]
|
|
||||||
entries =
|
|
||||||
lE @ArchiveResult
|
|
||||||
. Tar.foldEntries
|
|
||||||
(\e x -> fmap (Tar.entryTarPath e :) x)
|
|
||||||
(Right [])
|
|
||||||
(\_ -> Left ArchiveFailed)
|
|
||||||
. Tar.decodeLongNames
|
|
||||||
. Tar.read
|
|
||||||
|
|
||||||
rf :: MonadIO m => FilePath -> Excepts '[ArchiveResult] m BL.ByteString
|
|
||||||
rf = liftIO . BL.readFile
|
|
||||||
#else
|
|
||||||
let entries :: Monad m => BL.ByteString -> Excepts '[ArchiveResult] m [FilePath]
|
|
||||||
entries = (fmap . fmap) filepath . lE . readArchiveBSL
|
|
||||||
|
|
||||||
rf :: MonadIO m => FilePath -> Excepts '[ArchiveResult] m BL.ByteString
|
|
||||||
rf = liftIO . BL.readFile
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-- extract, depending on file extension
|
|
||||||
if
|
|
||||||
| ".tar.gz" `isSuffixOf` fn -> liftE
|
|
||||||
(entries . GZip.decompress =<< rf av)
|
|
||||||
| ".tar.xz" `isSuffixOf` fn -> do
|
|
||||||
filecontents <- liftE $ rf av
|
|
||||||
let decompressed = Lzma.decompressWith (Lzma.defaultDecompressParams { Lzma.decompressAutoDecoder= True }) filecontents
|
|
||||||
liftE $ entries decompressed
|
|
||||||
| ".tar.bz2" `isSuffixOf` fn ->
|
|
||||||
liftE (entries . BZip.decompress =<< rf av)
|
|
||||||
| ".tar" `isSuffixOf` fn -> liftE (entries =<< rf av)
|
|
||||||
| ".zip" `isSuffixOf` fn ->
|
|
||||||
#if defined(TAR)
|
|
||||||
withArchive av $ do
|
|
||||||
entries' <- getEntries
|
|
||||||
pure $ fmap unEntrySelector $ Map.keys entries'
|
|
||||||
#else
|
|
||||||
liftE (entries =<< rf av)
|
|
||||||
#endif
|
|
||||||
| otherwise -> throwE $ UnknownArchive fn
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user