packages feed

koji-install 0.2.0 → 0.3

raw patch · 5 files changed

+112/−67 lines, 5 filesdep +http-commondep −optparse-applicative

Dependencies added: http-common

Dependencies removed: optparse-applicative

Files

ChangeLog.md view
@@ -1,5 +1,10 @@ # Release history for koji-install +## 0.3 (2021-12-03)+- add `--list` command to list recent builds+- fix bug in generating kojifiles url from short name+- workarounds for rpmfusion's older koji not supporting patterns+ ## 0.2.0 (2021-12-03) - initial Hackage release - `--hub` to select hub
README.md view
@@ -13,33 +13,32 @@ Will download the latest build for your Fedora version, and try to install it. -You can specify a different hub using `--hub`.+You can specify a different Koji hub service with `--hub`.  ### Selecting subpackages -By default only installed subpackages are and downloaded and updated,+By default only installed subpackages are downloaded and updated, but the following options change the behavior:  `--all`: install all subpackages  `--ask`: ask about each subpackage -`--base-only`: only install base package+`--base-only`: only install the base package  `--exclude-devel`: skip devel subpackages  ### Help ```shellsession-$ koji-install-Install latest build from Koji+$ koji-install --help+Download and install latest package build from Koji tag.  Usage: koji-install [--version] [-n|--dry-run] [-D|--debug] [-H|--hub HUB]                     [-P|--packages-url URL]-                    [(-a|--all) | (-A|--ask) | (-b|--base-only) |+                    [(-l|--list) | (-a|--all) | (-A|--ask) | (-b|--base-only) |                       (-D|--exclude-devel)] [-d|--disttag DISTTAG]                     [(-R|--nvr) | (-V|--nv)] PACKAGE-  Download and install latest package build from Koji tag.-  HUB = fedora, stream, mbox, rpmfusion, URL+  HUB = fedora, stream, rpmfusion, or URL  Available options:   -h,--help                Show this help text@@ -48,6 +47,7 @@   -D,--debug               More detailed output   -H,--hub HUB             KojiHub shortname or url [default: fedora]   -P,--packages-url URL    KojiFiles packages url [default: fedora]+  -l,--list                List builds   -a,--all                 all subpackages   -A,--ask                 ask for each subpackge   -b,--base-only           only base package
koji-install.cabal view
@@ -1,10 +1,10 @@ name:                koji-install-version:             0.2.0+version:             0.3 synopsis:            CLI tool for installing rpms directly from Fedora Koji description:         koji-install can install the latest koji build of a package locally.-        By default it only downloads newer binaries of the subpackages-        already installed, but there are options to override that.+        By default it only downloads newer binaries of already-installed+        subpackages, but there are options to override that. license:             BSD3 license-file:        LICENSE author:              Jens Petersen <juhpetersen@gmail.com>@@ -37,11 +37,12 @@                        extra,                        filepath,                        koji >= 0.0.2,-                       optparse-applicative,                        rpm-nvr,                        simple-cmd,                        simple-cmd-args,                        xdg-userdirs+  if impl(ghc<8.4)+       build-depends: http-common < 0.8.3.4   default-language:    Haskell2010   ghc-options:         -Wall -threaded   if impl(ghc >= 8.0)
src/Main.hs view
@@ -9,8 +9,6 @@ import Data.RPM import Distribution.Koji import qualified Distribution.Koji.API as Koji-import Options.Applicative (fullDesc, header, progDescDoc)-import qualified Options.Applicative.Help.Pretty as P import SimpleCmd import SimpleCmdArgs import System.Directory@@ -20,9 +18,15 @@ import DownloadDir import Paths_koji_install (version) +-- FIXME use subtype for listing vs installation+data Mode = List | InstMode InstallMode+  deriving Eq+ data InstallMode = Update | All | Ask | Base | NoDevel+  deriving Eq  data Request = ReqName | ReqNV | ReqNVR+  deriving Eq  -- FIXME --include devel, --exclude * -- FIXME specify tag or task@@ -33,13 +37,12 @@  main :: IO () main = do-  sysdisttag <- cmd "rpm" ["--eval", "%{dist}"]-  let pdoc = Just $ P.vcat-             [ P.text "Download and install latest package build from Koji tag.",-               P.text ("HUB = " <> intercalate ", " knownHubs)-             ]-  simpleCmdArgsWithMods (Just Paths_koji_install.version)-    (fullDesc <> header "Install latest build from Koji" <> progDescDoc pdoc) $+  sysdisttag <- do+    dist <- cmd "rpm" ["--eval", "%{dist}"]+    return $ if dist == "%{dist}" then "" else dist+  simpleCmdArgs (Just Paths_koji_install.version)+    "Download and install latest package build from Koji tag."+    ("HUB = " ++ intercalate ", " knownHubs) $     program     <$> switchWith 'n' "dry-run" "Don't actually download anything"     <*> switchWith 'D' "debug" "More detailed output"@@ -53,13 +56,15 @@          <|> flagWith ReqName ReqNVR 'V' "nv" "Give an N-V instead of package name")     <*> some (strArg "PACKAGE")   where-    modeOpt :: Parser InstallMode+    modeOpt :: Parser Mode     modeOpt =-      flagWith' All 'a' "all" "all subpackages" <|>+      flagWith' List 'l' "list" "List builds" <|>+      InstMode <$>+      (flagWith' All 'a' "all" "all subpackages" <|>       flagWith' Ask 'A' "ask" "ask for each subpackge" <|>       flagWith' Base 'b' "base-only" "only base package" <|>       flagWith' NoDevel 'D' "exclude-devel" "Skip devel packages" <|>-      pure Update+      pure Update)      disttagOpt :: String -> Parser String     disttagOpt disttag = startingDot <$> strOptionalWith 'd' "disttag" "DISTTAG" ("Use a different disttag [default: " ++ disttag ++ "]") disttag@@ -69,14 +74,15 @@         "" -> error' "empty disttag"         (c:_) -> if c == '.' then cs else '.' : cs +-- mbox kojihub is locked knownHubs :: [String]-knownHubs = ["fedora","stream","mbox","rpmfusion", "URL"]+knownHubs = ["fedora","stream","rpmfusion", "or URL"]  hubURL :: String -> String hubURL "fedora" = fedoraKojiHub -- later use centosKojiHub hubURL "stream" = "https://kojihub.stream.centos.org/kojihub"-hubURL "mbox" = "https://koji.mbox.centos.org/kojihub"+--hubURL "mbox" = "https://koji.mbox.centos.org/kojihub" hubURL "rpmfusion" = "https://koji.rpmfusion.org/kojihub" hubURL "fusion" = "https://koji.rpmfusion.org/kojihub" hubURL hub =@@ -84,23 +90,23 @@   then hub   else error' $ "unknown hub: try " ++ show knownHubs -defaultPkgsURL :: Maybe String -> String-defaultPkgsURL Nothing =-  "https://kojipkgs.fedoraproject.org/packages"-defaultPkgsURL (Just url) =-  case url of+defaultPkgsURL :: String -> String+defaultPkgsURL url =+  case dropSuffix "/" url of+    "https://koji.fedoraproject.org/kojihub" ->+      "https://kojipkgs.fedoraproject.org/packages"     "https://kojihub.stream.centos.org/kojihub" ->       "https://kojihub.stream.centos.org/kojifiles/packages"     _ ->       if "kojihub" `isSuffixOf` url       then replace "kojihub" "kojifiles" url-      else error' "use --files-url to specify kojifiles url for this kojihub"+      else error' $ "use --files-url to specify kojifiles url for " ++ url -program :: Bool -> Bool -> Maybe String -> Maybe String -> InstallMode+program :: Bool -> Bool -> Maybe String -> Maybe String -> Mode         -> String -> Request -> [String] -> IO () program dryrun debug mhuburl mpkgsurl mode disttag request pkgs = do   let huburl = maybe fedoraKojiHub hubURL mhuburl-      pkgsurl = fromMaybe (defaultPkgsURL mhuburl) mpkgsurl+      pkgsurl = fromMaybe (defaultPkgsURL huburl) mpkgsurl   when debug $ do     putStrLn huburl     putStrLn pkgsurl@@ -109,22 +115,29 @@   when debug $ putStrLn dlDir   setNoBuffering   mapM (kojiLatestRPMs huburl pkgsurl dlDir) pkgs-    >>= installRPMs dryrun . mconcat+    >>= case mode of+          List -> mapM_ putStrLn . mconcat+          _ -> installRPMs dryrun . mconcat   where     kojiLatestRPMs :: String -> String -> String -> String -> IO [String]     kojiLatestRPMs huburl pkgsurl dlDir pkg = do-      mnvr <- kojiLatestOSBuild huburl disttag request pkg-      case mnvr of-        Nothing -> error' $ "latest " ++ pkg ++ " not found"-        Just nvr -> do-          putStrLn $ nvr ++ "\n"-          allRpms <- map (<.> "rpm") . sort . filter (not . debugPkg) <$> kojiGetBuildRPMs huburl nvr-          dlRpms <- decideRpms mode allRpms-          unless (dryrun || null dlRpms) $ do-            mapM_ (downloadRpm pkgsurl (readNVR nvr)) dlRpms-            -- FIXME once we check file size - can skip if no downloads-            putStrLn $ "Packages downloaded to " ++ dlDir-          return dlRpms+      nvrs <- kojiLatestOSBuilds debug huburl (mode == List) disttag request pkg+      case mode of+        List -> return nvrs+        InstMode instmode ->+          case nvrs of+            [] -> error' $ "latest " ++ pkg ++ " not found for " ++ disttag+            [nvr] -> do+              putStrLn $ nvr ++ "\n"+              allRpms <- map (<.> "rpm") . sort . filter (not . debugPkg) <$> kojiGetBuildRPMs huburl nvr+              dlRpms <- decideRpms instmode allRpms+              unless (dryrun || null dlRpms) $ do+                mapM_ (downloadRpm pkgsurl (readNVR nvr)) dlRpms+                -- FIXME once we check file size - can skip if no downloads+                putStrLn $ "Packages downloaded to " ++ dlDir+              return dlRpms+            _ -> error $ "multiple latest build founds for " ++ pkg ++ ": " +++                 unwords nvrs       where         decideRpms :: InstallMode -> [String] -> IO [String]         decideRpms mode' allRpms =@@ -155,23 +168,39 @@     debugPkg :: String -> Bool     debugPkg p = "-debuginfo-" `isInfixOf` p || "-debugsource-" `isInfixOf` p -kojiLatestOSBuild :: String -> String -> Request -> String -> IO (Maybe String)-kojiLatestOSBuild hub disttag request pkgpat = do+kojiLatestOSBuilds :: Bool -> String -> Bool -> String -> Request -> String+                  -> IO [String]+kojiLatestOSBuilds debug hub listmode disttag request pkgpat = do   let (pkg,full) = packageOfPattern pkgpat+      oldkoji = "rpmfusion" `isInfixOf` hub+  when (oldkoji && ("*" `isInfixOf` pkgpat || request /= ReqName)) $+    error' "cannot use pattern with this kojihub"   mpkgid <- Koji.getPackageID hub pkg   case mpkgid of     Nothing -> error $ "package not found: " ++ pkg     Just pkgid -> do-      let opts = [("packageID", ValueInt pkgid),+      -- strictly should getAPIVersion+      let opts = (if oldkoji+                  then id+                  else (("pattern", ValueString (if full then pkgpat else dropSuffix "*" pkgpat ++ "*" ++ disttag ++ "*")) :))+                 [("packageID", ValueInt pkgid),                   ("state", ValueInt (fromEnum BuildComplete)),-                  ("queryOpts",ValueStruct [("limit",ValueInt 1),-                                            ("order",ValueString "-build_id")])]-      res <- Koji.listBuilds hub $-             ("pattern", ValueString (if full then pkgpat else dropSuffix "*" pkgpat ++ "*" ++ disttag)) : opts-      case res of-        [] -> return Nothing-        [bld] -> return $ lookupStruct "nvr" bld-        _ -> error $ "more than one latest build found for " ++ pkg+                  ("queryOpts",ValueStruct+                    [("limit",ValueInt $ if listmode || oldkoji then 10 else 1),+                     ("order",ValueString "-build_id")])]+      when debug $ print opts+      nvrs <- mapMaybe (lookupStruct "nvr") <$> Koji.listBuilds hub opts+      if null nvrs+        then error' $ "no builds found for " ++ disttag+        else+        return $+        if oldkoji+        then case filter (disttag `isInfixOf`) nvrs of+               [] -> error' $ "no builds found for " ++ disttag+               [res] -> [res]+               rs@(r:_) ->+                 if listmode then rs else [r]+        else nvrs   where     packageOfPattern :: String -> (String, Bool)     packageOfPattern pat =
test/tests.hs view
@@ -3,18 +3,28 @@  program :: [String] -> IO () program args =-  putStrLn "" >> cmdLog "koji-install" ("-n" : "-b" : args)+  putStrLn "" >>+  cmdLog "koji-install" ("-n" : args) -tests :: [[String]]-tests =-  [["podman"]-  ,["-H", "https://kojihub.stream.centos.org/kojihub", "-d", "el9", "bash"]-  ,["-H", "stream", "-d", "el9", "kernel"]---  ,["-H", "rpmfusion", "ffmpeg"]+tests :: Bool -> [[String]]+tests havedist =+  [["-b", "podman"] ++ sysdist+  ,["-l", "coreutils"] ++ sysdist+  ,["-b", "-H", "https://kojihub.stream.centos.org/kojihub", "-d", "el9", "bash"]+  ,["-b", "-H", "stream", "-d", "el9", "kernel"]+  ,["-l", "-H", "stream", "-d", "el9", "grep"]+  ,["-b", "-H", "rpmfusion", "ffmpeg"] ++ sysdist+  ,["-l", "-H", "rpmfusion", "ffmpeg"] ++ sysdist   ]+  where+    sysdist = if havedist then [] else ["-d", "fc35"]  main :: IO () main = do   hSetBuffering stdout NoBuffering-  mapM_ program tests-  putStrLn $ show (length tests) ++ " tests run"+  havedist <- do+    dist <- cmd "rpm" ["--eval", "%{dist}"]+    return $ dist /= "%{dist}"+  let cases = tests havedist+  mapM_ program cases+  putStrLn $ show (length cases) ++ " tests run"