Skip to content

Commit 85ad9f8

Browse files
committed
Faster cabal update
Contributed by Hideyuki Tanaka.
1 parent 80cc9b6 commit 85ad9f8

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

cabal-install/Distribution/Client/Update.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import Distribution.Client.FetchUtils
2121
import qualified Distribution.Client.PackageIndex as PackageIndex
2222
import Distribution.Client.IndexUtils
2323
( getSourcePackages, updateRepoIndexCache )
24+
import Distribution.Client.Utils
25+
( writeFileAtomic )
2426
import qualified Paths_cabal_install
2527
( version )
2628

@@ -29,12 +31,11 @@ import Distribution.Package
2931
import Distribution.Version
3032
( anyVersion, withinRange )
3133
import Distribution.Simple.Utils
32-
( warn, notice, writeFileAtomic )
34+
( warn, notice )
3335
import Distribution.Verbosity
3436
( Verbosity )
3537

3638
import qualified Data.ByteString.Lazy as BS
37-
import qualified Data.ByteString.Lazy.Char8 as BS.Char8
3839
import Distribution.Client.GZipUtils (maybeDecompress)
3940
import qualified Data.Map as Map
4041
import System.FilePath (dropExtension)
@@ -57,8 +58,7 @@ updateRepo verbosity repo = case repoKind repo of
5758
notice verbosity $ "Downloading the latest package list from "
5859
++ remoteRepoName remoteRepo
5960
indexPath <- downloadIndex verbosity remoteRepo (repoLocalDir repo)
60-
writeFileAtomic (dropExtension indexPath) . BS.Char8.unpack
61-
. maybeDecompress
61+
writeFileAtomic (dropExtension indexPath) . maybeDecompress
6262
=<< BS.readFile indexPath
6363
updateRepoIndexCache verbosity repo
6464

cabal-install/Distribution/Client/Utils.hs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,23 @@
22

33
module Distribution.Client.Utils ( MergeResult(..)
44
, mergeBy, duplicates, duplicatesBy
5-
, moreRecentFile, inDir, numberOfProcessors )
5+
, moreRecentFile, inDir, numberOfProcessors
6+
, writeFileAtomic )
67
where
78

89
import Data.List
910
( sortBy, groupBy )
1011
import Foreign.C.Types ( CInt(..) )
1112
import System.Directory
1213
( doesFileExist, getModificationTime
13-
, getCurrentDirectory, setCurrentDirectory )
14+
, getCurrentDirectory, setCurrentDirectory
15+
, renameFile, removeFile )
16+
import System.FilePath ( splitFileName, (<.>) )
17+
import System.IO ( openBinaryTempFile, hClose )
1418
import System.IO.Unsafe ( unsafePerformIO )
1519
import qualified Control.Exception as Exception
16-
( finally )
20+
( bracketOnError, finally )
21+
import qualified Data.ByteString.Lazy as BS
1722

1823
-- | Generic merging utility. For sorted input lists this is a full outer join.
1924
--
@@ -72,3 +77,22 @@ foreign import ccall "getNumberOfProcessors" c_getNumberOfProcessors :: IO CInt
7277
-- program, so unsafePerformIO is safe here.
7378
numberOfProcessors :: Int
7479
numberOfProcessors = fromEnum $ unsafePerformIO c_getNumberOfProcessors
80+
81+
-- | Writes a file atomically.
82+
--
83+
-- The file is either written sucessfully or an IO exception is raised and
84+
-- the original file is left unchanged.
85+
--
86+
-- On windows it is not possible to delete a file that is open by a process.
87+
-- This case will give an IO exception but the atomic property is not affected.
88+
--
89+
writeFileAtomic :: FilePath -> BS.ByteString -> IO ()
90+
writeFileAtomic targetPath content = do
91+
let (targetDir, targetFile) = splitFileName targetPath
92+
Exception.bracketOnError
93+
(openBinaryTempFile targetDir $ targetFile <.> "tmp")
94+
(\(tmpPath, handle) -> hClose handle >> removeFile tmpPath)
95+
(\(tmpPath, handle) -> do
96+
BS.hPut handle content
97+
hClose handle
98+
renameFile tmpPath targetPath)

0 commit comments

Comments
 (0)