-- Copyright (C) 2016-2017 Red Hat, Inc. -- -- This library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- This library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with this library; if not, see . {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} import Control.Conditional(unlessM) import Control.Exception(catch) import Control.Monad(forM_) import Control.Monad.Except(MonadError, runExceptT, throwError) import Control.Monad.IO.Class(MonadIO, liftIO) import Control.Monad.Reader(ReaderT, runReaderT) import Data.ContentStore(CsError(..), mkContentStore) import Data.List(isSuffixOf) import Network.URI(URI(..), parseURI) import System.Directory(doesFileExist) import System.Environment(getArgs) import System.Exit(exitFailure) import BDCS.Exceptions(DBException) import qualified BDCS.Import.Comps as Comps import qualified BDCS.Import.NPM as NPM import qualified BDCS.Import.RPM as RPM import qualified BDCS.Import.Repodata as Repodata import BDCS.Import.URI(isCompsFile, isPrimaryXMLFile) import BDCS.Import.State(ImportState(..)) import BDCS.Utils.Either(whenLeft) import BDCS.Version import Utils.GetOpt(commandLineArgs) processThing :: String -> ReaderT ImportState IO () processThing url = case parseURI url of Just uri@URI{..} -> if | isPrimaryXMLFile uri -> Repodata.loadFromURI uri | isCompsFile uri -> Comps.loadFromURI uri | ".rpm" `isSuffixOf` uriPath -> RPM.loadFromURI uri | uriScheme == "npm:" -> NPM.loadFromURI uri | otherwise -> Repodata.loadRepoFromURI uri _ -> liftIO usage runCommand :: (MonadError CsError m, MonadIO m) => FilePath -> FilePath -> [String] -> m () runCommand db repo things = do cs <- mkContentStore repo let st = ImportState { stDB=db, stRepo=cs } unlessM (liftIO $ doesFileExist db) $ throwError $ CsError "Database must already exist - create with sqlite3 schema.sql" forM_ things $ \path -> liftIO $ runReaderT (processThing path) st usage :: IO () usage = do printVersion "import" putStrLn "Usage: import output.db repo thing [thing ...]" putStrLn "- repo is the path to an already existing content store repo or " putStrLn " the path to a repo to be created" putStrLn "- thing can be:" putStrLn "\t* An HTTP, HTTPS, or file: URL to an RPM" putStrLn "\t* A URL to a yum repo primary.xml.gz file" putStrLn "\t* A URL to a yum repo comps.xml.gz file" exitFailure main :: IO () main = commandLineArgs <$> getArgs >>= \case Nothing -> usage Just (db, repo, args) -> do result <- catch (runExceptT $ runCommand db repo args) (\(e :: DBException) -> return $ Left $ CsError $ show e) whenLeft result (\e -> putStrLn $ "error: " ++ show e)