diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,13 @@
 # Revision history for fedora-repoquery
 
+## 0.7.1 (2024-09-08)
+- fix for branched: "frozen" state is still in development/ like "pending"
+- enable updates-testing for fedora branched from Beta freeze
+- help: can use -- for system repoquery
+- only output "slow redirection" for debug
+- refactor eitherRelease with lower case
+- curl connection: timeout for Location redirect but not Last-Modified
+
 ## 0.7 (2024-07-18)
 - use curl library for HTTP instead of http-directory
 - rename the executable back to fedora-repoquery to avoid confusion with fedrq
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@
 `$ fedora-repoquery rawhide firefox`
 
 ```
-firefox-128.0-2.fc41.x86_64 (fedora-rawhide)
+firefox-130.0-1.fc42.x86_64 (fedora-rawhide)
 ```
 
 `$ fedora-repoquery 40 --requires filesystem`
@@ -34,7 +34,7 @@
 `$ fedora-repoquery eln kernel`
 
 ```
-kernel-6.11.0-0.rc0.20240716gitd67978318827.2.eln141.x86_64 (eln-BaseOS)
+kernel-6.11.0-0.rc6.20240906gitb831f83e40a2.53.eln142.x86_64 (eln-BaseOS)
 ```
 
 Without a release argument, the system yum repo configuration is used:
@@ -42,9 +42,21 @@
 `$ fedora-repoquery pandoc`
 
 ```
-pandoc-3.1.3-29.fc41.x86_64 (rawhide)
+pandoc-3.1.11.1-32.fc41.x86_64 (rawhide)
 ```
+but then currently you have to insert `--` before a query option:
 
+`$ fedora-repoquery -- --whatrequires pandoc`
+
+```
+R-reprex-2.0.2-12.fc41.noarch (rawhide)
+R-rmarkdown-2.24-5.fc41.noarch (rawhide)
+pandoc-pdf-3.1.11.1-32.fc41.x86_64 (rawhide)
+python3-nb2plots-0.7.2-5.fc41.noarch (rawhide)
+python3-pypandoc-1.13-6.fc41.noarch (rawhide)
+rstudio-common-2024.04.2+764-3.fc41.x86_64 (rawhide)
+```
+
 Use the --time (-T) option to display repo timestamps:
 ```
 $ fedora-repoquery -T 41 fedrq
@@ -60,16 +72,18 @@
 
 ```
 2024-04-20 02:22:34 +08 <https://mirror.freedif.org/fedora/fedora/linux/releases/40/>
-2024-07-18 12:15:13 +08 <https://mirror.freedif.org/fedora/fedora/linux/updates/40/>
+2024-09-07 09:37:56 +08 <https://mirror.freedif.org/fedora/fedora/linux/updates/40/>
 ```
 
 One can also query multiple releases (or arch's):
+
 `$ fedora-repoquery 40 41 python3 | grep x86_64`
 
 ```
 python3-3.12.2-2.fc40.x86_64 (f40)
-python3-3.12.4-1.fc40.x86_64 (f40-updates)
-python3-3.13.0~b3-2.fc41.x86_64 (fedora-rawhide)
+python3-3.12.5-2.fc40.x86_64 (f40-updates)
+python3-3.13.0~rc1-2.fc41.x86_64 (f41-development)
+python3-3.13.0~rc1-3.fc41.x86_64 (f41-updates-testing)
 ```
 
 
@@ -77,7 +91,7 @@
 `$ fedora-repoquery --version`
 
 ```
-0.7
+0.7.1
 ```
 
 `$ fedora-repoquery --help`
@@ -85,15 +99,15 @@
 ```
 fedora-repoquery tool for querying Fedora repos for packages.
 
-Usage: fedora-repoquery [--version] [-4|--dnf4] [(-q|--quiet) | (-v|--verbose)] 
-                        [--dynamic] [-T|--time] [-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]...)
+Usage: fedora-repoquery [--version] [-4|--dnf4] [(-q|--quiet) | (-v|--verbose)]
+                        [--dynamic] [-T|--time] [-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]...)
 
   where RELEASE is {fN or N (fedora), 'rawhide', epelN, epelN-next, cN (centos
   stream), 'eln'}, with N the release version number.
@@ -125,8 +139,8 @@
 The default arch is the system arch.
 
 ## Installation
-fedora-repoquery can be installed from
-[copr](https://copr.fedorainfracloud.org/coprs/petersen/fedora-repoquery/)
+fedora-repoquery is available in Fedora and EPEL 9:
+<https://src.fedoraproject.org/rpms/fedora-repoquery>.
 
 ## Building from source
 Use `stack install fedora-repoquery` or `cabal install fedora-repoquery`
diff --git a/fedora-repoquery.cabal b/fedora-repoquery.cabal
--- a/fedora-repoquery.cabal
+++ b/fedora-repoquery.cabal
@@ -1,5 +1,5 @@
 name:                fedora-repoquery
-version:             0.7
+version:             0.7.1
 synopsis:            Fedora release repos package query tool
 description:
         A CLI tool for repoquerying Fedora and Centos Stream release packages:
@@ -40,7 +40,7 @@
                        Common
                        List
                        Query
-                       ShowRelease
+                       Release
                        Types
                        URL
   hs-source-dirs:      src
diff --git a/src/BodhiRelease.hs b/src/BodhiRelease.hs
--- a/src/BodhiRelease.hs
+++ b/src/BodhiRelease.hs
@@ -4,8 +4,9 @@
   BodhiRelease (..),
   activeFedoraRelease,
   activeFedoraReleases,
-  pendingFedoraRelease,
-  rawhideFedoraRelease
+  fedoraReleaseState,
+  rawhideFedoraRelease,
+  fedoraReleasePostBeta
   )
 where
 
@@ -21,7 +22,8 @@
 data BodhiRelease =
   Release {releaseVersion :: String, -- to handle eln
            releaseState ::  String,
-           releaseBranch :: String}
+           releaseBranch :: String,
+           releasePostBeta :: Bool}
   deriving Eq
 
 -- Left is oldest active version
@@ -43,18 +45,29 @@
       version <- lookupKey "version" obj
       state <- lookupKey "state" obj
       branch <- lookupKey "branch" obj
-      return $ Release version state branch
+      let setting = lookupKey "setting_status" obj
+      return $
+        Release version state branch $
+        setting == Just ("post_beta" :: String)
 
-pendingFedoraRelease :: Natural -> IO Bool
-pendingFedoraRelease n = do
+fedoraReleaseState :: Natural -> IO String
+fedoraReleaseState n = do
   eactive <- activeFedoraRelease n
   return $
     case eactive of
-      Left _ -> False
-      Right rel -> releaseState rel == "pending"
+      Left _ -> error' $ "could find F" ++ show n ++ " release (state)"
+      Right rel -> releaseState rel
 
 rawhideFedoraRelease :: IO Natural
 rawhideFedoraRelease = do
   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
diff --git a/src/List.hs b/src/List.hs
--- a/src/List.hs
+++ b/src/List.hs
@@ -5,11 +5,11 @@
 import Data.List.Extra
 import SimpleCmd ((+-+))
 
-import ShowRelease (activeFedoraReleases, BodhiRelease(..))
+import Release (activeFedoraReleases, BodhiRelease(..))
 
 listVersionsCmd :: IO ()
 listVersionsCmd =
   activeFedoraReleases >>= mapM_ printRelease . sortOn releaseState
   where
-    printRelease (Release _version state branch) =
+    printRelease (Release _version state branch _postbeta) =
       putStrLn $ branch +-+ state
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -28,7 +28,7 @@
 import List (listVersionsCmd)
 import Paths_fedora_repoquery (version)
 import Query (repoqueryCmd)
-import ShowRelease (showReleaseCmd, downloadServer)
+import Release (showReleaseCmd, downloadServer)
 import Types (Channel(..), Mirror(..), Release (System), RepoSource(..), Verbosity(..),
               eitherRelease)
 
@@ -61,7 +61,7 @@
     <*> (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]..."))
+         <|> Query <$> some (strArg "[RELEASE|--]... [REPOQUERY_OPTS]... [PACKAGE]..."))
 
 runMain :: Arch -> Bool -> Verbosity -> Bool -> Bool -> RepoSource -> [Arch]
         -> Bool -> Bool -> Command -> IO ()
diff --git a/src/Query.hs b/src/Query.hs
--- a/src/Query.hs
+++ b/src/Query.hs
@@ -15,7 +15,7 @@
 
 import Arch
 import Common (warning)
-import ShowRelease (showRelease)
+import Release (getRelease)
 import Types
 import URL (FileDir(Dir), URL, renderUrl)
 
@@ -44,7 +44,7 @@
     repoConfigs <-
       if release == System
       then return []
-      else showRelease debug dynredir True checkdate reposource release sysarch (Just arch) testing
+      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
diff --git a/src/Release.hs b/src/Release.hs
new file mode 100644
--- /dev/null
+++ b/src/Release.hs
@@ -0,0 +1,254 @@
+{-# LANGUAGE CPP, OverloadedStrings #-}
+
+module Release (
+  showReleaseCmd,
+  getRelease,
+  activeFedoraReleases,
+  BodhiRelease(..),
+  downloadServer
+  )
+where
+
+import Control.Monad.Extra (forM_, unless, void, when, whenJust)
+import Data.Bifunctor (first)
+import qualified Data.CaseInsensitive as CI
+import Data.List.Extra
+import Data.Maybe (fromMaybe)
+import Data.Time.Format (defaultTimeLocale, parseTimeM, rfc822DateFormat)
+import Data.Time.LocalTime (utcToLocalZonedTime)
+import Network.Curl (curlHead, CurlOption(..))
+import SimpleCmd (error', (+-+))
+import Text.Regex (mkRegex, subRegex)
+
+import Arch
+import BodhiRelease
+import Common (warning)
+import Types
+import URL
+
+showReleaseCmd :: Bool -> Bool -> RepoSource -> Release  -> Arch -> Maybe Arch
+               -> Bool -> IO ()
+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 debug dynredir warn checkdate reposource@(RepoSource koji _chan _mirror) release sysarch march testing = do
+  let arch = fromMaybe sysarch march
+  (url,path) <- getURL debug dynredir reposource release arch
+  let urlpath = url +//+ path
+  when debug $ print $ renderUrl Dir urlpath
+  (basicrepos,morerepos) <-
+    case release of
+      -- RepoKoji -> ["koji-fedora"]
+      Centos n -> return ([("BaseOS",urlpath)],
+                          [("AppStream",url),(if n >= 9 then "CRB" else "PowerTools",url)])
+      ELN -> return ([("BaseOS",urlpath)],
+                     [("AppStream",urlpath),("CRB",urlpath)])
+      Rawhide -> return ([("development", urlpath)],[])
+      Fedora n -> do
+        state <- fedoraReleaseState n
+        postbeta <- fedoraReleasePostBeta n
+        return $
+          if state `elem` ["pending","frozen"]
+          then (("development", urlpath) :
+                [("updates", url +//+ ["updates",show n]) | postbeta , state == "frozen"] ++
+                -- FIXME add way to disable or invert testing
+                [("updates-testing", url +//+ ["updates","testing",show n]) | testing || state == "frozen" || postbeta]
+               ,[])
+          else (("releases", urlpath) :
+                ("updates", url +//+ ["updates",show n]) :
+                [("updates-testing", url +//+ ["updates","testing",show n]) | testing || postbeta]
+               ,[])
+      EPEL n -> return
+                (("epel",urlpath) :
+                 [("epel-testing",url +//+ ["testing", show n]) | testing],
+                 [])
+      EPELNext _n -> return ([("epelnext",urlpath)],[])
+      System -> error' "showRelease: system unsupported"
+  rawhide <- rawhideFedoraRelease
+  let basicrepourls =
+        map (repoConfigArgs reposource sysarch march rawhide release) basicrepos
+      morerepourls =
+        map (repoConfigArgs reposource sysarch march rawhide release) morerepos
+  forM_ basicrepourls $ \(reponame,(url',path')) -> do
+    let baserepo = url' +//+ path'
+    when debug $ print $ renderUrl Dir baserepo
+    unless (not checkdate || release == System) $ do
+      let composeinfo =
+            url' +//+
+            if koji
+            then ["repo.json"]
+            else
+              case release of
+                Centos 10 -> ["metadata","composeinfo.json"]
+                Centos _ -> ["COMPOSE_ID"] -- ["metadata","composeinfo.json"]
+                ELN -> ["metadata","composeinfo.json"]
+                EPEL _ -> ["Everything", "state"]
+                EPELNext _ -> ["Everything", "state"]
+                Fedora _ -> if "updates" `isInfixOf` reponame
+                            then ["Everything", "state"]
+                            else ["COMPOSE_ID"]
+                Rawhide -> ["COMPOSE_ID"]
+                System -> error' "system not supported"
+      let composeUrl = renderUrl File composeinfo
+      when debug $ print composeUrl
+      mtimestr <- curlGetHeader Nothing "Last-Modified" composeUrl
+      whenJust mtimestr $ \timestr -> do
+        utc <- parseTimeM False defaultTimeLocale rfc822DateFormat timestr
+        date <- utcToLocalZonedTime utc
+        (if warn then warning else putStrLn) $ show date +-+ "<" ++ renderUrl Dir url' ++ ">"
+  return $ map (fmap (uncurry (+//+))) $ basicrepourls ++ morerepourls
+
+getURL :: Bool -> Bool -> RepoSource -> Release -> Arch
+       -> IO (URL,[String])
+getURL debug dynredir reposource@(RepoSource koji chan _mirror) release arch =
+  case release of
+    Centos n ->
+      case n of
+        10 ->
+          let url = URL $
+                if koji
+                then "https://odcs.stream.centos.org/stream-10"
+                else "https://composes.stream.centos.org/stream-10/production/latest-CentOS-Stream/compose/"
+          in return (url,[])
+        9 ->
+          let url = URL $
+                if koji
+                then "https://odcs.stream.centos.org"
+                else "https://mirror.stream.centos.org/9-stream/"
+          in return (url,[])
+        8 -> return (URL "http://vault.centos.org/8-stream/", [])
+        _ -> error' "old Centos is not supported"
+    ELN ->
+      return (URL "https://odcs.fedoraproject.org/composes", [channel chan, "latest-Fedora-ELN", "compose"])
+    EPEL n | n < 7 ->
+               return
+               (URL "https://archives.fedoraproject.org/pub/archive/epel", [show n])
+    EPEL n -> getFedoraServer debug dynredir reposource ["epel"] [show n]
+    EPELNext n -> getFedoraServer debug dynredir reposource ["epel","next"] [show n]
+    Fedora n -> do
+      ebodhirelease <- activeFedoraRelease n
+      case ebodhirelease of
+        Left oldest ->
+          if n < oldest
+          then
+          return
+          (URL "https://archives.fedoraproject.org/pub/archive" +//+ fedoraTop, ["releases", show n])
+          else error' $ "unknown fedora release:" +-+ show n
+        Right rel ->
+          -- state values: ["disabled","pending","frozen","current","archived"]
+          let pending = releaseState rel /= "current"
+              rawhide = pending && releaseBranch rel == "rawhide"
+              releasestr = if rawhide then "rawhide" else show n
+          in getFedoraServer debug dynredir reposource fedoraTop
+             [if pending then "development" else "releases", releasestr]
+    Rawhide -> getFedoraServer debug dynredir reposource fedoraTop ["development", "rawhide"]
+    System -> error' "getURL: system unsupported"
+  where
+    fedoraTop =
+      -- FIXME support older archs
+      if arch `elem` [PPC64LE, S390X]
+      then ["fedora-secondary"]
+      else ["fedora", "linux"]
+
+repoConfigArgs :: RepoSource -> Arch -> Maybe Arch -> Natural -> Release
+               -> (String,URL) -> (String,(URL,[String]))
+-- non-koji
+repoConfigArgs (RepoSource False _chan mirror) sysarch march rawhide release (repo,url) =
+  let arch = fromMaybe sysarch march
+      archsuffix = if arch == sysarch then "" else "-" ++ showArch arch
+      reponame = repoVersion ++ archsuffix ++
+                 case mirror of
+                   DownloadFpo -> ""
+                   Mirror serv ->
+                     '-' : takeWhile (/= '/') (subRegex (mkRegex "https?://") serv "")
+                   DlFpo -> "-dl.fpo"
+      path =
+        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 >= 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
+    repoVersion =
+      if release `elem` [Rawhide, Fedora rawhide]
+      then "fedora-rawhide"
+      else
+        show release ++
+        case release of
+          Centos _ -> '-':repo
+          ELN -> '-':repo
+          EPEL _ -> if repo == "epel-testing" then "-testing" else ""
+          Fedora _ | repo /= "releases" -> '-':repo
+          _ -> ""
+-- koji
+repoConfigArgs (RepoSource True _chan _mirror) sysarch march _rawhide release (repo,url) =
+  let (compose,path) =
+        case release of
+          Rawhide -> (["repos", show release, "latest"],"")
+          _ -> (["repos", show release ++ "-build/latest"],"")
+      arch = fromMaybe sysarch march
+      reponame = repo ++ "-" ++ show release ++ "-build" ++
+                 if arch == sysarch then "" else "-" ++ showArch arch
+  in (reponame, (url +//+ compose, [path, showArch arch, ""]))
+-- repoConfigArgs url (RepoCentosStream chan) arch release repo =
+--   let (compose,path) = (["composes", channel chan, "latest-CentOS-Stream", "compose"], repo)
+--       reponame = repo ++ "-Centos-" ++ show release ++ "-Stream" ++ "-" ++ show chan ++ if arch == sysarch then "" else "-" ++ showArch arch
+--   in (reponame, (url +//+ compose, [path, showArch arch, "os/"]))
+
+getFedoraServer :: Bool -> Bool -> RepoSource -> [String] -> [String]
+                -> IO (URL,[String])
+getFedoraServer debug dynredir (RepoSource koji _ mirror) top path =
+  if koji
+  then return (URL "https://kojipkgs.fedoraproject.org",[])
+  else
+    case mirror of
+      DownloadFpo -> do
+        let url = URL downloadServer +//+ top ++ path
+            rurl = renderUrl Dir url
+        when debug $ print rurl
+        redir <-
+          if dynredir
+          then return Nothing
+          else curlGetHeader (Just 3000) "Location" rurl
+        when debug $ print redir
+        case redir of
+          Nothing -> do
+            when (debug && not dynredir) $
+              warning $ "slow redirection for" +-+ rurl
+            return (URL downloadServer +//+ top,path)
+          Just actual -> do
+            when debug $ do
+              warning rurl
+              warning $ "redirected to" +-+ show actual
+            let actualstr =
+                  if "https://ftp.yzyu.jp/" `isPrefixOf` actual
+                  then replace "https://" "http://" actual
+                  else actual
+            when (actual /= actualstr) $
+              warning $ "replacing to" +-+ actualstr
+            return (URL $ removeSubpath path actualstr, path)
+      -- FIXME how to handle any path
+      Mirror serv -> return (URL serv,path)
+      DlFpo -> return (URL "https://dl.fedoraproject.org/pub" +//+ top, path)
+
+downloadServer :: String
+downloadServer = "https://download.fedoraproject.org/pub"
+
+-- FIXME check CurlCode(CurlOK) status
+curlGetHeader :: Maybe Natural -> CI.CI String -> String -> IO (Maybe String)
+curlGetHeader mtimeout field url = do
+  (_status,headers) <- curlHead url $ maybe [] (singleton . CurlConnectTimeoutMS . fromIntegral) mtimeout
+  -- tail because curl leaves space before field value
+  return $ tail <$> lookup field (map (first CI.mk) headers)
+
+#if !MIN_VERSION_base(4,15,0)
+singleton :: a -> [a]
+singleton x = [x]
+#endif
diff --git a/src/ShowRelease.hs b/src/ShowRelease.hs
deleted file mode 100644
--- a/src/ShowRelease.hs
+++ /dev/null
@@ -1,244 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-
-module ShowRelease (
-  showReleaseCmd,
-  showRelease,
-  activeFedoraReleases,
-  BodhiRelease(..),
-  downloadServer
-  )
-where
-
-import Control.Monad.Extra (forM_, unless, void, when, whenJust)
-import Data.Bifunctor (first)
-import qualified Data.CaseInsensitive as CI
-import Data.List.Extra
-import Data.Maybe (fromMaybe)
-import Data.Time.Format (defaultTimeLocale, parseTimeM, rfc822DateFormat)
-import Data.Time.LocalTime (utcToLocalZonedTime)
-import Network.Curl (curlHead, CurlOption(..))
-import SimpleCmd (error', (+-+))
-import Text.Regex (mkRegex, subRegex)
-
-import Arch
-import BodhiRelease
-import Common (warning)
-import Types
-import URL
-
-showReleaseCmd :: Bool -> Bool -> RepoSource -> Release  -> Arch -> Maybe Arch
-               -> Bool -> IO ()
-showReleaseCmd debug dynredir reposource release sysarch march testing =
-  void $ showRelease debug dynredir False True reposource release sysarch march testing
-
-showRelease :: Bool -> Bool -> Bool -> Bool -> RepoSource
-            -> Release -> Arch -> Maybe Arch -> Bool -> IO [(String, URL)]
-showRelease debug dynredir warn checkdate reposource@(RepoSource koji _chan _mirror) release sysarch march testing = do
-  let arch = fromMaybe sysarch march
-  (url,path) <- getURL debug dynredir reposource release arch
-  let urlpath = url +//+ path
-  when debug $ print $ renderUrl Dir urlpath
-  (basicrepos,morerepos) <-
-    case release of
-      -- RepoKoji -> ["koji-fedora"]
-      Centos n -> return ([("BaseOS",urlpath)],
-                          [("AppStream",url),(if n >= 9 then "CRB" else "PowerTools",url)])
-      ELN -> return ([("BaseOS",urlpath)],
-                     [("AppStream",urlpath),("CRB",urlpath)])
-      Rawhide -> return ([("development", urlpath)],[])
-      Fedora n -> do
-        pending <- pendingFedoraRelease n
-        return $
-          if pending
-          then ([("development", urlpath)],[])
-          else (("releases", urlpath) :
-                ("updates", url +//+ ["updates",show n]) :
-                [("updates-testing", url +//+ ["updates","testing",show n]) | testing],
-                [])
-      EPEL n -> return
-                (("epel",urlpath) :
-                 [("epel-testing",url +//+ ["testing", show n]) | testing],
-                 [])
-      EPELNext _n -> return ([("epelnext",urlpath)],[])
-      System -> error' "showRelease: system unsupported"
-  rawhide <- rawhideFedoraRelease
-  let basicrepourls =
-        map (repoConfigArgs reposource sysarch march rawhide release) basicrepos
-      morerepourls =
-        map (repoConfigArgs reposource sysarch march rawhide release) morerepos
-  forM_ basicrepourls $ \(reponame,(url',path')) -> do
-    let baserepo = url' +//+ path'
-    when debug $ print $ renderUrl Dir baserepo
-    unless (not checkdate || release == System) $ do
-      let composeinfo =
-            url' +//+
-            if koji
-            then ["repo.json"]
-            else
-              case release of
-                Centos 10 -> ["metadata","composeinfo.json"]
-                Centos _ -> ["COMPOSE_ID"] -- ["metadata","composeinfo.json"]
-                ELN -> ["metadata","composeinfo.json"]
-                EPEL _ -> ["Everything", "state"]
-                EPELNext _ -> ["Everything", "state"]
-                Fedora _ -> if "updates" `isInfixOf` reponame ||
-                               "updates-testing" `isInfixOf` reponame
-                            then ["Everything", "state"]
-                            else ["COMPOSE_ID"]
-                Rawhide -> ["COMPOSE_ID"]
-                System -> error' "system not supported"
-      let composeUrl = renderUrl File composeinfo
-      when debug $ print composeUrl
-      mtimestr <- curlGetHeader "Last-Modified" composeUrl
-      whenJust mtimestr $ \timestr -> do
-        utc <- parseTimeM False defaultTimeLocale rfc822DateFormat timestr
-        date <- utcToLocalZonedTime utc
-        (if warn then warning else putStrLn) $ show date +-+ "<" ++ renderUrl Dir url' ++ ">"
-  return $ map (fmap (uncurry (+//+))) $ basicrepourls ++ morerepourls
-
-getURL :: Bool -> Bool -> RepoSource -> Release -> Arch
-       -> IO (URL,[String])
-getURL debug dynredir reposource@(RepoSource koji chan _mirror) release arch =
-  case release of
-    Centos n ->
-      case n of
-        10 ->
-          let url = URL $
-                if koji
-                then "https://odcs.stream.centos.org/stream-10"
-                else "https://composes.stream.centos.org/stream-10/production/latest-CentOS-Stream/compose/"
-          in return (url,[])
-        9 ->
-          let url = URL $
-                if koji
-                then "https://odcs.stream.centos.org"
-                else "https://mirror.stream.centos.org/9-stream/"
-          in return (url,[])
-        8 -> return (URL "http://vault.centos.org/8-stream/", [])
-        _ -> error' "old Centos is not supported"
-    ELN ->
-      return (URL "https://odcs.fedoraproject.org/composes", [channel chan, "latest-Fedora-ELN", "compose"])
-    EPEL n | n < 7 ->
-               return
-               (URL "https://archives.fedoraproject.org/pub/archive/epel", [show n])
-    EPEL n -> getFedoraServer debug dynredir reposource ["epel"] [show n]
-    EPELNext n -> getFedoraServer debug dynredir reposource ["epel","next"] [show n]
-    Fedora n -> do
-      ebodhirelease <- activeFedoraRelease n
-      case ebodhirelease of
-        Left oldest ->
-          if n < oldest
-          then
-          return
-          (URL "https://archives.fedoraproject.org/pub/archive" +//+ fedoraTop, ["releases", show n])
-          else error' $ "unknown fedora release:" +-+ show n
-        Right rel ->
-          let pending = releaseState rel == "pending"
-              rawhide = pending && releaseBranch rel == "rawhide"
-              releasestr = if rawhide then "rawhide" else show n
-          in getFedoraServer debug dynredir reposource fedoraTop
-             [if pending then "development" else "releases", releasestr]
-    Rawhide -> getFedoraServer debug dynredir reposource fedoraTop ["development", "rawhide"]
-    System -> error' "getURL: system unsupported"
-  where
-    fedoraTop =
-      -- FIXME support older archs
-      if arch `elem` [PPC64LE, S390X]
-      then ["fedora-secondary"]
-      else ["fedora", "linux"]
-
-repoConfigArgs :: RepoSource -> Arch -> Maybe Arch -> Natural -> Release
-               -> (String,URL) -> (String,(URL,[String]))
--- non-koji
-repoConfigArgs (RepoSource False _chan mirror) sysarch march rawhide release (repo,url) =
-  let arch = fromMaybe sysarch march
-      archsuffix = if arch == sysarch then "" else "-" ++ showArch arch
-      reponame = repoVersion ++ archsuffix ++
-                 case mirror of
-                   DownloadFpo -> ""
-                   Mirror serv ->
-                     '-' : takeWhile (/= '/') (subRegex (mkRegex "https?://") serv "")
-                   DlFpo -> "-dl.fpo"
-      path =
-        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 >= 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
-    repoVersion =
-      if release `elem` [Rawhide, Fedora rawhide]
-      then "fedora-rawhide"
-      else
-        show release ++
-        case release of
-          Centos _ -> '-':repo
-          ELN -> '-':repo
-          EPEL _ -> if repo == "epel-testing" then "-testing" else ""
-          Fedora _ | repo /= "releases" -> '-':repo
-          _ -> ""
--- koji
-repoConfigArgs (RepoSource True _chan _mirror) sysarch march _rawhide release (repo,url) =
-  let (compose,path) =
-        case release of
-          Rawhide -> (["repos", show release, "latest"],"")
-          _ -> (["repos", show release ++ "-build/latest"],"")
-      arch = fromMaybe sysarch march
-      reponame = repo ++ "-" ++ show release ++ "-build" ++
-                 if arch == sysarch then "" else "-" ++ showArch arch
-  in (reponame, (url +//+ compose, [path, showArch arch, ""]))
--- repoConfigArgs url (RepoCentosStream chan) arch release repo =
---   let (compose,path) = (["composes", channel chan, "latest-CentOS-Stream", "compose"], repo)
---       reponame = repo ++ "-Centos-" ++ show release ++ "-Stream" ++ "-" ++ show chan ++ if arch == sysarch then "" else "-" ++ showArch arch
---   in (reponame, (url +//+ compose, [path, showArch arch, "os/"]))
-
-getFedoraServer :: Bool -> Bool -> RepoSource -> [String] -> [String]
-                -> IO (URL,[String])
-getFedoraServer debug dynredir (RepoSource koji _ mirror) top path =
-  if koji
-  then return (URL "https://kojipkgs.fedoraproject.org",[])
-  else
-    case mirror of
-      DownloadFpo -> do
-        let url = URL downloadServer +//+ top ++ path
-            rurl = renderUrl Dir url
-        when debug $ print rurl
-        redir <-
-          if dynredir
-          then return Nothing
-          else curlGetHeader "location" rurl
-        when debug $ print redir
-        case redir of
-          Nothing -> do
-            unless dynredir $
-              warning $ "slow redirection for" +-+ rurl
-            return (URL downloadServer +//+ top,path)
-          Just actual -> do
-            when debug $ do
-              warning rurl
-              warning $ "redirected to" +-+ show actual
-            let actualstr =
-                  if "https://ftp.yzyu.jp/" `isPrefixOf` actual
-                  then replace "https://" "http://" actual
-                  else actual
-            when (actual /= actualstr) $
-              warning $ "replacing to" +-+ actualstr
-            return (URL $ removeSubpath path actualstr, path)
-      -- FIXME how to handle any path
-      Mirror serv -> return (URL serv,path)
-      DlFpo -> return (URL "https://dl.fedoraproject.org/pub" +//+ top, path)
-
-downloadServer :: String
-downloadServer = "https://download.fedoraproject.org/pub"
-
--- FIXME check CurlCode(CurlOK) status
-curlGetHeader :: CI.CI String -> String -> IO (Maybe String)
-curlGetHeader field url = do
-  (_status,headers) <- curlHead url [CurlConnectTimeoutMS 5000]
-  -- tail because curl leaves space before field value
-  return $ tail <$> lookup field (map (first CI.mk) headers)
diff --git a/src/Types.hs b/src/Types.hs
--- a/src/Types.hs
+++ b/src/Types.hs
@@ -12,6 +12,7 @@
   ) where
 
 import Data.Char (isDigit)
+import Data.List.Extra (lower)
 import Numeric.Natural
 
 --import Distribution.Fedora.Repoquery
@@ -43,28 +44,32 @@
              | ELN | Rawhide | System
   deriving (Eq, Ord)
 
+-- FIXME determine via EPEL or Centos
 elnVersion :: Natural
 elnVersion = 11
 
--- | Read a Release name, otherwise return an error message
+-- FIXME error if short/release-like
+-- | Read a Release name
 eitherRelease :: String -> Either String Release
-eitherRelease "rawhide" = Right Rawhide
--- FIXME add proper parsing:
-eitherRelease "epel8-next" = Right $ EPELNext 8
-eitherRelease "epel9-next" = Right $ EPELNext 9
-eitherRelease ('e':'p':'e':'l':n) | all isDigit n = let br = EPEL (read n) in Right br
-eitherRelease ('e':'l':n) | all isDigit n = let r = read n in Right (EPEL r)
-eitherRelease ('c':n) | all isDigit n = let r = read n in Right (Centos r)
-eitherRelease ('C':n) | all isDigit n = let r = read n in Right (Centos r)
-eitherRelease "eln" = Right ELN
-eitherRelease ('f':ns) | all isDigit ns = let r = read ns in Right (Fedora r)
-eitherRelease ns | all isDigit ns = let r = read ns in
-                     Right $
-                     case compare r elnVersion of
-                       LT -> Centos r
-                       EQ -> ELN
-                       GT -> Fedora r
-eitherRelease cs = Left cs
+eitherRelease rel =
+  case lower rel of
+    "rawhide" -> Right Rawhide
+    -- FIXME add proper parsing:
+    "epel8-next" -> Right $ EPELNext 8
+    "epel9-next" -> Right $ EPELNext 9
+    ('e':'p':'e':'l':n@(_:_)) | all isDigit n -> let br = EPEL (read n)
+                                                 in Right br
+    ('c':n@(_:_)) | all isDigit n -> let r = read n in Right (Centos r)
+    "eln" -> Right ELN
+    ('f':n@(_:_)) | all isDigit n -> let r = read n in Right (Fedora r)
+    ns@(_:_) | all isDigit ns ->
+               let r = read ns in
+                 Right $
+                 case compare r elnVersion of
+                   LT -> Centos r
+                   EQ -> ELN
+                   GT -> Fedora r
+    _ -> Left rel
 
 instance Show Release where
   show Rawhide = "rawhide"
diff --git a/test/tests.hs b/test/tests.hs
--- a/test/tests.hs
+++ b/test/tests.hs
@@ -18,7 +18,7 @@
 
 -- copied from dl-fedora
 branched :: Int
-branched = 40
+branched = 41
 current, previous, prevprev, rawhide :: String
 current = show branched
 previous = show (branched - 1)
@@ -42,6 +42,7 @@
   ,(["epel9"], Just "ghc")
   ,(["c10"], Just "bash")
   ,(["c9"], Just "kernel")
+  ,(["rawhide", "--whatprovides"], Just "perl(Regexp::Pattern::License)")
   ]
 
 main :: IO ()
