mirror of
https://github.com/commercialhaskell/stackage.git
synced 2026-01-28 23:20:26 +01:00
Remove unneeded upload code
This commit is contained in:
parent
48f5629dd8
commit
58cd68ff7e
@ -1,198 +0,0 @@
|
|||||||
{-# LANGUAGE PatternGuards #-}
|
|
||||||
-- | Review the upload log and compare against a locally kept list of allowed
|
|
||||||
-- uploaders.
|
|
||||||
module Stackage.Uploads
|
|
||||||
( checkUploads
|
|
||||||
, printForbidden
|
|
||||||
, filterForbidden
|
|
||||||
) where
|
|
||||||
|
|
||||||
import Control.Arrow (second)
|
|
||||||
import Control.Exception (assert, evaluate)
|
|
||||||
import Control.Monad (forM_, unless)
|
|
||||||
import Data.Map (Map)
|
|
||||||
import qualified Data.Map as Map
|
|
||||||
import Data.Maybe (fromMaybe)
|
|
||||||
import Data.Monoid (Monoid (..))
|
|
||||||
import Data.Set (Set)
|
|
||||||
import qualified Data.Set as Set
|
|
||||||
import Data.Time (UTCTime, parseTime)
|
|
||||||
import Distribution.Text (display)
|
|
||||||
import Network.HTTP (getRequest, getResponseBody, simpleHTTP)
|
|
||||||
import qualified Stackage.Types as ST
|
|
||||||
import System.Directory (doesFileExist)
|
|
||||||
import System.Exit (exitFailure)
|
|
||||||
import System.Locale
|
|
||||||
|
|
||||||
checkUploads :: FilePath -- ^ allowed
|
|
||||||
-> FilePath -- ^ new allowed
|
|
||||||
-> IO Forbidden
|
|
||||||
checkUploads allowedFP newAllowedFP = do
|
|
||||||
putStrLn "Getting upload log"
|
|
||||||
uploadLog <- getUploadLog
|
|
||||||
|
|
||||||
putStrLn "Reading allowed uploaders list"
|
|
||||||
allowed <- readAllowed allowedFP
|
|
||||||
|
|
||||||
putStrLn "Computing new and forbidden uploaders"
|
|
||||||
let (allowed', forbidden) = updateAllowed uploadLog allowed
|
|
||||||
_ <- evaluate $ msize allowed'
|
|
||||||
_ <- evaluate $ msize forbidden
|
|
||||||
|
|
||||||
unless (Map.null $ unMonoidMap allowed') $ do
|
|
||||||
putStrLn $ "Newly uploaded packages detected, writing to " ++ newAllowedFP
|
|
||||||
writeAllowed newAllowedFP allowed'
|
|
||||||
|
|
||||||
return forbidden
|
|
||||||
|
|
||||||
-- Define a Map newtype wrapper with a proper Monoid instance.
|
|
||||||
newtype MonoidMap k v = MonoidMap { unMonoidMap :: Map k v }
|
|
||||||
instance (Ord k, Monoid v) => Monoid (MonoidMap k v) where
|
|
||||||
mempty = MonoidMap mempty
|
|
||||||
MonoidMap x `mappend` MonoidMap y = MonoidMap $ Map.unionWith mappend x y
|
|
||||||
|
|
||||||
-- And some helper functions.
|
|
||||||
mlookup :: Ord k => k -> MonoidMap k v -> Maybe v
|
|
||||||
mlookup k = Map.lookup k . unMonoidMap
|
|
||||||
|
|
||||||
msingleton :: k -> v -> MonoidMap k v
|
|
||||||
msingleton k = MonoidMap . Map.singleton k
|
|
||||||
|
|
||||||
mkeys :: MonoidMap k v -> [k]
|
|
||||||
mkeys = Map.keys . unMonoidMap
|
|
||||||
|
|
||||||
msize :: MonoidMap k v -> Int
|
|
||||||
msize = Map.size . unMonoidMap
|
|
||||||
|
|
||||||
type Version = String
|
|
||||||
type UserName = String
|
|
||||||
type PackageName = String
|
|
||||||
|
|
||||||
type PackageHistory = Map Version (UserName, UTCTime)
|
|
||||||
type UploadLog = MonoidMap PackageName PackageHistory
|
|
||||||
type Allowed = MonoidMap PackageName (Map UserName AllowedVersions)
|
|
||||||
type Forbidden = UploadLog
|
|
||||||
|
|
||||||
data AllowedVersions = AllVersions | SpecificVersions (Set Version)
|
|
||||||
instance Monoid AllowedVersions where
|
|
||||||
mempty = SpecificVersions mempty
|
|
||||||
AllVersions `mappend` _ = AllVersions
|
|
||||||
_ `mappend` AllVersions = AllVersions
|
|
||||||
SpecificVersions x `mappend` SpecificVersions y = SpecificVersions (x `mappend` y)
|
|
||||||
|
|
||||||
getUploadLog :: IO UploadLog
|
|
||||||
getUploadLog = do
|
|
||||||
rsp <- simpleHTTP $ getRequest logURL
|
|
||||||
body <- getResponseBody rsp
|
|
||||||
return $ mconcat $ map go $ lines body
|
|
||||||
where
|
|
||||||
go :: String -> UploadLog
|
|
||||||
go s = fromMaybe mempty $ do
|
|
||||||
ver:pkg:user:date' <- Just $ reverse $ words s
|
|
||||||
t <- parseTime defaultTimeLocale fmtStr $ unwords $ reverse date'
|
|
||||||
Just $ msingleton pkg $ Map.singleton ver (user, t)
|
|
||||||
|
|
||||||
logURL :: String
|
|
||||||
logURL = "http://hackage.haskell.org/packages/archive/log"
|
|
||||||
|
|
||||||
fmtStr :: String
|
|
||||||
fmtStr = "%a %b %e %T %Z %Y"
|
|
||||||
|
|
||||||
readAllowed :: FilePath -> IO Allowed
|
|
||||||
readAllowed fp = do
|
|
||||||
exists <- doesFileExist fp
|
|
||||||
if exists
|
|
||||||
then do
|
|
||||||
s <- readFile fp
|
|
||||||
return $ mconcat $ map go $ lines s
|
|
||||||
else return mempty
|
|
||||||
where
|
|
||||||
go :: String -> Allowed
|
|
||||||
go s = fromMaybe mempty $ do
|
|
||||||
pkg:users <- Just $ words s
|
|
||||||
Just $ msingleton pkg $ Map.unionsWith mappend $ map parseUserAllowed users
|
|
||||||
|
|
||||||
parseUserAllowed s =
|
|
||||||
case break (== '-') s of
|
|
||||||
(user, '-':version) ->
|
|
||||||
Map.singleton user $ SpecificVersions $ Set.singleton version
|
|
||||||
_ -> Map.singleton s AllVersions
|
|
||||||
|
|
||||||
updateAllowed :: UploadLog -> Allowed -> (Allowed, Forbidden)
|
|
||||||
updateAllowed uploads allowed =
|
|
||||||
mconcat $ map go $ Set.toList allPackages
|
|
||||||
where
|
|
||||||
-- Map.keys uploads should be sufficient, but being redundant to ensure we
|
|
||||||
-- never lose any data from allowed.
|
|
||||||
allPackages = Set.fromList (mkeys uploads) `Set.union`
|
|
||||||
Set.fromList (mkeys allowed)
|
|
||||||
|
|
||||||
go :: PackageName -> (Allowed, Forbidden)
|
|
||||||
go pkg =
|
|
||||||
case (mlookup pkg uploads, mlookup pkg allowed) of
|
|
||||||
(Nothing, Nothing) -> assert False (mempty, mempty)
|
|
||||||
(Nothing, Just _) -> (mempty, mempty)
|
|
||||||
(Just u, Nothing) -> (msingleton pkg $ getAllUsers u, mempty)
|
|
||||||
(Just u, Just a) ->
|
|
||||||
let fval = mconcat $ map (check a) $ Map.toList u
|
|
||||||
forbidden
|
|
||||||
| Map.null fval = mempty
|
|
||||||
| otherwise = msingleton pkg fval
|
|
||||||
in (mempty, forbidden)
|
|
||||||
|
|
||||||
getAllUsers :: PackageHistory -> Map UserName AllowedVersions
|
|
||||||
getAllUsers = Map.fromList . map (second $ const AllVersions) . Map.elems
|
|
||||||
|
|
||||||
check :: Map UserName AllowedVersions
|
|
||||||
-> (Version, (UserName, UTCTime))
|
|
||||||
-> Map Version (UserName, UTCTime)
|
|
||||||
check allowed' (ver, (user, time)) = maybe (Map.singleton ver (user, time)) (const Map.empty) $ do
|
|
||||||
versions <- Map.lookup user allowed'
|
|
||||||
case versions of
|
|
||||||
AllVersions -> return ()
|
|
||||||
SpecificVersions vs
|
|
||||||
| ver `Set.member` vs -> return ()
|
|
||||||
| otherwise -> Nothing
|
|
||||||
|
|
||||||
writeAllowed :: FilePath -> Allowed -> IO ()
|
|
||||||
writeAllowed fp =
|
|
||||||
writeFile fp . unlines . map go . Map.toList . unMonoidMap
|
|
||||||
where
|
|
||||||
go (pkg, users) = unwords $ pkg : concatMap toStr (Map.toList users)
|
|
||||||
toStr (user, AllVersions) = [user]
|
|
||||||
toStr (user, SpecificVersions vs) =
|
|
||||||
map helper $ Set.toList vs
|
|
||||||
where
|
|
||||||
helper v = concat [user, "-", v]
|
|
||||||
|
|
||||||
printForbidden :: Forbidden -> IO ()
|
|
||||||
printForbidden (MonoidMap forbidden) = unless (Map.null forbidden) $ do
|
|
||||||
putStrLn $ "Following uploads were forbidden:"
|
|
||||||
forM_ (Map.toList forbidden) $ \(pkg, cases) -> do
|
|
||||||
putStrLn ""
|
|
||||||
putStrLn pkg
|
|
||||||
forM_ (Map.toList cases) $ \(version, (user, time)) ->
|
|
||||||
putStrLn $ concat
|
|
||||||
[ "Version "
|
|
||||||
, version
|
|
||||||
, " by "
|
|
||||||
, user
|
|
||||||
, " at "
|
|
||||||
, show time
|
|
||||||
]
|
|
||||||
exitFailure
|
|
||||||
|
|
||||||
filterForbidden :: ST.BuildPlan
|
|
||||||
-> Forbidden
|
|
||||||
-> Forbidden
|
|
||||||
filterForbidden bp =
|
|
||||||
MonoidMap . Map.mapMaybeWithKey isIncluded . unMonoidMap
|
|
||||||
where
|
|
||||||
isIncluded :: PackageName
|
|
||||||
-> PackageHistory
|
|
||||||
-> Maybe PackageHistory
|
|
||||||
isIncluded pn ph = do
|
|
||||||
spi <- Map.lookup (ST.PackageName pn) $ ST.bpPackages bp
|
|
||||||
let version = display $ ST.spiVersion spi
|
|
||||||
tuple <- Map.lookup version ph
|
|
||||||
Just $ Map.singleton version tuple
|
|
||||||
@ -9,7 +9,6 @@ import Stackage.Select (defaultSelectSettings, select)
|
|||||||
import Stackage.Tarballs (makeTarballs)
|
import Stackage.Tarballs (makeTarballs)
|
||||||
import Stackage.Test (runTestSuites)
|
import Stackage.Test (runTestSuites)
|
||||||
import Stackage.Types
|
import Stackage.Types
|
||||||
import Stackage.Uploads (checkUploads, printForbidden)
|
|
||||||
import Stackage.Util (allowPermissive)
|
import Stackage.Util (allowPermissive)
|
||||||
import System.Environment (getArgs, getProgName)
|
import System.Environment (getArgs, getProgName)
|
||||||
import System.IO (hFlush, stdout)
|
import System.IO (hFlush, stdout)
|
||||||
@ -85,7 +84,6 @@ main :: IO ()
|
|||||||
main = do
|
main = do
|
||||||
args <- getArgs
|
args <- getArgs
|
||||||
case args of
|
case args of
|
||||||
["uploads"] -> checkUploads "allowed.txt" "new-allowed.txt" >>= printForbidden
|
|
||||||
"select":rest -> do
|
"select":rest -> do
|
||||||
SelectArgs {..} <- parseSelectArgs rest
|
SelectArgs {..} <- parseSelectArgs rest
|
||||||
ghcVersion <- getGhcVersion
|
ghcVersion <- getGhcVersion
|
||||||
|
|||||||
@ -28,7 +28,6 @@ library
|
|||||||
Stackage.CheckCabalVersion
|
Stackage.CheckCabalVersion
|
||||||
Stackage.Select
|
Stackage.Select
|
||||||
Stackage.GhcPkg
|
Stackage.GhcPkg
|
||||||
Stackage.Uploads
|
|
||||||
build-depends: base >= 4 && < 5
|
build-depends: base >= 4 && < 5
|
||||||
, containers
|
, containers
|
||||||
, Cabal
|
, Cabal
|
||||||
@ -40,7 +39,6 @@ library
|
|||||||
, transformers
|
, transformers
|
||||||
, process
|
, process
|
||||||
, old-locale
|
, old-locale
|
||||||
, HTTP
|
|
||||||
, time
|
, time
|
||||||
, utf8-string
|
, utf8-string
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user