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 +13/−5
- README.md +8/−6
- fedora-repoquery.cabal +9/−4
- src/Cache.hs +21/−12
- src/Main.hs +17/−12
- src/Query.hs +49/−7
- src/ShowRelease.hs +41/−36
- src/Types.hs +4/−1
- test/tests.hs +0/−1
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 ()