dnf-repo 0.5.5 → 0.5.6
raw patch · 6 files changed
+144/−71 lines, 6 filesdep +curldep ~simple-cmd
Dependencies added: curl
Dependency ranges changed: simple-cmd
Files
- ChangeLog.md +7/−0
- README.md +15/−11
- data/copr.fedorainfracloud.orgCOLONOWNERCOLONREPO.repo +0/−10
- dnf-repo.cabal +5/−5
- src/Main.hs +101/−36
- src/YumRepoFile.hs +16/−9
ChangeLog.md view
@@ -1,5 +1,12 @@ # dnf-repo releases +## 0.5.6 (2024-04-18)+- --add-copr now supports non-fedora copr's and downloads .repo with curl+- with --add-copr can override --osname OS and --releasever VERSION+- use dnf5 if available+- --expire now enables the repo for the invocation+- --add-koji now uses rpm system arch+ ## 0.5.5 (2023-07-02) - for dnf5 test for dnf-3 (for config-manager) and also dnf - YumRepoFile: fix parsing of "enable = 1" (for UBI)
README.md view
@@ -15,15 +15,16 @@ It is also possible to expire repo caches individually. There are also smart options to enable/disable testing/modular repos-(and even source/debuginfo repos),-and also to create a repo file for a Copr or Koji repo.+(and even source/debuginfo repos), and also to a Copr repo or Koji repo file. ## Help -```shellsession-$ dnf-repo --version-0.5.5-$ dnf-repo --help+`$ dnf-repo --version`+```+0.5.6+```+`$ dnf-repo --help`+``` DNF wrapper repo tool Usage: dnf-repo [--version] [-n|--dryrun] [-q|--quiet] [-D|--debug] [-l|--list]@@ -34,8 +35,9 @@ (-T|--disable-testing) | (-m|--enable-modular) | (-M|--disable-modular) | --enable-debuginfo | --disable-debuginfo | --enable-source | --disable-source |- (-c|--add-copr COPR) | (-k|--add-koji REPO) |- (-u|--repourl URL)] [DNFARGS]+ (-c|--add-copr COPR) [--osname OSNAME]+ [--releasever RELEASEVER] |+ (-k|--add-koji REPO) | (-u|--repourl URL)] [DNFARGS] see https://github.com/juhp/dnf-repo#readme @@ -65,7 +67,9 @@ --enable-source Enable source repos --disable-source Disable source repos -c,--add-copr COPR Create repo file for copr repo- -k,--add-koji REPO Create repo file for koji repo (f38-build, rawhide,+ --osname OSNAME Specify OS Name to override (eg epel)+ --releasever RELEASEVER Specify OS Release Version to override (eg rawhide)+ -k,--add-koji REPO Create repo file for koji repo (f40-build, rawhide, epel9-build, etc) -u,--repourl URL Use temporary repo from a baseurl ```@@ -122,9 +126,9 @@ ``` ### Switch system from rawhide-Switch a system from Rawhide to F38:+Switch a system from Rawhide to F40: ```shellsession-$ dnf-repo -d rawhide -e fedora distrosync --releasever 38 fedora-\*+$ dnf-repo -d rawhide -e fedora distrosync --releasever 40 fedora-\* with disabled 'rawhide' with enabled 'fedora'
− data/copr.fedorainfracloud.orgCOLONOWNERCOLONREPO.repo
@@ -1,10 +0,0 @@-[copr:copr.fedorainfracloud.org:@COPR_OWNER@:@COPR_REPO@]-name=Copr repo for @COPR_REPO@ owned by @COPR_OWNER@-baseurl=https://download.copr.fedorainfracloud.org/results/@COPR_OWNER@/@COPR_REPO@/@DISTRO@-$releasever-$basearch/-type=rpm-md-skip_if_unavailable=True-gpgcheck=1-gpgkey=https://download.copr.fedorainfracloud.org/results/@COPR_OWNER@/@COPR_REPO@/pubkey.gpg-repo_gpgcheck=0-enabled=0-enabled_metadata=1
dnf-repo.cabal view
@@ -1,5 +1,5 @@ name: dnf-repo-version: 0.5.5+version: 0.5.6 synopsis: DNF wrapper tool to control repos description: A command-line wrapper of the dnf package manager to@@ -8,7 +8,7 @@ license-file: LICENSE author: Jens Petersen <juhpetersen@gmail.com> maintainer: Jens Petersen <juhpetersen@gmail.com>-copyright: 2022-2023 Jens Petersen <juhpetersen@gmail.com>+copyright: 2022-2024 Jens Petersen <juhpetersen@gmail.com> category: Utility homepage: https://github.com/juhp/dnf-repo bug-reports: https://github.com/juhp/dnf-repo/issues@@ -23,8 +23,7 @@ || == 9.2.7 || == 9.4.5 data-dir: data-data-files: copr.fedorainfracloud.orgCOLONOWNERCOLONREPO.repo- koji-REPO.repo+data-files: koji-REPO.repo source-repository head type: git@@ -39,12 +38,13 @@ autogen-modules: Paths_dnf_repo hs-source-dirs: src build-depends: base < 5,+ curl, directory, extra, filepath, Glob, http-directory >= 0.1.9,- simple-cmd,+ simple-cmd >= 0.2.2, simple-cmd-args >= 0.1.8, simple-prompt >= 0.2 default-language: Haskell2010
src/Main.hs view
@@ -9,6 +9,7 @@ import Data.Char (isDigit) import Data.List.Extra import Data.Maybe (isJust, mapMaybe, maybeToList)+import Network.Curl import Network.HTTP.Directory (httpExists', (+/+)) import SimpleCmd import SimpleCmdArgs@@ -51,7 +52,7 @@ (fmap . fmap . fmap . fmap) cleanupReponame . strOptionWith where cleanupReponame =- dropWhileEnd (== ':') . replace "/" ":" . dropWhile (== '/')+ dropWhileEnd (== '/') . dropWhile (== '/') . replace ":" "/" modeOpt = DisableRepo <$> repoOptionWith 'd' "disable" "REPOPAT" "Disable repos" <|>@@ -67,12 +68,15 @@ flagLongWith' (Specific DisableDebuginfo) "disable-debuginfo" "Disable debuginfo repos" <|> flagLongWith' (Specific EnableSource) "enable-source" "Enable source repos" <|> flagLongWith' (Specific DisableSource) "disable-source" "Disable source repos" <|>- AddCopr <$> repoOptionWith 'c' "add-copr" "COPR" "Create repo file for copr repo" <|>- AddKoji <$> repoOptionWith 'k' "add-koji" "REPO" "Create repo file for koji repo (f38-build, rawhide, epel9-build, etc)" <|>+ AddCopr+ <$> repoOptionWith 'c' "add-copr" "COPR" "Create repo file for copr repo"+ <*> optional (strOptionLongWith "osname" "OSNAME" "Specify OS Name to override (eg epel)")+ <*> optional (strOptionLongWith "releasever" "RELEASEVER" "Specify OS Release Version to override (eg rawhide)") <|>+ AddKoji <$> repoOptionWith 'k' "add-koji" "REPO" "Create repo file for koji repo (f40-build, rawhide, epel9-build, etc)" <|> RepoURL <$> strOptionWith 'u' "repourl" "URL" "Use temporary repo from a baseurl" -coprRepoTemplate :: FilePath-coprRepoTemplate = "copr.fedorainfracloud.orgCOLONOWNERCOLONREPO.repo"+fedoraCopr :: String+fedoraCopr = "copr.fedorainfracloud.org" kojiRepoTemplate :: FilePath kojiRepoTemplate = "koji-REPO.repo"@@ -88,7 +92,7 @@ withCurrentDirectory "/etc/yum.repos.d" $ do forM_ modes $ \case- AddCopr copr -> addCoprRepo dryrun debug copr+ AddCopr copr mosname mrelease -> addCoprRepo dryrun debug mosname mrelease copr AddKoji repo -> addKojiRepo dryrun debug repo _ -> return () repofiles <- filesWithExtension "." "repo"@@ -103,7 +107,7 @@ outputs <- forM actions $ \case- Expire repo -> do+ Expire repo _ -> do expireRepo dryrun debug repo return True UnExpire -> do@@ -137,7 +141,11 @@ else do sleep 1 when save $ putStrLn ""- mdnf <- findExecutable "dnf"+ mdnf <- do+ mdnf5 <- findExecutable "dnf5"+ case mdnf5 of+ Just dnf5 -> return $ Just dnf5+ Nothing -> findExecutable "dnf" case mdnf of Just dnf -> do when debug $ putStrLn dnf@@ -145,40 +153,59 @@ weakdeps = maybe [] (\w -> ["--setopt=install_weak_deps=" ++ show w]) mweakdeps quietopt = if quiet then ("-q" :) else id cachedir = ["--setopt=cachedir=/var/cache/dnf" </> relver | relver <- maybeToList (maybeReleaseVer args)]- in doSudo dryrun debug dnf $ quietopt repoargs ++ cachedir ++ weakdeps ++ args+ in doSudo dryrun debug dnf $ quietopt repoargs ++ cachedir ++ weakdeps ++ map mungeArg args -- FIXME rpm-ostree install supports --enablerepo Nothing -> error' "rpm-ostree not supported"+ where+ mungeArg :: String -> String+ mungeArg "distrosync" = "distro-sync"+ mungeArg arg = arg --- FIXME pull non-fedora copr repo file-addCoprRepo :: Bool -> Bool -> String -> IO ()-addCoprRepo dryrun debug repo = do- case stripInfix ":" repo of- Nothing -> error' $ "invalid copr: " ++ repo- Just (copr_owner,copr_repo) -> do- let repourl = "https://download.copr.fedorainfracloud.org/results" +/+ copr_owner +/+ copr_repo- unlessM (httpExists' repourl) $ error' $ "no such copr repo: " ++ repourl- distro <- do- isFedora <- grep_ "ID=fedora" "/etc/os-release"- return $ if isFedora then "fedora" else "epel" -- FIXME!- template <- getDataFileName coprRepoTemplate- repodef <- cmd "sed" ["-e", "s/@COPR_OWNER@/" ++ copr_owner ++ "/g", "-e", "s/@COPR_REPO@/" ++ copr_repo ++ "/g", "-e", "s/@DISTRO@/" ++ distro ++ "/", template]- let repofile = ("_copr:" ++) $- replace "COLON" ":" $- replace "OWNER" copr_owner $- replace "REPO" copr_repo coprRepoTemplate- exists <- doesFileExist repofile- if exists- then error' $ "repo already defined: " ++ repofile- else putStrLn $ "Setting up copr repo " ++ repo- withTempDir $ \ tmpdir -> do- let tmpfile = tmpdir </> repofile- unless dryrun $ writeFile tmpfile repodef- doSudo dryrun debug "cp" [tmpfile, repofile]- putStrLn ""+addCoprRepo :: Bool -> Bool -> Maybe String -> Maybe String -> String -> IO ()+addCoprRepo dryrun debug mosname mrelease repo = do+ let (server,owner,project) =+ case splitOn "/" repo of+ [] -> error' "empty repo string"+ [_] -> error' $ "unqualified repo project:" +-+ repo+ [o,p] -> (fedoraCopr, o , p)+ [c,o,p] ->+ if c == "redhat"+ then ("copr.devel.redhat.com", o, p)+ else+ if '.' `elem` c+ then (c, o, p)+ else error' $ "unknown copr server:" +-+ repo+ _ -> error' $ "unknown copr:" +-+ repo+ repofile =+ "_copr:" ++ server ++ ':' : mungeGroupFile owner ++ ':' : project <.> "repo"+ whenM (doesFileExist repofile) $+ error' $ "repo already defined: " ++ repofile+ osName <- maybe getRpmOSName return mosname+ osVersion <- maybe getRpmOsRelease return mrelease+ let repofileUrl = "https://" ++ server +/+ "coprs" +/+ mungeGroupUrl owner +/+ project +/+ "repo" +/+ osName ++ '-' : osVersion +/+ mungeGroupFile owner ++ '-' : project <.> "repo"+ (curlres,curlcontent) <- curlGetString repofileUrl []+ unless (curlres == CurlOK) $+ error' $ "downloading failed of" +-+ repofileUrl+ putStrLn $ "Setting up copr repo " ++ repo+ withTempDir $ \ tmpdir -> do+ let tmpfile = tmpdir </> repofile+ unless dryrun $ writeFile tmpfile $+ maybe id (replace "$releasever") mrelease $+ replace "enabled=1" "enabled=0" curlcontent+ doSudo dryrun debug "cp" [tmpfile, repofile]+ putStrLn ""+ where+ mungeGroupFile ('@':own) = "group_" ++ own+ mungeGroupFile own = own + mungeGroupUrl ('@':own) = "g" +/+ own+ mungeGroupUrl own = own+ addKojiRepo :: Bool -> Bool -> String -> IO () addKojiRepo dryrun debug repo = do- let repourl = "https://kojipkgs.fedoraproject.org/repos" +/+ repo +/+ "/latest/x86_64/"+ sysarch <- cmd "rpm" ["--eval", "%{_arch}"]+ -- FIXME repo validation/sanity: not "-k list" or other dnf command+ let repourl = "https://kojipkgs.fedoraproject.org/repos" +/+ repo +/+ "latest" +/+ sysarch ++ "/" unlessM (httpExists' repourl) $ error' $ "no such koji repo: " ++ repourl template <- getDataFileName kojiRepoTemplate repodef <- cmd "sed" ["-e", "s/@REPO@/" ++ repo ++ "/g", template]@@ -247,3 +274,41 @@ issudo <- isJust <$> lookupEnv "SUDO_USER" when issudo $ warning "*No need to run dnf-repo directly with sudo*"++getRpmOsRelease :: IO String+getRpmOsRelease = do+ -- not defined for fedora branches+ let systemReleaseVer = "system-release(releasever)"+ mReleaseVerPkg <- cmdMaybe "rpm" ["-q", "--whatprovides", systemReleaseVer]+ case mReleaseVerPkg of+ Just relverPkg -> do+ mreleasever <- find (systemReleaseVer `isPrefixOf`) <$> cmdLines "rpm" ["-q", "--provides", relverPkg]+ case mreleasever of+ Just releasever -> return $ last (words releasever)+ Nothing -> error' $ "failed to determine" +-+ systemReleaseVer+ Nothing -> do+ let systemRelease = "system-release"+ msysreleasepkg <- cmdMaybe "rpm" ["-q", "--whatprovides", systemRelease]+ case msysreleasepkg of+ Just sysrelpkg -> do+ let prefix = systemRelease ++ "("+ msysrelease <- find (prefix `isPrefixOf`) <$> cmdLines "rpm" ["-q", "--provides", sysrelpkg]+ case msysrelease of+ Just sysrelease ->+ -- "system-release(40)"+ return $ init $ dropPrefix prefix sysrelease+ Nothing -> error' $ "failed to determine" +-+ systemRelease+ Nothing -> error' "failed to determine OS version"++getRpmOSName :: IO String+getRpmOSName = do+ let osrelease = "/etc/os-release"+ idkey = "ID="+ osids <- grep ('^' : idkey) osrelease+ case osids of+ [] -> error' $ "failed to find ID in" +-+ osrelease+ [osid] -> return $+ dropSuffix "\"" $+ dropPrefix "\"" $+ dropPrefix idkey osid+ oss -> error' $ "multiple IDs in" +-+ osrelease ++ ":" ++ unwords oss
src/YumRepoFile.hs view
@@ -25,7 +25,8 @@ type RepoState = (String,(Bool,FilePath)) -data Mode = AddCopr String | AddKoji String | RepoURL String+data Mode = AddCopr String (Maybe String) (Maybe String) | AddKoji String+ | RepoURL String | EnableRepo String | DisableRepo String | ExpireRepo String | ClearExpires | DeleteRepo String@@ -33,7 +34,7 @@ deriving (Eq, Ord, Show) modePattern :: Mode -> Maybe String-modePattern (AddCopr c) = Just c+modePattern (AddCopr c _ _) = Just c modePattern (AddKoji k) = Just k modePattern (RepoURL _) = Nothing modePattern (EnableRepo r) = Just r@@ -61,7 +62,7 @@ data ChangeEnable = Disable String Bool | Enable String Bool- | Expire String+ | Expire String Bool | UnExpire | Delete FilePath Bool | BaseURL String@@ -84,7 +85,12 @@ then "enable " ++ quote r else "with enabled " ++ quote r else Just $ Left $ quote r ++ " already enabled"-printAction _ (Expire _) = Nothing+printAction _ (Expire r s) =+ if s+ then+ Just . Right $+ "with enabled " ++ quote r+ else Nothing printAction _ UnExpire = Just $ Right "unexpire:" printAction _ (Delete f s) =@@ -105,7 +111,7 @@ maybeRepoName :: ChangeEnable -> Maybe (ChangeEnable, String) maybeRepoName d@(Disable r _) = Just (d, r) maybeRepoName e@(Enable r _) = Just (e, r)-maybeRepoName x@(Expire r) = Just (x, r)+maybeRepoName x@(Expire r _) = Just (x, r) maybeRepoName UnExpire = Nothing maybeRepoName (Delete _ _) = Nothing maybeRepoName (BaseURL _) = Nothing@@ -113,6 +119,7 @@ changeRepo :: ChangeEnable -> [String] changeRepo (Disable r True) = ["--disablerepo", r] changeRepo (Enable r True) = ["--enablerepo", r]+changeRepo (Expire r True) = ["--enablerepo", r] changeRepo (BaseURL url) = ["--repofrompath", repoUrlName ++ "," ++ url] where repoUrlName = replace "/" ":" $@@ -128,7 +135,7 @@ saveRepo _ = [] expiring :: ChangeEnable -> Maybe String-expiring (Expire r) = Just r+expiring (Expire r _) = Just r expiring _ = Nothing deleting :: ChangeEnable -> Maybe String@@ -153,7 +160,7 @@ let results = nub $ mapMaybe (selectRepoMode mode acc) repostates in case results of- [] -> error' ("no match for repo pattern action: " ++ show mode)+ [] -> [] [_] -> acc ++ results _ -> acc ++@@ -178,7 +185,7 @@ -> Maybe ChangeEnable selectRepoMode mode acc (name,(enabled,file)) = case mode of- AddCopr repo ->+ AddCopr repo _ _ -> maybeChange repo isSuffixOf (not enabled) (Enable name) AddKoji repo -> maybeChange repo isSuffixOf (not enabled) (Enable name)@@ -188,7 +195,7 @@ DisableRepo pat -> maybeChange pat matchesRepo enabled (Disable name) ExpireRepo pat ->- maybeChange pat matchesRepo True (const (Expire name))+ maybeChange pat matchesRepo True (Expire name) ClearExpires -> Just UnExpire DeleteRepo pat -> maybeChange pat matchesRepo