packages feed

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 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