@@ -20,14 +20,13 @@ import Amazonka.Auth (fromKeys)
2020import Amazonka.S3.PutObject
2121import Amazonka.S3 (BucketName (.. ), ObjectKey (.. ), ObjectCannedACL (.. ))
2222import Network.HTTP.Client (parseUrlThrow )
23- import Network.HTTP.Simple
24- (Request , parseRequest , addRequestHeader , getResponseStatus ,
25- getResponseStatusCode , getResponseHeader , getResponseBody , httpLBS )
23+ import Network.HTTP.Simple (getResponseBody , httpLBS )
2624import Options.Applicative
2725import System.Environment (getEnv , lookupEnv )
2826import System.IO (hPutStrLn )
2927
3028import Stackage.Package.Update
29+ import Stackage.Package.Hackage
3130import Stackage.Package.Locations
3231import Stackage.Package.Git
3332import Stackage.Package.IndexConduit
@@ -108,38 +107,25 @@ updateIndex00 awsMech bucketName = do
108107 Left e -> error $ show (key, e :: Error )
109108 Right _ -> putStrLn " Success"
110109
110+ -- | Refresh the local index and, if it moved (or a refresh is being forced),
111+ -- regenerate the repositories from it.
111112processIndexUpdate
112113 :: MonadIO m
113- => Repositories
114- -> Request -- ^ Request that should be processed
115- -> Maybe ByteString -- ^ Previous Etag, so we can check if the content has changed.
116- -> m (Bool , Maybe ByteString )
117- processIndexUpdate repos indexReq mLastEtag = liftIO $ do
118- let indexReqWithEtag =
119- maybe id (addRequestHeader " if-none-match" ) mLastEtag indexReq
120- mValidVersionsWithEtag <-
121- httpTarballSink
122- indexReqWithEtag
123- True
124- (\ res ->
125- case getResponseStatusCode res of
126- 200 -> do
127- validVersions <- allHashesUpdate repos
128- return $
129- Just (validVersions, listToMaybe $ getResponseHeader " etag" res)
130- 304 -> return Nothing
131- _ -> error $ " Unexpected status: " ++ show (getResponseStatus res))
132- case mValidVersionsWithEtag of
133- Nothing -> return (False , mLastEtag)
134- Just (validVersions, mNewEtag) ->
135- httpTarballSink
136- indexReqWithEtag
137- True
138- (\ res ->
139- case getResponseStatusCode res of
140- 200 -> (True , mNewEtag) <$ allCabalUpdate repos validVersions
141- 304 -> return (False , mLastEtag)
142- _ -> error $ " Unexpected status: " ++ show (getResponseStatus res))
114+ => Hackage
115+ -> Repositories
116+ -> UTCTime -- ^ Time to judge index metadata expiry against
117+ -> Bool -- ^ Regenerate even when the index is unchanged.
118+ -> m Bool
119+ processIndexUpdate hackage repos now forceUpdate = liftIO $ do
120+ (hasUpdates, indexPath) <- refreshIndex hackage now
121+ case hasUpdates of
122+ NoUpdates
123+ | not forceUpdate -> return False
124+ _ -> do
125+ validVersions <-
126+ localTarballSink indexPath False (allHashesUpdate hackage repos)
127+ localTarballSink indexPath False (allCabalUpdate hackage repos validVersions)
128+ return True
143129
144130
145131
@@ -152,6 +138,7 @@ data Options = Options
152138 , oLocalPath :: Maybe FilePath -- default $HOME
153139 , oGithubAccount :: String -- default "commercialhaskell"
154140 , oDelay :: Maybe Int -- default 60 seconds
141+ , oOneShot :: Bool
155142 , oS3Bucket :: Maybe BucketName
156143 , oAwsDiscoveryMech :: AwsDiscoverMechanism
157144 }
@@ -200,6 +187,10 @@ optionsParser =
200187 help
201188 (" Delay in seconds before next check for a new version " ++
202189 " of 01-index.tar.gz file" )))) <*>
190+ (switch
191+ (long " one-shot" <>
192+ help
193+ (" Update once and exit, instead of polling forever. " ))) <*>
203194 (optional
204195 ((BucketName . pack) <$>
205196 (strOption
@@ -233,29 +224,36 @@ main = do
233224 when (isNothing ms3Bucket) $
234225 putStrLn
235226 " WARNING: No s3-bucket is provided. Uploading of 00-index.tar.gz will be disabled."
236- indexReq <- parseRequest $ mirrorFPComplete ++ " /01-index.tar.gz"
237227 reposInfoInit <- getReposInfo localPath oGithubAccount gitUser
238- let innerLoop reposInfo mlastEtag = do
239- putStrLn $ " Checking index, etag == " ++ tshow mlastEtag
240- commitMessage <- getCommitMessage
241- (newInfo, mnewEtag) <- withRepositories reposInfo $ \ repos -> do
242- (updated, mnewEtag) <- processIndexUpdate repos indexReq mlastEtag
243- when updated $
244- do pushRepos repos commitMessage
245- case ms3Bucket of
246- Just s3Bucket ->
247- updateIndex00 oAwsDiscoveryMech s3Bucket
248- _ -> return ()
249- return mnewEtag
250- threadDelay delay
251- innerLoop newInfo mnewEtag
252- let outerLoop = do
253- catchAny
254- (innerLoop reposInfoInit Nothing )
255- (\ e -> do
256- hPutStrLn stderr $
257- " ERROR: Received an unexpected exception while updating repositories: " ++
258- show e
259- threadDelay delay
260- outerLoop)
261- outerLoop
228+ withHackage (localPath </> " hackage-security-cache" ) $ \ hackage -> do
229+ let onePass reposInfo forceUpdate = do
230+ putStrLn " Checking index"
231+ now <- getCurrentTime
232+ commitMessage <- getCommitMessage
233+ (newInfo, () ) <- withRepositories reposInfo $ \ repos -> do
234+ updated <- processIndexUpdate hackage repos now forceUpdate
235+ when updated $
236+ do pushRepos repos commitMessage
237+ case ms3Bucket of
238+ Just s3Bucket ->
239+ updateIndex00 oAwsDiscoveryMech s3Bucket
240+ _ -> return ()
241+ return newInfo
242+ let innerLoop reposInfo forceUpdate = do
243+ newInfo <- onePass reposInfo forceUpdate
244+ threadDelay delay
245+ innerLoop newInfo False
246+ let outerLoop = do
247+ catchAny
248+ -- A fresh process has no idea how far behind the repositories are,
249+ -- so the first pass runs whether or not the index moved.
250+ (innerLoop reposInfoInit True )
251+ (\ e -> do
252+ hPutStrLn stderr $
253+ " ERROR: Received an unexpected exception while updating repositories: " ++
254+ show e
255+ threadDelay delay
256+ outerLoop)
257+ if oOneShot
258+ then void $ onePass reposInfoInit False
259+ else outerLoop
0 commit comments