Skip to content

Commit

Permalink
Add errors for future and missing index-states
Browse files Browse the repository at this point in the history
  • Loading branch information
jasagredo committed Oct 31, 2023
1 parent b81c44e commit 5b79d77
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 31 deletions.
2 changes: 1 addition & 1 deletion cabal-install/src/Distribution/Client/CmdUpdate.hs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ updateRepo verbosity _updateFlags repoCtxt (repo, indexState) = do
RepoSecure{} -> repoContextWithSecureRepo repoCtxt repo $ \repoSecure -> do
let index = RepoIndex repoCtxt repo
-- NB: This may be a NoTimestamp if we've never updated before
current_ts <- currentIndexTimestamp (lessVerbose verbosity) repoCtxt repo
current_ts <- currentIndexTimestamp (lessVerbose verbosity) index
-- NB: always update the timestamp, even if we didn't actually
-- download anything
writeIndexTimestamp index indexState
Expand Down
21 changes: 21 additions & 0 deletions cabal-install/src/Distribution/Client/Errors.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import Data.ByteString (ByteString)
import qualified Data.ByteString.Base16 as Base16
import qualified Data.ByteString.Char8 as BS8
import Data.List (groupBy)
import Distribution.Client.IndexUtils.Timestamp
import Distribution.Client.Types.Repo
import Distribution.Client.Types.RepoName (RepoName (..))
import Distribution.Compat.Prelude
import Distribution.Deprecated.ParseUtils (PWarning, showPWarning)
import Distribution.Package
Expand Down Expand Up @@ -179,6 +182,8 @@ data CabalInstallException
| FreezeException String
| PkgSpecifierException [String]
| CorruptedIndexCache String
| UnusableIndexState RemoteRepo Timestamp Timestamp
| MissingPackageList RemoteRepo
deriving (Show, Typeable)

exceptionCodeCabalInstall :: CabalInstallException -> Int
Expand Down Expand Up @@ -327,6 +332,8 @@ exceptionCodeCabalInstall e = case e of
FreezeException{} -> 7156
PkgSpecifierException{} -> 7157
CorruptedIndexCache{} -> 7158
UnusableIndexState{} -> 7159
MissingPackageList{} -> 7160

exceptionMessageCabalInstall :: CabalInstallException -> String
exceptionMessageCabalInstall e = case e of
Expand Down Expand Up @@ -828,6 +835,20 @@ exceptionMessageCabalInstall e = case e of
FreezeException errs -> errs
PkgSpecifierException errorStr -> unlines errorStr
CorruptedIndexCache str -> str
UnusableIndexState repoRemote maxFound requested ->
"Latest known index-state for '"
++ unRepoName (remoteRepoName repoRemote)
++ "' ("
++ prettyShow maxFound
++ ") is older than the requested index-state ("
++ prettyShow requested
++ ").\nRun 'cabal update' or set the index-state to a value at or before "
++ prettyShow maxFound
++ "."
MissingPackageList repoRemote ->
"The package list for '"
++ unRepoName (remoteRepoName repoRemote)
++ "' does not exist. Run 'cabal update' to download it."

instance Exception (VerboseException CabalInstallException) where
displayException :: VerboseException CabalInstallException -> [Char]
Expand Down
56 changes: 26 additions & 30 deletions cabal-install/src/Distribution/Client/IndexUtils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -318,21 +318,31 @@ getSourcePackagesAtIndexState verbosity repoCtxt mb_idxState mb_activeRepos = do
IndexStateHead -> do
info verbosity ("index-state(" ++ unRepoName rname ++ ") = " ++ prettyShow (isiHeadTime isi))
return ()
IndexStateTime ts0 -> do
IndexStateTime ts0 ->
-- isiMaxTime is the latest timestamp in the filtered view returned by
-- `readRepoIndex` above. It is always true that isiMaxTime is less or
-- equal to a requested IndexStateTime. When `isiMaxTime isi /= ts0` (or
-- equivalently `isiMaxTime isi < ts0`) it means that ts0 falls between
-- two timestamps in the index.
when (isiMaxTime isi /= ts0) $
info verbosity $
"There is no index-state for '"
++ unRepoName rname
++ "' exactly at the requested timestamp ("
++ prettyShow ts0
++ "). Falling back to the previous index-state that exists: "
++ prettyShow (isiMaxTime isi)

let commonMsg =
"There is no index-state for '"
++ unRepoName rname
++ "' exactly at the requested timestamp ("
++ prettyShow ts0
++ "). "
in if isNothing $ timestampToUTCTime (isiMaxTime isi)
then
warn verbosity $
commonMsg
++ "Also, there are no index-states before the one requested, so the repository '"
++ unRepoName rname
++ "' will be empty."
else
info verbosity $
commonMsg
++ "Falling back to the previous index-state that exists: "
++ prettyShow (isiMaxTime isi)
pure
RepoData
{ rdRepoName = rname
Expand Down Expand Up @@ -450,8 +460,8 @@ readRepoIndex verbosity repoCtxt repo idxState =
if isDoesNotExistError e
then do
case repo of
RepoRemote{..} -> die' verbosity $ errMissingPackageList repoRemote
RepoSecure{..} -> die' verbosity $ errMissingPackageList repoRemote
RepoRemote{..} -> dieWithException verbosity $ MissingPackageList repoRemote
RepoSecure{..} -> dieWithException verbosity $ MissingPackageList repoRemote
RepoLocalNoIndex local _ ->
warn verbosity $
"Error during construction of local+noindex "
Expand All @@ -465,40 +475,26 @@ readRepoIndex verbosity repoCtxt repo idxState =
isOldThreshold = 15 -- days
warnIfIndexIsOld dt = do
when (dt >= isOldThreshold) $ case repo of
RepoRemote{..} -> warn verbosity $ errOutdatedPackageList repoRemote dt
RepoSecure{..} -> warn verbosity $ errOutdatedPackageList repoRemote dt
RepoRemote{..} -> warn verbosity $ warnOutdatedPackageList repoRemote dt
RepoSecure{..} -> warn verbosity $ warnOutdatedPackageList repoRemote dt
RepoLocalNoIndex{} -> return ()

dieIfRequestedIdxIsNewer isi =
let latestTime = isiHeadTime isi
in case idxState of
IndexStateTime t -> when (t > latestTime) $ case repo of
RepoSecure{..} ->
die' verbosity $ errRequestedIdxIsNewer repoRemote latestTime t
dieWithException verbosity $ UnusableIndexState repoRemote latestTime t
RepoRemote{} -> pure ()
RepoLocalNoIndex{} -> return ()
IndexStateHead -> pure ()

errMissingPackageList repoRemote =
"The package list for '"
++ unRepoName (remoteRepoName repoRemote)
++ "' does not exist. Run 'cabal update' to download it."
errOutdatedPackageList repoRemote dt =
warnOutdatedPackageList repoRemote dt =
"The package list for '"
++ unRepoName (remoteRepoName repoRemote)
++ "' is "
++ shows (floor dt :: Int) " days old.\nRun "
++ "'cabal update' to get the latest list of available packages."
errRequestedIdxIsNewer repoRemote maxFound req =
"Latest known index-state for '"
++ unRepoName (remoteRepoName repoRemote)
++ "' ("
++ prettyShow maxFound
++ ") is older than the requested index-state ("
++ prettyShow req
++ ").\nRun 'cabal update' or set the index-state to a value at or before "
++ prettyShow maxFound
++ "."

-- | Return the age of the index file in days (as a Double).
getIndexFileAge :: Repo -> IO Double
Expand Down Expand Up @@ -1126,7 +1122,7 @@ readIndexCache verbosity index = do
--
-- If a corrupted index cache is detected this function regenerates
-- the index cache and then reattempts to read the index once (and
-- 'die's if it fails again). Throws IOException if any arise.
-- 'dieWithException's if it fails again). Throws IOException if any arise.
readNoIndexCache :: Verbosity -> Index -> IO NoIndexCache
readNoIndexCache verbosity index = do
cacheOrFail <- readNoIndexCache' index
Expand Down

0 comments on commit 5b79d77

Please sign in to comment.