Skip to content

Commit 410e1e2

Browse files
committed
Merge branch 'master' into buffering
2 parents e9d0a01 + 54e719a commit 410e1e2

File tree

55 files changed

+1474
-1058
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1474
-1058
lines changed

.travis.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ script:
4141

4242
- cabal copy
4343
- cd test/integration
44-
- stack setup
45-
- stack test
44+
# Takes too long for now
45+
# - stack setup
46+
# - stack test
4647
- cd ../..
4748

4849
# Check that the resulting source distribution can be built & installed.

ChangeLog.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1-
## Unreleased
1+
## 0.1.0.0
22

33
* Fall back to cabal dependency solver when a snapshot can't be found
44
* Basic implementation of `stack new` [#137](https://github.com/commercialhaskell/stack/issues/137)
5+
* `stack solver` command [#364](https://github.com/commercialhaskell/stack/issues/364)
6+
* `stack path` command [#95](https://github.com/commercialhaskell/stack/issues/95)
7+
* Haddocks [#143](https://github.com/commercialhaskell/stack/issues/143):
8+
* Build for dependencies
9+
* Use relative links
10+
* Generate module contents and index for all packages in project
511

612
## 0.0.3
713

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ A full description of the architecture
5656
please see
5757
[the FAQ](https://github.com/commercialhaskell/stack/wiki/FAQ).
5858
* For general questions, comments, feedback and support please write
59-
to
60-
[the Commercial Haskell mailing list](https://groups.google.com/d/forum/commercialhaskell).
59+
to [the stack mailing list](https://groups.google.com/d/forum/haskell-stack).
6160
* For bugs, issues, or requests please
6261
[open an issue](https://github.com/commercialhaskell/stack/issues/new).
6362

src/Data/Aeson/Extended.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ import Data.Text (unpack, Text)
1515
import Data.Monoid ((<>))
1616

1717
(.:) :: FromJSON a => Object -> Text -> Parser a
18-
(.:) o p = modifyFailure (("failed to parse field " <> unpack p <> ": ") <>) (o A..: p)
18+
(.:) o p = modifyFailure (("failed to parse field '" <> unpack p <> "': ") <>) (o A..: p)
1919
{-# INLINE (.:) #-}
2020

2121
(.:?) :: FromJSON a => Object -> Text -> Parser (Maybe a)
22-
(.:?) o p = modifyFailure (("failed to parse field " <> unpack p <> ": ") <>) (o A..:? p)
22+
(.:?) o p = modifyFailure (("failed to parse field '" <> unpack p <> "': ") <>) (o A..:? p)
2323
{-# INLINE (.:?) #-}

src/Data/Attoparsec/Args.hs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
-- | Parsing argument-like things.
2+
3+
module Data.Attoparsec.Args (EscapingMode(..), argsParser) where
4+
5+
import Control.Applicative
6+
import Data.Attoparsec.Text ((<?>))
7+
import qualified Data.Attoparsec.Text as P
8+
import Data.Attoparsec.Types (Parser)
9+
import Data.Text (Text)
10+
11+
-- | Mode for parsing escape characters.
12+
data EscapingMode
13+
= Escaping
14+
| NoEscaping
15+
deriving (Show,Eq,Enum)
16+
17+
-- | A basic argument parser. It supports space-separated text, and
18+
-- string quotation with identity escaping: \x -> x.
19+
argsParser :: EscapingMode -> Parser Text [String]
20+
argsParser mode = many (P.skipSpace *> (quoted <|> unquoted)) <*
21+
P.skipSpace <* (P.endOfInput <?> "unterminated string")
22+
where
23+
unquoted = P.many1 naked
24+
quoted = P.char '"' *> string <* P.char '"'
25+
string = many (case mode of
26+
Escaping -> escaped <|> nonquote
27+
NoEscaping -> nonquote)
28+
escaped = P.char '\\' *> P.anyChar
29+
nonquote = P.satisfy (not . (=='"'))
30+
naked = P.satisfy (not . flip elem ("\" " :: String))

src/Data/Binary/VersionTagged.hs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,48 @@
11
{-# LANGUAGE OverloadedStrings #-}
2+
{-# LANGUAGE ScopedTypeVariables #-}
23
-- | Tag a Binary instance with the stack version number to ensure we're
34
-- reading a compatible format.
45
module Data.Binary.VersionTagged
56
( taggedDecodeOrLoad
67
, taggedEncodeFile
8+
, BinarySchema (..)
79
) where
810

911
import Control.Monad.IO.Class (MonadIO, liftIO)
1012
import Data.Binary (Binary (..), encodeFile, decodeFileOrFail, putWord8, getWord8)
1113
import Control.Exception.Enclosed (tryIO)
12-
import qualified Paths_stack
13-
import Stack.Types.Version (Version, fromCabalVersion)
1414
import System.FilePath (takeDirectory)
1515
import System.Directory (createDirectoryIfMissing)
1616
import qualified Data.ByteString as S
1717
import Data.ByteString (ByteString)
1818
import Control.Monad (forM_, when)
19-
20-
tag :: Version
21-
tag = fromCabalVersion Paths_stack.version
19+
import Data.Proxy
2220

2321
magic :: ByteString
24-
magic = "STACK"
22+
magic = "stack"
23+
24+
-- | A @Binary@ instance that also has a schema version
25+
class Binary a => BinarySchema a where
26+
binarySchema :: Proxy a -> Int
2527

2628
newtype WithTag a = WithTag a
27-
instance Binary a => Binary (WithTag a) where
29+
instance forall a. BinarySchema a => Binary (WithTag a) where
2830
get = do
2931
forM_ (S.unpack magic) $ \w -> do
3032
w' <- getWord8
3133
when (w /= w')
3234
$ fail "Mismatched magic string, forcing a recompute"
3335
tag' <- get
34-
if tag == tag'
36+
if binarySchema (Proxy :: Proxy a) == tag'
3537
then fmap WithTag get
3638
else fail "Mismatched tags, forcing a recompute"
3739
put (WithTag x) = do
3840
mapM_ putWord8 $ S.unpack magic
39-
put tag
41+
put (binarySchema (Proxy :: Proxy a))
4042
put x
4143

4244
-- | Write to the given file, with a version tag.
43-
taggedEncodeFile :: (Binary a, MonadIO m)
45+
taggedEncodeFile :: (BinarySchema a, MonadIO m)
4446
=> FilePath
4547
-> a
4648
-> m ()
@@ -51,7 +53,7 @@ taggedEncodeFile fp x = liftIO $ do
5153
-- | Read from the given file. If the read fails, run the given action and
5254
-- write that back to the file. Always starts the file off with the version
5355
-- tag.
54-
taggedDecodeOrLoad :: (Binary a, MonadIO m)
56+
taggedDecodeOrLoad :: (BinarySchema a, MonadIO m)
5557
=> FilePath
5658
-> m a
5759
-> m a

src/Network/HTTP/Download/Verified.hs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -72,29 +72,35 @@ type LengthCheck = Int
7272
-- | An exception regarding verification of a download.
7373
data VerifiedDownloadException
7474
= WrongContentLength
75+
Request
7576
Int -- expected
7677
ByteString -- actual (as listed in the header)
7778
| WrongStreamLength
79+
Request
7880
Int -- expected
7981
Int -- actual
8082
| WrongDigest
83+
Request
8184
String -- algorithm
8285
CheckHexDigest -- expected
8386
String -- actual (shown)
8487
deriving (Typeable)
8588
instance Show VerifiedDownloadException where
86-
show (WrongContentLength expected actual) =
89+
show (WrongContentLength req expected actual) =
8790
"Download expectation failure: ContentLength header\n"
8891
++ "Expected: " ++ show expected ++ "\n"
89-
++ "Actual: " ++ displayByteString actual
90-
show (WrongStreamLength expected actual) =
92+
++ "Actual: " ++ displayByteString actual ++ "\n"
93+
++ "For: " ++ show (getUri req)
94+
show (WrongStreamLength req expected actual) =
9195
"Download expectation failure: download size\n"
9296
++ "Expected: " ++ show expected ++ "\n"
93-
++ "Actual: " ++ show actual
94-
show (WrongDigest algo expected actual) =
97+
++ "Actual: " ++ show actual ++ "\n"
98+
++ "For: " ++ show (getUri req)
99+
show (WrongDigest req algo expected actual) =
95100
"Download expectation failure: content hash (" ++ algo ++ ")\n"
96101
++ "Expected: " ++ displayCheckHexDigest expected ++ "\n"
97-
++ "Actual: " ++ actual
102+
++ "Actual: " ++ actual ++ "\n"
103+
++ "For: " ++ show (getUri req)
98104

99105
instance Exception VerifiedDownloadException
100106

@@ -125,9 +131,10 @@ displayCheckHexDigest (CheckHexDigestHeader h) =
125131
--
126132
-- Throws WrongDigest (VerifiedDownloadException)
127133
sinkCheckHash :: MonadThrow m
128-
=> HashCheck
134+
=> Request
135+
-> HashCheck
129136
-> Consumer ByteString m ()
130-
sinkCheckHash HashCheck{..} = do
137+
sinkCheckHash req HashCheck{..} = do
131138
digest <- sinkHashUsing hashCheckAlgorithm
132139
let actualDigestString = show digest
133140
let actualDigestHexByteString = digestToHexByteString digest
@@ -142,23 +149,24 @@ sinkCheckHash HashCheck{..} = do
142149
|| b == actualDigestHexByteString
143150

144151
when (not passedCheck) $
145-
throwM $ WrongDigest (show hashCheckAlgorithm) hashCheckHexDigest actualDigestString
152+
throwM $ WrongDigest req (show hashCheckAlgorithm) hashCheckHexDigest actualDigestString
146153

147154
assertLengthSink :: MonadThrow m
148-
=> LengthCheck
155+
=> Request
156+
-> LengthCheck
149157
-> ZipSink ByteString m ()
150-
assertLengthSink expectedStreamLength = ZipSink $ do
158+
assertLengthSink req expectedStreamLength = ZipSink $ do
151159
Sum actualStreamLength <- CL.foldMap (Sum . ByteString.length)
152160
when (actualStreamLength /= expectedStreamLength) $
153-
throwM $ WrongStreamLength expectedStreamLength actualStreamLength
161+
throwM $ WrongStreamLength req expectedStreamLength actualStreamLength
154162

155163
-- | A more explicitly type-guided sinkHash.
156164
sinkHashUsing :: (Monad m, HashAlgorithm a) => a -> Consumer ByteString m (Digest a)
157165
sinkHashUsing _ = sinkHash
158166

159167
-- | Turns a list of hash checks into a ZipSink that checks all of them.
160-
hashChecksToZipSink :: MonadThrow m => [HashCheck] -> ZipSink ByteString m ()
161-
hashChecksToZipSink = traverse_ (ZipSink . sinkCheckHash)
168+
hashChecksToZipSink :: MonadThrow m => Request -> [HashCheck] -> ZipSink ByteString m ()
169+
hashChecksToZipSink req = traverse_ (ZipSink . sinkCheckHash req)
162170

163171
-- | Copied and extended version of Network.HTTP.Download.download.
164172
--
@@ -215,7 +223,7 @@ verifiedDownload DownloadRequest{..} destpath progressSink = do
215223

216224
checkExpectations = bracket (openFile fp ReadMode) hClose $ \h -> do
217225
whenJust drLengthCheck $ checkFileSizeExpectations h
218-
sourceHandle h $$ getZipSink (hashChecksToZipSink drHashChecks)
226+
sourceHandle h $$ getZipSink (hashChecksToZipSink drRequest drHashChecks)
219227

220228
-- doesn't move the handle
221229
checkFileSizeExpectations h expectedFileSize = do
@@ -231,7 +239,7 @@ verifiedDownload DownloadRequest{..} destpath progressSink = do
231239
Just lengthBS -> do
232240
let lengthStr = displayByteString lengthBS
233241
when (lengthStr /= show expectedContentLength) $
234-
throwM $ WrongContentLength expectedContentLength lengthBS
242+
throwM $ WrongContentLength drRequest expectedContentLength lengthBS
235243
_ -> return ()
236244

237245
go h res = do
@@ -250,7 +258,7 @@ verifiedDownload DownloadRequest{..} destpath progressSink = do
250258
responseBody res
251259
$= maybe (awaitForever yield) CB.isolate drLengthCheck
252260
$$ getZipSink
253-
( hashChecksToZipSink hashChecks
254-
*> maybe (pure ()) assertLengthSink drLengthCheck
261+
( hashChecksToZipSink drRequest hashChecks
262+
*> maybe (pure ()) (assertLengthSink drRequest) drLengthCheck
255263
*> ZipSink (sinkHandle h)
256264
*> ZipSink progressSink)

src/Options/Applicative/Args.hs

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,11 @@
55
module Options.Applicative.Args
66
(argsArgument
77
,argsOption
8-
,parseArgsFromString
9-
,argsParser)
8+
,parseArgsFromString)
109
where
1110

12-
import Control.Applicative
13-
import Data.Attoparsec.Text ((<?>))
11+
import Data.Attoparsec.Args
1412
import qualified Data.Attoparsec.Text as P
15-
import Data.Attoparsec.Types (Parser)
16-
import Data.Text (Text)
1713
import qualified Data.Text as T
1814
import qualified Options.Applicative as O
1915

@@ -33,17 +29,4 @@ argsOption =
3329

3430
-- | Parse from a string.
3531
parseArgsFromString :: String -> Either String [String]
36-
parseArgsFromString = P.parseOnly argsParser . T.pack
37-
38-
-- | A basic argument parser. It supports space-separated text, and
39-
-- string quotation with identity escaping: \x -> x.
40-
argsParser :: Parser Text [String]
41-
argsParser = many (P.skipSpace *> (quoted <|> unquoted)) <*
42-
P.skipSpace <* (P.endOfInput <?> "unterminated string")
43-
where
44-
unquoted = P.many1 naked
45-
quoted = P.char '"' *> string <* P.char '"'
46-
string = many (escaped <|> nonquote)
47-
escaped = P.char '\\' *> P.anyChar
48-
nonquote = P.satisfy (not . (=='"'))
49-
naked = P.satisfy (not . flip elem ("\" " :: String))
32+
parseArgsFromString = P.parseOnly (argsParser Escaping) . T.pack

src/Options/Applicative/Builder/Extra.hs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
module Options.Applicative.Builder.Extra
44
(boolFlags
5+
,boolFlagsNoDefault
56
,maybeBoolFlags
67
,enableDisableFlags
8+
,enableDisableFlagsNoDefault
79
,extraHelpOption
810
,execExtraHelp)
911
where
@@ -17,13 +19,23 @@ import System.FilePath (takeBaseName)
1719
boolFlags :: Bool -> String -> String -> Mod FlagFields Bool -> Parser Bool
1820
boolFlags defaultValue = enableDisableFlags defaultValue True False
1921

22+
-- | Enable/disable flags for a @Bool@, without a default case (to allow chaining @<|>@s).
23+
boolFlagsNoDefault :: String -> String -> Mod FlagFields Bool -> Parser Bool
24+
boolFlagsNoDefault = enableDisableFlagsNoDefault True False
25+
2026
-- | Enable/disable flags for a @(Maybe Bool)@.
2127
maybeBoolFlags :: String -> String -> Mod FlagFields (Maybe Bool) -> Parser (Maybe Bool)
2228
maybeBoolFlags = enableDisableFlags Nothing (Just True) (Just False)
2329

2430
-- | Enable/disable flags for any type.
2531
enableDisableFlags :: a -> a -> a -> String -> String -> Mod FlagFields a -> Parser a
2632
enableDisableFlags defaultValue enabledValue disabledValue name helpSuffix mods =
33+
enableDisableFlagsNoDefault enabledValue disabledValue name helpSuffix mods <|>
34+
pure defaultValue
35+
36+
-- | Enable/disable flags for any type, without a default (to allow chaining @<|>@s)
37+
enableDisableFlagsNoDefault :: a -> a -> String -> String -> Mod FlagFields a -> Parser a
38+
enableDisableFlagsNoDefault enabledValue disabledValue name helpSuffix mods =
2739
flag' enabledValue
2840
(long name <>
2941
help ("Enable " ++ helpSuffix) <>
@@ -41,8 +53,7 @@ enableDisableFlags defaultValue enabledValue disabledValue name helpSuffix mods
4153
(internal <>
4254
long ("disable-" ++ name) <>
4355
help ("Disable " ++ helpSuffix) <>
44-
mods) <|>
45-
pure defaultValue
56+
mods)
4657

4758
-- | Show an extra help option (e.g. @--docker-help@ shows help for all @--docker*@ args).
4859
-- To actually show have that help appear, use 'execExtraHelp' before executing the main parser.

src/Path/IO.hs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ module Path.IO
1414
,removeTree
1515
,removeTreeIfExists
1616
,fileExists
17-
,dirExists)
17+
,dirExists
18+
,copyDirectoryRecursive)
1819
where
1920

2021
import Control.Exception hiding (catch)
@@ -150,3 +151,24 @@ fileExists =
150151
dirExists :: MonadIO m => Path b Dir -> m Bool
151152
dirExists =
152153
liftIO . doesFileExist . toFilePath
154+
155+
-- | Copy a directory recursively. This just uses 'copyFile', so it is not smart about symbolic
156+
-- links or other special files.
157+
copyDirectoryRecursive :: (MonadIO m,MonadThrow m)
158+
=> Path Abs Dir -- ^ Source directory
159+
-> Path Abs Dir -- ^ Destination directory
160+
-> m ()
161+
copyDirectoryRecursive srcDir destDir =
162+
do liftIO (createDirectoryIfMissing False (toFilePath destDir))
163+
(srcSubDirs,srcFiles) <- listDirectory srcDir
164+
forM_ srcFiles
165+
(\srcFile ->
166+
case stripDir srcDir srcFile of
167+
Nothing -> return ()
168+
Just relFile -> liftIO (copyFile (toFilePath srcFile)
169+
(toFilePath (destDir </> relFile))))
170+
forM_ srcSubDirs
171+
(\srcSubDir ->
172+
case stripDir srcDir srcSubDir of
173+
Nothing -> return ()
174+
Just relSubDir -> copyDirectoryRecursive srcSubDir (destDir </> relSubDir))

0 commit comments

Comments
 (0)