Hannes Siebenhandl pushed to branch wip/fendor/ghc-pkg-ospath at Glasgow Haskell Compiler / GHC

Commits:

8 changed files:

Changes:

  • compiler/GHC/Unit/State.hs
    ... ... @@ -802,7 +802,7 @@ readUnitDatabase logger cfg conf_file = do
    802 802
           if cache_exists
    
    803 803
             then do
    
    804 804
               debugTraceMsg logger 2 $ text "Using binary package database:" <+> ppr filename
    
    805
    -          readPackageDbForGhc (OsPath.unsafeDecodeUtf filename)
    
    805
    +          readPackageDbForGhc filename
    
    806 806
             else do
    
    807 807
               -- If there is no package.cache file, we check if the database is not
    
    808 808
               -- empty by inspecting if the directory contains any .conf file. If it
    

  • libraries/ghc-boot/GHC/Unit/Database.hs
    ... ... @@ -68,6 +68,8 @@ module GHC.Unit.Database
    68 68
        -- * Misc
    
    69 69
        , mkMungePathUrl
    
    70 70
        , mungeUnitInfoPaths
    
    71
    +   , writeFileAtomic
    
    72
    +   , unsafeDecodeUtf
    
    71 73
        )
    
    72 74
     where
    
    73 75
     
    
    ... ... @@ -86,10 +88,10 @@ import Data.Binary.Get as Bin
    86 88
     import Data.List (intersperse)
    
    87 89
     import Control.Exception as Exception
    
    88 90
     import Control.Monad (when)
    
    89
    -import System.FilePath as FilePath
    
    91
    +import qualified System.FilePath as FilePath
    
    90 92
     #if !defined(mingw32_HOST_OS)
    
    91 93
     import Data.Bits ((.|.))
    
    92
    -import System.Posix.Files
    
    94
    +import System.Posix.Files.PosixString
    
    93 95
     import System.Posix.Types (FileMode)
    
    94 96
     #endif
    
    95 97
     import System.IO
    
    ... ... @@ -97,7 +99,12 @@ import System.IO.Error
    97 99
     import GHC.IO.Exception (IOErrorType(InappropriateType))
    
    98 100
     import qualified GHC.Data.ShortText as ST
    
    99 101
     import GHC.IO.Handle.Lock
    
    100
    -import System.Directory
    
    102
    +import GHC.Stack.Types (HasCallStack)
    
    103
    +import System.OsPath
    
    104
    +import System.OsString.Internal.Types (getOsString)
    
    105
    +import qualified System.Directory.OsPath as OsPath
    
    106
    +import qualified System.Directory.Internal as OsPath.Internal
    
    107
    +import qualified System.File.OsPath as FileIO
    
    101 108
     
    
    102 109
     -- | @ghc-boot@'s UnitInfo, serialized to the database.
    
    103 110
     type DbUnitInfo      = GenericUnitInfo BS.ByteString BS.ByteString BS.ByteString BS.ByteString DbModule
    
    ... ... @@ -314,13 +321,13 @@ data DbInstUnitId
    314 321
     newtype PackageDbLock = PackageDbLock Handle
    
    315 322
     
    
    316 323
     -- | Acquire an exclusive lock related to package DB under given location.
    
    317
    -lockPackageDb :: FilePath -> IO PackageDbLock
    
    324
    +lockPackageDb :: OsPath -> IO PackageDbLock
    
    318 325
     
    
    319 326
     -- | Release the lock related to package DB.
    
    320 327
     unlockPackageDb :: PackageDbLock -> IO ()
    
    321 328
     
    
    322 329
     -- | Acquire a lock of given type related to package DB under given location.
    
    323
    -lockPackageDbWith :: LockMode -> FilePath -> IO PackageDbLock
    
    330
    +lockPackageDbWith :: LockMode -> OsPath -> IO PackageDbLock
    
    324 331
     lockPackageDbWith mode file = do
    
    325 332
       -- We are trying to open the lock file and then lock it. Thus the lock file
    
    326 333
       -- needs to either exist or we need to be able to create it. Ideally we
    
    ... ... @@ -350,10 +357,10 @@ lockPackageDbWith mode file = do
    350 357
         (lockFileOpenIn ReadWriteMode)
    
    351 358
         (const $ lockFileOpenIn ReadMode)
    
    352 359
       where
    
    353
    -    lock = file <.> "lock"
    
    360
    +    lock = file <.> OsPath.Internal.os "lock"
    
    354 361
     
    
    355 362
         lockFileOpenIn io_mode = bracketOnError
    
    356
    -      (openBinaryFile lock io_mode)
    
    363
    +      (FileIO.openBinaryFile lock io_mode)
    
    357 364
           hClose
    
    358 365
           -- If file locking support is not available, ignore the error and proceed
    
    359 366
           -- normally. Without it the only thing we lose on non-Windows platforms is
    
    ... ... @@ -387,7 +394,7 @@ isDbOpenReadMode = \case
    387 394
     
    
    388 395
     -- | Read the part of the package DB that GHC is interested in.
    
    389 396
     --
    
    390
    -readPackageDbForGhc :: FilePath -> IO [DbUnitInfo]
    
    397
    +readPackageDbForGhc :: OsPath -> IO [DbUnitInfo]
    
    391 398
     readPackageDbForGhc file =
    
    392 399
       decodeFromFile file DbOpenReadOnly getDbForGhc >>= \case
    
    393 400
         (pkgs, DbOpenReadOnly) -> return pkgs
    
    ... ... @@ -409,7 +416,7 @@ readPackageDbForGhc file =
    409 416
     -- we additionally receive a PackageDbLock that represents a lock on the
    
    410 417
     -- database, so that we can safely update it later.
    
    411 418
     --
    
    412
    -readPackageDbForGhcPkg :: Binary pkgs => FilePath -> DbOpenMode mode t ->
    
    419
    +readPackageDbForGhcPkg :: Binary pkgs => OsPath -> DbOpenMode mode t ->
    
    413 420
                               IO (pkgs, DbOpenMode mode PackageDbLock)
    
    414 421
     readPackageDbForGhcPkg file mode =
    
    415 422
         decodeFromFile file mode getDbForGhcPkg
    
    ... ... @@ -425,7 +432,7 @@ readPackageDbForGhcPkg file mode =
    425 432
     
    
    426 433
     -- | Write the whole of the package DB, both parts.
    
    427 434
     --
    
    428
    -writePackageDb :: Binary pkgs => FilePath -> [DbUnitInfo] -> pkgs -> IO ()
    
    435
    +writePackageDb :: Binary pkgs => OsPath -> [DbUnitInfo] -> pkgs -> IO ()
    
    429 436
     writePackageDb file ghcPkgs ghcPkgPart = do
    
    430 437
       writeFileAtomic file (runPut putDbForGhcPkg)
    
    431 438
     #if !defined(mingw32_HOST_OS)
    
    ... ... @@ -446,10 +453,10 @@ writePackageDb file ghcPkgs ghcPkgPart = do
    446 453
             ghcPart    = encode ghcPkgs
    
    447 454
     
    
    448 455
     #if !defined(mingw32_HOST_OS)
    
    449
    -addFileMode :: FilePath -> FileMode -> IO ()
    
    456
    +addFileMode :: OsPath -> FileMode -> IO ()
    
    450 457
     addFileMode file m = do
    
    451
    -  o <- fileMode <$> getFileStatus file
    
    452
    -  setFileMode file (m .|. o)
    
    458
    +  o <- fileMode <$> getFileStatus (getOsString file)
    
    459
    +  setFileMode (getOsString file) (m .|. o)
    
    453 460
     #endif
    
    454 461
     
    
    455 462
     getHeader :: Get (Word32, Word32)
    
    ... ... @@ -496,7 +503,7 @@ headerMagic = BS.Char8.pack "\0ghcpkg\0"
    496 503
     
    
    497 504
     -- | Feed a 'Get' decoder with data chunks from a file.
    
    498 505
     --
    
    499
    -decodeFromFile :: FilePath -> DbOpenMode mode t -> Get pkgs ->
    
    506
    +decodeFromFile :: OsPath -> DbOpenMode mode t -> Get pkgs ->
    
    500 507
                       IO (pkgs, DbOpenMode mode PackageDbLock)
    
    501 508
     decodeFromFile file mode decoder = case mode of
    
    502 509
       DbOpenReadOnly -> do
    
    ... ... @@ -517,7 +524,7 @@ decodeFromFile file mode decoder = case mode of
    517 524
         bracketOnError (lockPackageDb file) unlockPackageDb $ \lock -> do
    
    518 525
           (, DbOpenReadWrite lock) <$> decodeFileContents
    
    519 526
       where
    
    520
    -    decodeFileContents = withBinaryFile file ReadMode $ \hnd ->
    
    527
    +    decodeFileContents = FileIO.withBinaryFile file ReadMode $ \hnd ->
    
    521 528
           feed hnd (runGetIncremental decoder)
    
    522 529
     
    
    523 530
         feed hnd (Partial k)  = do chunk <- BS.hGet hnd BS.Lazy.defaultChunkSize
    
    ... ... @@ -527,21 +534,21 @@ decodeFromFile file mode decoder = case mode of
    527 534
         feed _ (Done _ _ res) = return res
    
    528 535
         feed _ (Fail _ _ msg) = ioError err
    
    529 536
           where
    
    530
    -        err = mkIOError InappropriateType loc Nothing (Just file)
    
    537
    +        err = mkIOError InappropriateType loc Nothing (Just $ unsafeDecodeUtf file)
    
    531 538
                   `ioeSetErrorString` msg
    
    532 539
             loc = "GHC.Unit.Database.readPackageDb"
    
    533 540
     
    
    534 541
     -- Copied from Cabal's Distribution.Simple.Utils.
    
    535
    -writeFileAtomic :: FilePath -> BS.Lazy.ByteString -> IO ()
    
    542
    +writeFileAtomic :: OsPath -> BS.Lazy.ByteString -> IO ()
    
    536 543
     writeFileAtomic targetPath content = do
    
    537 544
       let (targetDir, targetFile) = splitFileName targetPath
    
    538 545
       Exception.bracketOnError
    
    539
    -    (openBinaryTempFileWithDefaultPermissions targetDir $ targetFile <.> "tmp")
    
    540
    -    (\(tmpPath, handle) -> hClose handle >> removeFile tmpPath)
    
    546
    +    (FileIO.openBinaryTempFileWithDefaultPermissions targetDir $ targetFile <.> OsPath.Internal.os "tmp")
    
    547
    +    (\(tmpPath, handle) -> hClose handle >> OsPath.removeFile tmpPath)
    
    541 548
         (\(tmpPath, handle) -> do
    
    542 549
             BS.Lazy.hPut handle content
    
    543 550
             hClose handle
    
    544
    -        renameFile tmpPath targetPath)
    
    551
    +        OsPath.renameFile tmpPath targetPath)
    
    545 552
     
    
    546 553
     instance Binary DbUnitInfo where
    
    547 554
       put (GenericUnitInfo
    
    ... ... @@ -711,7 +718,7 @@ mkMungePathUrl top_dir pkgroot = (munge_path, munge_url)
    711 718
         -- rather than letting FilePath change it to use \ as the separator
    
    712 719
         stripVarPrefix var path = case ST.stripPrefix var path of
    
    713 720
                                   Just "" -> Just ""
    
    714
    -                              Just cs | isPathSeparator (ST.head cs) -> Just cs
    
    721
    +                              Just cs | FilePath.isPathSeparator (ST.head cs) -> Just cs
    
    715 722
                                   _ -> Nothing
    
    716 723
     
    
    717 724
     
    
    ... ... @@ -742,3 +749,8 @@ mungeUnitInfoPaths top_dir pkgroot pkg =
    742 749
           munge_paths = map munge_path
    
    743 750
           munge_urls  = map munge_url
    
    744 751
           (munge_path,munge_url) = mkMungePathUrl top_dir pkgroot
    
    752
    +
    
    753
    +-- | Decode an 'OsPath' to 'FilePath', throwing an 'error' if decoding failed.
    
    754
    +-- Prefer 'decodeUtf' and gracious error handling.
    
    755
    +unsafeDecodeUtf :: HasCallStack => OsPath -> FilePath
    
    756
    +unsafeDecodeUtf = OsPath.Internal.so

  • libraries/ghc-boot/ghc-boot.cabal.in
    ... ... @@ -81,6 +81,8 @@ Library
    81 81
                        containers >= 0.5 && < 0.9,
    
    82 82
                        directory  >= 1.2 && < 1.4,
    
    83 83
                        filepath   >= 1.3 && < 1.6,
    
    84
    +                   file-io,
    
    85
    +                   os-string,
    
    84 86
                        deepseq    >= 1.4 && < 1.6,
    
    85 87
                        ghc-platform  >= 0.1,
    
    86 88
                        ghc-toolchain >= 0.1
    

  • testsuite/tests/cabal/Makefile
    ... ... @@ -79,6 +79,25 @@ ghcpkg04 :
    79 79
     	@: # testpkg-1.2.3.4 and newtestpkg-2.0 are both exposed now
    
    80 80
     	'$(TEST_HC)' $(TEST_HC_OPTS) -package-db $(PKGCONF04) -c ghcpkg04.hs || true
    
    81 81
     
    
    82
    +PKGCONF20=local20.package.conf
    
    83
    +LOCAL_GHC_PKG20 = '$(GHC_PKG)' --no-user-package-db
    
    84
    +
    
    85
    +DIR1=asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf
    
    86
    +DIR2=zxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcv
    
    87
    +DIR3=uiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiop
    
    88
    +DIR4=qwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwer
    
    89
    +WDIR=$(DIR1)/$(DIR2)/$(DIR3)/$(DIR4)
    
    90
    +.PHONY: ghcpkg10
    
    91
    +ghcpkg10 :
    
    92
    +	@mkdir -p $(WDIR)
    
    93
    +	@rm -rf $(WDIR)/$(PKGCONF20)
    
    94
    +	$(LOCAL_GHC_PKG20) -f $(WDIR)/$(PKGCONF20) init $(WDIR)/$(PKGCONF20)
    
    95
    +	$(LOCAL_GHC_PKG20) -f $(WDIR)/$(PKGCONF20) list
    
    96
    +	$(LOCAL_GHC_PKG20) -f $(WDIR)/$(PKGCONF20) register --force test.pkg 2>/dev/null
    
    97
    +	$(LOCAL_GHC_PKG20) -f $(WDIR)/$(PKGCONF20) describe testpkg         | $(STRIP_PKGROOT)
    
    98
    +	$(LOCAL_GHC_PKG20) -f $(WDIR)/$(PKGCONF20) describe testpkg-1.2.3.4 | $(STRIP_PKGROOT)
    
    99
    +	$(LOCAL_GHC_PKG20) -f $(WDIR)/$(PKGCONF20) field testpkg-1.2.3.4 import-dirs
    
    100
    +
    
    82 101
     # Test stacking of package.confs (also #2441)
    
    83 102
     PKGCONF05a=local05a.package.conf
    
    84 103
     PKGCONF05b=local05b.package.conf
    

  • testsuite/tests/cabal/all.T
    ... ... @@ -5,6 +5,7 @@ def ignore_warnings(str):
    5 5
         return re.sub(r'Warning:.*\n', '', str)
    
    6 6
     
    
    7 7
     test('ghcpkg01', [extra_files(['test.pkg', 'test2.pkg', 'test3.pkg'])], makefile_test, [])
    
    8
    +test('ghcpkg10', [extra_files(['test.pkg', 'test2.pkg', 'test3.pkg'])], makefile_test, [])
    
    8 9
     
    
    9 10
     # Use ignore_stderr to prevent (when HADDOCK_DOCS=NO):
    
    10 11
     #  warning: haddock-interfaces .. doesn't exist or isn't a file
    

  • testsuite/tests/cabal/ghcpkg10.stdout
    1
    +asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf/zxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcvzxcv/uiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiopuiop/qwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwerqwer/local20.package.conf
    
    2
    +    (no packages)
    
    3
    +Reading package info from "test.pkg" ... done.
    
    4
    +name:            testpkg
    
    5
    +version:         1.2.3.4
    
    6
    +visibility:      public
    
    7
    +id:              testpkg-1.2.3.4-XXX
    
    8
    +key:             testpkg-1.2.3.4-XXX
    
    9
    +license:         BSD3
    
    10
    +copyright:       (c) The Univsersity of Glasgow 2004
    
    11
    +maintainer:      glasgow-haskell-users@haskell.org
    
    12
    +author:          simonmar@microsoft.com
    
    13
    +stability:       stable
    
    14
    +homepage:        http://www.haskell.org/ghc
    
    15
    +package-url:     http://www.haskell.org/ghc
    
    16
    +description:     A Test Package
    
    17
    +category:        none
    
    18
    +exposed:         True
    
    19
    +exposed-modules: A
    
    20
    +hidden-modules:  B C.D
    
    21
    +import-dirs:     /usr/local/lib/testpkg "c:/Program Files/testpkg"
    
    22
    +library-dirs:    /usr/local/lib/testpkg "c:/Program Files/testpkg"
    
    23
    +hs-libraries:    testpkg-1.2.3.4-XXX
    
    24
    +include-dirs:    /usr/local/include/testpkg "c:/Program Files/testpkg"
    
    25
    +pkgroot: 
    
    26
    +
    
    27
    +name:            testpkg
    
    28
    +version:         1.2.3.4
    
    29
    +visibility:      public
    
    30
    +id:              testpkg-1.2.3.4-XXX
    
    31
    +key:             testpkg-1.2.3.4-XXX
    
    32
    +license:         BSD3
    
    33
    +copyright:       (c) The Univsersity of Glasgow 2004
    
    34
    +maintainer:      glasgow-haskell-users@haskell.org
    
    35
    +author:          simonmar@microsoft.com
    
    36
    +stability:       stable
    
    37
    +homepage:        http://www.haskell.org/ghc
    
    38
    +package-url:     http://www.haskell.org/ghc
    
    39
    +description:     A Test Package
    
    40
    +category:        none
    
    41
    +exposed:         True
    
    42
    +exposed-modules: A
    
    43
    +hidden-modules:  B C.D
    
    44
    +import-dirs:     /usr/local/lib/testpkg "c:/Program Files/testpkg"
    
    45
    +library-dirs:    /usr/local/lib/testpkg "c:/Program Files/testpkg"
    
    46
    +hs-libraries:    testpkg-1.2.3.4-XXX
    
    47
    +include-dirs:    /usr/local/include/testpkg "c:/Program Files/testpkg"
    
    48
    +pkgroot: 
    
    49
    +
    
    50
    +import-dirs: /usr/local/lib/testpkg "c:/Program Files/testpkg"

  • utils/ghc-pkg/Main.hs
    ... ... @@ -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

  • utils/ghc-pkg/ghc-pkg.cabal.in
    ... ... @@ -25,6 +25,7 @@ Executable ghc-pkg
    25 25
                        process    >= 1   && < 1.7,
    
    26 26
                        containers,
    
    27 27
                        filepath,
    
    28
    +                   file-io,
    
    28 29
                        Cabal,
    
    29 30
                        Cabal-syntax,
    
    30 31
                        binary,