packages feed

fedora-repoquery 0.4 → 0.5

raw patch · 9 files changed

+162/−84 lines, 9 filesdep +Globdep +safedep +utility-ht

Dependencies added: Glob, safe, utility-ht, xdg-basedir

Files

ChangeLog.md view
@@ -1,12 +1,20 @@ # Revision history for fedora-repoquery +## 0.5 (2024-07-02)+- allow multiple release args+- with no release arg use system yum repos+- add --quick to skip url http checks, also done when multiple releases+- dnf5 --qf does not add "\n" so we do it if no trailing "space"+- update cache dir commands to support also dnf5 xdg cache path+- use dnf5 repoquery.cpp list of --qf conflicts+ ## 0.4 (2024-05-24) - add --dnf4 option to use dnf4 (actually /usr/bin/dnf-3) instead of dnf5-- rawhide and oldest active releases are now determined/cached via Bodhi API-- can now query with rawhide version (eg 41 currently)-- --requires do not allow --qf-- --list now shows active fedora releases-- for centos and eln only check compose via BaseOS repo+- oldest and newest active releases are now determined/cached via Bodhi API+- can now query with rawhide by version (eg 41 currently)+- disable --qf for --requires+- --list now only shows active fedora releases+- for centos and eln only check compose for the BaseOS repo - map version 11 to eln  ## 0.3.2 (2024-02-19)
README.md view
@@ -9,7 +9,7 @@ `$ fdrq rawhide firefox`  ```-firefox-126.0-7.fc41.x86_64 (fedora-rawhide)+firefox-127.0.2-1.fc41.x86_64 (fedora-rawhide) ```  `$ fdrq 40 --requires filesystem`@@ -33,7 +33,7 @@ `$ fdrq eln kernel`  ```-kernel-6.10.0-0.rc0.20240523gitc760b3725e52.12.eln136.x86_64 (eln-BaseOS)+kernel-6.10.0-0.rc6.50.eln141.x86_64 (eln-BaseOS) ```  etc.@@ -54,19 +54,20 @@ `$ fdrq --version`  ```-0.4+0.5 ``` `$ fdrq --help`  ``` fedora-repoquery tool for querying Fedora repos for packages. -Usage: fdrq [--version] [-4|--dnf4] [(-q|--quiet) | (-v|--verbose)] [-K|--koji] -            [--devel-channel | --test-channel] [(-m|--mirror URL) | (-D|--dl)] +Usage: fdrq [--version] [-4|--dnf4] [(-q|--quiet) | (-v|--verbose)] [--no-check]+            [-K|--koji] [--devel-channel | --test-channel] +            [(-m|--mirror URL) | (-D|--dl)]              [(-s|--source) | (-A|--all-archs) | [-a|--arch ARCH]] [-t|--testing]             [-d|--debug]              ((-z|--cache-size) | (-e|--cache-clean-empty) | (-l|--list) | -              RELEASE [[REPOQUERY_OPTS] [PACKAGE]...])+              RELEASE... [REPOQUERY_OPTS]... [PACKAGE]...)    where RELEASE is {fN or N (fedora), 'rawhide', epelN, epelN-next, cN (centos   stream), 'eln'}, with N the release version number.@@ -78,6 +79,7 @@   -4,--dnf4                Use dnf4 instead of dnf5 (if available)   -q,--quiet               Avoid output to stderr   -v,--verbose             Show stderr from dnf repoquery+  --no-check               Skip http repo url checks   -K,--koji                Use Koji buildroot   --devel-channel          Use eln development compose   --test-channel           Use eln test compose [default: production]
fedora-repoquery.cabal view
@@ -1,9 +1,10 @@ name:                fedora-repoquery-version:             0.4+version:             0.5 synopsis:            Fedora repoquery tool description:-        A CLI tool for querying Fedora packages-        including their version and repo location+        A CLI tool for repoquerying Fedora packages:+        by default it displays their version and repo location+        with compose timestamp license:             GPL-3 license-file:        COPYING author:              Jens Petersen <juhpetersen@gmail.com>@@ -50,12 +51,16 @@                        directory,                        extra,                        filepath,+                       Glob,                        http-client,                        http-directory >= 0.1.4 && (< 0.1.6 || >= 0.1.8),                        regex-compat,+                       safe,                        simple-cmd,                        simple-cmd-args,-                       time+                       time,+                       utility-ht >= 0.0.16,+                       xdg-basedir    default-language:    Haskell2010   ghc-options:         -Wall
src/Cache.hs view
@@ -7,25 +7,30 @@ import Data.List.Extra import SimpleCmd import System.Directory+import System.Environment.XDG.BaseDir (getUserCacheDir) import System.FilePath+import System.FilePath.Glob -cacheDir :: IO FilePath-cacheDir = do-  dirs <- lines <$> shell "ls -d /var/tmp/dnf-*"-  case dirs of-    [] -> error' "no /var/tmp/dnf-*/ cache found"-    [d] -> return d-    _ -> error' "More than one /var/tmp/dnf-*/ cache found"+cacheDirs :: IO [FilePath]+cacheDirs = do+  dnf5cache <- getUserCacheDir "libdnf5"+  exists <- doesDirectoryExist dnf5cache+  olddirs <- glob "/var/tmp/dnf-*"+  return $+    (if exists then (dnf5cache :) else id) olddirs  cacheSize :: IO () cacheSize = do-  cache <- cacheDir-  cmd_ "du" ["-sh", cache]+  caches <- cacheDirs+  forM_ caches $ \cache ->+    cmd_ "du" ["-sh", cache] +-- FIXME offer deleting old repos cleanEmptyCaches :: IO () cleanEmptyCaches = do-  cache <- cacheDir-  withCurrentDirectory cache $ do+  caches <- cacheDirs+  forM_ caches $ \cache ->+    withCurrentDirectory cache $ do     repocaches <- groupOn cachePrefix .                   filter (\ f -> '.' `notElem` f && '-' `elem` f) <$>                   listDirectory "."@@ -43,7 +48,11 @@           putStrLn $ "removing " ++ r           removeDirectory repodata           removeDirectory r-        else putStrLn ("removing " ++ r) >> removeDirectory r+        else do+        files <- listDirectory r+        when (null files) $ do+          putStrLn ("removing " ++ r)+          removeDirectory r       removeEmptyCaches rs  -- "AppStream-8-312ff1df17be2171" -> "AppStream-8-"
src/Main.hs view
@@ -14,6 +14,7 @@   ) #endif import Control.Monad (forM_)+import Data.List.HT (spanJust) #if !MIN_VERSION_simple_cmd_args(0,1,7) import Options.Applicative (eitherReader, maybeReader, ReadM) #endif@@ -27,10 +28,10 @@ import Paths_fedora_repoquery (version) import Query (repoqueryCmd) import ShowRelease (showReleaseCmd, downloadServer)-import Types (Channel(..), Mirror(..), Release, RepoSource(..), Verbosity(..),+import Types (Channel(..), Mirror(..), Release (System), RepoSource(..), Verbosity(..),               readRelease) -data Command = Query Release [String] | CacheSize | CacheEmpties | List+data Command = Query [String] | CacheSize | CacheEmpties | List  main :: IO () main = do@@ -41,7 +42,9 @@      "https://github.com/juhp/fedora-repoquery#readme") $     runMain sysarch     <$> switchWith '4' "dnf4" "Use dnf4 instead of dnf5 (if available)"-    <*> (flagWith' Quiet 'q' "quiet" "Avoid output to stderr" <|> flagWith Normal Verbose 'v' "verbose" "Show stderr from dnf repoquery")+    <*> (flagWith' Quiet 'q' "quiet" "Avoid output to stderr" <|>+         flagWith Normal Verbose 'v' "verbose" "Show stderr from dnf repoquery")+    <*> switchLongWith "no-check" "Skip http repo url checks"     <*> (RepoSource           <$> switchWith 'K' "koji" "Use Koji buildroot"           <*> (flagLongWith' ChanDevel "devel-channel" "Use eln development compose" <|>@@ -56,21 +59,23 @@     <*> (flagWith' CacheSize 'z' "cache-size" "Show total dnf repo metadata cache disksize"          <|> flagWith' CacheEmpties 'e' "cache-clean-empty" "Remove empty dnf caches"          <|> flagWith' List 'l' "list" "List Fedora versions"-         <|> Query <$> argumentWith releaseM "RELEASE" <*> many (strArg "[REPOQUERY_OPTS] [PACKAGE]..."))-  where-    releaseM :: ReadM Release-    releaseM = maybeReader readRelease+         <|> Query <$> some (strArg "RELEASE... [REPOQUERY_OPTS]... [PACKAGE]...")) -runMain :: Arch -> Bool -> Verbosity -> RepoSource -> [Arch] -> Bool -> Bool+runMain :: Arch -> Bool -> Verbosity -> Bool -> RepoSource -> [Arch] -> Bool -> Bool         -> Command -> IO ()-runMain sysarch dnf4 verbose reposource archs testing debug command = do+runMain sysarch dnf4 verbose nourlchecks reposource archs testing debug command = do   case command of     CacheSize -> cacheSize     CacheEmpties -> cleanEmptyCaches     List -> listVersionsCmd-    Query release args -> do-      if null args+    Query relargs ->+      let (releases,args) = spanJust readRelease relargs+      in+        forM_ (if null releases then [System] else releases) $ \release ->+        if null args         then if null archs              then showReleaseCmd debug reposource release sysarch Nothing testing              else forM_ archs $ \arch -> showReleaseCmd debug reposource release sysarch (Just arch) testing-      else repoqueryCmd dnf4 debug verbose release reposource sysarch archs testing args+        else+          let multiple = length releases > 1 || length archs > 1+          in repoqueryCmd dnf4 debug verbose (nourlchecks || multiple) release reposource sysarch archs testing args
src/Query.hs view
@@ -5,8 +5,10 @@   ) where  import Control.Monad.Extra+import Data.Char (isSpace) import qualified Data.List.Extra as L import Data.Maybe (isJust, fromMaybe)+import Safe (lastMay) import SimpleCmd (cmdLines) import System.Directory (doesFileExist, findExecutable) import System.FilePath (takeBaseName)@@ -17,14 +19,34 @@ import Types import URL (URL, renderUrl) +-- from dnf5 repoquery.cpp pkg_attrs_options+pkgAttrsOptions :: [String]+pkgAttrsOptions =+  map ("--" ++)+  [+    "conflicts",+    "depends",+    "enhances",+    "obsoletes",+    "provides",+    "recommends",+    "requires",+    "requires_pre",+    "suggests",+    "supplements"+  ]+ -- FIXME --no-redirect? -- FIXME error if no testing repo-repoqueryCmd :: Bool -> Bool -> Verbosity -> Release -> RepoSource -> Arch-             -> [Arch] -> Bool -> [String] -> IO ()-repoqueryCmd dnf4 debug verbose release reposource sysarch archs testing args = do+repoqueryCmd :: Bool -> Bool -> Verbosity -> Bool -> Release -> RepoSource+             -> Arch -> [Arch] -> Bool -> [String] -> IO ()+repoqueryCmd dnf4 debug verbose nourlcheck release reposource sysarch archs testing args = do   forM_ (if null archs then [sysarch] else archs) $ \arch -> do-    repoConfigs <- showRelease debug verbose True reposource release sysarch (Just arch) testing-    let qfAllowed = not $ any (`elem` ["-i","--info","-l","--list","-s","--source","--nvr","--nevra","--envra","-qf","--queryformat", "--changelog", "--provides", "--requires"]) args+    repoConfigs <-+      if release == System+      then return []+      else showRelease debug verbose True nourlcheck reposource release sysarch (Just arch) testing+    let qfAllowed = not $ any (`elem` ["-i","--info","-l","--list","-s","--source","--nvr","--nevra","--envra","--qf","--queryformat", "--changelog"] ++ pkgAttrsOptions) args     -- dnf5 writes repo update output to stdout     -- https://github.com/rpm-software-management/dnf5/issues/1361     -- but seems to cache better@@ -35,6 +57,7 @@     -- LANG=C.utf8     rhsm <- doesFileExist "/etc/dnf/plugins/subscription-manager.conf"     let cmdargs = "repoquery" :+                  -- for dnf5 does not suppress repodata downloading                   ["--quiet" | verbose /= Verbose] ++                   -- https://bugzilla.redhat.com/show_bug.cgi?id=1876828                   ["--disableplugin=subscription-manager" | rhsm] ++@@ -42,15 +65,34 @@                   -- drop modules for F39+                   ["--setopt=module_platform_id=platform:" ++ show release] ++                   concatMap renderRepoConfig repoConfigs ++-                  args+                  tweakedArgs (isJust mdnf5)     -- FIXME drop "/usr/bin/"?     let dnf = fromMaybe "/usr/bin/dnf-3" mdnf5     when debug $       warning $ unwords $ ('\n' : takeBaseName dnf) : map show cmdargs     res <- cmdLines dnf cmdargs     unless (null res) $ do-      unless (verbose == Quiet) $ warning ""+      unless (verbose == Quiet || nourlcheck || release == System) $ warning ""       putStrLn $ L.intercalate "\n" res+  where+    tweakedArgs dnf5 =+      if not dnf5+      then args+      else tweakQf $ map tweakInfo args+      where+        -- dnf5 only has --info not -i+        tweakInfo "-i" = "--info"+        tweakInfo arg = arg++        -- dnf5 doesn't append \n to queryformat+        tweakQf as@(x:y:rest) | x `elem` ["--qf","--queryformat"] =+                                case lastMay y of+                                  Just sp -> if isSpace sp+                                             then as+                                             else x : (y ++ "\n") : rest+                                  Nothing -> as+                              | otherwise = x : tweakQf (y:rest)+        tweakQf xs = xs  renderRepoConfig :: (String, URL) -> [String] renderRepoConfig (name, url) =
src/ShowRelease.hs view
@@ -28,11 +28,11 @@ showReleaseCmd :: Bool -> RepoSource -> Release  -> Arch -> Maybe Arch -> Bool                -> IO () showReleaseCmd debug reposource release sysarch march testing =-  void $ showRelease debug Normal False reposource release sysarch march testing+  void $ showRelease debug Normal False False reposource release sysarch march testing -showRelease :: Bool -> Verbosity -> Bool -> RepoSource -> Release -> Arch-            -> Maybe Arch -> Bool -> IO [(String, URL)]-showRelease debug verbose warn reposource@(RepoSource koji _chan _mirror) release sysarch march testing = do+showRelease :: Bool -> Verbosity -> Bool -> Bool -> RepoSource -> Release+            -> Arch -> Maybe Arch -> Bool -> IO [(String, URL)]+showRelease debug verbose warn nourlcheck reposource@(RepoSource koji _chan _mirror) release sysarch march testing = do   mgr <- httpManager   let arch = fromMaybe sysarch march   (url,path) <- getURL debug mgr reposource release arch@@ -60,6 +60,7 @@                  [("epel-testing",url +//+ ["testing", show n]) | testing],                  [])       EPELNext _n -> return ([("epelnext",urlpath)],[])+      System -> error' "showRelease: system unsupported"   let basicrepourls =         map (repoConfigArgs reposource sysarch march release) basicrepos       morerepourls =@@ -67,37 +68,39 @@   forM_ basicrepourls $ \(reponame,(url',path')) -> do     let baserepo = url' +//+ path'     when debug $ print $ renderUrl baserepo-    ok <- httpExists mgr $ trailingSlash $ renderUrl baserepo-    if ok-      then do-      unless (verbose == Quiet) $ do-        mtime <- do-          let composeinfo =-                if koji-                then url' +//+ ["repo.json"]-                else-                  case release of-                    Centos 10 -> url' +//+ ["metadata","composeinfo.json"]-                    Centos _ -> url' +//+ ["COMPOSE_ID"] -- ["metadata","composeinfo.json"]-                    ELN -> url' +//+ ["metadata","composeinfo.json"]-                    EPEL _ -> url' +//+ ["Everything", "state"]-                    EPELNext _ -> url' +//+ ["Everything", "state"]-                    Fedora _ -> url' +//+-                                if "updates" `isSuffixOf` reponame ||-                                   "updates-testing" `isSuffixOf` reponame-                                then ["Everything", "state"]-                                else ["COMPOSE_ID"]-                    Rawhide -> url' +//+ ["COMPOSE_ID"]-          when debug $ print $ renderUrl composeinfo-          exists <- httpExists mgr (renderUrl composeinfo)-          if exists-            then httpLastModified mgr (renderUrl composeinfo)-            else return Nothing-        whenJust mtime $ \utc -> do-          date <- utcToLocalZonedTime utc-          (if warn then warning else putStrLn) $ show date +-+ "<" ++ renderUrl url' ++ ">"-      else-      error' $ renderUrl baserepo +-+ "not found"+    unless nourlcheck $ do+      ok <- httpExists mgr $ trailingSlash $ renderUrl baserepo+      if ok+        then do+        unless (verbose == Quiet || release == System) $ do+          mtime <- do+            let composeinfo =+                  if koji+                  then url' +//+ ["repo.json"]+                  else+                    case release of+                      Centos 10 -> url' +//+ ["metadata","composeinfo.json"]+                      Centos _ -> url' +//+ ["COMPOSE_ID"] -- ["metadata","composeinfo.json"]+                      ELN -> url' +//+ ["metadata","composeinfo.json"]+                      EPEL _ -> url' +//+ ["Everything", "state"]+                      EPELNext _ -> url' +//+ ["Everything", "state"]+                      Fedora _ -> url' +//++                                  if "updates" `isSuffixOf` reponame ||+                                     "updates-testing" `isSuffixOf` reponame+                                  then ["Everything", "state"]+                                  else ["COMPOSE_ID"]+                      Rawhide -> url' +//+ ["COMPOSE_ID"]+                      System -> error' "system not supported"+            when debug $ print $ renderUrl composeinfo+            exists <- httpExists mgr (renderUrl composeinfo)+            if exists+              then httpLastModified mgr (renderUrl composeinfo)+              else return Nothing+          whenJust mtime $ \utc -> do+            date <- utcToLocalZonedTime utc+            (if warn then warning else putStrLn) $ show date +-+ "<" ++ renderUrl url' ++ ">"+        else+        error' $ renderUrl baserepo +-+ "not found"   return $ map (fmap (uncurry (+//+))) $ basicrepourls ++ morerepourls  getURL :: Bool -> Manager -> RepoSource -> Release -> Arch -> IO (URL,[String])@@ -142,6 +145,7 @@           in getFedoraServer debug mgr reposource fedoraTop              [if pending then "development" else "releases", releasestr]     Rawhide -> getFedoraServer debug mgr reposource fedoraTop ["development", "rawhide"]+    System -> error' "getURL: system unsupported"   where     fedoraTop =       -- FIXME support older archs@@ -165,10 +169,11 @@         case release of           Centos _ -> [repo, showArch arch] ++ (if arch == Source then ["tree"] else ["os"])           ELN -> [repo, showArch arch] ++ (if arch == Source then ["tree"] else ["os"])-          EPEL n -> (if n >= 7 then ("Everything" :) else id) [showArch arch]+          EPEL n -> (if n >= 8 then ("Everything" :) else id) [showArch arch] ++ ["tree" | arch == Source]           EPELNext _n -> ["Everything", showArch arch]           Fedora _ -> ["Everything", showArch arch] ++ (if arch == Source then ["tree"] else ["os" | repo `elem` ["releases","development"]])           Rawhide -> ["Everything", showArch arch, if arch == Source then "tree" else "os"]+          System -> error' "repoConfigArgs: system unsupported"   in (reponame, (url, path ++ ["/"]))   where     repoVersion :: String
src/Types.hs view
@@ -39,7 +39,8 @@   show ChanTest = "test"   show ChanProd = "prod" -data Release = EPEL Natural | EPELNext Natural | Centos Natural | Fedora Natural | ELN | Rawhide+data Release = EPEL Natural | EPELNext Natural | Centos Natural | Fedora Natural+             | ELN | Rawhide | System   deriving (Eq, Ord)  elnVersion :: Natural@@ -47,6 +48,7 @@  -- | Read a Release name, otherwise return an error message eitherRelease :: String -> Either String Release+-- FIXME: alias "raw" or "r"?? eitherRelease "rawhide" = Right Rawhide -- FIXME add proper parsing: eitherRelease "epel8-next" = Right $ EPELNext 8@@ -79,3 +81,4 @@   show (EPELNext n) = "epel" ++ show n ++ "-next"   show ELN = "eln"   show (Centos n) = 'c' : show n ++ "s"+  show System = "system"
test/tests.hs view
@@ -41,7 +41,6 @@   ,(["epel9"], Just "ghc")   ,(["c10"], Just "bash")   ,(["c9"], Just "kernel")-  ,(["c8"], Just "pandoc")   ]  main :: IO ()