on master help sign in
When searching for the containing project, don't stat the same thing twice
ef45f6bRyan Trinkle
command/src/Obelisk/Command/Project.hs+10−7
@@ -17,7 +17,7 @@ import System.Directory
17import System.Exit
17import System.Exit
18import System.FilePath
18import System.FilePath
19import System.IO
19import System.IO
20−import System.Posix (getFileStatus, deviceID, fileID, getRealUserID, fileOwner, fileMode)
20+import System.Posix (FileStatus, getFileStatus, deviceID, fileID, getRealUserID, fileOwner, fileMode)
21import System.Process
21import System.Process
22import Control.Monad.IO.Class
22import Control.Monad.IO.Class
23import Control.Monad.Trans.State
23import Control.Monad.Trans.State
@@ -69,12 +69,14 @@ findProjectObeliskCommand target = do
69 isSecure s = fileOwner s == myUid && fileMode s .&. 0o22 == 0
69 isSecure s = fileOwner s == myUid && fileMode s .&. 0o22 == 0
70 -- | Get the FilePath to the containing project directory, if there is
70 -- | Get the FilePath to the containing project directory, if there is
71 -- one; accumulate insecure directories we visited along the way
71 -- one; accumulate insecure directories we visited along the way
72− findImpl :: FilePath -> StateT [FilePath] IO (Maybe FilePath)
72+ findImpl :: FilePath -> FileStatus -> StateT [FilePath] IO (Maybe FilePath)
73− findImpl this = liftIO (doesDirectoryExist this) >>= \case
73+ findImpl this thisStat = liftIO (doesDirectoryExist this) >>= \case
74 -- It's not a directory, so it can't be a project
74 -- It's not a directory, so it can't be a project
75+ False -> do
75− False -> findImpl $ takeDirectory this
76+ let dir = takeDirectory this
77+ dirStat <- liftIO $ getFileStatus dir
78+ findImpl dir dirStat
76 True -> do
79 True -> do
77− thisStat <- liftIO $ getFileStatus this
78 when (not $ isSecure thisStat) $ modify (this:)
80 when (not $ isSecure thisStat) $ modify (this:)
79 liftIO (doesDirectoryExist (this </> ".obelisk")) >>= \case
81 liftIO (doesDirectoryExist (this </> ".obelisk")) >>= \case
80 True -> do
82 True -> do
@@ -92,8 +94,9 @@ findProjectObeliskCommand target = do
92 isSameFileAs = (==) `on` fileIdentity
94 isSameFileAs = (==) `on` fileIdentity
93 if thisStat `isSameFileAs` nextStat
95 if thisStat `isSameFileAs` nextStat
94 then return Nothing -- Found a cycle; probably hit root directory
96 then return Nothing -- Found a cycle; probably hit root directory
95− else findImpl next
97+ else findImpl next nextStat
98+ targetStat <- liftIO $ getFileStatus target
96− (result, insecurePaths) <- runStateT (findImpl target) []
99+ (result, insecurePaths) <- runStateT (findImpl target targetStat) []
97 case (result, insecurePaths) of
100 case (result, insecurePaths) of
98 (Just projDir, []) -> do
101 (Just projDir, []) -> do
99 obeliskCommandPkg <- nixBuildDashA (projDir </> ".obelisk" </> "impl") "command"
102 obeliskCommandPkg <- nixBuildDashA (projDir </> ".obelisk" </> "impl") "command"