Skip to content

Commit 97f9917

Browse files
jasagredoMikolaj
authored andcommitted
Use Base16 hash for script path.
Issue #9334 shows that `%` characters on Windows result in invalid paths, also `/` characters on Linux create invalid paths. This changes from using base64 to using base16 with the same length we use for unit-ids.
1 parent 4f53a2f commit 97f9917

File tree

6 files changed

+19
-18
lines changed

6 files changed

+19
-18
lines changed

cabal-install/cabal-install.cabal

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ library
209209
async >= 2.0 && < 2.3,
210210
array >= 0.4 && < 0.6,
211211
base16-bytestring >= 0.1.1 && < 1.1.0.0,
212-
base64-bytestring >= 1.0 && < 1.3,
213212
binary >= 0.7.3 && < 0.9,
214213
bytestring >= 0.10.6.0 && < 0.13,
215214
containers >= 0.5.6.2 && < 0.8,

cabal-install/src/Distribution/Client/HashValue.hs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ module Distribution.Client.HashValue
77
, hashValue
88
, truncateHash
99
, showHashValue
10-
, showHashValueBase64
1110
, readFileHashValue
1211
, hashFromTUF
1312
) where
@@ -19,7 +18,6 @@ import qualified Hackage.Security.Client as Sec
1918

2019
import qualified Crypto.Hash.SHA256 as SHA256
2120
import qualified Data.ByteString.Base16 as Base16
22-
import qualified Data.ByteString.Base64 as Base64
2321
import qualified Data.ByteString.Char8 as BS
2422
import qualified Data.ByteString.Lazy.Char8 as LBS
2523

@@ -57,9 +55,6 @@ hashValue = HashValue . SHA256.hashlazy
5755
showHashValue :: HashValue -> String
5856
showHashValue (HashValue digest) = BS.unpack (Base16.encode digest)
5957

60-
showHashValueBase64 :: HashValue -> String
61-
showHashValueBase64 (HashValue digest) = BS.unpack (Base64.encode digest)
62-
6358
-- | Hash the content of a file. Uses SHA256.
6459
readFileHashValue :: FilePath -> IO HashValue
6560
readFileHashValue tarball =

cabal-install/src/Distribution/Client/ScriptUtils.hs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ import Distribution.Client.DistDirLayout
3737
)
3838
import Distribution.Client.HashValue
3939
( hashValue
40-
, showHashValueBase64
40+
, showHashValue
41+
, truncateHash
4142
)
4243
import Distribution.Client.HttpUtils
4344
( HttpTransport
@@ -218,18 +219,15 @@ import qualified Text.Parsec as P
218219
-- repl to deal with the fact that the repl is relative to the working directory and not
219220
-- the project root.
220221

221-
-- | Get the hash of a script's absolute path)
222+
-- | Get the hash of a script's absolute path.
222223
--
223224
-- Two hashes will be the same as long as the absolute paths
224225
-- are the same.
225226
getScriptHash :: FilePath -> IO String
226227
getScriptHash script =
227-
-- Base64 is shorter than Base16, which helps avoid long path issues on windows
228-
-- but it can contain /'s which aren't valid in file paths so replace them with
229-
-- %'s. 26 chars / 130 bits is enough to practically avoid collisions.
230-
map (\c -> if c == '/' then '%' else c)
231-
. take 26
232-
. showHashValueBase64
228+
-- Truncation here tries to help with long path issues on Windows.
229+
showHashValue
230+
. truncateHash 26
233231
. hashValue
234232
. fromString
235233
<$> canonicalizePath script

cabal-testsuite/cabal-testsuite.cabal

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ library
6060
, aeson ^>= 1.4.2.0 || ^>=1.5.0.0 || ^>= 2.0.0.0 || ^>= 2.1.0.0 || ^>= 2.2.1.0
6161
, async ^>= 2.2.1
6262
, attoparsec ^>= 0.13.2.2 || ^>=0.14.1
63-
, base64-bytestring ^>= 1.0.0.0 || ^>= 1.1.0.0 || ^>= 1.2.0.0
63+
, base16-bytestring ^>= 0.1.1.5 || ^>= 1.0
6464
, bytestring ^>= 0.10.0.2 || ^>= 0.11.0.0 || ^>= 0.12.0.0
6565
, containers ^>= 0.5.0.0 || ^>= 0.6.0.1
6666
, cryptohash-sha256 ^>= 0.11.101.0
@@ -120,6 +120,7 @@ executable setup
120120

121121
-- If you require an external dependency for a test it must be listed here.
122122
executable test-runtime-deps
123+
default-language: Haskell2010
123124
build-depends: cabal-testsuite,
124125
base,
125126
directory,

cabal-testsuite/src/Test/Cabal/Prelude.hs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ import Control.Monad (unless, when, void, forM_, liftM2, liftM4)
5353
import Control.Monad.Trans.Reader (withReaderT, runReaderT)
5454
import Control.Monad.IO.Class (MonadIO (..))
5555
import qualified Crypto.Hash.SHA256 as SHA256
56-
import qualified Data.ByteString.Base64 as Base64
56+
import qualified Data.ByteString.Base16 as Base16
5757
import qualified Data.ByteString.Char8 as C
5858
import Data.List (isInfixOf, stripPrefix, isPrefixOf, intercalate)
5959
import Data.List.NonEmpty (NonEmpty (..))
@@ -856,8 +856,7 @@ getScriptCacheDirectory :: FilePath -> TestM FilePath
856856
getScriptCacheDirectory script = do
857857
cabalDir <- testCabalDir `fmap` getTestEnv
858858
hashinput <- liftIO $ canonicalizePath script
859-
let hash = map (\c -> if c == '/' then '%' else c) . take 26
860-
. C.unpack . Base64.encode . SHA256.hash . C.pack $ hashinput
859+
let hash = C.unpack . Base16.encode . C.take 26 . SHA256.hash . C.pack $ hashinput
861860
return $ cabalDir </> "script-builds" </> hash
862861

863862
------------------------------------------------------------------------

changelog.d/base16-script-cache

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
synopsis: Script cache dir is the base16 hash of the canonical path of the script.
2+
prs: #9459
3+
packages: cabal-install
4+
5+
description: {
6+
7+
Script cache dir is the base16 hash of the canonical path of the script.
8+
9+
}

0 commit comments

Comments
 (0)