| ... |
... |
@@ -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
|
|
-import GHC.IO ( catchException )
|
|
|
79
|
+import GHC.IO ( catchException, unsafePerformIO )
|
|
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 )
|
| ... |
... |
@@ -429,8 +434,9 @@ runit verbosity cli nonopts = do |
|
429
|
434
|
print filename
|
|
430
|
435
|
glob filename >>= print
|
|
431
|
436
|
#endif
|
|
432
|
|
- ["init", filename] ->
|
|
433
|
|
- initPackageDB filename verbosity cli
|
|
|
437
|
+ ["init", filename] -> do
|
|
|
438
|
+ filenameOs <- encodeFS filename
|
|
|
439
|
+ initPackageDB filenameOs verbosity cli
|
|
434
|
440
|
["register", filename] ->
|
|
435
|
441
|
registerPackage filename verbosity cli
|
|
436
|
442
|
multi_instance
|
| ... |
... |
@@ -538,7 +544,7 @@ readPackageArg AsDefault str = Id <$> readGlobPkgId str |
|
538
|
544
|
|
|
539
|
545
|
data PackageDB (mode :: GhcPkg.DbMode)
|
|
540
|
546
|
= PackageDB {
|
|
541
|
|
- location, locationAbsolute :: !FilePath,
|
|
|
547
|
+ location, locationAbsolute :: !OsPath,
|
|
542
|
548
|
-- We need both possibly-relative and definitely-absolute package
|
|
543
|
549
|
-- db locations. This is because the relative location is used as
|
|
544
|
550
|
-- an identifier for the db, so it is important we do not modify it.
|
| ... |
... |
@@ -570,14 +576,14 @@ allPackagesInStack = concatMap packages |
|
570
|
576
|
-- specified package DB can depend on, since dependencies can only extend
|
|
571
|
577
|
-- down the stack, not up (e.g. global packages cannot depend on user
|
|
572
|
578
|
-- packages).
|
|
573
|
|
-stackUpTo :: FilePath -> PackageDBStack -> PackageDBStack
|
|
|
579
|
+stackUpTo :: OsPath -> PackageDBStack -> PackageDBStack
|
|
574
|
580
|
stackUpTo to_modify = dropWhile ((/= to_modify) . location)
|
|
575
|
581
|
|
|
576
|
|
-readFromSettingsFile :: FilePath
|
|
577
|
|
- -> (FilePath -> RawSettings -> Either String b)
|
|
|
582
|
+readFromSettingsFile :: OsPath
|
|
|
583
|
+ -> (OsPath -> RawSettings -> Either String b)
|
|
578
|
584
|
-> IO (Either String b)
|
|
579
|
585
|
readFromSettingsFile settingsFile f = do
|
|
580
|
|
- settingsStr <- readFile settingsFile
|
|
|
586
|
+ settingsStr <- readUtf8File settingsFile
|
|
581
|
587
|
pure $ do
|
|
582
|
588
|
mySettings <- case maybeReadFuzzy settingsStr of
|
|
583
|
589
|
Just s -> pure $ Map.fromList s
|
| ... |
... |
@@ -586,11 +592,11 @@ readFromSettingsFile settingsFile f = do |
|
586
|
592
|
Nothing -> Left $ "Can't parse settings file " ++ show settingsFile
|
|
587
|
593
|
f settingsFile mySettings
|
|
588
|
594
|
|
|
589
|
|
-readFromTargetFile :: FilePath
|
|
|
595
|
+readFromTargetFile :: OsPath
|
|
590
|
596
|
-> (Target -> b)
|
|
591
|
597
|
-> IO (Either String b)
|
|
592
|
598
|
readFromTargetFile targetFile f = do
|
|
593
|
|
- targetStr <- readFile targetFile
|
|
|
599
|
+ targetStr <- readUtf8File targetFile
|
|
594
|
600
|
pure $ do
|
|
595
|
601
|
target <- case maybeReadFuzzy targetStr of
|
|
596
|
602
|
Just t -> Right t
|
| ... |
... |
@@ -626,33 +632,35 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
626
|
632
|
case [ f | FlagGlobalConfig f <- my_flags ] of
|
|
627
|
633
|
-- See Note [Base Dir] for more information on the base dir / top dir.
|
|
628
|
634
|
[] -> do mb_dir <- getBaseDir
|
|
629
|
|
- case mb_dir of
|
|
|
635
|
+ mb_dir_os <- traverse encodeFS mb_dir
|
|
|
636
|
+ case mb_dir_os of
|
|
630
|
637
|
Nothing -> die err_msg
|
|
631
|
638
|
Just dir -> do
|
|
632
|
639
|
-- Look for where it is given in the settings file, if marked there.
|
|
633
|
640
|
-- See Note [Settings file] about this file, and why we need GHC to share it with us.
|
|
634
|
|
- let settingsFile = dir </> "settings"
|
|
|
641
|
+ let settingsFile = dir </> os "settings"
|
|
635
|
642
|
exists_settings_file <- doesFileExist settingsFile
|
|
636
|
643
|
erel_db <-
|
|
637
|
644
|
if exists_settings_file
|
|
638
|
|
- then readFromSettingsFile settingsFile getGlobalPackageDb
|
|
639
|
|
- else pure (Left ("Settings file doesn't exist: " ++ settingsFile))
|
|
|
645
|
+ then do
|
|
|
646
|
+ readFromSettingsFile settingsFile (\ settings -> getGlobalPackageDb (unsafeDecodeUtf settings))
|
|
|
647
|
+ else pure (Left ("Settings file doesn't exist: " ++ showOsPath settingsFile))
|
|
640
|
648
|
|
|
641
|
649
|
case erel_db of
|
|
642
|
|
- Right rel_db -> return (dir, dir </> rel_db)
|
|
|
650
|
+ Right rel_db -> return (dir, dir </> unsafeEncodeUtf rel_db)
|
|
643
|
651
|
-- If the version of GHC doesn't have this field or the settings file
|
|
644
|
652
|
-- doesn't exist for some reason, look in the libdir.
|
|
645
|
653
|
Left err -> do
|
|
646
|
654
|
r <- lookForPackageDBIn dir
|
|
647
|
655
|
case r of
|
|
648
|
|
- Nothing -> die (unlines [err, ("Fallback: Can't find package database in " ++ dir)])
|
|
|
656
|
+ Nothing -> die (unlines [err, ("Fallback: Can't find package database in " ++ showOsPath dir)])
|
|
649
|
657
|
Just path -> return (dir, path)
|
|
650
|
658
|
fs -> do
|
|
651
|
659
|
-- The value of the $topdir variable used in some package descriptions
|
|
652
|
660
|
-- Note that the way we calculate this is slightly different to how it
|
|
653
|
661
|
-- is done in ghc itself. We rely on the convention that the global
|
|
654
|
662
|
-- package db lives in ghc's libdir.
|
|
655
|
|
- let pkg_db = last fs
|
|
|
663
|
+ let pkg_db = unsafeEncodeUtf $ last fs
|
|
656
|
664
|
top_dir <- absolutePath (takeDirectory pkg_db)
|
|
657
|
665
|
return (top_dir, pkg_db)
|
|
658
|
666
|
|
| ... |
... |
@@ -662,10 +670,10 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
662
|
670
|
-- getXdgDirectory can fail (e.g. if $HOME isn't set)
|
|
663
|
671
|
|
|
664
|
672
|
mb_user_conf <-
|
|
665
|
|
- case [ f | FlagUserConfig f <- my_flags ] of
|
|
|
673
|
+ case [ unsafeEncodeUtf f | FlagUserConfig f <- my_flags ] of
|
|
666
|
674
|
_ | no_user_db -> return Nothing
|
|
667
|
675
|
[] -> do
|
|
668
|
|
- let targetFile = top_dir </> "targets" </> "default.target"
|
|
|
676
|
+ let targetFile = top_dir </> os "targets" </> os "default.target"
|
|
669
|
677
|
exists_settings_file <- doesFileExist targetFile
|
|
670
|
678
|
targetArchOS <- case exists_settings_file of
|
|
671
|
679
|
False -> do
|
| ... |
... |
@@ -694,15 +702,15 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
694
|
702
|
-- otherwise we use $XDG_DATA_HOME/$UNIQUE_SUBDIR
|
|
695
|
703
|
--
|
|
696
|
704
|
-- 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/
|
|
|
705
|
+ m_appdir <- getFirstSuccess $ map (fmap (</> unsafeEncodeUtf subdir))
|
|
|
706
|
+ [ getAppUserDataDirectory $ os "ghc" -- this is ~/.ghc/
|
|
|
707
|
+ , getXdgDirectory XdgData $ os "ghc" -- this is $XDG_DATA_HOME/
|
|
700
|
708
|
]
|
|
701
|
709
|
case m_appdir of
|
|
702
|
710
|
Nothing -> return Nothing
|
|
703
|
711
|
Just dir -> do
|
|
704
|
712
|
lookForPackageDBIn dir >>= \case
|
|
705
|
|
- Nothing -> return (Just (dir </> "package.conf.d", False))
|
|
|
713
|
+ Nothing -> return (Just (dir </> os "package.conf.d", False))
|
|
706
|
714
|
Just f -> return (Just (f, True))
|
|
707
|
715
|
fs -> return (Just (last fs, True))
|
|
708
|
716
|
|
| ... |
... |
@@ -716,11 +724,11 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
716
|
724
|
|
|
717
|
725
|
e_pkg_path <- tryIO (System.Environment.getEnv "GHC_PACKAGE_PATH")
|
|
718
|
726
|
let env_stack =
|
|
719
|
|
- case e_pkg_path of
|
|
|
727
|
+ case fmap unsafeEncodeUtf e_pkg_path of
|
|
720
|
728
|
Left _ -> sys_databases
|
|
721
|
729
|
Right path
|
|
722
|
|
- | not (null path) && isSearchPathSeparator (last path)
|
|
723
|
|
- -> splitSearchPath (init path) ++ sys_databases
|
|
|
730
|
+ | hasTrailingPathSeparator path
|
|
|
731
|
+ -> splitSearchPath (dropTrailingPathSeparator path) <> sys_databases
|
|
724
|
732
|
| otherwise
|
|
725
|
733
|
-> splitSearchPath path
|
|
726
|
734
|
|
| ... |
... |
@@ -733,7 +741,7 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
733
|
741
|
| Just (user_conf, _user_exists) <- mb_user_conf
|
|
734
|
742
|
= Just user_conf
|
|
735
|
743
|
is_db_flag FlagGlobal = Just virt_global_conf
|
|
736
|
|
- is_db_flag (FlagConfig f) = Just f
|
|
|
744
|
+ is_db_flag (FlagConfig f) = Just $ unsafeEncodeUtf f
|
|
737
|
745
|
is_db_flag _ = Nothing
|
|
738
|
746
|
|
|
739
|
747
|
let flag_db_names | null db_flags = env_stack
|
| ... |
... |
@@ -748,7 +756,7 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
748
|
756
|
-- stack, unless any of them are present in the stack
|
|
749
|
757
|
-- already.
|
|
750
|
758
|
let final_stack = filter (`notElem` env_stack)
|
|
751
|
|
- [ f | FlagConfig f <- reverse my_flags ]
|
|
|
759
|
+ [ unsafeEncodeUtf f | FlagConfig f <- reverse my_flags ]
|
|
752
|
760
|
++ env_stack
|
|
753
|
761
|
|
|
754
|
762
|
top_db = if null db_flags
|
| ... |
... |
@@ -764,7 +772,7 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
764
|
772
|
when (verbosity > Normal) $ do
|
|
765
|
773
|
infoLn ("db stack: " ++ show (map location db_stack))
|
|
766
|
774
|
F.forM_ db_to_operate_on $ \db ->
|
|
767
|
|
- infoLn ("modifying: " ++ (location db))
|
|
|
775
|
+ infoLn ("modifying: " ++ showOsPath (location db))
|
|
768
|
776
|
infoLn ("flag db stack: " ++ show (map location flag_db_stack))
|
|
769
|
777
|
|
|
770
|
778
|
return (db_stack, db_to_operate_on, flag_db_stack)
|
| ... |
... |
@@ -843,17 +851,19 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
843
|
851
|
|
|
844
|
852
|
return (db_stack, GhcPkg.DbOpenReadWrite to_modify)
|
|
845
|
853
|
where
|
|
846
|
|
- couldntOpenDbForModification :: FilePath -> IOError -> IO a
|
|
|
854
|
+ couldntOpenDbForModification :: OsPath -> IOError -> IO a
|
|
847
|
855
|
couldntOpenDbForModification db_path e = die $ "Couldn't open database "
|
|
848
|
|
- ++ db_path ++ " for modification: " ++ show e
|
|
|
856
|
+ ++ showOsPath db_path ++ " for modification: " ++ show e
|
|
849
|
857
|
|
|
850
|
858
|
-- Parse package db in read-only mode.
|
|
851
|
|
- readDatabase :: FilePath -> IO (PackageDB 'GhcPkg.DbReadOnly)
|
|
|
859
|
+ readDatabase :: OsPath -> IO (PackageDB 'GhcPkg.DbReadOnly)
|
|
852
|
860
|
readDatabase db_path = do
|
|
853
|
861
|
db <- readParseDatabase verbosity mb_user_conf
|
|
854
|
862
|
GhcPkg.DbOpenReadOnly use_cache db_path
|
|
855
|
863
|
if expand_vars
|
|
856
|
|
- then return $ mungePackageDBPaths top_dir db
|
|
|
864
|
+ then do
|
|
|
865
|
+ top_dir_filepath <- decodeFS top_dir
|
|
|
866
|
+ return $ mungePackageDBPaths top_dir_filepath db
|
|
857
|
867
|
else return db
|
|
858
|
868
|
|
|
859
|
869
|
stateSequence :: Monad m => s -> [s -> m (a, s)] -> m ([a], s)
|
| ... |
... |
@@ -863,20 +873,20 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do |
|
863
|
873
|
(as, s'') <- stateSequence s' ms
|
|
864
|
874
|
return (a : as, s'')
|
|
865
|
875
|
|
|
866
|
|
-lookForPackageDBIn :: FilePath -> IO (Maybe FilePath)
|
|
|
876
|
+lookForPackageDBIn :: OsPath -> IO (Maybe OsPath)
|
|
867
|
877
|
lookForPackageDBIn dir = do
|
|
868
|
|
- let path_dir = dir </> "package.conf.d"
|
|
|
878
|
+ let path_dir = dir </> os "package.conf.d"
|
|
869
|
879
|
exists_dir <- doesDirectoryExist path_dir
|
|
870
|
880
|
if exists_dir then return (Just path_dir) else do
|
|
871
|
|
- let path_file = dir </> "package.conf"
|
|
|
881
|
+ let path_file = dir </> os "package.conf"
|
|
872
|
882
|
exists_file <- doesFileExist path_file
|
|
873
|
883
|
if exists_file then return (Just path_file) else return Nothing
|
|
874
|
884
|
|
|
875
|
885
|
readParseDatabase :: forall mode t. Verbosity
|
|
876
|
|
- -> Maybe (FilePath,Bool)
|
|
|
886
|
+ -> Maybe (OsPath,Bool)
|
|
877
|
887
|
-> GhcPkg.DbOpenMode mode t
|
|
878
|
888
|
-> Bool -- use cache
|
|
879
|
|
- -> FilePath
|
|
|
889
|
+ -> OsPath
|
|
880
|
890
|
-> IO (PackageDB mode)
|
|
881
|
891
|
readParseDatabase verbosity mb_user_conf mode use_cache path
|
|
882
|
892
|
-- the user database (only) is allowed to be non-existent
|
| ... |
... |
@@ -898,7 +908,7 @@ readParseDatabase verbosity mb_user_conf mode use_cache path |
|
898
|
908
|
Just db -> return db
|
|
899
|
909
|
Nothing ->
|
|
900
|
910
|
die $ "ghc no longer supports single-file style package "
|
|
901
|
|
- ++ "databases (" ++ path ++ ") use 'ghc-pkg init'"
|
|
|
911
|
+ ++ "databases (" ++ showOsPath path ++ ") use 'ghc-pkg init'"
|
|
902
|
912
|
++ "to create the database with the correct format."
|
|
903
|
913
|
|
|
904
|
914
|
| otherwise -> ioError err
|
| ... |
... |
@@ -914,7 +924,7 @@ readParseDatabase verbosity mb_user_conf mode use_cache path |
|
914
|
924
|
-- It's fine if the cache is not there as long as the
|
|
915
|
925
|
-- database is empty.
|
|
916
|
926
|
when (not $ null confs) $ do
|
|
917
|
|
- warn ("WARNING: cache does not exist: " ++ cache)
|
|
|
927
|
+ warn ("WARNING: cache does not exist: " ++ showOsPath cache)
|
|
918
|
928
|
warn ("ghc will fail to read this package db. " ++
|
|
919
|
929
|
recacheAdvice)
|
|
920
|
930
|
else do
|
| ... |
... |
@@ -923,7 +933,7 @@ readParseDatabase verbosity mb_user_conf mode use_cache path |
|
923
|
933
|
ignore_cache (const $ return ())
|
|
924
|
934
|
Right tcache -> do
|
|
925
|
935
|
when (verbosity >= Verbose) $ do
|
|
926
|
|
- warn ("Timestamp " ++ show tcache ++ " for " ++ cache)
|
|
|
936
|
+ warn ("Timestamp " ++ show tcache ++ " for " ++ showOsPath cache)
|
|
927
|
937
|
-- If any of the .conf files is newer than package.cache, we
|
|
928
|
938
|
-- assume that cache is out of date.
|
|
929
|
939
|
cache_outdated <- (`anyM` confs) $ \conf ->
|
| ... |
... |
@@ -931,12 +941,12 @@ readParseDatabase verbosity mb_user_conf mode use_cache path |
|
931
|
941
|
if not cache_outdated
|
|
932
|
942
|
then do
|
|
933
|
943
|
when (verbosity > Normal) $
|
|
934
|
|
- infoLn ("using cache: " ++ cache)
|
|
|
944
|
+ infoLn ("using cache: " ++ showOsPath cache)
|
|
935
|
945
|
GhcPkg.readPackageDbForGhcPkg cache mode
|
|
936
|
946
|
>>= uncurry mkPackageDB
|
|
937
|
947
|
else do
|
|
938
|
948
|
whenReportCacheErrors $ do
|
|
939
|
|
- warn ("WARNING: cache is out of date: " ++ cache)
|
|
|
949
|
+ warn ("WARNING: cache is out of date: " ++ showOsPath cache)
|
|
940
|
950
|
warn ("ghc will see an old view of this " ++
|
|
941
|
951
|
"package db. " ++ recacheAdvice)
|
|
942
|
952
|
ignore_cache $ \file -> do
|
| ... |
... |
@@ -947,11 +957,11 @@ readParseDatabase verbosity mb_user_conf mode use_cache path |
|
947
|
957
|
GT -> " (older than cache)"
|
|
948
|
958
|
EQ -> " (same as cache)"
|
|
949
|
959
|
warn ("Timestamp " ++ show tFile
|
|
950
|
|
- ++ " for " ++ file ++ rel)
|
|
|
960
|
+ ++ " for " ++ showOsPath file ++ rel)
|
|
951
|
961
|
where
|
|
952
|
|
- confs = map (path </>) $ filter (".conf" `isSuffixOf`) fs
|
|
|
962
|
+ confs = map (path </>) $ filter (os ".conf" `OsPath.isExtensionOf`) fs
|
|
953
|
963
|
|
|
954
|
|
- ignore_cache :: (FilePath -> IO ()) -> IO (PackageDB mode)
|
|
|
964
|
+ ignore_cache :: (OsPath -> IO ()) -> IO (PackageDB mode)
|
|
955
|
965
|
ignore_cache checkTime = do
|
|
956
|
966
|
-- If we're opening for modification, we need to acquire a
|
|
957
|
967
|
-- lock even if we don't open the cache now, because we are
|
| ... |
... |
@@ -987,17 +997,18 @@ readParseDatabase verbosity mb_user_conf mode use_cache path |
|
987
|
997
|
packages = pkgs
|
|
988
|
998
|
}
|
|
989
|
999
|
|
|
990
|
|
-parseSingletonPackageConf :: Verbosity -> FilePath -> IO InstalledPackageInfo
|
|
|
1000
|
+parseSingletonPackageConf :: Verbosity -> OsPath -> IO InstalledPackageInfo
|
|
991
|
1001
|
parseSingletonPackageConf verbosity file = do
|
|
992
|
|
- when (verbosity > Normal) $ infoLn ("reading package config: " ++ file)
|
|
993
|
|
- BS.readFile file >>= fmap fst . parsePackageInfo
|
|
|
1002
|
+ when (verbosity > Normal) $ infoLn ("reading package config: " ++ showOsPath file)
|
|
|
1003
|
+ FileIO.readFile file >>= fmap fst . parsePackageInfo . BS.toStrict
|
|
|
1004
|
+
|
|
994
|
1005
|
|
|
995
|
|
-cachefilename :: FilePath
|
|
996
|
|
-cachefilename = "package.cache"
|
|
|
1006
|
+cachefilename :: OsPath
|
|
|
1007
|
+cachefilename = os "package.cache"
|
|
997
|
1008
|
|
|
998
|
1009
|
mungePackageDBPaths :: FilePath -> PackageDB mode -> PackageDB mode
|
|
999
|
1010
|
mungePackageDBPaths top_dir db@PackageDB { packages = pkgs } =
|
|
1000
|
|
- db { packages = map (mungePackagePaths top_dir pkgroot) pkgs }
|
|
|
1011
|
+ db { packages = map (mungePackagePaths top_dir (unsafeDecodeUtf pkgroot)) pkgs }
|
|
1001
|
1012
|
where
|
|
1002
|
1013
|
pkgroot = takeDirectory $ dropTrailingPathSeparator (locationAbsolute db)
|
|
1003
|
1014
|
-- It so happens that for both styles of package db ("package.conf"
|
| ... |
... |
@@ -1044,12 +1055,13 @@ mkMungePathUrl top_dir pkgroot = (munge_path, munge_url) |
|
1044
|
1055
|
| Just p' <- stripVarPrefix "$httptopdir" p = toUrlPath top_dir p'
|
|
1045
|
1056
|
| otherwise = p
|
|
1046
|
1057
|
|
|
|
1058
|
+ toUrlPath :: FilePath -> FilePath -> FilePath
|
|
1047
|
1059
|
toUrlPath r p = "file:///"
|
|
1048
|
1060
|
-- URLs always use posix style '/' separators:
|
|
1049
|
1061
|
++ FilePath.Posix.joinPath
|
|
1050
|
1062
|
(r : -- We need to drop a leading "/" or "\\"
|
|
1051
|
1063
|
-- if there is one:
|
|
1052
|
|
- dropWhile (all isPathSeparator)
|
|
|
1064
|
+ dropWhile (all FilePath.isPathSeparator)
|
|
1053
|
1065
|
(FilePath.splitDirectories p))
|
|
1054
|
1066
|
|
|
1055
|
1067
|
-- We could drop the separator here, and then use </> above. However,
|
| ... |
... |
@@ -1057,7 +1069,7 @@ mkMungePathUrl top_dir pkgroot = (munge_path, munge_url) |
|
1057
|
1069
|
-- rather than letting FilePath change it to use \ as the separator
|
|
1058
|
1070
|
stripVarPrefix var path = case stripPrefix var path of
|
|
1059
|
1071
|
Just [] -> Just []
|
|
1060
|
|
- Just cs@(c : _) | isPathSeparator c -> Just cs
|
|
|
1072
|
+ Just cs@(c : _) | FilePath.isPathSeparator c -> Just cs
|
|
1061
|
1073
|
_ -> Nothing
|
|
1062
|
1074
|
|
|
1063
|
1075
|
-- -----------------------------------------------------------------------------
|
| ... |
... |
@@ -1074,18 +1086,18 @@ mkMungePathUrl top_dir pkgroot = (munge_path, munge_url) |
|
1074
|
1086
|
|
|
1075
|
1087
|
-- ghc itself also cooperates in this workaround
|
|
1076
|
1088
|
|
|
1077
|
|
-tryReadParseOldFileStyleDatabase :: Verbosity -> Maybe (FilePath, Bool)
|
|
1078
|
|
- -> GhcPkg.DbOpenMode mode t -> Bool -> FilePath
|
|
|
1089
|
+tryReadParseOldFileStyleDatabase :: Verbosity -> Maybe (OsPath, Bool)
|
|
|
1090
|
+ -> GhcPkg.DbOpenMode mode t -> Bool -> OsPath
|
|
1079
|
1091
|
-> IO (Maybe (PackageDB mode))
|
|
1080
|
1092
|
tryReadParseOldFileStyleDatabase verbosity mb_user_conf
|
|
1081
|
1093
|
mode use_cache path = do
|
|
1082
|
1094
|
-- assumes we've already established that path exists and is not a dir
|
|
1083
|
|
- content <- readFile path `catchIO` \_ -> return ""
|
|
|
1095
|
+ content <- readUtf8File path `catchIO` \_ -> return ""
|
|
1084
|
1096
|
if take 2 content == "[]"
|
|
1085
|
1097
|
then do
|
|
1086
|
1098
|
path_abs <- absolutePath path
|
|
1087
|
1099
|
let path_dir = adjustOldDatabasePath path
|
|
1088
|
|
- warn $ "Warning: ignoring old file-style db and trying " ++ path_dir
|
|
|
1100
|
+ warn $ "Warning: ignoring old file-style db and trying " ++ showOsPath path_dir
|
|
1089
|
1101
|
direxists <- doesDirectoryExist path_dir
|
|
1090
|
1102
|
if direxists
|
|
1091
|
1103
|
then do
|
| ... |
... |
@@ -1112,7 +1124,7 @@ tryReadParseOldFileStyleDatabase verbosity mb_user_conf |
|
1112
|
1124
|
adjustOldFileStylePackageDB :: PackageDB mode -> IO (PackageDB mode)
|
|
1113
|
1125
|
adjustOldFileStylePackageDB db = do
|
|
1114
|
1126
|
-- assumes we have not yet established if it's an old style or not
|
|
1115
|
|
- mcontent <- liftM Just (readFile (location db)) `catchIO` \_ -> return Nothing
|
|
|
1127
|
+ mcontent <- liftM Just (readUtf8File (location db)) `catchIO` \_ -> return Nothing
|
|
1116
|
1128
|
case fmap (take 2) mcontent of
|
|
1117
|
1129
|
-- it is an old style and empty db, so look for a dir kind in location.d/
|
|
1118
|
1130
|
Just "[]" -> return db {
|
| ... |
... |
@@ -1121,20 +1133,20 @@ adjustOldFileStylePackageDB db = do |
|
1121
|
1133
|
}
|
|
1122
|
1134
|
-- it is old style but not empty, we have to bail
|
|
1123
|
1135
|
Just _ -> die $ "ghc no longer supports single-file style package "
|
|
1124
|
|
- ++ "databases (" ++ location db ++ ") use 'ghc-pkg init'"
|
|
|
1136
|
+ ++ "databases (" ++ showOsPath (location db) ++ ") use 'ghc-pkg init'"
|
|
1125
|
1137
|
++ "to create the database with the correct format."
|
|
1126
|
1138
|
-- probably not old style, carry on as normal
|
|
1127
|
1139
|
Nothing -> return db
|
|
1128
|
1140
|
|
|
1129
|
|
-adjustOldDatabasePath :: FilePath -> FilePath
|
|
1130
|
|
-adjustOldDatabasePath = (<.> "d")
|
|
|
1141
|
+adjustOldDatabasePath :: OsPath -> OsPath
|
|
|
1142
|
+adjustOldDatabasePath = (<.> os "d")
|
|
1131
|
1143
|
|
|
1132
|
1144
|
-- -----------------------------------------------------------------------------
|
|
1133
|
1145
|
-- Creating a new package DB
|
|
1134
|
1146
|
|
|
1135
|
|
-initPackageDB :: FilePath -> Verbosity -> [Flag] -> IO ()
|
|
|
1147
|
+initPackageDB :: OsPath -> Verbosity -> [Flag] -> IO ()
|
|
1136
|
1148
|
initPackageDB filename verbosity _flags = do
|
|
1137
|
|
- let eexist = die ("cannot create: " ++ filename ++ " already exists")
|
|
|
1149
|
+ let eexist = die ("cannot create: " ++ showOsPath filename ++ " already exists")
|
|
1138
|
1150
|
b1 <- doesFileExist filename
|
|
1139
|
1151
|
when b1 eexist
|
|
1140
|
1152
|
b2 <- doesDirectoryExist filename
|
| ... |
... |
@@ -1183,7 +1195,8 @@ registerPackage input verbosity my_flags multi_instance |
|
1183
|
1195
|
f -> do
|
|
1184
|
1196
|
when (verbosity >= Normal) $
|
|
1185
|
1197
|
info ("Reading package info from " ++ show f ++ " ... ")
|
|
1186
|
|
- readUTF8File f
|
|
|
1198
|
+ fs <- encodeFS f
|
|
|
1199
|
+ readUtf8File fs
|
|
1187
|
1200
|
|
|
1188
|
1201
|
expanded <- if expand_env_vars then expandEnvVars s force
|
|
1189
|
1202
|
else return s
|
| ... |
... |
@@ -1199,7 +1212,11 @@ registerPackage input verbosity my_flags multi_instance |
|
1199
|
1212
|
-- validate the expanded pkg, but register the unexpanded
|
|
1200
|
1213
|
pkgroot <- absolutePath (takeDirectory to_modify)
|
|
1201
|
1214
|
let top_dir = takeDirectory (location (last db_stack))
|
|
1202
|
|
- pkg_expanded = mungePackagePaths top_dir pkgroot pkg
|
|
|
1215
|
+
|
|
|
1216
|
+ top_dir_filepath <- decodeFS top_dir
|
|
|
1217
|
+ pkgroot_filepath <- decodeFS pkgroot
|
|
|
1218
|
+ let
|
|
|
1219
|
+ pkg_expanded = mungePackagePaths top_dir_filepath pkgroot_filepath pkg
|
|
1203
|
1220
|
|
|
1204
|
1221
|
let truncated_stack = stackUpTo to_modify db_stack
|
|
1205
|
1222
|
-- truncate the stack for validation, because we don't allow
|
| ... |
... |
@@ -1274,13 +1291,13 @@ changeDBDir verbosity cmds db db_stack = do |
|
1274
|
1291
|
updateDBCache verbosity db db_stack
|
|
1275
|
1292
|
where
|
|
1276
|
1293
|
do_cmd (RemovePackage p) = do
|
|
1277
|
|
- let file = location db </> display (installedUnitId p) <.> "conf"
|
|
1278
|
|
- when (verbosity > Normal) $ infoLn ("removing " ++ file)
|
|
|
1294
|
+ let file = location db </> unsafeEncodeUtf (display (installedUnitId p)) <.> os "conf"
|
|
|
1295
|
+ when (verbosity > Normal) $ infoLn ("removing " ++ showOsPath file)
|
|
1279
|
1296
|
removeFileSafe file
|
|
1280
|
1297
|
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)
|
|
|
1298
|
+ let file = location db </> unsafeEncodeUtf (display (installedUnitId p)) <.> os "conf"
|
|
|
1299
|
+ when (verbosity > Normal) $ infoLn ("writing " ++ showOsPath file)
|
|
|
1300
|
+ writeUtf8File file (showInstalledPackageInfo p)
|
|
1284
|
1301
|
do_cmd (ModifyPackage p) =
|
|
1285
|
1302
|
do_cmd (AddPackage p)
|
|
1286
|
1303
|
|
| ... |
... |
@@ -1338,13 +1355,13 @@ updateDBCache verbosity db db_stack = do |
|
1338
|
1355
|
warn $ " " ++ pkg
|
|
1339
|
1356
|
|
|
1340
|
1357
|
when (verbosity > Normal) $
|
|
1341
|
|
- infoLn ("writing cache " ++ filename)
|
|
|
1358
|
+ infoLn ("writing cache " ++ showOsPath filename)
|
|
1342
|
1359
|
|
|
1343
|
1360
|
let d = fmap (fromPackageCacheFormat . fst) pkgsGhcCacheFormat
|
|
1344
|
1361
|
GhcPkg.writePackageDb filename d pkgsCabalFormat
|
|
1345
|
1362
|
`catchIO` \e ->
|
|
1346
|
1363
|
if isPermissionError e
|
|
1347
|
|
- then die $ filename ++ ": you don't have permission to modify this file"
|
|
|
1364
|
+ then die $ showOsPath filename ++ ": you don't have permission to modify this file"
|
|
1348
|
1365
|
else ioError e
|
|
1349
|
1366
|
|
|
1350
|
1367
|
case packageDbLock db of
|
| ... |
... |
@@ -1583,7 +1600,7 @@ listPackages verbosity my_flags mPackageName mModuleName = do |
|
1583
|
1600
|
broken = map installedUnitId (brokenPackages pkg_map)
|
|
1584
|
1601
|
|
|
1585
|
1602
|
show_normal PackageDB{ location = db_name, packages = pkg_confs } =
|
|
1586
|
|
- do hPutStrLn stdout db_name
|
|
|
1603
|
+ do hPutStrLn stdout (showOsPath db_name)
|
|
1587
|
1604
|
if null pkg_confs
|
|
1588
|
1605
|
then hPutStrLn stdout " (no packages)"
|
|
1589
|
1606
|
else hPutStrLn stdout $ unlines (map (" " ++) (map pp_pkg pkg_confs))
|
| ... |
... |
@@ -1610,7 +1627,7 @@ listPackages verbosity my_flags mPackageName mModuleName = do |
|
1610
|
1627
|
#else
|
|
1611
|
1628
|
let
|
|
1612
|
1629
|
show_colour PackageDB{ location = db_name, packages = pkg_confs } =
|
|
1613
|
|
- do hPutStrLn stdout db_name
|
|
|
1630
|
+ do hPutStrLn stdout (showOsPath db_name)
|
|
1614
|
1631
|
if null pkg_confs
|
|
1615
|
1632
|
then hPutStrLn stdout " (no packages)"
|
|
1616
|
1633
|
else hPutStrLn stdout $ unlines (map (" " ++) (map pp_pkg pkg_confs))
|
| ... |
... |
@@ -1698,7 +1715,7 @@ dumpUnits verbosity my_flags expand_pkgroot = do |
|
1698
|
1715
|
doDump expand_pkgroot [ (pkg, locationAbsolute db)
|
|
1699
|
1716
|
| db <- flag_db_stack, pkg <- packages db ]
|
|
1700
|
1717
|
|
|
1701
|
|
-doDump :: Bool -> [(InstalledPackageInfo, FilePath)] -> IO ()
|
|
|
1718
|
+doDump :: Bool -> [(InstalledPackageInfo, OsPath)] -> IO ()
|
|
1702
|
1719
|
doDump expand_pkgroot pkgs = do
|
|
1703
|
1720
|
-- fix the encoding to UTF-8, since this is an interchange format
|
|
1704
|
1721
|
hSetEncoding stdout utf8
|
| ... |
... |
@@ -1731,7 +1748,7 @@ findPackagesByDB db_stack pkgarg |
|
1731
|
1748
|
|
|
1732
|
1749
|
cannotFindPackage :: PackageArg -> Maybe (PackageDB mode) -> IO a
|
|
1733
|
1750
|
cannotFindPackage pkgarg mdb = die $ "cannot find package " ++ pkg_msg pkgarg
|
|
1734
|
|
- ++ maybe "" (\db -> " in " ++ location db) mdb
|
|
|
1751
|
+ ++ maybe "" (\db -> " in " ++ showOsPath (location db)) mdb
|
|
1735
|
1752
|
where
|
|
1736
|
1753
|
pkg_msg (Id pkgid) = displayGlobPkgId pkgid
|
|
1737
|
1754
|
pkg_msg (IUId ipid) = display ipid
|
| ... |
... |
@@ -1944,7 +1961,7 @@ checkPackageConfig pkg verbosity db_stack |
|
1944
|
1961
|
checkExposedModules db_stack pkg
|
|
1945
|
1962
|
checkOtherModules pkg
|
|
1946
|
1963
|
let has_code = Set.null (openModuleSubstFreeHoles (Map.fromList (instantiatedWith pkg)))
|
|
1947
|
|
- when has_code $ mapM_ (checkHSLib verbosity (libraryDirs pkg ++ libraryDynDirs pkg)) (hsLibraries pkg)
|
|
|
1964
|
+ when has_code $ mapM_ (checkHSLib verbosity (fmap unsafeEncodeUtf $ libraryDirs pkg ++ libraryDynDirs pkg)) (hsLibraries pkg)
|
|
1948
|
1965
|
-- ToDo: check these somehow?
|
|
1949
|
1966
|
-- extra_libraries :: [String],
|
|
1950
|
1967
|
-- c_includes :: [String],
|
| ... |
... |
@@ -2011,20 +2028,20 @@ checkPath url_ok is_dir warn_only thisfield d |
|
2011
|
2028
|
|| "https://" `isPrefixOf` d) = return ()
|
|
2012
|
2029
|
|
|
2013
|
2030
|
| url_ok
|
|
2014
|
|
- , Just d' <- stripPrefix "file://" d
|
|
2015
|
|
- = checkPath False is_dir warn_only thisfield d'
|
|
|
2031
|
+ , Just f <- stripPrefix "file://" d
|
|
|
2032
|
+ = checkPath False is_dir warn_only thisfield f
|
|
2016
|
2033
|
|
|
2017
|
2034
|
-- Note: we don't check for $topdir/${pkgroot} here. We rely on these
|
|
2018
|
2035
|
-- variables having been expanded already, see mungePackagePaths.
|
|
2019
|
2036
|
|
|
2020
|
|
- | isRelative d = verror ForceFiles $
|
|
|
2037
|
+ | isRelative d' = verror ForceFiles $
|
|
2021
|
2038
|
thisfield ++ ": " ++ d ++ " is a relative path which "
|
|
2022
|
2039
|
++ "makes no sense (as there is nothing for it to be "
|
|
2023
|
2040
|
++ "relative to). You can make paths relative to the "
|
|
2024
|
2041
|
++ "package database itself by using ${pkgroot}."
|
|
2025
|
2042
|
-- relative paths don't make any sense; #4134
|
|
2026
|
2043
|
| otherwise = do
|
|
2027
|
|
- there <- liftIO $ if is_dir then doesDirectoryExist d else doesFileExist d
|
|
|
2044
|
+ there <- liftIO $ if is_dir then doesDirectoryExist d' else doesFileExist d'
|
|
2028
|
2045
|
when (not there) $
|
|
2029
|
2046
|
let msg = thisfield ++ ": " ++ d ++ " doesn't exist or isn't a "
|
|
2030
|
2047
|
++ if is_dir then "directory" else "file"
|
| ... |
... |
@@ -2032,6 +2049,8 @@ checkPath url_ok is_dir warn_only thisfield d |
|
2032
|
2049
|
if warn_only
|
|
2033
|
2050
|
then vwarn msg
|
|
2034
|
2051
|
else verror ForceFiles msg
|
|
|
2052
|
+ where
|
|
|
2053
|
+ d' = unsafeEncodeUtf d
|
|
2035
|
2054
|
|
|
2036
|
2055
|
checkDep :: PackageDBStack -> UnitId -> Validate ()
|
|
2037
|
2056
|
checkDep db_stack pkgid
|
| ... |
... |
@@ -2050,24 +2069,25 @@ checkDuplicateDepends deps |
|
2050
|
2069
|
where
|
|
2051
|
2070
|
dups = [ p | (p:_:_) <- group (sort deps) ]
|
|
2052
|
2071
|
|
|
2053
|
|
-checkHSLib :: Verbosity -> [String] -> String -> Validate ()
|
|
|
2072
|
+checkHSLib :: Verbosity -> [OsPath] -> String -> Validate ()
|
|
2054
|
2073
|
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
|
|
- ]
|
|
|
2074
|
+ let filenames = fmap OsPath.unsafeEncodeUtf
|
|
|
2075
|
+ [ "lib" ++ lib ++ ".a"
|
|
|
2076
|
+ , "lib" ++ lib ++ "_p.a"
|
|
|
2077
|
+ , "lib" ++ lib ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".so"
|
|
|
2078
|
+ , "lib" ++ lib ++ "_p" ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".so"
|
|
|
2079
|
+ , "lib" ++ lib ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dylib"
|
|
|
2080
|
+ , "lib" ++ lib ++ "_p" ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dylib"
|
|
|
2081
|
+ , lib ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dll"
|
|
|
2082
|
+ , lib ++ "_p" ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dll"
|
|
|
2083
|
+ , lib ++ ".bytecodelib"
|
|
|
2084
|
+ ]
|
|
2065
|
2085
|
b <- liftIO $ doesFileExistOnPath filenames dirs
|
|
2066
|
2086
|
when (not b) $
|
|
2067
|
2087
|
verror ForceFiles ("cannot find any of " ++ show filenames ++
|
|
2068
|
2088
|
" on library path")
|
|
2069
|
2089
|
|
|
2070
|
|
-doesFileExistOnPath :: [FilePath] -> [FilePath] -> IO Bool
|
|
|
2090
|
+doesFileExistOnPath :: [OsPath] -> [OsPath] -> IO Bool
|
|
2071
|
2091
|
doesFileExistOnPath filenames paths = anyM doesFileExist fullFilenames
|
|
2072
|
2092
|
where fullFilenames = [ path </> filename
|
|
2073
|
2093
|
| filename <- filenames
|
| ... |
... |
@@ -2096,9 +2116,9 @@ checkModuleFile :: InstalledPackageInfo -> ModuleName -> Validate () |
|
2096
|
2116
|
checkModuleFile pkg modl =
|
|
2097
|
2117
|
-- there's no interface file for GHC.Prim
|
|
2098
|
2118
|
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)
|
|
|
2119
|
+ let files = [ unsafeEncodeUtf (ModuleName.toFilePath modl) <.> extension
|
|
|
2120
|
+ | extension <- fmap os ["hi", "p_hi", "dyn_hi", "p_dyn_hi"] ]
|
|
|
2121
|
+ b <- liftIO $ doesFileExistOnPath files (fmap unsafeEncodeUtf $ importDirs pkg)
|
|
2102
|
2122
|
when (not b) $
|
|
2103
|
2123
|
verror ForceFiles ("cannot find any of " ++ show files)
|
|
2104
|
2124
|
|
| ... |
... |
@@ -2273,19 +2293,45 @@ installSignalHandlers = do |
|
2273
|
2293
|
return ()
|
|
2274
|
2294
|
#endif
|
|
2275
|
2295
|
|
|
|
2296
|
+-- ------------------------------------------------
|
|
|
2297
|
+-- OsPath Utils
|
|
|
2298
|
+
|
|
|
2299
|
+-- | Show an 'OsPath', throwing an exception if we fail to decode it.
|
|
|
2300
|
+showOsPath :: HasCallStack => OsPath -> FilePath
|
|
|
2301
|
+showOsPath = unsafePerformIO . decodeFS
|
|
|
2302
|
+
|
|
|
2303
|
+-- | Turn a path relative to the current directory into a (normalised)
|
|
|
2304
|
+-- absolute path.
|
|
|
2305
|
+absolutePath :: OsPath -> IO OsPath
|
|
|
2306
|
+absolutePath path = return . normalise . (</> path) =<< getCurrentDirectory
|
|
|
2307
|
+
|
|
|
2308
|
+-- ------------------------------------------------
|
|
|
2309
|
+
|
|
2276
|
2310
|
catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a
|
|
2277
|
2311
|
catchIO = catchException
|
|
2278
|
2312
|
|
|
2279
|
2313
|
tryIO :: IO a -> IO (Either Exception.IOException a)
|
|
2280
|
2314
|
tryIO = Exception.try
|
|
2281
|
2315
|
|
|
2282
|
|
--- removeFileSave doesn't throw an exceptions, if the file is already deleted
|
|
2283
|
|
-removeFileSafe :: FilePath -> IO ()
|
|
|
2316
|
+-----------------------------------------
|
|
|
2317
|
+-- Adapted from ghc/compiler/utils/Panic
|
|
|
2318
|
+
|
|
|
2319
|
+-- | 'removeFileSave' doesn't throw an exceptions, if the file is already deleted
|
|
|
2320
|
+removeFileSafe :: OsPath -> IO ()
|
|
2284
|
2321
|
removeFileSafe fn =
|
|
2285
|
2322
|
removeFile fn `catchIO` \ e ->
|
|
2286
|
2323
|
when (not $ isDoesNotExistError e) $ ioError e
|
|
2287
|
2324
|
|
|
2288
|
|
--- | Turn a path relative to the current directory into a (normalised)
|
|
2289
|
|
--- absolute path.
|
|
2290
|
|
-absolutePath :: FilePath -> IO FilePath
|
|
2291
|
|
-absolutePath path = return . normalise . (</> path) =<< getCurrentDirectory |
|
|
2325
|
+-- | Read a file using UTF-8 encoding
|
|
|
2326
|
+--
|
|
|
2327
|
+-- Taken from https://github.com/haskell/cabal/blob/cea1d8ff1a80df3c3b3148d1556bd3edf656da93/Cabal-syntax/src/Distribution/Utils/Generic.hs#L326
|
|
|
2328
|
+-- and adapted to 'OsPath'.
|
|
|
2329
|
+writeUtf8File :: OsPath -> String -> IO ()
|
|
|
2330
|
+writeUtf8File file contents = writeFileAtomic file (toUTF8LBS contents)
|
|
|
2331
|
+
|
|
|
2332
|
+-- | Read a file and interpret its content to be UTF-8 encoded.
|
|
|
2333
|
+--
|
|
|
2334
|
+-- Taken from https://github.com/haskell/cabal/blob/cea1d8ff1a80df3c3b3148d1556bd3edf656da93/Cabal-syntax/src/Distribution/Utils/Generic.hs#L309
|
|
|
2335
|
+-- and adapted to 'OsPath'.
|
|
|
2336
|
+readUtf8File :: OsPath -> IO String
|
|
|
2337
|
+readUtf8File file = (ignoreBOM . fromUTF8LBS) <$> FileIO.readFile file |