dnf-repo 0.2 → 0.3
raw patch · 5 files changed
+98/−87 lines, 5 files
Files
- ChangeLog.md +4/−0
- README.md +10/−4
- dnf-repo.cabal +1/−1
- src/Main.hs +13/−18
- src/YumRepoFile.hs +70/−64
ChangeLog.md view
@@ -1,5 +1,9 @@ # dnf-repo releases +## 0.3 (2022-08-12)+- fold over multiple changes (eg -m -t now combine correctly)+- handle debuginfo and source repos+ ## 0.2 (2022-08-12) - support multiple repos per repo file (eg needed for eln) - support multiple repo actions (eg "-d rawhide -e fedora")
README.md view
@@ -16,16 +16,18 @@ ```shellsession $ dnf-repo --version-0.2+0.3 $ dnf-repo --help DNF wrapper repo tool Usage: dnf-repo [--version] [-n|--dryrun] [-D|--debug] [--exact] [-s|--save] [(-c|--add-copr COPR) | (-k|--add-koji REPO) | (-d|--disable REPOPAT) | (-e|--enable REPOPAT) |- (-x|--expire REPOPAT) | (-E|--delete-repofile REPOPAT)]- [(-t|--enable-testing) | (-T|--disable-testing)]- [(-m|--enable-modular) | (-M|--disable-modular)] [DNFARGS]+ (-x|--expire REPOPAT) | (-E|--delete-repofile REPOPAT) |+ (-t|--enable-testing) | (-T|--disable-testing) |+ (-m|--enable-modular) | (-M|--disable-modular) |+ --enable-debuginfo | --disable-debuginfo | --enable-source |+ --disable-source] [DNFARGS] see https://github.com/juhp/dnf-repo#readme Available options:@@ -46,6 +48,10 @@ -T,--disable-testing Disable testing repos -m,--enable-modular Enable modular repos -M,--disable-modular Disable modular repos+ --enable-debuginfo Enable debuginfo repos+ --disable-debuginfo Disable debuginfo repos+ --enable-source Enable source repos+ --disable-source Disable source repos ``` ## Usage examples
dnf-repo.cabal view
@@ -1,5 +1,5 @@ name: dnf-repo-version: 0.2+version: 0.3 synopsis: DNF wrapper tool to control repos description: A command-line wrapper of the dnf package manager to
src/Main.hs view
@@ -8,7 +8,6 @@ import Data.Bifunctor (bimap) import Data.List.Extra import Data.Maybe (mapMaybe)-import Data.Tuple.Extra (fst3,snd3) import SimpleCmd import SimpleCmdArgs import System.Directory@@ -33,8 +32,6 @@ <*> switchLongWith "exact" "Match repo names exactly" <*> switchWith 's' "save" "Save the repo enable/disable state" <*> many modeOpt- <*> optional testingOpt- <*> optional modularOpt <*> many (strArg "DNFARGS") where modeOpt =@@ -43,15 +40,15 @@ DisableRepo <$> strOptionWith 'd' "disable" "REPOPAT" "Disable repos" <|> EnableRepo <$> strOptionWith 'e' "enable" "REPOPAT" "Enable repos" <|> ExpireRepo <$> strOptionWith 'x' "expire" "REPOPAT" "Expire repo cache" <|>- DeleteRepo <$> strOptionWith 'E' "delete-repofile" "REPOPAT" "Remove unwanted .repo file"-- testingOpt =- flagWith' EnableTesting 't' "enable-testing" "Enable testing repos" <|>- flagWith' DisableTesting 'T' "disable-testing" "Disable testing repos"-- modularOpt =- flagWith' EnableModular 'm' "enable-modular" "Enable modular repos" <|>- flagWith' DisableModular 'M' "disable-modular" "Disable modular repos"+ DeleteRepo <$> strOptionWith 'E' "delete-repofile" "REPOPAT" "Remove unwanted .repo file" <|>+ flagWith' (Specific EnableTesting) 't' "enable-testing" "Enable testing repos" <|>+ flagWith' (Specific DisableTesting) 'T' "disable-testing" "Disable testing repos" <|>+ flagWith' (Specific EnableModular) 'm' "enable-modular" "Enable modular repos" <|>+ flagWith' (Specific DisableModular) 'M' "disable-modular" "Disable modular repos" <|>+ flagLongWith' (Specific EnableDebuginfo) "enable-debuginfo" "Enable debuginfo repos" <|>+ flagLongWith' (Specific DisableDebuginfo) "disable-debuginfo" "Disable debuginfo repos" <|>+ flagLongWith' (Specific EnableSource) "enable-source" "Enable source repos" <|>+ flagLongWith' (Specific DisableSource) "disable-source" "Disable source repos" coprRepoTemplate :: FilePath coprRepoTemplate = "copr.fedorainfracloud.orgCOLONOWNERCOLONREPO.repo"@@ -63,10 +60,8 @@ -- FIXME --enable-all-coprs (for updating etc) -- FIXME confirm repos if many -- FIXME --disable-non-cores (modular,testing,cisco, etc)-runMain :: Bool -> Bool -> Bool -> Bool -> [Mode]- -> Maybe Testing -> Maybe Modular- -> [String] -> IO ()-runMain dryrun debug exact save modes mtesting mmodular args = do+runMain :: Bool -> Bool -> Bool -> Bool -> [Mode] -> [String] -> IO ()+runMain dryrun debug exact save modes args = do hSetBuffering stdout NoBuffering withCurrentDirectory "/etc/yum.repos.d" $ do forM_ modes $@@ -77,7 +72,7 @@ repofiles <- filesWithExtension "." "repo" -- when debug $ print repofiles nameStates <- sort <$> concatMapM readRepos repofiles- let repoActs = concatMap (selectRepo exact modes mtesting mmodular) nameStates+ let repoActs = selectRepo exact nameStates modes unless (null repoActs) $ do mapM_ print repoActs putStrLn ""@@ -146,7 +141,7 @@ listRepos repoStates = do let (on,off) = -- can't this be simplified?- bimap (map fst3) (map fst3) $ partition snd3 repoStates+ bimap (map fst) (map fst) $ partition (fst . snd) repoStates putStrLn "Enabled:" mapM_ putStrLn on putStrLn ""
src/YumRepoFile.hs view
@@ -2,11 +2,10 @@ module YumRepoFile ( Mode(..),+ SpecificChange(..), readRepos, RepoState, selectRepo,- Modular(..),- Testing(..), changeRepo, saveRepo, updateState,@@ -15,16 +14,34 @@ ) where -import Data.List.Extra (isPrefixOf, isInfixOf, isSuffixOf, trim)+import Data.List.Extra (isPrefixOf, isInfixOf, isSuffixOf, sort, stripInfix,+ trim) import SimpleCmd (error') -type RepoState = (String,Bool,FilePath)+type RepoState = (String,(Bool,FilePath)) data Mode = AddCopr String | AddKoji String | EnableRepo String | DisableRepo String | ExpireRepo String | DeleteRepo String- deriving Eq+ | Specific SpecificChange+ deriving (Eq, Ord) +data SpecificChange = EnableModular | DisableModular+ | EnableTesting | DisableTesting+ | EnableDebuginfo | DisableDebuginfo+ | EnableSource | DisableSource+ deriving (Eq, Ord)++repoSubstr :: SpecificChange -> String+repoSubstr EnableModular = "-modular"+repoSubstr DisableModular = "-modular"+repoSubstr EnableTesting = "-testing"+repoSubstr DisableTesting = "-testing"+repoSubstr EnableDebuginfo = "-debuginfo"+repoSubstr DisableDebuginfo = "-debuginfo"+repoSubstr EnableSource = "-source"+repoSubstr DisableSource = "-source"+ data ChangeEnable = Disable String | Enable String | Expire String | Delete FilePath deriving (Eq,Ord,Show)@@ -49,76 +66,60 @@ updateState :: [ChangeEnable] -> RepoState -> RepoState updateState [] rs = rs-updateState (ce:ces) re@(repo,enabled,file) =+updateState (ce:ces) re@(repo,(enabled,file)) = case ce of- Disable r | r == repo && enabled -> (repo,False,file)- Enable r | r == repo && not enabled -> (repo,True,file)+ Disable r | r == repo && enabled -> (repo,(False,file))+ Enable r | r == repo && not enabled -> (repo,(True,file)) _ -> updateState ces re -data Modular = EnableModular | DisableModular- deriving Eq--data Testing = EnableTesting | DisableTesting- deriving Eq+selectRepo :: Bool -> [RepoState] -> [Mode] -> [ChangeEnable]+selectRepo exact repostates modes =+ foldr selectRepo' [] (sort modes)+ where+ selectRepo' :: Mode -> [ChangeEnable] -> [ChangeEnable]+ selectRepo' mode acc =+ acc ++ concatMap (selectRepoMode mode acc) repostates -selectRepo :: Bool -> [Mode] -> Maybe Testing -> Maybe Modular- -> RepoState -> [ChangeEnable]-selectRepo exact modes mtesting mmodular (name,enabled,file) =- case modes of- [] -> selectOther- (mode:modes') ->+ selectRepoMode :: Mode -> [ChangeEnable] -> RepoState -> [ChangeEnable]+ selectRepoMode mode acc (name,(enabled,file)) = case mode of- AddCopr repo -> if repo `isSuffixOf` name && not enabled- then [Enable name]- else selectOther- AddKoji repo -> if repo `isSuffixOf` name && not enabled- then [Enable name]- else selectOther- EnableRepo pat -> if pat `matchesRepo` name && not enabled- then [Enable name]- else selectOther- DisableRepo pat -> if pat `matchesRepo` name && enabled- then [Disable name]- else selectOther+ AddCopr repo ->+ [Enable name | repo `isSuffixOf` name, not enabled]+ AddKoji repo ->+ [Enable name | repo `isSuffixOf` name, not enabled]+ EnableRepo pat ->+ [Enable name | pat `matchesRepo` name, not enabled]+ DisableRepo pat ->+ [Disable name | pat `matchesRepo` name, enabled] ExpireRepo pat -> [Expire name | pat `matchesRepo` name]- DeleteRepo pat -> if pat `matchesRepo` name- then if enabled- then error' $ "disable repo before deleting: " ++ name- else [Delete file]- else []- ++ selectRepo exact modes' mtesting mmodular (name,enabled,file)- where- matchesRepo = if exact then (==) else isInfixOf+ DeleteRepo pat ->+ if pat `matchesRepo` name+ then if enabled+ then error' $ "disable repo before deleting: " ++ name+ else [Delete file]+ else []+ Specific change ->+ let substr = repoSubstr change in+ if change `elem`+ [EnableModular,EnableTesting,EnableDebuginfo,EnableSource]+ then [Enable name | substr `isInfixOf` name, not enabled,+ repoStatus acc (removeInfix substr name) True]+ else [Disable name | substr `isInfixOf` name, enabled] - selectOther :: [ChangeEnable]- selectOther- | "modular" `isSuffixOf` name =- case mmodular of- Nothing -> []- Just include ->- case include of- EnableModular | not enabled ->- if "testing" `isInfixOf` name- then- [Enable name | mtesting == Just EnableTesting]- else [Enable name]- DisableModular | enabled -> [Disable name]- _ -> []- | "testing" `isInfixOf` name =- case mtesting of- Nothing -> []- Just include ->- case include of- EnableTesting | not enabled -> [Enable name]- DisableTesting | enabled -> [Disable name]- _ -> []- | otherwise = []+ repoStatus :: [ChangeEnable] -> String -> Bool -> Bool+ repoStatus acc repo state =+ case lookup repo repostates of+ Just (enabled,_) ->+ enabled == state || Enable repo `elem` acc+ Nothing -> False + matchesRepo = if exact then (==) else isInfixOf+ readRepos :: FilePath -> IO [RepoState] readRepos file = parseRepos file . lines <$> readFile file --- was called parseIni+-- parse ini parseRepos :: FilePath -> [String] -> [RepoState] parseRepos file ls = case nextSection ls of@@ -132,7 +133,7 @@ "enabled=1" -> (True,more') "enabled=0" -> (False,more') _ -> error' $ "unknown enabled state " ++ e ++ " for " ++ section- in (section,enabled,file) : parseRepos file more+ in (section,(enabled,file)) : parseRepos file more where nextSection :: [String] -> Maybe (String,[String]) nextSection [] = Nothing@@ -143,3 +144,8 @@ then Just (init rest, ls') else error' $ "bad section " ++ l ++ " in " ++ file _ -> nextSection ls'++-- adapted from simple-cmd+removeInfix :: String -> String-> String+removeInfix inf orig =+ maybe orig (uncurry (++)) $ stripInfix inf orig