packages feed

pagure-cli 0.2.1 → 0.2.2

raw patch · 4 files changed

+197/−111 lines, 4 filesdep +http-querydep +simple-cmddep ~pagure

Dependencies added: http-query, simple-cmd

Dependency ranges changed: pagure

Files

CHANGELOG.md view
@@ -1,5 +1,10 @@ # Changelog +## 0.2.2 (2024-05-06)+- new add group and groupinfo commands+- help: order commands with better grouping+- update to Haskell pagure-0.2.0+ ## 0.2.1 (2022-02-17) - new commands: 'project', 'issue', 'userinfo' - drop --url and use aeson-pretty
README.md view
@@ -5,97 +5,120 @@ [![Stackage Lts](http://stackage.org/package/pagure-cli/badge/lts)](http://stackage.org/lts/package/pagure-cli) [![Stackage Nightly](http://stackage.org/package/pagure-cli/badge/nightly)](http://stackage.org/nightly/package/pagure-cli) -A [pagure](https://docs.pagure.org/pagure/) client for querying-projects and users.+A [pagure](https://docs.pagure.org/pagure/) gitforge client for querying+and listing projects (repos), users, groups, and issues.  ## Usage By default it uses the [src.fedoraproject.org](https://src.fedoraproject.org/) Pagure server instance (aka Fedora dist-git), but this can be overriden by the `--server` option. -## List/search for repos+### List/search for repos +`$ pagure list rac\*`+ ```-$ pagure list emacs\*-emacs-:+rpms/raceintospace+rpms/racket ```+ Note by default 'orphan' owned packages are excluded.  One can also filter by owner or committer. -## List user's projects+### List user's projects  Count projects of a user:++`$ pagure user --server pagure.io --count mattdm`+ ```-$ pagure user -s pagure.io --count mattdm-93+120 ``` -## List groups:+### List groups:  ``` $ pagure groups : ``` -## More commands+### List group packages+`$ pagure group budgie-sig` -- `branches` lists the git branches of a repo+```+rpms/libxfce4windowing+rpms/sassc+rpms/wlrctl+``` -- `issues` to query and list issues+`$ pagure group -c rust-sig` -- `users` to list usernames of users+```+3093+``` -- `username` shows the fullname of a user+## Help -- `git-url` shows the git urls for a repo+`$ pagure --version` -## Help+```+0.2.2+``` -Use `--help` to get help on individual commands:+`$ pagure --help`  ```-$ pagure list --help-Usage: pagure list [-s|--server SERVER] [-c|--count] [(-j|--json) | (-y|--yaml)]-                   [(-F|--only-forks) | (-f|--include-forks)]-                   [-n|--namespace NAMESPACE]-                   [(-o|--owner OWNER) | (-u|--username USERNAME)] [PATTERN]-  list projects+Pagure client +Usage: pagure [--version] COMMAND++  Simple pagure CLI+ Available options:-  -s,--server SERVER       Pagure server-  -c,--count               Show number only-  -j,--json                Output JSON-  -y,--yaml                YAML output-  -F,--only-forks          Only list forks-  -f,--include-forks       Include forks [default: ignore forks]-  -n,--namespace NAMESPACE Specify project repo namespace-  -o,--owner OWNER         Projects with certain owner-  -u,--username USERNAME   Projects to which username can commit   -h,--help                Show this help text+  --version                Show version++Available commands:+  list                     list projects+  user                     list user repos+  group                    list group repos+  project                  show project details+  branches                 list project branches+  git-url                  show project repo's git urls+  issues                   list project issues+  issue                    show project issue+  users                    list users+  username                 fullname of user+  userinfo                 show user details+  groups                   list groups+  groupinfo                show group details ```+Use `--help` to get help on individual commands: + ## Installation+pagure-cli is packaged in Fedora and EPEL 9: <https://src.fedoraproject.org/rpms/pagure-cli> +## Build from source To build the latest release you will need cabal-install and ghc, or stack: -`stack install pagure-cli` or `cabal new-install pagure-cli`.--Or to build from the git source, run directly without the package name.--## Binaries+`stack install pagure-cli` or `cabal install pagure-cli`. -pagure-cli is packaged in Fedora (since F34).+Or to build from the git source, run the commands without the package name.  ## Contributions- Pagure rest API can be found on pagure servers: eg <https://pagure.io/api/0>. There are still many unsupported commands and options.-Please open a ticket or PR to request adding more.+Please open a ticket or PR to request adding more at+<https://github.com/juhp/pagure-cli>. -## Other clients+Also part of this client uses the simple+[pagure-hs](https://hackage.haskell.org/package/pagure) bindings.++## Other pagure clients After writing the initial version I discovered that Ricky Elrod (relrod) had made <https://github.com/fedora-infra/pagure-cli>. -I discovered a client in Rust <https://pagure.io/ironthree/bodhi-cli> by decathorpe.+There is a library client in Rust <https://pagure.io/ironthree/pagure-rs>+by decathorpe.
pagure-cli.cabal view
@@ -1,21 +1,23 @@ cabal-version:       1.18 name:                pagure-cli-version:             0.2.1-synopsis:            Pagure client-description:         A command-line Pagure client for querying projects and users.+version:             0.2.2+synopsis:            A Pagure gitforge query tool+description:         A command-line Pagure (gitforge) client for querying+                     and listing projects, users, groups, and issues. homepage:            https://github.com/juhp/pagure-cli bug-reports:         https://github.com/juhp/pagure-cli/issues license:             GPL-2 license-file:        LICENSE author:              Jens Petersen <juhpetersen@gmail.com> maintainer:          Jens Petersen <juhpetersen@gmail.com>-copyright:           2019-2020,2022 Jens Petersen+copyright:           2019-2020,2022,2024 Jens Petersen category:            Utility build-type:          Simple extra-doc-files:     README.md-                   , CHANGELOG.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 == 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  source-repository head   type:                git@@ -29,8 +31,10 @@                      , base < 5                      , bytestring                      , filepath+                     , http-query                      , optparse-applicative-                     , pagure >= 0.1.1+                     , pagure >= 0.2+                     , simple-cmd                      , simple-cmd-args >= 0.1.6                      , text                      , unordered-containers
src/Main.hs view
@@ -22,16 +22,13 @@ import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy.Char8 as BL import Data.Maybe-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,11,0))-#else-import Data.Semigroup ((<>))-#endif import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.IO as T import Data.Yaml (encode)+import Network.HTTP.Query ((+/+))+import SimpleCmd (error', (+-+)) import SimpleCmdArgs-import System.FilePath ((</>)) import Fedora.Pagure  import Paths_pagure_cli (version)@@ -41,27 +38,83 @@   simpleCmdArgs (Just version) "Pagure client" "Simple pagure CLI" $   subcommands   [ Subcommand "list" "list projects" $-    listProjects <$> serverOpt <*> countOpt <*> formatOpt <*> forksOpt <*> optional namespaceOpt <*> optional packagerOpt <*> optional (strArg "PATTERN")-  , Subcommand "user" "user repos" $-    userRepos <$> serverOpt <*> countOpt <*> switchWith 'f' "forks" "List user's forks" <*> strArg "USER"+    listProjects+    <$> serverOpt+    <*> countOpt+    <*> formatOpt+    <*> forksOpt+    <*> optional namespaceOpt+    <*> optional packagerOpt+    <*> optional (strArg "PATTERN")+  , Subcommand "user" "list user repos" $+    userRepos+    <$> serverOpt+    <*> countOpt+    <*> switchWith 'f' "forks" "List user's forks"+    <*> strArg "USER"+  , Subcommand "group" "list group repos" $+    groupProjects+    <$> serverOpt+    <*> switchWith 'c' "count" "Count projects"+    <*> strArg "GROUP"+  , Subcommand "project" "show project details" $+    projectInfo+    <$> serverOpt+    <*> formatOpt+    <*> strArg "PROJECT"   , Subcommand "branches" "list project branches" $-    repoBranches <$> serverOpt <*> formatOpt <*> strArg "REPO"+    repoBranches+    <$> serverOpt+    <*> formatOpt+    <*> strArg "REPO"+  , Subcommand "git-url" "show project repo's git urls" $+    gitUrl+    <$> serverOpt+    <*> formatOpt+    <*> strArg "REPO"   , Subcommand "issues" "list project issues" $-    projectIssues <$> serverOpt <*> countOpt <*> formatOpt <*> strArg "REPO" <*> switchWith 'A' "all" "list Open and Closed issues" <*> optional (strOptionWith 'a' "author" "AUTHOR" "Filter issues by creator") <*> optional (strOptionWith 'S' "since" "Y-M-D" "Filter issues updated after date") <*> optional (strOptionWith 't' "title" "pattern" "Filter issues by title")+    projectIssues+    <$> serverOpt+    <*> countOpt+    <*> formatOpt+    <*> strArg "REPO"+    <*> switchWith 'A' "all" "list Open and Closed issues"+    <*> optional (strOptionWith 'a' "author" "AUTHOR" "Filter issues by creator")+    <*> optional (strOptionWith 'S' "since" "Y-M-D" "Filter issues updated after date")+    <*> optional (strOptionWith 't' "title" "pattern" "Filter issues by title")+  , Subcommand "issue" "show project issue" $+    projectIssue+    <$> serverOpt+    <*> formatOpt+    <*> strArg "REPO"+    <*> argumentWith auto "ISSUE"   , Subcommand "users" "list users" $-    users <$> serverOpt <*> formatOpt <*> strArg "PATTERN"+    users+    <$> serverOpt+    <*> formatOpt+    <*> strArg "PATTERN"   , Subcommand "username" "fullname of user" $-    username <$> serverOpt <*> formatOpt <*> strArg "USERNAME"-  , Subcommand "groups" "list groups" $-    groups <$> serverOpt <*> countOpt <*> formatOpt <*> optional (strArg "PATTERN")-  , Subcommand "git-url" "show project repo's git urls" $-    gitUrl <$> serverOpt <*> formatOpt <*> strArg "REPO"-  , Subcommand "project" "show project details" $-    projectInfo <$> serverOpt <*> formatOpt <*> strArg "PROJECT"-  , Subcommand "issue" "show project issue" $-    projectIssue <$> serverOpt <*> formatOpt <*> strArg "REPO" <*> argumentWith auto "ISSUE"+    username+    <$> serverOpt+    <*> formatOpt+    <*> strArg "USERNAME"   , Subcommand "userinfo" "show user details" $-    userInfo <$> serverOpt <*> formatOpt <*> strArg "USERNAME"+    userInfo+    <$> serverOpt+    <*> formatOpt+    <*> strArg "USERNAME"+  , Subcommand "groups" "list groups" $+    groups+    <$> serverOpt+    <*> countOpt+    <*> formatOpt+    <*> optional (strArg "PATTERN")+  , Subcommand "groupinfo" "show group details" $+    groupInfo+    <$> serverOpt+    <*> switchWith 'p' "projects" "List projects"+    <*> formatOpt+    <*> strArg "GROUP"   ]   where     countOpt = switchWith 'c' "count" "Show number only"@@ -94,7 +147,7 @@     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 <- queryPaged server count path params ("pagination", "page")+  pages <- queryPagureCountPaged server count path params ("pagination", "page")   mapM_ (defaultPrinter format printPage) pages   where     -- (!orphan only works on pagure >=0.29)@@ -114,27 +167,21 @@           projects = lookupKey' "projects" result       (mapM_ T.putStrLn . mapMaybe (lookupKey key')) projects +-- FIXME duplicates subset of listProjects userRepos :: String -> Bool -> Bool -> String -> IO () userRepos server count forks user =   if count then do-    let path = "user" </> user+    let path = "user" +/+ user     mcnt <- queryPagureCount server path [] $             if forks then "forks_pagination" else "repos_pagination"     print $       fromMaybe-      (error' ("number of " ++ (if forks then "forks" else "repos") ++ " could not be determined"))+      (error' ("number of" +-+ (if forks then "forks" else "repos") +-+ "could not be determined"))       mcnt     else do     repos <- (if forks then pagureUserForks else pagureUserRepos) server user     mapM_ T.putStrLn repos --- maybeKey :: String -> Maybe String -> Query--- maybeKey _ Nothing = []--- maybeKey k mval = [(B.pack k, fmap B.pack mval)]---- makeKey :: String -> String -> Query--- makeKey k val = [(B.pack k, Just (B.pack val))]- boolKey :: String -> Bool -> String -> Query boolKey _ False _ = [] boolKey k True val = makeKey k val@@ -142,10 +189,10 @@ -- 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-  let path = repo </> "issues"-      params = [("status", Just "all") | allstatus] +++  let path = repo +/+ "issues"+      params = [makeItem "status" "all" | allstatus] ++                maybeKey "author" mauthor ++ maybeKey "since" msince-  pages <- queryPaged server count path params ("pagination", "page")+  pages <- queryPagureCountPaged server count path params ("pagination", "page")   mapM_ (defaultPrinter format printIssues) pages   where     printIssues :: Object -> IO ()@@ -160,7 +207,7 @@         Nothing -> putStrLn "parsing issue failed"         Just (id',title,status) ->           when (isNothing mpat || T.pack (fromJust mpat) `T.isInfixOf` title) $-          putStrLn $ "https://" <> server </> repo </> "issue" </> show id' <> " (" <> T.unpack status <> "): " <> T.unpack title+          putStrLn $ "https://" ++ server +/+ repo +/+ "issue" +/+ show id' +-+ "(" ++ T.unpack status ++ "):" +-+ T.unpack title      parseIssue :: Object -> Maybe (Integer, Text, Text)     parseIssue =@@ -170,24 +217,12 @@         status <- obj .: "status"         return (id',title,status) --- FIXME limit max number of pages (10?) or --pages-queryPaged :: String -> Bool -> String -> Query -> (String,String)-           -> IO [Object]-queryPaged server count path params (pagination,paging) =-  if count-    then do-    mnum <- queryPagureCount server path params pagination-    print $ fromMaybe (error' "pages not found") mnum-    return []-    else-    queryPagurePaged server path params (pagination,paging)- repoBranches :: String -> OutputFormat -> String -> IO () repoBranches server format repo = do   let namespace =         if server == srcFedoraprojectOrg && '/' `notElem` repo         then "rpms/" else ""-      path = namespace ++ repo </> "git/branches"+      path = namespace ++ repo +/+ "git/branches"   eres <- queryPagureSingle server path []   either error' (defaultPrinter format (printKeyList "branches")) eres @@ -200,9 +235,11 @@  username :: String -> OutputFormat -> String -> IO () username server format user = do-  let path = "user" </> user-  res <- queryPagure' server path $ makeKey "per_page" "1"-  defaultPrinter format printName res+  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   where     printName res =       case lookupKey "user" res >>= lookupKey "fullname" of@@ -213,7 +250,7 @@ groups server count format mpat = do   let path = "groups"       params = maybeKey "pattern" mpat-  pages <- queryPaged server count path params ("pagination", "page")+  pages <- queryPagureCountPaged server count path params ("pagination", "page")   mapM_ (defaultPrinter format (printKeyList "groups")) pages  printKeyList :: String -> Object -> IO ()@@ -225,7 +262,7 @@   let namespace =         if server == srcFedoraprojectOrg && '/' `notElem` repo         then "rpms/" else ""-      path = namespace ++ repo </> "git/urls"+      path = namespace ++ repo +/+ "git/urls"   res <- queryPagure server path []   defaultPrinter format printURLs res   where@@ -241,14 +278,6 @@ #endif     localLookupKey = lookupKey' . T.pack --- from simple-cmd-error' :: String -> a-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,9,0))-error' = errorWithoutStackTrace-#else-error' = error-#endif- yamlPrinter :: OutputFormat -> Object -> IO () yamlPrinter FormatDefault = yamlPrinter FormatYaml yamlPrinter FormatJson = BL.putStrLn . encodePretty@@ -272,3 +301,28 @@ userInfo server format user = do   eval <- pagureUserInfo server user []   either error' (yamlPrinter format) eval++groupInfo :: String -> Bool -> OutputFormat -> String -> IO ()+groupInfo server projects format group = do+  let params = [makeItem "projects" "1" | projects]+  eval <- pagureGroupInfo server group params+  either error' (yamlPrinter 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