pagure-cli 0.2.2 → 0.2.3
raw patch · 4 files changed
+123/−71 lines, 4 filesdep +extradep +vectordep ~pagure
Dependencies added: extra, vector
Dependency ranges changed: pagure
Files
- CHANGELOG.md +5/−0
- README.md +12/−5
- pagure-cli.cabal +7/−4
- src/Main.hs +99/−62
CHANGELOG.md view
@@ -1,5 +1,10 @@ # Changelog +## 0.2.3 (2026-02-11)+- hide output of empty lists and object by default (behind --show-empty)+- add 'contributors' command+- use pagureGroupRepos from pagure-0.2.1+ ## 0.2.2 (2024-05-06) - new add group and groupinfo commands - help: order commands with better grouping
README.md view
@@ -30,10 +30,10 @@ Count projects of a user: -`$ pagure user --server pagure.io --count mattdm`+`$ pagure user --server pagure.io --count jspaleta` ```-120+11 ``` ### List groups:@@ -47,7 +47,13 @@ `$ pagure group budgie-sig` ```+rpms/bluejay+rpms/budgie-desktop-services+rpms/budgie-display-configurator+rpms/gtklock+rpms/gtk-session-lock rpms/libxfce4windowing+rpms/pocillo-gtk-theme rpms/sassc rpms/wlrctl ```@@ -55,7 +61,7 @@ `$ pagure group -c rust-sig` ```-3093+4266 ``` ## Help@@ -63,7 +69,7 @@ `$ pagure --version` ```-0.2.2+0.2.3 ``` `$ pagure --help`@@ -86,6 +92,7 @@ project show project details branches list project branches git-url show project repo's git urls+ contributors show project repo's contributors issues list project issues issue show project issue users list users@@ -98,7 +105,7 @@ ## Installation-pagure-cli is packaged in Fedora and EPEL 9: <https://src.fedoraproject.org/rpms/pagure-cli>+pagure-cli is packaged in Fedora and EPEL: <https://src.fedoraproject.org/rpms/pagure-cli> ## Build from source To build the latest release you will need cabal-install and ghc, or stack:
pagure-cli.cabal view
@@ -1,6 +1,6 @@ cabal-version: 1.18 name: pagure-cli-version: 0.2.2+version: 0.2.3 synopsis: A Pagure gitforge query tool description: A command-line Pagure (gitforge) client for querying and listing projects, users, groups, and issues.@@ -10,14 +10,15 @@ license-file: LICENSE author: Jens Petersen <juhpetersen@gmail.com> maintainer: Jens Petersen <juhpetersen@gmail.com>-copyright: 2019-2020,2022,2024 Jens Petersen+copyright: 2019-2020,2022,2024-2026 Jens Petersen category: Utility build-type: Simple extra-doc-files: README.md CHANGELOG.md tested-with: GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5, GHC == 8.8.4, GHC == 8.10.4, GHC == 9.0.2, GHC == 9.2.8,- GHC == 9.4.8, GHC == 9.6.5, GHC == 9.8.2+ GHC == 9.4.8, GHC == 9.6.6, GHC == 9.8.4, GHC == 9.10.3,+ GHC == 9.12.3 source-repository head type: git@@ -30,14 +31,16 @@ , aeson-pretty , base < 5 , bytestring+ , extra , filepath , http-query , optparse-applicative- , pagure >= 0.2+ , pagure >= 0.2.1 , simple-cmd , simple-cmd-args >= 0.1.6 , text , unordered-containers+ , vector , yaml if impl(ghc<8.0)
src/Main.hs view
@@ -11,7 +11,7 @@ (<|>) #endif )-import Control.Monad (unless, when)+import Control.Monad.Extra (unless, when, whenJust) import Data.Aeson.Encode.Pretty (encodePretty) import Data.Aeson.Types #if MIN_VERSION_aeson(2,0,0)@@ -25,6 +25,7 @@ import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.IO as T+import qualified Data.Vector as V import Data.Yaml (encode) import Network.HTTP.Query ((+/+)) import SimpleCmd (error', (+-+))@@ -41,6 +42,7 @@ listProjects <$> serverOpt <*> countOpt+ <*> nohideOpt <*> formatOpt <*> forksOpt <*> optional namespaceOpt@@ -60,22 +62,32 @@ , Subcommand "project" "show project details" $ projectInfo <$> serverOpt+ <*> nohideOpt <*> formatOpt <*> strArg "PROJECT" , Subcommand "branches" "list project branches" $ repoBranches <$> serverOpt+ <*> nohideOpt <*> formatOpt <*> strArg "REPO" , Subcommand "git-url" "show project repo's git urls" $ gitUrl <$> serverOpt+ <*> nohideOpt <*> formatOpt <*> strArg "REPO"+ , Subcommand "contributors" "show project repo's contributors" $+ contributors+ <$> serverOpt+ <*> nohideOpt+ <*> formatOpt+ <*> strArg "REPO" , Subcommand "issues" "list project issues" $ projectIssues <$> serverOpt <*> countOpt+ <*> nohideOpt <*> formatOpt <*> strArg "REPO" <*> switchWith 'A' "all" "list Open and Closed issues"@@ -85,39 +97,46 @@ , Subcommand "issue" "show project issue" $ projectIssue <$> serverOpt+ <*> nohideOpt <*> formatOpt <*> strArg "REPO" <*> argumentWith auto "ISSUE" , Subcommand "users" "list users" $ users <$> serverOpt+ <*> nohideOpt <*> formatOpt <*> strArg "PATTERN" , Subcommand "username" "fullname of user" $ username <$> serverOpt+ <*> nohideOpt <*> formatOpt <*> strArg "USERNAME" , Subcommand "userinfo" "show user details" $ userInfo <$> serverOpt+ <*> nohideOpt <*> formatOpt <*> strArg "USERNAME" , Subcommand "groups" "list groups" $ groups <$> serverOpt <*> countOpt+ <*> nohideOpt <*> formatOpt <*> optional (strArg "PATTERN") , Subcommand "groupinfo" "show group details" $ groupInfo <$> serverOpt <*> switchWith 'p' "projects" "List projects"+ <*> nohideOpt <*> formatOpt <*> strArg "GROUP" ] where countOpt = switchWith 'c' "count" "Show number only"+ nohideOpt = switchWith 'e' "show-empty" "Display empty lists and objects" formatOpt = flagWith' FormatJson 'j' "json" "Output JSON" <|> flagWith FormatDefault FormatYaml 'y' "yaml" "YAML output" namespaceOpt = strOptionWith 'n' "namespace" "NAMESPACE" "Specify project repo namespace" packagerOpt = Owner <$> ownerOpt <|> Committer <$> usernameOpt@@ -136,19 +155,20 @@ srcFedoraprojectOrg :: String srcFedoraprojectOrg = "src.fedoraproject.org" -defaultPrinter :: OutputFormat -> (Object -> IO ()) -> Object -> IO ()-defaultPrinter FormatDefault pr = pr-defaultPrinter FormatJson _ = BL.putStrLn . encodePretty-defaultPrinter FormatYaml _ = B.putStrLn . encode+defaultPrinter :: Bool -> OutputFormat -> (Object -> IO ()) -> Object -> IO ()+defaultPrinter _ FormatDefault pr = pr+defaultPrinter nohide fmt _ = yamlPrinter nohide fmt -listProjects :: String -> Bool -> OutputFormat -> Forks -> Maybe String -> Maybe Packager -> Maybe String -> IO ()-listProjects server count format forks mnamespace mpackager mpattern = do+listProjects :: String -> Bool -> Bool -> OutputFormat -> Forks -> Maybe String+ -> Maybe Packager -> Maybe String -> IO ()+listProjects server count nohide format forks mnamespace mpackager mpattern = do unless (count || isJust mpackager || isJust mpattern) $ error' "Please give a package pattern, --count, or --owner/--username" let path = "projects" params = makeKey "short" "1" ++ fork ++ packager ++ maybeKey "namespace" mnamespace ++ maybeKey "pattern" mpattern pages <- queryPagureCountPaged server count path params ("pagination", "page")- mapM_ (defaultPrinter format printPage) pages+ let projects = concatMap (lookupKey' "projects") pages+ mapM_ (defaultPrinter nohide format printProject) projects where -- (!orphan only works on pagure >=0.29) packager = case mpackager of@@ -161,11 +181,10 @@ IncludeForks -> [] OnlyForks -> makeKey "fork" "1" - printPage :: Object -> IO ()- printPage result = do+ printProject :: Object -> IO ()+ printProject project = do let key' = if isJust mnamespace then "name" else "fullname"- projects = lookupKey' "projects" result- (mapM_ T.putStrLn . mapMaybe (lookupKey key')) projects+ whenJust (lookupKey key' project) T.putStrLn -- FIXME duplicates subset of listProjects userRepos :: String -> Bool -> Bool -> String -> IO ()@@ -187,13 +206,14 @@ boolKey k True val = makeKey k val -- FIXME limit max number of issues-projectIssues :: String -> Bool -> OutputFormat -> String -> Bool -> Maybe String -> Maybe String -> Maybe String -> IO ()-projectIssues server count format repo allstatus mauthor msince mpat = do+projectIssues :: String -> Bool -> Bool -> OutputFormat -> String -> Bool+ -> Maybe String -> Maybe String -> Maybe String -> IO ()+projectIssues server count nohide format repo allstatus mauthor msince mpat = do let path = repo +/+ "issues" params = [makeItem "status" "all" | allstatus] ++ maybeKey "author" mauthor ++ maybeKey "since" msince pages <- queryPagureCountPaged server count path params ("pagination", "page")- mapM_ (defaultPrinter format printIssues) pages+ mapM_ (defaultPrinter nohide format printIssues) pages where printIssues :: Object -> IO () printIssues result = do@@ -217,54 +237,54 @@ status <- obj .: "status" return (id',title,status) -repoBranches :: String -> OutputFormat -> String -> IO ()-repoBranches server format repo = do+repoBranches :: String -> Bool -> OutputFormat -> String -> IO ()+repoBranches server nohide format repo = do let namespace = if server == srcFedoraprojectOrg && '/' `notElem` repo then "rpms/" else "" path = namespace ++ repo +/+ "git/branches" eres <- queryPagureSingle server path []- either error' (defaultPrinter format (printKeyList "branches")) eres+ either error' (defaultPrinter nohide format (printKeyList "branches")) eres -users :: String -> OutputFormat -> String -> IO ()-users server format pat = do+users :: String -> Bool -> OutputFormat -> String -> IO ()+users server nohide format pat = do let path = "users" params = makeKey "pattern" pat res <- queryPagure server path params- defaultPrinter format (printKeyList "users") res+ defaultPrinter nohide format (printKeyList "users") res -username :: String -> OutputFormat -> String -> IO ()-username server format user = do+username :: String -> Bool -> OutputFormat -> String -> IO ()+username server nohide format user = do let path = "user" +/+ user eres <- queryPagureSingle server path $ makeKey "per_page" "1" case eres of Left err -> error' err- Right res -> defaultPrinter format printName res+ Right res -> defaultPrinter nohide format printName res where printName res = case lookupKey "user" res >>= lookupKey "fullname" of Nothing -> error' "User fullname not found" Just fn -> T.putStrLn fn -groups :: String -> Bool -> OutputFormat -> Maybe String -> IO ()-groups server count format mpat = do+groups :: String -> Bool -> Bool -> OutputFormat -> Maybe String -> IO ()+groups server count nohide format mpat = do let path = "groups" params = maybeKey "pattern" mpat pages <- queryPagureCountPaged server count path params ("pagination", "page")- mapM_ (defaultPrinter format (printKeyList "groups")) pages+ mapM_ (defaultPrinter nohide format (printKeyList "groups")) pages printKeyList :: String -> Object -> IO () printKeyList key' res = mapM_ T.putStrLn (lookupKey' (T.pack key') res :: [Text]) -gitUrl :: String -> OutputFormat -> String -> IO ()-gitUrl server format repo = do+gitUrl :: String -> Bool -> OutputFormat -> String -> IO ()+gitUrl server nohide format repo = do let namespace = if server == srcFedoraprojectOrg && '/' `notElem` repo then "rpms/" else "" path = namespace ++ repo +/+ "git/urls" res <- queryPagure server path []- defaultPrinter format printURLs res+ defaultPrinter nohide format printURLs res where printURLs result = mapM_ T.putStrLn $@@ -278,51 +298,68 @@ #endif localLookupKey = lookupKey' . T.pack -yamlPrinter :: OutputFormat -> Object -> IO ()-yamlPrinter FormatDefault = yamlPrinter FormatYaml-yamlPrinter FormatJson = BL.putStrLn . encodePretty-yamlPrinter FormatYaml = B.putStrLn . encode+contributors :: String -> Bool -> OutputFormat -> String -> IO ()+contributors server nohide format repo = do+ let namespace =+ if server == srcFedoraprojectOrg && '/' `notElem` repo+ then "rpms/" else ""+ path = namespace ++ repo +/+ "contributors"+ res <- queryPagure server path []+ yamlPrinter nohide format res -projectInfo :: String -> OutputFormat -> String -> IO ()-projectInfo server format repo = do+yamlPrinter :: Bool -> OutputFormat -> Object -> IO ()+yamlPrinter nohide format =+ case format of+ FormatDefault -> yamlPrinter nohide FormatYaml+ FormatJson -> BL.putStrLn . encodePretty . hideEmpty+ FormatYaml -> B.putStrLn . encode . hideEmpty+ where+ hideEmpty = if nohide then id else cleanObject++cleanObject :: Object -> Object+cleanObject = M.mapMaybe go+ where+ go :: Value -> Maybe Value+ -- drop empty lists+ go (Array v) | V.null v = Nothing+ | otherwise = Just $ Array (V.map (wrap go) v)+ where+ wrap f (Object o) = Object (M.mapMaybe f o)+ wrap f (Array a) = Array (V.map (wrap f) a)+ wrap _ x = x+ -- drop empty objects+ go (Object o) =+ let cleaned = M.mapMaybe go o+ in if M.null cleaned then Nothing else Just (Object cleaned)+ go other = Just other++projectInfo :: String -> Bool -> OutputFormat -> String -> IO ()+projectInfo server nohide format repo = do let namespace = if server == srcFedoraprojectOrg && '/' `notElem` repo then "rpms/" else "" path = namespace ++ repo eval <- pagureProjectInfo server path- either error' (yamlPrinter format) eval+ either error' (yamlPrinter nohide format) eval -projectIssue :: String -> OutputFormat -> String -> Int -> IO ()-projectIssue server format repo issue = do+projectIssue :: String -> Bool -> OutputFormat -> String -> Int -> IO ()+projectIssue server nohide format repo issue = do eval <- pagureProjectIssueInfo server repo issue- either error' (yamlPrinter format) eval+ either error' (yamlPrinter nohide format) eval -userInfo :: String -> OutputFormat -> String -> IO ()-userInfo server format user = do+userInfo :: String -> Bool -> OutputFormat -> String -> IO ()+userInfo server nohide format user = do eval <- pagureUserInfo server user []- either error' (yamlPrinter format) eval+ either error' (yamlPrinter nohide format) eval -groupInfo :: String -> Bool -> OutputFormat -> String -> IO ()-groupInfo server projects format group = do+groupInfo :: String -> Bool -> Bool -> OutputFormat -> String -> IO ()+groupInfo server projects nohide format group = do let params = [makeItem "projects" "1" | projects] eval <- pagureGroupInfo server group params- either error' (yamlPrinter format) eval+ either error' (yamlPrinter nohide format) eval -- FIXME support acl parameter (admin, commit or ticket) groupProjects :: String -> Bool -> String -> IO ()-groupProjects server count group = do- let path = "group" +/+ group- params = makeKey "projects" "1"- pages <- queryPagureCountPaged server count path params ("pagination", "page")- mapM_ (defaultPrinter FormatDefault printPage) pages- where- -- acl- -- packager = case mpackager of- -- Nothing -> boolKey "owner" (server == srcFedoraprojectOrg) "!orphan"- -- Just (Owner o) -> makeKey "owner" o- -- Just (Committer c) -> makeKey "username" c-- printPage :: Object -> IO ()- printPage result = do- let projects = lookupKey' "projects" result- (mapM_ T.putStrLn . mapMaybe (lookupKey "fullname")) projects+groupProjects server count group =+ pagureGroupRepos server count group >>=+ mapM_ T.putStrLn