Skip to content

Commit b2e3d9e

Browse files
committed
Integration test for unlisted/TH dependencies (#32/#105)
1 parent ee9eaae commit b2e3d9e

File tree

12 files changed

+131
-3
lines changed

12 files changed

+131
-3
lines changed

src/Path/IO.hs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{-# LANGUAGE DeriveDataTypeable #-}
2+
{-# LANGUAGE ViewPatterns #-}
23

34
-- | IO actions that might be put in a package at some point.
45

@@ -30,7 +31,9 @@ module Path.IO
3031
,copyFileIfExists
3132
,copyDirectoryRecursive
3233
,createTree
33-
,dropRoot)
34+
,dropRoot
35+
,parseCollapsedAbsFile
36+
,parseCollapsedAbsDir)
3437
where
3538

3639
import Control.Exception hiding (catch)
@@ -123,6 +126,44 @@ resolveFileMaybe :: (MonadIO m,MonadThrow m)
123126
=> Path Abs Dir -> FilePath -> m (Maybe (Path Abs File))
124127
resolveFileMaybe = resolveCheckParse D.doesFileExist parseAbsFile
125128

129+
-- | Collapse intermediate "." and ".." directories from path, then parse
130+
-- it with 'parseAbsFile'.
131+
-- (probably should be moved to the Path module)
132+
parseCollapsedAbsFile :: MonadThrow m => FilePath -> m (Path Abs File)
133+
parseCollapsedAbsFile = parseAbsFile . collapseFilePath
134+
135+
-- | Collapse intermediate "." and ".." directories from path, then parse
136+
-- it with 'parseAbsDir'.
137+
-- (probably should be moved to the Path module)
138+
parseCollapsedAbsDir :: MonadThrow m => FilePath -> m (Path Abs Dir)
139+
parseCollapsedAbsDir = parseAbsDir . collapseFilePath
140+
141+
-- | Collapse intermediate "." and ".." directories from a path.
142+
--
143+
-- > collapseFilePath "./foo" == "foo"
144+
-- > collapseFilePath "/bar/../baz" == "/baz"
145+
-- > collapseFilePath "/../baz" == "/../baz"
146+
-- > collapseFilePath "parent/foo/baz/../bar" == "parent/foo/bar"
147+
-- > collapseFilePath "parent/foo/baz/../../bar" == "parent/bar"
148+
-- > collapseFilePath "parent/foo/.." == "parent"
149+
-- > collapseFilePath "/parent/foo/../../bar" == "/bar"
150+
--
151+
-- (borrowed from @Text.Pandoc.Shared@)
152+
collapseFilePath :: FilePath -> FilePath
153+
collapseFilePath = FP.joinPath . reverse . foldl go [] . FP.splitDirectories
154+
where
155+
go rs "." = rs
156+
go r@(p:rs) ".." = case p of
157+
".." -> ("..":r)
158+
(checkPathSeperator -> Just True) -> ("..":r)
159+
_ -> rs
160+
go _ (checkPathSeperator -> Just True) = [[FP.pathSeparator]]
161+
go rs x = x:rs
162+
isSingleton [] = Nothing
163+
isSingleton [x] = Just x
164+
isSingleton _ = Nothing
165+
checkPathSeperator = fmap FP.isPathSeparator . isSingleton
166+
126167
-- | List objects in a directory, excluding "@.@" and "@..@". Entries are not sorted.
127168
listDirectory :: (MonadIO m,MonadThrow m) => Path Abs Dir -> m ([Path Abs Dir],[Path Abs File])
128169
listDirectory dir =

src/Stack/Package.hs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -801,15 +801,22 @@ findCandidate dirs exts name = do
801801
-> IO [Either ResolveException (Path Abs File)]
802802
makeDirCandidates dir =
803803
case name of
804-
Right fp -> liftM return (try (resolveFile dir fp))
804+
Right fp -> liftM return (try (resolveFile' dir fp))
805805
Left mn ->
806806
mapM
807807
(\ext ->
808808
try
809-
(resolveFile
809+
(resolveFile'
810810
dir
811811
(Cabal.toFilePath mn ++ "." ++ ext)))
812812
(map T.unpack exts)
813+
resolveFile' :: (MonadIO m, MonadThrow m) => Path Abs Dir -> FilePath.FilePath -> m (Path Abs File)
814+
resolveFile' x y = do
815+
p <- parseCollapsedAbsFile (toFilePath x FilePath.</> y)
816+
exists <- fileExists p
817+
if exists
818+
then return p
819+
else throwM $ ResolveFileFailed x y (toFilePath p)
813820

814821
-- | Warn the user that multiple candidates are available for an
815822
-- entry, but that we picked one anyway and continued.

test/integration/lib/StackTest.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,8 @@ doesFileOrDirExist fp = do
6666
if isDir
6767
then return (Right ("Directory exists: " ++ fp))
6868
else return (Left ())
69+
70+
copy :: FilePath -> FilePath -> IO ()
71+
copy src dest = do
72+
putStrLn ("Copy " ++ show src ++ " to " ++ show dest)
73+
System.Directory.copyFile src dest
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import Control.Concurrent
2+
import StackTest
3+
4+
main :: IO ()
5+
main = do
6+
copy "src/Unlisted_OK.hs" "src/Unlisted.hs"
7+
copy "embed_OK.txt" "embed.txt"
8+
stack ["build"]
9+
pause
10+
copy "src/Unlisted_FAIL.hs" "src/Unlisted.hs"
11+
stackErr ["build"]
12+
pause
13+
copy "src/Unlisted_OK.hs" "src/Unlisted.hs"
14+
stack ["build"]
15+
stack ["exec", "files-exe"]
16+
pause
17+
copy "embed_FAIL.txt" "embed.txt"
18+
stack ["build"]
19+
stackErr ["exec", "files-exe"]
20+
pause
21+
copy "embed_OK.txt" "embed.txt"
22+
stack ["build"]
23+
stack ["exec", "files-exe"]
24+
25+
pause = threadDelay 1000000
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FAIL
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
OK
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: files
2+
version: 0.1.0.0
3+
synopsis: Initial project template from stack
4+
description: Please see README.md
5+
homepage: http://github.com/githubuser/files#readme
6+
license: BSD3
7+
build-type: Simple
8+
-- extra-source-files:
9+
cabal-version: >=1.10
10+
11+
executable files-exe
12+
hs-source-dirs: src/../src
13+
main-is: Main.hs
14+
build-depends: base >= 4.7 && < 5
15+
, file-embed
16+
default-language: Haskell2010
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{-# LANGUAGE TemplateHaskell #-}
2+
{-# LANGUAGE OverloadedStrings #-}
3+
module Main where
4+
5+
import Data.FileEmbed
6+
import Unlisted
7+
8+
main :: IO ()
9+
main = do
10+
putStrLn ("main " ++ show foo ++ " " ++ show embedded)
11+
if embedded == "FAIL\n"
12+
then error "embedded contains FAIL"
13+
else return ()
14+
15+
embedded = $(embedFile "embed.txt")
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- | Version of Unlisted with different export that causes failure to compile.
2+
module Unlisted where
3+
4+
fooRenamed :: String
5+
fooRenamed = "foo"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Unlisted where
2+
3+
foo :: String
4+
foo = "foo"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module Main where
2+
3+
main = do putStrLn "Hello, world."
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
flags: {}
2+
packages:
3+
- '.'
4+
extra-deps: []
5+
resolver: lts-3.0

0 commit comments

Comments
 (0)