fedora-repoquery 0.7.4 → 0.8
raw patch · 9 files changed
+236/−89 lines, 9 filesdep +optparse-applicative
Dependencies added: optparse-applicative
Files
- ChangeLog.md +15/−0
- README.md +44/−21
- fedora-repoquery.cabal +2/−1
- src/BodhiRelease.hs +1/−10
- src/List.hs +5/−1
- src/Main.hs +126/−24
- src/Query.hs +40/−29
- src/Release.hs +2/−2
- test/tests.hs +1/−1
ChangeLog.md view
@@ -1,5 +1,20 @@ # Revision history for fedora-repoquery +## 0.8 (2025-09-23)+- rework dnf option handling with full parsing and completions:+ with free ordering of arguments, releases and options+- no longer outputs "(using system repos)" when no release specified+- `--list-releases` lists in order (was `--list`)+- rename `--arch` to `--repo-arch`+- new `--all-fedora` releases option+- alias `--changelog` to `--changelogs`+- `--queryformat` now accepts format alias 'default'+- add `--help-dnf` option for 'dnf --help' output++## 0.7.4 (2025-08-16)+- Query renderRepoConfig: disable skip_if_unavailable+- Query: don't use dnf --quiet output for --debug+ ## 0.7.3 (2025-06-03) - fix the naming of koji dnf repos - flip the --dl and --debug short options
README.md view
@@ -10,7 +10,7 @@ `$ fedora-repoquery rawhide firefox` ```-firefox-142.0-1.fc44.x86_64 (fedora-rawhide)+firefox-143.0.1-1.fc44.x86_64 (fedora-rawhide) ``` `$ fedora-repoquery 43 --requires filesystem`@@ -35,25 +35,24 @@ `$ fedora-repoquery eln kernel` ```-kernel-6.17.0-0.rc1.250814g0cc53520e68b.20.eln151.x86_64 (eln-BaseOS)+kernel-6.17.0-0.rc6.250919g097a6c336d008.53.eln151.x86_64 (eln-BaseOS) ``` Without a release argument, the system yum repo configuration is used: -`$ fedora-repoquery pandoc`+`$ fedora-repoquery pandoc-cli` ```-pandoc-3.6.4-37.fc43.x86_64 (rawhide)+pandoc-cli-3.6.4-38.fc44.x86_64 (rawhide) ```-but then currently you have to insert `--` before a query option: -`$ fedora-repoquery -- --whatrequires pandoc`+`$ fedora-repoquery --whatrequires pandoc` ``` R-reprex-2.1.1-2.fc43.noarch (rawhide) R-rmarkdown-2.24-9.fc43.noarch (rawhide)-pandoc-pdf-3.6.4-37.fc43.x86_64 (rawhide)-python3-pypandoc-1.15-6.fc43.noarch (rawhide)+pandoc-pdf-3.6.4-38.fc44.x86_64 (rawhide)+python3-pypandoc-1.15-8.fc44.noarch (rawhide) ``` Use the --time (-T) option to display repo timestamps:@@ -71,7 +70,7 @@ ``` 2025-04-15 01:43:43 +08 <https://mirror.freedif.org/fedora/fedora/linux/releases/42/>-2025-08-16 09:11:49 +08 <https://mirror.freedif.org/fedora/fedora/linux/updates/42/>+2025-09-23 09:11:46 +08 <https://mirror.freedif.org/fedora/fedora/linux/updates/42/> ``` One can also query multiple releases (or arch's):@@ -80,8 +79,9 @@ ``` python3-3.13.2-2.fc42.x86_64 (f42)-python3-3.13.6-1.fc42.x86_64 (f42-updates)-python3-3.14.0~rc1-2.fc43.x86_64 (f43-development)+python3-3.13.7-1.fc42.x86_64 (f42-updates)+python3-3.14.0~rc2-1.fc43.x86_64 (f43-development)+python3-3.14.0~rc3-1.fc43.x86_64 (f43-updates-testing) ``` @@ -89,7 +89,7 @@ `$ fedora-repoquery --version` ```-0.7.4+0.8 ``` `$ fedora-repoquery --help`@@ -99,16 +99,37 @@ Usage: fedora-repoquery [--version] [-4|--dnf4] [(-q|--quiet) | (-v|--verbose)] [--dynamic] [-T|--time] [-K|--koji] - [(-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]...)+ [(-m|--mirror URL) | (-d|--dl)] [-F|--all-fedora] + [(-s|--source) | (-A|--all-archs) | + [-a|--repo-arch ARCH]] [-t|--testing] [-D|--debug] + [(-z|--cache-size) | (-e|--cache-clean-empty) | + --list-releases | --help-dnf | + [--advisories ARG | --advisory-severities ARG | + --arch ARG | --available | --bugfix | --bzs ARG | + --cves ARG | --disable-modular-filtering | + --duplicates | --enhancement | --exactdeps | + --extras | (-f|--file ARG) | --installed | + --installed-from-repo ARG | --installonly | + --latest-limit ARG | --leaves | --newpackage | + --providers-of ARG | --recent | --recursive | + --security | --srpm | --unneeded | --upgrades | + --userinstalled | --whatconflicts ARG | + --whatdepends ARG | --whatenhances ARG | + --whatobsoletes ARG | --whatprovides ARG | + --whatrecommends ARG | --whatrequires ARG | + --whatsuggests ARG | --whatsupplements ARG | + --conflicts | --depends | --enhances | --files | + (-l|--list) | --obsoletes | --provides | + --recommends | --requires | --requires-pre | + --sourcerpm | --suggests | --supplements | + --location | (-i|--info) | + (--changelog|--changelogs) | --querytags | + (--qf|--queryformat ARG)] + [[RELEASE]... [REPOQUERY_OPTS]... [PKGSPECIFIER]...]] where RELEASE is {fN or N (fedora), 'rawhide', epelN, epelN-next, cN (centos stream), 'eln'}, with N the release version number.- https://github.com/juhp/fedora-repoquery#readme+ <https://github.com/juhp/fedora-repoquery#readme> Available options: -h,--help Show this help text@@ -122,14 +143,16 @@ -m,--mirror URL Fedora mirror [default: https://download.fedoraproject.org/pub] -d,--dl Use dl.fp.o+ -F,--all-fedora Query all Fedora releases -s,--source Query source repos -A,--all-archs Query all (64 bit) arch repos- -a,--arch ARCH Specify arch [default: x86_64]+ -a,--repo-arch ARCH Specify repo arch [default: x86_64] -t,--testing Fedora updates-testing -D,--debug Show some debug output -z,--cache-size Show total dnf repo metadata cache disksize -e,--cache-clean-empty Remove empty dnf caches- -l,--list List Fedora versions+ --list-releases List Fedora versions+ --help-dnf Show dnf --help ``` The default arch is the system arch.
fedora-repoquery.cabal view
@@ -1,5 +1,5 @@ name: fedora-repoquery-version: 0.7.4+version: 0.8 synopsis: Fedora release repos package query tool description: A CLI tool for repoquerying Fedora and Centos Stream release packages:@@ -52,6 +52,7 @@ fedora-releases >= 0.2, filepath, Glob,+ optparse-applicative, regex-compat, safe, simple-cmd >= 0.2,
src/BodhiRelease.hs view
@@ -5,8 +5,7 @@ activeFedoraRelease, activeFedoraReleases, fedoraReleaseState,- rawhideFedoraRelease,- fedoraReleasePostBeta+ rawhideFedoraRelease ) where @@ -64,11 +63,3 @@ actives <- activeFedoraReleases let pending = map releaseVersion (filter (\r -> releaseState r == "pending") actives) return $ read $ maximum (L.delete "eln" pending)--fedoraReleasePostBeta :: Natural -> IO Bool-fedoraReleasePostBeta n = do- eactive <- activeFedoraRelease n- return $- case eactive of- Left _ -> error' $ "could find F" ++ show n ++ " release (setting)"- Right rel -> releasePostBeta rel
src/List.hs view
@@ -3,13 +3,17 @@ ) where import Data.List.Extra+import Data.Ord (Down(Down)) import SimpleCmd ((+-+)) import Release (activeFedoraReleases, BodhiRelease(..)) listVersionsCmd :: IO () listVersionsCmd =- activeFedoraReleases >>= mapM_ printRelease . sortOn releaseState+ activeFedoraReleases >>= mapM_ printRelease . sortOn releaseSorter where printRelease (Release _version state branch _composed _postbeta) = putStrLn $ branch +-+ state++ releaseSorter rel =+ (Down (releaseState rel), Down(releaseVersion rel))
src/Main.hs view
@@ -13,34 +13,48 @@ #endif ) #endif-import Control.Monad (forM_, when)-import Data.Either (partitionEithers)-import Data.Tuple (swap)+import Control.Monad (forM_, unless, when)+import Data.Either (rights, partitionEithers)+#if !MIN_VERSION_base(4,11,0)+import Data.Semigroup ((<>))+#endif+import Options.Applicative (flag', long, short, strOption, #if !MIN_VERSION_simple_cmd_args(0,1,7)-import Options.Applicative (eitherReader, maybeReader, ReadM)+ eitherReader #endif-import SimpleCmd ((+-+), warning)+ )+import SimpleCmd ((+-+), cmd_, error', warning) import SimpleCmdArgs+import System.Environment (getArgs, withArgs) import System.IO (BufferMode(NoBuffering), hSetBuffering, stdout) import Arch import Cache (cacheSize, cleanEmptyCaches) import List (listVersionsCmd) import Paths_fedora_repoquery (version)-import Query (repoqueryCmd)-import Release (showReleaseCmd, downloadServer)+import Query+import Release (activeFedoraReleases, downloadServer, releaseBranch,+ showReleaseCmd) import Types (Mirror(..), Release (System), RepoSource(..), Verbosity(..), eitherRelease) -data Command = Query [String] | CacheSize | CacheEmpties | List+data Command = Query [DnfOption] [String]+ | CacheSize | CacheEmpties | DnfHelp | ReleaseList main :: IO () main = do hSetBuffering stdout NoBuffering+ args <- getArgs+ if null args+ then withArgs ["--help"] main'+ else main'++main' :: IO ()+main' = do sysarch <- getSystemArch- simpleCmdArgs' (Just version) "fedora-repoquery tool for querying Fedora repos for packages."+ simpleCmdArgs (Just version) "fedora-repoquery tool for querying Fedora repos for packages." ("where RELEASE is {fN or N (fedora), 'rawhide', epelN, epelN-next, cN (centos stream), 'eln'}, with N the release version number." +-+- "https://github.com/juhp/fedora-repoquery#readme") $+ "<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" <|>@@ -51,34 +65,122 @@ <$> switchWith 'K' "koji" "Use Koji buildroot" <*> ((Mirror <$> strOptionWith 'm' "mirror" "URL" ("Fedora mirror [default: " ++ downloadServer ++ "]")) <|> flagWith DownloadFpo DlFpo 'd' "dl" "Use dl.fp.o"))+ -- FIXME: --all-epel and --all-releases+ <*> switchWith 'F' "all-fedora" "Query all Fedora releases" <*> (flagWith' [Source] 's' "source" "Query source repos" <|> flagWith' allArchs 'A' "all-archs" "Query all (64 bit) arch repos" <|>- many (optionWith (eitherReader eitherArch) 'a' "arch" "ARCH" ("Specify arch [default:" +-+ showArch sysarch ++ "]")))+ many (optionWith (eitherReader eitherArch) 'a' "repo-arch" "ARCH" ("Specify repo arch [default:" +-+ showArch sysarch ++ "]"))) <*> switchWith 't' "testing" "Fedora updates-testing" <*> switchWith 'D' "debug" "Show some debug output" <*> (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 <$> some (strArg "[RELEASE|--]... [REPOQUERY_OPTS]... [PACKAGE]..."))+ <|> flagLongWith' ReleaseList "list-releases" "List Fedora versions"+ <|> flagLongWith' DnfHelp "help-dnf" "Show dnf --help"+ <|> Query <$> many queryOptions <*> many (strArg "[RELEASE]... [REPOQUERY_OPTS]... [PKGSPECIFIER]...")) -runMain :: Arch -> Bool -> Verbosity -> Bool -> Bool -> RepoSource -> [Arch]- -> Bool -> Bool -> Command -> IO ()-runMain sysarch dnf4 verbose dynredir time reposource archs testing debug command = do+-- man 8 dnf-repoquery (dnf5-5.2.17.0-2.fc44)+-- https://github.com/rpm-software-management/dnf5/blob/main/doc/commands/repoquery.8.rst++dnfFlag, dnfOption :: String -> Parser DnfOption+dnfFlag o = flag' (DnfFlag o) (long o)+dnfOption o = DnfOption o <$> strOption (long o)+dnfFlag', dnfOption' :: Char -> String -> Parser DnfOption+dnfFlag' s l = flag' (DnfFlag l) (short s <> long l)+dnfOption' s l = DnfOption l <$> strOption (short s <> long l)+dnfFlag'', dnfOption'' :: String -> String -> Parser DnfOption+dnfFlag'' s l = flag' (DnfFlag l) (long s <> long l)+dnfOption'' s l = DnfOption l <$> strOption (long s <> long l)++queryOptions :: Parser DnfOption+queryOptions =+ -- # OPTIONS+ dnfOption "advisories"+ <|> dnfOption "advisory-severities"+ <|> dnfOption "arch"+ <|> dnfFlag "available" -- default+ <|> dnfFlag "bugfix"+ <|> dnfOption "bzs"+ <|> dnfOption "cves"+ <|> dnfFlag "disable-modular-filtering"+ <|> dnfFlag "duplicates"+ <|> dnfFlag "enhancement"+ <|> dnfFlag "exactdeps"+ <|> dnfFlag "extras"+ <|> dnfOption' 'f' "file"+ <|> dnfFlag "installed"+ <|> dnfOption "installed-from-repo"+ <|> dnfFlag "installonly"+ <|> dnfOption "latest-limit"+ <|> dnfFlag "leaves"+ <|> dnfFlag "newpackage"+ <|> dnfOption "providers-of" -- for certain commands see manpage+ <|> dnfFlag "recent"+ <|> dnfFlag "recursive" -- with --whatrequires or --providers-of only+ <|> dnfFlag "security"+ <|> dnfFlag "srpm"+ <|> dnfFlag "unneeded"+ <|> dnfFlag "upgrades"+ <|> dnfFlag "userinstalled"+ <|> dnfOption "whatconflicts"+ <|> dnfOption "whatdepends"+ <|> dnfOption "whatenhances"+ <|> dnfOption "whatobsoletes"+ <|> dnfOption "whatprovides"+ <|> dnfOption "whatrecommends"+ <|> dnfOption "whatrequires"+ <|> dnfOption "whatsuggests"+ <|> dnfOption "whatsupplements"+ -- # FORMATTING+ <|> dnfFlag "conflicts"+ <|> dnfFlag "depends"+ <|> dnfFlag "enhances"+ <|> dnfFlag "files"+ <|> dnfFlag' 'l' "list"+ <|> dnfFlag "obsoletes"+ <|> dnfFlag "provides"+ <|> dnfFlag "recommends"+ <|> dnfFlag "requires"+ <|> dnfFlag "requires-pre"+ <|> dnfFlag "sourcerpm"+ <|> dnfFlag "suggests"+ <|> dnfFlag "supplements"+ <|> dnfFlag "location"+ <|> dnfFlag' 'i' "info"+ <|> dnfFlag'' "changelog" "changelogs"+ <|> dnfFlag "querytags"+ <|> dnfOption'' "qf" "queryformat"++runMain :: Arch -> Bool -> Verbosity -> Bool -> Bool -> RepoSource -> Bool+ -> [Arch] -> Bool -> Bool -> Command -> IO ()+runMain sysarch dnf4 verbose dynredir time reposource allreleases archs testing debug command = do case command of CacheSize -> cacheSize CacheEmpties -> cleanEmptyCaches- List -> listVersionsCmd- Query relargs ->+ ReleaseList -> listVersionsCmd+ DnfHelp -> cmd_ (if dnf4 then "dnf4" else "dnf") ["--help"]+ Query opts relargs -> -- spanJust from utility-ht nicer but this gets us enough- let (releases,args) = swap $ partitionEithers $ map eitherRelease relargs+ let (args,releases) = partitionEithers $ map eitherRelease relargs in do- when (null releases && verbose /= Quiet) $+ unless (null releases || not allreleases) $+ error' "cannot specify releases and --all-releases"+ when (null releases && not allreleases) $+ when (verbose == Verbose || debug) $ warning "(using system repos)"- forM_ (if null releases then [System] else releases) $ \release ->- if null args+ releaselist <-+ if null releases+ then+ if allreleases+ then+ rights . map (eitherRelease . releaseBranch)+ <$> activeFedoraReleases+ else return [System]+ else return releases+ forM_ releaselist $ \release ->+ if null args && null opts then if null archs then showReleaseCmd debug dynredir reposource release sysarch Nothing testing else forM_ archs $ \arch -> showReleaseCmd debug dynredir reposource release sysarch (Just arch) testing else- let multiple = length releases > 1 || length archs > 1- in repoqueryCmd dnf4 debug verbose multiple dynredir time release reposource sysarch archs testing args+ let multiple = length releaselist > 1 || length archs > 1+ in repoqueryCmd dnf4 debug verbose multiple dynredir time release reposource sysarch archs testing opts args
src/Query.hs view
@@ -2,6 +2,7 @@ module Query ( repoqueryCmd,+ DnfOption(..) ) where import Control.Monad.Extra@@ -19,11 +20,18 @@ import Types import URL (FileDir(Dir), URL, renderUrl) --- from dnf5 repoquery.cpp pkg_attrs_options-pkgAttrsOptions :: [String]-pkgAttrsOptions =- map ("--" ++)+data DnfOption =+ DnfFlag String | DnfOption String String+ deriving Eq++renderOption :: DnfOption -> String+renderOption (DnfFlag o) = '-' : '-' : o+renderOption (DnfOption o v) = '-' : '-' : o ++ '=' : v++noQueryFormatOptions :: [String]+noQueryFormatOptions = [+ -- from dnf5 repoquery.cpp pkg_attrs_options "conflicts", "depends", "enhances",@@ -31,20 +39,27 @@ "provides", "recommends", "requires",- "requires_pre",+ "require-pre", "suggests",- "supplements"+ "supplements",+ -- others conflicting with '--qf'+ "info",+ "list",+ "location",+ "source",+ "queryformat",+ "changelogs" ] repoqueryCmd :: Bool -> Bool -> Verbosity -> Bool -> Bool -> Bool -> Release- -> RepoSource -> Arch -> [Arch] -> Bool -> [String] -> IO ()-repoqueryCmd dnf4 debug verbose multiple dynredir checkdate release reposource sysarch archs testing args = do+ -> RepoSource -> Arch -> [Arch] -> Bool -> [DnfOption]+ -> [String] -> IO ()+repoqueryCmd dnf4 debug verbose multiple dynredir checkdate release reposource sysarch archs testing opts args = do forM_ (if null archs then [sysarch] else archs) $ \arch -> do repoConfigs <- if release == System then return [] else getRelease debug dynredir True checkdate 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@@ -59,11 +74,11 @@ ["--quiet" | verbose /= Verbose || not debug] ++ -- https://bugzilla.redhat.com/show_bug.cgi?id=1876828 ["--disableplugin=subscription-manager" | rhsm] ++- (if qfAllowed then ["--qf", queryformat] else []) +++ ["--queryformat=" ++ queryformat | queryFormatAllowed] ++ -- drop modules for F39+ ["--setopt=module_platform_id=platform:" ++ show release] ++ concatMap renderRepoConfig repoConfigs ++- tweakedArgs (isJust mdnf5)+ map (renderOption . tweakQfOpt (isJust mdnf5)) opts ++ args -- FIXME drop "/usr/bin/"? let dnf = fromMaybe "/usr/bin/dnf-3" mdnf5 when debug $@@ -73,26 +88,20 @@ unless (not checkdate || release == System || multiple) $ warning "" putStrLn $ intercalate "\n" res where- tweakedArgs dnf5 =- if not dnf5- then args- else tweakQfOpt $ map tweakInfo args- where- -- dnf5 only has --info not -i- tweakInfo "-i" = "--info"- tweakInfo arg = arg+ queryFormatAllowed =+ not $ any (`elem` map DnfFlag noQueryFormatOptions) opts + tweakQfOpt dnf5 opt =+ case opt of+ DnfOption "queryformat" fv -> DnfOption "queryformat" (tweakQf fv)+ _ -> opt+ where -- dnf5 doesn't append \n to queryformat- tweakQfOpt (x:y:rest) | x `elem` ["--qf","--queryformat"] =- x : tweakQf y : rest- | otherwise = x : tweakQfOpt (y:rest)- tweakQfOpt xs = xs-- tweakQf qf =- expandQf qf ++- case lastMay qf of- Just lc -> if isSpace lc then "" else "\n"- Nothing -> ""+ tweakQf fv =+ expandQf fv +++ case lastMay fv of+ Just lc | dnf5 -> if isSpace lc then "" else "\n"+ _ -> "" expandQf qf = case lower qf of@@ -100,8 +109,10 @@ "nv" -> "%{name}-%{version}" "nvr" -> expandQf "nv" ++ "-%{release}" "nvra" -> expandQf "nvr" <.> "%{arch}"+ -- fixme? check order correct for epoch "envr" -> "%{epoch}:" ++ expandQf "nvr" "envra" -> "%{epoch}:" ++ expandQf "nvra"+ "default" -> "%{full_nevra}" _ -> qf renderRepoConfig :: (String, URL) -> [String]
src/Release.hs view
@@ -32,8 +32,8 @@ showReleaseCmd debug dynredir reposource release sysarch march testing = void $ getRelease debug dynredir False True reposource release sysarch march testing -getRelease :: Bool -> Bool -> Bool -> Bool -> RepoSource- -> Release -> Arch -> Maybe Arch -> Bool -> IO [(String, URL)]+getRelease :: Bool -> Bool -> Bool -> Bool -> RepoSource -> Release -> Arch+ -> Maybe Arch -> Bool -> IO [(String, URL)] getRelease debug dynredir warn checkdate reposource@(RepoSource koji _mirror) release sysarch march testing = do let arch = fromMaybe sysarch march (url,path) <- getURL debug dynredir reposource release arch
test/tests.hs view
@@ -18,7 +18,7 @@ -- copied from dl-fedora branched :: Int-branched = 42+branched = 43 current, previous, prevprev, rawhide :: String current = show branched previous = show (branched - 1)