Skip to content

Commit fa686f8

Browse files
committed
[#198] Fix getFileStatus exception
Problem: hnix-store throws getFileStatus error, if directory contains file with self-symlink Solution: capture if target file is symlink before trying to call narIsDir
1 parent bda3a97 commit fa686f8

File tree

1 file changed

+22
-25
lines changed

1 file changed

+22
-25
lines changed

hnix-store-core/src/System/Nix/Internal/Nar/Streamer.hs

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
-- | Stream out a NAR file from a regular file
22

3-
{-# language ScopedTypeVariables #-}
3+
{-# LANGUAGE ScopedTypeVariables #-}
44

55
module System.Nix.Internal.Nar.Streamer
66
( NarSource
@@ -17,7 +17,7 @@ import qualified Data.ByteString.Char8 as Bytes.Char8
1717
import qualified Data.ByteString.Lazy as Bytes.Lazy
1818
import qualified Data.Serialize as Serial
1919
import qualified System.Directory as Directory
20-
import System.FilePath ( (</>) )
20+
import System.FilePath ((</>))
2121

2222
import qualified System.Nix.Internal.Nar.Effects as Nar
2323

@@ -61,33 +61,30 @@ streamNarIO effs basePath yield = do
6161
where
6262
go :: FilePath -> m ()
6363
go path = do
64-
isDir <- IO.liftIO $ Nar.narIsDir effs path
6564
isSymLink <- IO.liftIO $ Nar.narIsSymLink effs path
66-
let isRegular = not $ isDir || isSymLink
67-
68-
when isSymLink $ do
65+
if isSymLink then do
6966
target <- IO.liftIO $ Nar.narReadLink effs path
7067
yield $
7168
strs ["type", "symlink", "target", Bytes.Char8.pack target]
72-
73-
when isRegular $ do
74-
isExec <- IO.liftIO $ isExecutable effs path
75-
yield $ strs ["type", "regular"]
76-
when (isExec == Executable) $ yield $ strs ["executable", ""]
77-
fSize <- IO.liftIO $ Nar.narFileSize effs path
78-
yield $ str "contents"
79-
yield $ int fSize
80-
yieldFile path fSize
81-
82-
when (isDir && not isSymLink) $ do
83-
fs <- IO.liftIO (Nar.narListDir effs path)
84-
yield $ strs ["type", "directory"]
85-
forM_ (sort fs) $ \f -> do
86-
yield $ str "entry"
87-
parens $ do
88-
let fullName = path </> f
89-
yield $ strs ["name", Bytes.Char8.pack f, "node"]
90-
parens $ go fullName
69+
else do
70+
isDir <- IO.liftIO $ Nar.narIsDir effs path
71+
if isDir then do
72+
fs <- IO.liftIO (Nar.narListDir effs path)
73+
yield $ strs ["type", "directory"]
74+
forM_ (sort fs) $ \f -> do
75+
yield $ str "entry"
76+
parens $ do
77+
let fullName = path </> f
78+
yield $ strs ["name", Bytes.Char8.pack f, "node"]
79+
parens $ go fullName
80+
else do
81+
isExec <- IO.liftIO $ isExecutable effs path
82+
yield $ strs ["type", "regular"]
83+
when (isExec == Executable) $ yield $ strs ["executable", ""]
84+
fSize <- IO.liftIO $ Nar.narFileSize effs path
85+
yield $ str "contents"
86+
yield $ int fSize
87+
yieldFile path fSize
9188

9289
parens act = do
9390
yield $ str "("

0 commit comments

Comments
 (0)