| ... |
... |
@@ -47,12 +47,19 @@ import Distribution.Types.UnqualComponentName |
|
47
|
47
|
import Distribution.Types.LibraryName
|
|
48
|
48
|
import Distribution.Types.MungedPackageName
|
|
49
|
49
|
import Distribution.Types.MungedPackageId
|
|
50
|
|
-import Distribution.Simple.Utils (toUTF8BS, writeUTF8File, readUTF8File)
|
|
|
50
|
+import Distribution.Simple.Utils (ignoreBOM, toUTF8BS, toUTF8LBS, fromUTF8LBS)
|
|
51
|
51
|
import qualified Data.Version as Version
|
|
52
|
|
-import System.FilePath as FilePath
|
|
|
52
|
+import System.OsPath as OsPath
|
|
|
53
|
+import qualified System.FilePath as FilePath
|
|
53
|
54
|
import qualified System.FilePath.Posix as FilePath.Posix
|
|
54
|
|
-import System.Directory ( getXdgDirectory, createDirectoryIfMissing, getAppUserDataDirectory,
|
|
55
|
|
- getModificationTime, XdgDirectory ( XdgData ) )
|
|
|
55
|
+import System.Directory.OsPath
|
|
|
56
|
+ ( getXdgDirectory, createDirectoryIfMissing, getAppUserDataDirectory,
|
|
|
57
|
+ getModificationTime, XdgDirectory ( XdgData ),
|
|
|
58
|
+ doesDirectoryExist, getDirectoryContents,
|
|
|
59
|
+ doesFileExist, removeFile,
|
|
|
60
|
+ getCurrentDirectory )
|
|
|
61
|
+import System.Directory.Internal (os)
|
|
|
62
|
+import qualified System.File.OsPath as FileIO
|
|
56
|
63
|
import Text.Printf
|
|
57
|
64
|
|
|
58
|
65
|
import Prelude hiding (Foldable(..))
|
| ... |
... |
@@ -65,15 +72,13 @@ import Data.Bifunctor |
|
65
|
72
|
|
|
66
|
73
|
import Data.Char ( toLower )
|
|
67
|
74
|
import Control.Monad
|
|
68
|
|
-import System.Directory ( doesDirectoryExist, getDirectoryContents,
|
|
69
|
|
- doesFileExist, removeFile,
|
|
70
|
|
- getCurrentDirectory )
|
|
71
|
75
|
import System.Exit ( exitWith, ExitCode(..) )
|
|
72
|
76
|
import System.Environment ( getArgs, getProgName, getEnv )
|
|
73
|
77
|
import System.IO
|
|
74
|
78
|
import System.IO.Error
|
|
75
|
79
|
import GHC.IO ( catchException )
|
|
76
|
80
|
import GHC.IO.Exception (IOErrorType(InappropriateType))
|
|
|
81
|
+import GHC.Stack.Types (HasCallStack)
|
|
77
|
82
|
import Data.List ( group, sort, sortBy, nub, partition, find
|
|
78
|
83
|
, intercalate, intersperse, unfoldr
|
|
79
|
84
|
, isInfixOf, isSuffixOf, isPrefixOf, stripPrefix )
|
| ... |
... |
@@ -430,7 +435,7 @@ runit verbosity cli nonopts = do |
|
430
|
435
|
glob filename >>= print
|
|
431
|
436
|
#endif
|
|
432
|
437
|
["init", filename] ->
|
|
433
|
|
- initPackageDB filename verbosity cli
|
|
|
438
|
+ initPackageDB (unsafeEncodeUtf filename) verbosity cli
|
|
434
|
439
|
["register", filename] ->
|
|
435
|
440
|
registerPackage filename verbosity cli
|
|
436
|
441
|
multi_instance
|
| ... |
... |
@@ -538,7 +543,7 @@ readPackageArg AsDefault str = Id <$> readGlobPkgId str |
|
538
|
543
|
|
|
539
|
544
|
data PackageDB (mode :: GhcPkg.DbMode)
|
|
540
|
545
|
= PackageDB {
|
|
541
|
|
- location, locationAbsolute :: !FilePath,
|
|
|
546
|
+ location, locationAbsolute :: !OsPath,
|
|
542
|
547
|
-- We need both possibly-relative and definitely-absolute package
|
|
543
|
548
|
-- db locations. This is because the relative location is used as
|
|
544
|
549
|
-- an identifier for the db, so it is important we do not modify it.
|
| ... |
... |
@@ -570,14 +575,14 @@ allPackagesInStack = concatMap packages |
|
570
|
575
|
-- specified package DB can depend on, since dependencies can only extend
|
|
571
|
576
|
-- down the stack, not up (e.g. global packages cannot depend on user
|
|
572
|
577
|
-- packages).
|
|
573
|
|
-stackUpTo :: FilePath -> PackageDBStack -> PackageDBStack
|
|
|
578
|
+stackUpTo :: OsPath -> PackageDBStack -> PackageDBStack
|
|
574
|
579
|
stackUpTo to_modify = dropWhile ((/= to_modify) . location)
|
|
575
|
580
|
|
|
576
|
|
-readFromSettingsFile :: FilePath
|
|
577
|
|
- -> (FilePath -> RawSettings -> Either String b)
|
|
|
581
|
+readFromSettingsFile :: OsPath
|
|
|
582
|
+ -> (OsPath -> RawSettings -> Either String b)
|
|
578
|
583
|
-> IO (Either String b)
|
|
579
|
584
|
readFromSettingsFile settingsFile f = do
|
|
580
|
|
- settingsStr <- readFile settingsFile
|
|
|
585
|
+ settingsStr <- readUtf8File settingsFile
|
|
581
|
586
|
pure $ do
|
|
582
|
587
|
mySettings <- case maybeReadFuzzy settingsStr of
|
|
583
|
588
|
Just s -> pure $ Map.fromList s
|
| ... |
... |
@@ -586,11 +591,11 @@ readFromSettingsFile settingsFile f = do |
|
586
|
591
|
Nothing -> Left $ "Can't parse settings file " ++ show settingsFile
|
|
587
|
592
|
f settingsFile mySettings
|
|
588
|
593
|
|
|
589
|
|
-readFromTargetFile :: FilePath
|
|
|
594
|
+readFromTargetFile :: OsPath
|
|
590
|
595
|
-> (Target -> b)
|
|
591
|
596
|
-> IO (Either String b)
|
|
592
|
597
|
readFromTargetFile targetFile f = do
|
|
593
|
|
- targetStr <- readFile targetFile
|
|
|
598
|
+ targetStr <- readUtf8File targetFile
|
|
594
|
599
|
pure $ do
|
|
595
|
600
|
target <- case maybeReadFuzzy targetStr of
|
|
596
|
601
|
Just t -> Right t
|
| ... |
... |
@@ -626,33 +631,33 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
626
|
631
|
case [ f | FlagGlobalConfig f <- my_flags ] of
|
|
627
|
632
|
-- See Note [Base Dir] for more information on the base dir / top dir.
|
|
628
|
633
|
[] -> do mb_dir <- getBaseDir
|
|
629
|
|
- case mb_dir of
|
|
|
634
|
+ case fmap unsafeEncodeUtf mb_dir of
|
|
630
|
635
|
Nothing -> die err_msg
|
|
631
|
636
|
Just dir -> do
|
|
632
|
637
|
-- Look for where it is given in the settings file, if marked there.
|
|
633
|
638
|
-- See Note [Settings file] about this file, and why we need GHC to share it with us.
|
|
634
|
|
- let settingsFile = dir </> "settings"
|
|
|
639
|
+ let settingsFile = dir </> os "settings"
|
|
635
|
640
|
exists_settings_file <- doesFileExist settingsFile
|
|
636
|
641
|
erel_db <-
|
|
637
|
642
|
if exists_settings_file
|
|
638
|
|
- then readFromSettingsFile settingsFile getGlobalPackageDb
|
|
639
|
|
- else pure (Left ("Settings file doesn't exist: " ++ settingsFile))
|
|
|
643
|
+ then readFromSettingsFile settingsFile (\ ospath -> getGlobalPackageDb (unsafeDecodeUtf ospath))
|
|
|
644
|
+ else pure (Left ("Settings file doesn't exist: " ++ showOsPath settingsFile))
|
|
640
|
645
|
|
|
641
|
646
|
case erel_db of
|
|
642
|
|
- Right rel_db -> return (dir, dir </> rel_db)
|
|
|
647
|
+ Right rel_db -> return (dir, dir </> unsafeEncodeUtf rel_db)
|
|
643
|
648
|
-- If the version of GHC doesn't have this field or the settings file
|
|
644
|
649
|
-- doesn't exist for some reason, look in the libdir.
|
|
645
|
650
|
Left err -> do
|
|
646
|
651
|
r <- lookForPackageDBIn dir
|
|
647
|
652
|
case r of
|
|
648
|
|
- Nothing -> die (unlines [err, ("Fallback: Can't find package database in " ++ dir)])
|
|
|
653
|
+ Nothing -> die (unlines [err, ("Fallback: Can't find package database in " ++ showOsPath dir)])
|
|
649
|
654
|
Just path -> return (dir, path)
|
|
650
|
655
|
fs -> do
|
|
651
|
656
|
-- The value of the $topdir variable used in some package descriptions
|
|
652
|
657
|
-- Note that the way we calculate this is slightly different to how it
|
|
653
|
658
|
-- is done in ghc itself. We rely on the convention that the global
|
|
654
|
659
|
-- package db lives in ghc's libdir.
|
|
655
|
|
- let pkg_db = last fs
|
|
|
660
|
+ let pkg_db = unsafeEncodeUtf $ last fs
|
|
656
|
661
|
top_dir <- absolutePath (takeDirectory pkg_db)
|
|
657
|
662
|
return (top_dir, pkg_db)
|
|
658
|
663
|
|
| ... |
... |
@@ -662,10 +667,10 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
662
|
667
|
-- getXdgDirectory can fail (e.g. if $HOME isn't set)
|
|
663
|
668
|
|
|
664
|
669
|
mb_user_conf <-
|
|
665
|
|
- case [ f | FlagUserConfig f <- my_flags ] of
|
|
|
670
|
+ case [ unsafeEncodeUtf f | FlagUserConfig f <- my_flags ] of
|
|
666
|
671
|
_ | no_user_db -> return Nothing
|
|
667
|
672
|
[] -> do
|
|
668
|
|
- let targetFile = top_dir </> "targets" </> "default.target"
|
|
|
673
|
+ let targetFile = top_dir </> os "targets" </> os "default.target"
|
|
669
|
674
|
exists_settings_file <- doesFileExist targetFile
|
|
670
|
675
|
targetArchOS <- case exists_settings_file of
|
|
671
|
676
|
False -> do
|
| ... |
... |
@@ -694,15 +699,15 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
694
|
699
|
-- otherwise we use $XDG_DATA_HOME/$UNIQUE_SUBDIR
|
|
695
|
700
|
--
|
|
696
|
701
|
-- UNIQUE_SUBDIR is typically a combination of the target platform and GHC version
|
|
697
|
|
- m_appdir <- getFirstSuccess $ map (fmap (</> subdir))
|
|
698
|
|
- [ getAppUserDataDirectory "ghc" -- this is ~/.ghc/
|
|
699
|
|
- , getXdgDirectory XdgData "ghc" -- this is $XDG_DATA_HOME/
|
|
|
702
|
+ m_appdir <- getFirstSuccess $ map (fmap (</> unsafeEncodeUtf subdir))
|
|
|
703
|
+ [ getAppUserDataDirectory $ os "ghc" -- this is ~/.ghc/
|
|
|
704
|
+ , getXdgDirectory XdgData $ os "ghc" -- this is $XDG_DATA_HOME/
|
|
700
|
705
|
]
|
|
701
|
706
|
case m_appdir of
|
|
702
|
707
|
Nothing -> return Nothing
|
|
703
|
708
|
Just dir -> do
|
|
704
|
709
|
lookForPackageDBIn dir >>= \case
|
|
705
|
|
- Nothing -> return (Just (dir </> "package.conf.d", False))
|
|
|
710
|
+ Nothing -> return (Just (dir </> os "package.conf.d", False))
|
|
706
|
711
|
Just f -> return (Just (f, True))
|
|
707
|
712
|
fs -> return (Just (last fs, True))
|
|
708
|
713
|
|
| ... |
... |
@@ -716,11 +721,11 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
716
|
721
|
|
|
717
|
722
|
e_pkg_path <- tryIO (System.Environment.getEnv "GHC_PACKAGE_PATH")
|
|
718
|
723
|
let env_stack =
|
|
719
|
|
- case e_pkg_path of
|
|
|
724
|
+ case fmap unsafeEncodeUtf e_pkg_path of
|
|
720
|
725
|
Left _ -> sys_databases
|
|
721
|
726
|
Right path
|
|
722
|
|
- | not (null path) && isSearchPathSeparator (last path)
|
|
723
|
|
- -> splitSearchPath (init path) ++ sys_databases
|
|
|
727
|
+ | hasTrailingPathSeparator path
|
|
|
728
|
+ -> splitSearchPath (dropTrailingPathSeparator path) <> sys_databases
|
|
724
|
729
|
| otherwise
|
|
725
|
730
|
-> splitSearchPath path
|
|
726
|
731
|
|
| ... |
... |
@@ -733,7 +738,7 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
733
|
738
|
| Just (user_conf, _user_exists) <- mb_user_conf
|
|
734
|
739
|
= Just user_conf
|
|
735
|
740
|
is_db_flag FlagGlobal = Just virt_global_conf
|
|
736
|
|
- is_db_flag (FlagConfig f) = Just f
|
|
|
741
|
+ is_db_flag (FlagConfig f) = Just $ unsafeEncodeUtf f
|
|
737
|
742
|
is_db_flag _ = Nothing
|
|
738
|
743
|
|
|
739
|
744
|
let flag_db_names | null db_flags = env_stack
|
| ... |
... |
@@ -748,7 +753,7 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
748
|
753
|
-- stack, unless any of them are present in the stack
|
|
749
|
754
|
-- already.
|
|
750
|
755
|
let final_stack = filter (`notElem` env_stack)
|
|
751
|
|
- [ f | FlagConfig f <- reverse my_flags ]
|
|
|
756
|
+ [ unsafeEncodeUtf f | FlagConfig f <- reverse my_flags ]
|
|
752
|
757
|
++ env_stack
|
|
753
|
758
|
|
|
754
|
759
|
top_db = if null db_flags
|
| ... |
... |
@@ -764,7 +769,7 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
764
|
769
|
when (verbosity > Normal) $ do
|
|
765
|
770
|
infoLn ("db stack: " ++ show (map location db_stack))
|
|
766
|
771
|
F.forM_ db_to_operate_on $ \db ->
|
|
767
|
|
- infoLn ("modifying: " ++ (location db))
|
|
|
772
|
+ infoLn ("modifying: " ++ showOsPath (location db))
|
|
768
|
773
|
infoLn ("flag db stack: " ++ show (map location flag_db_stack))
|
|
769
|
774
|
|
|
770
|
775
|
return (db_stack, db_to_operate_on, flag_db_stack)
|
| ... |
... |
@@ -843,12 +848,12 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
843
|
848
|
|
|
844
|
849
|
return (db_stack, GhcPkg.DbOpenReadWrite to_modify)
|
|
845
|
850
|
where
|
|
846
|
|
- couldntOpenDbForModification :: FilePath -> IOError -> IO a
|
|
|
851
|
+ couldntOpenDbForModification :: OsPath -> IOError -> IO a
|
|
847
|
852
|
couldntOpenDbForModification db_path e = die $ "Couldn't open database "
|
|
848
|
|
- ++ db_path ++ " for modification: " ++ show e
|
|
|
853
|
+ ++ showOsPath db_path ++ " for modification: " ++ show e
|
|
849
|
854
|
|
|
850
|
855
|
-- Parse package db in read-only mode.
|
|
851
|
|
- readDatabase :: FilePath -> IO (PackageDB 'GhcPkg.DbReadOnly)
|
|
|
856
|
+ readDatabase :: OsPath -> IO (PackageDB 'GhcPkg.DbReadOnly)
|
|
852
|
857
|
readDatabase db_path = do
|
|
853
|
858
|
db <- readParseDatabase verbosity mb_user_conf
|
|
854
|
859
|
GhcPkg.DbOpenReadOnly use_cache db_path
|
| ... |
... |
@@ -863,20 +868,20 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
863
|
868
|
(as, s'') <- stateSequence s' ms
|
|
864
|
869
|
return (a : as, s'')
|
|
865
|
870
|
|
|
866
|
|
-lookForPackageDBIn :: FilePath -> IO (Maybe FilePath)
|
|
|
871
|
+lookForPackageDBIn :: OsPath -> IO (Maybe OsPath)
|
|
867
|
872
|
lookForPackageDBIn dir = do
|
|
868
|
|
- let path_dir = dir </> "package.conf.d"
|
|
|
873
|
+ let path_dir = dir </> os "package.conf.d"
|
|
869
|
874
|
exists_dir <- doesDirectoryExist path_dir
|
|
870
|
875
|
if exists_dir then return (Just path_dir) else do
|
|
871
|
|
- let path_file = dir </> "package.conf"
|
|
|
876
|
+ let path_file = dir </> os "package.conf"
|
|
872
|
877
|
exists_file <- doesFileExist path_file
|
|
873
|
878
|
if exists_file then return (Just path_file) else return Nothing
|
|
874
|
879
|
|
|
875
|
880
|
readParseDatabase :: forall mode t. Verbosity
|
|
876
|
|
- -> Maybe (FilePath,Bool)
|
|
|
881
|
+ -> Maybe (OsPath,Bool)
|
|
877
|
882
|
-> GhcPkg.DbOpenMode mode t
|
|
878
|
883
|
-> Bool -- use cache
|
|
879
|
|
- -> FilePath
|
|
|
884
|
+ -> OsPath
|
|
880
|
885
|
-> IO (PackageDB mode)
|
|
881
|
886
|
readParseDatabase verbosity mb_user_conf mode use_cache path
|
|
882
|
887
|
-- the user database (only) is allowed to be non-existent
|
| ... |
... |
@@ -898,7 +903,7 @@ readParseDatabase verbosity mb_user_conf mode use_cache path |
|
898
|
903
|
Just db -> return db
|
|
899
|
904
|
Nothing ->
|
|
900
|
905
|
die $ "ghc no longer supports single-file style package "
|
|
901
|
|
- ++ "databases (" ++ path ++ ") use 'ghc-pkg init'"
|
|
|
906
|
+ ++ "databases (" ++ showOsPath path ++ ") use 'ghc-pkg init'"
|
|
902
|
907
|
++ "to create the database with the correct format."
|
|
903
|
908
|
|
|
904
|
909
|
| otherwise -> ioError err
|
| ... |
... |
@@ -914,7 +919,7 @@ readParseDatabase verbosity mb_user_conf mode use_cache path |
|
914
|
919
|
-- It's fine if the cache is not there as long as the
|
|
915
|
920
|
-- database is empty.
|
|
916
|
921
|
when (not $ null confs) $ do
|
|
917
|
|
- warn ("WARNING: cache does not exist: " ++ cache)
|
|
|
922
|
+ warn ("WARNING: cache does not exist: " ++ showOsPath cache)
|
|
918
|
923
|
warn ("ghc will fail to read this package db. " ++
|
|
919
|
924
|
recacheAdvice)
|
|
920
|
925
|
else do
|
| ... |
... |
@@ -923,7 +928,7 @@ readParseDatabase verbosity mb_user_conf mode use_cache path |
|
923
|
928
|
ignore_cache (const $ return ())
|
|
924
|
929
|
Right tcache -> do
|
|
925
|
930
|
when (verbosity >= Verbose) $ do
|
|
926
|
|
- warn ("Timestamp " ++ show tcache ++ " for " ++ cache)
|
|
|
931
|
+ warn ("Timestamp " ++ show tcache ++ " for " ++ showOsPath cache)
|
|
927
|
932
|
-- If any of the .conf files is newer than package.cache, we
|
|
928
|
933
|
-- assume that cache is out of date.
|
|
929
|
934
|
cache_outdated <- (`anyM` confs) $ \conf ->
|
| ... |
... |
@@ -931,12 +936,12 @@ readParseDatabase verbosity mb_user_conf mode use_cache path |
|
931
|
936
|
if not cache_outdated
|
|
932
|
937
|
then do
|
|
933
|
938
|
when (verbosity > Normal) $
|
|
934
|
|
- infoLn ("using cache: " ++ cache)
|
|
|
939
|
+ infoLn ("using cache: " ++ showOsPath cache)
|
|
935
|
940
|
GhcPkg.readPackageDbForGhcPkg cache mode
|
|
936
|
941
|
>>= uncurry mkPackageDB
|
|
937
|
942
|
else do
|
|
938
|
943
|
whenReportCacheErrors $ do
|
|
939
|
|
- warn ("WARNING: cache is out of date: " ++ cache)
|
|
|
944
|
+ warn ("WARNING: cache is out of date: " ++ showOsPath cache)
|
|
940
|
945
|
warn ("ghc will see an old view of this " ++
|
|
941
|
946
|
"package db. " ++ recacheAdvice)
|
|
942
|
947
|
ignore_cache $ \file -> do
|
| ... |
... |
@@ -947,11 +952,11 @@ readParseDatabase verbosity mb_user_conf mode use_cache path |
|
947
|
952
|
GT -> " (older than cache)"
|
|
948
|
953
|
EQ -> " (same as cache)"
|
|
949
|
954
|
warn ("Timestamp " ++ show tFile
|
|
950
|
|
- ++ " for " ++ file ++ rel)
|
|
|
955
|
+ ++ " for " ++ showOsPath file ++ rel)
|
|
951
|
956
|
where
|
|
952
|
|
- confs = map (path </>) $ filter (".conf" `isSuffixOf`) fs
|
|
|
957
|
+ confs = map (path </>) $ filter (os ".conf" `OsPath.isExtensionOf`) fs
|
|
953
|
958
|
|
|
954
|
|
- ignore_cache :: (FilePath -> IO ()) -> IO (PackageDB mode)
|
|
|
959
|
+ ignore_cache :: (OsPath -> IO ()) -> IO (PackageDB mode)
|
|
955
|
960
|
ignore_cache checkTime = do
|
|
956
|
961
|
-- If we're opening for modification, we need to acquire a
|
|
957
|
962
|
-- lock even if we don't open the cache now, because we are
|
| ... |
... |
@@ -987,15 +992,16 @@ readParseDatabase verbosity mb_user_conf mode use_cache path |
|
987
|
992
|
packages = pkgs
|
|
988
|
993
|
}
|
|
989
|
994
|
|
|
990
|
|
-parseSingletonPackageConf :: Verbosity -> FilePath -> IO InstalledPackageInfo
|
|
|
995
|
+parseSingletonPackageConf :: Verbosity -> OsPath -> IO InstalledPackageInfo
|
|
991
|
996
|
parseSingletonPackageConf verbosity file = do
|
|
992
|
|
- when (verbosity > Normal) $ infoLn ("reading package config: " ++ file)
|
|
993
|
|
- BS.readFile file >>= fmap fst . parsePackageInfo
|
|
|
997
|
+ when (verbosity > Normal) $ infoLn ("reading package config: " ++ showOsPath file)
|
|
|
998
|
+ FileIO.readFile file >>= fmap fst . parsePackageInfo . BS.toStrict
|
|
994
|
999
|
|
|
995
|
|
-cachefilename :: FilePath
|
|
996
|
|
-cachefilename = "package.cache"
|
|
997
|
1000
|
|
|
998
|
|
-mungePackageDBPaths :: FilePath -> PackageDB mode -> PackageDB mode
|
|
|
1001
|
+cachefilename :: OsPath
|
|
|
1002
|
+cachefilename = os "package.cache"
|
|
|
1003
|
+
|
|
|
1004
|
+mungePackageDBPaths :: OsPath -> PackageDB mode -> PackageDB mode
|
|
999
|
1005
|
mungePackageDBPaths top_dir db@PackageDB { packages = pkgs } =
|
|
1000
|
1006
|
db { packages = map (mungePackagePaths top_dir pkgroot) pkgs }
|
|
1001
|
1007
|
where
|
| ... |
... |
@@ -1012,7 +1018,7 @@ mungePackageDBPaths top_dir db@PackageDB { packages = pkgs } = |
|
1012
|
1018
|
-- Also perform a similar substitution for the older GHC-specific
|
|
1013
|
1019
|
-- "$topdir" variable. The "topdir" is the location of the ghc
|
|
1014
|
1020
|
-- installation (obtained from the -B option).
|
|
1015
|
|
-mungePackagePaths :: FilePath -> FilePath
|
|
|
1021
|
+mungePackagePaths :: OsPath -> OsPath
|
|
1016
|
1022
|
-> InstalledPackageInfo -> InstalledPackageInfo
|
|
1017
|
1023
|
mungePackagePaths top_dir pkgroot pkg =
|
|
1018
|
1024
|
-- TODO: similar code is duplicated in GHC.Unit.Database
|
| ... |
... |
@@ -1031,25 +1037,26 @@ mungePackagePaths top_dir pkgroot pkg = |
|
1031
|
1037
|
munge_urls = map munge_url
|
|
1032
|
1038
|
(munge_path,munge_url) = mkMungePathUrl top_dir pkgroot
|
|
1033
|
1039
|
|
|
1034
|
|
-mkMungePathUrl :: FilePath -> FilePath -> (FilePath -> FilePath, FilePath -> FilePath)
|
|
|
1040
|
+mkMungePathUrl :: OsPath -> OsPath -> (FilePath -> FilePath, FilePath -> FilePath)
|
|
1035
|
1041
|
mkMungePathUrl top_dir pkgroot = (munge_path, munge_url)
|
|
1036
|
1042
|
where
|
|
1037
|
1043
|
munge_path p
|
|
1038
|
|
- | Just p' <- stripVarPrefix "${pkgroot}" p = pkgroot ++ p'
|
|
1039
|
|
- | Just p' <- stripVarPrefix "$topdir" p = top_dir ++ p'
|
|
|
1044
|
+ | Just p' <- stripVarPrefix "${pkgroot}" p = unsafeDecodeUtf pkgroot ++ p'
|
|
|
1045
|
+ | Just p' <- stripVarPrefix "$topdir" p = unsafeDecodeUtf top_dir ++ p'
|
|
1040
|
1046
|
| otherwise = p
|
|
1041
|
1047
|
|
|
1042
|
1048
|
munge_url p
|
|
1043
|
|
- | Just p' <- stripVarPrefix "${pkgrooturl}" p = toUrlPath pkgroot p'
|
|
1044
|
|
- | Just p' <- stripVarPrefix "$httptopdir" p = toUrlPath top_dir p'
|
|
|
1049
|
+ | Just p' <- stripVarPrefix "${pkgrooturl}" p = toUrlPath (unsafeDecodeUtf pkgroot) p'
|
|
|
1050
|
+ | Just p' <- stripVarPrefix "$httptopdir" p = toUrlPath (unsafeDecodeUtf top_dir) p'
|
|
1045
|
1051
|
| otherwise = p
|
|
1046
|
1052
|
|
|
|
1053
|
+ toUrlPath :: FilePath -> FilePath -> FilePath
|
|
1047
|
1054
|
toUrlPath r p = "file:///"
|
|
1048
|
1055
|
-- URLs always use posix style '/' separators:
|
|
1049
|
1056
|
++ FilePath.Posix.joinPath
|
|
1050
|
1057
|
(r : -- We need to drop a leading "/" or "\\"
|
|
1051
|
1058
|
-- if there is one:
|
|
1052
|
|
- dropWhile (all isPathSeparator)
|
|
|
1059
|
+ dropWhile (all FilePath.isPathSeparator)
|
|
1053
|
1060
|
(FilePath.splitDirectories p))
|
|
1054
|
1061
|
|
|
1055
|
1062
|
-- We could drop the separator here, and then use </> above. However,
|
| ... |
... |
@@ -1057,7 +1064,7 @@ mkMungePathUrl top_dir pkgroot = (munge_path, munge_url) |
|
1057
|
1064
|
-- rather than letting FilePath change it to use \ as the separator
|
|
1058
|
1065
|
stripVarPrefix var path = case stripPrefix var path of
|
|
1059
|
1066
|
Just [] -> Just []
|
|
1060
|
|
- Just cs@(c : _) | isPathSeparator c -> Just cs
|
|
|
1067
|
+ Just cs@(c : _) | FilePath.isPathSeparator c -> Just cs
|
|
1061
|
1068
|
_ -> Nothing
|
|
1062
|
1069
|
|
|
1063
|
1070
|
-- -----------------------------------------------------------------------------
|
| ... |
... |
@@ -1074,18 +1081,18 @@ mkMungePathUrl top_dir pkgroot = (munge_path, munge_url) |
|
1074
|
1081
|
|
|
1075
|
1082
|
-- ghc itself also cooperates in this workaround
|
|
1076
|
1083
|
|
|
1077
|
|
-tryReadParseOldFileStyleDatabase :: Verbosity -> Maybe (FilePath, Bool)
|
|
1078
|
|
- -> GhcPkg.DbOpenMode mode t -> Bool -> FilePath
|
|
|
1084
|
+tryReadParseOldFileStyleDatabase :: Verbosity -> Maybe (OsPath, Bool)
|
|
|
1085
|
+ -> GhcPkg.DbOpenMode mode t -> Bool -> OsPath
|
|
1079
|
1086
|
-> IO (Maybe (PackageDB mode))
|
|
1080
|
1087
|
tryReadParseOldFileStyleDatabase verbosity mb_user_conf
|
|
1081
|
1088
|
mode use_cache path = do
|
|
1082
|
1089
|
-- assumes we've already established that path exists and is not a dir
|
|
1083
|
|
- content <- readFile path `catchIO` \_ -> return ""
|
|
|
1090
|
+ content <- readUtf8File path `catchIO` \_ -> return ""
|
|
1084
|
1091
|
if take 2 content == "[]"
|
|
1085
|
1092
|
then do
|
|
1086
|
1093
|
path_abs <- absolutePath path
|
|
1087
|
1094
|
let path_dir = adjustOldDatabasePath path
|
|
1088
|
|
- warn $ "Warning: ignoring old file-style db and trying " ++ path_dir
|
|
|
1095
|
+ warn $ "Warning: ignoring old file-style db and trying " ++ showOsPath path_dir
|
|
1089
|
1096
|
direxists <- doesDirectoryExist path_dir
|
|
1090
|
1097
|
if direxists
|
|
1091
|
1098
|
then do
|
| ... |
... |
@@ -1112,7 +1119,7 @@ tryReadParseOldFileStyleDatabase verbosity mb_user_conf |
|
1112
|
1119
|
adjustOldFileStylePackageDB :: PackageDB mode -> IO (PackageDB mode)
|
|
1113
|
1120
|
adjustOldFileStylePackageDB db = do
|
|
1114
|
1121
|
-- assumes we have not yet established if it's an old style or not
|
|
1115
|
|
- mcontent <- liftM Just (readFile (location db)) `catchIO` \_ -> return Nothing
|
|
|
1122
|
+ mcontent <- liftM Just (readUtf8File (location db)) `catchIO` \_ -> return Nothing
|
|
1116
|
1123
|
case fmap (take 2) mcontent of
|
|
1117
|
1124
|
-- it is an old style and empty db, so look for a dir kind in location.d/
|
|
1118
|
1125
|
Just "[]" -> return db {
|
| ... |
... |
@@ -1121,20 +1128,20 @@ adjustOldFileStylePackageDB db = do |
|
1121
|
1128
|
}
|
|
1122
|
1129
|
-- it is old style but not empty, we have to bail
|
|
1123
|
1130
|
Just _ -> die $ "ghc no longer supports single-file style package "
|
|
1124
|
|
- ++ "databases (" ++ location db ++ ") use 'ghc-pkg init'"
|
|
|
1131
|
+ ++ "databases (" ++ showOsPath (location db) ++ ") use 'ghc-pkg init'"
|
|
1125
|
1132
|
++ "to create the database with the correct format."
|
|
1126
|
1133
|
-- probably not old style, carry on as normal
|
|
1127
|
1134
|
Nothing -> return db
|
|
1128
|
1135
|
|
|
1129
|
|
-adjustOldDatabasePath :: FilePath -> FilePath
|
|
1130
|
|
-adjustOldDatabasePath = (<.> "d")
|
|
|
1136
|
+adjustOldDatabasePath :: OsPath -> OsPath
|
|
|
1137
|
+adjustOldDatabasePath = (<.> os "d")
|
|
1131
|
1138
|
|
|
1132
|
1139
|
-- -----------------------------------------------------------------------------
|
|
1133
|
1140
|
-- Creating a new package DB
|
|
1134
|
1141
|
|
|
1135
|
|
-initPackageDB :: FilePath -> Verbosity -> [Flag] -> IO ()
|
|
|
1142
|
+initPackageDB :: OsPath -> Verbosity -> [Flag] -> IO ()
|
|
1136
|
1143
|
initPackageDB filename verbosity _flags = do
|
|
1137
|
|
- let eexist = die ("cannot create: " ++ filename ++ " already exists")
|
|
|
1144
|
+ let eexist = die ("cannot create: " ++ showOsPath filename ++ " already exists")
|
|
1138
|
1145
|
b1 <- doesFileExist filename
|
|
1139
|
1146
|
when b1 eexist
|
|
1140
|
1147
|
b2 <- doesDirectoryExist filename
|
| ... |
... |
@@ -1148,7 +1155,7 @@ initPackageDB filename verbosity _flags = do |
|
1148
|
1155
|
packageDbLock = GhcPkg.DbOpenReadWrite lock,
|
|
1149
|
1156
|
packages = []
|
|
1150
|
1157
|
}
|
|
1151
|
|
- -- We can get away with passing an empty stack here, because the new DB is
|
|
|
1158
|
+ -- We can get away with passing an empty stack here,FilePath because the new DB is
|
|
1152
|
1159
|
-- going to be initially empty, so no dependencies are going to be actually
|
|
1153
|
1160
|
-- looked up.
|
|
1154
|
1161
|
[]
|
| ... |
... |
@@ -1183,7 +1190,7 @@ registerPackage input verbosity my_flags multi_instance |
|
1183
|
1190
|
f -> do
|
|
1184
|
1191
|
when (verbosity >= Normal) $
|
|
1185
|
1192
|
info ("Reading package info from " ++ show f ++ " ... ")
|
|
1186
|
|
- readUTF8File f
|
|
|
1193
|
+ readUtf8File $ unsafeEncodeUtf f
|
|
1187
|
1194
|
|
|
1188
|
1195
|
expanded <- if expand_env_vars then expandEnvVars s force
|
|
1189
|
1196
|
else return s
|
| ... |
... |
@@ -1274,13 +1281,13 @@ changeDBDir verbosity cmds db db_stack = do |
|
1274
|
1281
|
updateDBCache verbosity db db_stack
|
|
1275
|
1282
|
where
|
|
1276
|
1283
|
do_cmd (RemovePackage p) = do
|
|
1277
|
|
- let file = location db </> display (installedUnitId p) <.> "conf"
|
|
1278
|
|
- when (verbosity > Normal) $ infoLn ("removing " ++ file)
|
|
|
1284
|
+ let file = location db </> unsafeEncodeUtf (display (installedUnitId p)) <.> os "conf"
|
|
|
1285
|
+ when (verbosity > Normal) $ infoLn ("removing " ++ showOsPath file)
|
|
1279
|
1286
|
removeFileSafe file
|
|
1280
|
1287
|
do_cmd (AddPackage p) = do
|
|
1281
|
|
- let file = location db </> display (installedUnitId p) <.> "conf"
|
|
1282
|
|
- when (verbosity > Normal) $ infoLn ("writing " ++ file)
|
|
1283
|
|
- writeUTF8File file (showInstalledPackageInfo p)
|
|
|
1288
|
+ let file = location db </> unsafeEncodeUtf (display (installedUnitId p)) <.> os "conf"
|
|
|
1289
|
+ when (verbosity > Normal) $ infoLn ("writing " ++ showOsPath file)
|
|
|
1290
|
+ writeUtf8File file (showInstalledPackageInfo p)
|
|
1284
|
1291
|
do_cmd (ModifyPackage p) =
|
|
1285
|
1292
|
do_cmd (AddPackage p)
|
|
1286
|
1293
|
|
| ... |
... |
@@ -1338,13 +1345,13 @@ updateDBCache verbosity db db_stack = do |
|
1338
|
1345
|
warn $ " " ++ pkg
|
|
1339
|
1346
|
|
|
1340
|
1347
|
when (verbosity > Normal) $
|
|
1341
|
|
- infoLn ("writing cache " ++ filename)
|
|
|
1348
|
+ infoLn ("writing cache " ++ showOsPath filename)
|
|
1342
|
1349
|
|
|
1343
|
1350
|
let d = fmap (fromPackageCacheFormat . fst) pkgsGhcCacheFormat
|
|
1344
|
1351
|
GhcPkg.writePackageDb filename d pkgsCabalFormat
|
|
1345
|
1352
|
`catchIO` \e ->
|
|
1346
|
1353
|
if isPermissionError e
|
|
1347
|
|
- then die $ filename ++ ": you don't have permission to modify this file"
|
|
|
1354
|
+ then die $ showOsPath filename ++ ": you don't have permission to modify this file"
|
|
1348
|
1355
|
else ioError e
|
|
1349
|
1356
|
|
|
1350
|
1357
|
case packageDbLock db of
|
| ... |
... |
@@ -1583,7 +1590,7 @@ listPackages verbosity my_flags mPackageName mModuleName = do |
|
1583
|
1590
|
broken = map installedUnitId (brokenPackages pkg_map)
|
|
1584
|
1591
|
|
|
1585
|
1592
|
show_normal PackageDB{ location = db_name, packages = pkg_confs } =
|
|
1586
|
|
- do hPutStrLn stdout db_name
|
|
|
1593
|
+ do hPutStrLn stdout (showOsPath db_name)
|
|
1587
|
1594
|
if null pkg_confs
|
|
1588
|
1595
|
then hPutStrLn stdout " (no packages)"
|
|
1589
|
1596
|
else hPutStrLn stdout $ unlines (map (" " ++) (map pp_pkg pkg_confs))
|
| ... |
... |
@@ -1610,7 +1617,7 @@ listPackages verbosity my_flags mPackageName mModuleName = do |
|
1610
|
1617
|
#else
|
|
1611
|
1618
|
let
|
|
1612
|
1619
|
show_colour PackageDB{ location = db_name, packages = pkg_confs } =
|
|
1613
|
|
- do hPutStrLn stdout db_name
|
|
|
1620
|
+ do hPutStrLn stdout (showOsPath db_name)
|
|
1614
|
1621
|
if null pkg_confs
|
|
1615
|
1622
|
then hPutStrLn stdout " (no packages)"
|
|
1616
|
1623
|
else hPutStrLn stdout $ unlines (map (" " ++) (map pp_pkg pkg_confs))
|
| ... |
... |
@@ -1698,7 +1705,7 @@ dumpUnits verbosity my_flags expand_pkgroot = do |
|
1698
|
1705
|
doDump expand_pkgroot [ (pkg, locationAbsolute db)
|
|
1699
|
1706
|
| db <- flag_db_stack, pkg <- packages db ]
|
|
1700
|
1707
|
|
|
1701
|
|
-doDump :: Bool -> [(InstalledPackageInfo, FilePath)] -> IO ()
|
|
|
1708
|
+doDump :: Bool -> [(InstalledPackageInfo, OsPath)] -> IO ()
|
|
1702
|
1709
|
doDump expand_pkgroot pkgs = do
|
|
1703
|
1710
|
-- fix the encoding to UTF-8, since this is an interchange format
|
|
1704
|
1711
|
hSetEncoding stdout utf8
|
| ... |
... |
@@ -1731,7 +1738,7 @@ findPackagesByDB db_stack pkgarg |
|
1731
|
1738
|
|
|
1732
|
1739
|
cannotFindPackage :: PackageArg -> Maybe (PackageDB mode) -> IO a
|
|
1733
|
1740
|
cannotFindPackage pkgarg mdb = die $ "cannot find package " ++ pkg_msg pkgarg
|
|
1734
|
|
- ++ maybe "" (\db -> " in " ++ location db) mdb
|
|
|
1741
|
+ ++ maybe "" (\db -> " in " ++ showOsPath (location db)) mdb
|
|
1735
|
1742
|
where
|
|
1736
|
1743
|
pkg_msg (Id pkgid) = displayGlobPkgId pkgid
|
|
1737
|
1744
|
pkg_msg (IUId ipid) = display ipid
|
| ... |
... |
@@ -1944,7 +1951,7 @@ checkPackageConfig pkg verbosity db_stack |
|
1944
|
1951
|
checkExposedModules db_stack pkg
|
|
1945
|
1952
|
checkOtherModules pkg
|
|
1946
|
1953
|
let has_code = Set.null (openModuleSubstFreeHoles (Map.fromList (instantiatedWith pkg)))
|
|
1947
|
|
- when has_code $ mapM_ (checkHSLib verbosity (libraryDirs pkg ++ libraryDynDirs pkg)) (hsLibraries pkg)
|
|
|
1954
|
+ when has_code $ mapM_ (checkHSLib verbosity (fmap unsafeEncodeUtf $ libraryDirs pkg ++ libraryDynDirs pkg)) (hsLibraries pkg)
|
|
1948
|
1955
|
-- ToDo: check these somehow?
|
|
1949
|
1956
|
-- extra_libraries :: [String],
|
|
1950
|
1957
|
-- c_includes :: [String],
|
| ... |
... |
@@ -2011,20 +2018,20 @@ checkPath url_ok is_dir warn_only thisfield d |
|
2011
|
2018
|
|| "https://" `isPrefixOf` d) = return ()
|
|
2012
|
2019
|
|
|
2013
|
2020
|
| url_ok
|
|
2014
|
|
- , Just d' <- stripPrefix "file://" d
|
|
2015
|
|
- = checkPath False is_dir warn_only thisfield d'
|
|
|
2021
|
+ , Just f <- stripPrefix "file://" d
|
|
|
2022
|
+ = checkPath False is_dir warn_only thisfield f
|
|
2016
|
2023
|
|
|
2017
|
2024
|
-- Note: we don't check for $topdir/${pkgroot} here. We rely on these
|
|
2018
|
2025
|
-- variables having been expanded already, see mungePackagePaths.
|
|
2019
|
2026
|
|
|
2020
|
|
- | isRelative d = verror ForceFiles $
|
|
|
2027
|
+ | isRelative d' = verror ForceFiles $
|
|
2021
|
2028
|
thisfield ++ ": " ++ d ++ " is a relative path which "
|
|
2022
|
2029
|
++ "makes no sense (as there is nothing for it to be "
|
|
2023
|
2030
|
++ "relative to). You can make paths relative to the "
|
|
2024
|
2031
|
++ "package database itself by using ${pkgroot}."
|
|
2025
|
2032
|
-- relative paths don't make any sense; #4134
|
|
2026
|
2033
|
| otherwise = do
|
|
2027
|
|
- there <- liftIO $ if is_dir then doesDirectoryExist d else doesFileExist d
|
|
|
2034
|
+ there <- liftIO $ if is_dir then doesDirectoryExist d' else doesFileExist d'
|
|
2028
|
2035
|
when (not there) $
|
|
2029
|
2036
|
let msg = thisfield ++ ": " ++ d ++ " doesn't exist or isn't a "
|
|
2030
|
2037
|
++ if is_dir then "directory" else "file"
|
| ... |
... |
@@ -2032,6 +2039,8 @@ checkPath url_ok is_dir warn_only thisfield d |
|
2032
|
2039
|
if warn_only
|
|
2033
|
2040
|
then vwarn msg
|
|
2034
|
2041
|
else verror ForceFiles msg
|
|
|
2042
|
+ where
|
|
|
2043
|
+ d' = unsafeEncodeUtf d
|
|
2035
|
2044
|
|
|
2036
|
2045
|
checkDep :: PackageDBStack -> UnitId -> Validate ()
|
|
2037
|
2046
|
checkDep db_stack pkgid
|
| ... |
... |
@@ -2050,24 +2059,25 @@ checkDuplicateDepends deps |
|
2050
|
2059
|
where
|
|
2051
|
2060
|
dups = [ p | (p:_:_) <- group (sort deps) ]
|
|
2052
|
2061
|
|
|
2053
|
|
-checkHSLib :: Verbosity -> [String] -> String -> Validate ()
|
|
|
2062
|
+checkHSLib :: Verbosity -> [OsPath] -> String -> Validate ()
|
|
2054
|
2063
|
checkHSLib _verbosity dirs lib = do
|
|
2055
|
|
- let filenames = ["lib" ++ lib ++ ".a",
|
|
2056
|
|
- "lib" ++ lib ++ "_p.a",
|
|
2057
|
|
- "lib" ++ lib ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".so",
|
|
2058
|
|
- "lib" ++ lib ++ "_p" ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".so",
|
|
2059
|
|
- "lib" ++ lib ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dylib",
|
|
2060
|
|
- "lib" ++ lib ++ "_p" ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dylib",
|
|
2061
|
|
- lib ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dll",
|
|
2062
|
|
- lib ++ "_p" ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dll",
|
|
2063
|
|
- lib ++ ".bytecodelib"
|
|
2064
|
|
- ]
|
|
|
2064
|
+ let filenames = fmap OsPath.unsafeEncodeUtf
|
|
|
2065
|
+ [ "lib" ++ lib ++ ".a"
|
|
|
2066
|
+ , "lib" ++ lib ++ "_p.a"
|
|
|
2067
|
+ , "lib" ++ lib ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".so"
|
|
|
2068
|
+ , "lib" ++ lib ++ "_p" ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".so"
|
|
|
2069
|
+ , "lib" ++ lib ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dylib"
|
|
|
2070
|
+ , "lib" ++ lib ++ "_p" ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dylib"
|
|
|
2071
|
+ , lib ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dll"
|
|
|
2072
|
+ , lib ++ "_p" ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dll"
|
|
|
2073
|
+ , lib ++ ".bytecodelib"
|
|
|
2074
|
+ ]
|
|
2065
|
2075
|
b <- liftIO $ doesFileExistOnPath filenames dirs
|
|
2066
|
2076
|
when (not b) $
|
|
2067
|
2077
|
verror ForceFiles ("cannot find any of " ++ show filenames ++
|
|
2068
|
2078
|
" on library path")
|
|
2069
|
2079
|
|
|
2070
|
|
-doesFileExistOnPath :: [FilePath] -> [FilePath] -> IO Bool
|
|
|
2080
|
+doesFileExistOnPath :: [OsPath] -> [OsPath] -> IO Bool
|
|
2071
|
2081
|
doesFileExistOnPath filenames paths = anyM doesFileExist fullFilenames
|
|
2072
|
2082
|
where fullFilenames = [ path </> filename
|
|
2073
|
2083
|
| filename <- filenames
|
| ... |
... |
@@ -2096,9 +2106,9 @@ checkModuleFile :: InstalledPackageInfo -> ModuleName -> Validate () |
|
2096
|
2106
|
checkModuleFile pkg modl =
|
|
2097
|
2107
|
-- there's no interface file for GHC.Prim
|
|
2098
|
2108
|
unless (modl == ModuleName.fromString "GHC.Prim") $ do
|
|
2099
|
|
- let files = [ ModuleName.toFilePath modl <.> extension
|
|
2100
|
|
- | extension <- ["hi", "p_hi", "dyn_hi", "p_dyn_hi"] ]
|
|
2101
|
|
- b <- liftIO $ doesFileExistOnPath files (importDirs pkg)
|
|
|
2109
|
+ let files = [ unsafeEncodeUtf (ModuleName.toFilePath modl) <.> extension
|
|
|
2110
|
+ | extension <- fmap os ["hi", "p_hi", "dyn_hi", "p_dyn_hi"] ]
|
|
|
2111
|
+ b <- liftIO $ doesFileExistOnPath files (fmap unsafeEncodeUtf $ importDirs pkg)
|
|
2102
|
2112
|
when (not b) $
|
|
2103
|
2113
|
verror ForceFiles ("cannot find any of " ++ show files)
|
|
2104
|
2114
|
|
| ... |
... |
@@ -2280,12 +2290,21 @@ tryIO :: IO a -> IO (Either Exception.IOException a) |
|
2280
|
2290
|
tryIO = Exception.try
|
|
2281
|
2291
|
|
|
2282
|
2292
|
-- removeFileSave doesn't throw an exceptions, if the file is already deleted
|
|
2283
|
|
-removeFileSafe :: FilePath -> IO ()
|
|
|
2293
|
+removeFileSafe :: OsPath -> IO ()
|
|
2284
|
2294
|
removeFileSafe fn =
|
|
2285
|
2295
|
removeFile fn `catchIO` \ e ->
|
|
2286
|
2296
|
when (not $ isDoesNotExistError e) $ ioError e
|
|
2287
|
2297
|
|
|
2288
|
2298
|
-- | Turn a path relative to the current directory into a (normalised)
|
|
2289
|
2299
|
-- absolute path.
|
|
2290
|
|
-absolutePath :: FilePath -> IO FilePath
|
|
|
2300
|
+absolutePath :: OsPath -> IO OsPath
|
|
2291
|
2301
|
absolutePath path = return . normalise . (</> path) =<< getCurrentDirectory
|
|
|
2302
|
+
|
|
|
2303
|
+writeUtf8File :: OsPath -> String -> IO ()
|
|
|
2304
|
+writeUtf8File file contents = writeFileAtomic file (toUTF8LBS contents)
|
|
|
2305
|
+
|
|
|
2306
|
+readUtf8File :: OsPath -> IO String
|
|
|
2307
|
+readUtf8File file = (ignoreBOM . fromUTF8LBS) <$> FileIO.readFile file
|
|
|
2308
|
+
|
|
|
2309
|
+showOsPath :: HasCallStack => OsPath -> FilePath
|
|
|
2310
|
+showOsPath = unsafeDecodeUtf |
|
|
\ No newline at end of file |