From 162e1584da8dacc22de8ef7935e66b96bb47f214 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 17 Jul 2023 22:22:20 +0200 Subject: [PATCH 001/236] Start tutorial --- docs/gcli-tutorial.md | 246 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 docs/gcli-tutorial.md diff --git a/docs/gcli-tutorial.md b/docs/gcli-tutorial.md new file mode 100644 index 00000000..db5b5b06 --- /dev/null +++ b/docs/gcli-tutorial.md @@ -0,0 +1,246 @@ +# GCLI Tutorial + +This document is aimed at those who are new to gcli and want get +started using it. + +## Installation + +### Through package manager + +If you're on FreeBSD you can just install gcli by running the +following command: + + # pkg install gcli + +### Compile the source code + +Other operating systems currently require manual compilation and +installation. + +For this purpose go to +[https://herrhotzenplotz.de/gcli/releases](https://herrhotzenplotz.de/gcli/releases) +and choose the latest release. Then download one of the tarballs. + +For version 1.1.0 this would be: + +https://herrhotzenplotz.de/gcli/releases/gcli-1.1.0/gcli-1.1.0.tar.xz + +Now that you have a link, you can download it, extract it, compile the +code and install it: + + $ mkdir ~/build + $ cd ~/build + $ curl -4LO https://herrhotzenplotz.de/gcli/releases/gcli-1.1.0/gcli-1.1.0.tar.xz + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 100 342k 100 342k 0 0 2739k 0 --:--:-- --:--:-- --:--:-- 2736k + $ ls + gcli-1.1.0.tar.xz + $ + +Install the dependencies for building gcli: + +e.g. on Debian systems: + + # apt install libcurl4-openssl-dev pkgconf build-essential + +Extract the tarball: + + $ tar xf gcli-1.1.0.tar.xz + $ cd gcli-1.1.0 + +Configure, build and install gcli: + + $ ./configure --prefix=${HOME}/.local + ... + $ make + ... + $ make install + +Now put the gcli executable into your PATH variable to allow the shell +to easily find it: + + $ PATH=${PATH}:${HOME}/.local/bin + $ export PATH + +You can put the above commands into your shell initialisation file, e.g.: + + $ echo 'PATH=${PATH}:${HOME}/.local/bin; export PATH' >> ~/.shrc + +Check that the shell finds gcli: + + $ which gcli + /usr/home/nico/.local/bin/gcli + $ + $ gcli version + gcli 1.1.0 (amd64-unknown-freebsd13.2) + Using libcurl/8.1.2 OpenSSL/1.1.1t zlib/1.2.13 libpsl/0.21.2 (+libidn2/2.3.4) libssh2/1.11.0 nghttp2/1.53.0 + Using vendored pdjson library + Report bugs at https://gitlab.com/herrhotzenplotz/gcli/. + Copyright 2021, 2022, 2023 Nico Sonack and contributors. + $ + +Furthermore I recommend setting the `MANPATH` variable so that you can +easily read the installed manual pages: + + $ MANPATH=:${HOME}/.local/share/man; export MANPATH + +You can also put this into your shell initialisation file. + +## First steps + +### Issues + +Let's start off by listing some issues - here for the curl project +which is hosted on GitHub under curl/curl. To list issues for it one +would run: + + $ gcli -t github issues -o curl -r curl + +You will see the list of the 30 most recent open issue tickets. The +command above does the following: + + - invoke gcli + - as a global option we switch it into Github-Mode + - invoke the issues subcommand + - operate on the repository owner curl (`-o curl`) + - operate on the repository curl (`-r curl`) + +Note that the `-t github` option goes before the issues subcommand +because it is a global option for gcli that affects how all the +following things like subcommands operate. + +However, now I also want to see closed issues: + + $ gcli -t github issues -o curl -r curl -a + +The `-a` option will disregard the status of the issue. + +Oh and the screen is a bit cluttered by all these tickets - let's only +fetch the first 10 issues: + + $ gcli -t github issues -o curl -r curl -n10 + +#### Details about issues + +As of now we only produced lists of issues. However, we may also want +to look at the details of an issue such as: + + - the original post + - labels + - comments + - assignees of the issue (that is someone who is working on the bug) + +Let's get a good summary of issue `#11268` in the curl project: + + $ gcli -t github issues -o curl -r curl -i 11268 all + +As you can see most of the options are the same, however now we tell +gcli with the `-i 11268` option that we want to work with a single +issue. Then we tell gcli what actions to perform on the issue. Another +important action is `comments`. Guess what it does: + + $ gcli -t github issues -o curl -r curl -i 11268 comments + +I know a person that likes to post long verbose traces. Let's search +for an issue authored by them on the OpenSSL GitHub page: + + $ gcli -t github issues -o openssl -r openssl -A blastwave -a + NUMBER STATE TITLE + 20379 open test "80-test_ssl_new.t" fails on Solaris 10 SPARCv9 + 10547 open Strict C90 CFLAGS results in sha.h:91 ISO C90 does not support long long + 8048 closed OPENSSL_strnlen SIGSEGV in o_str.c line 76 + $ + +The `-A` option lets you filter for specific authors. + +Let's look at the issue state of `#10547`: + + $ gcli -t github issues -o openssl -r openssl -i 10547 status + NAME : 10547 + TITLE : Strict C90 CFLAGS results in sha.h:91 ISO C90 does not support long long + CREATED : 2019-12-01T04:35:23Z + AUTHOR : blastwave + STATE : open + COMMENTS : 9 + LOCKED : no + LABELS : triaged: bug + ASSIGNEES : none + $ + +That's nine comments - let's read the original post and the comments +in our favourite pager `less`: + + $ gcli -t github issues -o openssl -r openssl -i 10547 op comments | less + +As you can see gcli will accept multiple actions for an issue and +executes them sequentially. + +#### Further reading + +You can list all available options for the issues subcommand by doing: + + $ gcli issues --help + +With your current knowledge you can also explore the `gcli pulls` subcommand. + +Furthermore I recommend reading into the manual page `gcli-issues(1)` +and `gcli-pulls(1)`: + + $ man gcli-issues + $ man gcli-pulls + +### Creating issues + +Creating issues on Github requires an account which we need to +generate an authentication token for gcli. + +Log into your GitHub account and click on your account icon in the top +right corner. Then choose the `Settings` option. Scroll down and +choose `Developer settings` on the bottom of the left column. Under +`Personal access tokens` choose `Tokens (classic)`. + +Click on `Generate new token (classic)`. + +Set a useful name such as `gcli` in the Note field, set the expiration +to `No expiration` and allow the following `Scopes`: + + - `repo` + - `workflow` + - `admin:public_key` + - `gist` + +Then create the token. It'll be printed in green. Do not share it! + +Now we need to tell gcli about this new token. To do this, create a +configuration file for gcli: + + $ mkdir -p ${HOME}/.config/gcli + $ vi ${HOME}/.config/gcli/config + +Obviously, you can choose any other editor of your choice. Put the +following into this file: + + + defaults { + editor=vi + github-default-account=my-github-account + } + + my-github-account { + token= + account= + forge-type=github + } + +Replace the `` with the previously generated token +and the `` with your account name. + +If you now run + + $ gcli -t github repos + +you should get a list of your repos. If not, check again that you did +all the steps above correctly. + +**To be continued** From 5a145514246847e12a1edfd6d90a7801c4390ff7 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 15:44:55 +0200 Subject: [PATCH 002/236] Add .hgignore for hggit compat Some people apparently use this. Just drop it in. Signed-off-by: Nico Sonack --- .hgignore | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .hgignore diff --git a/.hgignore b/.hgignore new file mode 100644 index 00000000..4f0ee6e4 --- /dev/null +++ b/.hgignore @@ -0,0 +1,31 @@ +syntax: glob +build/* +Makefile.in +aclocal.m4 +ar-lib +autom4te.cache/output.0 +autom4te.cache/output.1 +autom4te.cache/output.2 +autom4te.cache/output.3 +autom4te.cache/requests +autom4te.cache/traces.0 +autom4te.cache/traces.1 +autom4te.cache/traces.2 +autom4te.cache/traces.3 +compile +config.guess +config.h.in +config.sub +configure +depcomp +install-sh +ltmain.sh +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 +missing +test-driver +ylwrap +*~ From 4783425fbd868283ce600c14965d6418064a2e6a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 19:51:58 +0200 Subject: [PATCH 003/236] Add generated html file to .hgignore --- .hgignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgignore b/.hgignore index 4f0ee6e4..6bd888a7 100644 --- a/.hgignore +++ b/.hgignore @@ -29,3 +29,4 @@ missing test-driver ylwrap *~ +docs/gcli-tutorial.html From a2ae6f788d71dfd4b8d881fc269c824b755b5cb9 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 19:52:57 +0200 Subject: [PATCH 004/236] tutorial: Finish the section about how to create issues --- docs/gcli-tutorial.md | 61 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/docs/gcli-tutorial.md b/docs/gcli-tutorial.md index db5b5b06..d57eeb55 100644 --- a/docs/gcli-tutorial.md +++ b/docs/gcli-tutorial.md @@ -243,4 +243,63 @@ If you now run you should get a list of your repos. If not, check again that you did all the steps above correctly. -**To be continued** +### First issue + +For this case I have a playground repository that you may as well use +for testing with gcli. It is available at +`herrhotzenplotz/ghcli-playground`. + +To see a list of issues, we can run: + + $ gcli -t github issues -o herrhotzenplotz -r ghcli-playground -a + NUMBER NOTES STATE TITLE + 13 0 open yet another issue + 12 0 closed wat + 11 0 closed blaaaaaaaaaaaaaaaaaaaah + 10 0 closed "this is the quoted" issue title? anyone?" + 9 0 closed test + 8 0 closed foobar + 7 0 closed foobar + 5 0 closed test2 + 4 0 closed test + $ + +#### Invoke gcli +Let's create a bug report where we complain about things not working: + + $ gcli -t github issues create -o herrhotzenplotz -r ghcli-playground \ + "Bug: Doesn't work on my machine" + +The message "Bug: doesn't work on my machine" is the title of the +issue. + +#### Original Post + +You will see the default editor come up and instruct you to type in a +message. This message is the "original post" or the body of the issue +ticket that you're about to submit. You can use Markdown Syntax: + + I tried building this code on my machine but unfortunately it errors + out with the following message: + + ```console + $ make love + make: don't know how to make love. Stop + + make: stopped in /tmp/wat + $ + ``` + + What am I doing wrong? + + ! ISSUE TITLE : Bug: Doesn't work on my machine + ! Enter issue description above. + ! All lines starting with '!' will be discarded. + +#### Submit the issue + +After you save and exit the editor gcli gives you a chance to check +back and finally submit the issue. Type 'y' and hit enter. + +You can check back if the issue was created and also view details +about it as you learned earlier. From 18a2630681736b3235f75b39007ba2b7c08c67ae Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 19:54:29 +0200 Subject: [PATCH 005/236] tutorial: Move into separate directory This is in preparation to splitting this into multiple pages. --- docs/{gcli-tutorial.md => tutorial/01-Index.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/{gcli-tutorial.md => tutorial/01-Index.md} (100%) diff --git a/docs/gcli-tutorial.md b/docs/tutorial/01-Index.md similarity index 100% rename from docs/gcli-tutorial.md rename to docs/tutorial/01-Index.md From 429fb6acce4a5882f0ebcc334320c9c83e4499da Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 20:02:16 +0200 Subject: [PATCH 006/236] tutorial: Split out installation instructions --- .hgignore | 2 +- docs/tutorial/01-Index.md | 84 +------------------------------- docs/tutorial/02-Installation.md | 83 +++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 83 deletions(-) create mode 100644 docs/tutorial/02-Installation.md diff --git a/.hgignore b/.hgignore index 6bd888a7..74eb9da7 100644 --- a/.hgignore +++ b/.hgignore @@ -29,4 +29,4 @@ missing test-driver ylwrap *~ -docs/gcli-tutorial.html +docs/tutorial/*.html diff --git a/docs/tutorial/01-Index.md b/docs/tutorial/01-Index.md index d57eeb55..8fcc05f0 100644 --- a/docs/tutorial/01-Index.md +++ b/docs/tutorial/01-Index.md @@ -3,89 +3,9 @@ This document is aimed at those who are new to gcli and want get started using it. -## Installation +## Table of contents -### Through package manager - -If you're on FreeBSD you can just install gcli by running the -following command: - - # pkg install gcli - -### Compile the source code - -Other operating systems currently require manual compilation and -installation. - -For this purpose go to -[https://herrhotzenplotz.de/gcli/releases](https://herrhotzenplotz.de/gcli/releases) -and choose the latest release. Then download one of the tarballs. - -For version 1.1.0 this would be: - -https://herrhotzenplotz.de/gcli/releases/gcli-1.1.0/gcli-1.1.0.tar.xz - -Now that you have a link, you can download it, extract it, compile the -code and install it: - - $ mkdir ~/build - $ cd ~/build - $ curl -4LO https://herrhotzenplotz.de/gcli/releases/gcli-1.1.0/gcli-1.1.0.tar.xz - % Total % Received % Xferd Average Speed Time Time Time Current - Dload Upload Total Spent Left Speed - 100 342k 100 342k 0 0 2739k 0 --:--:-- --:--:-- --:--:-- 2736k - $ ls - gcli-1.1.0.tar.xz - $ - -Install the dependencies for building gcli: - -e.g. on Debian systems: - - # apt install libcurl4-openssl-dev pkgconf build-essential - -Extract the tarball: - - $ tar xf gcli-1.1.0.tar.xz - $ cd gcli-1.1.0 - -Configure, build and install gcli: - - $ ./configure --prefix=${HOME}/.local - ... - $ make - ... - $ make install - -Now put the gcli executable into your PATH variable to allow the shell -to easily find it: - - $ PATH=${PATH}:${HOME}/.local/bin - $ export PATH - -You can put the above commands into your shell initialisation file, e.g.: - - $ echo 'PATH=${PATH}:${HOME}/.local/bin; export PATH' >> ~/.shrc - -Check that the shell finds gcli: - - $ which gcli - /usr/home/nico/.local/bin/gcli - $ - $ gcli version - gcli 1.1.0 (amd64-unknown-freebsd13.2) - Using libcurl/8.1.2 OpenSSL/1.1.1t zlib/1.2.13 libpsl/0.21.2 (+libidn2/2.3.4) libssh2/1.11.0 nghttp2/1.53.0 - Using vendored pdjson library - Report bugs at https://gitlab.com/herrhotzenplotz/gcli/. - Copyright 2021, 2022, 2023 Nico Sonack and contributors. - $ - -Furthermore I recommend setting the `MANPATH` variable so that you can -easily read the installed manual pages: - - $ MANPATH=:${HOME}/.local/share/man; export MANPATH - -You can also put this into your shell initialisation file. +1. [Installing GCLI](./02-Installation.html) ## First steps diff --git a/docs/tutorial/02-Installation.md b/docs/tutorial/02-Installation.md new file mode 100644 index 00000000..72590669 --- /dev/null +++ b/docs/tutorial/02-Installation.md @@ -0,0 +1,83 @@ +# Installing GCLI + +## Through package manager + +If you're on FreeBSD you can just install gcli by running the +following command: + + # pkg install gcli + +## Compile the source code + +Other operating systems currently require manual compilation and +installation. + +For this purpose go to +[https://herrhotzenplotz.de/gcli/releases](https://herrhotzenplotz.de/gcli/releases) +and choose the latest release. Then download one of the tarballs. + +For version 1.1.0 this would be: + +https://herrhotzenplotz.de/gcli/releases/gcli-1.1.0/gcli-1.1.0.tar.xz + +Now that you have a link, you can download it, extract it, compile the +code and install it: + + $ mkdir ~/build + $ cd ~/build + $ curl -4LO https://herrhotzenplotz.de/gcli/releases/gcli-1.1.0/gcli-1.1.0.tar.xz + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 100 342k 100 342k 0 0 2739k 0 --:--:-- --:--:-- --:--:-- 2736k + $ ls + gcli-1.1.0.tar.xz + $ + +Install the dependencies for building gcli: + +e.g. on Debian systems: + + # apt install libcurl4-openssl-dev pkgconf build-essential + +Extract the tarball: + + $ tar xf gcli-1.1.0.tar.xz + $ cd gcli-1.1.0 + +Configure, build and install gcli: + + $ ./configure --prefix=${HOME}/.local + ... + $ make + ... + $ make install + +Now put the gcli executable into your PATH variable to allow the shell +to easily find it: + + $ PATH=${PATH}:${HOME}/.local/bin + $ export PATH + +You can put the above commands into your shell initialisation file, e.g.: + + $ echo 'PATH=${PATH}:${HOME}/.local/bin; export PATH' >> ~/.shrc + +Check that the shell finds gcli: + + $ which gcli + /usr/home/nico/.local/bin/gcli + $ + $ gcli version + gcli 1.1.0 (amd64-unknown-freebsd13.2) + Using libcurl/8.1.2 OpenSSL/1.1.1t zlib/1.2.13 libpsl/0.21.2 (+libidn2/2.3.4) libssh2/1.11.0 nghttp2/1.53.0 + Using vendored pdjson library + Report bugs at https://gitlab.com/herrhotzenplotz/gcli/. + Copyright 2021, 2022, 2023 Nico Sonack and contributors. + $ + +Furthermore I recommend setting the `MANPATH` variable so that you can +easily read the installed manual pages: + + $ MANPATH=:${HOME}/.local/share/man; export MANPATH + +You can also put this into your shell initialisation file. From d19a0c2e284e15fcb02c756e9077a22b78b387ec Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 20:43:31 +0200 Subject: [PATCH 007/236] tutorial: Make a shell script generate the various pages This is a simple static site generator. No need for hugo and other piles of crap. --- ...{02-Installation.md => 01-Installation.md} | 0 docs/tutorial/02-First-Steps.md | 88 +++++++++++++++++++ docs/tutorial/gen.sh | 56 ++++++++++++ docs/tutorial/{01-Index.md => old_index.md} | 35 +------- docs/tutorial/toc | 2 + 5 files changed, 147 insertions(+), 34 deletions(-) rename docs/tutorial/{02-Installation.md => 01-Installation.md} (100%) create mode 100644 docs/tutorial/02-First-Steps.md create mode 100755 docs/tutorial/gen.sh rename docs/tutorial/{01-Index.md => old_index.md} (84%) create mode 100644 docs/tutorial/toc diff --git a/docs/tutorial/02-Installation.md b/docs/tutorial/01-Installation.md similarity index 100% rename from docs/tutorial/02-Installation.md rename to docs/tutorial/01-Installation.md diff --git a/docs/tutorial/02-First-Steps.md b/docs/tutorial/02-First-Steps.md new file mode 100644 index 00000000..da9684c7 --- /dev/null +++ b/docs/tutorial/02-First-Steps.md @@ -0,0 +1,88 @@ +# First steps + +## Listing issues + +Let's start off by listing some issues - here for the curl project +which is hosted on GitHub under curl/curl. To list issues for it one +would run: + + $ gcli -t github issues -o curl -r curl + +You will see the list of the 30 most recent open issue tickets. The +command above does the following: + + - invoke gcli + - as a global option we switch it into Github-Mode + - invoke the issues subcommand + - operate on the repository owner curl (`-o curl`) + - operate on the repository curl (`-r curl`) + +Note that the `-t github` option goes before the issues subcommand +because it is a global option for gcli that affects how all the +following things like subcommands operate. + +However, now I also want to see closed issues: + + $ gcli -t github issues -o curl -r curl -a + +The `-a` option will disregard the status of the issue. + +Oh and the screen is a bit cluttered by all these tickets - let's only +fetch the first 10 issues: + + $ gcli -t github issues -o curl -r curl -n10 + +## Examining issues + +As of now we only produced lists of issues. However, we may also want +to look at the details of an issue such as: + + - the original post + - labels + - comments + - assignees of the issue (that is someone who is working on the bug) + +Let's get a good summary of issue `#11268` in the curl project: + + $ gcli -t github issues -o curl -r curl -i 11268 all + +As you can see most of the options are the same, however now we tell +gcli with the `-i 11268` option that we want to work with a single +issue. Then we tell gcli what actions to perform on the issue. Another +important action is `comments`. Guess what it does: + + $ gcli -t github issues -o curl -r curl -i 11268 comments + +I know a person that likes to post long verbose traces. Let's search +for an issue authored by them on the OpenSSL GitHub page: + + $ gcli -t github issues -o openssl -r openssl -A blastwave -a + NUMBER STATE TITLE + 20379 open test "80-test_ssl_new.t" fails on Solaris 10 SPARCv9 + 10547 open Strict C90 CFLAGS results in sha.h:91 ISO C90 does not support long long + 8048 closed OPENSSL_strnlen SIGSEGV in o_str.c line 76 + $ + +The `-A` option lets you filter for specific authors. + +Let's look at the issue state of `#10547`: + + $ gcli -t github issues -o openssl -r openssl -i 10547 status + NAME : 10547 + TITLE : Strict C90 CFLAGS results in sha.h:91 ISO C90 does not support long long + CREATED : 2019-12-01T04:35:23Z + AUTHOR : blastwave + STATE : open + COMMENTS : 9 + LOCKED : no + LABELS : triaged: bug + ASSIGNEES : none + $ + +That's nine comments - let's read the original post and the comments +in our favourite pager `less`: + + $ gcli -t github issues -o openssl -r openssl -i 10547 op comments | less + +As you can see gcli will accept multiple actions for an issue and +executes them sequentially. diff --git a/docs/tutorial/gen.sh b/docs/tutorial/gen.sh new file mode 100755 index 00000000..7b61f1dc --- /dev/null +++ b/docs/tutorial/gen.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +# +# Static Site generator for the tutorial. +# +# You will need cmark for this to work. +# + +header() { + cat top.html + printf "%s\n" "${1}" + cat middle.html +} + +footer() { + cat footer.html +} + +genindex() { + header "GCLI Tutorial" + + cat <A GCLI Tutorial +

This document is aimed at those who are new to gcli and want get + started using it.

+ +

Table of contents

+EOF + + echo "
    " + + awk '{printf "
  1. %s
  2. \n", $1, $2}' < toc + + echo "
" + + footer +} + +genpage() { + PAGETITLE="${1}" + PAGEMDFILE="${2}" + + header "GCLI Tutorial | ${PAGETITLE}" + cmark -t html < ${PAGEMDFILE} + footer +} + +genindex > index.html + +while read record; do + title="$(echo ${record} | awk '{print $2}')" + htmldoc="$(echo ${record} | awk '{print $1}')" + mddoc="${htmldoc%.html}.md" + + genpage "${title}" "${mddoc}" > "${htmldoc}" +done < toc diff --git a/docs/tutorial/01-Index.md b/docs/tutorial/old_index.md similarity index 84% rename from docs/tutorial/01-Index.md rename to docs/tutorial/old_index.md index 8fcc05f0..133d5ddc 100644 --- a/docs/tutorial/01-Index.md +++ b/docs/tutorial/old_index.md @@ -6,40 +6,7 @@ started using it. ## Table of contents 1. [Installing GCLI](./02-Installation.html) - -## First steps - -### Issues - -Let's start off by listing some issues - here for the curl project -which is hosted on GitHub under curl/curl. To list issues for it one -would run: - - $ gcli -t github issues -o curl -r curl - -You will see the list of the 30 most recent open issue tickets. The -command above does the following: - - - invoke gcli - - as a global option we switch it into Github-Mode - - invoke the issues subcommand - - operate on the repository owner curl (`-o curl`) - - operate on the repository curl (`-r curl`) - -Note that the `-t github` option goes before the issues subcommand -because it is a global option for gcli that affects how all the -following things like subcommands operate. - -However, now I also want to see closed issues: - - $ gcli -t github issues -o curl -r curl -a - -The `-a` option will disregard the status of the issue. - -Oh and the screen is a bit cluttered by all these tickets - let's only -fetch the first 10 issues: - - $ gcli -t github issues -o curl -r curl -n10 +1. [First steps](./03-First-Steps.html) #### Details about issues diff --git a/docs/tutorial/toc b/docs/tutorial/toc new file mode 100644 index 00000000..cf271186 --- /dev/null +++ b/docs/tutorial/toc @@ -0,0 +1,2 @@ +01-Installation.html Installation +02-First-Steps.html First Steps From d158e35fdc29b268ff690e7ef21958a1ca7e0c69 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 20:52:21 +0200 Subject: [PATCH 008/236] tutorial: Fix generation of TOC We did not tell awk about the correct field separator and it was splitting on spaces. Split on tabs instead. --- docs/tutorial/gen.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/gen.sh b/docs/tutorial/gen.sh index 7b61f1dc..2495a392 100755 --- a/docs/tutorial/gen.sh +++ b/docs/tutorial/gen.sh @@ -29,7 +29,7 @@ EOF echo "
    " - awk '{printf "
  1. %s
  2. \n", $1, $2}' < toc + awk -F\\t '{printf "
  3. %s
  4. \n", $1, $2}' < toc echo "
" From 88ce0f94a9c1ed3fed3eb7dd83725bba9e8c66f3 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 20:52:59 +0200 Subject: [PATCH 009/236] tutorial: Add 'how to find documentation' page --- docs/tutorial/03-Find-Documentation.md | 69 ++++++++++++++++++++++++++ docs/tutorial/toc | 1 + 2 files changed, 70 insertions(+) create mode 100644 docs/tutorial/03-Find-Documentation.md diff --git a/docs/tutorial/03-Find-Documentation.md b/docs/tutorial/03-Find-Documentation.md new file mode 100644 index 00000000..4999c8d4 --- /dev/null +++ b/docs/tutorial/03-Find-Documentation.md @@ -0,0 +1,69 @@ +# How to find documentation + +When using gcli one may not always remember all the options and flags +for every subcommand. gcli has lots of integrated help to guide you +through its commands. + +## Subcommand help + +You can list all available options for the issues subcommand by doing: + + $ gcli issues --help + +With your current knowledge you can also explore the `gcli pulls` subcommand. + +## General usage + +Run the following command: + + $ gcli --help + usage: gcli [options] subcommand + + OPTIONS: + -a account Use the configured account instead of inferring it + -r remote Infer account from the given git remote + -t type Force the account type: + - github (default: github.com) + - gitlab (default: gitlab.com) + - gitea (default: codeberg.org) + -c Force colour and text formatting. + -q Be quiet. (Not implemented yet) + + -v Be verbose. + + SUBCOMMANDS: + ci Github CI status info + comment Comment under issues and PRs + config Configure forges + forks Create, delete and list repository forks + gists Create, fetch and list Github Gists + issues Manage issues + labels Manage issue and PR labels + milestones Milestone handling + pipelines Gitlab CI management + pulls Create, view and manage PRs + releases Manage releases of repositories + repos Remote Repository management + snippets Fetch and list Gitlab snippets + status General user status and notifications + api Fetch plain JSON info from an API (for debugging purposes) + version Print version + + gcli 1.2.0 (amd64-unknown-freebsd13.2) + Using libcurl/8.1.2 OpenSSL/1.1.1t zlib/1.2.13 libpsl/0.21.2 (+libidn2/2.3.4) libssh2/1.11.0 nghttp2/1.53.0 + Using vendored pdjson library + Report bugs at https://gitlab.com/herrhotzenplotz/gcli/. + Copyright 2021, 2022, 2023 Nico Sonack and contributors. + + +This gives you an overview over all the available subcommands. Each +subcommand in turn allows you to get its usage by supplying the +`--help` option to it. + +## Manual pages + +Furthermore I recommend reading into the manual page `gcli-issues(1)` +and `gcli-pulls(1)`: + + $ man gcli-issues + $ man gcli-pulls diff --git a/docs/tutorial/toc b/docs/tutorial/toc index cf271186..c268755d 100644 --- a/docs/tutorial/toc +++ b/docs/tutorial/toc @@ -1,2 +1,3 @@ 01-Installation.html Installation 02-First-Steps.html First Steps +03-Find-Documentation.html How to find documentation From fb47f29ce4978850d74c403abb5c361d4395102a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 20:57:04 +0200 Subject: [PATCH 010/236] tutorial: Add page for account setup --- docs/tutorial/04-Account-Setup.md | 52 ++++++++++++++ docs/tutorial/old_index.md | 116 ------------------------------ docs/tutorial/toc | 1 + 3 files changed, 53 insertions(+), 116 deletions(-) create mode 100644 docs/tutorial/04-Account-Setup.md diff --git a/docs/tutorial/04-Account-Setup.md b/docs/tutorial/04-Account-Setup.md new file mode 100644 index 00000000..d4a2a029 --- /dev/null +++ b/docs/tutorial/04-Account-Setup.md @@ -0,0 +1,52 @@ +# Setting up gcli for use with an account + +Creating issues on Github requires an account which we need to +generate an authentication token for gcli. + +Log into your GitHub account and click on your account icon in the top +right corner. Then choose the `Settings` option. Scroll down and +choose `Developer settings` on the bottom of the left column. Under +`Personal access tokens` choose `Tokens (classic)`. + +Click on `Generate new token (classic)`. + +Set a useful name such as `gcli` in the Note field, set the expiration +to `No expiration` and allow the following `Scopes`: + + - `repo` + - `workflow` + - `admin:public_key` + - `gist` + +Then create the token. It'll be printed in green. Do not share it! + +Now we need to tell gcli about this new token. To do this, create a +configuration file for gcli: + + $ mkdir -p ${HOME}/.config/gcli + $ vi ${HOME}/.config/gcli/config + +Obviously, you can choose any other editor of your choice. Put the +following into this file: + + + defaults { + editor=vi + github-default-account=my-github-account + } + + my-github-account { + token= + account= + forge-type=github + } + +Replace the `` with the previously generated token +and the `` with your account name. + +If you now run + + $ gcli -t github repos + +you should get a list of your repos. If not, check again that you did +all the steps above correctly. diff --git a/docs/tutorial/old_index.md b/docs/tutorial/old_index.md index 133d5ddc..9bbcb44e 100644 --- a/docs/tutorial/old_index.md +++ b/docs/tutorial/old_index.md @@ -10,126 +10,10 @@ started using it. #### Details about issues -As of now we only produced lists of issues. However, we may also want -to look at the details of an issue such as: - - - the original post - - labels - - comments - - assignees of the issue (that is someone who is working on the bug) - -Let's get a good summary of issue `#11268` in the curl project: - - $ gcli -t github issues -o curl -r curl -i 11268 all - -As you can see most of the options are the same, however now we tell -gcli with the `-i 11268` option that we want to work with a single -issue. Then we tell gcli what actions to perform on the issue. Another -important action is `comments`. Guess what it does: - - $ gcli -t github issues -o curl -r curl -i 11268 comments - -I know a person that likes to post long verbose traces. Let's search -for an issue authored by them on the OpenSSL GitHub page: - - $ gcli -t github issues -o openssl -r openssl -A blastwave -a - NUMBER STATE TITLE - 20379 open test "80-test_ssl_new.t" fails on Solaris 10 SPARCv9 - 10547 open Strict C90 CFLAGS results in sha.h:91 ISO C90 does not support long long - 8048 closed OPENSSL_strnlen SIGSEGV in o_str.c line 76 - $ - -The `-A` option lets you filter for specific authors. - -Let's look at the issue state of `#10547`: - - $ gcli -t github issues -o openssl -r openssl -i 10547 status - NAME : 10547 - TITLE : Strict C90 CFLAGS results in sha.h:91 ISO C90 does not support long long - CREATED : 2019-12-01T04:35:23Z - AUTHOR : blastwave - STATE : open - COMMENTS : 9 - LOCKED : no - LABELS : triaged: bug - ASSIGNEES : none - $ - -That's nine comments - let's read the original post and the comments -in our favourite pager `less`: - - $ gcli -t github issues -o openssl -r openssl -i 10547 op comments | less - -As you can see gcli will accept multiple actions for an issue and -executes them sequentially. - #### Further reading -You can list all available options for the issues subcommand by doing: - - $ gcli issues --help - -With your current knowledge you can also explore the `gcli pulls` subcommand. - -Furthermore I recommend reading into the manual page `gcli-issues(1)` -and `gcli-pulls(1)`: - - $ man gcli-issues - $ man gcli-pulls - ### Creating issues -Creating issues on Github requires an account which we need to -generate an authentication token for gcli. - -Log into your GitHub account and click on your account icon in the top -right corner. Then choose the `Settings` option. Scroll down and -choose `Developer settings` on the bottom of the left column. Under -`Personal access tokens` choose `Tokens (classic)`. - -Click on `Generate new token (classic)`. - -Set a useful name such as `gcli` in the Note field, set the expiration -to `No expiration` and allow the following `Scopes`: - - - `repo` - - `workflow` - - `admin:public_key` - - `gist` - -Then create the token. It'll be printed in green. Do not share it! - -Now we need to tell gcli about this new token. To do this, create a -configuration file for gcli: - - $ mkdir -p ${HOME}/.config/gcli - $ vi ${HOME}/.config/gcli/config - -Obviously, you can choose any other editor of your choice. Put the -following into this file: - - - defaults { - editor=vi - github-default-account=my-github-account - } - - my-github-account { - token= - account= - forge-type=github - } - -Replace the `` with the previously generated token -and the `` with your account name. - -If you now run - - $ gcli -t github repos - -you should get a list of your repos. If not, check again that you did -all the steps above correctly. - ### First issue For this case I have a playground repository that you may as well use diff --git a/docs/tutorial/toc b/docs/tutorial/toc index c268755d..b774139f 100644 --- a/docs/tutorial/toc +++ b/docs/tutorial/toc @@ -1,3 +1,4 @@ 01-Installation.html Installation 02-First-Steps.html First Steps 03-Find-Documentation.html How to find documentation +04-Account-Setup.html Setting up an account From ca0cac2b2f9431f5f3f0e26380de618112cc340c Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 21:03:23 +0200 Subject: [PATCH 011/236] tutorial: Split out creating an issue --- docs/tutorial/05-Creating-an-issue.md | 64 +++++++++++++++++++++++++++ docs/tutorial/old_index.md | 59 ------------------------ docs/tutorial/toc | 1 + 3 files changed, 65 insertions(+), 59 deletions(-) create mode 100644 docs/tutorial/05-Creating-an-issue.md diff --git a/docs/tutorial/05-Creating-an-issue.md b/docs/tutorial/05-Creating-an-issue.md new file mode 100644 index 00000000..07a5e8f1 --- /dev/null +++ b/docs/tutorial/05-Creating-an-issue.md @@ -0,0 +1,64 @@ +# Creating an issue + +**Note**: This assumes you have [configured gcli with an account](./04-Account-Setup.html) for Github already. + +## Preparation + +For this case I have a playground repository that you may as well use +for testing with gcli. It is available at +`herrhotzenplotz/ghcli-playground`. + +To see a list of issues, we can run: + + $ gcli -t github issues -o herrhotzenplotz -r ghcli-playground -a + NUMBER NOTES STATE TITLE + 13 0 open yet another issue + 12 0 closed wat + 11 0 closed blaaaaaaaaaaaaaaaaaaaah + 10 0 closed "this is the quoted" issue title? anyone?" + 9 0 closed test + 8 0 closed foobar + 7 0 closed foobar + 5 0 closed test2 + 4 0 closed test + $ + +## Invoke gcli +Let's create a bug report where we complain about things not working: + + $ gcli -t github issues create -o herrhotzenplotz -r ghcli-playground \ + "Bug: Doesn't work on my machine" + +The message "Bug: doesn't work on my machine" is the title of the +issue. + +## Original Post + +You will see the default editor come up and instruct you to type in a +message. This message is the "original post" or the body of the issue +ticket that you're about to submit. You can use Markdown Syntax: + + I tried building this code on my machine but unfortunately it errors + out with the following message: + + ```console + $ make love + make: don't know how to make love. Stop + + make: stopped in /tmp/wat + $ + ``` + + What am I doing wrong? + + ! ISSUE TITLE : Bug: Doesn't work on my machine + ! Enter issue description above. + ! All lines starting with '!' will be discarded. + +## Submit the issue + +After you save and exit the editor gcli gives you a chance to check +back and finally submit the issue. Type 'y' and hit enter. + +You can check back if the issue was created and also view details +about it as you learned earlier. diff --git a/docs/tutorial/old_index.md b/docs/tutorial/old_index.md index 9bbcb44e..4fa76974 100644 --- a/docs/tutorial/old_index.md +++ b/docs/tutorial/old_index.md @@ -15,62 +15,3 @@ started using it. ### Creating issues ### First issue - -For this case I have a playground repository that you may as well use -for testing with gcli. It is available at -`herrhotzenplotz/ghcli-playground`. - -To see a list of issues, we can run: - - $ gcli -t github issues -o herrhotzenplotz -r ghcli-playground -a - NUMBER NOTES STATE TITLE - 13 0 open yet another issue - 12 0 closed wat - 11 0 closed blaaaaaaaaaaaaaaaaaaaah - 10 0 closed "this is the quoted" issue title? anyone?" - 9 0 closed test - 8 0 closed foobar - 7 0 closed foobar - 5 0 closed test2 - 4 0 closed test - $ - -#### Invoke gcli -Let's create a bug report where we complain about things not working: - - $ gcli -t github issues create -o herrhotzenplotz -r ghcli-playground \ - "Bug: Doesn't work on my machine" - -The message "Bug: doesn't work on my machine" is the title of the -issue. - -#### Original Post - -You will see the default editor come up and instruct you to type in a -message. This message is the "original post" or the body of the issue -ticket that you're about to submit. You can use Markdown Syntax: - - I tried building this code on my machine but unfortunately it errors - out with the following message: - - ```console - $ make love - make: don't know how to make love. Stop - - make: stopped in /tmp/wat - $ - ``` - - What am I doing wrong? - - ! ISSUE TITLE : Bug: Doesn't work on my machine - ! Enter issue description above. - ! All lines starting with '!' will be discarded. - -#### Submit the issue - -After you save and exit the editor gcli gives you a chance to check -back and finally submit the issue. Type 'y' and hit enter. - -You can check back if the issue was created and also view details -about it as you learned earlier. diff --git a/docs/tutorial/toc b/docs/tutorial/toc index b774139f..d73c9829 100644 --- a/docs/tutorial/toc +++ b/docs/tutorial/toc @@ -2,3 +2,4 @@ 02-First-Steps.html First Steps 03-Find-Documentation.html How to find documentation 04-Account-Setup.html Setting up an account +05-Creating-an-issue.html Creating an issue From 8d93acf6328f38a7a949c78101280a39ea09a854 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 21:29:26 +0200 Subject: [PATCH 012/236] tutorial: Add page discussing how to comment on issues and pull requests --- docs/tutorial/06-Commenting.md | 31 +++++++++++++++++++++++++++++++ docs/tutorial/toc | 1 + 2 files changed, 32 insertions(+) create mode 100644 docs/tutorial/06-Commenting.md diff --git a/docs/tutorial/06-Commenting.md b/docs/tutorial/06-Commenting.md new file mode 100644 index 00000000..bce626aa --- /dev/null +++ b/docs/tutorial/06-Commenting.md @@ -0,0 +1,31 @@ +# Commenting + +Discussions on Github and the like are done through comments. You can +comment on issues and pull requests. + +## Reviewing a discussion + +Say you were looking at an issue in curl/curl: + + $ gcli issues -o curl -r curl -i 11461 comments + +## Create the comment + +And now you wish to respond to this thread: + + $ gcli comment -o curl -r curl -i 11461 + +This will now open the editor and lets you type in your message. +After saving and exiting gcli will ask you to confirm. Type 'y' and +hit enter: + + $ gcli -t github comment -o curl -r curl -i 11461 + You will be commenting the following in curl/curl #11461: + + Is this okay? [yN] y + $ + +## Commenting on pull requests + +When you want to comment under a pull request use the `-p` flag +instead of the `-i` flag to indicate the PR number. diff --git a/docs/tutorial/toc b/docs/tutorial/toc index d73c9829..30f89b2f 100644 --- a/docs/tutorial/toc +++ b/docs/tutorial/toc @@ -3,3 +3,4 @@ 03-Find-Documentation.html How to find documentation 04-Account-Setup.html Setting up an account 05-Creating-an-issue.html Creating an issue +06-Commenting.html Interacting and commenting From 0275ee70edee93489da0ad45374222166c65ed39 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 21:42:58 +0200 Subject: [PATCH 013/236] tutorial: Add some nice rules and links back to the tutorial index --- docs/tutorial/gen.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/tutorial/gen.sh b/docs/tutorial/gen.sh index 2495a392..2f6caad3 100755 --- a/docs/tutorial/gen.sh +++ b/docs/tutorial/gen.sh @@ -41,7 +41,14 @@ genpage() { PAGEMDFILE="${2}" header "GCLI Tutorial | ${PAGETITLE}" + + echo "

⇐ Back to table of contents

" + echo "
" cmark -t html < ${PAGEMDFILE} + echo "
" + echo "
" + echo "

⇐ Back to table of contents

" + footer } From 71189869085bf0ddd8093a80923b6802927550de Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 22:29:27 +0200 Subject: [PATCH 014/236] (#190) Return error codes from gcli_fetch_with_method and gcli_fetch This is the first step to making all the functions return error codes. Now we need to go through all the calls in to these and check the return codes. --- include/gcli/curl.h | 16 ++++++------- src/curl.c | 56 +++++++++++++++++++++++++++++---------------- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/include/gcli/curl.h b/include/gcli/curl.h index 31b04bf8..04cc77a6 100644 --- a/include/gcli/curl.h +++ b/include/gcli/curl.h @@ -47,19 +47,19 @@ struct gcli_fetch_buffer { size_t length; }; -void gcli_fetch(char const *url, - char **pagination_next, - gcli_fetch_buffer *out); +int gcli_fetch(char const *url, + char **pagination_next, + gcli_fetch_buffer *out); void gcli_curl(FILE *stream, char const *url, char const *content_type); -void gcli_fetch_with_method(char const *method, - char const *url, - char const *data, - char **pagination_next, - gcli_fetch_buffer *out); +int gcli_fetch_with_method(char const *method, + char const *url, + char const *data, + char **pagination_next, + gcli_fetch_buffer *out); void gcli_post_upload(char const *url, char const *content_type, diff --git a/src/curl.c b/src/curl.c index ea9aee40..8df2755f 100644 --- a/src/curl.c +++ b/src/curl.c @@ -89,29 +89,35 @@ gcli_curl_ensure(void) /* Check the given curl code for an OK result. If not, print an * appropriate error message and exit */ -static void +static int gcli_curl_check_api_error(CURLcode code, char const *url, gcli_fetch_buffer *const result) { long status_code = 0; - if (code != CURLE_OK) - errx(1, - "error: request to %s failed\n" - " : curl error: %s", - url, - curl_easy_strerror(code)); + if (code != CURLE_OK) { + fprintf(stderr, + "error: request to %s failed\n" + " : curl error: %s", + url, + curl_easy_strerror(code)); + + return -1; + } curl_easy_getinfo(gcli_curl_session, CURLINFO_RESPONSE_CODE, &status_code); if (status_code >= 300L) { - errx(1, - "error: request to %s failed with code %ld\n" - " : API error: %s", - url, status_code, - gcli_forge()->get_api_error_string(result)); + fprintf(stderr, + "error: request to %s failed with code %ld\n" + " : API error: %s", + url, status_code, + gcli_forge()->get_api_error_string(result)); + return -1; } + + return 0; } /* Callback for writing data into the gcli_fetch_buffer passed by @@ -136,13 +142,13 @@ fetch_write_callback(char *in, size_t size, size_t nmemb, void *data) * * pagination_next returns the next url to query for paged results. * Results are placed into the gcli_fetch_buffer. */ -void +int gcli_fetch( char const *url, char **const pagination_next, gcli_fetch_buffer *out) { - gcli_fetch_with_method("GET", url, NULL, pagination_next, out); + return gcli_fetch_with_method("GET", url, NULL, pagination_next, out); } /* Check the given url for a successful query */ @@ -312,7 +318,7 @@ parse_link_header(char *_header) * If pagination_next is non-null a URL that can be queried for more * data (pagination) is placed into it. If there is no more data, it * will be set to NULL. */ -void +int gcli_fetch_with_method( char const *method, /* HTTP method. e.g. POST, GET, DELETE etc. */ char const *url, /* Endpoint */ @@ -320,11 +326,12 @@ gcli_fetch_with_method( char **const pagination_next, /* Next URL for pagination */ gcli_fetch_buffer *const out) /* output buffer */ { - CURLcode ret; + CURLcode ret; struct curl_slist *headers; gcli_fetch_buffer tmp = {0}; /* used for error codes when out is NULL */ gcli_fetch_buffer *buf = NULL; char *link_header = NULL; + int rc = 0; char *auth_header = gcli_config_get_authheader(); @@ -370,10 +377,17 @@ gcli_fetch_with_method( curl_easy_setopt(gcli_curl_session, CURLOPT_FOLLOWLOCATION, 1L); ret = curl_easy_perform(gcli_curl_session); - gcli_curl_check_api_error(ret, url, buf); - - if (link_header && pagination_next) - *pagination_next = parse_link_header(link_header); + rc = gcli_curl_check_api_error(ret, url, buf); + + /* only parse these headers and continue if there was no error */ + if (rc == 0) { + if (link_header && pagination_next) + *pagination_next = parse_link_header(link_header); + } else if (out) { /* error happened and we have an output buffer */ + free(out->data); + out->data = NULL; + out->length = 0; + } free(link_header); @@ -386,6 +400,8 @@ gcli_fetch_with_method( free(tmp.data); free(auth_header); + + return rc; } /* Perform a POST request to the given URL and upload the buffer to it. From d3c6903bd4611a389cfdfb6a2277dfcf78d97c3d Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 22:33:00 +0200 Subject: [PATCH 015/236] (#190) check return code of fetch in gitlab_get_labels --- src/gitlab/labels.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/gitlab/labels.c b/src/gitlab/labels.c index d64fff3e..ad51e831 100644 --- a/src/gitlab/labels.c +++ b/src/gitlab/labels.c @@ -45,6 +45,7 @@ gitlab_get_labels(char const *owner, char *next_url = NULL; gcli_fetch_buffer buffer = {0}; struct json_stream stream = {0}; + int rc; *out = (gcli_label_list) {0}; @@ -52,16 +53,23 @@ gitlab_get_labels(char const *owner, gitlab_get_apibase(), owner, repo); do { - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_labels(&stream, &out->labels, &out->labels_size); + rc = gcli_fetch(url, &next_url, &buffer); + + if (rc == 0) { + json_open_buffer(&stream, buffer.data, buffer.length); + parse_gitlab_labels(&stream, &out->labels, &out->labels_size); + } free(buffer.data); free(url); json_close(&stream); + + if (rc < 0) + break; + } while ((url = next_url) && (max == -1 || (int)out->labels_size < max)); - return 0; + return rc; } void From 16dec2c2cc230460a9297924e37c79afb5e874d5 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 22:40:15 +0200 Subject: [PATCH 016/236] (#190) Refactor create_label routines to return error codes --- include/gcli/forges.h | 2 +- include/gcli/gitea/labels.h | 6 +++--- include/gcli/github/labels.h | 6 +++--- include/gcli/gitlab/labels.h | 6 +++--- include/gcli/labels.h | 6 +++--- src/cmd/labels.c | 5 ++++- src/gitea/labels.c | 4 ++-- src/github/labels.c | 16 +++++++++++----- src/gitlab/labels.c | 18 +++++++++++------- src/labels.c | 4 ++-- 10 files changed, 43 insertions(+), 30 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index ad295da3..871c6dbb 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -367,7 +367,7 @@ struct gcli_forge_descriptor { * Create the given label * * The ID will be filled in for you */ - void (*create_label)( + int (*create_label)( char const *owner, char const *repo, gcli_label *label); diff --git a/include/gcli/gitea/labels.h b/include/gcli/gitea/labels.h index 2a14dd41..2e8f18fc 100644 --- a/include/gcli/gitea/labels.h +++ b/include/gcli/gitea/labels.h @@ -41,9 +41,9 @@ int gitea_get_labels(char const *owner, int max, gcli_label_list *out); -void gitea_create_label(char const *owner, - char const *repo, - gcli_label *label); +int gitea_create_label(char const *owner, + char const *repo, + gcli_label *label); void gitea_delete_label(char const *owner, char const *repo, diff --git a/include/gcli/github/labels.h b/include/gcli/github/labels.h index 15155c9f..276a9219 100644 --- a/include/gcli/github/labels.h +++ b/include/gcli/github/labels.h @@ -41,9 +41,9 @@ int github_get_labels(char const *owner, int max, gcli_label_list *out); -void github_create_label(char const *owner, - char const *repo, - gcli_label *label); +int github_create_label(char const *owner, + char const *repo, + gcli_label *label); void github_delete_label(char const *owner, char const *repo, diff --git a/include/gcli/gitlab/labels.h b/include/gcli/gitlab/labels.h index e2f440ed..d34cfe78 100644 --- a/include/gcli/gitlab/labels.h +++ b/include/gcli/gitlab/labels.h @@ -41,9 +41,9 @@ int gitlab_get_labels(char const *owner, int max, gcli_label_list *out); -void gitlab_create_label(char const *owner, - char const *repo, - gcli_label *label); +int gitlab_create_label(char const *owner, + char const *repo, + gcli_label *label); void gitlab_delete_label(char const *owner, char const *repo, diff --git a/include/gcli/labels.h b/include/gcli/labels.h index f8dad5c1..ec0249da 100644 --- a/include/gcli/labels.h +++ b/include/gcli/labels.h @@ -65,9 +65,9 @@ void gcli_free_labels(gcli_label_list *labels); void gcli_print_labels(gcli_label_list const *list, int max); -void gcli_create_label(char const *owner, - char const *repo, - gcli_label *label); +int gcli_create_label(char const *owner, + char const *repo, + gcli_label *label); void gcli_delete_label(char const *owner, char const *repo, diff --git a/src/cmd/labels.c b/src/cmd/labels.c index e485a255..c7f883d1 100644 --- a/src/cmd/labels.c +++ b/src/cmd/labels.c @@ -160,7 +160,10 @@ subcommand_labels_create(int argc, char *argv[]) return EXIT_FAILURE; } - gcli_create_label(owner, repo, &label); + if (gcli_create_label(owner, repo, &label) < 0) { + fprintf(stderr, "error: could not create label\n"); + return EXIT_FAILURE; + } /* only if we are not quieted */ if (!sn_quiet()) diff --git a/src/gitea/labels.c b/src/gitea/labels.c index 41f31a6f..c8b7741b 100644 --- a/src/gitea/labels.c +++ b/src/gitea/labels.c @@ -44,12 +44,12 @@ gitea_get_labels(char const *owner, return github_get_labels(owner, reponame, max, list); } -void +int gitea_create_label(char const *owner, char const *repo, gcli_label *const label) { - github_create_label(owner, repo, label); + return github_create_label(owner, repo, label); } void diff --git a/src/github/labels.c b/src/github/labels.c index b45d2a8d..2d3256ad 100644 --- a/src/github/labels.c +++ b/src/github/labels.c @@ -66,7 +66,7 @@ github_get_labels(char const *owner, return 0; } -void +int github_create_label(char const *owner, char const *repo, gcli_label *const label) @@ -81,6 +81,7 @@ github_create_label(char const *owner, sn_sv label_colour = SV_NULL; gcli_fetch_buffer buffer = {0}; struct json_stream stream = {0}; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -105,11 +106,14 @@ github_create_label(char const *owner, SV_ARGS(label_descr), SV_ARGS(label_colour)); - gcli_fetch_with_method("POST", url, data, NULL, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_label(&stream, label); + rc = gcli_fetch_with_method("POST", url, data, NULL, &buffer); + + if (rc == 0) { + json_open_buffer(&stream, buffer.data, buffer.length); + parse_github_label(&stream, label); + json_close(&stream); + } - json_close(&stream); free(url); free(data); free(e_owner); @@ -119,6 +123,8 @@ github_create_label(char const *owner, free(label_descr.data); free(label_colour.data); free(buffer.data); + + return rc; } void diff --git a/src/gitlab/labels.c b/src/gitlab/labels.c index ad51e831..fb523340 100644 --- a/src/gitlab/labels.c +++ b/src/gitlab/labels.c @@ -72,7 +72,7 @@ gitlab_get_labels(char const *owner, return rc; } -void +int gitlab_create_label(char const *owner, char const *repo, gcli_label *const label) { char *url = NULL; @@ -82,6 +82,7 @@ gitlab_create_label(char const *owner, char const *repo, gcli_label *const label sn_sv ldesc_escaped = SV_NULL; gcli_fetch_buffer buffer = {0}; struct json_stream stream = {0}; + int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/labels", gitlab_get_apibase(), @@ -97,20 +98,23 @@ gitlab_create_label(char const *owner, char const *repo, gcli_label *const label colour_string, SV_ARGS(ldesc_escaped)); - gcli_fetch_with_method("POST", url, data, NULL, &buffer); - - json_open_buffer(&stream, buffer.data, buffer.length); - json_set_streaming(&stream, 1); + rc = gcli_fetch_with_method("POST", url, data, NULL, &buffer); - parse_gitlab_label(&stream, label); + if (rc == 0) { + json_open_buffer(&stream, buffer.data, buffer.length); + json_set_streaming(&stream, 1); + parse_gitlab_label(&stream, label); + json_close(&stream); + } - json_close(&stream); free(lname_escaped.data); free(ldesc_escaped.data); free(colour_string); free(data); free(url); free(buffer.data); + + return rc; } void diff --git a/src/labels.c b/src/labels.c index 22780eff..64602666 100644 --- a/src/labels.c +++ b/src/labels.c @@ -95,10 +95,10 @@ gcli_print_labels(gcli_label_list const *const list, int const max) gcli_tbl_end(table); } -void +int gcli_create_label(char const *owner, char const *repo, gcli_label *const label) { - gcli_forge()->create_label(owner, repo, label); + return gcli_forge()->create_label(owner, repo, label); } void From 14592b3c7106a32b5f7944a6be6a709c06ec6311 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 22:41:33 +0200 Subject: [PATCH 017/236] Add TAGS file to .hgignore --- .hgignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgignore b/.hgignore index 74eb9da7..ad253f1c 100644 --- a/.hgignore +++ b/.hgignore @@ -30,3 +30,4 @@ test-driver ylwrap *~ docs/tutorial/*.html +TAGS From ad0d4cace64167f8a53287d22130d7bc02499d3e Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 23:02:34 +0200 Subject: [PATCH 018/236] (#190) make delete_label routines return error codes --- include/gcli/forges.h | 2 +- include/gcli/gitea/labels.h | 6 +++--- include/gcli/github/labels.h | 6 +++--- include/gcli/gitlab/labels.h | 6 +++--- include/gcli/labels.h | 6 +++--- src/cmd/labels.c | 8 ++++++-- src/gitea/labels.c | 27 ++++++++++++++++----------- src/github/labels.c | 13 +++++++------ src/gitlab/labels.c | 9 +++++---- src/labels.c | 4 ++-- 10 files changed, 49 insertions(+), 38 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 871c6dbb..9c79faad 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -374,7 +374,7 @@ struct gcli_forge_descriptor { /** * Delete the given label */ - void (*delete_label)( + int (*delete_label)( char const *owner, char const *repo, char const *label); diff --git a/include/gcli/gitea/labels.h b/include/gcli/gitea/labels.h index 2e8f18fc..75a82f79 100644 --- a/include/gcli/gitea/labels.h +++ b/include/gcli/gitea/labels.h @@ -45,8 +45,8 @@ int gitea_create_label(char const *owner, char const *repo, gcli_label *label); -void gitea_delete_label(char const *owner, - char const *repo, - char const *label); +int gitea_delete_label(char const *owner, + char const *repo, + char const *label); #endif /* GITEA_LABELS_H */ diff --git a/include/gcli/github/labels.h b/include/gcli/github/labels.h index 276a9219..1eda3364 100644 --- a/include/gcli/github/labels.h +++ b/include/gcli/github/labels.h @@ -45,8 +45,8 @@ int github_create_label(char const *owner, char const *repo, gcli_label *label); -void github_delete_label(char const *owner, - char const *repo, - char const *label); +int github_delete_label(char const *owner, + char const *repo, + char const *label); #endif /* GITHUB_LABELS_H */ diff --git a/include/gcli/gitlab/labels.h b/include/gcli/gitlab/labels.h index d34cfe78..43bcf652 100644 --- a/include/gcli/gitlab/labels.h +++ b/include/gcli/gitlab/labels.h @@ -45,8 +45,8 @@ int gitlab_create_label(char const *owner, char const *repo, gcli_label *label); -void gitlab_delete_label(char const *owner, - char const *repo, - char const *label); +int gitlab_delete_label(char const *owner, + char const *repo, + char const *label); #endif /* GITLAB_LABELS_H */ diff --git a/include/gcli/labels.h b/include/gcli/labels.h index ec0249da..922e26af 100644 --- a/include/gcli/labels.h +++ b/include/gcli/labels.h @@ -69,8 +69,8 @@ int gcli_create_label(char const *owner, char const *repo, gcli_label *label); -void gcli_delete_label(char const *owner, - char const *repo, - char const *label); +int gcli_delete_label(char const *owner, + char const *repo, + char const *label); #endif /* LABELS_H */ diff --git a/src/cmd/labels.c b/src/cmd/labels.c index c7f883d1..6c60331a 100644 --- a/src/cmd/labels.c +++ b/src/cmd/labels.c @@ -60,7 +60,7 @@ usage(void) static int subcommand_labels_delete(int argc, char *argv[]) { - int ch; + int ch, rc; char const *owner = NULL, *repo = NULL; const struct option options[] = { {.name = "repo", .has_arg = required_argument, .val = 'r'}, @@ -94,7 +94,11 @@ subcommand_labels_delete(int argc, char *argv[]) return EXIT_FAILURE; } - gcli_delete_label(owner, repo, argv[0]); + rc = gcli_delete_label(owner, repo, argv[0]); + if (rc < 0) { + fprintf(stderr, "error: couldn't delete label\n"); + return EXIT_FAILURE; + } return EXIT_SUCCESS; } diff --git a/src/gitea/labels.c b/src/gitea/labels.c index c8b7741b..e5059b88 100644 --- a/src/gitea/labels.c +++ b/src/gitea/labels.c @@ -52,20 +52,21 @@ gitea_create_label(char const *owner, return github_create_label(owner, repo, label); } -void +int gitea_delete_label(char const *owner, char const *repo, char const *label) { - char *url = NULL; - gcli_fetch_buffer buffer = {0}; - gcli_label_list list = {0}; - int id = -1; + char *url = NULL; + gcli_label_list list = {0}; + int id = -1; + int rc = 0; /* Gitea wants the id of the label, not its name. thus fetch all * the labels first to then find out what the id is we need. */ - if (gitea_get_labels(owner, repo, -1, &list) < 0) - errx(1, "error: could not get list of labels"); + rc = gitea_get_labels(owner, repo, -1, &list); + if (rc < 0) + return rc; /* Search for the id */ for (size_t i = 0; i < list.labels_size; ++i) { @@ -76,17 +77,21 @@ gitea_delete_label(char const *owner, } /* did we find a label? */ - if (id < 0) - errx(1, "error: label '%s' does not exist", label); + if (id < 0) { + /* TODO: Save error message + * errx(1, "error: label '%s' does not exist", label); */ + return -1; + } /* DELETE /repos/{owner}/{repo}/labels/{} */ url = sn_asprintf("%s/repos/%s/%s/labels/%d", gitea_get_apibase(), owner, repo, id); - gcli_fetch_with_method("DELETE", url, NULL, NULL, &buffer); + rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); gcli_free_labels(&list); free(url); - free(buffer.data); + + return rc; } diff --git a/src/github/labels.c b/src/github/labels.c index 2d3256ad..58ec0617 100644 --- a/src/github/labels.c +++ b/src/github/labels.c @@ -127,14 +127,14 @@ github_create_label(char const *owner, return rc; } -void +int github_delete_label(char const *owner, char const *repo, char const *label) { - char *url = NULL; - char *e_label = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *e_label = NULL; + int rc = 0; e_label = gcli_urlencode(label); @@ -143,9 +143,10 @@ github_delete_label(char const *owner, gcli_get_apibase(), owner, repo, e_label); - gcli_fetch_with_method("DELETE", url, NULL, NULL, &buffer); + rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); free(url); free(e_label); - free(buffer.data); + + return rc; } diff --git a/src/gitlab/labels.c b/src/gitlab/labels.c index fb523340..3d1e2f68 100644 --- a/src/gitlab/labels.c +++ b/src/gitlab/labels.c @@ -117,20 +117,21 @@ gitlab_create_label(char const *owner, char const *repo, gcli_label *const label return rc; } -void +int gitlab_delete_label(char const *owner, char const *repo, char const *label) { char *url = NULL; char *e_label = NULL; - gcli_fetch_buffer buffer = {0}; + int rc; e_label = gcli_urlencode(label); url = sn_asprintf("%s/projects/%s%%2F%s/labels/%s", gitlab_get_apibase(), owner, repo, e_label); - gcli_fetch_with_method("DELETE", url, NULL, NULL, &buffer); + rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); free(url); - free(buffer.data); free(e_label); + + return rc; } diff --git a/src/labels.c b/src/labels.c index 64602666..8f239f26 100644 --- a/src/labels.c +++ b/src/labels.c @@ -101,8 +101,8 @@ gcli_create_label(char const *owner, char const *repo, gcli_label *const label) return gcli_forge()->create_label(owner, repo, label); } -void +int gcli_delete_label(char const *owner, char const *repo, char const *const label) { - gcli_forge()->delete_label(owner, repo, label); + return gcli_forge()->delete_label(owner, repo, label); } From cfee174c174a79c69af62207b54f655872fc5c1c Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 23:09:27 +0200 Subject: [PATCH 019/236] (#190) make issue_close return error codes --- include/gcli/forges.h | 2 +- include/gcli/gitea/issues.h | 6 +++--- include/gcli/github/issues.h | 6 +++--- include/gcli/gitlab/issues.h | 6 +++--- include/gcli/issues.h | 6 +++--- src/cmd/issues.c | 3 ++- src/gitea/issues.c | 21 +++++++++++---------- src/github/issues.c | 17 +++++++++-------- src/gitlab/issues.c | 18 +++++++++--------- src/issues.c | 4 ++-- 10 files changed, 46 insertions(+), 43 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 9c79faad..daae3224 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -109,7 +109,7 @@ struct gcli_forge_descriptor { /** * Close the given issue */ - void (*issue_close)( + int (*issue_close)( char const *owner, char const *repo, int issue_number); diff --git a/include/gcli/gitea/issues.h b/include/gcli/gitea/issues.h index 3f4b5b6c..7569e007 100644 --- a/include/gcli/gitea/issues.h +++ b/include/gcli/gitea/issues.h @@ -50,9 +50,9 @@ void gitea_get_issue_summary(char const *owner, void gitea_submit_issue(gcli_submit_issue_options opts, gcli_fetch_buffer *out); -void gitea_issue_close(char const *owner, - char const *repo, - int issue_number); +int gitea_issue_close(char const *owner, + char const *repo, + int issue_number); void gitea_issue_reopen(char const *owner, char const *repo, diff --git a/include/gcli/github/issues.h b/include/gcli/github/issues.h index 969e9fe6..270b2ebd 100644 --- a/include/gcli/github/issues.h +++ b/include/gcli/github/issues.h @@ -52,9 +52,9 @@ void github_get_issue_summary(char const *owner, int issue_number, gcli_issue *out); -void github_issue_close(char const *owner, - char const *repo, - int issue_number); +int github_issue_close(char const *owner, + char const *repo, + int issue_number); void github_issue_reopen(char const *owner, char const *repo, diff --git a/include/gcli/gitlab/issues.h b/include/gcli/gitlab/issues.h index 984fbc18..caa59f1e 100644 --- a/include/gcli/gitlab/issues.h +++ b/include/gcli/gitlab/issues.h @@ -52,9 +52,9 @@ void gitlab_get_issue_summary(char const *owner, int issue_number, gcli_issue *out); -void gitlab_issue_close(char const *owner, - char const *repo, - int issue_number); +int gitlab_issue_close(char const *owner, + char const *repo, + int issue_number); void gitlab_issue_reopen(char const *owner, char const *repo, diff --git a/include/gcli/issues.h b/include/gcli/issues.h index 0db5d5b7..e8e836da 100644 --- a/include/gcli/issues.h +++ b/include/gcli/issues.h @@ -102,9 +102,9 @@ void gcli_issue_free(gcli_issue *it); void gcli_issue_print_summary(gcli_issue const *it); void gcli_issue_print_op(gcli_issue const *it); -void gcli_issue_close(char const *owner, - char const *repo, - int issue_number); +int gcli_issue_close(char const *owner, + char const *repo, + int issue_number); void gcli_issue_reopen(char const *owner, char const *repo, diff --git a/src/cmd/issues.c b/src/cmd/issues.c index e345f67e..d7e923d5 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -398,7 +398,8 @@ handle_issues_actions(int argc, char *argv[], } else if (strcmp("close", operation) == 0) { - gcli_issue_close(owner, repo, issue_id); + if (gcli_issue_close(owner, repo, issue_id) < 0) + errx(1, "failed to close issue"); } else if (strcmp("reopen", operation) == 0) { diff --git a/src/gitea/issues.c b/src/gitea/issues.c index f988902e..98098d07 100644 --- a/src/gitea/issues.c +++ b/src/gitea/issues.c @@ -64,17 +64,17 @@ gitea_submit_issue(gcli_submit_issue_options opts, } /* Gitea has closed, Github has close ... go figure */ -static void +static int gitea_issue_patch_state(char const *owner, char const *repo, int const issue_number, char const *const state) { - gcli_fetch_buffer json_buffer = {0}; - char *url = NULL; - char *data = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + char *url = NULL; + char *data = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -86,21 +86,22 @@ gitea_issue_patch_state(char const *owner, issue_number); data = sn_asprintf("{ \"state\": \"%s\"}", state); - gcli_fetch_with_method("PATCH", url, data, NULL, &json_buffer); + rc = gcli_fetch_with_method("PATCH", url, data, NULL, NULL); free(data); free(url); free(e_owner); free(e_repo); - free(json_buffer.data); + + return rc; } -void +int gitea_issue_close(char const *owner, char const *repo, int const issue_number) { - gitea_issue_patch_state(owner, repo, issue_number, "closed"); + return gitea_issue_patch_state(owner, repo, issue_number, "closed"); } void diff --git a/src/github/issues.c b/src/github/issues.c index b169c958..e8da6823 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -161,14 +161,14 @@ github_get_issue_summary(char const *owner, free(buffer.data); } -void +int github_issue_close(char const *owner, char const *repo, int const issue_number) { - gcli_fetch_buffer json_buffer = {0}; - char *url = NULL; - char *data = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + char *url = NULL; + char *data = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -180,13 +180,14 @@ github_issue_close(char const *owner, char const *repo, int const issue_number) issue_number); data = sn_asprintf("{ \"state\": \"close\"}"); - gcli_fetch_with_method("PATCH", url, data, NULL, &json_buffer); + rc = gcli_fetch_with_method("PATCH", url, data, NULL, NULL); free(data); free(url); free(e_owner); free(e_repo); - free(json_buffer.data); + + return rc; } void diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index 4f9e7e58..ddd506b5 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -141,15 +141,14 @@ gitlab_get_issue_summary(char const *owner, free(buffer.data); } - -void +int gitlab_issue_close(char const *owner, char const *repo, int const issue_number) { - gcli_fetch_buffer json_buffer = {0}; - char *url = NULL; - char *data = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + char *url = NULL; + char *data = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -161,13 +160,14 @@ gitlab_issue_close(char const *owner, char const *repo, int const issue_number) issue_number); data = sn_asprintf("{ \"state_event\": \"close\"}"); - gcli_fetch_with_method("PUT", url, data, NULL, &json_buffer); + rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); free(data); free(url); free(e_owner); free(e_repo); - free(json_buffer.data); + + return rc; } void diff --git a/src/issues.c b/src/issues.c index 50683ebc..01072239 100644 --- a/src/issues.c +++ b/src/issues.c @@ -192,10 +192,10 @@ gcli_get_issue(char const *owner, gcli_forge()->get_issue_summary(owner, repo, issue_number, out); } -void +int gcli_issue_close(char const *owner, char const *repo, int const issue_number) { - gcli_forge()->issue_close(owner, repo, issue_number); + return gcli_forge()->issue_close(owner, repo, issue_number); } void From 07060145ff9be49ce6c3ba8443885fa7b6691313 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 23:23:42 +0200 Subject: [PATCH 020/236] (#190) Make issue_reopen return error codes --- include/gcli/forges.h | 2 +- include/gcli/gitea/issues.h | 6 +++--- include/gcli/github/issues.h | 6 +++--- include/gcli/gitlab/issues.h | 6 +++--- include/gcli/issues.h | 6 +++--- src/cmd/issues.c | 3 ++- src/gitea/issues.c | 4 ++-- src/github/issues.c | 17 +++++++++-------- src/gitlab/issues.c | 17 +++++++++-------- src/issues.c | 4 ++-- 10 files changed, 37 insertions(+), 34 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index daae3224..528ca828 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -116,7 +116,7 @@ struct gcli_forge_descriptor { /** * Reopen the given issue */ - void (*issue_reopen)( + int (*issue_reopen)( char const *owner, char const *repo, int issue_number); diff --git a/include/gcli/gitea/issues.h b/include/gcli/gitea/issues.h index 7569e007..0a3026fd 100644 --- a/include/gcli/gitea/issues.h +++ b/include/gcli/gitea/issues.h @@ -54,9 +54,9 @@ int gitea_issue_close(char const *owner, char const *repo, int issue_number); -void gitea_issue_reopen(char const *owner, - char const *repo, - int issue_number); +int gitea_issue_reopen(char const *owner, + char const *repo, + int issue_number); void gitea_issue_assign(char const *owner, char const *repo, diff --git a/include/gcli/github/issues.h b/include/gcli/github/issues.h index 270b2ebd..929ebd41 100644 --- a/include/gcli/github/issues.h +++ b/include/gcli/github/issues.h @@ -56,9 +56,9 @@ int github_issue_close(char const *owner, char const *repo, int issue_number); -void github_issue_reopen(char const *owner, - char const *repo, - int issue_number); +int github_issue_reopen(char const *owner, + char const *repo, + int issue_number); void github_perform_submit_issue(gcli_submit_issue_options opts, gcli_fetch_buffer *out); diff --git a/include/gcli/gitlab/issues.h b/include/gcli/gitlab/issues.h index caa59f1e..f4c9ec90 100644 --- a/include/gcli/gitlab/issues.h +++ b/include/gcli/gitlab/issues.h @@ -56,9 +56,9 @@ int gitlab_issue_close(char const *owner, char const *repo, int issue_number); -void gitlab_issue_reopen(char const *owner, - char const *repo, - int issue_number); +int gitlab_issue_reopen(char const *owner, + char const *repo, + int issue_number); void gitlab_issue_assign(char const *owner, char const *repo, diff --git a/include/gcli/issues.h b/include/gcli/issues.h index e8e836da..abaff968 100644 --- a/include/gcli/issues.h +++ b/include/gcli/issues.h @@ -106,9 +106,9 @@ int gcli_issue_close(char const *owner, char const *repo, int issue_number); -void gcli_issue_reopen(char const *owner, - char const *repo, - int issue_number); +int gcli_issue_reopen(char const *owner, + char const *repo, + int issue_number); void gcli_issue_submit(gcli_submit_issue_options); diff --git a/src/cmd/issues.c b/src/cmd/issues.c index d7e923d5..820f7952 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -403,7 +403,8 @@ handle_issues_actions(int argc, char *argv[], } else if (strcmp("reopen", operation) == 0) { - gcli_issue_reopen(owner, repo, issue_id); + if (gcli_issue_reopen(owner, repo, issue_id) < 0) + errx(1, "failed to reopen issue"); } else if (strcmp("assign", operation) == 0) { diff --git a/src/gitea/issues.c b/src/gitea/issues.c index 98098d07..d4cb0c01 100644 --- a/src/gitea/issues.c +++ b/src/gitea/issues.c @@ -104,12 +104,12 @@ gitea_issue_close(char const *owner, return gitea_issue_patch_state(owner, repo, issue_number, "closed"); } -void +int gitea_issue_reopen(char const *owner, char const *repo, int const issue_number) { - gitea_issue_patch_state(owner, repo, issue_number, "open"); + return gitea_issue_patch_state(owner, repo, issue_number, "open"); } void diff --git a/src/github/issues.c b/src/github/issues.c index e8da6823..966eedf5 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -190,14 +190,14 @@ github_issue_close(char const *owner, char const *repo, int const issue_number) return rc; } -void +int github_issue_reopen(char const *owner, char const *repo, int const issue_number) { - gcli_fetch_buffer json_buffer = {0}; - char *url = NULL; - char *data = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + char *url = NULL; + char *data = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -209,13 +209,14 @@ github_issue_reopen(char const *owner, char const *repo, int const issue_number) issue_number); data = sn_asprintf("{ \"state\": \"open\"}"); - gcli_fetch_with_method("PATCH", url, data, NULL, &json_buffer); + rc = gcli_fetch_with_method("PATCH", url, data, NULL, NULL); free(data); free(url); free(e_owner); free(e_repo); - free(json_buffer.data); + + return rc; } void diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index ddd506b5..53eb9df1 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -170,14 +170,14 @@ gitlab_issue_close(char const *owner, char const *repo, int const issue_number) return rc; } -void +int gitlab_issue_reopen(char const *owner, char const *repo, int const issue_number) { - gcli_fetch_buffer json_buffer = {0}; - char *url = NULL; - char *data = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + char *url = NULL; + char *data = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -189,13 +189,14 @@ gitlab_issue_reopen(char const *owner, char const *repo, int const issue_number) issue_number); data = sn_asprintf("{ \"state_event\": \"reopen\"}"); - gcli_fetch_with_method("PUT", url, data, NULL, &json_buffer); + rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); free(data); free(url); free(e_owner); free(e_repo); - free(json_buffer.data); + + return rc; } void diff --git a/src/issues.c b/src/issues.c index 01072239..8f77eb8f 100644 --- a/src/issues.c +++ b/src/issues.c @@ -198,10 +198,10 @@ gcli_issue_close(char const *owner, char const *repo, int const issue_number) return gcli_forge()->issue_close(owner, repo, issue_number); } -void +int gcli_issue_reopen(char const *owner, char const *repo, int const issue_number) { - gcli_forge()->issue_reopen(owner, repo, issue_number); + return gcli_forge()->issue_reopen(owner, repo, issue_number); } static void From 0b1a52f0a61a995287df4e71d24d73ce20129481 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 23:28:52 +0200 Subject: [PATCH 021/236] (#190) Make submit_issue routines return error codes --- include/gcli/forges.h | 2 +- include/gcli/gitea/issues.h | 4 ++-- include/gcli/github/issues.h | 4 ++-- include/gcli/gitlab/issues.h | 4 ++-- include/gcli/issues.h | 2 +- src/cmd/issues.c | 3 ++- src/gitea/issues.c | 4 ++-- src/github/issues.c | 7 +++++-- src/gitlab/issues.c | 7 +++++-- src/issues.c | 11 ++++++++--- 10 files changed, 30 insertions(+), 18 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 528ca828..2de656fd 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -149,7 +149,7 @@ struct gcli_forge_descriptor { /** * Submit an issue */ - void (*perform_submit_issue)( + int (*perform_submit_issue)( gcli_submit_issue_options opts, gcli_fetch_buffer *out); diff --git a/include/gcli/gitea/issues.h b/include/gcli/gitea/issues.h index 0a3026fd..4e554ddf 100644 --- a/include/gcli/gitea/issues.h +++ b/include/gcli/gitea/issues.h @@ -47,8 +47,8 @@ void gitea_get_issue_summary(char const *owner, int issue, gcli_issue *out); -void gitea_submit_issue(gcli_submit_issue_options opts, - gcli_fetch_buffer *out); +int gitea_submit_issue(gcli_submit_issue_options opts, + gcli_fetch_buffer *out); int gitea_issue_close(char const *owner, char const *repo, diff --git a/include/gcli/github/issues.h b/include/gcli/github/issues.h index 929ebd41..6b7b286b 100644 --- a/include/gcli/github/issues.h +++ b/include/gcli/github/issues.h @@ -60,8 +60,8 @@ int github_issue_reopen(char const *owner, char const *repo, int issue_number); -void github_perform_submit_issue(gcli_submit_issue_options opts, - gcli_fetch_buffer *out); +int github_perform_submit_issue(gcli_submit_issue_options opts, + gcli_fetch_buffer *out); void github_issue_assign(char const *owner, char const *repo, diff --git a/include/gcli/gitlab/issues.h b/include/gcli/gitlab/issues.h index f4c9ec90..069f58e2 100644 --- a/include/gcli/gitlab/issues.h +++ b/include/gcli/gitlab/issues.h @@ -65,8 +65,8 @@ void gitlab_issue_assign(char const *owner, int issue_number, char const *assignee); -void gitlab_perform_submit_issue(gcli_submit_issue_options opts, - gcli_fetch_buffer *out); +int gitlab_perform_submit_issue(gcli_submit_issue_options opts, + gcli_fetch_buffer *out); void gitlab_issue_add_labels(char const *owner, char const *repo, diff --git a/include/gcli/issues.h b/include/gcli/issues.h index abaff968..8d80a78b 100644 --- a/include/gcli/issues.h +++ b/include/gcli/issues.h @@ -110,7 +110,7 @@ int gcli_issue_reopen(char const *owner, char const *repo, int issue_number); -void gcli_issue_submit(gcli_submit_issue_options); +int gcli_issue_submit(gcli_submit_issue_options); void gcli_issue_assign(char const *owner, char const *repo, diff --git a/src/cmd/issues.c b/src/cmd/issues.c index 820f7952..58c44f5e 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -127,7 +127,8 @@ subcommand_issue_create(int argc, char *argv[]) opts.title = SV(argv[0]); - gcli_issue_submit(opts); + if (gcli_issue_submit(opts) < 0) + errx(1, "failed to submit issue"); return EXIT_SUCCESS; } diff --git a/src/gitea/issues.c b/src/gitea/issues.c index d4cb0c01..f38b1354 100644 --- a/src/gitea/issues.c +++ b/src/gitea/issues.c @@ -56,11 +56,11 @@ gitea_get_issue_summary(char const *owner, github_get_issue_summary(owner, repo, issue_number, out); } -void +int gitea_submit_issue(gcli_submit_issue_options opts, gcli_fetch_buffer *const out) { - github_perform_submit_issue(opts, out); + return github_perform_submit_issue(opts, out); } /* Gitea has closed, Github has close ... go figure */ diff --git a/src/github/issues.c b/src/github/issues.c index 966eedf5..f32392e6 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -219,7 +219,7 @@ github_issue_reopen(char const *owner, char const *repo, int const issue_number) return rc; } -void +int github_perform_submit_issue(gcli_submit_issue_options opts, gcli_fetch_buffer *out) { @@ -227,6 +227,7 @@ github_perform_submit_issue(gcli_submit_issue_options opts, char *e_repo = gcli_urlencode(opts.repo); sn_sv e_title = gcli_json_escape(opts.title); sn_sv e_body = gcli_json_escape(opts.body); + int rc = 0; char *post_fields = sn_asprintf( "{ \"title\": \""SV_FMT"\", \"body\": \""SV_FMT"\" }", @@ -235,7 +236,7 @@ github_perform_submit_issue(gcli_submit_issue_options opts, char *url = sn_asprintf("%s/repos/%s/%s/issues", gcli_get_apibase(), e_owner, e_repo); - gcli_fetch_with_method("POST", url, post_fields, NULL, out); + rc = gcli_fetch_with_method("POST", url, post_fields, NULL, out); free(e_owner); free(e_repo); @@ -243,6 +244,8 @@ github_perform_submit_issue(gcli_submit_issue_options opts, free(e_body.data); free(post_fields); free(url); + + return rc; } void diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index 53eb9df1..03bb73e1 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -199,7 +199,7 @@ gitlab_issue_reopen(char const *owner, char const *repo, int const issue_number) return rc; } -void +int gitlab_perform_submit_issue(gcli_submit_issue_options opts, gcli_fetch_buffer *const out) { @@ -207,6 +207,7 @@ gitlab_perform_submit_issue(gcli_submit_issue_options opts, char *e_repo = gcli_urlencode(opts.repo); sn_sv e_title = gcli_json_escape(opts.title); sn_sv e_body = gcli_json_escape(opts.body); + int rc = 0; char *post_fields = sn_asprintf( "{ \"title\": \""SV_FMT"\", \"description\": \""SV_FMT"\" }", @@ -215,7 +216,7 @@ gitlab_perform_submit_issue(gcli_submit_issue_options opts, "%s/projects/%s%%2F%s/issues", gitlab_get_apibase(), e_owner, e_repo); - gcli_fetch_with_method("POST", url, post_fields, NULL, out); + rc = gcli_fetch_with_method("POST", url, post_fields, NULL, out); free(e_owner); free(e_repo); @@ -223,6 +224,8 @@ gitlab_perform_submit_issue(gcli_submit_issue_options opts, free(e_body.data); free(post_fields); free(url); + + return rc; } static int diff --git a/src/issues.c b/src/issues.c index 8f77eb8f..de41ef7f 100644 --- a/src/issues.c +++ b/src/issues.c @@ -222,10 +222,11 @@ gcli_issue_get_user_message(gcli_submit_issue_options *opts) return gcli_editor_get_user_message(issue_init_user_file, opts); } -void +int gcli_issue_submit(gcli_submit_issue_options opts) { gcli_fetch_buffer json_buffer = {0}; + int rc = 0; opts.body = gcli_issue_get_user_message(&opts); @@ -246,12 +247,16 @@ gcli_issue_submit(gcli_submit_issue_options opts) errx(1, "Submission aborted."); } - gcli_forge()->perform_submit_issue(opts, &json_buffer); - gcli_print_html_url(json_buffer); + rc = gcli_forge()->perform_submit_issue(opts, &json_buffer); + + if (rc == 0) + gcli_print_html_url(json_buffer); free(opts.body.data); free(opts.body.data); free(json_buffer.data); + + return rc; } void From 9b0f7c8a4c3184c03aa1bd52b09ac3c071ffc51b Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 23:51:18 +0200 Subject: [PATCH 022/236] (#190) make (pull|issue)_(add|remove)_lables return error codes --- include/gcli/forges.h | 8 ++++---- include/gcli/gitea/issues.h | 20 +++++++++---------- include/gcli/github/issues.h | 20 +++++++++---------- include/gcli/gitlab/issues.h | 20 +++++++++---------- include/gcli/gitlab/merge_requests.h | 22 ++++++++++---------- include/gcli/issues.h | 22 ++++++++++---------- include/gcli/pulls.h | 22 ++++++++++---------- src/cmd/issues.c | 22 ++++++++++++++------ src/cmd/pulls.c | 16 +++++++++++---- src/gitea/issues.c | 30 +++++++++++++++++----------- src/github/issues.c | 28 ++++++++++++++------------ src/gitlab/issues.c | 30 +++++++++++++++------------- src/gitlab/merge_requests.c | 30 +++++++++++++++------------- src/issues.c | 8 ++++---- src/pulls.c | 8 ++++---- 15 files changed, 168 insertions(+), 138 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 2de656fd..9bfe538a 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -131,7 +131,7 @@ struct gcli_forge_descriptor { /** * Add labels to issues */ - void (*issue_add_labels)( + int (*issue_add_labels)( char const *owner, char const *repo, int issue, @@ -140,7 +140,7 @@ struct gcli_forge_descriptor { /** * Removes labels from issues */ - void (*issue_remove_labels)( + int (*issue_remove_labels)( char const *owner, char const *repo, int issue, @@ -304,7 +304,7 @@ struct gcli_forge_descriptor { /** * Add labels to Pull Requests */ - void (*pr_add_labels)( + int (*pr_add_labels)( char const *owner, char const *repo, int pr, @@ -313,7 +313,7 @@ struct gcli_forge_descriptor { /** * Removes labels from Pull Requests */ - void (*pr_remove_labels)( + int (*pr_remove_labels)( char const *owner, char const *repo, int pr, diff --git a/include/gcli/gitea/issues.h b/include/gcli/gitea/issues.h index 4e554ddf..efa98609 100644 --- a/include/gcli/gitea/issues.h +++ b/include/gcli/gitea/issues.h @@ -63,17 +63,17 @@ void gitea_issue_assign(char const *owner, int issue_number, char const *assignee); -void gitea_issue_add_labels(char const *owner, - char const *repo, - int issue, - char const *const labels[], - size_t labels_size); +int gitea_issue_add_labels(char const *owner, + char const *repo, + int issue, + char const *const labels[], + size_t labels_size); -void gitea_issue_remove_labels(char const *owner, - char const *repo, - int issue, - char const *const labels[], - size_t labels_size); +int gitea_issue_remove_labels(char const *owner, + char const *repo, + int issue, + char const *const labels[], + size_t labels_size); int gitea_issue_set_milestone(char const *owner, char const *repo, diff --git a/include/gcli/github/issues.h b/include/gcli/github/issues.h index 6b7b286b..11222c7b 100644 --- a/include/gcli/github/issues.h +++ b/include/gcli/github/issues.h @@ -68,17 +68,17 @@ void github_issue_assign(char const *owner, int issue_number, char const *assignee); -void github_issue_add_labels(char const *owner, - char const *repo, - int issue, - char const *const labels[], - size_t labels_size); +int github_issue_add_labels(char const *owner, + char const *repo, + int issue, + char const *const labels[], + size_t labels_size); -void github_issue_remove_labels(char const *owner, - char const *repo, - int issue, - char const *const labels[], - size_t labels_size); +int github_issue_remove_labels(char const *owner, + char const *repo, + int issue, + char const *const labels[], + size_t labels_size); int github_issue_set_milestone(char const *owner, char const *repo, diff --git a/include/gcli/gitlab/issues.h b/include/gcli/gitlab/issues.h index 069f58e2..b0b0fb9f 100644 --- a/include/gcli/gitlab/issues.h +++ b/include/gcli/gitlab/issues.h @@ -68,17 +68,17 @@ void gitlab_issue_assign(char const *owner, int gitlab_perform_submit_issue(gcli_submit_issue_options opts, gcli_fetch_buffer *out); -void gitlab_issue_add_labels(char const *owner, - char const *repo, - int issue, - char const *const labels[], - size_t labels_size); +int gitlab_issue_add_labels(char const *owner, + char const *repo, + int issue, + char const *const labels[], + size_t labels_size); -void gitlab_issue_remove_labels(char const *owner, - char const *repo, - int issue, - char const *const labels[], - size_t labels_size); +int gitlab_issue_remove_labels(char const *owner, + char const *repo, + int issue, + char const *const labels[], + size_t labels_size); int gitlab_issue_set_milestone(char const *owner, char const *repo, diff --git a/include/gcli/gitlab/merge_requests.h b/include/gcli/gitlab/merge_requests.h index c110296b..4a4bc31f 100644 --- a/include/gcli/gitlab/merge_requests.h +++ b/include/gcli/gitlab/merge_requests.h @@ -76,17 +76,17 @@ int gitlab_get_pull_commits(char const *owner, void gitlab_perform_submit_mr(gcli_submit_pull_options opts); -void gitlab_mr_add_labels(char const *owner, - char const *repo, - int mr, - char const *const labels[], - size_t labels_size); - -void gitlab_mr_remove_labels(char const *owner, - char const *repo, - int mr, - char const *const labels[], - size_t labels_size); +int gitlab_mr_add_labels(char const *owner, + char const *repo, + int mr, + char const *const labels[], + size_t labels_size); + +int gitlab_mr_remove_labels(char const *owner, + char const *repo, + int mr, + char const *const labels[], + size_t labels_size); int gitlab_mr_set_milestone(char const *owner, char const *repo, diff --git a/include/gcli/issues.h b/include/gcli/issues.h index 8d80a78b..a515748b 100644 --- a/include/gcli/issues.h +++ b/include/gcli/issues.h @@ -117,17 +117,17 @@ void gcli_issue_assign(char const *owner, int issue_number, char const *assignee); -void gcli_issue_add_labels(char const *owner, - char const *repo, - int issue_number, - char const *const labels[], - size_t labels_size); - -void gcli_issue_remove_labels(char const *owner, - char const *repo, - int issue_number, - char const *const labels[], - size_t labels_size); +int gcli_issue_add_labels(char const *owner, + char const *repo, + int issue_number, + char const *const labels[], + size_t labels_size); + +int gcli_issue_remove_labels(char const *owner, + char const *repo, + int issue_number, + char const *const labels[], + size_t labels_size); int gcli_issue_set_milestone(char const *owner, char const *repo, diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index e40714fa..1188e1ac 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -156,17 +156,17 @@ void gcli_pull_reopen(char const *owner, char const *reponame, int pr_number); -void gcli_pull_add_labels(char const *owner, - char const *repo, - int pr_number, - char const *const labels[], - size_t labels_size); - -void gcli_pull_remove_labels(char const *owner, - char const *repo, - int pr_number, - char const *const labels[], - size_t labels_size); +int gcli_pull_add_labels(char const *owner, + char const *repo, + int pr_number, + char const *const labels[], + size_t labels_size); + +int gcli_pull_remove_labels(char const *owner, + char const *repo, + int pr_number, + char const *const labels[], + size_t labels_size); int gcli_pull_set_milestone(char const *owner, char const *repo, diff --git a/src/cmd/issues.c b/src/cmd/issues.c index 58c44f5e..c9843bf1 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -283,6 +283,7 @@ handle_issue_labels_action(int *argc, char ***argv, size_t add_labels_size = 0; char const **remove_labels = NULL; size_t remove_labels_size = 0; + int rc = 0; if (argc == 0) { fprintf(stderr, "error: expected label operations\n"); @@ -294,12 +295,21 @@ handle_issue_labels_action(int *argc, char ***argv, &remove_labels, &remove_labels_size); /* actually go about deleting and adding the labels */ - if (add_labels_size) - gcli_issue_add_labels(owner, repo, issue_id, - add_labels, add_labels_size); - if (remove_labels_size) - gcli_issue_remove_labels(owner, repo, issue_id, - remove_labels, remove_labels_size); + if (add_labels_size) { + rc = gcli_issue_add_labels(owner, repo, issue_id, + add_labels, add_labels_size); + + if (rc < 0) + errx(1, "failed to add labels"); + } + + if (remove_labels_size) { + rc = gcli_issue_remove_labels(owner, repo, issue_id, + remove_labels, remove_labels_size); + + if (rc < 0) + errx(1, "failed to remove labels"); + } free(add_labels); free(remove_labels); diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 28180832..8c63a64e 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -468,6 +468,7 @@ handle_pull_actions(int argc, char *argv[], size_t add_labels_size = 0; const char **remove_labels = NULL; size_t remove_labels_size = 0; + int rc = 0; if (argc == 0) { fprintf(stderr, "error: expected label action\n"); @@ -480,13 +481,20 @@ handle_pull_actions(int argc, char *argv[], &remove_labels, &remove_labels_size); /* actually go about deleting and adding the labels */ - if (add_labels_size) - gcli_pull_add_labels( + if (add_labels_size) { + rc = gcli_pull_add_labels( owner, repo, pr, add_labels, add_labels_size); - if (remove_labels_size) - gcli_pull_remove_labels( + if (rc < 0) + errx(1, "failed to add labels"); + } + if (remove_labels_size) { + rc = gcli_pull_remove_labels( owner, repo, pr, remove_labels, remove_labels_size); + if (rc < 0) + errx(1, "failed to remove labels"); + } + free(add_labels); free(remove_labels); diff --git a/src/gitea/issues.c b/src/gitea/issues.c index f38b1354..eaebb4c2 100644 --- a/src/gitea/issues.c +++ b/src/gitea/issues.c @@ -193,17 +193,17 @@ free_id_list(char *list[], size_t const list_size) free(list); } -void +int gitea_issue_add_labels(char const *owner, char const *repo, int const issue, char const *const labels[], size_t const labels_size) { - char *list = NULL; - char *data = NULL; - char *url = NULL; - gcli_fetch_buffer buffer = {0}; + char *list = NULL; + char *data = NULL; + char *url = NULL; + int rc = 0; /* First, convert to ids */ char **ids = label_names_to_ids(owner, repo, labels, labels_size); @@ -216,40 +216,46 @@ gitea_issue_add_labels(char const *owner, url = sn_asprintf("%s/repos/%s/%s/issues/%d/labels", gitea_get_apibase(), owner, repo, issue); - gcli_fetch_with_method("POST", url, data, NULL, &buffer); + + rc = gcli_fetch_with_method("POST", url, data, NULL, NULL); free(list); free(data); free(url); - free(buffer.data); free_id_list(ids, labels_size); + + return rc; } -void +int gitea_issue_remove_labels(char const *owner, char const *repo, int const issue, char const *const labels[], size_t const labels_size) { + int rc = 0; /* Unfortunately the gitea api does not give us an endpoint to * delete labels from an issue in bulk. So, just iterate over the * given labels and delete them one after another. */ char **ids = label_names_to_ids(owner, repo, labels, labels_size); for (size_t i = 0; i < labels_size; ++i) { - char *url = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; url = sn_asprintf("%s/repos/%s/%s/issues/%d/labels/%s", gitea_get_apibase(), owner, repo, issue, ids[i]); - gcli_fetch_with_method("DELETE", url, NULL, NULL, &buffer); + rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); - free(buffer.data); free(url); + + if (rc < 0) + break; } free_id_list(ids, labels_size); + + return rc; } int diff --git a/src/github/issues.c b/src/github/issues.c index f32392e6..b511d687 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -282,17 +282,17 @@ github_issue_assign(char const *owner, free(url); } -void +int github_issue_add_labels(char const *owner, char const *repo, int const issue, char const *const labels[], size_t const labels_size) { - char *url = NULL; - char *data = NULL; - char *list = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *data = NULL; + char *list = NULL; + int rc = 0; assert(labels_size > 0); @@ -302,24 +302,25 @@ github_issue_add_labels(char const *owner, list = sn_join_with(labels, labels_size, "\",\""); data = sn_asprintf("{ \"labels\": [\"%s\"]}", list); - gcli_fetch_with_method("POST", url, data, NULL, &buffer); + rc = gcli_fetch_with_method("POST", url, data, NULL, NULL); free(url); free(data); free(list); - free(buffer.data); + + return rc; } -void +int github_issue_remove_labels(char const *owner, char const *repo, int const issue, char const *const labels[], size_t const labels_size) { - char *url = NULL; - char *e_label = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *e_label = NULL; + int rc = 0; if (labels_size != 1) errx(1, "error: GitHub only supports removing labels from " @@ -330,11 +331,12 @@ github_issue_remove_labels(char const *owner, url = sn_asprintf("%s/repos/%s/%s/issues/%d/labels/%s", gcli_get_apibase(), owner, repo, issue, e_label); - gcli_fetch_with_method("DELETE", url, NULL, NULL, &buffer); + rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); free(url); free(e_label); - free(buffer.data); + + return rc; } int diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index 03bb73e1..debc4615 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -288,17 +288,17 @@ gitlab_issue_assign(char const *owner, free(post_data); } -void +int gitlab_issue_add_labels(char const *owner, char const *repo, int const issue, char const *const labels[], size_t const labels_size) { - char *url = NULL; - char *data = NULL; - char *list = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *data = NULL; + char *list = NULL; + int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gitlab_get_apibase(), owner, repo, issue); @@ -306,25 +306,26 @@ gitlab_issue_add_labels(char const *owner, list = sn_join_with(labels, labels_size, ","); data = sn_asprintf("{ \"add_labels\": \"%s\"}", list); - gcli_fetch_with_method("PUT", url, data, NULL, &buffer); + rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); free(url); free(data); free(list); - free(buffer.data); + + return rc; } -void +int gitlab_issue_remove_labels(char const *owner, char const *repo, int const issue, char const *const labels[], size_t const labels_size) { - char *url = NULL; - char *data = NULL; - char *list = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *data = NULL; + char *list = NULL; + int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gitlab_get_apibase(), owner, repo, issue); @@ -332,12 +333,13 @@ gitlab_issue_remove_labels(char const *owner, list = sn_join_with(labels, labels_size, ","); data = sn_asprintf("{ \"remove_labels\": \"%s\"}", list); - gcli_fetch_with_method("PUT", url, data, NULL, &buffer); + rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); free(url); free(data); free(list); - free(buffer.data); + + return rc; } int diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index 3fcbeeaa..343adca9 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -379,17 +379,17 @@ gitlab_perform_submit_mr(gcli_submit_pull_options opts) free(url); } -void +int gitlab_mr_add_labels(char const *owner, char const *repo, int const mr, char const *const labels[], size_t const labels_size) { - char *url = NULL; - char *data = NULL; - char *list = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *data = NULL; + char *list = NULL; + int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", gitlab_get_apibase(), owner, repo, mr); @@ -397,25 +397,26 @@ gitlab_mr_add_labels(char const *owner, list = sn_join_with(labels, labels_size, ","); data = sn_asprintf("{ \"add_labels\": \"%s\"}", list); - gcli_fetch_with_method("PUT", url, data, NULL, &buffer); + rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); free(url); free(data); free(list); - free(buffer.data); + + return rc; } -void +int gitlab_mr_remove_labels(char const *owner, char const *repo, int const mr, char const *const labels[], size_t const labels_size) { - char *url = NULL; - char *data = NULL; - char *list = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *data = NULL; + char *list = NULL; + int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", gitlab_get_apibase(), owner, repo, mr); @@ -423,12 +424,13 @@ gitlab_mr_remove_labels(char const *owner, list = sn_join_with(labels, labels_size, ","); data = sn_asprintf("{ \"remove_labels\": \"%s\"}", list); - gcli_fetch_with_method("PUT", url, data, NULL, &buffer); + rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); free(url); free(data); free(list); - free(buffer.data); + + return rc; } int diff --git a/src/issues.c b/src/issues.c index de41ef7f..a7269da2 100644 --- a/src/issues.c +++ b/src/issues.c @@ -268,24 +268,24 @@ gcli_issue_assign(char const *owner, gcli_forge()->issue_assign(owner, repo, issue_number, assignee); } -void +int gcli_issue_add_labels(char const *owner, char const *repo, int const issue, char const *const labels[], size_t const labels_size) { - gcli_forge()->issue_add_labels(owner, repo, issue, labels, labels_size); + return gcli_forge()->issue_add_labels(owner, repo, issue, labels, labels_size); } -void +int gcli_issue_remove_labels(char const *owner, char const *repo, int const issue, char const *const labels[], size_t const labels_size) { - gcli_forge()->issue_remove_labels(owner, repo, issue, labels, labels_size); + return gcli_forge()->issue_remove_labels(owner, repo, issue, labels, labels_size); } int diff --git a/src/pulls.c b/src/pulls.c index 4a68efa5..6c381d72 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -373,25 +373,25 @@ gcli_pull_reopen(char const *owner, char const *reponame, int const pr_number) gcli_forge()->pr_reopen(owner, reponame, pr_number); } -void +int gcli_pull_add_labels(char const *owner, char const *repo, int const pr_number, char const *const labels[], size_t const labels_size) { - gcli_forge()->pr_add_labels( + return gcli_forge()->pr_add_labels( owner, repo, pr_number, labels, labels_size); } -void +int gcli_pull_remove_labels(char const *owner, char const *repo, int const pr_number, char const *const labels[], size_t const labels_size) { - gcli_forge()->pr_remove_labels( + return gcli_forge()->pr_remove_labels( owner, repo, pr_number, labels, labels_size); } From f873f5f29f567285f1cc65721aca6e6cd5839051 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 12 Aug 2023 23:56:35 +0200 Subject: [PATCH 023/236] (#190) Make issue_assign return error codes --- include/gcli/forges.h | 2 +- include/gcli/gitea/issues.h | 8 ++++---- include/gcli/github/issues.h | 8 ++++---- include/gcli/gitlab/issues.h | 8 ++++---- include/gcli/issues.h | 8 ++++---- src/cmd/issues.c | 3 ++- src/gitea/issues.c | 19 ++++++++++--------- src/github/issues.c | 19 ++++++++++--------- src/gitlab/issues.c | 19 ++++++++++--------- src/issues.c | 4 ++-- 10 files changed, 51 insertions(+), 47 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 9bfe538a..7d57ca4b 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -123,7 +123,7 @@ struct gcli_forge_descriptor { /** * Assign an issue to a user */ - void (*issue_assign)( + int (*issue_assign)( char const *owner, char const *repo, int issue_number, diff --git a/include/gcli/gitea/issues.h b/include/gcli/gitea/issues.h index efa98609..5524fadb 100644 --- a/include/gcli/gitea/issues.h +++ b/include/gcli/gitea/issues.h @@ -58,10 +58,10 @@ int gitea_issue_reopen(char const *owner, char const *repo, int issue_number); -void gitea_issue_assign(char const *owner, - char const *repo, - int issue_number, - char const *assignee); +int gitea_issue_assign(char const *owner, + char const *repo, + int issue_number, + char const *assignee); int gitea_issue_add_labels(char const *owner, char const *repo, diff --git a/include/gcli/github/issues.h b/include/gcli/github/issues.h index 11222c7b..319a813d 100644 --- a/include/gcli/github/issues.h +++ b/include/gcli/github/issues.h @@ -63,10 +63,10 @@ int github_issue_reopen(char const *owner, int github_perform_submit_issue(gcli_submit_issue_options opts, gcli_fetch_buffer *out); -void github_issue_assign(char const *owner, - char const *repo, - int issue_number, - char const *assignee); +int github_issue_assign(char const *owner, + char const *repo, + int issue_number, + char const *assignee); int github_issue_add_labels(char const *owner, char const *repo, diff --git a/include/gcli/gitlab/issues.h b/include/gcli/gitlab/issues.h index b0b0fb9f..ebd5ac0a 100644 --- a/include/gcli/gitlab/issues.h +++ b/include/gcli/gitlab/issues.h @@ -60,10 +60,10 @@ int gitlab_issue_reopen(char const *owner, char const *repo, int issue_number); -void gitlab_issue_assign(char const *owner, - char const *repo, - int issue_number, - char const *assignee); +int gitlab_issue_assign(char const *owner, + char const *repo, + int issue_number, + char const *assignee); int gitlab_perform_submit_issue(gcli_submit_issue_options opts, gcli_fetch_buffer *out); diff --git a/include/gcli/issues.h b/include/gcli/issues.h index a515748b..7a16b9f3 100644 --- a/include/gcli/issues.h +++ b/include/gcli/issues.h @@ -112,10 +112,10 @@ int gcli_issue_reopen(char const *owner, int gcli_issue_submit(gcli_submit_issue_options); -void gcli_issue_assign(char const *owner, - char const *repo, - int issue_number, - char const *assignee); +int gcli_issue_assign(char const *owner, + char const *repo, + int issue_number, + char const *assignee); int gcli_issue_add_labels(char const *owner, char const *repo, diff --git a/src/cmd/issues.c b/src/cmd/issues.c index c9843bf1..8578cfa8 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -420,7 +420,8 @@ handle_issues_actions(int argc, char *argv[], } else if (strcmp("assign", operation) == 0) { char const *assignee = shift(&argc, &argv); - gcli_issue_assign(owner, repo, issue_id, assignee); + if (gcli_issue_assign(owner, repo, issue_id, assignee) < 0) + errx(1, "failed to assign issue"); } else if (strcmp("labels", operation) == 0) { diff --git a/src/gitea/issues.c b/src/gitea/issues.c index eaebb4c2..89a969b5 100644 --- a/src/gitea/issues.c +++ b/src/gitea/issues.c @@ -112,18 +112,18 @@ gitea_issue_reopen(char const *owner, return gitea_issue_patch_state(owner, repo, issue_number, "open"); } -void +int gitea_issue_assign(char const *owner, char const *repo, int const issue_number, char const *const assignee) { - gcli_fetch_buffer buffer = {0}; - sn_sv escaped_assignee = SV_NULL; - char *post_fields = NULL; - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + sn_sv escaped_assignee = SV_NULL; + char *post_fields = NULL; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; escaped_assignee = gcli_json_escape(SV((char *)assignee)); post_fields = sn_asprintf("{ \"assignees\": [\""SV_FMT"\"] }", @@ -136,14 +136,15 @@ gitea_issue_assign(char const *owner, "%s/repos/%s/%s/issues/%d", gitea_get_apibase(), e_owner, e_repo, issue_number); - gcli_fetch_with_method("PATCH", url, post_fields, NULL, &buffer); + rc = gcli_fetch_with_method("PATCH", url, post_fields, NULL, NULL); - free(buffer.data); free(escaped_assignee.data); free(post_fields); free(e_owner); free(e_repo); free(url); + + return rc; } /* Return the stringified id of the given label */ diff --git a/src/github/issues.c b/src/github/issues.c index b511d687..53adfddb 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -248,18 +248,18 @@ github_perform_submit_issue(gcli_submit_issue_options opts, return rc; } -void +int github_issue_assign(char const *owner, char const *repo, int const issue_number, char const *assignee) { - gcli_fetch_buffer buffer = {0}; - sn_sv escaped_assignee = SV_NULL; - char *post_fields = NULL; - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + sn_sv escaped_assignee = SV_NULL; + char *post_fields = NULL; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; escaped_assignee = gcli_json_escape(SV((char *)assignee)); post_fields = sn_asprintf("{ \"assignees\": [\""SV_FMT"\"] }", @@ -272,14 +272,15 @@ github_issue_assign(char const *owner, "%s/repos/%s/%s/issues/%d/assignees", gcli_get_apibase(), e_owner, e_repo, issue_number); - gcli_fetch_with_method("POST", url, post_fields, NULL, &buffer); + rc = gcli_fetch_with_method("POST", url, post_fields, NULL, NULL); - free(buffer.data); free(escaped_assignee.data); free(post_fields); free(e_owner); free(e_repo); free(url); + + return rc; } int diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index debc4615..5e272f51 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -257,18 +257,18 @@ gitlab_user_id(char const *user_name) return uid; } -void +int gitlab_issue_assign(char const *owner, char const *repo, int const issue_number, char const *assignee) { - int assignee_uid = -1; - gcli_fetch_buffer buffer = {0}; - char *url = NULL; - char *post_data = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + int assignee_uid = -1; + char *url = NULL; + char *post_data = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; assignee_uid = gitlab_user_id(assignee); @@ -279,13 +279,14 @@ gitlab_issue_assign(char const *owner, gitlab_get_apibase(), e_owner, e_repo, issue_number); post_data = sn_asprintf("{ \"assignee_ids\": [ %d ] }", assignee_uid); - gcli_fetch_with_method("PUT", url, post_data, NULL, &buffer); + rc = gcli_fetch_with_method("PUT", url, post_data, NULL, NULL); free(e_owner); free(e_repo); - free(buffer.data); free(url); free(post_data); + + return rc; } int diff --git a/src/issues.c b/src/issues.c index a7269da2..4857815d 100644 --- a/src/issues.c +++ b/src/issues.c @@ -259,13 +259,13 @@ gcli_issue_submit(gcli_submit_issue_options opts) return rc; } -void +int gcli_issue_assign(char const *owner, char const *repo, int const issue_number, char const *assignee) { - gcli_forge()->issue_assign(owner, repo, issue_number, assignee); + return gcli_forge()->issue_assign(owner, repo, issue_number, assignee); } int From 27d6cf310daf55fa08621f29c96e4697da8f8d39 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 00:02:58 +0200 Subject: [PATCH 024/236] Make issue_set_milestone routines check error status of fetch --- src/github/issues.c | 5 +++-- src/gitlab/issues.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/github/issues.c b/src/github/issues.c index 53adfddb..91f749d2 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -347,6 +347,7 @@ github_issue_set_milestone(char const *const owner, int const milestone) { char *url, *e_owner, *e_repo, *body; + int rc; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -357,14 +358,14 @@ github_issue_set_milestone(char const *const owner, body = sn_asprintf("{ \"milestone\": %d }", milestone); - gcli_fetch_with_method("PATCH", url, body, NULL, NULL); + rc = gcli_fetch_with_method("PATCH", url, body, NULL, NULL); free(body); free(url); free(e_repo); free(e_owner); - return 0; + return rc; } int diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index 5e272f51..ea84a6b1 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -350,19 +350,20 @@ gitlab_issue_set_milestone(char const *const owner, int const milestone) { char *url, *e_owner, *e_repo; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d?milestone_id=%d", gitlab_get_apibase(), e_owner, e_repo, issue, milestone); - gcli_fetch_with_method("PUT", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method("PUT", url, NULL, NULL, NULL); free(url); free(e_repo); free(e_owner); - return 0; + return rc; } int From ccb9687ffa30a102c7e5ddaebdec969358bd0c41 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 00:05:56 +0200 Subject: [PATCH 025/236] (#190) Make issue_clear_milestone check error status of fetch --- src/cmd/pulls.c | 3 ++- src/github/issues.c | 5 +++-- src/gitlab/issues.c | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 8c63a64e..b8ed7e28 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -502,7 +502,8 @@ handle_pull_actions(int argc, char *argv[], char const *arg = shift(&argc, &argv); if (strcmp(arg, "-d") == 0) { - gcli_pull_clear_milestone(owner, repo, pr); + if (gcli_pull_clear_milestone(owner, repo, pr) < 0) + errx(1, "failed to clear milestone"); } else { int milestone_id = 0; diff --git a/src/github/issues.c b/src/github/issues.c index 91f749d2..2a2413e3 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -374,6 +374,7 @@ github_issue_clear_milestone(char const *const owner, int const issue) { char *url, *e_owner, *e_repo, *body; + int rc; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -384,12 +385,12 @@ github_issue_clear_milestone(char const *const owner, body = sn_asprintf("{ \"milestone\": null }"); - gcli_fetch_with_method("PATCH", url, body, NULL, NULL); + rc = gcli_fetch_with_method("PATCH", url, body, NULL, NULL); free(body); free(url); free(e_repo); free(e_owner); - return 0; + return rc; } diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index ea84a6b1..5fedb5d6 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -372,6 +372,7 @@ gitlab_issue_clear_milestone(char const *const owner, int const issue) { char *url, *e_owner, *e_repo, *payload; + int rc; /* The Gitlab API says: * @@ -391,12 +392,12 @@ gitlab_issue_clear_milestone(char const *const owner, gitlab_get_apibase(), e_owner, e_repo, issue); payload = sn_asprintf("{ \"milestone_id\": null }"); - gcli_fetch_with_method("PUT", url, payload, NULL, NULL); + rc = gcli_fetch_with_method("PUT", url, payload, NULL, NULL); free(payload); free(url); free(e_repo); free(e_owner); - return 0; + return rc; } From 6bd62119d5a4bc5e0c33f4a6883a8307bf66474b Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 02:06:29 +0200 Subject: [PATCH 026/236] (#190) Make create_release routines return error codes Not yet fully complete as we ignore the results from potential asset uploads --- include/gcli/forges.h | 2 +- include/gcli/gitea/releases.h | 2 +- include/gcli/github/releases.h | 2 +- include/gcli/gitlab/releases.h | 2 +- include/gcli/releases.h | 2 +- src/cmd/releases.c | 3 ++- src/gitea/releases.c | 11 +++++++++-- src/github/releases.c | 11 +++++++++-- src/gitlab/releases.c | 25 +++++++++++++------------ src/releases.c | 4 ++-- 10 files changed, 40 insertions(+), 24 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 7d57ca4b..52ac84cd 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -345,7 +345,7 @@ struct gcli_forge_descriptor { /** * Create a new release */ - void (*create_release)( + int (*create_release)( gcli_new_release const *release); /** diff --git a/include/gcli/gitea/releases.h b/include/gcli/gitea/releases.h index 5e620a1e..8ca3547d 100644 --- a/include/gcli/gitea/releases.h +++ b/include/gcli/gitea/releases.h @@ -41,7 +41,7 @@ int gitea_get_releases(char const *owner, int max, gcli_release_list *list); -void gitea_create_release(gcli_new_release const *release); +int gitea_create_release(gcli_new_release const *release); void gitea_delete_release(char const *owner, char const *repo, diff --git a/include/gcli/github/releases.h b/include/gcli/github/releases.h index dcb3d249..f657195c 100644 --- a/include/gcli/github/releases.h +++ b/include/gcli/github/releases.h @@ -41,7 +41,7 @@ int github_get_releases(char const *owner, int max, gcli_release_list *list); -void github_create_release(gcli_new_release const *release); +int github_create_release(gcli_new_release const *release); void github_delete_release(char const *owner, char const *repo, diff --git a/include/gcli/gitlab/releases.h b/include/gcli/gitlab/releases.h index 9f3893da..f50991b6 100644 --- a/include/gcli/gitlab/releases.h +++ b/include/gcli/gitlab/releases.h @@ -41,7 +41,7 @@ int gitlab_get_releases(char const *owner, int max, gcli_release_list *list); -void gitlab_create_release(gcli_new_release const *release); +int gitlab_create_release(gcli_new_release const *release); void gitlab_delete_release(char const *owner, char const *repo, diff --git a/include/gcli/releases.h b/include/gcli/releases.h index a0384dd6..a8d070a8 100644 --- a/include/gcli/releases.h +++ b/include/gcli/releases.h @@ -98,7 +98,7 @@ void gcli_print_releases(enum gcli_output_flags flags, void gcli_free_releases(gcli_release_list *); -void gcli_create_release(gcli_new_release const *); +int gcli_create_release(gcli_new_release const *); void gcli_release_push_asset(gcli_new_release *, gcli_release_asset_upload); diff --git a/src/cmd/releases.c b/src/cmd/releases.c index 2b1df7cb..dfc50738 100644 --- a/src/cmd/releases.c +++ b/src/cmd/releases.c @@ -192,7 +192,8 @@ subcommand_releases_create(int argc, char *argv[]) if (!sn_yesno("Do you want to create this release?")) errx(1, "Aborted by user"); - gcli_create_release(&release); + if (gcli_create_release(&release) < 0) + errx(1, "failed to create release"); return EXIT_SUCCESS; } diff --git a/src/gitea/releases.c b/src/gitea/releases.c index 482e7e3d..790bf8d6 100644 --- a/src/gitea/releases.c +++ b/src/gitea/releases.c @@ -71,7 +71,7 @@ gitea_upload_release_asset(char *const url, free(buffer.data); } -void +int gitea_create_release(gcli_new_release const *release) { char *commitish_json = NULL; @@ -84,6 +84,7 @@ gitea_create_release(gcli_new_release const *release) gcli_fetch_buffer buffer = {0}; gcli_release response = {0}; sn_sv escaped_body = {0}; + int rc = 0; e_owner = gcli_urlencode(release->owner); e_repo = gcli_urlencode(release->repo); @@ -119,7 +120,10 @@ gitea_create_release(gcli_new_release const *release) commitish_json ? commitish_json : "", name_json ? name_json : ""); - gcli_fetch_with_method("POST", url, post_data, NULL, &buffer); + rc = gcli_fetch_with_method("POST", url, post_data, NULL, &buffer); + if (rc < 0) + goto out; + gitea_parse_release(&buffer, &response); printf("INFO : Release at "SV_FMT"\n", SV_ARGS(response.html_url)); @@ -133,6 +137,7 @@ gitea_create_release(gcli_new_release const *release) gitea_upload_release_asset(upload_url, release->assets[i]); } +out: free(upload_url); free(buffer.data); free(url); @@ -142,6 +147,8 @@ gitea_create_release(gcli_new_release const *release) free(e_repo); free(name_json); free(commitish_json); + + return rc; } void diff --git a/src/github/releases.c b/src/github/releases.c index 605a7426..4e9799b8 100644 --- a/src/github/releases.c +++ b/src/github/releases.c @@ -127,7 +127,7 @@ github_upload_release_asset(char const *url, free(buffer.data); } -void +int github_create_release(gcli_new_release const *release) { char *url = NULL; @@ -140,6 +140,7 @@ github_create_release(gcli_new_release const *release) sn_sv escaped_body = {0}; gcli_fetch_buffer buffer = {0}; gcli_release response = {0}; + int rc = 0; assert(release); @@ -179,7 +180,10 @@ github_create_release(gcli_new_release const *release) commitish_json ? commitish_json : "", name_json ? name_json : ""); - gcli_fetch_with_method("POST", url, post_data, NULL, &buffer); + rc = gcli_fetch_with_method("POST", url, post_data, NULL, &buffer); + if (rc < 0) + goto out; + github_parse_single_release(buffer, &response); printf("INFO : Release at "SV_FMT"\n", SV_ARGS(response.html_url)); @@ -191,6 +195,7 @@ github_create_release(gcli_new_release const *release) github_upload_release_asset(upload_url, release->assets[i]); } +out: free(upload_url); free(buffer.data); free(url); @@ -200,6 +205,8 @@ github_create_release(gcli_new_release const *release) free(e_repo); free(name_json); free(commitish_json); + + return rc; } void diff --git a/src/gitlab/releases.c b/src/gitlab/releases.c index 9fcb250d..ad73050a 100644 --- a/src/gitlab/releases.c +++ b/src/gitlab/releases.c @@ -101,18 +101,18 @@ gitlab_get_releases(char const *owner, return 0; } -void +int gitlab_create_release(gcli_new_release const *release) { - char *url = NULL; - char *upload_url = NULL; - char *post_data = NULL; - char *name_json = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - char *commitish_json = NULL; - sn_sv escaped_body = {0}; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *upload_url = NULL; + char *post_data = NULL; + char *name_json = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + char *commitish_json = NULL; + sn_sv escaped_body = {0}; + int rc = 0; e_owner = gcli_urlencode(release->owner); e_repo = gcli_urlencode(release->repo); @@ -153,13 +153,12 @@ gitlab_create_release(gcli_new_release const *release) commitish_json ? commitish_json : "", name_json ? name_json : ""); - gcli_fetch_with_method("POST", url, post_data, NULL, &buffer); + rc = gcli_fetch_with_method("POST", url, post_data, NULL, NULL); if (release->assets_size) warnx("GitLab release asset uploads are not yet supported"); free(upload_url); - free(buffer.data); free(url); free(post_data); free(escaped_body.data); @@ -167,6 +166,8 @@ gitlab_create_release(gcli_new_release const *release) free(commitish_json); free(e_owner); free(e_repo); + + return rc; } void diff --git a/src/releases.c b/src/releases.c index 910f8b2b..22e54559 100644 --- a/src/releases.c +++ b/src/releases.c @@ -187,10 +187,10 @@ gcli_free_releases(gcli_release_list *const list) list->releases_size = 0; } -void +int gcli_create_release(gcli_new_release const *release) { - gcli_forge()->create_release(release); + return gcli_forge()->create_release(release); } void From 95b0ee037cf66bfc534724a4067b3b27336cec1b Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 11:46:31 +0200 Subject: [PATCH 027/236] (#190) Make delete_release return error codes --- include/gcli/forges.h | 2 +- include/gcli/gitea/releases.h | 6 +++--- include/gcli/github/releases.h | 6 +++--- include/gcli/gitlab/releases.h | 6 +++--- include/gcli/releases.h | 6 +++--- src/cmd/releases.c | 3 ++- src/gitea/releases.c | 4 ++-- src/github/releases.c | 15 ++++++++------- src/gitlab/releases.c | 15 ++++++++------- src/releases.c | 4 ++-- 10 files changed, 35 insertions(+), 32 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 52ac84cd..4b3cd576 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -350,7 +350,7 @@ struct gcli_forge_descriptor { /** * Delete the release */ - void (*delete_release)( + int (*delete_release)( char const *owner, char const *repo, char const *id); diff --git a/include/gcli/gitea/releases.h b/include/gcli/gitea/releases.h index 8ca3547d..eee3e7dc 100644 --- a/include/gcli/gitea/releases.h +++ b/include/gcli/gitea/releases.h @@ -43,8 +43,8 @@ int gitea_get_releases(char const *owner, int gitea_create_release(gcli_new_release const *release); -void gitea_delete_release(char const *owner, - char const *repo, - char const *id); +int gitea_delete_release(char const *owner, + char const *repo, + char const *id); #endif /* GITEA_RELEASES_H */ diff --git a/include/gcli/github/releases.h b/include/gcli/github/releases.h index f657195c..36ff16fa 100644 --- a/include/gcli/github/releases.h +++ b/include/gcli/github/releases.h @@ -43,8 +43,8 @@ int github_get_releases(char const *owner, int github_create_release(gcli_new_release const *release); -void github_delete_release(char const *owner, - char const *repo, - char const *id); +int github_delete_release(char const *owner, + char const *repo, + char const *id); #endif /* GITHUB_RELEASES_H */ diff --git a/include/gcli/gitlab/releases.h b/include/gcli/gitlab/releases.h index f50991b6..3367bde6 100644 --- a/include/gcli/gitlab/releases.h +++ b/include/gcli/gitlab/releases.h @@ -43,8 +43,8 @@ int gitlab_get_releases(char const *owner, int gitlab_create_release(gcli_new_release const *release); -void gitlab_delete_release(char const *owner, - char const *repo, - char const *id); +int gitlab_delete_release(char const *owner, + char const *repo, + char const *id); #endif /* GITLAB_RELEASES_H */ diff --git a/include/gcli/releases.h b/include/gcli/releases.h index a8d070a8..2caa7e0e 100644 --- a/include/gcli/releases.h +++ b/include/gcli/releases.h @@ -103,8 +103,8 @@ int gcli_create_release(gcli_new_release const *); void gcli_release_push_asset(gcli_new_release *, gcli_release_asset_upload); -void gcli_delete_release(char const *owner, - char const *repo, - char const *id); +int gcli_delete_release(char const *owner, + char const *repo, + char const *id); #endif /* RELEASES_H */ diff --git a/src/cmd/releases.c b/src/cmd/releases.c index dfc50738..7f515254 100644 --- a/src/cmd/releases.c +++ b/src/cmd/releases.c @@ -255,7 +255,8 @@ subcommand_releases_delete(int argc, char *argv[]) if (!sn_yesno("Are you sure you want to delete this release?")) errx(1, "Aborted by user"); - gcli_delete_release(owner, repo, argv[0]); + if (gcli_delete_release(owner, repo, argv[0]) < 0) + errx(1, "failed to delete the release"); return EXIT_SUCCESS; } diff --git a/src/gitea/releases.c b/src/gitea/releases.c index 790bf8d6..32e130e7 100644 --- a/src/gitea/releases.c +++ b/src/gitea/releases.c @@ -151,8 +151,8 @@ gitea_create_release(gcli_new_release const *release) return rc; } -void +int gitea_delete_release(char const *owner, char const *repo, char const *id) { - github_delete_release(owner, repo, id); + return github_delete_release(owner, repo, id); } diff --git a/src/github/releases.c b/src/github/releases.c index 4e9799b8..fc859fb2 100644 --- a/src/github/releases.c +++ b/src/github/releases.c @@ -209,13 +209,13 @@ github_create_release(gcli_new_release const *release) return rc; } -void +int github_delete_release(char const *owner, char const *repo, char const *id) { - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -224,10 +224,11 @@ github_delete_release(char const *owner, char const *repo, char const *id) "%s/repos/%s/%s/releases/%s", gcli_get_apibase(), e_owner, e_repo, id); - gcli_fetch_with_method("DELETE", url, NULL, NULL, &buffer); + rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); free(url); free(e_owner); free(e_repo); - free(buffer.data); + + return rc; } diff --git a/src/gitlab/releases.c b/src/gitlab/releases.c index ad73050a..aeec7594 100644 --- a/src/gitlab/releases.c +++ b/src/gitlab/releases.c @@ -170,13 +170,13 @@ gitlab_create_release(gcli_new_release const *release) return rc; } -void +int gitlab_delete_release(char const *owner, char const *repo, char const *id) { - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -186,10 +186,11 @@ gitlab_delete_release(char const *owner, char const *repo, char const *id) gitlab_get_apibase(), e_owner, e_repo, id); - gcli_fetch_with_method("DELETE", url, NULL, NULL, &buffer); + rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); free(url); free(e_owner); free(e_repo); - free(buffer.data); + + return rc; } diff --git a/src/releases.c b/src/releases.c index 22e54559..d3525486 100644 --- a/src/releases.c +++ b/src/releases.c @@ -203,10 +203,10 @@ gcli_release_push_asset(gcli_new_release *const release, release->assets[release->assets_size++] = asset; } -void +int gcli_delete_release(char const *const owner, char const *const repo, char const *const id) { - gcli_forge()->delete_release(owner, repo, id); + return gcli_forge()->delete_release(owner, repo, id); } From d97857f984d4f422803a8c088df623e49aae6305 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 11:50:13 +0200 Subject: [PATCH 028/236] (#190) Make notification_mark_as_read return error codes --- include/gcli/forges.h | 2 +- include/gcli/github/status.h | 2 +- include/gcli/gitlab/status.h | 2 +- include/gcli/status.h | 2 +- src/cmd/status.c | 3 ++- src/github/status.c | 11 ++++++----- src/gitlab/status.c | 11 ++++++----- src/status.c | 4 ++-- 8 files changed, 20 insertions(+), 17 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 4b3cd576..3001ce34 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -421,7 +421,7 @@ struct gcli_forge_descriptor { * Mark notification with the given id as read * * Returns 0 on success or negative code on failure. */ - void (*notification_mark_as_read)( + int (*notification_mark_as_read)( char const *id); /** diff --git a/include/gcli/github/status.h b/include/gcli/github/status.h index 9c4dce26..93450efb 100644 --- a/include/gcli/github/status.h +++ b/include/gcli/github/status.h @@ -39,6 +39,6 @@ size_t github_get_notifications(gcli_notification **notifications, int count); -void github_notification_mark_as_read(char const *id); +int github_notification_mark_as_read(char const *id); #endif /* GITHUB_STATUS_H */ diff --git a/include/gcli/gitlab/status.h b/include/gcli/gitlab/status.h index 7d974999..d2116e14 100644 --- a/include/gcli/gitlab/status.h +++ b/include/gcli/gitlab/status.h @@ -39,6 +39,6 @@ size_t gitlab_get_notifications(gcli_notification **notifications, int count); -void gitlab_notification_mark_as_read(char const *id); +int gitlab_notification_mark_as_read(char const *id); #endif /* GITLAB_STATUS_H */ diff --git a/include/gcli/status.h b/include/gcli/status.h index ddb639e8..b2b42401 100644 --- a/include/gcli/status.h +++ b/include/gcli/status.h @@ -51,7 +51,7 @@ void gcli_status(int count); size_t gcli_get_notifications(gcli_notification **out, int count); -void gcli_notification_mark_as_read(char const *id); +int gcli_notification_mark_as_read(char const *id); void gcli_free_notifications(gcli_notification *, size_t); diff --git a/src/cmd/status.c b/src/cmd/status.c index 49777cd7..7d94988f 100644 --- a/src/cmd/status.c +++ b/src/cmd/status.c @@ -106,7 +106,8 @@ subcommand_status(int argc, char *argv[]) return EXIT_FAILURE; } - gcli_notification_mark_as_read(argv[0]); + if (gcli_notification_mark_as_read(argv[0]) < 0) + errx(1, "failed to mark the notification as read"); } return EXIT_SUCCESS; diff --git a/src/github/status.c b/src/github/status.c index c36340ea..4db796f6 100644 --- a/src/github/status.c +++ b/src/github/status.c @@ -64,18 +64,19 @@ github_get_notifications(gcli_notification **const notifications, return notifications_size; } -void +int github_notification_mark_as_read(char const *id) { - char *url = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + int rc = 0; url = sn_asprintf( "%s/notifications/threads/%s", gcli_get_apibase(), id); - gcli_fetch_with_method("PATCH", url, NULL, NULL, &buffer); + rc = gcli_fetch_with_method("PATCH", url, NULL, NULL, NULL); free(url); - free(buffer.data); + + return rc; } diff --git a/src/gitlab/status.c b/src/gitlab/status.c index c985fffb..d3b069bb 100644 --- a/src/gitlab/status.c +++ b/src/gitlab/status.c @@ -64,15 +64,16 @@ gitlab_get_notifications(gcli_notification **const notifications, return notifications_size; } -void +int gitlab_notification_mark_as_read(char const *id) { - char *url = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + int rc = 0; url = sn_asprintf("%s/todos/%s/mark_as_done", gitlab_get_apibase(), id); - gcli_fetch_with_method("POST", url, NULL, NULL, &buffer); + rc = gcli_fetch_with_method("POST", url, NULL, NULL, NULL); free(url); - free(buffer.data); + + return rc; } diff --git a/src/status.c b/src/status.c index 69dc16c7..1431c39f 100644 --- a/src/status.c +++ b/src/status.c @@ -87,8 +87,8 @@ gcli_print_notifications(gcli_notification const *const notifications, } } -void +int gcli_notification_mark_as_read(char const *id) { - gcli_forge()->notification_mark_as_read(id); + return gcli_forge()->notification_mark_as_read(id); } From f980d6eba29b2d1c9bbc04428ae0eb3cfd08f850 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 11:53:15 +0200 Subject: [PATCH 029/236] (#190) Make all create_milestone routines return error codes --- src/github/milestones.c | 5 +++-- src/gitlab/milestones.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/github/milestones.c b/src/github/milestones.c index 3a632c29..0ff99d9f 100644 --- a/src/github/milestones.c +++ b/src/github/milestones.c @@ -132,6 +132,7 @@ github_create_milestone(struct gcli_milestone_create_args const *args) { char *url, *e_owner, *e_repo; char *json_body, *description; + int rc = 0; e_owner = gcli_urlencode(args->owner); e_repo = gcli_urlencode(args->repo); @@ -154,7 +155,7 @@ github_create_milestone(struct gcli_milestone_create_args const *args) url = sn_asprintf("%s/repos/%s/%s/milestones", gcli_get_apibase(), e_owner, e_repo); - gcli_fetch_with_method("POST", url, json_body, NULL, NULL); + rc = gcli_fetch_with_method("POST", url, json_body, NULL, NULL); free(json_body); free(description); @@ -162,7 +163,7 @@ github_create_milestone(struct gcli_milestone_create_args const *args) free(e_repo); free(e_owner); - return 0; + return rc; } int diff --git a/src/gitlab/milestones.c b/src/gitlab/milestones.c index 7bd970a3..f4187ed0 100644 --- a/src/gitlab/milestones.c +++ b/src/gitlab/milestones.c @@ -133,6 +133,7 @@ int gitlab_create_milestone(struct gcli_milestone_create_args const *args) { char *url, *e_owner, *e_repo, *e_title, *json_body, *description = NULL; + int rc = 0; e_owner = gcli_urlencode(args->owner); e_repo = gcli_urlencode(args->repo); @@ -155,7 +156,7 @@ gitlab_create_milestone(struct gcli_milestone_create_args const *args) "}", e_title, description ? description : ""); - gcli_fetch_with_method("POST", url, json_body, NULL, NULL); + rc = gcli_fetch_with_method("POST", url, json_body, NULL, NULL); free(json_body); free(description); @@ -164,7 +165,7 @@ gitlab_create_milestone(struct gcli_milestone_create_args const *args) free(e_repo); free(e_owner); - return 0; + return rc; } int From dcc0cd5ca8911169bef93a136cf412f7df70dd8a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 11:56:13 +0200 Subject: [PATCH 030/236] (#190) Make delete_milestone routines return error codes --- src/github/milestones.c | 5 +++-- src/gitlab/milestones.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/github/milestones.c b/src/github/milestones.c index 0ff99d9f..c28e3457 100644 --- a/src/github/milestones.c +++ b/src/github/milestones.c @@ -172,6 +172,7 @@ github_delete_milestone(char const *const owner, int const milestone) { char *url, *e_owner, *e_repo; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -181,13 +182,13 @@ github_delete_milestone(char const *const owner, e_owner, e_repo, milestone); - gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); free(url); free(e_repo); free(e_owner); - return 0; + return rc; } static void diff --git a/src/gitlab/milestones.c b/src/gitlab/milestones.c index f4187ed0..117d2122 100644 --- a/src/gitlab/milestones.c +++ b/src/gitlab/milestones.c @@ -174,6 +174,7 @@ gitlab_delete_milestone(char const *const owner, int const milestone) { char *url, *e_owner, *e_repo; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -181,13 +182,13 @@ gitlab_delete_milestone(char const *const owner, url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d", gitlab_get_apibase(), e_owner, e_repo, milestone); - gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); free(url); free(e_repo); free(e_owner); - return 0; + return rc; } /* TODO: merge this with the github code */ From ade84a57b7f67778305580fd41864cf52cb8fd0c Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 11:58:36 +0200 Subject: [PATCH 031/236] (#190) Make milestone_set_duedate routines return error codes --- src/github/milestones.c | 5 +++-- src/gitlab/milestones.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/github/milestones.c b/src/github/milestones.c index c28e3457..a9462f65 100644 --- a/src/github/milestones.c +++ b/src/github/milestones.c @@ -226,6 +226,7 @@ github_milestone_set_duedate(char const *const owner, char const *const date) { char *url, *e_owner, *e_repo, *payload, norm_date[21] = {0}; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -237,12 +238,12 @@ github_milestone_set_duedate(char const *const owner, normalize_date_to_iso8601(date, norm_date, sizeof norm_date); payload = sn_asprintf("{ \"due_on\": \"%s\"}", norm_date); - gcli_fetch_with_method("PATCH", url, payload, NULL, NULL); + rc = gcli_fetch_with_method("PATCH", url, payload, NULL, NULL); free(payload); free(url); free(e_repo); free(e_owner); - return 0; + return rc; } diff --git a/src/gitlab/milestones.c b/src/gitlab/milestones.c index 117d2122..ee1b0094 100644 --- a/src/gitlab/milestones.c +++ b/src/gitlab/milestones.c @@ -227,6 +227,7 @@ gitlab_milestone_set_duedate(char const *const owner, char const *const date) { char *url, *e_owner, *e_repo, norm_date[9] = {0}; + int rc = 0; normalize_date_to_gitlab_format(date, norm_date, sizeof norm_date); @@ -237,11 +238,11 @@ gitlab_milestone_set_duedate(char const *const owner, gitlab_get_apibase(), e_owner, e_repo, milestone, norm_date); - gcli_fetch_with_method("PUT", url, "", NULL, NULL); + rc = gcli_fetch_with_method("PUT", url, "", NULL, NULL); free(url); free(e_repo); free(e_owner); - return 0; + return rc; } From c5207719ee29f1e7c67bd06d126faf089ec79a80 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 12:10:32 +0200 Subject: [PATCH 032/236] (#190) Make gitlab pipeline functions return error codes --- include/gcli/gitlab/pipelines.h | 26 +++++----- src/cmd/pipelines.c | 8 +-- src/gitlab/pipelines.c | 88 ++++++++++++++++++++------------- 3 files changed, 72 insertions(+), 50 deletions(-) diff --git a/include/gcli/gitlab/pipelines.h b/include/gcli/gitlab/pipelines.h index a5c35cf9..680f2dfb 100644 --- a/include/gcli/gitlab/pipelines.h +++ b/include/gcli/gitlab/pipelines.h @@ -97,29 +97,29 @@ void gitlab_print_jobs(gitlab_job const *jobs, void gitlab_free_jobs(gitlab_job *jobs, int jobs_size); -void gitlab_job_get_log(char const *owner, - char const *repo, - long job_id); - -void gitlab_job_status(char const *owner, +int gitlab_job_get_log(char const *owner, char const *repo, long job_id); -void gitlab_job_cancel(char const *owner, - char const *repo, - long job_id); +int gitlab_job_status(char const *owner, + char const *repo, + long job_id); -void gitlab_job_retry(char const *owner, +int gitlab_job_cancel(char const *owner, char const *repo, long job_id); +int gitlab_job_retry(char const *owner, + char const *repo, + long job_id); + int gitlab_mr_pipelines(char const *owner, char const *repo, int mr_id); -void gitlab_job_download_artifacts(char const *owner, - char const *repo, - long jid, - char const *outfile); +int gitlab_job_download_artifacts(char const *owner, + char const *repo, + long jid, + char const *outfile); #endif /* GITLAB_PIPELINES_H */ diff --git a/src/cmd/pipelines.c b/src/cmd/pipelines.c index 7e84a903..239fe221 100644 --- a/src/cmd/pipelines.c +++ b/src/cmd/pipelines.c @@ -172,7 +172,7 @@ subcommand_pipelines(int argc, char *argv[]) /* Definition of the action list */ struct { char const *name; /* Name on the cli */ - void (*fn)(char const *, char const *, long); /* Function to be invoked for this action */ + int (*fn)(char const *, char const *, long); /* Function to be invoked for this action */ } job_actions[] = { { .name = "log", .fn = gitlab_job_get_log }, { .name = "status", .fn = gitlab_job_status }, @@ -202,14 +202,16 @@ subcommand_pipelines(int argc, char *argv[]) argc -= 2; argv += 2; } - gitlab_job_download_artifacts(owner, repo, jid, outfile); + if (gitlab_job_download_artifacts(owner, repo, jid, outfile) < 0) + errx(1, "error: failed to download file"); goto next_action; } /* Find the action and invoke it */ for (size_t i = 0; i < ARRAY_SIZE(job_actions); ++i) { if (strcmp(action, job_actions[i].name) == 0) { - job_actions[i].fn(owner, repo, jid); + if (job_actions[i].fn(owner, repo, jid) < 0) + errx(1, "error: failed to perform action '%s'", action); goto next_action; } } diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index 6e536db0..ed22faad 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -251,45 +251,54 @@ gitlab_free_jobs(gitlab_job *jobs, int const jobs_size) free(jobs); } -void +int gitlab_job_get_log(char const *owner, char const *repo, long const job_id) { - gcli_fetch_buffer buffer = {0}; - char *url = NULL; + gcli_fetch_buffer buffer = {0}; + char *url = NULL; + int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld/trace", gitlab_get_apibase(), owner, repo, job_id); - gcli_fetch(url, NULL, &buffer); - - fwrite(buffer.data, buffer.length, 1, stdout); + rc = gcli_fetch(url, NULL, &buffer); + if (rc == 0) { + fwrite(buffer.data, buffer.length, 1, stdout); + } free(buffer.data); free(url); + + return rc; } -static void +static int gitlab_get_job(char const *owner, char const *repo, long const jid, gitlab_job *const out) { - gcli_fetch_buffer buffer = {0}; - char *url = NULL; - struct json_stream stream = {0}; + gcli_fetch_buffer buffer = {0}; + char *url = NULL; + int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld", gitlab_get_apibase(), owner, repo, jid); - gcli_fetch(url, NULL, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - json_set_streaming(&stream, 1); + rc = gcli_fetch(url, NULL, &buffer); + if (rc == 0) { + struct json_stream stream = {0}; - parse_gitlab_job(&stream, out); + json_open_buffer(&stream, buffer.data, buffer.length); + json_set_streaming(&stream, 1); + parse_gitlab_job(&stream, out); + json_close(&stream); + } free(buffer.data); free(url); - json_close(&stream); + + return rc; } static void @@ -314,69 +323,78 @@ gitlab_print_job_status(gitlab_job const *const job) gcli_dict_end(printer); } -void +int gitlab_job_status(char const *owner, char const *repo, long const jid) { gitlab_job job = {0}; + int rc = 0; + + rc = gitlab_get_job(owner, repo, jid, &job); + if (rc == 0) + gitlab_print_job_status(&job); - gitlab_get_job(owner, repo, jid, &job); - gitlab_print_job_status(&job); gitlab_free_job_data(&job); + + return rc; } -void +int gitlab_job_cancel(char const *owner, char const *repo, long const jid) { - gcli_fetch_buffer buffer = {0}; - char *url = NULL; + char *url = NULL; + int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld/cancel", gitlab_get_apibase(), owner, repo, jid); - gcli_fetch_with_method("POST", url, NULL, NULL, &buffer); + rc = gcli_fetch_with_method("POST", url, NULL, NULL, NULL); free(url); - free(buffer.data); + + return rc; } -void +int gitlab_job_retry(char const *owner, char const *repo, long const jid) { - gcli_fetch_buffer buffer = {0}; - char *url = NULL; + int rc = 0; + char *url = NULL; url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld/retry", gitlab_get_apibase(), owner, repo, jid); - gcli_fetch_with_method("POST", url, NULL, NULL, &buffer); + rc = gcli_fetch_with_method("POST", url, NULL, NULL, NULL); free(url); - free(buffer.data); + + return rc; } int gitlab_mr_pipelines(char const *owner, char const *repo, int const mr_id) { gitlab_pipeline_list list = {0}; + int rc = 0; - if (gitlab_get_mr_pipelines(owner, repo, mr_id, &list) < 0) - return -1; + rc = gitlab_get_mr_pipelines(owner, repo, mr_id, &list); + if (rc == 0) + gitlab_print_pipelines(&list); - gitlab_print_pipelines(&list); gitlab_free_pipelines(&list); - return 0; + return rc; } -void +int gitlab_job_download_artifacts(char const *owner, char const *repo, long const jid, char const *const outfile) { char *url; char *e_owner, *e_repo; FILE *f; + int rc = 0; f = fopen(outfile, "wb"); if (f == NULL) - err(1, "could not open %s", outfile); + return -1; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -391,4 +409,6 @@ gitlab_job_download_artifacts(char const *owner, char const *repo, free(url); free(e_owner); free(e_repo); + + return rc; } From e3b0878bd9c9ad74548f6a9d4af8f454f471598b Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 12:17:16 +0200 Subject: [PATCH 033/236] (#190) Make submit_comment routines return error codes --- include/gcli/comments.h | 12 ++++++------ include/gcli/forges.h | 2 +- include/gcli/gitea/comments.h | 2 +- include/gcli/github/comments.h | 2 +- include/gcli/gitlab/comments.h | 4 ++-- src/cmd/comment.c | 13 ++++++++----- src/comments.c | 10 +++++----- src/gitea/comments.c | 4 ++-- src/github/comments.c | 13 +++++++++---- src/gitlab/comments.c | 14 +++++++++----- 10 files changed, 44 insertions(+), 32 deletions(-) diff --git a/include/gcli/comments.h b/include/gcli/comments.h index f68d8add..82c6509e 100644 --- a/include/gcli/comments.h +++ b/include/gcli/comments.h @@ -45,16 +45,16 @@ typedef struct gcli_submit_comment_opts gcli_submit_comment_opts; struct gcli_comment { char const *author; /* Login name of the comment author */ char const *date; /* Creation date of the comment */ - int id; /* id of the comment */ + int id; /* id of the comment */ char const *body; /* Raw text of the comment */ }; struct gcli_submit_comment_opts { enum comment_target_type { ISSUE_COMMENT, PR_COMMENT } target_type; - char const *owner, *repo; - int target_id; - sn_sv message; - bool always_yes; + char const *owner, *repo; + int target_id; + sn_sv message; + bool always_yes; }; void gcli_print_comment_list(gcli_comment const *comments, @@ -62,6 +62,6 @@ void gcli_print_comment_list(gcli_comment const *comments, void gcli_issue_comments(char const *owner, char const *repo, int issue); void gcli_pull_comments(char const *owner, char const *repo, int issue); -void gcli_comment_submit(gcli_submit_comment_opts opts); +int gcli_comment_submit(gcli_submit_comment_opts opts); #endif /* COMMENTS_H */ diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 3001ce34..70b67b0e 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -55,7 +55,7 @@ typedef struct gcli_forge_descriptor gcli_forge_descriptor; struct gcli_forge_descriptor { /** * Submit a comment to a pull/mr or issue */ - void (*perform_submit_comment)( + int (*perform_submit_comment)( gcli_submit_comment_opts opts, gcli_fetch_buffer *out); diff --git a/include/gcli/gitea/comments.h b/include/gcli/gitea/comments.h index eaeaf847..868a0880 100644 --- a/include/gcli/gitea/comments.h +++ b/include/gcli/gitea/comments.h @@ -43,7 +43,7 @@ int gitea_get_comments( int issue, gcli_comment **out); -void gitea_perform_submit_comment( +int gitea_perform_submit_comment( gcli_submit_comment_opts opts, gcli_fetch_buffer *out); diff --git a/include/gcli/github/comments.h b/include/gcli/github/comments.h index 9f383a68..5b450b14 100644 --- a/include/gcli/github/comments.h +++ b/include/gcli/github/comments.h @@ -37,7 +37,7 @@ #include #include -void github_perform_submit_comment( +int github_perform_submit_comment( gcli_submit_comment_opts opts, gcli_fetch_buffer *out); diff --git a/include/gcli/gitlab/comments.h b/include/gcli/gitlab/comments.h index 617a2f67..c9ff9a30 100644 --- a/include/gcli/gitlab/comments.h +++ b/include/gcli/gitlab/comments.h @@ -37,8 +37,8 @@ #include #include -void gitlab_perform_submit_comment(gcli_submit_comment_opts opts, - gcli_fetch_buffer *out); +int gitlab_perform_submit_comment(gcli_submit_comment_opts opts, + gcli_fetch_buffer *out); int gitlab_get_issue_comments(char const *owner, char const *repo, diff --git a/src/cmd/comment.c b/src/cmd/comment.c index 0f3e195d..7f6d1a47 100644 --- a/src/cmd/comment.c +++ b/src/cmd/comment.c @@ -53,10 +53,10 @@ usage(void) int subcommand_comment(int argc, char *argv[]) { - int ch, target_id = -1; - char const *repo = NULL, *owner = NULL; - bool always_yes = false; - enum comment_target_type target_type; + int ch, target_id = -1, rc = 0; + char const *repo = NULL, *owner = NULL; + bool always_yes = false; + enum comment_target_type target_type; struct option const options[] = { { .name = "yes", @@ -121,12 +121,15 @@ subcommand_comment(int argc, char *argv[]) return EXIT_FAILURE; } - gcli_comment_submit((gcli_submit_comment_opts) { + rc = gcli_comment_submit((gcli_submit_comment_opts) { .owner = owner, .repo = repo, .target_type = target_type, .target_id = target_id, .always_yes = always_yes }); + if (rc < 0) + errx(1, "error: failed to submit comment"); + return EXIT_SUCCESS; } diff --git a/src/comments.c b/src/comments.c index b1a3ab89..2b500ea8 100644 --- a/src/comments.c +++ b/src/comments.c @@ -126,12 +126,12 @@ gcli_comment_get_message(gcli_submit_comment_opts *info) return gcli_editor_get_user_message(comment_init, info); } -void +int gcli_comment_submit(gcli_submit_comment_opts opts) { - gcli_fetch_buffer buffer = {0}; sn_sv const message = gcli_comment_get_message(&opts); opts.message = gcli_json_escape(message); + int rc = 0; fprintf( stdout, @@ -143,10 +143,10 @@ gcli_comment_submit(gcli_submit_comment_opts opts) errx(1, "Aborted by user"); } - gcli_forge()->perform_submit_comment(opts, &buffer); - gcli_print_html_url(buffer); + rc = gcli_forge()->perform_submit_comment(opts, NULL); - free(buffer.data); free(message.data); free(opts.message.data); + + return rc; } diff --git a/src/gitea/comments.c b/src/gitea/comments.c index cada0b2c..496d4c77 100644 --- a/src/gitea/comments.c +++ b/src/gitea/comments.c @@ -39,9 +39,9 @@ gitea_get_comments(char const *owner, return github_get_comments(owner, repo, issue, out); } -void +int gitea_perform_submit_comment(gcli_submit_comment_opts opts, gcli_fetch_buffer *const out) { - github_perform_submit_comment(opts, out); + return github_perform_submit_comment(opts, out); } diff --git a/src/github/comments.c b/src/github/comments.c index eca8b883..4f6f0487 100644 --- a/src/github/comments.c +++ b/src/github/comments.c @@ -36,12 +36,14 @@ #include -void +int github_perform_submit_comment(gcli_submit_comment_opts opts, gcli_fetch_buffer *out) { - char *e_owner = gcli_urlencode(opts.owner); - char *e_repo = gcli_urlencode(opts.repo); + int rc = 0; + char *e_owner = gcli_urlencode(opts.owner); + char *e_repo = gcli_urlencode(opts.repo); + char *post_fields = sn_asprintf( "{ \"body\": \""SV_FMT"\" }", SV_ARGS(opts.message)); @@ -50,11 +52,14 @@ github_perform_submit_comment(gcli_submit_comment_opts opts, gcli_get_apibase(), e_owner, e_repo, opts.target_id); - gcli_fetch_with_method("POST", url, post_fields, NULL, out); + rc = gcli_fetch_with_method("POST", url, post_fields, NULL, out); + free(post_fields); free(e_owner); free(e_repo); free(url); + + return rc; } static int diff --git a/src/gitlab/comments.c b/src/gitlab/comments.c index e4628c9e..90c19c2d 100644 --- a/src/gitlab/comments.c +++ b/src/gitlab/comments.c @@ -33,13 +33,14 @@ #include -void +int gitlab_perform_submit_comment(gcli_submit_comment_opts opts, gcli_fetch_buffer *const out) { - char const *type = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + char const *type = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(opts.owner); e_repo = gcli_urlencode(opts.repo); @@ -61,11 +62,14 @@ gitlab_perform_submit_comment(gcli_submit_comment_opts opts, gitlab_get_apibase(), e_owner, e_repo, type, opts.target_id); - gcli_fetch_with_method("POST", url, post_fields, NULL, out); + rc = gcli_fetch_with_method("POST", url, post_fields, NULL, out); + free(post_fields); free(e_owner); free(e_repo); free(url); + + return rc; } static int From 93e2dca58ce9223b39ec3009ac136d00d25ee094 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 12:24:58 +0200 Subject: [PATCH 034/236] (#190) Make add_ssh_key routines return error codes --- src/gitlab/sshkeys.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/gitlab/sshkeys.c b/src/gitlab/sshkeys.c index fdd966fa..1be8f136 100644 --- a/src/gitlab/sshkeys.c +++ b/src/gitlab/sshkeys.c @@ -73,6 +73,7 @@ gitlab_add_sshkey(char const *const title, char *url, *payload; char *e_title, *e_key; gcli_fetch_buffer buf = {0}; + int rc = 0; url = sn_asprintf("%s/user/keys", gcli_get_apibase()); @@ -85,8 +86,8 @@ gitlab_add_sshkey(char const *const title, free(e_title); free(e_key); - gcli_fetch_with_method("POST", url, payload, NULL, &buf); - if (out) { + rc = gcli_fetch_with_method("POST", url, payload, NULL, &buf); + if (rc == 0 && out) { json_stream str; json_open_buffer(&str, buf.data, buf.length); @@ -96,7 +97,7 @@ gitlab_add_sshkey(char const *const title, free(buf.data); - return 0; + return rc; } int From c15212b4a61d541694be55c42aefa829a2f1d83b Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 12:28:33 +0200 Subject: [PATCH 035/236] (#190) Make delete_sshkey routines return error codes --- src/gitlab/sshkeys.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gitlab/sshkeys.c b/src/gitlab/sshkeys.c index 1be8f136..6ebb1c17 100644 --- a/src/gitlab/sshkeys.c +++ b/src/gitlab/sshkeys.c @@ -104,11 +104,12 @@ int gitlab_delete_sshkey(int id) { char *url; + int rc = 0; url = sn_asprintf("%s/user/keys/%d", gcli_get_apibase(), id); - gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); free(url); - return 0; + return rc; } From bfb7d7a0201797a2bb164fb8eeb15d9db5b3b726 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 12:36:49 +0200 Subject: [PATCH 036/236] (#190) Make merge_pull routines return error codes --- include/gcli/forges.h | 2 +- include/gcli/gitea/pulls.h | 8 ++++---- include/gcli/github/pulls.h | 8 ++++---- include/gcli/gitlab/merge_requests.h | 8 ++++---- include/gcli/pulls.h | 8 ++++---- src/cmd/pulls.c | 3 ++- src/gitea/pulls.c | 9 +++++---- src/github/pulls.c | 18 ++++++++++++------ src/gitlab/merge_requests.c | 9 ++++++--- src/pulls.c | 4 ++-- 10 files changed, 44 insertions(+), 33 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 70b67b0e..1f59af71 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -251,7 +251,7 @@ struct gcli_forge_descriptor { /** * Merge the given PR/MR */ - void (*pr_merge)( + int (*pr_merge)( char const *owner, char const *reponame, int pr_number, diff --git a/include/gcli/gitea/pulls.h b/include/gcli/gitea/pulls.h index 05d2e839..44dd501d 100644 --- a/include/gcli/gitea/pulls.h +++ b/include/gcli/gitea/pulls.h @@ -55,10 +55,10 @@ int gitea_get_pull_commits(char const *owner, void gitea_pull_submit(gcli_submit_pull_options opts); -void gitea_pull_merge(char const *owner, - char const *reponame, - int pr_number, - enum gcli_merge_flags flags); +int gitea_pull_merge(char const *owner, + char const *reponame, + int pr_number, + enum gcli_merge_flags flags); void gitea_pull_close(char const *owner, char const *repo, diff --git a/include/gcli/github/pulls.h b/include/gcli/github/pulls.h index 006cde49..f809546f 100644 --- a/include/gcli/github/pulls.h +++ b/include/gcli/github/pulls.h @@ -57,10 +57,10 @@ int github_pull_checks(char const *owner, char const *repo, int pr_number); -void github_pull_merge(char const *owner, - char const *reponame, - int pr_number, - enum gcli_merge_flags flags); +int github_pull_merge(char const *owner, + char const *reponame, + int pr_number, + enum gcli_merge_flags flags); void github_pull_reopen(char const *owner, char const *reponame, diff --git a/include/gcli/gitlab/merge_requests.h b/include/gcli/gitlab/merge_requests.h index 4a4bc31f..c781f1db 100644 --- a/include/gcli/gitlab/merge_requests.h +++ b/include/gcli/gitlab/merge_requests.h @@ -51,10 +51,10 @@ void gitlab_print_pr_diff(FILE *stream, char const *reponame, int pr_number); -void gitlab_mr_merge(char const *owner, - char const *reponame, - int mr_number, - enum gcli_merge_flags flags); +int gitlab_mr_merge(char const *owner, + char const *reponame, + int mr_number, + enum gcli_merge_flags flags); void gitlab_mr_close(char const *owner, char const *reponame, diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index 1188e1ac..5b6467d5 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -143,10 +143,10 @@ enum gcli_merge_flags { GCLI_PULL_MERGE_DELETEHEAD = 0x2, /* delete the source branch after merging */ }; -void gcli_pull_merge(char const *owner, - char const *reponame, - int pr_number, - enum gcli_merge_flags flags); +int gcli_pull_merge(char const *owner, + char const *reponame, + int pr_number, + enum gcli_merge_flags flags); void gcli_pull_close(char const *owner, char const *reponame, diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index b8ed7e28..2b33e6d0 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -447,7 +447,8 @@ handle_pull_actions(int argc, char *argv[], } } - gcli_pull_merge(owner, repo, pr, flags); + if (gcli_pull_merge(owner, repo, pr, flags) < 0) + errx(1, "error: failed to merge pull request"); } else if (strcmp(action, "close") == 0) { gcli_pull_close(owner, repo, pr); diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index 064a83db..bfca6f0f 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -68,17 +68,17 @@ gitea_pull_submit(gcli_submit_pull_options opts) github_perform_submit_pull(opts); } -void +int gitea_pull_merge(char const *owner, char const *repo, int const pr_number, enum gcli_merge_flags const flags) { + int rc = 0; char *url = NULL; char *e_owner = NULL; char *e_repo = NULL; char *data = NULL; - gcli_fetch_buffer buffer = {0}; bool const squash = flags & GCLI_PULL_MERGE_SQUASH; bool const delete_branch = flags & GCLI_PULL_MERGE_DELETEHEAD; @@ -90,13 +90,14 @@ gitea_pull_merge(char const *owner, squash ? "squash" : "merge", delete_branch ? "true" : "false"); - gcli_fetch_with_method("POST", url, data, NULL, &buffer); + rc = gcli_fetch_with_method("POST", url, data, NULL, NULL); free(url); free(e_owner); free(e_repo); free(data); - free(buffer.data); + + return rc; } static void diff --git a/src/github/pulls.c b/src/github/pulls.c index f4742d4b..40327816 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -152,7 +152,7 @@ github_print_pull_diff(FILE *stream, /* TODO: figure out a way to get rid of the 3 consecutive urlencode * calls */ -static void +static int github_pull_delete_head_branch(char const *owner, char const *repo, int const pr_number) @@ -160,6 +160,7 @@ github_pull_delete_head_branch(char const *owner, gcli_pull pull = {0}; char *url, *e_owner, *e_repo; char const *head_branch; + int rc = 0; github_get_pull(owner, repo, pr_number, &pull); @@ -173,15 +174,17 @@ github_pull_delete_head_branch(char const *owner, github_get_apibase(), e_owner, e_repo, head_branch); - gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); free(url); free(e_owner); free(e_repo); gcli_pull_free(&pull); + + return rc; } -void +int github_pull_merge(char const *owner, char const *repo, int const pr_number, @@ -193,6 +196,7 @@ github_pull_merge(char const *owner, char const *data = "{}"; bool const squash = flags & GCLI_PULL_MERGE_SQUASH; bool const delete_source = flags & GCLI_PULL_MERGE_DELETEHEAD; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -203,14 +207,16 @@ github_pull_merge(char const *owner, e_owner, e_repo, pr_number, squash ? "squash" : "merge"); - gcli_fetch_with_method("PUT", url, data, NULL, NULL); + rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); - if (delete_source) - github_pull_delete_head_branch(owner, repo, pr_number); + if (rc == 0 && delete_source) + rc = github_pull_delete_head_branch(owner, repo, pr_number); free(url); free(e_owner); free(e_repo); + + return rc; } void diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index 343adca9..4db6cbe7 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -131,7 +131,7 @@ gitlab_print_pr_diff(FILE *stream, "supported on GitLab. Blame the Gitlab people.\n"); } -void +int gitlab_mr_merge(char const *owner, char const *repo, int const mr_number, @@ -144,6 +144,7 @@ gitlab_mr_merge(char const *owner, char const *data = "{}"; bool const squash = flags & GCLI_PULL_MERGE_SQUASH; bool const delete_source = flags & GCLI_PULL_MERGE_DELETEHEAD; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -158,16 +159,18 @@ gitlab_mr_merge(char const *owner, squash ? "true" : "false", delete_source ? "true" : "false"); - gcli_fetch_with_method("PUT", url, data, NULL, &buffer); + rc = gcli_fetch_with_method("PUT", url, data, NULL, &buffer); /* if verbose or normal noise level, print the url */ - if (!sn_quiet()) + if (rc == 0 && !sn_quiet()) gcli_print_html_url(buffer); free(buffer.data); free(url); free(e_owner); free(e_repo); + + return rc; } void diff --git a/src/pulls.c b/src/pulls.c index 6c381d72..b132431e 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -352,13 +352,13 @@ gcli_pull_submit(gcli_submit_pull_options opts) gcli_forge()->perform_submit_pr(opts); } -void +int gcli_pull_merge(char const *owner, char const *reponame, int const pr_number, enum gcli_merge_flags flags) { - gcli_forge()->pr_merge(owner, reponame, pr_number, flags); + return gcli_forge()->pr_merge(owner, reponame, pr_number, flags); } void From 1b31dcb85c8546937fef531d4ed4505c1c33f380 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 12:41:08 +0200 Subject: [PATCH 037/236] (#190) Clean up names of pull request dispatch functions This makes it more consistent and cleaner --- include/gcli/forges.h | 28 +++++++++--------- src/forges.c | 66 +++++++++++++++++++++---------------------- src/pulls.c | 22 +++++++-------- 3 files changed, 58 insertions(+), 58 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 1f59af71..e23ba909 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -222,7 +222,7 @@ struct gcli_forge_descriptor { /** * Get a list of PRs/MRs on the given repo */ - int (*get_prs)( + int (*get_pulls)( char const *owner, char const *reponame, gcli_pull_fetch_details const *details, @@ -231,7 +231,7 @@ struct gcli_forge_descriptor { /** * Print a diff of the changes of a PR/MR to the stream */ - void (*print_pr_diff)( + void (*print_pull_diff)( FILE *stream, char const *owner, char const *reponame, @@ -244,14 +244,14 @@ struct gcli_forge_descriptor { * underlying the forge are so different that we cannot properly * unify them. For Gitlab this will call into the pipelines code, * for Github into the actions code. */ - int (*print_pr_checks)( + int (*print_pull_checks)( char const *owner, char const *reponame, int pr_number); /** * Merge the given PR/MR */ - int (*pr_merge)( + int (*pull_merge)( char const *owner, char const *reponame, int pr_number, @@ -259,21 +259,21 @@ struct gcli_forge_descriptor { /** * Reopen the given PR/MR */ - void (*pr_reopen)( + void (*pull_reopen)( char const *owner, char const *reponame, int pr_number); /** * Close the given PR/MR */ - void (*pr_close)( + void (*pull_close)( char const *owner, char const *reponame, int pr_number); /** * Submit PR/MR */ - void (*perform_submit_pr)( + void (*perform_submit_pull)( gcli_submit_pull_options opts); /** @@ -286,7 +286,7 @@ struct gcli_forge_descriptor { /** Bitmask of unsupported fields in the pull summary for this * forge */ - enum gcli_pr_summary_quirks { + enum gcli_pull_summary_quirks { GCLI_PRS_QUIRK_ADDDEL = 0x01, GCLI_PRS_QUIRK_COMMITS = 0x02, GCLI_PRS_QUIRK_CHANGES = 0x04, @@ -304,7 +304,7 @@ struct gcli_forge_descriptor { /** * Add labels to Pull Requests */ - int (*pr_add_labels)( + int (*pull_add_labels)( char const *owner, char const *repo, int pr, @@ -313,7 +313,7 @@ struct gcli_forge_descriptor { /** * Removes labels from Pull Requests */ - int (*pr_remove_labels)( + int (*pull_remove_labels)( char const *owner, char const *repo, int pr, @@ -322,18 +322,18 @@ struct gcli_forge_descriptor { /** * Assign a PR to a milestone */ - int (*pr_set_milestone)( + int (*pull_set_milestone)( char const *owner, char const *repo, - int pr, + int pull, int milestone_id); /** * Clear a milestone on a PR */ - int (*pr_clear_milestone)( + int (*pull_clear_milestone)( char const *owner, char const *repo, - int pr); + int pull); /** * Get a list of releases in the given repo */ diff --git a/src/forges.c b/src/forges.c index b1d1d767..3c784ef8 100644 --- a/src/forges.c +++ b/src/forges.c @@ -96,27 +96,27 @@ github_forge_descriptor = .delete_milestone = github_delete_milestone, .milestone_set_duedate = github_milestone_set_duedate, .get_milestone_issues = github_milestone_get_issues, - .get_prs = github_get_pulls, - .print_pr_diff = github_print_pull_diff, - .print_pr_checks = github_pull_checks, - .pr_merge = github_pull_merge, - .pr_reopen = github_pull_reopen, - .pr_close = github_pull_close, + .get_pulls = github_get_pulls, + .print_pull_diff = github_print_pull_diff, + .print_pull_checks = github_pull_checks, + .pull_merge = github_pull_merge, + .pull_reopen = github_pull_reopen, + .pull_close = github_pull_close, /* HACK: Here we can use the same functions as with issues because * PRs are the same as issues on Github and the functions have the * same types/arguments */ - .pr_add_labels = github_issue_add_labels, - .pr_remove_labels = github_issue_remove_labels, + .pull_add_labels = github_issue_add_labels, + .pull_remove_labels = github_issue_remove_labels, - .perform_submit_pr = github_perform_submit_pull, + .perform_submit_pull = github_perform_submit_pull, .get_pull_commits = github_get_pull_commits, .get_pull = github_get_pull, /* This works because the function signatures are the same and * GitHub treats pull requests as issues */ - .pr_set_milestone = github_issue_set_milestone, - .pr_clear_milestone = github_issue_clear_milestone, + .pull_set_milestone = github_issue_set_milestone, + .pull_clear_milestone = github_issue_clear_milestone, .get_releases = github_get_releases, .create_release = github_create_release, @@ -171,19 +171,19 @@ gitlab_forge_descriptor = .get_milestone_issues = gitlab_milestone_get_issues, .issue_set_milestone = gitlab_issue_set_milestone, .issue_clear_milestone = gitlab_issue_clear_milestone, - .get_prs = gitlab_get_mrs, - .print_pr_diff = gitlab_print_pr_diff, - .print_pr_checks = gitlab_mr_pipelines, - .pr_merge = gitlab_mr_merge, - .pr_reopen = gitlab_mr_reopen, - .pr_close = gitlab_mr_close, - .perform_submit_pr = gitlab_perform_submit_mr, + .get_pulls = gitlab_get_mrs, + .print_pull_diff = gitlab_print_pr_diff, + .print_pull_checks = gitlab_mr_pipelines, + .pull_merge = gitlab_mr_merge, + .pull_reopen = gitlab_mr_reopen, + .pull_close = gitlab_mr_close, + .perform_submit_pull = gitlab_perform_submit_mr, .get_pull_commits = gitlab_get_pull_commits, .get_pull = gitlab_get_pull, - .pr_add_labels = gitlab_mr_add_labels, - .pr_remove_labels = gitlab_mr_remove_labels, - .pr_set_milestone = gitlab_mr_set_milestone, - .pr_clear_milestone = gitlab_mr_clear_milestone, + .pull_add_labels = gitlab_mr_add_labels, + .pull_remove_labels = gitlab_mr_remove_labels, + .pull_set_milestone = gitlab_mr_set_milestone, + .pull_clear_milestone = gitlab_mr_clear_milestone, .get_releases = gitlab_get_releases, .create_release = gitlab_create_release, .delete_release = gitlab_delete_release, @@ -236,26 +236,26 @@ gitea_forge_descriptor = .get_labels = gitea_get_labels, .create_label = gitea_create_label, .delete_label = gitea_delete_label, - .get_prs = gitea_get_pulls, - .print_pr_checks = gitea_pull_checks, /* stub */ - .pr_merge = gitea_pull_merge, - .pr_reopen = gitea_pull_reopen, - .pr_close = gitea_pull_close, + .get_pulls = gitea_get_pulls, + .print_pull_checks = gitea_pull_checks, /* stub */ + .pull_merge = gitea_pull_merge, + .pull_reopen = gitea_pull_reopen, + .pull_close = gitea_pull_close, .get_pull_comments = gitea_get_comments, .get_pull = gitea_get_pull, .get_pull_commits = gitea_get_pull_commits, - .pr_set_milestone = gitea_pull_set_milestone, - .pr_clear_milestone = gitea_pull_clear_milestone, + .pull_set_milestone = gitea_pull_set_milestone, + .pull_clear_milestone = gitea_pull_clear_milestone, .get_releases = gitea_get_releases, .create_release = gitea_create_release, .delete_release = gitea_delete_release, - .perform_submit_pr = gitea_pull_submit, - .print_pr_diff = gitea_print_pr_diff, + .perform_submit_pull = gitea_pull_submit, + .print_pull_diff = gitea_print_pr_diff, .get_forks = gitea_get_forks, /* Same procedure as with Github (see comment up there) */ - .pr_add_labels = gitea_issue_add_labels, - .pr_remove_labels = gitea_issue_remove_labels, + .pull_add_labels = gitea_issue_add_labels, + .pull_remove_labels = gitea_issue_remove_labels, .get_repos = gitea_get_repos, .get_own_repos = gitea_get_own_repos, .repo_create = gitea_repo_create, diff --git a/src/pulls.c b/src/pulls.c index b132431e..c338806e 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -58,7 +58,7 @@ gcli_get_pulls(char const *owner, int const max, gcli_pull_list *const out) { - return gcli_forge()->get_prs(owner, repo, details, max, out); + return gcli_forge()->get_pulls(owner, repo, details, max, out); } void @@ -124,7 +124,7 @@ gcli_print_pull_diff(FILE *stream, char const *reponame, int const pr_number) { - gcli_forge()->print_pr_diff(stream, owner, reponame, pr_number); + gcli_forge()->print_pull_diff(stream, owner, reponame, pr_number); } void @@ -304,7 +304,7 @@ gcli_pull_print_op(gcli_pull *const pull) void gcli_pull_checks(char const *owner, char const *repo, int const pr_number) { - gcli_forge()->print_pr_checks(owner, repo, pr_number); + gcli_forge()->print_pull_checks(owner, repo, pr_number); } static void @@ -349,7 +349,7 @@ gcli_pull_submit(gcli_submit_pull_options opts) if (!sn_yesno("Do you want to continue?")) errx(1, "PR aborted."); - gcli_forge()->perform_submit_pr(opts); + gcli_forge()->perform_submit_pull(opts); } int @@ -358,19 +358,19 @@ gcli_pull_merge(char const *owner, int const pr_number, enum gcli_merge_flags flags) { - return gcli_forge()->pr_merge(owner, reponame, pr_number, flags); + return gcli_forge()->pull_merge(owner, reponame, pr_number, flags); } void gcli_pull_close(char const *owner, char const *reponame, int const pr_number) { - gcli_forge()->pr_close(owner, reponame, pr_number); + gcli_forge()->pull_close(owner, reponame, pr_number); } void gcli_pull_reopen(char const *owner, char const *reponame, int const pr_number) { - gcli_forge()->pr_reopen(owner, reponame, pr_number); + gcli_forge()->pull_reopen(owner, reponame, pr_number); } int @@ -380,7 +380,7 @@ gcli_pull_add_labels(char const *owner, char const *const labels[], size_t const labels_size) { - return gcli_forge()->pr_add_labels( + return gcli_forge()->pull_add_labels( owner, repo, pr_number, labels, labels_size); } @@ -391,7 +391,7 @@ gcli_pull_remove_labels(char const *owner, char const *const labels[], size_t const labels_size) { - return gcli_forge()->pr_remove_labels( + return gcli_forge()->pull_remove_labels( owner, repo, pr_number, labels, labels_size); } @@ -401,7 +401,7 @@ gcli_pull_set_milestone(char const *owner, int pr_number, int milestone_id) { - return gcli_forge()->pr_set_milestone(owner, repo, pr_number, milestone_id); + return gcli_forge()->pull_set_milestone(owner, repo, pr_number, milestone_id); } int @@ -409,5 +409,5 @@ gcli_pull_clear_milestone(char const *owner, char const *repo, int pr_number) { - return gcli_forge()->pr_clear_milestone(owner, repo, pr_number); + return gcli_forge()->pull_clear_milestone(owner, repo, pr_number); } From 9809809167dfffed38d0cab2c9018071d8ae615e Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 12:47:01 +0200 Subject: [PATCH 038/236] (#190) Make pull_close routines return error codes --- include/gcli/forges.h | 2 +- include/gcli/gitea/pulls.h | 6 +++--- include/gcli/github/pulls.h | 6 +++--- include/gcli/gitlab/merge_requests.h | 6 +++--- include/gcli/pulls.h | 6 +++--- src/cmd/pulls.c | 3 ++- src/gitea/pulls.c | 23 ++++++++++++----------- src/github/pulls.c | 21 +++++++++++---------- src/gitlab/merge_requests.c | 17 +++++++++-------- src/pulls.c | 4 ++-- 10 files changed, 49 insertions(+), 45 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index e23ba909..1365f651 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -266,7 +266,7 @@ struct gcli_forge_descriptor { /** * Close the given PR/MR */ - void (*pull_close)( + int (*pull_close)( char const *owner, char const *reponame, int pr_number); diff --git a/include/gcli/gitea/pulls.h b/include/gcli/gitea/pulls.h index 44dd501d..73b975c8 100644 --- a/include/gcli/gitea/pulls.h +++ b/include/gcli/gitea/pulls.h @@ -60,9 +60,9 @@ int gitea_pull_merge(char const *owner, int pr_number, enum gcli_merge_flags flags); -void gitea_pull_close(char const *owner, - char const *repo, - int pr_number); +int gitea_pull_close(char const *owner, + char const *repo, + int pr_number); void gitea_pull_reopen(char const *owner, char const *repo, diff --git a/include/gcli/github/pulls.h b/include/gcli/github/pulls.h index f809546f..28377e6a 100644 --- a/include/gcli/github/pulls.h +++ b/include/gcli/github/pulls.h @@ -66,9 +66,9 @@ void github_pull_reopen(char const *owner, char const *reponame, int pr_number); -void github_pull_close(char const *owner, - char const *reponame, - int pr_number); +int github_pull_close(char const *owner, + char const *reponame, + int pr_number); void github_perform_submit_pull(gcli_submit_pull_options opts); diff --git a/include/gcli/gitlab/merge_requests.h b/include/gcli/gitlab/merge_requests.h index c781f1db..f33396fd 100644 --- a/include/gcli/gitlab/merge_requests.h +++ b/include/gcli/gitlab/merge_requests.h @@ -56,9 +56,9 @@ int gitlab_mr_merge(char const *owner, int mr_number, enum gcli_merge_flags flags); -void gitlab_mr_close(char const *owner, - char const *reponame, - int pr_number); +int gitlab_mr_close(char const *owner, + char const *reponame, + int pr_number); void gitlab_mr_reopen(char const *owner, char const *reponame, diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index 5b6467d5..65913b15 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -148,9 +148,9 @@ int gcli_pull_merge(char const *owner, int pr_number, enum gcli_merge_flags flags); -void gcli_pull_close(char const *owner, - char const *reponame, - int pr_number); +int gcli_pull_close(char const *owner, + char const *reponame, + int pr_number); void gcli_pull_reopen(char const *owner, char const *reponame, diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 2b33e6d0..5b84a851 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -451,7 +451,8 @@ handle_pull_actions(int argc, char *argv[], errx(1, "error: failed to merge pull request"); } else if (strcmp(action, "close") == 0) { - gcli_pull_close(owner, repo, pr); + if (gcli_pull_close(owner, repo, pr) < 0) + errx(1, "error: failed to close pull request"); } else if (strcmp(action, "reopen") == 0) { gcli_pull_reopen(owner, repo, pr); diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index bfca6f0f..06f724a8 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -100,20 +100,20 @@ gitea_pull_merge(char const *owner, return rc; } -static void +static int gitea_pulls_patch_state(char const *owner, char const *repo, int const pr_number, char const *state) { - gcli_fetch_buffer json_buffer = {0}; - char *url = NULL; - char *data = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + char *url = NULL; + char *data = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); url = sn_asprintf( "%s/repos/%s/%s/pulls/%d", @@ -122,21 +122,22 @@ gitea_pulls_patch_state(char const *owner, pr_number); data = sn_asprintf("{ \"state\": \"%s\"}", state); - gcli_fetch_with_method("PATCH", url, data, NULL, &json_buffer); + rc = gcli_fetch_with_method("PATCH", url, data, NULL, NULL); free(data); free(url); free(e_owner); free(e_repo); - free(json_buffer.data); + + return rc; } -void +int gitea_pull_close(char const *owner, char const *repo, int const pr_number) { - gitea_pulls_patch_state(owner, repo, pr_number, "closed"); + return gitea_pulls_patch_state(owner, repo, pr_number, "closed"); } void diff --git a/src/github/pulls.c b/src/github/pulls.c index 40327816..0048256c 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -219,31 +219,32 @@ github_pull_merge(char const *owner, return rc; } -void +int github_pull_close(char const *owner, char const *repo, int const pr_number) { - gcli_fetch_buffer json_buffer = {0}; - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - char *data = NULL; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + char *data = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); - url = sn_asprintf( + url = sn_asprintf( "%s/repos/%s/%s/pulls/%d", gcli_get_apibase(), e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state\": \"closed\"}"); - gcli_fetch_with_method("PATCH", url, data, NULL, &json_buffer); + rc = gcli_fetch_with_method("PATCH", url, data, NULL, NULL); - free(json_buffer.data); free(url); free(e_repo); free(e_owner); free(data); + + return rc; } void diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index 4db6cbe7..e60c1240 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -246,14 +246,14 @@ gitlab_get_pull_commits(char const *owner, return (int)(count); } -void +int gitlab_mr_close(char const *owner, char const *repo, int const pr_number) { - gcli_fetch_buffer json_buffer = {0}; - char *url = NULL; - char *data = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + char *url = NULL; + char *data = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -264,13 +264,14 @@ gitlab_mr_close(char const *owner, char const *repo, int const pr_number) e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state_event\": \"close\"}"); - gcli_fetch_with_method("PUT", url, data, NULL, &json_buffer); + rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); - free(json_buffer.data); free(url); free(e_owner); free(e_repo); free(data); + + return rc; } void diff --git a/src/pulls.c b/src/pulls.c index c338806e..554094e5 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -361,10 +361,10 @@ gcli_pull_merge(char const *owner, return gcli_forge()->pull_merge(owner, reponame, pr_number, flags); } -void +int gcli_pull_close(char const *owner, char const *reponame, int const pr_number) { - gcli_forge()->pull_close(owner, reponame, pr_number); + return gcli_forge()->pull_close(owner, reponame, pr_number); } void From c67219a78b8af5487e462a1630a6d59e8da66fed Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 13:04:07 +0200 Subject: [PATCH 039/236] (#190) Make pull_reopen routines return error codes --- include/gcli/forges.h | 2 +- include/gcli/gitea/pulls.h | 6 +++--- include/gcli/github/pulls.h | 6 +++--- include/gcli/gitlab/merge_requests.h | 6 +++--- include/gcli/pulls.h | 6 +++--- src/cmd/pulls.c | 3 ++- src/gitea/pulls.c | 4 ++-- src/github/pulls.c | 19 ++++++++++--------- src/gitlab/merge_requests.c | 17 +++++++++-------- src/pulls.c | 4 ++-- 10 files changed, 38 insertions(+), 35 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 1365f651..75e384f5 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -259,7 +259,7 @@ struct gcli_forge_descriptor { /** * Reopen the given PR/MR */ - void (*pull_reopen)( + int (*pull_reopen)( char const *owner, char const *reponame, int pr_number); diff --git a/include/gcli/gitea/pulls.h b/include/gcli/gitea/pulls.h index 73b975c8..228c5f0b 100644 --- a/include/gcli/gitea/pulls.h +++ b/include/gcli/gitea/pulls.h @@ -64,9 +64,9 @@ int gitea_pull_close(char const *owner, char const *repo, int pr_number); -void gitea_pull_reopen(char const *owner, - char const *repo, - int pr_number); +int gitea_pull_reopen(char const *owner, + char const *repo, + int pr_number); void gitea_print_pr_diff(FILE *stream, char const *owner, diff --git a/include/gcli/github/pulls.h b/include/gcli/github/pulls.h index 28377e6a..20e9732d 100644 --- a/include/gcli/github/pulls.h +++ b/include/gcli/github/pulls.h @@ -62,9 +62,9 @@ int github_pull_merge(char const *owner, int pr_number, enum gcli_merge_flags flags); -void github_pull_reopen(char const *owner, - char const *reponame, - int pr_number); +int github_pull_reopen(char const *owner, + char const *reponame, + int pr_number); int github_pull_close(char const *owner, char const *reponame, diff --git a/include/gcli/gitlab/merge_requests.h b/include/gcli/gitlab/merge_requests.h index f33396fd..b924ef8e 100644 --- a/include/gcli/gitlab/merge_requests.h +++ b/include/gcli/gitlab/merge_requests.h @@ -60,9 +60,9 @@ int gitlab_mr_close(char const *owner, char const *reponame, int pr_number); -void gitlab_mr_reopen(char const *owner, - char const *reponame, - int pr_number); +int gitlab_mr_reopen(char const *owner, + char const *reponame, + int pr_number); void gitlab_get_pull(char const *owner, char const *repo, diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index 65913b15..e29e7ea6 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -152,9 +152,9 @@ int gcli_pull_close(char const *owner, char const *reponame, int pr_number); -void gcli_pull_reopen(char const *owner, - char const *reponame, - int pr_number); +int gcli_pull_reopen(char const *owner, + char const *reponame, + int pr_number); int gcli_pull_add_labels(char const *owner, char const *repo, diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 5b84a851..a09efc6d 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -455,7 +455,8 @@ handle_pull_actions(int argc, char *argv[], errx(1, "error: failed to close pull request"); } else if (strcmp(action, "reopen") == 0) { - gcli_pull_reopen(owner, repo, pr); + if (gcli_pull_reopen(owner, repo, pr) < 0) + errx(1, "error: failed to reopen pull request"); } else if (strcmp(action, "reviews") == 0) { /* list reviews */ diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index 06f724a8..d56c4d96 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -140,12 +140,12 @@ gitea_pull_close(char const *owner, return gitea_pulls_patch_state(owner, repo, pr_number, "closed"); } -void +int gitea_pull_reopen(char const *owner, char const *repo, int const pr_number) { - gitea_pulls_patch_state(owner, repo, pr_number, "open"); + return gitea_pulls_patch_state(owner, repo, pr_number, "open"); } void diff --git a/src/github/pulls.c b/src/github/pulls.c index 0048256c..c492aac7 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -247,17 +247,17 @@ github_pull_close(char const *owner, char const *repo, int const pr_number) return rc; } -void +int github_pull_reopen(char const *owner, char const *repo, int const pr_number) { - gcli_fetch_buffer json_buffer = {0}; - char *url = NULL; - char *data = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + char *url = NULL; + char *data = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); url = sn_asprintf( "%s/repos/%s/%s/pulls/%d", @@ -265,13 +265,14 @@ github_pull_reopen(char const *owner, char const *repo, int const pr_number) e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state\": \"open\"}"); - gcli_fetch_with_method("PATCH", url, data, NULL, &json_buffer); + rc = gcli_fetch_with_method("PATCH", url, data, NULL, NULL); - free(json_buffer.data); free(url); free(data); free(e_owner); free(e_repo); + + return rc; } void diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index e60c1240..a5d5f2d8 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -274,14 +274,14 @@ gitlab_mr_close(char const *owner, char const *repo, int const pr_number) return rc; } -void +int gitlab_mr_reopen(char const *owner, char const *repo, int const pr_number) { - gcli_fetch_buffer json_buffer = {0}; - char *url = NULL; - char *data = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + char *url = NULL; + char *data = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -292,13 +292,14 @@ gitlab_mr_reopen(char const *owner, char const *repo, int const pr_number) e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state_event\": \"reopen\"}"); - gcli_fetch_with_method("PUT", url, data, NULL, &json_buffer); + rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); - free(json_buffer.data); free(e_owner); free(e_repo); free(url); free(data); + + return rc; } void diff --git a/src/pulls.c b/src/pulls.c index 554094e5..dc13ba5f 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -367,10 +367,10 @@ gcli_pull_close(char const *owner, char const *reponame, int const pr_number) return gcli_forge()->pull_close(owner, reponame, pr_number); } -void +int gcli_pull_reopen(char const *owner, char const *reponame, int const pr_number) { - gcli_forge()->pull_reopen(owner, reponame, pr_number); + return gcli_forge()->pull_reopen(owner, reponame, pr_number); } int From f8d1ace0e41cc0b4b1ceec57bf1d716d71bc9d5b Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 13:48:06 +0200 Subject: [PATCH 040/236] (#190) Make pull_submit return error codes --- include/gcli/forges.h | 2 +- include/gcli/gitea/pulls.h | 2 +- include/gcli/github/pulls.h | 2 +- include/gcli/gitlab/merge_requests.h | 2 +- include/gcli/gitlab/repos.h | 6 +++--- include/gcli/pulls.h | 2 +- src/cmd/pulls.c | 3 ++- src/gitea/pulls.c | 4 ++-- src/github/pulls.c | 19 +++++++++++-------- src/gitlab/merge_requests.c | 23 +++++++++++++---------- src/gitlab/repos.c | 25 +++++++++++++++---------- src/pulls.c | 4 ++-- 12 files changed, 53 insertions(+), 41 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 75e384f5..989a2d80 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -273,7 +273,7 @@ struct gcli_forge_descriptor { /** * Submit PR/MR */ - void (*perform_submit_pull)( + int (*perform_submit_pull)( gcli_submit_pull_options opts); /** diff --git a/include/gcli/gitea/pulls.h b/include/gcli/gitea/pulls.h index 228c5f0b..49d2caad 100644 --- a/include/gcli/gitea/pulls.h +++ b/include/gcli/gitea/pulls.h @@ -53,7 +53,7 @@ int gitea_get_pull_commits(char const *owner, int pr_number, gcli_commit **out); -void gitea_pull_submit(gcli_submit_pull_options opts); +int gitea_pull_submit(gcli_submit_pull_options opts); int gitea_pull_merge(char const *owner, char const *reponame, diff --git a/include/gcli/github/pulls.h b/include/gcli/github/pulls.h index 20e9732d..b2ddaee6 100644 --- a/include/gcli/github/pulls.h +++ b/include/gcli/github/pulls.h @@ -70,7 +70,7 @@ int github_pull_close(char const *owner, char const *reponame, int pr_number); -void github_perform_submit_pull(gcli_submit_pull_options opts); +int github_perform_submit_pull(gcli_submit_pull_options opts); int github_get_pull_commits(char const *owner, char const *repo, diff --git a/include/gcli/gitlab/merge_requests.h b/include/gcli/gitlab/merge_requests.h index b924ef8e..7c2adef5 100644 --- a/include/gcli/gitlab/merge_requests.h +++ b/include/gcli/gitlab/merge_requests.h @@ -74,7 +74,7 @@ int gitlab_get_pull_commits(char const *owner, int pr_number, gcli_commit **out); -void gitlab_perform_submit_mr(gcli_submit_pull_options opts); +int gitlab_perform_submit_mr(gcli_submit_pull_options opts); int gitlab_mr_add_labels(char const *owner, char const *repo, diff --git a/include/gcli/gitlab/repos.h b/include/gcli/gitlab/repos.h index 8a17c535..3d1771e3 100644 --- a/include/gcli/gitlab/repos.h +++ b/include/gcli/gitlab/repos.h @@ -36,9 +36,9 @@ #include -void gitlab_get_repo(char const *owner, - char const *repo, - gcli_repo *out); +int gitlab_get_repo(char const *owner, + char const *repo, + gcli_repo *out); int gitlab_get_repos(char const *owner, int max, diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index e29e7ea6..e430346b 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -132,7 +132,7 @@ void gcli_get_pull(char const *owner, int pr_number, gcli_pull *out); -void gcli_pull_submit(gcli_submit_pull_options); +int gcli_pull_submit(gcli_submit_pull_options); void gcli_pull_print_status(gcli_pull const *it); diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index a09efc6d..a8dbb15c 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -194,7 +194,8 @@ subcommand_pull_create(int argc, char *argv[]) opts.title = SV(argv[0]); - gcli_pull_submit(opts); + if (gcli_pull_submit(opts) < 0) + errx(1, "error: failed to submit pull request"); free(opts.labels); diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index d56c4d96..90dbb88e 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -60,12 +60,12 @@ gitea_get_pull_commits(char const *owner, return github_get_pull_commits(owner, repo, pr_number, out); } -void +int gitea_pull_submit(gcli_submit_pull_options opts) { warnx("In case the following process errors out, see: " "https://github.com/go-gitea/gitea/issues/20175"); - github_perform_submit_pull(opts); + return github_perform_submit_pull(opts); } int diff --git a/src/github/pulls.c b/src/github/pulls.c index c492aac7..5e8c3691 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -275,13 +275,14 @@ github_pull_reopen(char const *owner, char const *repo, int const pr_number) return rc; } -void +int github_perform_submit_pull(gcli_submit_pull_options opts) { - sn_sv e_head, e_base, e_title, e_body; - gcli_fetch_buffer fetch_buffer = {0}; - struct json_stream json = {0}; - gcli_pull pull = {0}; + sn_sv e_head, e_base, e_title, e_body; + gcli_fetch_buffer fetch_buffer = {0}; + struct json_stream json = {0}; + gcli_pull pull = {0}; + int rc = 0; e_head = gcli_json_escape(opts.from); e_base = gcli_json_escape(opts.to); @@ -295,16 +296,16 @@ github_perform_submit_pull(gcli_submit_pull_options opts) SV_ARGS(e_base), SV_ARGS(e_title), SV_ARGS(e_body)); - char *url = sn_asprintf( + char *url = sn_asprintf( "%s/repos/%s/%s/pulls", gcli_get_apibase(), opts.owner, opts.repo); - gcli_fetch_with_method("POST", url, post_fields, NULL, &fetch_buffer); + rc = gcli_fetch_with_method("POST", url, post_fields, NULL, &fetch_buffer); /* Add labels if requested. GitHub doesn't allow us to do this all * with one request. */ - if (opts.labels_size) { + if (rc == 0 && opts.labels_size) { json_open_buffer(&json, fetch_buffer.data, fetch_buffer.length); parse_github_pull(&json, &pull); @@ -322,6 +323,8 @@ github_perform_submit_pull(gcli_submit_pull_options opts) free(e_body.data); free(post_fields); free(url); + + return rc; } int diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index a5d5f2d8..944ccb33 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -302,18 +302,18 @@ gitlab_mr_reopen(char const *owner, char const *repo, int const pr_number) return rc; } -void +int gitlab_perform_submit_mr(gcli_submit_pull_options opts) { /* Note: this doesn't really allow merging into repos with * different names. We need to figure out a way to make this * better for both github and gitlab. */ - gcli_repo target = {0}; - sn_sv target_branch = {0}; - sn_sv source_owner = {0}; - sn_sv source_branch = {0}; - char *labels = NULL; - gcli_fetch_buffer buffer = {0}; + gcli_repo target = {0}; + sn_sv target_branch = {0}; + sn_sv source_owner = {0}; + sn_sv source_branch = {0}; + char *labels = NULL; + int rc = 0; /* json escaped variants */ sn_sv e_source_branch, e_target_branch, e_title, e_body; @@ -325,7 +325,9 @@ gitlab_perform_submit_mr(gcli_submit_pull_options opts) source_branch.data += 1; /* Figure out the project id */ - gitlab_get_repo(opts.owner, opts.repo, &target); + rc = gitlab_get_repo(opts.owner, opts.repo, &target); + if (rc < 0) + return rc; /* escape things in the post payload */ e_source_branch = gcli_json_escape(source_branch); @@ -369,10 +371,9 @@ gitlab_perform_submit_mr(gcli_submit_pull_options opts) e_owner, e_repo); /* perform request */ - gcli_fetch_with_method("POST", url, post_fields, NULL, &buffer); + rc = gcli_fetch_with_method("POST", url, post_fields, NULL, NULL); /* cleanup */ - free(buffer.data); free(e_source_branch.data); free(e_target_branch.data); free(e_title.data); @@ -382,6 +383,8 @@ gitlab_perform_submit_mr(gcli_submit_pull_options opts) free(labels); free(post_fields); free(url); + + return rc; } int diff --git a/src/gitlab/repos.c b/src/gitlab/repos.c index 197322d4..9b157d86 100644 --- a/src/gitlab/repos.c +++ b/src/gitlab/repos.c @@ -36,17 +36,18 @@ #include -void +int gitlab_get_repo(char const *owner, char const *repo, gcli_repo *const out) { /* GET /projects/:id */ - char *url = NULL; - gcli_fetch_buffer buffer = {0}; - json_stream stream = {0}; - char *e_owner = {0}; - char *e_repo = {0}; + char *url = NULL; + gcli_fetch_buffer buffer = {0}; + json_stream stream = {0}; + char *e_owner = {0}; + char *e_repo = {0}; + int rc; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -56,16 +57,20 @@ gitlab_get_repo(char const *owner, gitlab_get_apibase(), e_owner, e_repo); - gcli_fetch(url, NULL, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); + rc = gcli_fetch(url, NULL, &buffer); - parse_gitlab_repo(&stream, out); + if (rc == 0) { + json_open_buffer(&stream, buffer.data, buffer.length); + parse_gitlab_repo(&stream, out); + json_close(&stream); + } - json_close(&stream); free(buffer.data); free(e_owner); free(e_repo); free(url); + + return rc; } static void diff --git a/src/pulls.c b/src/pulls.c index dc13ba5f..c86edf5d 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -325,7 +325,7 @@ gcli_pull_get_user_message(gcli_submit_pull_options *opts) return gcli_editor_get_user_message(pull_init_user_file, opts); } -void +int gcli_pull_submit(gcli_submit_pull_options opts) { opts.body = gcli_pull_get_user_message(&opts); @@ -349,7 +349,7 @@ gcli_pull_submit(gcli_submit_pull_options opts) if (!sn_yesno("Do you want to continue?")) errx(1, "PR aborted."); - gcli_forge()->perform_submit_pull(opts); + return gcli_forge()->perform_submit_pull(opts); } int From 8d11b81ecf94cef3f3a5337ef968fb06cc9f43b3 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 14:44:50 +0200 Subject: [PATCH 041/236] (#190) Make delet_repo routines return error codes --- include/gcli/forges.h | 2 +- include/gcli/gitea/repos.h | 4 ++-- include/gcli/github/repos.h | 4 ++-- include/gcli/gitlab/repos.h | 4 ++-- include/gcli/repos.h | 2 +- src/cmd.c | 7 ++++--- src/cmd/pulls.c | 3 ++- src/gitea/repos.c | 4 ++-- src/github/repos.c | 15 ++++++++------- src/gitlab/merge_requests.c | 5 +++-- src/gitlab/repos.c | 15 ++++++++------- src/repos.c | 4 ++-- todo.org | 5 ++++- 13 files changed, 41 insertions(+), 33 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 989a2d80..923b1445 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -399,7 +399,7 @@ struct gcli_forge_descriptor { /** * Delete the given repo */ - void (*repo_delete)( + int (*repo_delete)( char const *owner, char const *repo); diff --git a/include/gcli/gitea/repos.h b/include/gcli/gitea/repos.h index bb09784e..aa026523 100644 --- a/include/gcli/gitea/repos.h +++ b/include/gcli/gitea/repos.h @@ -45,7 +45,7 @@ int gitea_get_own_repos(int max, gcli_repo *gitea_repo_create(gcli_repo_create_options const *options); -void gitea_repo_delete(char const *owner, - char const *repo); +int gitea_repo_delete(char const *owner, + char const *repo); #endif /* GITEA_REPOS_H */ diff --git a/include/gcli/github/repos.h b/include/gcli/github/repos.h index 2884a496..b14c00e4 100644 --- a/include/gcli/github/repos.h +++ b/include/gcli/github/repos.h @@ -43,8 +43,8 @@ int github_get_repos(char const *owner, int github_get_own_repos(int max, gcli_repo_list *out); -void github_repo_delete(char const *owner, - char const *repo); +int github_repo_delete(char const *owner, + char const *repo); gcli_repo *github_repo_create(gcli_repo_create_options const *options); diff --git a/include/gcli/gitlab/repos.h b/include/gcli/gitlab/repos.h index 3d1771e3..5bdd8659 100644 --- a/include/gcli/gitlab/repos.h +++ b/include/gcli/gitlab/repos.h @@ -46,8 +46,8 @@ int gitlab_get_repos(char const *owner, int gitlab_get_own_repos(int max, gcli_repo_list *out); -void gitlab_repo_delete(char const *owner, - char const *repo); +int gitlab_repo_delete(char const *owner, + char const *repo); gcli_repo *gitlab_repo_create(gcli_repo_create_options const *options); diff --git a/include/gcli/repos.h b/include/gcli/repos.h index ca038448..8a887122 100644 --- a/include/gcli/repos.h +++ b/include/gcli/repos.h @@ -75,7 +75,7 @@ void gcli_print_repos_table(enum gcli_output_flags flags, gcli_repo_list const *repos, int max); -void gcli_repo_delete(char const *owner, char const *repo); +int gcli_repo_delete(char const *owner, char const *repo); gcli_repo *gcli_repo_create(gcli_repo_create_options const *); diff --git a/src/cmd.c b/src/cmd.c index b0b8bc6c..bd98e711 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -129,8 +129,9 @@ delete_repo(bool always_yes, const char *owner, const char *repo) delete = true; } - if (delete) - gcli_repo_delete(owner, repo); - else + if (!delete) errx(1, "Operation aborted"); + + if (gcli_repo_delete(owner, repo) < 0) + errx(1, "error: failed to delete repo"); } diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index a8dbb15c..297831af 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -519,7 +519,8 @@ handle_pull_actions(int argc, char *argv[], return EXIT_FAILURE; } - gcli_pull_set_milestone(owner, repo, pr, milestone_id); + if (gcli_pull_set_milestone(owner, repo, pr, milestone_id) < 0) + errx(1, "error: failed to set milestone"); } } else { /* At this point we found an unknown action / stray diff --git a/src/gitea/repos.c b/src/gitea/repos.c index 8973d806..a6b2feca 100644 --- a/src/gitea/repos.c +++ b/src/gitea/repos.c @@ -48,8 +48,8 @@ gitea_repo_create(gcli_repo_create_options const *options) return github_repo_create(options); } -void +int gitea_repo_delete(char const *owner, char const *repo) { - github_repo_delete(owner, repo); + return github_repo_delete(owner, repo); } diff --git a/src/github/repos.c b/src/github/repos.c index 76c00021..f5f94474 100644 --- a/src/github/repos.c +++ b/src/github/repos.c @@ -108,13 +108,13 @@ github_get_own_repos(int const max, gcli_repo_list *const list) return 0; } -void +int github_repo_delete(char const *owner, char const *repo) { - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -123,12 +123,13 @@ github_repo_delete(char const *owner, char const *repo) gcli_get_apibase(), e_owner, e_repo); - gcli_fetch_with_method("DELETE", url, NULL, NULL, &buffer); + rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); - free(buffer.data); free(e_owner); free(e_repo); free(url); + + return rc; } gcli_repo * diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index 944ccb33..347207bc 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -449,18 +449,19 @@ gitlab_mr_set_milestone(char const *owner, { char *url = NULL; char *data = NULL; + int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", gitlab_get_apibase(), owner, repo, mr); data = sn_asprintf("{ \"milestone_id\": \"%d\"}", milestone_id); - gcli_fetch_with_method("PUT", url, data, NULL, NULL); + rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); free(url); free(data); - return 0; + return rc; } int diff --git a/src/gitlab/repos.c b/src/gitlab/repos.c index 9b157d86..c50fc2ce 100644 --- a/src/gitlab/repos.c +++ b/src/gitlab/repos.c @@ -146,13 +146,13 @@ gitlab_get_own_repos(int const max, gcli_repo_list *const out) return n; } -void +int gitlab_repo_delete(char const *owner, char const *repo) { - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -161,12 +161,13 @@ gitlab_repo_delete(char const *owner, char const *repo) gitlab_get_apibase(), e_owner, e_repo); - gcli_fetch_with_method("DELETE", url, NULL, NULL, &buffer); + rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); - free(buffer.data); free(url); free(e_owner); free(e_repo); + + return rc; } gcli_repo * diff --git a/src/repos.c b/src/repos.c index 5544c52f..b06421de 100644 --- a/src/repos.c +++ b/src/repos.c @@ -115,10 +115,10 @@ gcli_get_own_repos(int const max, gcli_repo_list *const out) return gcli_forge()->get_own_repos(max, out); } -void +int gcli_repo_delete(char const *owner, char const *repo) { - gcli_forge()->repo_delete(owner, repo); + return gcli_forge()->repo_delete(owner, repo); } gcli_repo * diff --git a/todo.org b/todo.org index c8231543..475b3a20 100644 --- a/todo.org +++ b/todo.org @@ -121,4 +121,7 @@ + https://api.github.com/repos/zorchenhimer/MovieNight/pulls/156/reviews/611653998 - A review comment has got a diff hunk and a body attached to it. + https://api.github.com/repos/zorchenhimer/MovieNight/pulls/156/reviews/611653998/comments -https://open.spotify.com/track/spotify:tracks:5Xc7TIjrQ74V8B2qq4uCwS + +* Big refactor for libraryfication +** TODO Check errx calls if they print "error: " +** TODO Check for calls to errx in submit routines From 9cbd9172c5ab75028ec5e6a996af33d807dc2068 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 15:08:30 +0200 Subject: [PATCH 042/236] (#190) Make repo_create routines more library friendly We used to allocate inside the creation functions. This is bad practice. Instead pass in a pointer to the struct to fill in. If that pointer is NULL ignore the results. Return an error code instead. --- include/gcli/forges.h | 5 +++-- include/gcli/gitea/repos.h | 3 ++- include/gcli/github/repos.h | 3 ++- include/gcli/gitlab/repos.h | 3 ++- include/gcli/repos.h | 5 ++++- src/cmd/repos.c | 10 ++++----- src/gitea/repos.c | 7 ++++--- src/github/repos.c | 31 ++++++++++++++-------------- src/gitlab/repos.c | 30 +++++++++++++-------------- src/repos.c | 41 +++++++++++++++++++++++++++++-------- 10 files changed, 85 insertions(+), 53 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 923b1445..2e4af765 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -394,8 +394,9 @@ struct gcli_forge_descriptor { /** * Create the given repo */ - gcli_repo *(*repo_create)( - gcli_repo_create_options const *options); + int (*repo_create)( + gcli_repo_create_options const *options, + gcli_repo *out); /** * Delete the given repo */ diff --git a/include/gcli/gitea/repos.h b/include/gcli/gitea/repos.h index aa026523..36894911 100644 --- a/include/gcli/gitea/repos.h +++ b/include/gcli/gitea/repos.h @@ -43,7 +43,8 @@ int gitea_get_repos(char const *owner, int gitea_get_own_repos(int max, gcli_repo_list *out); -gcli_repo *gitea_repo_create(gcli_repo_create_options const *options); +int gitea_repo_create(gcli_repo_create_options const *options, + gcli_repo *out); int gitea_repo_delete(char const *owner, char const *repo); diff --git a/include/gcli/github/repos.h b/include/gcli/github/repos.h index b14c00e4..fb318c52 100644 --- a/include/gcli/github/repos.h +++ b/include/gcli/github/repos.h @@ -46,6 +46,7 @@ int github_get_own_repos(int max, int github_repo_delete(char const *owner, char const *repo); -gcli_repo *github_repo_create(gcli_repo_create_options const *options); +int github_repo_create(gcli_repo_create_options const *options, + gcli_repo *out); #endif /* GITHUB_REPOS_H */ diff --git a/include/gcli/gitlab/repos.h b/include/gcli/gitlab/repos.h index 5bdd8659..c1c871d6 100644 --- a/include/gcli/gitlab/repos.h +++ b/include/gcli/gitlab/repos.h @@ -49,6 +49,7 @@ int gitlab_get_own_repos(int max, gcli_repo_list *out); int gitlab_repo_delete(char const *owner, char const *repo); -gcli_repo *gitlab_repo_create(gcli_repo_create_options const *options); +int gitlab_repo_create(gcli_repo_create_options const *options, + gcli_repo *out); #endif /* GITLAB_REPOS_H */ diff --git a/include/gcli/repos.h b/include/gcli/repos.h index 8a887122..4d875c0a 100644 --- a/include/gcli/repos.h +++ b/include/gcli/repos.h @@ -70,13 +70,16 @@ int gcli_get_own_repos(int max, gcli_repo_list *list); void gcli_repos_free(gcli_repo_list *list); +void gcli_repo_free(gcli_repo *it); void gcli_print_repos_table(enum gcli_output_flags flags, gcli_repo_list const *repos, int max); +void gcli_repo_print(gcli_repo const *it); + int gcli_repo_delete(char const *owner, char const *repo); -gcli_repo *gcli_repo_create(gcli_repo_create_options const *); +int gcli_repo_create(gcli_repo_create_options const *, gcli_repo *out); #endif /* REPOS_H */ diff --git a/src/cmd/repos.c b/src/cmd/repos.c index 3e6736f3..619afbdf 100644 --- a/src/cmd/repos.c +++ b/src/cmd/repos.c @@ -60,7 +60,7 @@ subcommand_repos_create(int argc, char *argv[]) { int ch; gcli_repo_create_options create_options = {0}; - gcli_repo_list list = {0}; + gcli_repo repo = {0}; const struct option options[] = { { .name = "repo", @@ -107,11 +107,11 @@ subcommand_repos_create(int argc, char *argv[]) return EXIT_FAILURE; } - list.repos = gcli_repo_create(&create_options); - list.repos_size = 1; + if (gcli_repo_create(&create_options, &repo) < 0) + errx(1, "error: failed to create repository"); - gcli_print_repos_table(0, &list, 1); - gcli_repos_free(&list); + gcli_repo_print(&repo); + gcli_repo_free(&repo); return EXIT_SUCCESS; } diff --git a/src/gitea/repos.c b/src/gitea/repos.c index a6b2feca..887ad26f 100644 --- a/src/gitea/repos.c +++ b/src/gitea/repos.c @@ -42,10 +42,11 @@ gitea_get_own_repos(int const max, gcli_repo_list *const list) return github_get_own_repos(max, list); } -gcli_repo * -gitea_repo_create(gcli_repo_create_options const *options) +int +gitea_repo_create(gcli_repo_create_options const *options, + gcli_repo *const out) { - return github_repo_create(options); + return github_repo_create(options, out); } int diff --git a/src/github/repos.c b/src/github/repos.c index f5f94474..747241ae 100644 --- a/src/github/repos.c +++ b/src/github/repos.c @@ -132,17 +132,15 @@ github_repo_delete(char const *owner, char const *repo) return rc; } -gcli_repo * -github_repo_create(gcli_repo_create_options const *options) /* Options descriptor */ +int +github_repo_create(gcli_repo_create_options const *options, + gcli_repo *const out) { - gcli_repo *repo; - char *url, *data; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; - sn_sv e_name, e_description; - - /* Will be freed by the caller with gcli_repos_free */ - repo = calloc(1, sizeof(gcli_repo)); + char *url, *data; + gcli_fetch_buffer buffer = {0}; + struct json_stream stream = {0}; + sn_sv e_name, e_description; + int rc = 0; /* Request preparation */ url = sn_asprintf("%s/user/repos", gcli_get_apibase()); @@ -159,17 +157,20 @@ github_repo_create(gcli_repo_create_options const *options) /* Options descripto gcli_json_bool(options->private)); /* Fetch and parse result */ - gcli_fetch_with_method("POST", url, data, NULL, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_repo(&stream, repo); + rc = gcli_fetch_with_method("POST", url, data, NULL, out ? &buffer : NULL); + + if (rc == 0 && out) { + json_open_buffer(&stream, buffer.data, buffer.length); + parse_github_repo(&stream, out); + json_close(&stream); + } /* Cleanup */ - json_close(&stream); free(buffer.data); free(e_name.data); free(e_description.data); free(data); free(url); - return repo; + return rc; } diff --git a/src/gitlab/repos.c b/src/gitlab/repos.c index c50fc2ce..d0bc8c22 100644 --- a/src/gitlab/repos.c +++ b/src/gitlab/repos.c @@ -170,16 +170,14 @@ gitlab_repo_delete(char const *owner, char const *repo) return rc; } -gcli_repo * -gitlab_repo_create(gcli_repo_create_options const *options) /* Options descriptor */ +int +gitlab_repo_create(gcli_repo_create_options const *options, + gcli_repo *out) { - gcli_repo *repo; - char *url, *data; - gcli_fetch_buffer buffer = {0}; - json_stream stream = {0}; - - /* Will be freed by the caller with gcli_repos_free */ - repo = calloc(1, sizeof(gcli_repo)); + char *url, *data; + gcli_fetch_buffer buffer = {0}; + json_stream stream = {0}; + int rc; /* Request preparation */ url = sn_asprintf("%s/projects", gitlab_get_apibase()); @@ -192,15 +190,17 @@ gitlab_repo_create(gcli_repo_create_options const *options) /* Options descripto options->private ? "private" : "public"); /* Fetch and parse result */ - gcli_fetch_with_method("POST", url, data, NULL, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_repo(&stream, repo); + rc = gcli_fetch_with_method("POST", url, data, NULL, out ? &buffer : NULL); + if (rc == 0 && out) { + json_open_buffer(&stream, buffer.data, buffer.length); + parse_gitlab_repo(&stream, out); + + json_close(&stream); + } - /* Cleanup */ - json_close(&stream); free(buffer.data); free(data); free(url); - return repo; + return rc; } diff --git a/src/repos.c b/src/repos.c index b06421de..8ca730dd 100644 --- a/src/repos.c +++ b/src/repos.c @@ -92,15 +92,39 @@ gcli_print_repos_table(enum gcli_output_flags const flags, gcli_tbl_end(table); } +void +gcli_repo_print(gcli_repo const *it) +{ + gcli_dict dict; + + dict = gcli_dict_begin(); + gcli_dict_add(dict, "ID", 0, 0, "%d", it->id); + gcli_dict_add(dict, "FULL NAME", 0, 0, SV_FMT, SV_ARGS(it->full_name)); + gcli_dict_add(dict, "NAME", 0, 0, SV_FMT, SV_ARGS(it->name)); + gcli_dict_add(dict, "OWNER", 0, 0, SV_FMT, SV_ARGS(it->owner)); + gcli_dict_add(dict, "DATE", 0, 0, SV_FMT, SV_ARGS(it->date)); + gcli_dict_add(dict, "VISIBILITY", 0, 0, SV_FMT, SV_ARGS(it->visibility)); + gcli_dict_add(dict, "IS FORK", 0, 0, "%s", sn_bool_yesno(it->is_fork)); + + gcli_dict_end(dict); +} + +void +gcli_repo_free(gcli_repo *it) +{ + free(it->full_name.data); + free(it->name.data); + free(it->owner.data); + free(it->date.data); + free(it->visibility.data); + memset(it, 0, sizeof(*it)); +} + void gcli_repos_free(gcli_repo_list *const list) { for (size_t i = 0; i < list->repos_size; ++i) { - free(list->repos[i].full_name.data); - free(list->repos[i].name.data); - free(list->repos[i].owner.data); - free(list->repos[i].date.data); - free(list->repos[i].visibility.data); + gcli_repo_free(&list->repos[i]); } free(list->repos); @@ -121,9 +145,8 @@ gcli_repo_delete(char const *owner, char const *repo) return gcli_forge()->repo_delete(owner, repo); } -gcli_repo * -gcli_repo_create( - gcli_repo_create_options const *options) /* Options descriptor */ +int +gcli_repo_create(gcli_repo_create_options const *options, gcli_repo *out) { - return gcli_forge()->repo_create(options); + return gcli_forge()->repo_create(options, out); } From 98ee3a20601f06ffcc9b79e58ee15e5fab819d01 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 15:13:32 +0200 Subject: [PATCH 043/236] (#190) Make delete_snippet return an error code --- include/gcli/gitlab/snippets.h | 2 +- src/cmd/snippets.c | 3 ++- src/gitlab/snippets.c | 12 +++++++----- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/include/gcli/gitlab/snippets.h b/include/gcli/gitlab/snippets.h index ad2a94b6..fd1505c6 100644 --- a/include/gcli/gitlab/snippets.h +++ b/include/gcli/gitlab/snippets.h @@ -62,7 +62,7 @@ void gcli_snippets_print(enum gcli_output_flags flags, gcli_snippet_list const *list, int max); -void gcli_snippet_delete(char const *snippet_id); +int gcli_snippet_delete(char const *snippet_id); void gcli_snippet_get(char const *snippet_id); diff --git a/src/cmd/snippets.c b/src/cmd/snippets.c index 56744c18..f26bf114 100644 --- a/src/cmd/snippets.c +++ b/src/cmd/snippets.c @@ -99,7 +99,8 @@ subcommand_snippet_delete(int argc, char *argv[]) return EXIT_FAILURE; } - gcli_snippet_delete(snippet_id); + if (gcli_snippet_delete(snippet_id) < 0) + errx(1, "error: failed to delete snippet"); return EXIT_SUCCESS; } diff --git a/src/gitlab/snippets.c b/src/gitlab/snippets.c index 9d3ddcaa..d01c1f13 100644 --- a/src/gitlab/snippets.c +++ b/src/gitlab/snippets.c @@ -191,16 +191,18 @@ gcli_snippets_print(enum gcli_output_flags const flags, gcli_print_snippets_short(flags, list, max); } -void +int gcli_snippet_delete(char const *snippet_id) { - gcli_fetch_buffer buffer = {0}; - char *url = sn_asprintf("%s/snippets/%s", gitlab_get_apibase(), snippet_id); + int rc = 0; + char *url; - gcli_fetch_with_method("DELETE", url, NULL, NULL, &buffer); + url = sn_asprintf("%s/snippets/%s", gitlab_get_apibase(), snippet_id); + rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); free(url); - free(buffer.data); + + return rc; } void From b36b8014aef417cf0e8f7e7d3bfb647ade04a56a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 15:46:31 +0200 Subject: [PATCH 044/236] (#190) Make fork_create return error codes --- include/gcli/forges.h | 2 +- include/gcli/forks.h | 6 +++--- include/gcli/github/forks.h | 6 +++--- include/gcli/gitlab/forks.h | 6 +++--- src/cmd/forks.c | 3 ++- src/forks.c | 4 ++-- src/github/forks.c | 27 +++++++++++++-------------- src/gitlab/forks.c | 27 +++++++++++++-------------- 8 files changed, 40 insertions(+), 41 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 2e4af765..92b74010 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -85,7 +85,7 @@ struct gcli_forge_descriptor { /** * Fork the given repo into the owner _in */ - void (*fork_create)( + int (*fork_create)( char const *owner, char const *repo, char const *_in); diff --git a/include/gcli/forks.h b/include/gcli/forks.h index bd5d5e4f..675a7c1c 100644 --- a/include/gcli/forks.h +++ b/include/gcli/forks.h @@ -57,9 +57,9 @@ int gcli_get_forks(char const *owner, int max, gcli_fork_list *out); -void gcli_fork_create(char const *owner, - char const *repo, - char const *in); +int gcli_fork_create(char const *owner, + char const *repo, + char const *in); void gcli_print_forks(enum gcli_output_flags flags, gcli_fork_list const *list, diff --git a/include/gcli/github/forks.h b/include/gcli/github/forks.h index d3f336e5..1ac03b3e 100644 --- a/include/gcli/github/forks.h +++ b/include/gcli/github/forks.h @@ -41,8 +41,8 @@ int github_get_forks(char const *owner, int max, gcli_fork_list *out); -void github_fork_create(char const *owner, - char const *repo, - char const *_in); +int github_fork_create(char const *owner, + char const *repo, + char const *_in); #endif /* GITHUB_FORKS_H */ diff --git a/include/gcli/gitlab/forks.h b/include/gcli/gitlab/forks.h index 7d701f70..ec596186 100644 --- a/include/gcli/gitlab/forks.h +++ b/include/gcli/gitlab/forks.h @@ -41,8 +41,8 @@ int gitlab_get_forks(char const *owner, int max, gcli_fork_list *out); -void gitlab_fork_create(char const *owner, - char const *repo, - char const *_in); +int gitlab_fork_create(char const *owner, + char const *repo, + char const *_in); #endif /* GITLAB_FORKS_H */ diff --git a/src/cmd/forks.c b/src/cmd/forks.c index f3b49950..8ea5825b 100644 --- a/src/cmd/forks.c +++ b/src/cmd/forks.c @@ -110,7 +110,8 @@ subcommand_forks_create(int argc, char *argv[]) check_owner_and_repo(&owner, &repo); - gcli_fork_create(owner, repo, in); + if (gcli_fork_create(owner, repo, in) < 0) + errx(1, "error: failed to fork repository"); if (!always_yes) { if (!sn_yesno("Do you want to add a remote for the fork?")) diff --git a/src/forks.c b/src/forks.c index 77aafb52..0916ca3c 100644 --- a/src/forks.c +++ b/src/forks.c @@ -92,10 +92,10 @@ gcli_print_forks(enum gcli_output_flags const flags, gcli_tbl_end(table); } -void +int gcli_fork_create(char const *owner, char const *repo, char const *_in) { - gcli_forge()->fork_create(owner, repo, _in); + return gcli_forge()->fork_create(owner, repo, _in); } void diff --git a/src/github/forks.c b/src/github/forks.c index 0ac81dcb..22a060c9 100644 --- a/src/github/forks.c +++ b/src/github/forks.c @@ -77,36 +77,35 @@ github_get_forks(char const *owner, return 0; } -void +int github_fork_create(char const *owner, char const *repo, char const *_in) { - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - char *post_data = NULL; - sn_sv in = SV_NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + char *post_data = NULL; + sn_sv in = SV_NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/repos/%s/%s/forks", - gcli_get_apibase(), - e_owner, e_repo); + url = sn_asprintf("%s/repos/%s/%s/forks", + gcli_get_apibase(), + e_owner, e_repo); if (_in) { in = gcli_json_escape(SV((char *)_in)); post_data = sn_asprintf("{\"organization\":\""SV_FMT"\"}", SV_ARGS(in)); } - gcli_fetch_with_method("POST", url, post_data, NULL, &buffer); - gcli_print_html_url(buffer); + rc = gcli_fetch_with_method("POST", url, post_data, NULL, NULL); free(in.data); free(url); free(e_owner); free(e_repo); free(post_data); - free(buffer.data); + + return rc; } diff --git a/src/gitlab/forks.c b/src/gitlab/forks.c index 7cd34a91..ac5b33c2 100644 --- a/src/gitlab/forks.c +++ b/src/gitlab/forks.c @@ -76,36 +76,35 @@ gitlab_get_forks(char const *owner, return 0; } -void +int gitlab_fork_create(char const *owner, char const *repo, char const *_in) { - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - char *post_data = NULL; - sn_sv in = SV_NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + char *post_data = NULL; + sn_sv in = SV_NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/projects/%s%%2F%s/fork", - gitlab_get_apibase(), - e_owner, e_repo); + url = sn_asprintf("%s/projects/%s%%2F%s/fork", + gitlab_get_apibase(), + e_owner, e_repo); if (_in) { in = gcli_json_escape(SV((char *)_in)); post_data = sn_asprintf("{\"namespace_path\":\""SV_FMT"\"}", SV_ARGS(in)); } - gcli_fetch_with_method("POST", url, post_data, NULL, &buffer); - gcli_print_html_url(buffer); + rc = gcli_fetch_with_method("POST", url, post_data, NULL, NULL); free(in.data); free(url); free(post_data); free(e_owner); free(e_repo); - free(buffer.data); + + return rc; } From 5fecf38a40468eea94076e3ca6a649e4b29ef182 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 19:57:48 +0200 Subject: [PATCH 045/236] (#190) Make reviews subsystem return error codes This code requires a bit more love as it is very clunky and brittle. Probably rewrite it entirely. --- include/gcli/forges.h | 2 +- include/gcli/github/review.h | 8 +++---- include/gcli/gitlab/review.h | 8 +++---- include/gcli/review.h | 8 +++---- src/cmd/pulls.c | 8 +++++-- src/github/review.c | 44 ++++++++++++++++++++---------------- src/gitlab/review.c | 31 ++++++++++++++----------- src/review.c | 2 +- todo.org | 1 + 9 files changed, 63 insertions(+), 49 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 92b74010..64f9f732 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -406,7 +406,7 @@ struct gcli_forge_descriptor { /** * Fetch MR/PR reviews including comments */ - size_t (*get_reviews)( + int (*get_reviews)( char const *owner, char const *repo, int pr, diff --git a/include/gcli/github/review.h b/include/gcli/github/review.h index 2c8655c6..8941a8ef 100644 --- a/include/gcli/github/review.h +++ b/include/gcli/github/review.h @@ -36,9 +36,9 @@ #include -size_t github_review_get_reviews(char const *owner, - char const *repo, - int pr, - gcli_pr_review **out); +int github_review_get_reviews(char const *owner, + char const *repo, + int pr, + gcli_pr_review **out); #endif /* GITHUB_REVIEW_H */ diff --git a/include/gcli/gitlab/review.h b/include/gcli/gitlab/review.h index 404ad50e..ae9eb12e 100644 --- a/include/gcli/gitlab/review.h +++ b/include/gcli/gitlab/review.h @@ -36,9 +36,9 @@ #include -size_t gitlab_review_get_reviews(char const *owner, - char const *repo, - int pr, - gcli_pr_review **out); +int gitlab_review_get_reviews(char const *owner, + char const *repo, + int pr, + gcli_pr_review **out); #endif /* GITLAB_REVIEW_H */ diff --git a/include/gcli/review.h b/include/gcli/review.h index 6a528ecb..39a6af56 100644 --- a/include/gcli/review.h +++ b/include/gcli/review.h @@ -63,10 +63,10 @@ void gcli_review_reviews_free(gcli_pr_review *it, size_t size); void gcli_review_comments_free(gcli_pr_review_comment *it, size_t size); -size_t gcli_review_get_reviews(char const *owner, - char const *repo, - int pr, - gcli_pr_review **out); +int gcli_review_get_reviews(char const *owner, + char const *repo, + int pr, + gcli_pr_review **out); void gcli_review_print_review_table(gcli_pr_review const *headers, size_t headers_size); diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 297831af..48ec9aa9 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -461,9 +461,13 @@ handle_pull_actions(int argc, char *argv[], } else if (strcmp(action, "reviews") == 0) { /* list reviews */ - gcli_pr_review *reviews = NULL; - size_t reviews_size = gcli_review_get_reviews( + gcli_pr_review *reviews = NULL; + int reviews_size = gcli_review_get_reviews( owner, repo, pr, &reviews); + + if (reviews_size < 0) + errx(1, "error: failed to fetch reviews"); + gcli_review_print_review_table(reviews, reviews_size); gcli_review_reviews_free(reviews, reviews_size); diff --git a/src/github/review.c b/src/github/review.c index 8050d390..5b05957a 100644 --- a/src/github/review.c +++ b/src/github/review.c @@ -139,27 +139,35 @@ static char const *get_reviews_fmt = " }" "}"; -size_t +int github_review_get_reviews(char const *owner, char const *repo, int const pr, gcli_pr_review **const out) { - gcli_fetch_buffer buffer = {0}; - char *url = NULL; - char *query = NULL; - sn_sv query_escaped = {0}; - char *post_data = NULL; - struct json_stream stream = {0}; - enum json_type next = JSON_NULL; - size_t size = 0; - - url = sn_asprintf("%s/graphql", gcli_get_apibase()); - query = sn_asprintf(get_reviews_fmt, owner, repo, pr); + gcli_fetch_buffer buffer = {0}; + char *url = NULL; + char *query = NULL; + sn_sv query_escaped = {0}; + char *post_data = NULL; + struct json_stream stream = {0}; + enum json_type next = JSON_NULL; + int size = 0; + + url = sn_asprintf("%s/graphql", gcli_get_apibase()); + query = sn_asprintf(get_reviews_fmt, owner, repo, pr); query_escaped = gcli_json_escape(SV(query)); - post_data = sn_asprintf("{\"query\": \""SV_FMT"\"}", - SV_ARGS(query_escaped)); - gcli_fetch_with_method("POST", url, post_data, NULL, &buffer); + post_data = sn_asprintf("{\"query\": \""SV_FMT"\"}", + SV_ARGS(query_escaped)); + + size = gcli_fetch_with_method("POST", url, post_data, NULL, &buffer); + free(url); + free(query); + free(query_escaped.data); + free(post_data); + + if (size < 0) + return size; json_open_buffer(&stream, buffer.data, buffer.length); json_set_streaming(&stream, true); @@ -188,12 +196,8 @@ github_review_get_reviews(char const *owner, gcli_json_advance(&stream, "}}}}}"); - free(buffer.data); - free(url); - free(query); - free(query_escaped.data); - free(post_data); json_close(&stream); + free(buffer.data); return size; } diff --git a/src/gitlab/review.c b/src/gitlab/review.c index 93aa5fad..bd3644ab 100644 --- a/src/gitlab/review.c +++ b/src/gitlab/review.c @@ -39,35 +39,40 @@ #include -size_t +int gitlab_review_get_reviews(char const *owner, char const *repo, int const pr, gcli_pr_review **const out) { - gcli_fetch_buffer buffer = {0}; - json_stream stream = {0}; - char *url = NULL; - char *next_url = NULL; - size_t size = 0; + gcli_fetch_buffer buffer = {0}; + json_stream stream = {0}; + char *url = NULL; + char *next_url = NULL; + size_t size = 0; + int rc = 0; url = sn_asprintf( "%s/projects/%s%%2F%s/merge_requests/%d/notes?sort=asc", gitlab_get_apibase(), owner, repo, pr); do { - gcli_fetch(url, &next_url, &buffer); + rc = gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); + if (rc == 0) { + json_open_buffer(&stream, buffer.data, buffer.length); + parse_gitlab_reviews(&stream, out, &size); + json_close(&stream); + } - parse_gitlab_reviews(&stream, out, &size); - - json_close(&stream); free(url); free(buffer.data); - } while ((url = next_url)); /* I hope this doesn't cause any issues */ + } while ((rc == 0) && (url = next_url)); free(next_url); - return size; + if (rc < 0) + return rc; + + return (int)(size); } diff --git a/src/review.c b/src/review.c index c2a70df5..9cf2551b 100644 --- a/src/review.c +++ b/src/review.c @@ -120,7 +120,7 @@ gcli_review_comments_free(gcli_pr_review_comment *it, size_t const size) free(it); } -size_t +int gcli_review_get_reviews(char const *owner, char const *repo, int const pr, diff --git a/todo.org b/todo.org index 475b3a20..419925cd 100644 --- a/todo.org +++ b/todo.org @@ -125,3 +125,4 @@ * Big refactor for libraryfication ** TODO Check errx calls if they print "error: " ** TODO Check for calls to errx in submit routines +** TODO [[file:src/github/review.c::github_review_get_reviews(char const *owner)][github_review_get_reviews]] is garbage From fbb158b621b736d44f4d2d73bdbb9802f5abb17e Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 20:07:02 +0200 Subject: [PATCH 046/236] (#190) Make milestone_get_issues return error codes --- src/cmd/milestones.c | 7 +++++-- src/gitlab/issues.c | 24 +++++++++++++++--------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/cmd/milestones.c b/src/cmd/milestones.c index d0f020df..6b20cd10 100644 --- a/src/cmd/milestones.c +++ b/src/cmd/milestones.c @@ -266,8 +266,10 @@ handle_milestone_actions(int argc, char *argv[], &fetched_milestone, &milestone); gcli_print_milestone(&milestone); + if (gcli_milestone_get_issues(owner, repo, milestone_id, &issues) < 0) + errx(1, "error: failed to fetch issues"); + printf("\nISSUES:\n"); - gcli_milestone_get_issues(owner, repo, milestone_id, &issues); gcli_print_issues_table(0, &issues, -1); gcli_issues_free(&issues); @@ -276,7 +278,8 @@ handle_milestone_actions(int argc, char *argv[], gcli_issue_list issues = {0}; /* Fetch list of issues associated with milestone */ - gcli_milestone_get_issues(owner, repo, milestone_id, &issues); + if (gcli_milestone_get_issues(owner, repo, milestone_id, &issues) < 0) + errx(1, "error: failed to fetch issues"); /* Print them as a table */ gcli_print_issues_table(0, &issues, -1); diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index 5fedb5d6..43b92615 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -43,23 +43,29 @@ gitlab_fetch_issues(char *url, int const max, gcli_issue_list *const out) { - json_stream stream = {0}; - gcli_fetch_buffer json_buffer = {0}; - char *next_url = NULL; + json_stream stream = {0}; + gcli_fetch_buffer json_buffer = {0}; + char *next_url = NULL; + int rc = 0; do { - gcli_fetch(url, &next_url, &json_buffer); - - json_open_buffer(&stream, json_buffer.data, json_buffer.length); + rc = gcli_fetch(url, &next_url, &json_buffer); - parse_gitlab_issues(&stream, &out->issues, &out->issues_size); + if (rc == 0) { + json_open_buffer(&stream, json_buffer.data, json_buffer.length); + parse_gitlab_issues(&stream, &out->issues, &out->issues_size); + json_close(&stream); + } free(json_buffer.data); json_buffer.data = NULL; json_buffer.length = 0; free(url); - json_close(&stream); + + if (rc < 0) + break; + } while ((url = next_url) && (max == -1 || (int)out->issues_size < max)); /* continue iterating if we have both a next_url and we are * supposed to fetch more issues (either max is -1 thus all issues @@ -67,7 +73,7 @@ gitlab_fetch_issues(char *url, free(next_url); - return 0; + return rc; } int From 008dc70bc9200b8c37faa89007346cca53ad7c9b Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 20:14:08 +0200 Subject: [PATCH 047/236] (#190) Make get_issue routines return error codes --- include/gcli/forges.h | 2 +- include/gcli/gitea/issues.h | 8 ++++---- include/gcli/github/issues.h | 8 ++++---- include/gcli/gitlab/issues.h | 8 ++++---- include/gcli/issues.h | 6 ++---- src/cmd/issues.c | 4 +++- src/gitea/issues.c | 10 ++++------ src/github/issues.c | 33 ++++++++++++++++++--------------- src/gitlab/issues.c | 34 ++++++++++++++++++---------------- src/issues.c | 10 ++++------ 10 files changed, 62 insertions(+), 61 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 64f9f732..481f6eec 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -101,7 +101,7 @@ struct gcli_forge_descriptor { /** * Get a summary of an issue */ - void (*get_issue_summary)( + int (*get_issue_summary)( char const *owner, char const *repo, int issue_number, diff --git a/include/gcli/gitea/issues.h b/include/gcli/gitea/issues.h index 5524fadb..b6a9e6c1 100644 --- a/include/gcli/gitea/issues.h +++ b/include/gcli/gitea/issues.h @@ -42,10 +42,10 @@ int gitea_get_issues(char const *owner, int max, gcli_issue_list *out); -void gitea_get_issue_summary(char const *owner, - char const *repo, - int issue, - gcli_issue *out); +int gitea_get_issue_summary(char const *owner, + char const *repo, + int issue, + gcli_issue *out); int gitea_submit_issue(gcli_submit_issue_options opts, gcli_fetch_buffer *out); diff --git a/include/gcli/github/issues.h b/include/gcli/github/issues.h index 319a813d..faca1b51 100644 --- a/include/gcli/github/issues.h +++ b/include/gcli/github/issues.h @@ -47,10 +47,10 @@ int github_get_issues(char const *owner, int max, gcli_issue_list *out); -void github_get_issue_summary(char const *owner, - char const *repo, - int issue_number, - gcli_issue *out); +int github_get_issue_summary(char const *owner, + char const *repo, + int issue_number, + gcli_issue *out); int github_issue_close(char const *owner, char const *repo, diff --git a/include/gcli/gitlab/issues.h b/include/gcli/gitlab/issues.h index ebd5ac0a..42e65aa2 100644 --- a/include/gcli/gitlab/issues.h +++ b/include/gcli/gitlab/issues.h @@ -47,10 +47,10 @@ int gitlab_get_issues(char const *owner, int max, gcli_issue_list *out); -void gitlab_get_issue_summary(char const *owner, - char const *repo, - int issue_number, - gcli_issue *out); +int gitlab_get_issue_summary(char const *owner, + char const *repo, + int issue_number, + gcli_issue *out); int gitlab_issue_close(char const *owner, char const *repo, diff --git a/include/gcli/issues.h b/include/gcli/issues.h index 7a16b9f3..6a6faf95 100644 --- a/include/gcli/issues.h +++ b/include/gcli/issues.h @@ -92,10 +92,8 @@ void gcli_print_issues_table(enum gcli_output_flags flags, gcli_issue_list const *list, int max); -void gcli_get_issue(char const *owner, - char const *reponame, - int issue_number, - gcli_issue *out); +int gcli_get_issue(char const *owner, char const *reponame, + int issue_number, gcli_issue *out); void gcli_issue_free(gcli_issue *it); diff --git a/src/cmd/issues.c b/src/cmd/issues.c index 8578cfa8..22d6f5dd 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -269,7 +269,9 @@ ensure_issue(char const *const owner, char const *const repo, if (*have_fetched_issue) return; - gcli_get_issue(owner, repo, issue_id, issue); + if (gcli_get_issue(owner, repo, issue_id, issue) < 0) + errx(1, "error: failed to retrieve issue data"); + *have_fetched_issue = 1; } diff --git a/src/gitea/issues.c b/src/gitea/issues.c index 89a969b5..c851e0f3 100644 --- a/src/gitea/issues.c +++ b/src/gitea/issues.c @@ -47,13 +47,11 @@ gitea_get_issues(char const *owner, return github_get_issues(owner, repo, details, max, out); } -void -gitea_get_issue_summary(char const *owner, - char const *repo, - int const issue_number, - gcli_issue *const out) +int +gitea_get_issue_summary(char const *owner, char const *repo, + int const issue_number, gcli_issue *const out) { - github_get_issue_summary(owner, repo, issue_number, out); + return github_get_issue_summary(owner, repo, issue_number, out); } int diff --git a/src/github/issues.c b/src/github/issues.c index 2a2413e3..3a6a054b 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -127,17 +127,16 @@ github_get_issues(char const *owner, return github_fetch_issues(url, max, out); } -void -github_get_issue_summary(char const *owner, - char const *repo, - int const issue_number, - gcli_issue *const out) +int +github_get_issue_summary(char const *owner, char const *repo, + int const issue_number, gcli_issue *const out) { - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - gcli_fetch_buffer buffer = {0}; - json_stream parser = {0}; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + gcli_fetch_buffer buffer = {0}; + json_stream parser = {0}; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -147,18 +146,22 @@ github_get_issue_summary(char const *owner, gcli_get_apibase(), e_owner, e_repo, issue_number); - gcli_fetch(url, NULL, &buffer); - json_open_buffer(&parser, buffer.data, buffer.length); - json_set_streaming(&parser, true); + rc = gcli_fetch(url, NULL, &buffer); - parse_github_issue(&parser, out); + if (rc == 0) { + json_open_buffer(&parser, buffer.data, buffer.length); + json_set_streaming(&parser, true); + parse_github_issue(&parser, out); + json_close(&parser); + } - json_close(&parser); free(url); free(e_owner); free(e_repo); free(buffer.data); + + return rc; } int diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index 43b92615..9f24786f 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -113,17 +113,16 @@ gitlab_get_issues(char const *owner, return gitlab_fetch_issues(url, max, out); } -void -gitlab_get_issue_summary(char const *owner, - char const *repo, - int const issue_number, - gcli_issue *const out) +int +gitlab_get_issue_summary(char const *owner, char const *repo, + int const issue_number, gcli_issue *const out) { - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - gcli_fetch_buffer buffer = {0}; - json_stream parser = {0}; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + gcli_fetch_buffer buffer = {0}; + json_stream parser = {0}; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -133,18 +132,21 @@ gitlab_get_issue_summary(char const *owner, gitlab_get_apibase(), e_owner, e_repo, issue_number); - gcli_fetch(url, NULL, &buffer); - - json_open_buffer(&parser, buffer.data, buffer.length); - json_set_streaming(&parser, true); - parse_gitlab_issue(&parser, out); + rc = gcli_fetch(url, NULL, &buffer); + if (rc == 0) { + json_open_buffer(&parser, buffer.data, buffer.length); + json_set_streaming(&parser, true); + parse_gitlab_issue(&parser, out); + json_close(&parser); + } - json_close(&parser); free(url); free(e_owner); free(e_repo); free(buffer.data); + + return rc; } int diff --git a/src/issues.c b/src/issues.c index 4857815d..af7bbdfb 100644 --- a/src/issues.c +++ b/src/issues.c @@ -183,13 +183,11 @@ gcli_issue_print_op(gcli_issue const *const it) pretty_print(it->body.data, 4, 80, stdout); } -void -gcli_get_issue(char const *owner, - char const *repo, - int const issue_number, - gcli_issue *const out) +int +gcli_get_issue(char const *owner, char const *repo, + int const issue_number, gcli_issue *const out) { - gcli_forge()->get_issue_summary(owner, repo, issue_number, out); + return gcli_forge()->get_issue_summary(owner, repo, issue_number, out); } int From 8248610c928fd91e2c1484951b5dcbe709616891 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 20:16:48 +0200 Subject: [PATCH 048/236] (#190) Make gitlab_user_id return error codes --- src/gitlab/issues.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index 9f24786f..8930baf3 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -239,24 +239,26 @@ gitlab_perform_submit_issue(gcli_submit_issue_options opts, static int gitlab_user_id(char const *user_name) { - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; - char *url = NULL; - char *e_username; - int uid = -1; + gcli_fetch_buffer buffer = {0}; + struct json_stream stream = {0}; + char *url = NULL; + char *e_username; + int uid = -1; e_username = gcli_urlencode(user_name); url = sn_asprintf("%s/users?username=%s", gitlab_get_apibase(), e_username); - gcli_fetch(url, NULL, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - json_set_streaming(&stream, 1); + uid = gcli_fetch(url, NULL, &buffer); + if (uid == 0) { + json_open_buffer(&stream, buffer.data, buffer.length); + json_set_streaming(&stream, 1); - gcli_json_advance(&stream, "[{s", "id"); - uid = get_int(&stream); + gcli_json_advance(&stream, "[{s", "id"); + uid = get_int(&stream); - json_close(&stream); + json_close(&stream); + } free(e_username); free(url); @@ -271,17 +273,19 @@ gitlab_issue_assign(char const *owner, int const issue_number, char const *assignee) { - int assignee_uid = -1; - char *url = NULL; - char *post_data = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - int rc = 0; + int assignee_uid = -1; + char *url = NULL; + char *post_data = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; assignee_uid = gitlab_user_id(assignee); + if (assignee_uid < 0) + return assignee_uid; e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gitlab_get_apibase(), From 4af311bc30408da8a372b66ea4f1b5080f049dd6 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 20:27:47 +0200 Subject: [PATCH 049/236] (#190) Make get_release routines return error codes --- src/github/releases.c | 31 +++++++++++++++++++------------ src/gitlab/releases.c | 32 ++++++++++++++++++++------------ src/releases.c | 6 ++---- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/src/github/releases.c b/src/github/releases.c index fc859fb2..b67109b1 100644 --- a/src/github/releases.c +++ b/src/github/releases.c @@ -44,13 +44,13 @@ github_get_releases(char const *owner, int const max, gcli_release_list *const list) { - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - char *next_url = NULL; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; - + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + char *next_url = NULL; + gcli_fetch_buffer buffer = {0}; + struct json_stream stream = {0}; + int rc = 0; *list = (gcli_release_list) {0}; @@ -63,20 +63,27 @@ github_get_releases(char const *owner, e_owner, e_repo); do { - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_releases(&stream, &list->releases, &list->releases_size); + rc = gcli_fetch(url, &next_url, &buffer); + if (rc == 0) { + json_open_buffer(&stream, buffer.data, buffer.length); + parse_github_releases(&stream, &list->releases, &list->releases_size); + json_close(&stream); + } - json_close(&stream); free(url); free(buffer.data); + + if (rc < 0) + break; } while ((url = next_url) && (max == -1 || (int)list->releases_size < max)); free(next_url); free(e_owner); free(e_repo); - return 0; + /* TODO: Don't leak the list in case of an error */ + + return rc; } static void diff --git a/src/gitlab/releases.c b/src/gitlab/releases.c index aeec7594..50bf728c 100644 --- a/src/gitlab/releases.c +++ b/src/gitlab/releases.c @@ -64,13 +64,13 @@ gitlab_get_releases(char const *owner, int const max, gcli_release_list *const list) { - char *url = NULL; - char *next_url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - gcli_fetch_buffer buffer = {0}; - json_stream stream = {0}; - + char *url = NULL; + char *next_url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + gcli_fetch_buffer buffer = {0}; + json_stream stream = {0}; + int rc = 0; *list = (gcli_release_list) {0}; @@ -83,22 +83,30 @@ gitlab_get_releases(char const *owner, e_owner, e_repo); do { - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); + rc = gcli_fetch(url, &next_url, &buffer); - parse_gitlab_releases(&stream, &list->releases, &list->releases_size); + if (rc == 0) { + json_open_buffer(&stream, buffer.data, buffer.length); + parse_gitlab_releases(&stream, &list->releases, &list->releases_size); + json_close(&stream); + } free(url); free(buffer.data); + + if (rc < 0) + break; } while ((url = next_url) && (max == -1 || (int)list->releases_size < max)); free(e_owner); free(e_repo); free(next_url); - fixup_release_asset_names(list); + /* TODO: Don't leak the list in case of an error */ + if (rc == 0) + fixup_release_asset_names(list); - return 0; + return rc; } int diff --git a/src/releases.c b/src/releases.c index d3525486..f031ff67 100644 --- a/src/releases.c +++ b/src/releases.c @@ -36,10 +36,8 @@ #include int -gcli_get_releases(char const *owner, - char const *repo, - int const max, - gcli_release_list *const list) +gcli_get_releases(char const *owner, char const *repo, + int const max, gcli_release_list *const list) { return gcli_forge()->get_releases(owner, repo, max, list); } From 534fff54eee33df70a9d262b0f8467a234884338 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 21:29:19 +0200 Subject: [PATCH 050/236] (#190) Make get_notifications routines return error codes --- include/gcli/forges.h | 2 +- include/gcli/github/status.h | 3 +-- include/gcli/gitlab/status.h | 3 +-- include/gcli/status.h | 2 +- src/github/status.c | 33 +++++++++++++++++++++------------ src/gitlab/status.c | 33 +++++++++++++++++++++------------ src/status.c | 12 +++++++----- 7 files changed, 53 insertions(+), 35 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 481f6eec..86095eda 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -414,7 +414,7 @@ struct gcli_forge_descriptor { /** * Status summary for the account */ - size_t (*get_notifications)( + int (*get_notifications)( gcli_notification **notifications, int count); diff --git a/include/gcli/github/status.h b/include/gcli/github/status.h index 93450efb..2319dd11 100644 --- a/include/gcli/github/status.h +++ b/include/gcli/github/status.h @@ -36,8 +36,7 @@ #include -size_t github_get_notifications(gcli_notification **notifications, - int count); +int github_get_notifications(gcli_notification **notifications, int count); int github_notification_mark_as_read(char const *id); diff --git a/include/gcli/gitlab/status.h b/include/gcli/gitlab/status.h index d2116e14..120f58f0 100644 --- a/include/gcli/gitlab/status.h +++ b/include/gcli/gitlab/status.h @@ -36,8 +36,7 @@ #include -size_t gitlab_get_notifications(gcli_notification **notifications, - int count); +int gitlab_get_notifications(gcli_notification **notifications, int count); int gitlab_notification_mark_as_read(char const *id); diff --git a/include/gcli/status.h b/include/gcli/status.h index b2b42401..081515b0 100644 --- a/include/gcli/status.h +++ b/include/gcli/status.h @@ -49,7 +49,7 @@ typedef struct gcli_notification gcli_notification; void gcli_status(int count); -size_t gcli_get_notifications(gcli_notification **out, int count); +int gcli_get_notifications(gcli_notification **out, int count); int gcli_notification_mark_as_read(char const *id); diff --git a/src/github/status.c b/src/github/status.c index 4db796f6..ef1127cf 100644 --- a/src/github/status.c +++ b/src/github/status.c @@ -37,31 +37,40 @@ #include -size_t +int github_get_notifications(gcli_notification **const notifications, int const count) { - char *url = NULL; - char *next_url = NULL; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; - size_t notifications_size = 0; + char *url = NULL; + char *next_url = NULL; + gcli_fetch_buffer buffer = {0}; + struct json_stream stream = {0}; + size_t notifications_size = 0; + int rc = 0; url = sn_asprintf("%s/notifications", gcli_get_apibase()); do { - gcli_fetch(url, &next_url, &buffer); + rc = gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); + if (rc == 0) { + json_open_buffer(&stream, buffer.data, buffer.length); + parse_github_notifications(&stream, notifications, ¬ifications_size); + json_close(&stream); + } - parse_github_notifications(&stream, notifications, ¬ifications_size); - - json_close(&stream); free(url); free(buffer.data); + + if (rc < 0) + break; } while ((url = next_url) && (count < 0 || ((int)notifications_size < count))); - return notifications_size; + /* TODO: don't leak the list on error */ + if (rc < 0) + return rc; + + return (int)(notifications_size); } int diff --git a/src/gitlab/status.c b/src/gitlab/status.c index d3b069bb..8d0ee2fb 100644 --- a/src/gitlab/status.c +++ b/src/gitlab/status.c @@ -37,31 +37,40 @@ #include -size_t +int gitlab_get_notifications(gcli_notification **const notifications, int const count) { - char *url = NULL; - char *next_url = NULL; - gcli_fetch_buffer buffer = {0}; - json_stream stream = {0}; - size_t notifications_size = 0; + char *url = NULL; + char *next_url = NULL; + gcli_fetch_buffer buffer = {0}; + json_stream stream = {0}; + size_t notifications_size = 0; + int rc = 0; url = sn_asprintf("%s/todos", gitlab_get_apibase()); do { - gcli_fetch(url, &next_url, &buffer); + rc = gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); + if (rc == 0) { + json_open_buffer(&stream, buffer.data, buffer.length); + parse_gitlab_todos(&stream, notifications, ¬ifications_size); + json_close(&stream); + } - parse_gitlab_todos(&stream, notifications, ¬ifications_size); - - json_close(&stream); free(url); free(buffer.data); + + if (rc < 0) + break; } while ((url = next_url) && (count < 0 || (int)notifications_size < count)); - return notifications_size; + /* TODO: don't leak the list on error */ + if (rc < 0) + return rc; + + return (int)(notifications_size); } int diff --git a/src/status.c b/src/status.c index 1431c39f..5e4ce487 100644 --- a/src/status.c +++ b/src/status.c @@ -33,24 +33,26 @@ void gcli_status(int const count) { - gcli_notification *notifications = NULL; - size_t notifications_size = 0; + gcli_notification *notifications = NULL; + int notifications_size = 0; notifications_size = gcli_get_notifications(¬ifications, count); + if (notifications_size < 0) + errx(1, "error: failed to get notifications"); if (count < 0) { gcli_print_notifications(notifications, notifications_size); } else { gcli_print_notifications( notifications, - count < (int)notifications_size - ? (size_t)count : notifications_size); + (size_t)(count < (int)notifications_size + ? count : notifications_size)); } gcli_free_notifications(notifications, notifications_size); } -size_t +int gcli_get_notifications(gcli_notification **const out, int const count) { return gcli_forge()->get_notifications(out, count); From 500eac0ba80f2e0fa8733074f0d4b73664b606ea Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 20:45:30 +0200 Subject: [PATCH 051/236] (#190) Make gitlab_get_milestones return proper error codes --- src/gitlab/milestones.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/gitlab/milestones.c b/src/gitlab/milestones.c index ee1b0094..18de765b 100644 --- a/src/gitlab/milestones.c +++ b/src/gitlab/milestones.c @@ -51,6 +51,7 @@ gitlab_get_milestones(char const *owner, char *e_owner, *e_repo; gcli_fetch_buffer buffer = {0}; json_stream stream = {0}; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -59,22 +60,28 @@ gitlab_get_milestones(char const *owner, gitlab_get_apibase(), e_owner, e_repo); do { - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); + rc = gcli_fetch(url, &next_url, &buffer); - parse_gitlab_milestones(&stream, &out->milestones, &out->milestones_size); + if (rc == 0) { + json_open_buffer(&stream, buffer.data, buffer.length); + parse_gitlab_milestones(&stream, &out->milestones, &out->milestones_size); + json_close(&stream); + } free(buffer.data); free(url); - json_close(&stream); + + if (rc < 0) + break; } while ((url = next_url) && (max == -1 || (int)out->milestones_size < max)); free(next_url); - free(e_owner); free(e_repo); - return 0; + /* TODO: don't leak the list on error */ + + return rc; } int From f6e4e6be06a2bdf3fe843e7873ee3d66a036552a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 20:47:13 +0200 Subject: [PATCH 052/236] (#190) Make gitlab_get_milestone return proper error codes --- src/gitlab/milestones.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/gitlab/milestones.c b/src/gitlab/milestones.c index 18de765b..233dc914 100644 --- a/src/gitlab/milestones.c +++ b/src/gitlab/milestones.c @@ -101,12 +101,13 @@ gitlab_get_milestone(char const *owner, url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d", gitlab_get_apibase(), e_owner, e_repo, milestone); - gcli_fetch(url, NULL, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - - parse_gitlab_milestone(&stream, out); + rc = gcli_fetch(url, NULL, &buffer); + if (rc == 0) { + json_open_buffer(&stream, buffer.data, buffer.length); + parse_gitlab_milestone(&stream, out); + json_close(&stream); + } - json_close(&stream); free(buffer.data); free(url); free(e_owner); From af2e06bb783e388d15d069af9593372c336bcb37 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 20:51:21 +0200 Subject: [PATCH 053/236] (#190) Make fetch_pipelines return proper error codes --- src/gitlab/pipelines.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index ed22faad..4e22b6e2 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -42,25 +42,31 @@ static int fetch_pipelines(char *url, int const max, gitlab_pipeline_list *const list) { - char *next_url = NULL; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; + char *next_url = NULL; + gcli_fetch_buffer buffer = {0}; + struct json_stream stream = {0}; + int rc = 0; *list = (gitlab_pipeline_list) {0}; do { - gcli_fetch(url, &next_url, &buffer); - - json_open_buffer(&stream, buffer.data, buffer.length); + rc = gcli_fetch(url, &next_url, &buffer); - parse_gitlab_pipelines(&stream, &list->pipelines, &list->pipelines_size); + if (rc == 0) { + json_open_buffer(&stream, buffer.data, buffer.length); + parse_gitlab_pipelines(&stream, &list->pipelines, &list->pipelines_size); + json_close(&stream); + } - json_close(&stream); free(buffer.data); free(url); + + if (rc < 0) + break; } while ((url = next_url) && (max == -1 || (int)list->pipelines_size < max)); - return 0; + /* TODO: don't leak the list on error */ + return rc; } int From 2d37be6d4a618b20efbe43c1805d20225ca6de24 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 20:55:35 +0200 Subject: [PATCH 054/236] (#190) Make gitlab_perform_get_comments return proper error codes --- src/comments.c | 3 +++ src/gitlab/comments.c | 25 ++++++++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/comments.c b/src/comments.c index 2b500ea8..0effa1ba 100644 --- a/src/comments.c +++ b/src/comments.c @@ -65,6 +65,9 @@ gcli_issue_comments(char const *owner, char const *repo, int const issue) int n = -1; n = gcli_forge()->get_issue_comments(owner, repo, issue, &comments); + if (n < 0) + errx(1, "error: failed to fetch issue comments"); + gcli_print_comment_list(comments, (size_t)n); for (int i = 0; i < n; ++i) diff --git a/src/gitlab/comments.c b/src/gitlab/comments.c index 90c19c2d..6ce54a56 100644 --- a/src/gitlab/comments.c +++ b/src/gitlab/comments.c @@ -75,24 +75,31 @@ gitlab_perform_submit_comment(gcli_submit_comment_opts opts, static int gitlab_perform_get_comments(char const *_url, gcli_comment **const comments) { - size_t count = 0; - json_stream stream = {0}; - gcli_fetch_buffer json_buffer = {0}; - char *url = (char *)_url; - char *next_url = NULL; + size_t count = 0; + json_stream stream = {0}; + gcli_fetch_buffer json_buffer = {0}; + char *url = (char *)_url; + char *next_url = NULL; + int rc = 0; do { - gcli_fetch(url, &next_url, &json_buffer); - json_open_buffer(&stream, json_buffer.data, json_buffer.length); + rc = gcli_fetch(url, &next_url, &json_buffer); - parse_gitlab_comments(&stream, comments, &count); + if (rc == 0) { + json_open_buffer(&stream, json_buffer.data, json_buffer.length); + parse_gitlab_comments(&stream, comments, &count); + json_close(&stream); + } - json_close(&stream); free(json_buffer.data); if (url != _url) free(url); + /* TODO: don't leak the list on error */ + if (rc < 0) + return rc; + } while ((url = next_url)); return (int)(count); From 33ded9fa08283fed2596c8193bfec2746eb7447c Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 20:55:44 +0200 Subject: [PATCH 055/236] Update todo.org --- todo.org | 1 + 1 file changed, 1 insertion(+) diff --git a/todo.org b/todo.org index 419925cd..4ff56606 100644 --- a/todo.org +++ b/todo.org @@ -126,3 +126,4 @@ ** TODO Check errx calls if they print "error: " ** TODO Check for calls to errx in submit routines ** TODO [[file:src/github/review.c::github_review_get_reviews(char const *owner)][github_review_get_reviews]] is garbage +** TODO Clean up the generic comments code From 9bc006753afd743501399384ccf38f9d077b3f75 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 21:00:29 +0200 Subject: [PATCH 056/236] (#190) Make gitlab_get_sshkeys return proper error codes --- src/gitlab/sshkeys.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/gitlab/sshkeys.c b/src/gitlab/sshkeys.c index 6ebb1c17..6d79ee39 100644 --- a/src/gitlab/sshkeys.c +++ b/src/gitlab/sshkeys.c @@ -45,24 +45,32 @@ int gitlab_get_sshkeys(gcli_sshkey_list *list) { char *url, *next_url = NULL; + int rc = 0; *list = (gcli_sshkey_list) {0}; url = sn_asprintf("%s/user/keys", gcli_get_apibase()); do { gcli_fetch_buffer buf = {0}; - json_stream str; - gcli_fetch(url, &next_url, &buf); - json_open_buffer(&str, buf.data, buf.length); - parse_gitlab_sshkeys(&str, &list->keys, &list->keys_size); + rc = gcli_fetch(url, &next_url, &buf); + + if (rc == 0) { + json_stream str; + + json_open_buffer(&str, buf.data, buf.length); + parse_gitlab_sshkeys(&str, &list->keys, &list->keys_size); + json_close(&str); + } - json_close(&str); free(buf.data); free(url); - } while ((url = next_url)); - return 0; + } while ((rc == 0) && (url = next_url)); + + /* TODO: don't leak the list on error */ + + return rc; } int From b2487fe8c7d8926c4c6dc8a4a1bfd8aae26a0687 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 21:04:14 +0200 Subject: [PATCH 057/236] (#190) Make gitlab_fetch_mrs return proper error codes --- src/gitlab/merge_requests.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index 347207bc..07d97b57 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -50,25 +50,36 @@ gitlab_mrs_fixup(gcli_pull_list *const list) int gitlab_fetch_mrs(char *url, int const max, gcli_pull_list *const list) { - json_stream stream = {0}; - gcli_fetch_buffer json_buffer = {0}; - char *next_url = NULL; + char *next_url = NULL; + int rc = 0; do { - gcli_fetch(url, &next_url, &json_buffer); - json_open_buffer(&stream, json_buffer.data, json_buffer.length); - parse_gitlab_mrs(&stream, &list->pulls, &list->pulls_size); + gcli_fetch_buffer json_buffer = {0}; + + rc = gcli_fetch(url, &next_url, &json_buffer); + + if (rc == 0) { + json_stream stream = {0}; + + json_open_buffer(&stream, json_buffer.data, json_buffer.length); + parse_gitlab_mrs(&stream, &list->pulls, &list->pulls_size); + json_close(&stream); + } - free(json_buffer.data); free(url); - json_close(&stream); + free(json_buffer.data); + + if (rc < 0) + break; } while ((url = next_url) && (max == -1 || (int)list->pulls_size < max)); free(url); - gitlab_mrs_fixup(list); + /* TODO: don't leak the list on error */ + if (rc == 0) + gitlab_mrs_fixup(list); - return 0; + return rc; } int From fec83550ccdedf3d7562b9c88c7dbbd45d258528 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 21:10:33 +0200 Subject: [PATCH 058/236] (#190) Make get_pull routines return error codes --- include/gcli/forges.h | 2 +- include/gcli/gitea/pulls.h | 8 ++++---- include/gcli/github/pulls.h | 8 ++++---- include/gcli/gitlab/merge_requests.h | 8 ++++---- include/gcli/pulls.h | 6 ++---- src/cmd/pulls.c | 4 +++- src/gitea/pulls.c | 4 ++-- src/github/pulls.c | 29 ++++++++++++++++----------- src/gitlab/merge_requests.c | 30 ++++++++++++++++------------ src/pulls.c | 10 ++++------ 10 files changed, 58 insertions(+), 51 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 86095eda..bef9aede 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -296,7 +296,7 @@ struct gcli_forge_descriptor { /** * Get a summary of the given PR/MR */ - void (*get_pull)( + int (*get_pull)( char const *owner, char const *repo, int pr_number, diff --git a/include/gcli/gitea/pulls.h b/include/gcli/gitea/pulls.h index 49d2caad..54ab2138 100644 --- a/include/gcli/gitea/pulls.h +++ b/include/gcli/gitea/pulls.h @@ -43,10 +43,10 @@ int gitea_get_pulls(char const *owner, int max, gcli_pull_list *out); -void gitea_get_pull(char const *owner, - char const *repo, - int pr_number, - gcli_pull *out); +int gitea_get_pull(char const *owner, + char const *repo, + int pr_number, + gcli_pull *out); int gitea_get_pull_commits(char const *owner, char const *repo, diff --git a/include/gcli/github/pulls.h b/include/gcli/github/pulls.h index b2ddaee6..eb29a313 100644 --- a/include/gcli/github/pulls.h +++ b/include/gcli/github/pulls.h @@ -77,10 +77,10 @@ int github_get_pull_commits(char const *owner, int pr_number, gcli_commit **out); -void github_get_pull(char const *owner, - char const *repo, - int pr_number, - gcli_pull *out); +int github_get_pull(char const *owner, + char const *repo, + int pr_number, + gcli_pull *out); sn_sv github_pull_try_derive_head(void); diff --git a/include/gcli/gitlab/merge_requests.h b/include/gcli/gitlab/merge_requests.h index 7c2adef5..1de3a61f 100644 --- a/include/gcli/gitlab/merge_requests.h +++ b/include/gcli/gitlab/merge_requests.h @@ -64,10 +64,10 @@ int gitlab_mr_reopen(char const *owner, char const *reponame, int pr_number); -void gitlab_get_pull(char const *owner, - char const *repo, - int pr_number, - gcli_pull *out); +int gitlab_get_pull(char const *owner, + char const *repo, + int pr_number, + gcli_pull *out); int gitlab_get_pull_commits(char const *owner, char const *repo, diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index e430346b..302f08d4 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -127,10 +127,8 @@ void gcli_pull_commits(char const *owner, char const *repo, int pr_number); -void gcli_get_pull(char const *owner, - char const *repo, - int pr_number, - gcli_pull *out); +int gcli_get_pull(char const *owner, char const *repo, + int pr_number, gcli_pull *out); int gcli_pull_submit(gcli_submit_pull_options); diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 48ec9aa9..1271a233 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -339,7 +339,9 @@ ensure_pull(char const *owner, char const *repo, int pr, if (*fetched_pull) return; - gcli_get_pull(owner, repo, pr, pull); + if (gcli_get_pull(owner, repo, pr, pull) < 0) + errx(1, "error: failed to fetch pull request data"); + *fetched_pull = 1; } diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index 90dbb88e..ba3721ed 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -42,13 +42,13 @@ gitea_get_pulls(char const *owner, return github_get_pulls(owner, repo, details, max, out); } -void +int gitea_get_pull(char const *owner, char const *repo, int const pr_number, gcli_pull *const out) { - github_get_pull(owner, repo, pr_number, out); + return github_get_pull(owner, repo, pr_number, out); } int diff --git a/src/github/pulls.c b/src/github/pulls.c index 5e8c3691..aa3d3805 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -366,17 +366,17 @@ github_get_pull_commits(char const *owner, return (int)count; } -void +int github_get_pull(char const *owner, char const *repo, int const pr_number, gcli_pull *const out) { - json_stream stream = {0}; - gcli_fetch_buffer json_buffer = {0}; - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + int rc = 0; + gcli_fetch_buffer json_buffer = {0}; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -385,17 +385,22 @@ github_get_pull(char const *owner, "%s/repos/%s/%s/pulls/%d", gcli_get_apibase(), e_owner, e_repo, pr_number); - gcli_fetch(url, NULL, &json_buffer); + free(e_owner); + free(e_repo); - json_open_buffer(&stream, json_buffer.data, json_buffer.length); + rc = gcli_fetch(url, NULL, &json_buffer); + if (rc == 0) { + json_stream stream = {0}; - parse_github_pull(&stream, out); + json_open_buffer(&stream, json_buffer.data, json_buffer.length); + parse_github_pull(&stream, out); + json_close(&stream); + } - json_close(&stream); free(url); - free(e_owner); - free(e_repo); free(json_buffer.data); + + return rc; } int diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index 07d97b57..552d08c4 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -184,17 +184,17 @@ gitlab_mr_merge(char const *owner, return rc; } -void +int gitlab_get_pull(char const *owner, char const *repo, int const pr_number, gcli_pull *const out) { - json_stream stream = {0}; - gcli_fetch_buffer json_buffer = {0}; - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; + gcli_fetch_buffer json_buffer = {0}; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -204,17 +204,21 @@ gitlab_get_pull(char const *owner, "%s/projects/%s%%2F%s/merge_requests/%d", gitlab_get_apibase(), e_owner, e_repo, pr_number); - gcli_fetch(url, NULL, &json_buffer); - - json_open_buffer(&stream, json_buffer.data, json_buffer.length); + free(e_owner); + free(e_repo); - parse_gitlab_mr(&stream, out); + rc = gcli_fetch(url, NULL, &json_buffer); + if (rc == 0) { + json_stream stream = {0}; + json_open_buffer(&stream, json_buffer.data, json_buffer.length); + parse_gitlab_mr(&stream, out); + json_close(&stream); + } - json_close(&stream); free(url); - free(e_owner); - free(e_repo); free(json_buffer.data); + + return rc; } int diff --git a/src/pulls.c b/src/pulls.c index c86edf5d..89b84241 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -285,13 +285,11 @@ gcli_pull_free(gcli_pull *const it) free(it->labels); } -void -gcli_get_pull(char const *owner, - char const *repo, - int const pr_number, - gcli_pull *const out) +int +gcli_get_pull(char const *owner, char const *repo, + int const pr_number, gcli_pull *const out) { - gcli_forge()->get_pull(owner, repo, pr_number, out); + return gcli_forge()->get_pull(owner, repo, pr_number, out); } void From 0204feb895f574569114411688930abdba6db1d1 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 21:14:46 +0200 Subject: [PATCH 059/236] (#190) Make gitlab_get_pipeline_jobs return error codes --- src/gitlab/pipelines.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index 4e22b6e2..efa6ad63 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -164,6 +164,9 @@ gitlab_pipeline_jobs(char const *owner, { gitlab_job *jobs = NULL; int const jobs_size = gitlab_get_pipeline_jobs(owner, repo, id, count, &jobs); + if (jobs_size < 0) + errx(1, "error: failed to get jobs"); + gitlab_print_jobs(jobs, jobs_size); gitlab_free_jobs(jobs, jobs_size); } @@ -175,25 +178,37 @@ gitlab_get_pipeline_jobs(char const *owner, int const max, gitlab_job **const out) { - char *url = NULL; - char *next_url = NULL; - size_t out_size = 0; + char *url = NULL; + char *next_url = NULL; + size_t out_size = 0; + int rc; url = sn_asprintf("%s/projects/%s%%2F%s/pipelines/%ld/jobs", gitlab_get_apibase(), owner, repo, pipeline); do { gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); + rc = gcli_fetch(url, &next_url, &buffer); + if (rc == 0) { + json_stream stream = {0}; - parse_gitlab_jobs(&stream, out, &out_size); + json_open_buffer(&stream, buffer.data, buffer.length); + parse_gitlab_jobs(&stream, out, &out_size); + json_close(&stream); + } free(url); + + if (rc < 0) + break; } while ((url = next_url) && (((int)out_size < max) || (max == -1))); + free(next_url); + + if (rc < 0) + return rc; + return (int)out_size; } From fde7afb509d7e35fb05808bd979c5a82e29b0572 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 21:18:41 +0200 Subject: [PATCH 060/236] (#190) Make gitlab_get_pull_commits return error codes --- src/gitlab/merge_requests.c | 36 ++++++++++++++++++++++-------------- src/pulls.c | 7 +++++-- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index 552d08c4..7cf15d42 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -227,13 +227,12 @@ gitlab_get_pull_commits(char const *owner, int const pr_number, gcli_commit **const out) { - char *url = NULL; - char *next_url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - size_t count = 0; - json_stream stream = {0}; - gcli_fetch_buffer json_buffer = {0}; + char *url = NULL; + char *next_url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + size_t count = 0; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -244,19 +243,28 @@ gitlab_get_pull_commits(char const *owner, gitlab_get_apibase(), e_owner, e_repo, pr_number); + free(e_owner); + free(e_repo); + do { - gcli_fetch(url, &next_url, &json_buffer); - json_open_buffer(&stream, json_buffer.data, json_buffer.length); + gcli_fetch_buffer json_buffer = {0}; - parse_gitlab_commits(&stream, out, &count); + rc = gcli_fetch(url, &next_url, &json_buffer); + if (rc == 0) { + json_stream stream = {0}; + + json_open_buffer(&stream, json_buffer.data, json_buffer.length); + parse_gitlab_commits(&stream, out, &count); + json_close(&stream); + } - json_close(&stream); free(url); free(json_buffer.data); - } while ((url = next_url)); - free(e_owner); - free(e_repo); + /* TODO: don't leak the list on error */ + if (rc < 0) + return rc; + } while ((url = next_url)); return (int)(count); } diff --git a/src/pulls.c b/src/pulls.c index 89b84241..4d1e7d6c 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -259,10 +259,13 @@ gcli_pull_commits(char const *owner, char const *repo, int const pr_number) { - gcli_commit *commits = NULL; - int commits_size = 0; + gcli_commit *commits = NULL; + int commits_size = 0; commits_size = gcli_get_pull_commits(owner, repo, pr_number, &commits); + if (commits_size < 0) + errx(1, "error: failed to fetch commits of the pull request"); + gcli_print_commits_table(commits, commits_size); gcli_commits_free(commits, commits_size); } From 0a5e10d65d98a793f00b52982fd54e205e252066 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 22:14:18 +0200 Subject: [PATCH 061/236] (#190) Make gitlab_get_repos return proper error codes --- src/cmd/repos.c | 9 +++++++-- src/gitlab/repos.c | 33 ++++++++++++++++++++------------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/cmd/repos.c b/src/cmd/repos.c index 619afbdf..3dd00561 100644 --- a/src/cmd/repos.c +++ b/src/cmd/repos.c @@ -191,6 +191,8 @@ subcommand_repos(int argc, char *argv[]) /* List repos of the owner */ if (argc == 0) { + int rc = 0; + if (repo) { fprintf(stderr, "error: repos: no actions specified\n"); usage(); @@ -198,9 +200,12 @@ subcommand_repos(int argc, char *argv[]) } if (!owner) - gcli_get_own_repos(n, &repos); + rc = gcli_get_own_repos(n, &repos); else - gcli_get_repos(owner, n, &repos); + rc = gcli_get_repos(owner, n, &repos); + + if (rc < 0) + errx(1, "error: failed to fetch repos"); gcli_print_repos_table(flags, &repos, n); gcli_repos_free(&repos); diff --git a/src/gitlab/repos.c b/src/gitlab/repos.c index d0bc8c22..2e92d177 100644 --- a/src/gitlab/repos.c +++ b/src/gitlab/repos.c @@ -96,34 +96,41 @@ gitlab_get_repos(char const *owner, int const max, gcli_repo_list *const list) { - char *url = NULL; - char *next_url = NULL; - char *e_owner = NULL; - gcli_fetch_buffer buffer = {0}; - json_stream stream = {0}; + char *url = NULL; + char *next_url = NULL; + char *e_owner = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); - url = sn_asprintf("%s/users/%s/projects", gitlab_get_apibase(), e_owner); + free(e_owner); do { - gcli_fetch(url, &next_url, &buffer); + gcli_fetch_buffer buffer = {0}; - json_open_buffer(&stream, buffer.data, buffer.length); + rc = gcli_fetch(url, &next_url, &buffer); - parse_gitlab_repos(&stream, &list->repos, &list->repos_size); + if (rc == 0) { + json_stream stream = {0}; + + json_open_buffer(&stream, buffer.data, buffer.length); + parse_gitlab_repos(&stream, &list->repos, &list->repos_size); + json_close(&stream); + } free(url); free(buffer.data); - json_close(&stream); + + if (rc < 0) + break; } while ((url = next_url) && (max == -1 || (int)list->repos_size < max)); free(url); - free(e_owner); - gitlab_repos_fixup_missing_visibility(list); + if (rc == 0) + gitlab_repos_fixup_missing_visibility(list); - return 0; + return rc; } int From dba5536c9cab6f2c5c75928b7de1ff6fd325b8da Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 23:33:14 +0200 Subject: [PATCH 062/236] (#190) Make gcli_snippets_get return proper error codes --- src/cmd/snippets.c | 4 +++- src/gitlab/snippets.c | 30 +++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/cmd/snippets.c b/src/cmd/snippets.c index f26bf114..c65c0121 100644 --- a/src/cmd/snippets.c +++ b/src/cmd/snippets.c @@ -173,7 +173,9 @@ subcommand_snippets(int argc, char *argv[]) argc -= optind; argv += optind; - gcli_snippets_get(count, &list); + if (gcli_snippets_get(count, &list) < 0) + errx(1, "error: failed to fetch snippets"); + gcli_snippets_print(flags, &list, count); gcli_snippets_free(&list); diff --git a/src/gitlab/snippets.c b/src/gitlab/snippets.c index d01c1f13..fa1d77d3 100644 --- a/src/gitlab/snippets.c +++ b/src/gitlab/snippets.c @@ -61,28 +61,40 @@ gcli_snippets_free(gcli_snippet_list *const list) int gcli_snippets_get(int const max, gcli_snippet_list *const out) { - char *url = NULL; - char *next_url = NULL; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; + char *url = NULL; + char *next_url = NULL; + int rc = 0; *out = (gcli_snippet_list) {0}; url = sn_asprintf("%s/snippets", gitlab_get_apibase()); do { - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_snippets(&stream, &out->snippets, &out->snippets_size); + gcli_fetch_buffer buffer = {0}; + + rc = gcli_fetch(url, &next_url, &buffer); + + if (rc == 0) { + struct json_stream stream = {0}; + + json_open_buffer(&stream, buffer.data, buffer.length); + parse_gitlab_snippets(&stream, &out->snippets, &out->snippets_size); + json_close(&stream); + } - json_close(&stream); free(url); free(buffer.data); + + if (rc < 0) + break; + } while ((url = next_url) && (max == -1 || (int)out->snippets_size < max)); + /* TODO: don't leak list in case of an error */ + free(next_url); - return 0; + return rc; } static void From b151d5c3721c68d09efd2984581f85d2acadf929 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 13 Aug 2023 23:39:06 +0200 Subject: [PATCH 063/236] (#190) Refactor make gitlab_get_forks return proper error codes --- src/gitlab/forks.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/gitlab/forks.c b/src/gitlab/forks.c index ac5b33c2..b4affdd5 100644 --- a/src/gitlab/forks.c +++ b/src/gitlab/forks.c @@ -42,12 +42,11 @@ gitlab_get_forks(char const *owner, int const max, gcli_fork_list *const list) { - gcli_fetch_buffer buffer = {0}; - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - char *next_url = NULL; - struct json_stream stream = {0}; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + char *next_url = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -60,20 +59,32 @@ gitlab_get_forks(char const *owner, e_owner, e_repo); do { - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_forks(&stream, &list->forks, &list->forks_size); + gcli_fetch_buffer buffer = {0}; + + rc = gcli_fetch(url, &next_url, &buffer); + if (rc == 0) { + struct json_stream stream = {0}; + + json_open_buffer(&stream, buffer.data, buffer.length); + parse_gitlab_forks(&stream, &list->forks, &list->forks_size); + json_close(&stream); + } - json_close(&stream); free(buffer.data); free(url); + + if (rc < 0) + break; + } while ((url = next_url) && (max == -1 || (int)list->forks_size < max)); + /* TODO: don't leak the list on error */ + free(next_url); free(e_owner); free(e_repo); - return 0; + return rc; } int From fd24c70557a0c1d7d4df5e2dd66304ec659a4415 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 00:27:39 +0200 Subject: [PATCH 064/236] (#190) Introduce new fetchloop function and make gitlab_forks use it This might be reusable in various places. Or not in which case we can add a fetch context that adds things like.. filters. --- include/gcli/curl.h | 5 +++++ src/curl.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/gitlab/forks.c | 28 +++++----------------------- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/include/gcli/curl.h b/include/gcli/curl.h index 04cc77a6..3aef2735 100644 --- a/include/gcli/curl.h +++ b/include/gcli/curl.h @@ -38,8 +38,10 @@ #include #include +#include #include +typedef void (*parsefn)(json_stream *stream, void *list, size_t *listsize); typedef struct gcli_fetch_buffer gcli_fetch_buffer; struct gcli_fetch_buffer { @@ -75,5 +77,8 @@ bool gcli_curl_test_success(char const *url); char *gcli_urlencode(char const *); sn_sv gcli_urlencode_sv(sn_sv const); char *gcli_urldecode(char const *input); +int gcli_fetch_list(char *url, parsefn fn, + void *list, size_t *listsize, + int max); #endif /* CURL_H */ diff --git a/src/curl.c b/src/curl.c index 8df2755f..eaf2f73a 100644 --- a/src/curl.c +++ b/src/curl.c @@ -572,3 +572,47 @@ gcli_urldecode(char const *input) return result; } + +/* Convenience function for fetching lists. + * + * listptr must be a double-pointer (pointer to a pointer to the start + * of the array). e.g. + * + * struct foolist { struct foo *foos; size_t foos_size; } *out = ...; + * + * listptr = &out->foos; + * listsize = &out->foos_size; + * + * If max is -1 then everything will be fetched. */ +int +gcli_fetch_list(char *url, parsefn parse, + void *listptr, size_t *listsize, + int const max) +{ + char *next_url = NULL; + int rc; + + do { + gcli_fetch_buffer buffer = {0}; + + rc = gcli_fetch(url, &next_url, &buffer); + if (rc == 0) { + struct json_stream stream = {0}; + + json_open_buffer(&stream, buffer.data, buffer.length); + parse(&stream, list, listsize); + json_close(&stream); + } + + free(buffer.data); + free(url); + + if (rc < 0) + break; + + } while ((url = next_url) && (max == -1 || (int)(*listsize) < max)); + + free(next_url); + + return rc; +} diff --git a/src/gitlab/forks.c b/src/gitlab/forks.c index b4affdd5..879c8188 100644 --- a/src/gitlab/forks.c +++ b/src/gitlab/forks.c @@ -45,7 +45,6 @@ gitlab_get_forks(char const *owner, char *url = NULL; char *e_owner = NULL; char *e_repo = NULL; - char *next_url = NULL; int rc = 0; e_owner = gcli_urlencode(owner); @@ -58,32 +57,15 @@ gitlab_get_forks(char const *owner, gitlab_get_apibase(), e_owner, e_repo); - do { - gcli_fetch_buffer buffer = {0}; - - rc = gcli_fetch(url, &next_url, &buffer); - if (rc == 0) { - struct json_stream stream = {0}; - - json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_forks(&stream, &list->forks, &list->forks_size); - json_close(&stream); - } - - free(buffer.data); - free(url); - - if (rc < 0) - break; + free(e_owner); + free(e_repo); - } while ((url = next_url) && (max == -1 || (int)list->forks_size < max)); + rc = gcli_fetch_list(url, (parsefn)parse_gitlab_forks, + &list->forks, &list->forks_size, + max); /* TODO: don't leak the list on error */ - free(next_url); - free(e_owner); - free(e_repo); - return rc; } From 96f5375c8baa7bf4b275b175a6208a50c3bfa45a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 00:17:48 +0200 Subject: [PATCH 065/236] (#190) Clean up get_issue_comments and get_pull_comment routines - Return proper error codes - Use generic fetch_list function - Add proper list type such that the return type indicates status and not status + size --- include/gcli/comments.h | 11 ++++-- include/gcli/forges.h | 4 +-- include/gcli/gitea/comments.h | 7 ++-- include/gcli/github/comments.h | 2 +- include/gcli/gitlab/comments.h | 12 +++---- src/comments.c | 63 +++++++++++++++++++++------------- src/curl.c | 2 +- src/gitea/comments.c | 6 ++-- src/github/comments.c | 50 ++++++--------------------- src/gitlab/comments.c | 57 +++++------------------------- 10 files changed, 79 insertions(+), 135 deletions(-) diff --git a/include/gcli/comments.h b/include/gcli/comments.h index 82c6509e..e6edd21e 100644 --- a/include/gcli/comments.h +++ b/include/gcli/comments.h @@ -40,6 +40,7 @@ #include typedef struct gcli_comment gcli_comment; +typedef struct gcli_comment_list gcli_comment_list; typedef struct gcli_submit_comment_opts gcli_submit_comment_opts; struct gcli_comment { @@ -49,6 +50,11 @@ struct gcli_comment { char const *body; /* Raw text of the comment */ }; +struct gcli_comment_list { + gcli_comment *comments; /* List of comments */ + size_t comments_size; /* Size of the list */ +}; + struct gcli_submit_comment_opts { enum comment_target_type { ISSUE_COMMENT, PR_COMMENT } target_type; char const *owner, *repo; @@ -57,9 +63,8 @@ struct gcli_submit_comment_opts { bool always_yes; }; -void gcli_print_comment_list(gcli_comment const *comments, - size_t comments_size); - +void gcli_comment_list_free(gcli_comment_list *list); +void gcli_print_comment_list(gcli_comment_list const *list); void gcli_issue_comments(char const *owner, char const *repo, int issue); void gcli_pull_comments(char const *owner, char const *repo, int issue); int gcli_comment_submit(gcli_submit_comment_opts opts); diff --git a/include/gcli/forges.h b/include/gcli/forges.h index bef9aede..b24c90b7 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -65,7 +65,7 @@ struct gcli_forge_descriptor { char const *owner, char const *repo, int issue, - gcli_comment **out); + gcli_comment_list *out); /** * List comments on the given PR */ @@ -73,7 +73,7 @@ struct gcli_forge_descriptor { char const *owner, char const *repo, int pr, - gcli_comment **out); + gcli_comment_list *out); /** * List forks of the given repo */ diff --git a/include/gcli/gitea/comments.h b/include/gcli/gitea/comments.h index 868a0880..36f8524e 100644 --- a/include/gcli/gitea/comments.h +++ b/include/gcli/gitea/comments.h @@ -37,11 +37,8 @@ #include #include -int gitea_get_comments( - char const *owner, - char const *repo, - int issue, - gcli_comment **out); +int gitea_get_comments(char const *owner, char const *repo, + int issue, gcli_comment_list *out); int gitea_perform_submit_comment( gcli_submit_comment_opts opts, diff --git a/include/gcli/github/comments.h b/include/gcli/github/comments.h index 5b450b14..f8690589 100644 --- a/include/gcli/github/comments.h +++ b/include/gcli/github/comments.h @@ -44,6 +44,6 @@ int github_perform_submit_comment( int github_get_comments(char const *owner, char const *repo, int issue, - gcli_comment **out); + gcli_comment_list *out); #endif /* GITHUB_COMMENTS_H */ diff --git a/include/gcli/gitlab/comments.h b/include/gcli/gitlab/comments.h index c9ff9a30..557335b6 100644 --- a/include/gcli/gitlab/comments.h +++ b/include/gcli/gitlab/comments.h @@ -40,14 +40,10 @@ int gitlab_perform_submit_comment(gcli_submit_comment_opts opts, gcli_fetch_buffer *out); -int gitlab_get_issue_comments(char const *owner, - char const *repo, - int issue, - gcli_comment **out); +int gitlab_get_issue_comments(char const *owner, char const *repo, + int issue, gcli_comment_list *out); -int gitlab_get_mr_comments(char const *owner, - char const *repo, - int issue, - gcli_comment **out); +int gitlab_get_mr_comments(char const *owner, char const *repo, + int issue, gcli_comment_list *out); #endif /* GITLAB_COMMENTS_H */ diff --git a/src/comments.c b/src/comments.c index 0effa1ba..64fb41b7 100644 --- a/src/comments.c +++ b/src/comments.c @@ -45,50 +45,65 @@ gcli_issue_comment_free(gcli_comment *const it) } void -gcli_print_comment_list(gcli_comment const *const comments, - size_t const comments_size) +gcli_comment_list_free(gcli_comment_list *list) { - for (size_t i = 0; i < comments_size; ++i) { + for (size_t i = 0; i < list->comments_size; ++i) + gcli_issue_comment_free(&list->comments[i]); + + free(list->comments); + list->comments = NULL; + list->comments_size = 0; +} + +void +gcli_print_comment_list(gcli_comment_list const *const list) +{ + for (size_t i = 0; i < list->comments_size; ++i) { printf("AUTHOR : %s%s%s\n" "DATE : %s\n", - gcli_setbold(), comments[i].author, gcli_resetbold(), - comments[i].date); - pretty_print(comments[i].body, 9, 80, stdout); + gcli_setbold(), list->comments[i].author, gcli_resetbold(), + list->comments[i].date); + pretty_print(list->comments[i].body, 9, 80, stdout); putchar('\n'); } } +int +gcli_get_issue_comments(char const *owner, char const *repo, int const issue, + gcli_comment_list *out) +{ + return gcli_forge()->get_issue_comments(owner, repo, issue, out); +} + void gcli_issue_comments(char const *owner, char const *repo, int const issue) { - gcli_comment *comments = NULL; - int n = -1; + gcli_comment_list list = {0}; - n = gcli_forge()->get_issue_comments(owner, repo, issue, &comments); - if (n < 0) - errx(1, "error: failed to fetch issue comments"); + if (gcli_get_issue_comments(owner, repo, issue, &list) < 0) + errx(1, "error: failed to fetch comments"); - gcli_print_comment_list(comments, (size_t)n); - - for (int i = 0; i < n; ++i) - gcli_issue_comment_free(&comments[i]); + gcli_print_comment_list(&list); + gcli_comment_list_free(&list); +} - free(comments); +int +gcli_get_pull_comments(char const *owner, char const *repo, int const pull, + gcli_comment_list *out) +{ + return gcli_forge()->get_pull_comments(owner, repo, pull, out); } void gcli_pull_comments(char const *owner, char const *repo, int const issue) { - gcli_comment *comments = NULL; - int n = -1; - - n = gcli_forge()->get_pull_comments(owner, repo, issue, &comments); - gcli_print_comment_list(comments, (size_t)n); + gcli_comment_list list = {0}; - for (int i = 0; i < n; ++i) - gcli_issue_comment_free(&comments[i]); + if (gcli_get_pull_comments(owner, repo, issue, &list) < 0) + errx(1, "error: failed to fetch pull request comments"); - free(comments); + gcli_print_comment_list(&list); + gcli_comment_list_free(&list); } static void diff --git a/src/curl.c b/src/curl.c index eaf2f73a..18bc49ee 100644 --- a/src/curl.c +++ b/src/curl.c @@ -600,7 +600,7 @@ gcli_fetch_list(char *url, parsefn parse, struct json_stream stream = {0}; json_open_buffer(&stream, buffer.data, buffer.length); - parse(&stream, list, listsize); + parse(&stream, listptr, listsize); json_close(&stream); } diff --git a/src/gitea/comments.c b/src/gitea/comments.c index 496d4c77..44241342 100644 --- a/src/gitea/comments.c +++ b/src/gitea/comments.c @@ -31,10 +31,8 @@ #include int -gitea_get_comments(char const *owner, - char const *repo, - int const issue, - gcli_comment **const out) +gitea_get_comments(char const *owner, char const *repo, + int const issue, gcli_comment_list *const out) { return github_get_comments(owner, repo, issue, out); } diff --git a/src/github/comments.c b/src/github/comments.c index 4f6f0487..912a09a0 100644 --- a/src/github/comments.c +++ b/src/github/comments.c @@ -62,52 +62,24 @@ github_perform_submit_comment(gcli_submit_comment_opts opts, return rc; } -static int -github_perform_get_comments(char const *_url, gcli_comment **const comments) -{ - size_t count = 0; - json_stream stream = {0}; - gcli_fetch_buffer json_buffer = {0}; - char *next_url = NULL; - char *url = (char *)(_url); - - do { - gcli_fetch(url, &next_url, &json_buffer); - json_open_buffer(&stream, json_buffer.data, json_buffer.length); - - parse_github_comments(&stream, comments, &count); - - json_close(&stream); - free(json_buffer.data); - - if (url != _url) - free(url); - } while ((url = next_url)); - - return (int)count; -} - int -github_get_comments(char const *owner, - char const *repo, - int const issue, - gcli_comment **const out) +github_get_comments(char const *owner, char const *repo, + int const issue, gcli_comment_list *const out) { char *e_owner = NULL; - char *e_repo = NULL; - char *url = NULL; + char *e_repo = NULL; + char *url = NULL; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/repos/%s/%s/issues/%d/comments", - gcli_get_apibase(), - e_owner, e_repo, issue); - int n = github_perform_get_comments(url, out); - + url = sn_asprintf("%s/repos/%s/%s/issues/%d/comments", + gcli_get_apibase(), + e_owner, e_repo, issue); free(e_owner); free(e_repo); - free(url); - return n; + + return gcli_fetch_list(url, (parsefn)parse_github_comments, + &out->comments, &out->comments_size, + -1); } diff --git a/src/gitlab/comments.c b/src/gitlab/comments.c index 6ce54a56..f2170c06 100644 --- a/src/gitlab/comments.c +++ b/src/gitlab/comments.c @@ -72,44 +72,11 @@ gitlab_perform_submit_comment(gcli_submit_comment_opts opts, return rc; } -static int -gitlab_perform_get_comments(char const *_url, gcli_comment **const comments) -{ - size_t count = 0; - json_stream stream = {0}; - gcli_fetch_buffer json_buffer = {0}; - char *url = (char *)_url; - char *next_url = NULL; - int rc = 0; - - do { - rc = gcli_fetch(url, &next_url, &json_buffer); - - if (rc == 0) { - json_open_buffer(&stream, json_buffer.data, json_buffer.length); - parse_gitlab_comments(&stream, comments, &count); - json_close(&stream); - } - - free(json_buffer.data); - - if (url != _url) - free(url); - - /* TODO: don't leak the list on error */ - if (rc < 0) - return rc; - - } while ((url = next_url)); - - return (int)(count); -} - int gitlab_get_mr_comments(char const *owner, char const *repo, int const mr, - gcli_comment **const out) + gcli_comment_list *const out) { char *e_owner = gcli_urlencode(owner); char *e_repo = gcli_urlencode(repo); @@ -118,21 +85,17 @@ gitlab_get_mr_comments(char const *owner, "%s/projects/%s%%2F%s/merge_requests/%d/notes", gitlab_get_apibase(), e_owner, e_repo, mr); - - int n = gitlab_perform_get_comments(url, out); - - free(url); free(e_owner); free(e_repo); - return n; + return gcli_fetch_list(url, (parsefn)parse_gitlab_comments, + &out->comments, &out->comments_size, + -1); } int -gitlab_get_issue_comments(char const *owner, - char const *repo, - int const issue, - gcli_comment **const out) +gitlab_get_issue_comments(char const *owner, char const *repo, + int const issue, gcli_comment_list *const out) { char *e_owner = gcli_urlencode(owner); char *e_repo = gcli_urlencode(repo); @@ -141,12 +104,10 @@ gitlab_get_issue_comments(char const *owner, "%s/projects/%s%%2F%s/issues/%d/notes", gitlab_get_apibase(), e_owner, e_repo, issue); - - int n = gitlab_perform_get_comments(url, out); - - free(url); free(e_owner); free(e_repo); - return n; + return gcli_fetch_list(url, (parsefn)parse_gitlab_comments, + &out->comments, &out->comments_size, + -1); } From bfc98bc8dc42c43f8ed6d8771bdf3ee54d7f6847 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 00:22:43 +0200 Subject: [PATCH 066/236] (#190) Make github_get_milestone return proper error codes --- src/github/milestones.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/github/milestones.c b/src/github/milestones.c index a9462f65..1ff2e78e 100644 --- a/src/github/milestones.c +++ b/src/github/milestones.c @@ -84,7 +84,7 @@ github_get_milestone(char const *const owner, { char *url, *e_owner, *e_repo; gcli_fetch_buffer buffer = {0}; - json_stream stream = {0}; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -92,18 +92,22 @@ github_get_milestone(char const *const owner, url = sn_asprintf("%s/repos/%s/%s/milestones/%d", gcli_get_apibase(), e_owner, e_repo, milestone); - gcli_fetch(url, NULL, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); + free(e_repo); + free(e_owner); + + rc = gcli_fetch(url, NULL, &buffer); + if (rc == 0) { + json_stream stream = {0}; - parse_github_milestone(&stream, out); + json_open_buffer(&stream, buffer.data, buffer.length); + parse_github_milestone(&stream, out); + json_close(&stream); + } - json_close(&stream); free(url); free(buffer.data); - free(e_repo); - free(e_owner); - return 0; + return rc; } int From 449249eacea5c5792e955abb3286d55d6337828c Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 00:28:02 +0200 Subject: [PATCH 067/236] (#190) Make github_get_milestones use fetch_list routine --- src/github/milestones.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/github/milestones.c b/src/github/milestones.c index 1ff2e78e..c30249ff 100644 --- a/src/github/milestones.c +++ b/src/github/milestones.c @@ -48,7 +48,7 @@ github_get_milestones(char const *const owner, int const max, gcli_milestone_list *const out) { - char *url, *next_url = NULL, *e_owner, *e_repo; + char *url, *e_owner, *e_repo; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -57,23 +57,12 @@ github_get_milestones(char const *const owner, gcli_get_apibase(), e_owner, e_repo); - do { - gcli_fetch_buffer buffer = {0}; - json_stream stream = {0}; - - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - - parse_github_milestones(&stream, &out->milestones, &out->milestones_size); - - json_close(&stream); - free(url); - free(buffer.data); - } while ((url = next_url) && ((max < 0) || (out->milestones_size < (size_t)max))); - - free(url); + free(e_owner); + free(e_repo); - return 0; + return gcli_fetch_list(url, (parsefn)parse_github_milestones, + &out->milestones, &out->milestones_size, + max); } int From 6ee12e64428c866de67a6859dddf190d0642a6cc Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 12:28:43 +0200 Subject: [PATCH 068/236] (#190) Make gcli_get_gists return proper error codes --- src/github/gists.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/github/gists.c b/src/github/gists.c index 245b2ee4..b390d2a0 100644 --- a/src/github/gists.c +++ b/src/github/gists.c @@ -65,11 +65,7 @@ parse_github_gist_files_idiot_hack(json_stream *stream, gcli_gist *const gist) int gcli_get_gists(char const *user, int const max, gcli_gist_list *const list) { - char *url = NULL; - char *next_url = NULL; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; - size_t size = 0; + char *url = NULL; if (user) url = sn_asprintf( @@ -79,19 +75,9 @@ gcli_get_gists(char const *user, int const max, gcli_gist_list *const list) else url = sn_asprintf("%s/gists", github_get_apibase()); - do { - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_gists(&stream, &list->gists, &list->gists_size); - - json_close(&stream); - free(buffer.data); - free(url); - } while ((url = next_url) && (max == -1 || (int)size < max)); - - free(next_url); - - return (int)size; + return gcli_fetch_list(url, (parsefn)(parse_github_gists), + &list->gists, &list->gists_size, + max); } static char const * From 23643c8e2f0f0f4ad482aa03b0a3529488177a71 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 14:24:17 +0200 Subject: [PATCH 069/236] (#190) Make gcli_get_gist return proper error codes --- src/github/gists.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/github/gists.c b/src/github/gists.c index b390d2a0..943dc2b0 100644 --- a/src/github/gists.c +++ b/src/github/gists.c @@ -226,22 +226,26 @@ gcli_print_gists(enum gcli_output_flags const flags, gcli_gist * gcli_get_gist(char const *gist_id) { - char *url = NULL; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; - gcli_gist *it = NULL; + char *url = NULL; + gcli_fetch_buffer buffer = {0}; + gcli_gist *it = NULL; + int rc = 0; url = sn_asprintf("%s/gists/%s", github_get_apibase(), gist_id); + rc = gcli_fetch(url, NULL, &buffer); + + if (rc == 0) { + struct json_stream stream = {0}; - gcli_fetch(url, NULL, &buffer); + json_open_buffer(&stream, buffer.data, buffer.length); + json_set_streaming(&stream, 1); - json_open_buffer(&stream, buffer.data, buffer.length); - json_set_streaming(&stream, 1); + it = calloc(sizeof(gcli_gist), 1); + parse_github_gist(&stream, it); - it = calloc(sizeof(gcli_gist), 1); - parse_github_gist(&stream, it); + json_close(&stream); + } - json_close(&stream); free(buffer.data); free(url); From 7d00620aa97ba71d008de9fa73d56a24d61cd3c2 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 14:25:02 +0200 Subject: [PATCH 070/236] (#190) Make github_get_labels return proper error codes --- src/github/labels.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/github/labels.c b/src/github/labels.c index 58ec0617..cfffa583 100644 --- a/src/github/labels.c +++ b/src/github/labels.c @@ -42,8 +42,6 @@ github_get_labels(char const *owner, gcli_label_list *const out) { char *url = NULL; - char *next_url = NULL; - gcli_fetch_buffer buffer = {0}; *out = (gcli_label_list) {0}; @@ -51,19 +49,9 @@ github_get_labels(char const *owner, "%s/repos/%s/%s/labels", gcli_get_apibase(), owner, reponame); - do { - struct json_stream stream = {0}; - - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_labels(&stream, &out->labels, &out->labels_size); - - json_close(&stream); - free(url); - free(buffer.data); - } while ((url = next_url) && ((int)(out->labels_size) < max || max < 0)); - - return 0; + return gcli_fetch_list(url, (parsefn)(parse_github_labels), + &out->labels, &out->labels_size, + max); } int From 9b42ec9db7531e77d94d7cbec0c07a337e6bd97c Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 14:46:34 +0200 Subject: [PATCH 071/236] (#190) Make gcli_github_checks return proper error codes --- include/gcli/github/checks.h | 8 +++--- src/github/checks.c | 47 +++++++++++++++++++++--------------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/include/gcli/github/checks.h b/include/gcli/github/checks.h index 6db79dda..2a10ad57 100644 --- a/include/gcli/github/checks.h +++ b/include/gcli/github/checks.h @@ -53,11 +53,9 @@ struct gcli_github_checks { size_t checks_size; }; -void github_get_checks(char const *owner, - char const *repo, - char const *ref, - int max, - gcli_github_checks *checks); +int github_get_checks(char const *owner, char const *repo, + char const *ref, int max, + gcli_github_checks *checks); void github_print_checks(gcli_github_checks const *checks); diff --git a/src/github/checks.c b/src/github/checks.c index e4da88e7..1b02f83b 100644 --- a/src/github/checks.c +++ b/src/github/checks.c @@ -41,16 +41,14 @@ #include -void -github_get_checks(char const *owner, - char const *repo, - char const *ref, - int const max, +int +github_get_checks(char const *owner, char const *repo, + char const *ref, int const max, gcli_github_checks *const out) { - gcli_fetch_buffer buffer = {0}; - char *url = NULL; - char *next_url = NULL; + gcli_fetch_buffer buffer = {0}; + char *url = NULL, *next_url = NULL; + int rc = 0; assert(out); @@ -59,17 +57,26 @@ github_get_checks(char const *owner, owner, repo, ref); do { - struct json_stream stream = {0}; + rc = gcli_fetch(url, &next_url, &buffer); + if (rc == 0) { + struct json_stream stream = {0}; - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); + json_open_buffer(&stream, buffer.data, buffer.length); + parse_github_checks(&stream, out); + json_close(&stream); + } - parse_github_checks(&stream, out); - - json_close(&stream); free(url); free(buffer.data); + + if (rc < 0) + break; } while ((url = next_url) && ((int)(out->checks_size) < max || max < 0)); + + /* TODO: don't leak list on error */ + free(next_url); + + return rc; } void @@ -121,14 +128,16 @@ github_free_checks(gcli_github_checks *const list) } int -github_checks(char const *owner, - char const *repo, - char const *ref, - int const max) +github_checks(char const *owner, char const *repo, + char const *ref, int const max) { gcli_github_checks checks = {0}; + int rc; + + rc = github_get_checks(owner, repo, ref, max, &checks); + if (rc < 0) + return rc; - github_get_checks(owner, repo, ref, max, &checks); github_print_checks(&checks); github_free_checks(&checks); From 51920ba038a26f9bd8eedf52d728a48ed1ee3311 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 14:46:57 +0200 Subject: [PATCH 072/236] (#190) Make gcli_pull_checks pass error codes --- include/gcli/pulls.h | 6 +++--- src/cmd/pulls.c | 6 ++++-- src/pulls.c | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index 302f08d4..4d36a272 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -119,9 +119,9 @@ void gcli_print_pull_diff(FILE *stream, char const *reponame, int pr_number); -void gcli_pull_checks(char const *owner, - char const *repo, - int pr_number); +int gcli_pull_checks(char const *owner, + char const *repo, + int pr_number); void gcli_pull_commits(char const *owner, char const *repo, diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 1271a233..c5d23741 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -395,7 +395,8 @@ handle_pull_actions(int argc, char *argv[], /* Checks */ puts("\nCHECKS"); - gcli_pull_checks(owner, repo, pr); + if (gcli_pull_checks(owner, repo, pr) < 0) + errx(1, "error: failed to fetch pull request checks"); } else if (strcmp(action, "op") == 0) { @@ -426,7 +427,8 @@ handle_pull_actions(int argc, char *argv[], gcli_pull_comments(owner, repo, pr); } else if (strcmp(action, "ci") == 0) { - gcli_pull_checks(owner, repo, pr); + if (gcli_pull_checks(owner, repo, pr) < 0) + errx(1, "error: failed to fetch pull request checks"); } else if (strcmp(action, "merge") == 0) { enum gcli_merge_flags flags = GCLI_PULL_MERGE_DELETEHEAD; diff --git a/src/pulls.c b/src/pulls.c index 4d1e7d6c..7f36b2a8 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -302,10 +302,10 @@ gcli_pull_print_op(gcli_pull *const pull) pretty_print(pull->body, 4, 80, stdout); } -void +int gcli_pull_checks(char const *owner, char const *repo, int const pr_number) { - gcli_forge()->print_pull_checks(owner, repo, pr_number); + return gcli_forge()->print_pull_checks(owner, repo, pr_number); } static void From 2dfac99852eaae1cb66454e0731169c26b12b71c Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 15:19:52 +0200 Subject: [PATCH 073/236] (#190) Add a filter function to gcli_fetch_list --- include/gcli/curl.h | 15 +++++++++--- src/curl.c | 11 +++++---- src/github/comments.c | 10 +++++--- src/github/gists.c | 10 +++++--- src/github/issues.c | 51 +++++++++++++++-------------------------- src/github/labels.c | 10 +++++--- src/github/milestones.c | 10 +++++--- src/gitlab/comments.c | 21 ++++++++++++----- src/gitlab/forks.c | 16 ++++++------- 9 files changed, 87 insertions(+), 67 deletions(-) diff --git a/include/gcli/curl.h b/include/gcli/curl.h index 3aef2735..dcc8e6bc 100644 --- a/include/gcli/curl.h +++ b/include/gcli/curl.h @@ -42,13 +42,24 @@ #include typedef void (*parsefn)(json_stream *stream, void *list, size_t *listsize); +typedef void (*filterfn)(void *list, size_t *listsize); typedef struct gcli_fetch_buffer gcli_fetch_buffer; +typedef struct gcli_fetch_list_ctx gcli_fetch_list_ctx; struct gcli_fetch_buffer { char *data; size_t length; }; +struct gcli_fetch_list_ctx { + void *listp; /* pointer to pointer of start of list */ + size_t *sizep; /* pointer to list size */ + int max; + + parsefn parse; /* json parse routine */ + filterfn filter; /* optional filter */ +}; + int gcli_fetch(char const *url, char **pagination_next, gcli_fetch_buffer *out); @@ -77,8 +88,6 @@ bool gcli_curl_test_success(char const *url); char *gcli_urlencode(char const *); sn_sv gcli_urlencode_sv(sn_sv const); char *gcli_urldecode(char const *input); -int gcli_fetch_list(char *url, parsefn fn, - void *list, size_t *listsize, - int max); +int gcli_fetch_list(char *url, gcli_fetch_list_ctx *ctx); #endif /* CURL_H */ diff --git a/src/curl.c b/src/curl.c index 18bc49ee..fa684d9c 100644 --- a/src/curl.c +++ b/src/curl.c @@ -585,9 +585,7 @@ gcli_urldecode(char const *input) * * If max is -1 then everything will be fetched. */ int -gcli_fetch_list(char *url, parsefn parse, - void *listptr, size_t *listsize, - int const max) +gcli_fetch_list(char *url, gcli_fetch_list_ctx *ctx) { char *next_url = NULL; int rc; @@ -600,7 +598,10 @@ gcli_fetch_list(char *url, parsefn parse, struct json_stream stream = {0}; json_open_buffer(&stream, buffer.data, buffer.length); - parse(&stream, listptr, listsize); + ctx->parse(&stream, ctx->listp, ctx->sizep); + if (ctx->filter) + ctx->filter(ctx->listp, ctx->sizep); + json_close(&stream); } @@ -610,7 +611,7 @@ gcli_fetch_list(char *url, parsefn parse, if (rc < 0) break; - } while ((url = next_url) && (max == -1 || (int)(*listsize) < max)); + } while ((url = next_url) && (ctx->max == -1 || (int)(*ctx->sizep) < ctx->max)); free(next_url); diff --git a/src/github/comments.c b/src/github/comments.c index 912a09a0..ff39461b 100644 --- a/src/github/comments.c +++ b/src/github/comments.c @@ -69,6 +69,12 @@ github_get_comments(char const *owner, char const *repo, char *e_owner = NULL; char *e_repo = NULL; char *url = NULL; + gcli_fetch_list_ctx ctx = { + .listp = &out->comments, + .sizep = &out->comments_size, + .parse = (parsefn)parse_github_comments, + .max = -1, + }; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -79,7 +85,5 @@ github_get_comments(char const *owner, char const *repo, free(e_owner); free(e_repo); - return gcli_fetch_list(url, (parsefn)parse_github_comments, - &out->comments, &out->comments_size, - -1); + return gcli_fetch_list(url, &ctx); } diff --git a/src/github/gists.c b/src/github/gists.c index 943dc2b0..a6acbeeb 100644 --- a/src/github/gists.c +++ b/src/github/gists.c @@ -66,6 +66,12 @@ int gcli_get_gists(char const *user, int const max, gcli_gist_list *const list) { char *url = NULL; + gcli_fetch_list_ctx ctx = { + .listp = &list->gists, + .sizep = &list->gists_size, + .parse = (parsefn)(parse_github_gists), + .max = max, + }; if (user) url = sn_asprintf( @@ -75,9 +81,7 @@ gcli_get_gists(char const *user, int const max, gcli_gist_list *const list) else url = sn_asprintf("%s/gists", github_get_apibase()); - return gcli_fetch_list(url, (parsefn)(parse_github_gists), - &list->gists, &list->gists_size, - max); + return gcli_fetch_list(url, &ctx); } static char const * diff --git a/src/github/issues.c b/src/github/issues.c index 3a6a054b..d09b1baa 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -46,50 +46,35 @@ * request issues. This function nukes them from the list, readjusts * the allocation size and fixes the reported list size. */ static void -github_hack_fixup_issues_that_are_actually_pulls(gcli_issue_list *const it) +github_hack_fixup_issues_that_are_actually_pulls(gcli_issue **list, size_t *size) { - for (size_t i = it->issues_size; i > 0; --i) { - if (it->issues[i-1].is_pr) { + for (size_t i = *size; i > 0; --i) { + if ((*list)[i-1].is_pr) { + gcli_issue *l = *list; /* len = 7, i = 5, to move = 7 - 5 = 2 * 0 1 2 3 4 5 6 * | x | x | x | x | X | x | x | */ - gcli_issue_free(&it->issues[i-1]); - memmove(&it->issues[i-1], &it->issues[i], - sizeof(*it->issues) * (it->issues_size - i)); - it->issues = realloc( - it->issues, - (--it->issues_size) * sizeof(*it->issues)); + gcli_issue_free(&l[i-1]); + memmove(&l[i-1], &l[i], + sizeof(*l) * (*size - i)); + *list = realloc(l, (--(*size)) * sizeof(*l)); } } } int -github_fetch_issues(char *url, - int const max, +github_fetch_issues(char *url, int const max, gcli_issue_list *const out) { - json_stream stream = {0}; - gcli_fetch_buffer json_buffer = {0}; - char *next_url = NULL; - - do { - gcli_fetch(url, &next_url, &json_buffer); - - json_open_buffer(&stream, json_buffer.data, json_buffer.length); - - parse_github_issues(&stream, &out->issues, &out->issues_size); - /* Hack: Remove PRs from the issue list because github. */ - github_hack_fixup_issues_that_are_actually_pulls(out); - - free(json_buffer.data); - free(url); - json_close(&stream); - - } while ((url = next_url) && (max == -1 || (int)out->issues_size < max)); - - free(url); - - return 0; + gcli_fetch_list_ctx ctx = { + .listp = &out->issues, + .sizep = &out->issues_size, + .parse = (parsefn)(parse_github_issues), + .filter = (filterfn)(github_hack_fixup_issues_that_are_actually_pulls), + .max = max, + }; + + return gcli_fetch_list(url, &ctx); } int diff --git a/src/github/labels.c b/src/github/labels.c index cfffa583..7b0e81ff 100644 --- a/src/github/labels.c +++ b/src/github/labels.c @@ -42,6 +42,12 @@ github_get_labels(char const *owner, gcli_label_list *const out) { char *url = NULL; + gcli_fetch_list_ctx ctx = { + .listp = &out->labels, + .sizep= &out->labels_size, + .parse = (parsefn)(parse_github_labels), + .max = max, + }; *out = (gcli_label_list) {0}; @@ -49,9 +55,7 @@ github_get_labels(char const *owner, "%s/repos/%s/%s/labels", gcli_get_apibase(), owner, reponame); - return gcli_fetch_list(url, (parsefn)(parse_github_labels), - &out->labels, &out->labels_size, - max); + return gcli_fetch_list(url, &ctx); } int diff --git a/src/github/milestones.c b/src/github/milestones.c index c30249ff..d874324e 100644 --- a/src/github/milestones.c +++ b/src/github/milestones.c @@ -49,6 +49,12 @@ github_get_milestones(char const *const owner, gcli_milestone_list *const out) { char *url, *e_owner, *e_repo; + gcli_fetch_list_ctx ctx = { + .listp = &out->milestones, + .sizep = &out->milestones_size, + .parse = (parsefn)parse_github_milestones, + .max = max, + }; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -60,9 +66,7 @@ github_get_milestones(char const *const owner, free(e_owner); free(e_repo); - return gcli_fetch_list(url, (parsefn)parse_github_milestones, - &out->milestones, &out->milestones_size, - max); + return gcli_fetch_list(url, &ctx); } int diff --git a/src/gitlab/comments.c b/src/gitlab/comments.c index f2170c06..3361b3e6 100644 --- a/src/gitlab/comments.c +++ b/src/gitlab/comments.c @@ -80,17 +80,22 @@ gitlab_get_mr_comments(char const *owner, { char *e_owner = gcli_urlencode(owner); char *e_repo = gcli_urlencode(repo); + gcli_fetch_list_ctx ctx = { + .listp = &out->comments, + .sizep = &out->comments_size, + .parse = (parsefn)parse_gitlab_comments, + .max = -1, + }; char *url = sn_asprintf( "%s/projects/%s%%2F%s/merge_requests/%d/notes", gitlab_get_apibase(), e_owner, e_repo, mr); + free(e_owner); free(e_repo); - return gcli_fetch_list(url, (parsefn)parse_gitlab_comments, - &out->comments, &out->comments_size, - -1); + return gcli_fetch_list(url, &ctx); } int @@ -99,6 +104,12 @@ gitlab_get_issue_comments(char const *owner, char const *repo, { char *e_owner = gcli_urlencode(owner); char *e_repo = gcli_urlencode(repo); + gcli_fetch_list_ctx ctx = { + .listp = &out->comments, + .sizep = &out->comments_size, + .parse = (parsefn)parse_gitlab_comments, + .max = -1, + }; char *url = sn_asprintf( "%s/projects/%s%%2F%s/issues/%d/notes", @@ -107,7 +118,5 @@ gitlab_get_issue_comments(char const *owner, char const *repo, free(e_owner); free(e_repo); - return gcli_fetch_list(url, (parsefn)parse_gitlab_comments, - &out->comments, &out->comments_size, - -1); + return gcli_fetch_list(url, &ctx); } diff --git a/src/gitlab/forks.c b/src/gitlab/forks.c index 879c8188..12a027ce 100644 --- a/src/gitlab/forks.c +++ b/src/gitlab/forks.c @@ -45,7 +45,13 @@ gitlab_get_forks(char const *owner, char *url = NULL; char *e_owner = NULL; char *e_repo = NULL; - int rc = 0; + + gcli_fetch_list_ctx ctx = { + .listp = &list->forks, + .sizep = &list->forks_size, + .parse = (parsefn)parse_gitlab_forks, + .max = max, + }; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -60,13 +66,7 @@ gitlab_get_forks(char const *owner, free(e_owner); free(e_repo); - rc = gcli_fetch_list(url, (parsefn)parse_gitlab_forks, - &list->forks, &list->forks_size, - max); - - /* TODO: don't leak the list on error */ - - return rc; + return gcli_fetch_list(url, &ctx); } int From 094aca9ba600b6d3c7206b7d84f0bfe51c67fddb Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 15:32:01 +0200 Subject: [PATCH 074/236] (#190) Add userdata to filter function in gcli_fetch_list This allows us to pass custom data to the filter function (such as the author name) --- include/gcli/curl.h | 3 ++- src/curl.c | 2 +- src/github/issues.c | 5 ++++- src/github/pulls.c | 54 +++++++++++++++++---------------------------- 4 files changed, 27 insertions(+), 37 deletions(-) diff --git a/include/gcli/curl.h b/include/gcli/curl.h index dcc8e6bc..6f97ff25 100644 --- a/include/gcli/curl.h +++ b/include/gcli/curl.h @@ -42,7 +42,7 @@ #include typedef void (*parsefn)(json_stream *stream, void *list, size_t *listsize); -typedef void (*filterfn)(void *list, size_t *listsize); +typedef void (*filterfn)(void *list, size_t *listsize, void const *userdata); typedef struct gcli_fetch_buffer gcli_fetch_buffer; typedef struct gcli_fetch_list_ctx gcli_fetch_list_ctx; @@ -58,6 +58,7 @@ struct gcli_fetch_list_ctx { parsefn parse; /* json parse routine */ filterfn filter; /* optional filter */ + void const *userdata; }; int gcli_fetch(char const *url, diff --git a/src/curl.c b/src/curl.c index fa684d9c..2850b46e 100644 --- a/src/curl.c +++ b/src/curl.c @@ -600,7 +600,7 @@ gcli_fetch_list(char *url, gcli_fetch_list_ctx *ctx) json_open_buffer(&stream, buffer.data, buffer.length); ctx->parse(&stream, ctx->listp, ctx->sizep); if (ctx->filter) - ctx->filter(ctx->listp, ctx->sizep); + ctx->filter(ctx->listp, ctx->sizep, ctx->userdata); json_close(&stream); } diff --git a/src/github/issues.c b/src/github/issues.c index d09b1baa..23999bb6 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -46,8 +46,11 @@ * request issues. This function nukes them from the list, readjusts * the allocation size and fixes the reported list size. */ static void -github_hack_fixup_issues_that_are_actually_pulls(gcli_issue **list, size_t *size) +github_hack_fixup_issues_that_are_actually_pulls(gcli_issue **list, size_t *size, + void *_data) { + (void) _data; + for (size_t i = *size; i > 0; --i) { if ((*list)[i-1].is_pr) { gcli_issue *l = *list; diff --git a/src/github/pulls.c b/src/github/pulls.c index aa3d3805..11968227 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -53,49 +53,35 @@ * the actual storage and instead just record the new size of the * allocation. */ static void -github_pulls_filter_author(char const *const author, gcli_pull_list *const list) +github_pulls_filter_author(gcli_pull **listp, size_t *sizep, char const *const author) { - for (size_t i = list->pulls_size; i > 0; --i) { - if (strcmp(author, list->pulls[i-1].author) == 0) + for (size_t i = *sizep; i > 0; --i) { + gcli_pull *pulls = *listp; + + if (strcmp(author, pulls[i-1].author) == 0) continue; - gcli_pull_free(&list->pulls[i - 1]); + gcli_pull_free(&pulls[i - 1]); - memmove(&list->pulls[i - 1], &list->pulls[i], - sizeof(*list->pulls) * (list->pulls_size - i)); - list->pulls = realloc( - list->pulls, - sizeof(*list->pulls) * (--list->pulls_size)); + memmove(&pulls[i - 1], &pulls[i], sizeof(*pulls) * (*sizep - i)); + *listp = realloc(pulls, sizeof(*pulls) * (--(*sizep))); } } int -github_fetch_pulls(char *url, - char const *const filter_author, - int max, - gcli_pull_list *const list) +github_fetch_pulls(char *url, char const *const filter_author, + int max, gcli_pull_list *const list) { - json_stream stream = {0}; - gcli_fetch_buffer json_buffer = {0}; - char *next_url = NULL; - - do { - gcli_fetch(url, &next_url, &json_buffer); - json_open_buffer(&stream, json_buffer.data, json_buffer.length); - parse_github_pulls(&stream, &list->pulls, &list->pulls_size); - - /* Filter out PRs manually - but only when requested */ - if (filter_author) - github_pulls_filter_author(filter_author, list); - - free(json_buffer.data); - free(url); - json_close(&stream); - } while ((url = next_url) && (max == -1 || (int)(list->pulls_size) < max)); - - free(url); - - return 0; + gcli_fetch_list_ctx ctx = { + .listp = &list->pulls, + .sizep = &list->pulls_size, + .parse = (parsefn)(parse_github_pulls), + .filter = (filterfn)(github_pulls_filter_author), + .userdata = filter_author, + .max = max, + }; + + return gcli_fetch_list(url, &ctx); } int From 7f941424c5d1fe01bf1e0461319edfc2cdddfdf3 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 15:35:54 +0200 Subject: [PATCH 075/236] (#190) Use the gcli_fetch_list in gitlab_get_repos --- src/gitlab/repos.c | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/src/gitlab/repos.c b/src/gitlab/repos.c index 2e92d177..f9edb4ff 100644 --- a/src/gitlab/repos.c +++ b/src/gitlab/repos.c @@ -97,35 +97,20 @@ gitlab_get_repos(char const *owner, gcli_repo_list *const list) { char *url = NULL; - char *next_url = NULL; char *e_owner = NULL; int rc = 0; + gcli_fetch_list_ctx ctx = { + .listp = &list->repos, + .sizep = &list->repos_size, + .parse = (parsefn)(parse_gitlab_repos), + .max = max, + }; e_owner = gcli_urlencode(owner); url = sn_asprintf("%s/users/%s/projects", gitlab_get_apibase(), e_owner); free(e_owner); - do { - gcli_fetch_buffer buffer = {0}; - - rc = gcli_fetch(url, &next_url, &buffer); - - if (rc == 0) { - json_stream stream = {0}; - - json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_repos(&stream, &list->repos, &list->repos_size); - json_close(&stream); - } - - free(url); - free(buffer.data); - - if (rc < 0) - break; - } while ((url = next_url) && (max == -1 || (int)list->repos_size < max)); - - free(url); + rc = gcli_fetch_list(url, &ctx); if (rc == 0) gitlab_repos_fixup_missing_visibility(list); From 20152f6cb310c4a050883afc0fee8aa8bdec70c9 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 15:39:56 +0200 Subject: [PATCH 076/236] (#190) Use gcli_fetch_list in gitlab_get_releases --- src/gitlab/releases.c | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/src/gitlab/releases.c b/src/gitlab/releases.c index 50bf728c..b9b14d12 100644 --- a/src/gitlab/releases.c +++ b/src/gitlab/releases.c @@ -59,19 +59,21 @@ fixup_release_asset_names(gcli_release_list *list) } int -gitlab_get_releases(char const *owner, - char const *repo, - int const max, - gcli_release_list *const list) +gitlab_get_releases(char const *owner, char const *repo, + int const max, gcli_release_list *const list) { char *url = NULL; - char *next_url = NULL; char *e_owner = NULL; char *e_repo = NULL; - gcli_fetch_buffer buffer = {0}; - json_stream stream = {0}; int rc = 0; + gcli_fetch_list_ctx ctx = { + .listp = &list->releases, + .sizep = &list->releases_size, + .max = max, + .parse = (parsefn)(parse_gitlab_releases), + }; + *list = (gcli_release_list) {0}; e_owner = gcli_urlencode(owner); @@ -82,27 +84,11 @@ gitlab_get_releases(char const *owner, gitlab_get_apibase(), e_owner, e_repo); - do { - rc = gcli_fetch(url, &next_url, &buffer); - - if (rc == 0) { - json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_releases(&stream, &list->releases, &list->releases_size); - json_close(&stream); - } - - free(url); - free(buffer.data); - - if (rc < 0) - break; - } while ((url = next_url) && (max == -1 || (int)list->releases_size < max)); - free(e_owner); free(e_repo); - free(next_url); - /* TODO: Don't leak the list in case of an error */ + rc = gcli_fetch_list(url, &ctx); + if (rc == 0) fixup_release_asset_names(list); From dd27de175bfaeef39a7ce0aad3c224733878d7b1 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 16:07:49 +0200 Subject: [PATCH 077/236] (#190) Make commit list a proper struct This allows us to use the fetch list routines and also allows for clean return types when fetching commit lists. --- include/gcli/forges.h | 2 +- include/gcli/gitea/pulls.h | 2 +- include/gcli/github/pulls.h | 6 +-- include/gcli/gitlab/merge_requests.h | 6 +-- include/gcli/pulls.h | 8 +++- src/gitea/pulls.c | 2 +- src/github/pulls.c | 36 +++++--------- src/gitlab/merge_requests.c | 72 ++++++++-------------------- src/pulls.c | 50 +++++++++---------- 9 files changed, 71 insertions(+), 113 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index b24c90b7..d62c5ea2 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -282,7 +282,7 @@ struct gcli_forge_descriptor { char const *owner, char const *repo, int pr_number, - gcli_commit **out); + gcli_commit_list *out); /** Bitmask of unsupported fields in the pull summary for this * forge */ diff --git a/include/gcli/gitea/pulls.h b/include/gcli/gitea/pulls.h index 54ab2138..da3630ba 100644 --- a/include/gcli/gitea/pulls.h +++ b/include/gcli/gitea/pulls.h @@ -51,7 +51,7 @@ int gitea_get_pull(char const *owner, int gitea_get_pull_commits(char const *owner, char const *repo, int pr_number, - gcli_commit **out); + gcli_commit_list *out); int gitea_pull_submit(gcli_submit_pull_options opts); diff --git a/include/gcli/github/pulls.h b/include/gcli/github/pulls.h index eb29a313..3c9d02b4 100644 --- a/include/gcli/github/pulls.h +++ b/include/gcli/github/pulls.h @@ -72,10 +72,8 @@ int github_pull_close(char const *owner, int github_perform_submit_pull(gcli_submit_pull_options opts); -int github_get_pull_commits(char const *owner, - char const *repo, - int pr_number, - gcli_commit **out); +int github_get_pull_commits(char const *owner, char const *repo, + int pr_number, gcli_commit_list *out); int github_get_pull(char const *owner, char const *repo, diff --git a/include/gcli/gitlab/merge_requests.h b/include/gcli/gitlab/merge_requests.h index 1de3a61f..bc093593 100644 --- a/include/gcli/gitlab/merge_requests.h +++ b/include/gcli/gitlab/merge_requests.h @@ -69,10 +69,8 @@ int gitlab_get_pull(char const *owner, int pr_number, gcli_pull *out); -int gitlab_get_pull_commits(char const *owner, - char const *repo, - int pr_number, - gcli_commit **out); +int gitlab_get_pull_commits(char const *owner, char const *repo, + int pr_number, gcli_commit_list *out); int gitlab_perform_submit_mr(gcli_submit_pull_options opts); diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index 4d36a272..a9cf9992 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -44,6 +44,7 @@ typedef struct gcli_pull gcli_pull; typedef struct gcli_pull_fetch_details gcli_pull_fetch_details; typedef struct gcli_submit_pull_options gcli_submit_pull_options; typedef struct gcli_commit gcli_commit; +typedef struct gcli_commit_list gcli_commit_list; typedef struct gcli_pull_list gcli_pull_list; struct gcli_pull_list { @@ -78,7 +79,12 @@ struct gcli_pull { }; struct gcli_commit { - char const *sha, *message, *date, *author, *email; + char *sha, *message, *date, *author, *email; +}; + +struct gcli_commit_list { + gcli_commit *commits; + size_t commits_size; }; /* Options to submit to the gh api for creating a PR */ diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index ba3721ed..02d30d9c 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -55,7 +55,7 @@ int gitea_get_pull_commits(char const *owner, char const *repo, int const pr_number, - gcli_commit **const out) + gcli_commit_list *const out) { return github_get_pull_commits(owner, repo, pr_number, out); } diff --git a/src/github/pulls.c b/src/github/pulls.c index 11968227..efc0acf7 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -314,18 +314,19 @@ github_perform_submit_pull(gcli_submit_pull_options opts) } int -github_get_pull_commits(char const *owner, - char const *repo, - int const pr_number, - gcli_commit **const out) +github_get_pull_commits(char const *owner, char const *repo, + int const pr_number, gcli_commit_list *const out) { - char *url = NULL; - char *next_url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - size_t count = 0; - json_stream stream = {0}; - gcli_fetch_buffer json_buffer = {0}; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + + gcli_fetch_list_ctx ctx = { + .listp = &out->commits, + .sizep = &out->commits_size, + .max = -1, + .parse = (parsefn)(parse_github_commits), + }; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -335,21 +336,10 @@ github_get_pull_commits(char const *owner, gcli_get_apibase(), e_owner, e_repo, pr_number); - do { - gcli_fetch(url, &next_url, &json_buffer); - json_open_buffer(&stream, json_buffer.data, json_buffer.length); - - parse_github_commits(&stream, out, &count); - - json_close(&stream); - free(json_buffer.data); - free(url); - } while ((url = next_url)); - free(e_owner); free(e_repo); - return (int)count; + return gcli_fetch_list(url, &ctx); } int diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index 7cf15d42..4f7320ca 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -50,30 +50,16 @@ gitlab_mrs_fixup(gcli_pull_list *const list) int gitlab_fetch_mrs(char *url, int const max, gcli_pull_list *const list) { - char *next_url = NULL; int rc = 0; - do { - gcli_fetch_buffer json_buffer = {0}; + gcli_fetch_list_ctx ctx = { + .listp = &list->pulls, + .sizep = &list->pulls_size, + .max = max, + .parse = (parsefn)(parse_gitlab_mrs), + }; - rc = gcli_fetch(url, &next_url, &json_buffer); - - if (rc == 0) { - json_stream stream = {0}; - - json_open_buffer(&stream, json_buffer.data, json_buffer.length); - parse_gitlab_mrs(&stream, &list->pulls, &list->pulls_size); - json_close(&stream); - } - - free(url); - free(json_buffer.data); - - if (rc < 0) - break; - } while ((url = next_url) && (max == -1 || (int)list->pulls_size < max)); - - free(url); + rc = gcli_fetch_list(url, &ctx); /* TODO: don't leak the list on error */ if (rc == 0) @@ -185,10 +171,8 @@ gitlab_mr_merge(char const *owner, } int -gitlab_get_pull(char const *owner, - char const *repo, - int const pr_number, - gcli_pull *const out) +gitlab_get_pull(char const *owner, char const *repo, + int const pr_number, gcli_pull *const out) { gcli_fetch_buffer json_buffer = {0}; char *url = NULL; @@ -222,17 +206,19 @@ gitlab_get_pull(char const *owner, } int -gitlab_get_pull_commits(char const *owner, - char const *repo, - int const pr_number, - gcli_commit **const out) +gitlab_get_pull_commits(char const *owner, char const *repo, + int const pr_number, gcli_commit_list *const out) { char *url = NULL; - char *next_url = NULL; char *e_owner = NULL; char *e_repo = NULL; - size_t count = 0; - int rc = 0; + + gcli_fetch_list_ctx ctx = { + .listp = &out->commits, + .sizep = &out->commits_size, + .max = -1, + .parse = (parsefn)(parse_gitlab_commits), + }; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -246,27 +232,7 @@ gitlab_get_pull_commits(char const *owner, free(e_owner); free(e_repo); - do { - gcli_fetch_buffer json_buffer = {0}; - - rc = gcli_fetch(url, &next_url, &json_buffer); - if (rc == 0) { - json_stream stream = {0}; - - json_open_buffer(&stream, json_buffer.data, json_buffer.length); - parse_gitlab_commits(&stream, out, &count); - json_close(&stream); - } - - free(url); - free(json_buffer.data); - - /* TODO: don't leak the list on error */ - if (rc < 0) - return rc; - } while ((url = next_url)); - - return (int)(count); + return gcli_fetch_list(url, &ctx); } int diff --git a/src/pulls.c b/src/pulls.c index 7f36b2a8..d4434928 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -183,7 +183,7 @@ static int gcli_get_pull_commits(char const *owner, char const *repo, int const pr_number, - gcli_commit **const out) + gcli_commit_list *const out) { return gcli_forge()->get_pull_commits(owner, repo, pr_number, out); } @@ -208,8 +208,7 @@ cut_newline(char const *const _it) } static void -gcli_print_commits_table(gcli_commit const *const commits, - int const commits_size) +gcli_print_commits_table(gcli_commit_list const *const list) { gcli_tbl table; gcli_tblcoldef cols[] = { @@ -220,7 +219,7 @@ gcli_print_commits_table(gcli_commit const *const commits, { .name = "MESSAGE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, }; - if (commits_size == 0) { + if (list->commits_size == 0) { puts("No commits"); return; } @@ -229,10 +228,12 @@ gcli_print_commits_table(gcli_commit const *const commits, if (!table) errx(1, "error: could not initialize table"); - for (int i = 0; i < commits_size; ++i) { - char *message = cut_newline(commits[i].message); - gcli_tbl_add_row(table, GCLI_COLOR_YELLOW, commits[i].sha, - commits[i].author, commits[i].email, commits[i].date, + for (size_t i = 0; i < list->commits_size; ++i) { + char *message = cut_newline(list->commits[i].message); + gcli_tbl_add_row(table, GCLI_COLOR_YELLOW, list->commits[i].sha, + list->commits[i].author, + list->commits[i].email, + list->commits[i].date, message); free(message); /* message is copied by the function above */ } @@ -241,33 +242,32 @@ gcli_print_commits_table(gcli_commit const *const commits, } static void -gcli_commits_free(gcli_commit *it, int const size) +gcli_commits_free(gcli_commit_list *list) { - for (int i = 0; i < size; ++i) { - free((void *)it[i].sha); - free((void *)it[i].message); - free((void *)it[i].date); - free((void *)it[i].author); - free((void *)it[i].email); + for (size_t i = 0; i < list->commits_size; ++i) { + free(list->commits[i].sha); + free(list->commits[i].message); + free(list->commits[i].date); + free(list->commits[i].author); + free(list->commits[i].email); } - free(it); + free(list->commits); + + list->commits = NULL; + list->commits_size = 0; } void -gcli_pull_commits(char const *owner, - char const *repo, - int const pr_number) +gcli_pull_commits(char const *owner, char const *repo, int const pr_number) { - gcli_commit *commits = NULL; - int commits_size = 0; + gcli_commit_list commits = {0}; - commits_size = gcli_get_pull_commits(owner, repo, pr_number, &commits); - if (commits_size < 0) + if (gcli_get_pull_commits(owner, repo, pr_number, &commits) < 0) errx(1, "error: failed to fetch commits of the pull request"); - gcli_print_commits_table(commits, commits_size); - gcli_commits_free(commits, commits_size); + gcli_print_commits_table(&commits); + gcli_commits_free(&commits); } void From ff5ea16776a6f2eb7c34e0e37a1f7429b2e8b97e Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 16:13:40 +0200 Subject: [PATCH 078/236] (#190) Make gitlab_get_milestones use new fetch_list routine --- src/gitlab/milestones.c | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/src/gitlab/milestones.c b/src/gitlab/milestones.c index 233dc914..ad72d457 100644 --- a/src/gitlab/milestones.c +++ b/src/gitlab/milestones.c @@ -42,16 +42,18 @@ #include int -gitlab_get_milestones(char const *owner, - char const *repo, - int max, - gcli_milestone_list *const out) +gitlab_get_milestones(char const *owner, char const *repo, + int max, gcli_milestone_list *const out) { - char *url, *next_url = NULL; + char *url; char *e_owner, *e_repo; - gcli_fetch_buffer buffer = {0}; - json_stream stream = {0}; - int rc = 0; + + gcli_fetch_list_ctx ctx = { + .listp = &out->milestones, + .sizep = &out->milestones_size, + .max = max, + .parse = (parsefn)(parse_gitlab_milestones), + }; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -59,29 +61,10 @@ gitlab_get_milestones(char const *owner, url = sn_asprintf("%s/projects/%s%%2F%s/milestones", gitlab_get_apibase(), e_owner, e_repo); - do { - rc = gcli_fetch(url, &next_url, &buffer); - - if (rc == 0) { - json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_milestones(&stream, &out->milestones, &out->milestones_size); - json_close(&stream); - } - - free(buffer.data); - free(url); - - if (rc < 0) - break; - } while ((url = next_url) && (max == -1 || (int)out->milestones_size < max)); - - free(next_url); free(e_owner); free(e_repo); - /* TODO: don't leak the list on error */ - - return rc; + return gcli_fetch_list(url, &ctx); } int From 9cd67525f1994b2e6e6b08911fb380e736b8d03e Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 16:32:58 +0200 Subject: [PATCH 079/236] (#190) Add a gcli_pr_review_list type --- include/gcli/forges.h | 6 ++--- include/gcli/github/review.h | 6 ++--- include/gcli/gitlab/review.h | 6 ++--- include/gcli/review.h | 17 +++++++----- src/cmd/pulls.c | 12 ++++----- src/github/review.c | 23 ++++++++-------- src/gitlab/review.c | 38 +++++++------------------- src/review.c | 52 +++++++++++++++++------------------- 8 files changed, 67 insertions(+), 93 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index d62c5ea2..48e84c06 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -407,10 +407,8 @@ struct gcli_forge_descriptor { /** * Fetch MR/PR reviews including comments */ int (*get_reviews)( - char const *owner, - char const *repo, - int pr, - gcli_pr_review **out); + char const *owner, char const *repo, + int pr, gcli_pr_review_list *out); /** * Status summary for the account */ diff --git a/include/gcli/github/review.h b/include/gcli/github/review.h index 8941a8ef..92399b62 100644 --- a/include/gcli/github/review.h +++ b/include/gcli/github/review.h @@ -36,9 +36,7 @@ #include -int github_review_get_reviews(char const *owner, - char const *repo, - int pr, - gcli_pr_review **out); +int github_review_get_reviews(char const *owner, char const *repo, + int pr, gcli_pr_review_list *out); #endif /* GITHUB_REVIEW_H */ diff --git a/include/gcli/gitlab/review.h b/include/gcli/gitlab/review.h index ae9eb12e..75c5f840 100644 --- a/include/gcli/gitlab/review.h +++ b/include/gcli/gitlab/review.h @@ -36,9 +36,7 @@ #include -int gitlab_review_get_reviews(char const *owner, - char const *repo, - int pr, - gcli_pr_review **out); +int gitlab_review_get_reviews(char const *owner, char const *repo, + int pr, gcli_pr_review_list *out); #endif /* GITLAB_REVIEW_H */ diff --git a/include/gcli/review.h b/include/gcli/review.h index 39a6af56..2c0e9bca 100644 --- a/include/gcli/review.h +++ b/include/gcli/review.h @@ -37,6 +37,7 @@ #include typedef struct gcli_pr_review gcli_pr_review; +typedef struct gcli_pr_review_list gcli_pr_review_list; typedef struct gcli_pr_review_comment gcli_pr_review_comment; struct gcli_pr_review_comment { @@ -59,17 +60,19 @@ struct gcli_pr_review { size_t comments_size; }; -void gcli_review_reviews_free(gcli_pr_review *it, size_t size); +struct gcli_pr_review_list { + gcli_pr_review *reviews; + size_t reviews_size; +}; + +void gcli_review_reviews_free(gcli_pr_review_list *list); void gcli_review_comments_free(gcli_pr_review_comment *it, size_t size); -int gcli_review_get_reviews(char const *owner, - char const *repo, - int pr, - gcli_pr_review **out); +int gcli_review_get_reviews(char const *owner, char const *repo, + int pr, gcli_pr_review_list *out); -void gcli_review_print_review_table(gcli_pr_review const *headers, - size_t headers_size); +void gcli_review_print_review_table(gcli_pr_review_list const *reviews); void gcli_review_print_comments(gcli_pr_review_comment const *comments, size_t comments_size); diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index c5d23741..ce34e051 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -465,15 +465,13 @@ handle_pull_actions(int argc, char *argv[], } else if (strcmp(action, "reviews") == 0) { /* list reviews */ - gcli_pr_review *reviews = NULL; - int reviews_size = gcli_review_get_reviews( - owner, repo, pr, &reviews); + gcli_pr_review_list reviews = {0}; - if (reviews_size < 0) - errx(1, "error: failed to fetch reviews"); + if (gcli_review_get_reviews(owner, repo, pr, &reviews) < 0) + errx(1, "error: failed to fetch reviews"); - gcli_review_print_review_table(reviews, reviews_size); - gcli_review_reviews_free(reviews, reviews_size); + gcli_review_print_review_table(&reviews); + gcli_review_reviews_free(&reviews); } else if (strcmp("labels", action) == 0) { const char **add_labels = NULL; diff --git a/src/github/review.c b/src/github/review.c index 5b05957a..cb7740d5 100644 --- a/src/github/review.c +++ b/src/github/review.c @@ -140,10 +140,8 @@ static char const *get_reviews_fmt = "}"; int -github_review_get_reviews(char const *owner, - char const *repo, - int const pr, - gcli_pr_review **const out) +github_review_get_reviews(char const *owner, char const *repo, + int const pr, gcli_pr_review_list *const out) { gcli_fetch_buffer buffer = {0}; char *url = NULL; @@ -152,7 +150,7 @@ github_review_get_reviews(char const *owner, char *post_data = NULL; struct json_stream stream = {0}; enum json_type next = JSON_NULL; - int size = 0; + int rc = 0; url = sn_asprintf("%s/graphql", gcli_get_apibase()); query = sn_asprintf(get_reviews_fmt, owner, repo, pr); @@ -160,14 +158,14 @@ github_review_get_reviews(char const *owner, post_data = sn_asprintf("{\"query\": \""SV_FMT"\"}", SV_ARGS(query_escaped)); - size = gcli_fetch_with_method("POST", url, post_data, NULL, &buffer); + rc = gcli_fetch_with_method("POST", url, post_data, NULL, &buffer); free(url); free(query); free(query_escaped.data); free(post_data); - if (size < 0) - return size; + if (rc < 0) + return rc; json_open_buffer(&stream, buffer.data, buffer.length); json_set_streaming(&stream, true); @@ -181,14 +179,15 @@ github_review_get_reviews(char const *owner, errx(1, "error: expected json array for review list"); while ((next = json_peek(&stream)) == JSON_OBJECT) { - *out = realloc(*out, sizeof(gcli_pr_review) * (size + 1)); - gcli_pr_review *it = &(*out)[size]; + out->reviews = realloc(out->reviews, + sizeof(gcli_pr_review) * (out->reviews_size + 1)); + gcli_pr_review *it = &out->reviews[out->reviews_size]; *it = (gcli_pr_review) {0}; github_parse_review_header(&stream, it); - size++; + out->reviews_size++; } if (json_next(&stream) != JSON_ARRAY_END) @@ -199,5 +198,5 @@ github_review_get_reviews(char const *owner, json_close(&stream); free(buffer.data); - return size; + return 0; } diff --git a/src/gitlab/review.c b/src/gitlab/review.c index bd3644ab..49eb4feb 100644 --- a/src/gitlab/review.c +++ b/src/gitlab/review.c @@ -40,39 +40,21 @@ #include int -gitlab_review_get_reviews(char const *owner, - char const *repo, - int const pr, - gcli_pr_review **const out) +gitlab_review_get_reviews(char const *owner, char const *repo, + int const pr, gcli_pr_review_list *const out) { - gcli_fetch_buffer buffer = {0}; - json_stream stream = {0}; char *url = NULL; - char *next_url = NULL; - size_t size = 0; - int rc = 0; + + gcli_fetch_list_ctx ctx = { + .listp = &out->reviews, + .sizep = &out->reviews_size, + .max = -1, + .parse = (parsefn)(parse_gitlab_reviews), + }; url = sn_asprintf( "%s/projects/%s%%2F%s/merge_requests/%d/notes?sort=asc", gitlab_get_apibase(), owner, repo, pr); - do { - rc = gcli_fetch(url, &next_url, &buffer); - - if (rc == 0) { - json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_reviews(&stream, out, &size); - json_close(&stream); - } - - free(url); - free(buffer.data); - } while ((rc == 0) && (url = next_url)); - - free(next_url); - - if (rc < 0) - return rc; - - return (int)(size); + return gcli_fetch_list(url, &ctx); } diff --git a/src/review.c b/src/review.c index 9cf2551b..7cbdc874 100644 --- a/src/review.c +++ b/src/review.c @@ -40,28 +40,27 @@ #include void -gcli_review_print_review_table(gcli_pr_review const *const headers, - size_t const headers_size) +gcli_review_print_review_table(gcli_pr_review_list const *const list) { - for (size_t i = 0; i < headers_size; ++i) { - if (headers[i].state) { + for (size_t i = 0; i < list->reviews_size; ++i) { + if (list->reviews[i].state) { printf(" %s%s%s - %s - %s%s%s\n", - gcli_setbold(), headers[i].author, gcli_resetbold(), - headers[i].date, - gcli_state_colour_str(headers[i].state), - headers[i].state, + gcli_setbold(), list->reviews[i].author, gcli_resetbold(), + list->reviews[i].date, + gcli_state_colour_str(list->reviews[i].state), + list->reviews[i].state, gcli_resetcolour()); } else { printf(" %s%s%s - %s\n", - gcli_setbold(), headers[i].author, gcli_resetbold(), - headers[i].date); + gcli_setbold(), list->reviews[i].author, gcli_resetbold(), + list->reviews[i].date); } - pretty_print(headers[i].body, 9, 80, stdout); + pretty_print(list->reviews[i].body, 9, 80, stdout); gcli_review_print_comments( - headers[i].comments, - headers[i].comments_size); + list->reviews[i].comments, + list->reviews[i].comments_size); putchar('\n'); } @@ -84,22 +83,23 @@ gcli_review_print_comments(gcli_pr_review_comment const *const comments, } void -gcli_review_reviews_free(gcli_pr_review *it, size_t const size) +gcli_review_reviews_free(gcli_pr_review_list *list) { - if (!it) + if (!list) return; - for (size_t i = 0; i < size; ++i) { - free(it[i].author); - free(it[i].date); - free(it[i].state); - free(it[i].body); - free(it[i].id); + for (size_t i = 0; i < list->reviews_size; ++i) { + free(list->reviews[i].author); + free(list->reviews[i].date); + free(list->reviews[i].state); + free(list->reviews[i].body); + free(list->reviews[i].id); } - gcli_review_comments_free(it->comments, it->comments_size); + free(list->reviews); - free(it); + list->reviews = NULL; + list->reviews_size = 0; } void @@ -121,10 +121,8 @@ gcli_review_comments_free(gcli_pr_review_comment *it, size_t const size) } int -gcli_review_get_reviews(char const *owner, - char const *repo, - int const pr, - gcli_pr_review **const out) +gcli_review_get_reviews(char const *owner, char const *repo, + int const pr, gcli_pr_review_list *const out) { return gcli_forge()->get_reviews(owner, repo, pr, out); } From 1896700b4d6b4298672eb0a895cd776f12e48f25 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 16:35:34 +0200 Subject: [PATCH 080/236] (#190) Make gitlab_fetch_issues use new fetch_list routine --- src/gitlab/issues.c | 42 +++++++++--------------------------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index 8930baf3..2f9cc70f 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -39,41 +39,17 @@ /** Given the url fetch issues */ int -gitlab_fetch_issues(char *url, - int const max, +gitlab_fetch_issues(char *url, int const max, gcli_issue_list *const out) { - json_stream stream = {0}; - gcli_fetch_buffer json_buffer = {0}; - char *next_url = NULL; - int rc = 0; - - do { - rc = gcli_fetch(url, &next_url, &json_buffer); - - if (rc == 0) { - json_open_buffer(&stream, json_buffer.data, json_buffer.length); - parse_gitlab_issues(&stream, &out->issues, &out->issues_size); - json_close(&stream); - } - - free(json_buffer.data); - json_buffer.data = NULL; - json_buffer.length = 0; - - free(url); - - if (rc < 0) - break; - - } while ((url = next_url) && (max == -1 || (int)out->issues_size < max)); - /* continue iterating if we have both a next_url and we are - * supposed to fetch more issues (either max is -1 thus all issues - * or we haven't fetched enough yet). */ - - free(next_url); - - return rc; + gcli_fetch_list_ctx ctx = { + .listp = &out->issues, + .sizep = &out->issues_size, + .max = max, + .parse = (parsefn)(parse_gitlab_issues), + }; + + return gcli_fetch_list(url, &ctx); } int From 16bf24a3542343eba9a096635d8af97c4267b144 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 16:38:45 +0200 Subject: [PATCH 081/236] (#190) Make gcli_snippets_get use fetch_list routine --- src/gitlab/snippets.c | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/src/gitlab/snippets.c b/src/gitlab/snippets.c index fa1d77d3..6ca91259 100644 --- a/src/gitlab/snippets.c +++ b/src/gitlab/snippets.c @@ -62,39 +62,18 @@ int gcli_snippets_get(int const max, gcli_snippet_list *const out) { char *url = NULL; - char *next_url = NULL; - int rc = 0; - *out = (gcli_snippet_list) {0}; + gcli_fetch_list_ctx ctx = { + .listp = &out->snippets, + .sizep = &out->snippets_size, + .max = max, + .parse = (parsefn)(parse_gitlab_snippets), + }; + *out = (gcli_snippet_list) {0}; url = sn_asprintf("%s/snippets", gitlab_get_apibase()); - do { - gcli_fetch_buffer buffer = {0}; - - rc = gcli_fetch(url, &next_url, &buffer); - - if (rc == 0) { - struct json_stream stream = {0}; - - json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_snippets(&stream, &out->snippets, &out->snippets_size); - json_close(&stream); - } - - free(url); - free(buffer.data); - - if (rc < 0) - break; - - } while ((url = next_url) && (max == -1 || (int)out->snippets_size < max)); - - /* TODO: don't leak list in case of an error */ - - free(next_url); - - return rc; + return gcli_fetch_list(url, &ctx);; } static void From 8bc313283cf5d631f3fb5e4a4db99617784aa5c4 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 16:41:29 +0200 Subject: [PATCH 082/236] (#190) Make gitlab fetch_pipelines use new fetch_list routines --- src/gitlab/pipelines.c | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index efa6ad63..23841fce 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -42,31 +42,14 @@ static int fetch_pipelines(char *url, int const max, gitlab_pipeline_list *const list) { - char *next_url = NULL; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; - int rc = 0; - - *list = (gitlab_pipeline_list) {0}; - - do { - rc = gcli_fetch(url, &next_url, &buffer); - - if (rc == 0) { - json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_pipelines(&stream, &list->pipelines, &list->pipelines_size); - json_close(&stream); - } - - free(buffer.data); - free(url); - - if (rc < 0) - break; - } while ((url = next_url) && (max == -1 || (int)list->pipelines_size < max)); + gcli_fetch_list_ctx ctx = { + .listp = &list->pipelines, + .sizep = &list->pipelines_size, + .max = max, + .parse = (parsefn)(parse_gitlab_pipelines), + }; - /* TODO: don't leak the list on error */ - return rc; + return gcli_fetch_list(url, &ctx); } int From e42395777f963532c679d70bdcd2269e24156ba2 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 16:41:50 +0200 Subject: [PATCH 083/236] (#190) Check result of fetching list of pipelines --- src/gitlab/pipelines.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index 23841fce..c878839d 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -134,7 +134,9 @@ gitlab_pipelines(char const *owner, char const *repo, int const count) { gitlab_pipeline_list pipelines = {0}; - gitlab_get_pipelines(owner, repo, count, &pipelines); + if (gitlab_get_pipelines(owner, repo, count, &pipelines) < 0) + errx(1,"error: could not fetch list of pipelines"); + gitlab_print_pipelines(&pipelines); gitlab_free_pipelines(&pipelines); } From 263dae137ccb27389a47e6c6b82bfd31ea7d7155 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 16:48:02 +0200 Subject: [PATCH 084/236] (#190) Make gitlab pipelines use fetch_list for job lists --- include/gcli/gitlab/pipelines.h | 22 ++++---- src/gitlab/pipelines.c | 93 ++++++++++++++------------------- 2 files changed, 51 insertions(+), 64 deletions(-) diff --git a/include/gcli/gitlab/pipelines.h b/include/gcli/gitlab/pipelines.h index 680f2dfb..fa2bf0ab 100644 --- a/include/gcli/gitlab/pipelines.h +++ b/include/gcli/gitlab/pipelines.h @@ -37,6 +37,7 @@ typedef struct gitlab_pipeline gitlab_pipeline; typedef struct gitlab_pipeline_list gitlab_pipeline_list; typedef struct gitlab_job gitlab_job; +typedef struct gitlab_job_list gitlab_job_list; struct gitlab_pipeline { long id; @@ -67,6 +68,11 @@ struct gitlab_job { char *runner_description; }; +struct gitlab_job_list { + gitlab_job *jobs; + size_t jobs_size; +}; + int gitlab_get_pipelines(char const *owner, char const *repo, int max, @@ -85,17 +91,15 @@ void gitlab_pipeline_jobs(char const *owner, long pipeline, int count); -int gitlab_get_pipeline_jobs(char const *owner, - char const *repo, - long pipeline, - int count, - gitlab_job **jobs); +int gitlab_get_pipeline_jobs(char const *owner, char const *repo, + long pipeline, int count, + gitlab_job_list *out); + +void gitlab_print_jobs(gitlab_job_list const *jobs); -void gitlab_print_jobs(gitlab_job const *jobs, - int jobs_size); +void gitlab_free_jobs(gitlab_job_list *jobs); +void gitlab_free_job(gitlab_job *job); -void gitlab_free_jobs(gitlab_job *jobs, - int jobs_size); int gitlab_job_get_log(char const *owner, char const *repo, diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index c878839d..8f74fb5b 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -147,58 +147,38 @@ gitlab_pipeline_jobs(char const *owner, long const id, int const count) { - gitlab_job *jobs = NULL; - int const jobs_size = gitlab_get_pipeline_jobs(owner, repo, id, count, &jobs); - if (jobs_size < 0) + gitlab_job_list jobs = {0}; + int rc; + + rc = gitlab_get_pipeline_jobs(owner, repo, id, count, &jobs); + if (rc < 0) errx(1, "error: failed to get jobs"); - gitlab_print_jobs(jobs, jobs_size); - gitlab_free_jobs(jobs, jobs_size); + gitlab_print_jobs(&jobs); + gitlab_free_jobs(&jobs); } int -gitlab_get_pipeline_jobs(char const *owner, - char const *repo, - long const pipeline, - int const max, - gitlab_job **const out) +gitlab_get_pipeline_jobs(char const *owner, char const *repo, + long const pipeline, int const max, + gitlab_job_list *const out) { char *url = NULL; - char *next_url = NULL; - size_t out_size = 0; - int rc; + gcli_fetch_list_ctx ctx = { + .listp = &out->jobs, + .sizep = &out->jobs_size, + .max = max, + .parse = (parsefn)(parse_gitlab_jobs), + }; url = sn_asprintf("%s/projects/%s%%2F%s/pipelines/%ld/jobs", gitlab_get_apibase(), owner, repo, pipeline); - do { - gcli_fetch_buffer buffer = {0}; - - rc = gcli_fetch(url, &next_url, &buffer); - if (rc == 0) { - json_stream stream = {0}; - - json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_jobs(&stream, out, &out_size); - json_close(&stream); - } - - free(url); - - if (rc < 0) - break; - } while ((url = next_url) && (((int)out_size < max) || (max == -1))); - - free(next_url); - - if (rc < 0) - return rc; - - return (int)out_size; + return gcli_fetch_list(url, &ctx); } void -gitlab_print_jobs(gitlab_job const *const jobs, int const jobs_size) +gitlab_print_jobs(gitlab_job_list const *const list) { gcli_tbl table; gcli_tblcoldef cols[] = { @@ -211,7 +191,7 @@ gitlab_print_jobs(gitlab_job const *const jobs, int const jobs_size) { .name = "REF", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, }; - if (!jobs_size) { + if (!list->jobs_size) { printf("No jobs\n"); return; } @@ -220,22 +200,22 @@ gitlab_print_jobs(gitlab_job const *const jobs, int const jobs_size) if (!table) errx(1, "error: could not initialize table"); - for (int i = 0; i < jobs_size; ++i) { + for (size_t i = 0; i < list->jobs_size; ++i) { gcli_tbl_add_row(table, - jobs[i].id, - jobs[i].name, - jobs[i].status, - jobs[i].started_at, - jobs[i].finished_at, - jobs[i].runner_description, - jobs[i].ref); + list->jobs[i].id, + list->jobs[i].name, + list->jobs[i].status, + list->jobs[i].started_at, + list->jobs[i].finished_at, + list->jobs[i].runner_description, + list->jobs[i].ref); } gcli_tbl_end(table); } -static void -gitlab_free_job_data(gitlab_job *const job) +void +gitlab_free_job(gitlab_job *const job) { free(job->status); free(job->stage); @@ -249,12 +229,15 @@ gitlab_free_job_data(gitlab_job *const job) } void -gitlab_free_jobs(gitlab_job *jobs, int const jobs_size) +gitlab_free_jobs(gitlab_job_list *list) { - for (int i = 0; i < jobs_size; ++i) { - gitlab_free_job_data(&jobs[i]); - } - free(jobs); + for (size_t i = 0; i < list->jobs_size; ++i) + gitlab_free_job(&list->jobs[i]); + + free(list->jobs); + + list->jobs = NULL; + list->jobs_size = 0; } int @@ -339,7 +322,7 @@ gitlab_job_status(char const *owner, char const *repo, long const jid) if (rc == 0) gitlab_print_job_status(&job); - gitlab_free_job_data(&job); + gitlab_free_job(&job); return rc; } From b61193c101a1e88f30425cb52bf2618c19e315ca Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 16:50:32 +0200 Subject: [PATCH 085/236] (#190) Make gitlab_get_labels use new fetch_list routines --- src/gitlab/labels.c | 37 ++++++++++--------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/src/gitlab/labels.c b/src/gitlab/labels.c index 3d1e2f68..2175684e 100644 --- a/src/gitlab/labels.c +++ b/src/gitlab/labels.c @@ -36,40 +36,23 @@ #include int -gitlab_get_labels(char const *owner, - char const *repo, - int const max, - gcli_label_list *const out) +gitlab_get_labels(char const *owner, char const *repo, + int const max, gcli_label_list *const out) { - char *url = NULL; - char *next_url = NULL; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; - int rc; + char *url = NULL; + gcli_fetch_list_ctx ctx = { + .listp = &out->labels, + .sizep = &out->labels_size, + .max = max, + .parse = (parsefn)(parse_gitlab_labels), + }; *out = (gcli_label_list) {0}; url = sn_asprintf("%s/projects/%s%%2F%s/labels", gitlab_get_apibase(), owner, repo); - do { - rc = gcli_fetch(url, &next_url, &buffer); - - if (rc == 0) { - json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_labels(&stream, &out->labels, &out->labels_size); - } - - free(buffer.data); - free(url); - json_close(&stream); - - if (rc < 0) - break; - - } while ((url = next_url) && (max == -1 || (int)out->labels_size < max)); - - return rc; + return gcli_fetch_list(url, &ctx); } int From 3e6eb396e49271478026669d1871c7e28ef000f9 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 16:53:37 +0200 Subject: [PATCH 086/236] (#190) Make gitlab_get_sshkeys use new fetch_list routines --- src/gitlab/sshkeys.c | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/src/gitlab/sshkeys.c b/src/gitlab/sshkeys.c index 6d79ee39..441af1b7 100644 --- a/src/gitlab/sshkeys.c +++ b/src/gitlab/sshkeys.c @@ -44,33 +44,18 @@ int gitlab_get_sshkeys(gcli_sshkey_list *list) { - char *url, *next_url = NULL; - int rc = 0; + char *url; + gcli_fetch_list_ctx ctx = { + .listp = &list->keys, + .sizep = &list->keys_size, + .max = -1, + .parse = (parsefn)(parse_gitlab_sshkeys), + }; *list = (gcli_sshkey_list) {0}; url = sn_asprintf("%s/user/keys", gcli_get_apibase()); - do { - gcli_fetch_buffer buf = {0}; - - rc = gcli_fetch(url, &next_url, &buf); - - if (rc == 0) { - json_stream str; - - json_open_buffer(&str, buf.data, buf.length); - parse_gitlab_sshkeys(&str, &list->keys, &list->keys_size); - json_close(&str); - } - - free(buf.data); - free(url); - - } while ((rc == 0) && (url = next_url)); - - /* TODO: don't leak the list on error */ - - return rc; + return gcli_fetch_list(url, &ctx); } int From 086f601789dee5269745f0a7229822a39cb0812d Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:00:56 +0200 Subject: [PATCH 087/236] (#190) Make github_get_releases use new fetch_list routines --- src/github/releases.c | 37 ++++++++++--------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/src/github/releases.c b/src/github/releases.c index b67109b1..48e8a282 100644 --- a/src/github/releases.c +++ b/src/github/releases.c @@ -39,18 +39,19 @@ #include int -github_get_releases(char const *owner, - char const *repo, - int const max, - gcli_release_list *const list) +github_get_releases(char const *owner, char const *repo, + int const max, gcli_release_list *const list) { char *url = NULL; char *e_owner = NULL; char *e_repo = NULL; - char *next_url = NULL; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; - int rc = 0; + + gcli_fetch_list_ctx ctx = { + .listp = &list->releases, + .sizep = &list->releases_size, + .max = max, + .parse = (parsefn)(parse_github_releases), + }; *list = (gcli_release_list) {0}; @@ -62,28 +63,10 @@ github_get_releases(char const *owner, gcli_get_apibase(), e_owner, e_repo); - do { - rc = gcli_fetch(url, &next_url, &buffer); - if (rc == 0) { - json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_releases(&stream, &list->releases, &list->releases_size); - json_close(&stream); - } - - free(url); - free(buffer.data); - - if (rc < 0) - break; - } while ((url = next_url) && (max == -1 || (int)list->releases_size < max)); - - free(next_url); free(e_owner); free(e_repo); - /* TODO: Don't leak the list in case of an error */ - - return rc; + return gcli_fetch_list(url, &ctx); } static void From 1b6735da32fbb026b2121a581704948808d0b198 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:01:15 +0200 Subject: [PATCH 088/236] (#190) Clean up leaks in gcli_free_release --- src/releases.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/releases.c b/src/releases.c index f031ff67..ab13c871 100644 --- a/src/releases.c +++ b/src/releases.c @@ -166,10 +166,13 @@ void gcli_free_releases(gcli_release_list *const list) { for (size_t i = 0; i < list->releases_size; ++i) { + free(list->releases[i].id.data); free(list->releases[i].name.data); free(list->releases[i].body.data); free(list->releases[i].author.data); free(list->releases[i].date.data); + free(list->releases[i].upload_url.data); + free(list->releases[i].html_url.data); for (size_t j = 0; j < list->releases[i].assets_size; ++j) { free(list->releases[i].assets[j].name); From 591a1dc5d0c624f2c51ac0104bce1da1dfdfd691 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:15:18 +0200 Subject: [PATCH 089/236] (#190) make github forks use new fetch_list routines --- src/github/forks.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/src/github/forks.c b/src/github/forks.c index 22a060c9..b8f8d648 100644 --- a/src/github/forks.c +++ b/src/github/forks.c @@ -38,17 +38,19 @@ #include int -github_get_forks(char const *owner, - char const *repo, - int const max, - gcli_fork_list *const list) +github_get_forks(char const *owner, char const *repo, + int const max, gcli_fork_list *const list) { - gcli_fetch_buffer buffer = {0}; - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - char *next_url = NULL; - struct json_stream stream = {0}; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + + gcli_fetch_list_ctx ctx = { + .listp = &list->forks, + .sizep = &list->forks_size, + .max = max, + .parse = (parsefn)(parse_github_forks), + }; *list = (gcli_fork_list) {0}; @@ -60,21 +62,10 @@ github_get_forks(char const *owner, gcli_get_apibase(), e_owner, e_repo); - do { - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_forks(&stream, &list->forks, &list->forks_size); - - json_close(&stream); - free(buffer.data); - free(url); - } while ((url = next_url) && (max == -1 || (int)list->forks_size < max)); - - free(next_url); free(e_owner); free(e_repo); - return 0; + return gcli_fetch_list(url, &ctx); } int @@ -88,13 +79,13 @@ github_fork_create(char const *owner, char const *repo, char const *_in) int rc = 0; e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s/forks", gcli_get_apibase(), e_owner, e_repo); if (_in) { - in = gcli_json_escape(SV((char *)_in)); + in = gcli_json_escape(SV((char *)_in)); post_data = sn_asprintf("{\"organization\":\""SV_FMT"\"}", SV_ARGS(in)); } From 4e2393e6f89cd64a139cb06c5cedd5492ba44409 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:17:55 +0200 Subject: [PATCH 090/236] (#190) Make github_get_repos use new fetch_list routines --- src/github/repos.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/github/repos.c b/src/github/repos.c index 747241ae..f655a2a0 100644 --- a/src/github/repos.c +++ b/src/github/repos.c @@ -40,11 +40,14 @@ int github_get_repos(char const *owner, int const max, gcli_repo_list *const list) { - char *url = NULL; - char *next_url = NULL; - char *e_owner = NULL; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; + char *url = NULL; + char *e_owner = NULL; + gcli_fetch_list_ctx ctx = { + .listp = &list->repos, + .sizep = &list->repos_size, + .max = max, + .parse = (parsefn)(parse_github_repos), + }; e_owner = gcli_urlencode(owner); @@ -66,20 +69,9 @@ github_get_repos(char const *owner, int const max, gcli_repo_list *const list) e_owner); } - do { - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_repos(&stream, &list->repos, &list->repos_size); - - free(url); - free(buffer.data); - json_close(&stream); - } while ((url = next_url) && (max == -1 || (int)list->repos_size < max)); - - free(url); free(e_owner); - return 0; + return gcli_fetch_list(url, &ctx); } int From 0d1fd9b6da218862b2fa3fcdf414aeec89e63d4f Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:20:16 +0200 Subject: [PATCH 091/236] (#190) Make github_get_own_repos use new fetch_list routines --- src/github/repos.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/github/repos.c b/src/github/repos.c index f655a2a0..1924e8ed 100644 --- a/src/github/repos.c +++ b/src/github/repos.c @@ -77,27 +77,17 @@ github_get_repos(char const *owner, int const max, gcli_repo_list *const list) int github_get_own_repos(int const max, gcli_repo_list *const list) { - char *url = NULL; - char *next_url = NULL; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; + char *url = NULL; + gcli_fetch_list_ctx ctx = { + .listp = &list->repos, + .sizep = &list->repos_size, + .max = max, + .parse = (parsefn)(parse_github_repos), + }; url = sn_asprintf("%s/user/repos", gcli_get_apibase()); - do { - buffer.length = 0; - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_repos(&stream, &list->repos, &list->repos_size); - - free(buffer.data); - json_close(&stream); - free(url); - } while ((url = next_url) && (max == -1 || (int)list->repos_size < max)); - - free(next_url); - - return 0; + return gcli_fetch_list(url, &ctx); } int From 7837a5e643e3f202535ac572989777bf591ccbd3 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:23:37 +0200 Subject: [PATCH 092/236] (#190) Make gitea_get_milestones use new fetch_list routines --- src/gitea/milestones.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/gitea/milestones.c b/src/gitea/milestones.c index a8dbeefa..93630a22 100644 --- a/src/gitea/milestones.c +++ b/src/gitea/milestones.c @@ -45,10 +45,15 @@ gitea_get_milestones(char const *const owner, int const max, gcli_milestone_list *const out) { - char *url = NULL, *next_url = NULL; + char *url; char *e_owner, *e_repo; - gcli_fetch_buffer buffer = {0}; - json_stream stream = {0}; + + gcli_fetch_list_ctx ctx = { + .listp = &out->milestones, + .sizep = &out->milestones_size, + .max = max, + .parse = (parsefn)(parse_gitea_milestones), + }; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -56,22 +61,10 @@ gitea_get_milestones(char const *const owner, url = sn_asprintf("%s/repos/%s/%s/milestones", gcli_get_apibase(), e_owner, e_repo); - do { - gcli_fetch(url, &next_url, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); - - parse_gitea_milestones(&stream, &out->milestones, &out->milestones_size); - - json_close(&stream); - free(url); - free(buffer.data); - } while ((url = next_url) && ((max < 0) || (out->milestones_size < (size_t)max))); - - free(url); free(e_owner); free(e_repo); - return 0; + return gcli_fetch_list(url, &ctx); } int From d8f648872b539b457501c4a5e6bba52e1a52f140 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:26:06 +0200 Subject: [PATCH 093/236] (#190) Make gitea_get_milestone return proper error codes --- src/gitea/milestones.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/gitea/milestones.c b/src/gitea/milestones.c index 93630a22..976972f2 100644 --- a/src/gitea/milestones.c +++ b/src/gitea/milestones.c @@ -68,14 +68,12 @@ gitea_get_milestones(char const *const owner, } int -gitea_get_milestone(char const *const owner, - char const *const repo, - int const milestone, - gcli_milestone *const out) +gitea_get_milestone(char const *const owner, char const *const repo, + int const milestone, gcli_milestone *const out) { char *url, *e_owner, *e_repo; gcli_fetch_buffer buffer = {0}; - json_stream stream = {0}; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -83,20 +81,23 @@ gitea_get_milestone(char const *const owner, url = sn_asprintf("%s/repos/%s/%s/milestones/%d", gcli_get_apibase(), e_owner, e_repo, milestone); - gcli_fetch(url, NULL, &buffer); - json_open_buffer(&stream, buffer.data, buffer.length); + free(e_owner); + free(e_repo); + + rc = gcli_fetch(url, NULL, &buffer); - parse_gitea_milestone(&stream, out); + if (rc == 0) { + json_stream stream = {0}; - json_close(&stream); + json_open_buffer(&stream, buffer.data, buffer.length); + parse_gitea_milestone(&stream, out); + json_close(&stream); + } free(buffer.data); free(url); - free(e_owner); - free(e_repo); - - return 0; + return rc; } int From 66b1b1262846ceac32143687e31d5839eff7bab5 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:27:07 +0200 Subject: [PATCH 094/236] (#190) Handle fetch failures in api subcommand --- src/cmd/api.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/api.c b/src/cmd/api.c index ebba6474..7f6051b8 100644 --- a/src/cmd/api.c +++ b/src/cmd/api.c @@ -64,7 +64,8 @@ fetch_all(char *_url) do { gcli_fetch_buffer buffer = {0}; - gcli_fetch(url, &next_url, &buffer); + if (gcli_fetch(url, &next_url, &buffer) < 0) + errx(1, "error: failed to fetch data"); fwrite(buffer.data, buffer.length, 1, stdout); From f698fc222d9ccf17c7da51a0999a1cf1a68a5d79 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:32:14 +0200 Subject: [PATCH 095/236] (#190) Make gcli_curl return an error code --- include/gcli/curl.h | 6 +++--- src/curl.c | 17 +++++++++++------ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/include/gcli/curl.h b/include/gcli/curl.h index 6f97ff25..4847ed9c 100644 --- a/include/gcli/curl.h +++ b/include/gcli/curl.h @@ -65,9 +65,9 @@ int gcli_fetch(char const *url, char **pagination_next, gcli_fetch_buffer *out); -void gcli_curl(FILE *stream, - char const *url, - char const *content_type); +int gcli_curl(FILE *stream, + char const *url, + char const *content_type); int gcli_fetch_with_method(char const *method, char const *url, diff --git a/src/curl.c b/src/curl.c index 2850b46e..d11189be 100644 --- a/src/curl.c +++ b/src/curl.c @@ -198,13 +198,14 @@ gcli_curl_test_success(char const *url) * STREAM. * * content_type may be NULL. */ -void +int gcli_curl(FILE *stream, char const *url, char const *content_type) { - CURLcode ret; + CURLcode ret; struct curl_slist *headers; - gcli_fetch_buffer buffer = {0}; - char *auth_header = NULL; + gcli_fetch_buffer buffer = {0}; + char *auth_header = NULL; + int rc = 0; headers = NULL; @@ -234,14 +235,18 @@ gcli_curl(FILE *stream, char const *url, char const *content_type) curl_easy_setopt(gcli_curl_session, CURLOPT_FOLLOWLOCATION, 1L); ret = curl_easy_perform(gcli_curl_session); - gcli_curl_check_api_error(ret, url, &buffer); + rc = gcli_curl_check_api_error(ret, url, &buffer); + + if (rc == 0) + fwrite(buffer.data, 1, buffer.length, stream); - fwrite(buffer.data, 1, buffer.length, stream); free(buffer.data); curl_slist_free_all(headers); free(auth_header); + + return rc; } /* Callback to extract the link header for pagination handling. */ From 62ba4e2c86b66386241289b0fe9102885ef33a95 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:40:12 +0200 Subject: [PATCH 096/236] (#190) Make gcli_curl return error codes and pass / check at call sites --- include/gcli/forges.h | 2 +- include/gcli/gitea/pulls.h | 8 ++++---- include/gcli/github/pulls.h | 8 ++++---- include/gcli/gitlab/merge_requests.h | 8 ++++---- include/gcli/gitlab/snippets.h | 2 +- src/cmd/api.c | 4 ++-- src/cmd/gists.c | 4 +++- src/gitea/pulls.c | 12 ++++++++---- src/github/pulls.c | 14 ++++++++------ src/gitlab/merge_requests.c | 4 +++- src/gitlab/pipelines.c | 2 +- src/gitlab/snippets.c | 7 +++++-- 12 files changed, 44 insertions(+), 31 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 48e84c06..f754ea27 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -231,7 +231,7 @@ struct gcli_forge_descriptor { /** * Print a diff of the changes of a PR/MR to the stream */ - void (*print_pull_diff)( + int (*print_pull_diff)( FILE *stream, char const *owner, char const *reponame, diff --git a/include/gcli/gitea/pulls.h b/include/gcli/gitea/pulls.h index da3630ba..42dd4992 100644 --- a/include/gcli/gitea/pulls.h +++ b/include/gcli/gitea/pulls.h @@ -68,10 +68,10 @@ int gitea_pull_reopen(char const *owner, char const *repo, int pr_number); -void gitea_print_pr_diff(FILE *stream, - char const *owner, - char const *repo, - int pr_number); +int gitea_print_pr_diff(FILE *stream, + char const *owner, + char const *repo, + int pr_number); int gitea_pull_checks(char const *owner, char const *repo, diff --git a/include/gcli/github/pulls.h b/include/gcli/github/pulls.h index 3c9d02b4..6a22ae03 100644 --- a/include/gcli/github/pulls.h +++ b/include/gcli/github/pulls.h @@ -48,10 +48,10 @@ int github_get_pulls(char const *owner, int max, gcli_pull_list *out); -void github_print_pull_diff(FILE *stream, - char const *owner, - char const *reponame, - int pr_number); +int github_print_pull_diff(FILE *stream, + char const *owner, + char const *reponame, + int pr_number); int github_pull_checks(char const *owner, char const *repo, diff --git a/include/gcli/gitlab/merge_requests.h b/include/gcli/gitlab/merge_requests.h index bc093593..53dec57d 100644 --- a/include/gcli/gitlab/merge_requests.h +++ b/include/gcli/gitlab/merge_requests.h @@ -46,10 +46,10 @@ int gitlab_get_mrs(char const *owner, int max, gcli_pull_list *out); -void gitlab_print_pr_diff(FILE *stream, - char const *owner, - char const *reponame, - int pr_number); +int gitlab_print_pr_diff(FILE *stream, + char const *owner, + char const *reponame, + int pr_number); int gitlab_mr_merge(char const *owner, char const *reponame, diff --git a/include/gcli/gitlab/snippets.h b/include/gcli/gitlab/snippets.h index fd1505c6..201a67cd 100644 --- a/include/gcli/gitlab/snippets.h +++ b/include/gcli/gitlab/snippets.h @@ -64,6 +64,6 @@ void gcli_snippets_print(enum gcli_output_flags flags, int gcli_snippet_delete(char const *snippet_id); -void gcli_snippet_get(char const *snippet_id); +int gcli_snippet_get(char const *snippet_id); #endif /* GITLAB_SNIPPETS_H */ diff --git a/src/cmd/api.c b/src/cmd/api.c index 7f6051b8..f6a250a1 100644 --- a/src/cmd/api.c +++ b/src/cmd/api.c @@ -118,8 +118,8 @@ subcommand_api(int argc, char *argv[]) if (do_all) fetch_all(url); - else - gcli_curl(stdout, url, "application/json"); + else if (gcli_curl(stdout, url, "application/json") < 0) + errx(1, "error: failed to fetch data"); free(url); diff --git a/src/cmd/gists.c b/src/cmd/gists.c index f36acf65..895f1629 100644 --- a/src/cmd/gists.c +++ b/src/cmd/gists.c @@ -88,7 +88,9 @@ subcommand_gist_get(int argc, char *argv[]) if (isatty(STDOUT_FILENO) && (file->size >= 4 * 1024 * 1024)) errx(1, "File is bigger than 4 MiB, refusing to print to stdout."); - gcli_curl(stdout, file->url.data, file->type.data); + if (gcli_curl(stdout, file->url.data, file->type.data) < 0) + errx(1, "error: failed to fetch gist"); + return EXIT_SUCCESS; } diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index 02d30d9c..811bd952 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -148,15 +148,16 @@ gitea_pull_reopen(char const *owner, return gitea_pulls_patch_state(owner, repo, pr_number, "open"); } -void +int gitea_print_pr_diff(FILE *const stream, char const *owner, char const *repo, int const pr_number) { - char *url = NULL; + char *url = NULL; char *e_owner = NULL; - char *e_repo = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -165,11 +166,14 @@ gitea_print_pr_diff(FILE *const stream, "%s/repos/%s/%s/pulls/%d.patch", gcli_get_apibase(), e_owner, e_repo, pr_number); - gcli_curl(stream, url, NULL); + + rc = gcli_curl(stream, url, NULL); free(e_owner); free(e_repo); free(url); + + return rc; } int diff --git a/src/github/pulls.c b/src/github/pulls.c index efc0acf7..a51e7f51 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -112,15 +112,15 @@ github_get_pulls(char const *owner, return github_fetch_pulls(url, details->author, max, list); } -void +int github_print_pull_diff(FILE *stream, - char const *owner, - char const *repo, + char const *owner, char const *repo, int const pr_number) { - char *url = NULL; + char *url = NULL; char *e_owner = NULL; - char *e_repo = NULL; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -129,11 +129,13 @@ github_print_pull_diff(FILE *stream, "%s/repos/%s/%s/pulls/%d", gcli_get_apibase(), e_owner, e_repo, pr_number); - gcli_curl(stream, url, "Accept: application/vnd.github.v3.diff"); + rc = gcli_curl(stream, url, "Accept: application/vnd.github.v3.diff"); free(e_owner); free(e_repo); free(url); + + return rc; } /* TODO: figure out a way to get rid of the 3 consecutive urlencode diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index 4f7320ca..db2e718e 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -113,7 +113,7 @@ gitlab_get_mrs(char const *owner, return gitlab_fetch_mrs(url, max, list); } -void +int gitlab_print_pr_diff(FILE *stream, char const *owner, char const *repo, @@ -126,6 +126,8 @@ gitlab_print_pr_diff(FILE *stream, fprintf(stream, "note : Getting the diff of a Merge Request is not " "supported on GitLab. Blame the Gitlab people.\n"); + + return -1; } int diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index 8f74fb5b..1c8778a9 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -392,7 +392,7 @@ gitlab_job_download_artifacts(char const *owner, char const *repo, gitlab_get_apibase(), e_owner, e_repo, jid); - gcli_curl(f, url, "application/zip"); + rc = gcli_curl(f, url, "application/zip"); fclose(f); free(url); diff --git a/src/gitlab/snippets.c b/src/gitlab/snippets.c index 6ca91259..aa5b445f 100644 --- a/src/gitlab/snippets.c +++ b/src/gitlab/snippets.c @@ -196,12 +196,15 @@ gcli_snippet_delete(char const *snippet_id) return rc; } -void +int gcli_snippet_get(char const *snippet_id) { + int rc = 0; char *url = sn_asprintf("%s/snippets/%s/raw", gitlab_get_apibase(), snippet_id); - gcli_curl(stdout, url, NULL); + rc = gcli_curl(stdout, url, NULL); free(url); + + return rc; } From df42d341902887b1b6ac78b36a47927db4bfab82 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:41:54 +0200 Subject: [PATCH 097/236] (#190) Make gcli_post_upload return a proper error code --- include/gcli/curl.h | 10 +++++----- src/curl.c | 11 +++++++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/gcli/curl.h b/include/gcli/curl.h index 4847ed9c..855fc4c2 100644 --- a/include/gcli/curl.h +++ b/include/gcli/curl.h @@ -75,11 +75,11 @@ int gcli_fetch_with_method(char const *method, char **pagination_next, gcli_fetch_buffer *out); -void gcli_post_upload(char const *url, - char const *content_type, - void *buffer, - size_t buffer_size, - gcli_fetch_buffer *out); +int gcli_post_upload(char const *url, + char const *content_type, + void *buffer, + size_t buffer_size, + gcli_fetch_buffer *out); void gcli_curl_gitea_upload_attachment(char const *url, char const *filename, diff --git a/src/curl.c b/src/curl.c index d11189be..4749a870 100644 --- a/src/curl.c +++ b/src/curl.c @@ -415,15 +415,16 @@ gcli_fetch_with_method( * * content_type may not be NULL. */ -void +int gcli_post_upload(char const *url, char const *content_type, void *buffer, size_t const buffer_size, gcli_fetch_buffer *const out) { - CURLcode ret; - struct curl_slist *headers; + CURLcode ret; + struct curl_slist *headers; + int rc = 0; char *auth_header = gcli_config_get_authheader(); char *contenttype_header = sn_asprintf( @@ -457,7 +458,7 @@ gcli_post_upload(char const *url, curl_easy_setopt(gcli_curl_session, CURLOPT_WRITEFUNCTION, fetch_write_callback); ret = curl_easy_perform(gcli_curl_session); - gcli_curl_check_api_error(ret, url, out); + rc = gcli_curl_check_api_error(ret, url, out); curl_slist_free_all(headers); headers = NULL; @@ -465,6 +466,8 @@ gcli_post_upload(char const *url, free(auth_header); free(contentsize_header); free(contenttype_header); + + return rc; } /** gcli_gitea_upload_attachment: From 00508185f78cd07f04237ade3bb0fc63e7df4c4c Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:45:01 +0200 Subject: [PATCH 098/236] (#190) Check error code of call sites of gcli_post_upload and propagate errors --- src/github/releases.c | 52 ++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/github/releases.c b/src/github/releases.c index 48e8a282..814e8e87 100644 --- a/src/github/releases.c +++ b/src/github/releases.c @@ -91,22 +91,23 @@ github_get_upload_url(gcli_release *const it) return sn_strndup(it->upload_url.data, len); } -static void +static int github_upload_release_asset(char const *url, gcli_release_asset_upload const asset) { - char *req = NULL; - sn_sv file_content = {0}; - gcli_fetch_buffer buffer = {0}; + char *req = NULL; + sn_sv file_content = {0}; + gcli_fetch_buffer buffer = {0}; + int rc = 0; file_content.length = sn_mmap_file(asset.path, (void **)&file_content.data); if (file_content.length == 0) - errx(1, "Trying to upload an empty file"); + return -1; /* TODO: URL escape this */ req = sn_asprintf("%s?name=%s", url, asset.name); - gcli_post_upload( + rc = gcli_post_upload( req, "application/octet-stream", /* HACK */ file_content.data, @@ -115,27 +116,29 @@ github_upload_release_asset(char const *url, free(req); free(buffer.data); + + return rc; } int github_create_release(gcli_new_release const *release) { - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - char *upload_url = NULL; - char *post_data = NULL; - char *name_json = NULL; - char *commitish_json = NULL; - sn_sv escaped_body = {0}; - gcli_fetch_buffer buffer = {0}; - gcli_release response = {0}; - int rc = 0; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + char *upload_url = NULL; + char *post_data = NULL; + char *name_json = NULL; + char *commitish_json = NULL; + sn_sv escaped_body = {0}; + gcli_fetch_buffer buffer = {0}; + gcli_release response = {0}; + int rc = 0; assert(release); e_owner = gcli_urlencode(release->owner); - e_repo = gcli_urlencode(release->repo); + e_repo = gcli_urlencode(release->repo); /* https://docs.github.com/en/rest/reference/repos#create-a-release */ url = sn_asprintf( @@ -182,7 +185,10 @@ github_create_release(gcli_new_release const *release) for (size_t i = 0; i < release->assets_size; ++i) { printf("INFO : Uploading asset %s...\n", release->assets[i].path); - github_upload_release_asset(upload_url, release->assets[i]); + rc = github_upload_release_asset(upload_url, release->assets[i]); + + if (rc < 0) + break; } out: @@ -202,13 +208,13 @@ github_create_release(gcli_new_release const *release) int github_delete_release(char const *owner, char const *repo, char const *id) { - char *url = NULL; + char *url = NULL; char *e_owner = NULL; - char *e_repo = NULL; - int rc = 0; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); url = sn_asprintf( "%s/repos/%s/%s/releases/%s", From e0940cc0adbccc4758ca701eb60696f4c957abb0 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:46:03 +0200 Subject: [PATCH 099/236] (#190) Make gcli_curl_gitea_upload_attachment return proper error codes --- include/gcli/curl.h | 6 +++--- src/curl.c | 13 ++++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/gcli/curl.h b/include/gcli/curl.h index 855fc4c2..c584cf81 100644 --- a/include/gcli/curl.h +++ b/include/gcli/curl.h @@ -81,9 +81,9 @@ int gcli_post_upload(char const *url, size_t buffer_size, gcli_fetch_buffer *out); -void gcli_curl_gitea_upload_attachment(char const *url, - char const *filename, - gcli_fetch_buffer *out); +int gcli_curl_gitea_upload_attachment(char const *url, + char const *filename, + gcli_fetch_buffer *out); bool gcli_curl_test_success(char const *url); char *gcli_urlencode(char const *); diff --git a/src/curl.c b/src/curl.c index 4749a870..1e2f2e9b 100644 --- a/src/curl.c +++ b/src/curl.c @@ -475,15 +475,16 @@ gcli_post_upload(char const *url, * Upload the given file to the given url. This is gitea-specific * code. */ -void +int gcli_curl_gitea_upload_attachment(char const *url, char const *filename, gcli_fetch_buffer *const out) { - CURLcode ret; - curl_mime *mime; - curl_mimepart *contentpart; + CURLcode ret; + curl_mime *mime; + curl_mimepart *contentpart; struct curl_slist *headers; + int rc = 0; char *auth_header = gcli_config_get_authheader(); @@ -520,13 +521,15 @@ gcli_curl_gitea_upload_attachment(char const *url, curl_easy_setopt(gcli_curl_session, CURLOPT_WRITEFUNCTION, fetch_write_callback); ret = curl_easy_perform(gcli_curl_session); - gcli_curl_check_api_error(ret, url, out); + rc = gcli_curl_check_api_error(ret, url, out); /* Cleanup */ curl_slist_free_all(headers); headers = NULL; curl_mime_free(mime); free(auth_header); + + return rc; } sn_sv From 8c937227fcc7733863e9c4c74049457c9fe7b640 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:47:54 +0200 Subject: [PATCH 100/236] (#190) Make gitea_create_release check error of gitea_upload_release_asset --- src/gitea/releases.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/gitea/releases.c b/src/gitea/releases.c index 32e130e7..57d7b15a 100644 --- a/src/gitea/releases.c +++ b/src/gitea/releases.c @@ -53,38 +53,41 @@ gitea_parse_release(gcli_fetch_buffer const *const buffer, json_close(&stream); } -static void +static int gitea_upload_release_asset(char *const url, gcli_release_asset_upload const asset) { - char *e_assetname = NULL; - char *request = NULL; - gcli_fetch_buffer buffer = {0}; + char *e_assetname = NULL; + char *request = NULL; + gcli_fetch_buffer buffer = {0}; + int rc = 0; e_assetname = gcli_urlencode(asset.name); request = sn_asprintf("%s?name=%s", url, e_assetname); - gcli_curl_gitea_upload_attachment(request, asset.path, &buffer); + rc = gcli_curl_gitea_upload_attachment(request, asset.path, &buffer); free(request); free(e_assetname); free(buffer.data); + + return rc; } int gitea_create_release(gcli_new_release const *release) { - char *commitish_json = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - char *name_json = NULL; - char *post_data = NULL; - char *upload_url = NULL; - char *url = NULL; - gcli_fetch_buffer buffer = {0}; - gcli_release response = {0}; - sn_sv escaped_body = {0}; - int rc = 0; + char *commitish_json = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + char *name_json = NULL; + char *post_data = NULL; + char *upload_url = NULL; + char *url = NULL; + gcli_fetch_buffer buffer = {0}; + gcli_release response = {0}; + sn_sv escaped_body = {0}; + int rc = 0; e_owner = gcli_urlencode(release->owner); e_repo = gcli_urlencode(release->repo); @@ -134,7 +137,10 @@ gitea_create_release(gcli_new_release const *release) for (size_t i = 0; i < release->assets_size; ++i) { printf("INFO : Uploading asset %s...\n", release->assets[i].path); - gitea_upload_release_asset(upload_url, release->assets[i]); + rc = gitea_upload_release_asset(upload_url, release->assets[i]); + + if (rc < 0) + break; } out: From 409ec5db8497f776af8adb9fb2f78904c417006f Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 14 Aug 2023 17:52:32 +0200 Subject: [PATCH 101/236] Bump to new devel version --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6ab57672..0e460bde 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([gcli],[1.2.0-devel],[nsonack@herrhotzenplotz.de],[gcli],[https://gitlab.com/herrhotzenplotz/gcli/]) +AC_INIT([gcli],[1.3.0-devel],[nsonack@herrhotzenplotz.de],[gcli],[https://gitlab.com/herrhotzenplotz/gcli/]) AM_INIT_AUTOMAKE([1.0 foreign subdir-objects dist-bzip2 dist-xz -Wall]) dnl Release Date. From 17bf03ab034d953cf56fa31ebb5b7cde5023c7d6 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 15 Aug 2023 00:01:26 +0200 Subject: [PATCH 102/236] Add a gcli_ctx and pass it literally everywhere Sorry for this patch. --- Makefile.am | 10 +- configure.ac | 2 +- include/gcli/cmd.h | 4 +- include/gcli/colour.h | 16 +- include/gcli/comments.h | 13 +- include/gcli/config.h | 31 ++- include/gcli/ctx.h | 49 ++++ include/gcli/curl.h | 27 +-- include/gcli/editor.h | 8 +- include/gcli/forges.h | 67 +++++- include/gcli/forks.h | 14 +- include/gcli/gcli.h | 10 + include/gcli/gitconfig.h | 2 +- include/gcli/gitea/comments.h | 7 +- include/gcli/gitea/config.h | 8 +- include/gcli/gitea/forks.h | 13 +- include/gcli/gitea/issues.h | 51 ++-- include/gcli/gitea/labels.h | 12 +- include/gcli/gitea/milestones.h | 26 +-- include/gcli/gitea/pulls.h | 52 ++--- include/gcli/gitea/releases.h | 11 +- include/gcli/gitea/repos.h | 11 +- include/gcli/gitea/sshkeys.h | 11 +- include/gcli/github/api.h | 2 +- include/gcli/github/checks.h | 10 +- include/gcli/github/comments.h | 11 +- include/gcli/github/config.h | 8 +- include/gcli/github/forks.h | 9 +- include/gcli/github/gists.h | 18 +- include/gcli/github/issues.h | 55 ++--- include/gcli/github/labels.h | 12 +- include/gcli/github/milestones.h | 28 +-- include/gcli/github/pulls.h | 43 ++-- include/gcli/github/releases.h | 11 +- include/gcli/github/repos.h | 11 +- include/gcli/github/review.h | 5 +- include/gcli/github/sshkeys.h | 11 +- include/gcli/github/status.h | 5 +- include/gcli/gitlab/api.h | 2 +- include/gcli/gitlab/comments.h | 9 +- include/gcli/gitlab/config.h | 8 +- include/gcli/gitlab/forks.h | 9 +- include/gcli/gitlab/issues.h | 54 ++--- include/gcli/gitlab/labels.h | 12 +- include/gcli/gitlab/merge_requests.h | 56 ++--- include/gcli/gitlab/milestones.h | 30 +-- include/gcli/gitlab/pipelines.h | 44 ++-- include/gcli/gitlab/releases.h | 11 +- include/gcli/gitlab/repos.h | 13 +- include/gcli/gitlab/review.h | 5 +- include/gcli/gitlab/snippets.h | 11 +- include/gcli/gitlab/sshkeys.h | 11 +- include/gcli/gitlab/status.h | 5 +- include/gcli/issues.h | 52 ++--- include/gcli/json_util.h | 62 ++--- include/gcli/labels.h | 17 +- include/gcli/milestones.h | 32 ++- include/gcli/pulls.h | 62 ++--- include/gcli/releases.h | 16 +- include/gcli/repos.h | 18 +- include/gcli/review.h | 7 +- include/gcli/sshkeys.h | 13 +- include/gcli/status.h | 8 +- include/gcli/table.h | 6 +- src/cmd.c | 4 +- src/cmd/gcli.c | 173 ++++++++++++++ src/colour.c | 30 +-- src/comments.c | 48 ++-- src/config.c | 337 +++++++++++++++------------ src/curl.c | 62 +++-- src/editor.c | 7 +- src/forges.c | 4 +- src/forks.c | 20 +- src/gcli.c | 146 ++---------- src/gitconfig.c | 3 +- src/gitea/comments.c | 8 +- src/gitea/config.c | 23 +- src/gitea/forks.c | 13 +- src/gitea/issues.c | 116 ++++----- src/gitea/labels.c | 30 ++- src/gitea/milestones.c | 52 ++--- src/gitea/pulls.c | 86 +++---- src/gitea/releases.c | 29 +-- src/gitea/repos.c | 17 +- src/gitea/sshkeys.c | 15 +- src/github/api.c | 6 +- src/github/checks.c | 21 +- src/github/comments.c | 14 +- src/github/config.c | 23 +- src/github/forks.c | 15 +- src/github/gists.c | 72 +++--- src/github/issues.c | 142 ++++++----- src/github/labels.c | 54 ++--- src/github/milestones.c | 56 +++-- src/github/pulls.c | 98 ++++---- src/github/releases.c | 33 +-- src/github/repos.c | 36 +-- src/github/review.c | 45 ++-- src/github/sshkeys.c | 15 +- src/github/status.c | 16 +- src/gitlab/api.c | 8 +- src/gitlab/comments.c | 28 ++- src/gitlab/config.c | 23 +- src/gitlab/forks.c | 19 +- src/gitlab/issues.c | 143 ++++++------ src/gitlab/labels.c | 45 ++-- src/gitlab/merge_requests.c | 125 +++++----- src/gitlab/milestones.c | 54 ++--- src/gitlab/pipelines.c | 120 +++++----- src/gitlab/releases.c | 20 +- src/gitlab/repos.c | 46 ++-- src/gitlab/review.c | 8 +- src/gitlab/snippets.c | 49 ++-- src/gitlab/sshkeys.c | 25 +- src/gitlab/status.c | 15 +- src/issues.c | 90 ++++--- src/json_util.c | 58 +++-- src/labels.c | 25 +- src/milestones.c | 53 ++--- src/pgen/dump_c.c | 28 ++- src/pgen/dump_h.c | 5 +- src/pulls.c | 130 +++++------ src/releases.c | 44 ++-- src/repos.c | 29 +-- src/review.c | 15 +- src/sshkeys.c | 19 +- src/status.c | 13 +- src/table.c | 46 ++-- 128 files changed, 2201 insertions(+), 2218 deletions(-) create mode 100644 include/gcli/ctx.h create mode 100644 src/cmd/gcli.c diff --git a/Makefile.am b/Makefile.am index dcea2267..1455bd61 100644 --- a/Makefile.am +++ b/Makefile.am @@ -61,6 +61,7 @@ gcli_SOURCES = \ src/cmd/comment.c \ src/cmd/config.c \ src/cmd/forks.c \ + src/cmd/gcli.c \ src/cmd/gists.c \ src/cmd/issues.c \ src/cmd/labels.c \ @@ -70,9 +71,7 @@ gcli_SOURCES = \ src/cmd/releases.c \ src/cmd/repos.c \ src/cmd/snippets.c \ - src/cmd/status.c \ - include/gcli/gcli.h \ - src/gcli.c + src/cmd/status.c libsn_la_SOURCES = \ thirdparty/sn/sn.c \ @@ -110,6 +109,7 @@ TEMPLATES = \ templates/gitea/milestones.t libgcli_la_SOURCES = \ + include/gcli/gcli.h src/gcli.c \ src/colour.c include/gcli/colour.h \ src/comments.c include/gcli/comments.h \ src/config.c include/gcli/config.h \ @@ -171,6 +171,10 @@ libgcli_la_SOURCES = \ src/gitea/milestones.c include/gcli/gitea/milestones.h \ $(TEMPLATES) +libgcli_la_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -DIN_LIBGCLI=1 + BUILT_SOURCES = \ $(TEMPLATES:.t=.c) \ $(TEMPLATES:.t=.h) diff --git a/configure.ac b/configure.ac index 0e460bde..b0675e63 100644 --- a/configure.ac +++ b/configure.ac @@ -50,7 +50,7 @@ AC_CHECK_LIB([curl],[curl_easy_init],,[AC_MSG_ERROR([-lcurl doesn not contain cu dnl Go looking for headers that may define getopt_long AC_CHECK_HEADERS([getopt.h unistd.h]) dnl Other headers that we require -AC_CHECK_HEADERS([string.h signal.h sys/wait.h unistd.h sys/mman.h sys/types.h], +AC_CHECK_HEADERS([string.h signal.h sys/wait.h unistd.h sys/mman.h sys/types.h sys/queue.h], , [AC_MSG_ERROR([Required header not found])]) diff --git a/include/gcli/cmd.h b/include/gcli/cmd.h index bd8d9ee2..15e2e342 100644 --- a/include/gcli/cmd.h +++ b/include/gcli/cmd.h @@ -34,6 +34,8 @@ #include #endif +#include + #include static inline char * @@ -48,7 +50,7 @@ shift(int *argc, char ***argv) void version(void); void copyright(void); -void check_owner_and_repo(const char **owner, const char **repo); +void check_owner_and_repo(gcli_ctx *ctx, const char **owner, const char **repo); void parse_labels_options( int *argc, char ***argv, diff --git a/include/gcli/colour.h b/include/gcli/colour.h index d9ba7f90..9444b3a1 100644 --- a/include/gcli/colour.h +++ b/include/gcli/colour.h @@ -34,6 +34,8 @@ #include #endif +#include + #include #include @@ -53,12 +55,12 @@ enum { GCLI_COLOR_DEFAULT, }; -char const *gcli_setcolour256(uint32_t colourcode); -char const *gcli_resetcolour(void); -char const *gcli_setcolour(int colour); -char const *gcli_state_colour_sv(sn_sv const state); -char const *gcli_state_colour_str(char const *it); -char const *gcli_setbold(void); -char const *gcli_resetbold(void); +char const *gcli_setcolour256(gcli_ctx *ctx, uint32_t colourcode); +char const *gcli_resetcolour(gcli_ctx *ctx); +char const *gcli_setcolour(gcli_ctx *ctx, int colour); +char const *gcli_state_colour_sv(gcli_ctx *ctx, sn_sv const state); +char const *gcli_state_colour_str(gcli_ctx *ctx, char const *it); +char const *gcli_setbold(gcli_ctx *ctx); +char const *gcli_resetbold(gcli_ctx *ctx); #endif /* COLOR_H */ diff --git a/include/gcli/comments.h b/include/gcli/comments.h index e6edd21e..c39d3648 100644 --- a/include/gcli/comments.h +++ b/include/gcli/comments.h @@ -34,6 +34,8 @@ #include #endif +#include + #include #include @@ -64,9 +66,12 @@ struct gcli_submit_comment_opts { }; void gcli_comment_list_free(gcli_comment_list *list); -void gcli_print_comment_list(gcli_comment_list const *list); -void gcli_issue_comments(char const *owner, char const *repo, int issue); -void gcli_pull_comments(char const *owner, char const *repo, int issue); -int gcli_comment_submit(gcli_submit_comment_opts opts); +void gcli_print_comment_list(gcli_ctx *, gcli_comment_list const *list); +void gcli_issue_comments(gcli_ctx *ctx, + char const *owner, char const *repo, + int issue); +void gcli_pull_comments(gcli_ctx *ctx, char const *owner, char const *repo, + int issue); +int gcli_comment_submit(gcli_ctx *ctx, gcli_submit_comment_opts opts); #endif /* COMMENTS_H */ diff --git a/include/gcli/config.h b/include/gcli/config.h index aaa19b29..1274949a 100644 --- a/include/gcli/config.h +++ b/include/gcli/config.h @@ -37,25 +37,24 @@ #include #include -int gcli_config_init( - int *argc, - char ***argv); +int gcli_config_parse_args(gcli_ctx *ctx, int *argc, char ***argv); -void gcli_config_get_upstream_parts(sn_sv *owner, sn_sv *repo); +void gcli_config_get_upstream_parts(gcli_ctx *ctx, sn_sv *owner, sn_sv *repo); -sn_sv gcli_config_find_by_key(sn_sv const section_name, +sn_sv gcli_config_find_by_key(gcli_ctx *ctx, + sn_sv const section_name, char const *key); -char *gcli_config_get_editor(void); -char *gcli_config_get_authheader(void); -sn_sv gcli_config_get_account(void); -sn_sv gcli_config_get_upstream(void); -sn_sv gcli_config_get_base(void); -gcli_forge_type gcli_config_get_forge_type(void); -sn_sv gcli_config_get_override_default_account(void); -bool gcli_config_pr_inhibit_delete_source_branch(void); -void gcli_config_get_repo(char const **, char const **); -int gcli_config_have_colours(void); -char const *gcli_get_apibase(void); +char *gcli_config_get_editor(gcli_ctx *ctx); +char *gcli_config_get_authheader(gcli_ctx *ctx); +sn_sv gcli_config_get_account(gcli_ctx *ctx); +sn_sv gcli_config_get_upstream(gcli_ctx *ctx); +sn_sv gcli_config_get_base(gcli_ctx *ctx); +gcli_forge_type gcli_config_get_forge_type(gcli_ctx *ctx); +sn_sv gcli_config_get_override_default_account(gcli_ctx *ctx); +bool gcli_config_pr_inhibit_delete_source_branch(gcli_ctx *ctx); +void gcli_config_get_repo(gcli_ctx *ctx, char const **, char const **); +int gcli_config_have_colours(gcli_ctx *ctx); +char const *gcli_get_apibase(gcli_ctx *ctx); #endif /* CONFIG_H */ diff --git a/include/gcli/ctx.h b/include/gcli/ctx.h new file mode 100644 index 00000000..d76ad164 --- /dev/null +++ b/include/gcli/ctx.h @@ -0,0 +1,49 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CTX_H +#define GCLI_CTX_H + +#include + +/* Strictly internal structure containing the gcli library context + * data */ +struct gcli_ctx { + CURL *curl; + struct gcli_config *config; + struct gcli_dotgcli *dotgcli; + + char *last_error; +}; + +/* Functions that are strictly called from the init / deinit routines + * and not exposed to the public interface */ +int gcli_config_init_ctx(struct gcli_ctx *); + +#endif /* GCLI_CTX_H */ diff --git a/include/gcli/curl.h b/include/gcli/curl.h index c584cf81..15058a69 100644 --- a/include/gcli/curl.h +++ b/include/gcli/curl.h @@ -34,6 +34,8 @@ #include #endif +#include + #include #include #include @@ -61,27 +63,20 @@ struct gcli_fetch_list_ctx { void const *userdata; }; -int gcli_fetch(char const *url, - char **pagination_next, +int gcli_fetch(gcli_ctx *ctx, char const *url, char **pagination_next, gcli_fetch_buffer *out); -int gcli_curl(FILE *stream, - char const *url, +int gcli_curl(gcli_ctx *ctx, FILE *stream, char const *url, char const *content_type); -int gcli_fetch_with_method(char const *method, - char const *url, - char const *data, - char **pagination_next, - gcli_fetch_buffer *out); +int gcli_fetch_with_method(gcli_ctx *ctx, char const *method, + char const *url, char const *data, + char **pagination_next, gcli_fetch_buffer *out); -int gcli_post_upload(char const *url, - char const *content_type, - void *buffer, - size_t buffer_size, - gcli_fetch_buffer *out); +int gcli_post_upload(gcli_ctx *ctx, char const *url, char const *content_type, + void *buffer, size_t buffer_size, gcli_fetch_buffer *out); -int gcli_curl_gitea_upload_attachment(char const *url, +int gcli_curl_gitea_upload_attachment(gcli_ctx *ctx, char const *url, char const *filename, gcli_fetch_buffer *out); @@ -89,6 +84,6 @@ bool gcli_curl_test_success(char const *url); char *gcli_urlencode(char const *); sn_sv gcli_urlencode_sv(sn_sv const); char *gcli_urldecode(char const *input); -int gcli_fetch_list(char *url, gcli_fetch_list_ctx *ctx); +int gcli_fetch_list(gcli_ctx *ctx, char *url, gcli_fetch_list_ctx *fctx); #endif /* CURL_H */ diff --git a/include/gcli/editor.h b/include/gcli/editor.h index 4387c566..9b53c8a0 100644 --- a/include/gcli/editor.h +++ b/include/gcli/editor.h @@ -34,9 +34,13 @@ #include #endif +#include + #include -sn_sv gcli_editor_get_user_message(void (*initializer)(FILE *, void *), - void *user_data); +sn_sv gcli_editor_get_user_message( + gcli_ctx *ctx, + void (*initializer)(gcli_ctx *, FILE *, void *), + void *user_data); #endif /* EDITOR_H */ diff --git a/include/gcli/forges.h b/include/gcli/forges.h index f754ea27..0fdea189 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -56,12 +56,14 @@ struct gcli_forge_descriptor { /** * Submit a comment to a pull/mr or issue */ int (*perform_submit_comment)( + gcli_ctx *ctx, gcli_submit_comment_opts opts, gcli_fetch_buffer *out); /** * List comments on the given issue */ int (*get_issue_comments)( + gcli_ctx *ctx, char const *owner, char const *repo, int issue, @@ -70,6 +72,7 @@ struct gcli_forge_descriptor { /** * List comments on the given PR */ int (*get_pull_comments)( + gcli_ctx *ctx, char const *owner, char const *repo, int pr, @@ -78,6 +81,7 @@ struct gcli_forge_descriptor { /** * List forks of the given repo */ int (*get_forks)( + gcli_ctx *ctx, char const *owner, char const *repo, int max, @@ -86,6 +90,7 @@ struct gcli_forge_descriptor { /** * Fork the given repo into the owner _in */ int (*fork_create)( + gcli_ctx *ctx, char const *owner, char const *repo, char const *_in); @@ -93,6 +98,7 @@ struct gcli_forge_descriptor { /** * Get a list of issues on the given repo */ int (*get_issues)( + gcli_ctx *ctx, char const *owner, char const *repo, gcli_issue_fetch_details const *details, @@ -102,6 +108,7 @@ struct gcli_forge_descriptor { /** * Get a summary of an issue */ int (*get_issue_summary)( + gcli_ctx *ctx, char const *owner, char const *repo, int issue_number, @@ -110,6 +117,7 @@ struct gcli_forge_descriptor { /** * Close the given issue */ int (*issue_close)( + gcli_ctx *ctx, char const *owner, char const *repo, int issue_number); @@ -117,6 +125,7 @@ struct gcli_forge_descriptor { /** * Reopen the given issue */ int (*issue_reopen)( + gcli_ctx *ctx, char const *owner, char const *repo, int issue_number); @@ -124,6 +133,7 @@ struct gcli_forge_descriptor { /** * Assign an issue to a user */ int (*issue_assign)( + gcli_ctx *ctx, char const *owner, char const *repo, int issue_number, @@ -132,6 +142,7 @@ struct gcli_forge_descriptor { /** * Add labels to issues */ int (*issue_add_labels)( + gcli_ctx *ctx, char const *owner, char const *repo, int issue, @@ -141,6 +152,7 @@ struct gcli_forge_descriptor { /** * Removes labels from issues */ int (*issue_remove_labels)( + gcli_ctx *ctx, char const *owner, char const *repo, int issue, @@ -150,6 +162,7 @@ struct gcli_forge_descriptor { /** * Submit an issue */ int (*perform_submit_issue)( + gcli_ctx *ctx, gcli_submit_issue_options opts, gcli_fetch_buffer *out); @@ -165,6 +178,7 @@ struct gcli_forge_descriptor { /** * Get list of milestones */ int (*get_milestones)( + gcli_ctx *ctx, char const *owner, char const *repo, int max, @@ -173,6 +187,7 @@ struct gcli_forge_descriptor { /** * Get a single milestone */ int (*get_milestone)( + gcli_ctx *ctx, char const *owner, char const *repo, int milestone, @@ -181,11 +196,13 @@ struct gcli_forge_descriptor { /** * create a milestone */ int (*create_milestone)( + gcli_ctx *ctx, struct gcli_milestone_create_args const *args); /** * delete a milestone */ int (*delete_milestone)( + gcli_ctx *ctx, char const *owner, char const *repo, int milestone); @@ -193,6 +210,7 @@ struct gcli_forge_descriptor { /** * delete a milestone */ int (*milestone_set_duedate)( + gcli_ctx *ctx, char const *owner, char const *repo, int milestone, @@ -201,6 +219,7 @@ struct gcli_forge_descriptor { /** * Get list of issues attached to this milestone */ int (*get_milestone_issues)( + gcli_ctx *ctx, char const *owner, char const *repo, int milestone, @@ -208,6 +227,7 @@ struct gcli_forge_descriptor { /** Assign an issue to a milestone */ int (*issue_set_milestone)( + gcli_ctx *ctx, char const *owner, char const *repo, int issue, @@ -216,6 +236,7 @@ struct gcli_forge_descriptor { /** * Clear the milestones of an issue */ int (*issue_clear_milestone)( + gcli_ctx *ctx, char const *owner, char const *repo, int issue); @@ -223,6 +244,7 @@ struct gcli_forge_descriptor { /** * Get a list of PRs/MRs on the given repo */ int (*get_pulls)( + gcli_ctx *ctx, char const *owner, char const *reponame, gcli_pull_fetch_details const *details, @@ -232,6 +254,7 @@ struct gcli_forge_descriptor { /** * Print a diff of the changes of a PR/MR to the stream */ int (*print_pull_diff)( + gcli_ctx *ctx, FILE *stream, char const *owner, char const *reponame, @@ -245,6 +268,7 @@ struct gcli_forge_descriptor { * unify them. For Gitlab this will call into the pipelines code, * for Github into the actions code. */ int (*print_pull_checks)( + gcli_ctx *ctx, char const *owner, char const *reponame, int pr_number); @@ -252,6 +276,7 @@ struct gcli_forge_descriptor { /** * Merge the given PR/MR */ int (*pull_merge)( + gcli_ctx *ctx, char const *owner, char const *reponame, int pr_number, @@ -260,6 +285,7 @@ struct gcli_forge_descriptor { /** * Reopen the given PR/MR */ int (*pull_reopen)( + gcli_ctx *ctx, char const *owner, char const *reponame, int pr_number); @@ -267,6 +293,7 @@ struct gcli_forge_descriptor { /** * Close the given PR/MR */ int (*pull_close)( + gcli_ctx *ctx, char const *owner, char const *reponame, int pr_number); @@ -274,11 +301,13 @@ struct gcli_forge_descriptor { /** * Submit PR/MR */ int (*perform_submit_pull)( + gcli_ctx *ctx, gcli_submit_pull_options opts); /** * Get a list of commits in the given PR/MR */ int (*get_pull_commits)( + gcli_ctx *ctx, char const *owner, char const *repo, int pr_number, @@ -297,6 +326,7 @@ struct gcli_forge_descriptor { /** * Get a summary of the given PR/MR */ int (*get_pull)( + gcli_ctx *ctx, char const *owner, char const *repo, int pr_number, @@ -305,6 +335,7 @@ struct gcli_forge_descriptor { /** * Add labels to Pull Requests */ int (*pull_add_labels)( + gcli_ctx *ctx, char const *owner, char const *repo, int pr, @@ -314,6 +345,7 @@ struct gcli_forge_descriptor { /** * Removes labels from Pull Requests */ int (*pull_remove_labels)( + gcli_ctx *ctx, char const *owner, char const *repo, int pr, @@ -323,6 +355,7 @@ struct gcli_forge_descriptor { /** * Assign a PR to a milestone */ int (*pull_set_milestone)( + gcli_ctx *ctx, char const *owner, char const *repo, int pull, @@ -331,6 +364,7 @@ struct gcli_forge_descriptor { /** * Clear a milestone on a PR */ int (*pull_clear_milestone)( + gcli_ctx *ctx, char const *owner, char const *repo, int pull); @@ -338,6 +372,7 @@ struct gcli_forge_descriptor { /** * Get a list of releases in the given repo */ int (*get_releases)( + gcli_ctx *ctx, char const *owner, char const *repo, int max, @@ -346,11 +381,13 @@ struct gcli_forge_descriptor { /** * Create a new release */ int (*create_release)( + gcli_ctx *ctx, gcli_new_release const *release); /** * Delete the release */ int (*delete_release)( + gcli_ctx *ctx, char const *owner, char const *repo, char const *id); @@ -358,6 +395,7 @@ struct gcli_forge_descriptor { /** * Get a list of labels that are valid in the given repository */ int (*get_labels)( + gcli_ctx *ctx, char const *owner, char const *repo, int max, @@ -368,6 +406,7 @@ struct gcli_forge_descriptor { * * The ID will be filled in for you */ int (*create_label)( + gcli_ctx *ctx, char const *owner, char const *repo, gcli_label *label); @@ -375,6 +414,7 @@ struct gcli_forge_descriptor { /** * Delete the given label */ int (*delete_label)( + gcli_ctx *ctx, char const *owner, char const *repo, char const *label); @@ -382,6 +422,7 @@ struct gcli_forge_descriptor { /** * Get a list of repos of the given owner */ int (*get_repos)( + gcli_ctx *ctx, char const *owner, int max, gcli_repo_list *out); @@ -389,30 +430,34 @@ struct gcli_forge_descriptor { /** * Get a list of your own repos */ int (*get_own_repos)( + gcli_ctx *ctx, int max, gcli_repo_list *out); /** * Create the given repo */ int (*repo_create)( + gcli_ctx *ctx, gcli_repo_create_options const *options, gcli_repo *out); /** * Delete the given repo */ int (*repo_delete)( + gcli_ctx *ctx, char const *owner, char const *repo); /** * Fetch MR/PR reviews including comments */ int (*get_reviews)( - char const *owner, char const *repo, + gcli_ctx *ctx, char const *owner, char const *repo, int pr, gcli_pr_review_list *out); /** * Status summary for the account */ int (*get_notifications)( + gcli_ctx *ctx, gcli_notification **notifications, int count); @@ -421,33 +466,37 @@ struct gcli_forge_descriptor { * * Returns 0 on success or negative code on failure. */ int (*notification_mark_as_read)( + gcli_ctx *ctx, char const *id); /** * Get an the http authentication header for use by curl */ - char *(*get_authheader)(void); + char *(*get_authheader)(gcli_ctx *ctx); /** * Get the user account name */ - sn_sv (*get_account)(void); + sn_sv (*get_account)(gcli_ctx *ctx); /** * Get list of SSH keys */ - int (*get_sshkeys)(gcli_sshkey_list *); + int (*get_sshkeys)(gcli_ctx *ctx, gcli_sshkey_list *); /** * Add an SSH public key */ - int (*add_sshkey)(char const *title, - char const *public_key_path, - gcli_sshkey *out); + int (*add_sshkey)( + gcli_ctx *ctx, + char const *title, + char const *public_key_path, + gcli_sshkey *out); /** * Delete an SSH public key by its ID */ - int (*delete_sshkey)(int id); + int (*delete_sshkey)(gcli_ctx *ctx, int id); /** * Get the error string from the API */ char const *(*get_api_error_string)( + gcli_ctx *ctx, gcli_fetch_buffer *); /** @@ -461,6 +510,6 @@ struct gcli_forge_descriptor { char const *html_url_key; }; -gcli_forge_descriptor const *gcli_forge(void); +gcli_forge_descriptor const *gcli_forge(gcli_ctx *ctx); #endif /* FORGES_H */ diff --git a/include/gcli/forks.h b/include/gcli/forks.h index 675a7c1c..d493d789 100644 --- a/include/gcli/forks.h +++ b/include/gcli/forks.h @@ -52,18 +52,14 @@ struct gcli_fork_list { size_t forks_size; }; -int gcli_get_forks(char const *owner, - char const *reponame, - int max, - gcli_fork_list *out); +int gcli_get_forks(gcli_ctx *ctx, char const *owner, char const *reponame, + int max, gcli_fork_list *out); -int gcli_fork_create(char const *owner, - char const *repo, +int gcli_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, char const *in); -void gcli_print_forks(enum gcli_output_flags flags, - gcli_fork_list const *list, - int max); +void gcli_print_forks(gcli_ctx *ctx, enum gcli_output_flags flags, + gcli_fork_list const *list, int max); void gcli_fork_delete(char const *owner, char const *repo); diff --git a/include/gcli/gcli.h b/include/gcli/gcli.h index 760b4da1..a84c3bf3 100644 --- a/include/gcli/gcli.h +++ b/include/gcli/gcli.h @@ -34,6 +34,10 @@ #include #endif +#ifdef IN_LIBGCLI +#include +#endif /* IN_LIBGCLI */ + enum gcli_output_flags { OUTPUT_SORTED = (1 << 0), OUTPUT_LONG = (1 << 1), @@ -45,4 +49,10 @@ typedef enum gcli_forge_type { GCLI_FORGE_GITEA, } gcli_forge_type; +typedef struct gcli_ctx gcli_ctx; + +char const *gcli_init(gcli_ctx **); +void gcli_destroy(gcli_ctx **ctx); +char const *gcli_get_error(gcli_ctx *ctx); + #endif /* GCLI_H */ diff --git a/include/gcli/gitconfig.h b/include/gcli/gitconfig.h index ad46565a..73eea15c 100644 --- a/include/gcli/gitconfig.h +++ b/include/gcli/gitconfig.h @@ -50,7 +50,7 @@ sn_sv gcli_gitconfig_get_current_branch(void); void gcli_gitconfig_add_fork_remote(char const *org, char const *repo); -int gcli_gitconfig_get_forgetype(char const *remote_name); +int gcli_gitconfig_get_forgetype(gcli_ctx *ctx, char const *remote_name); int gcli_gitconfig_repo_by_remote(char const *remote_name, char const **owner, diff --git a/include/gcli/gitea/comments.h b/include/gcli/gitea/comments.h index 36f8524e..a9491edc 100644 --- a/include/gcli/gitea/comments.h +++ b/include/gcli/gitea/comments.h @@ -37,11 +37,10 @@ #include #include -int gitea_get_comments(char const *owner, char const *repo, +int gitea_get_comments(gcli_ctx *ctx, char const *owner, char const *repo, int issue, gcli_comment_list *out); -int gitea_perform_submit_comment( - gcli_submit_comment_opts opts, - gcli_fetch_buffer *out); +int gitea_perform_submit_comment(gcli_ctx *ctx, gcli_submit_comment_opts opts, + gcli_fetch_buffer *out); #endif /* GITEA_COMMENTS_H */ diff --git a/include/gcli/gitea/config.h b/include/gcli/gitea/config.h index 3b67233b..eefa19c9 100644 --- a/include/gcli/gitea/config.h +++ b/include/gcli/gitea/config.h @@ -34,10 +34,12 @@ #include #endif +#include + #include -char *gitea_get_apibase(void); -char *gitea_get_authheader(void); -sn_sv gitea_get_account(void); +char *gitea_get_apibase(gcli_ctx *ctx); +char *gitea_get_authheader(gcli_ctx *ctx); +sn_sv gitea_get_account(gcli_ctx *ctx); #endif /* GITEA_CONFIG_H */ diff --git a/include/gcli/gitea/forks.h b/include/gcli/gitea/forks.h index df8a074e..e79ebffd 100644 --- a/include/gcli/gitea/forks.h +++ b/include/gcli/gitea/forks.h @@ -36,15 +36,10 @@ #include -int gitea_get_forks( - char const *owner, - char const *repo, - int max, - gcli_fork_list *out); +int gitea_get_forks(gcli_ctx *ctx, char const *owner, char const *repo, + int max, gcli_fork_list *out); -void gitea_fork_create( - char const *owner, - char const *repo, - char const *_in); +void gitea_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, + char const *_in); #endif /* GITEA_FORKS_H */ diff --git a/include/gcli/gitea/issues.h b/include/gcli/gitea/issues.h index b6a9e6c1..4774d950 100644 --- a/include/gcli/gitea/issues.h +++ b/include/gcli/gitea/issues.h @@ -36,52 +36,37 @@ #include -int gitea_get_issues(char const *owner, - char const *reponame, - gcli_issue_fetch_details const *details, - int max, +int gitea_get_issues(gcli_ctx *ctx, char const *owner, char const *reponame, + gcli_issue_fetch_details const *details, int max, gcli_issue_list *out); -int gitea_get_issue_summary(char const *owner, - char const *repo, - int issue, - gcli_issue *out); +int gitea_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, + int issue, gcli_issue *out); -int gitea_submit_issue(gcli_submit_issue_options opts, +int gitea_submit_issue(gcli_ctx *ctx, gcli_submit_issue_options opts, gcli_fetch_buffer *out); -int gitea_issue_close(char const *owner, - char const *repo, +int gitea_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, int issue_number); -int gitea_issue_reopen(char const *owner, - char const *repo, +int gitea_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, int issue_number); -int gitea_issue_assign(char const *owner, - char const *repo, - int issue_number, - char const *assignee); +int gitea_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, + int issue_number, char const *assignee); -int gitea_issue_add_labels(char const *owner, - char const *repo, - int issue, - char const *const labels[], +int gitea_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int issue, char const *const labels[], size_t labels_size); -int gitea_issue_remove_labels(char const *owner, - char const *repo, - int issue, - char const *const labels[], - size_t labels_size); +int gitea_issue_remove_labels(gcli_ctx *ctx, char const *owner, + char const *repo, int issue, + char const *const labels[], size_t labels_size); -int gitea_issue_set_milestone(char const *owner, - char const *repo, - int issue, - int milestone); +int gitea_issue_set_milestone(gcli_ctx *ctx, char const *owner, + char const *repo, int issue, int milestone); -int gitea_issue_clear_milestone(char const *owner, - char const *repo, - int issue); +int gitea_issue_clear_milestone(gcli_ctx *ctx, char const *owner, + char const *repo, int issue); #endif /* GITEA_ISSUES_H */ diff --git a/include/gcli/gitea/labels.h b/include/gcli/gitea/labels.h index 75a82f79..930662ab 100644 --- a/include/gcli/gitea/labels.h +++ b/include/gcli/gitea/labels.h @@ -36,17 +36,13 @@ #include -int gitea_get_labels(char const *owner, - char const *reponame, - int max, - gcli_label_list *out); +int gitea_get_labels(gcli_ctx *ctx, char const *owner, char const *reponame, + int max, gcli_label_list *out); -int gitea_create_label(char const *owner, - char const *repo, +int gitea_create_label(gcli_ctx *ctx, char const *owner, char const *repo, gcli_label *label); -int gitea_delete_label(char const *owner, - char const *repo, +int gitea_delete_label(gcli_ctx *ctx, char const *owner, char const *repo, char const *label); #endif /* GITEA_LABELS_H */ diff --git a/include/gcli/gitea/milestones.h b/include/gcli/gitea/milestones.h index 8bb49047..45bfec28 100644 --- a/include/gcli/gitea/milestones.h +++ b/include/gcli/gitea/milestones.h @@ -32,30 +32,26 @@ #include -int gitea_get_milestones(char const *const owner, - char const *const repo, - int max, +int gitea_get_milestones(gcli_ctx *ctx, char const *const owner, + char const *const repo, int max, gcli_milestone_list *out); -int gitea_get_milestone(char const *const owner, - char const *const repo, - int milestone, +int gitea_get_milestone(gcli_ctx *ctx, char const *const owner, + char const *const repo, int milestone, gcli_milestone *out); -int gitea_create_milestone(struct gcli_milestone_create_args const *args); +int gitea_create_milestone(gcli_ctx *ctx, + struct gcli_milestone_create_args const *args); -int gitea_delete_milestone(char const *owner, - char const *repo, +int gitea_delete_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int milestone); -int gitea_milestone_set_duedate(char const *owner, - char const *repo, - int milestone, +int gitea_milestone_set_duedate(gcli_ctx *ctx, char const *owner, + char const *repo, int milestone, char const *date); -int gitea_milestone_get_issues(char const *owner, - char const *repo, - int milestone, +int gitea_milestone_get_issues(gcli_ctx *ctx, char const *owner, + char const *repo, int milestone, gcli_issue_list *out); #endif /* GCLI_GITEA_MILESTONES_H */ diff --git a/include/gcli/gitea/pulls.h b/include/gcli/gitea/pulls.h index 42dd4992..565d0ee6 100644 --- a/include/gcli/gitea/pulls.h +++ b/include/gcli/gitea/pulls.h @@ -37,53 +37,37 @@ #include #include -int gitea_get_pulls(char const *owner, - char const *reponame, - gcli_pull_fetch_details const *details, - int max, +int gitea_get_pulls(gcli_ctx *ctx, char const *owner, char const *reponame, + gcli_pull_fetch_details const *details, int max, gcli_pull_list *out); -int gitea_get_pull(char const *owner, - char const *repo, - int pr_number, - gcli_pull *out); +int gitea_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, + int pr_number, gcli_pull *out); -int gitea_get_pull_commits(char const *owner, - char const *repo, - int pr_number, - gcli_commit_list *out); +int gitea_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, + int pr_number, gcli_commit_list *out); -int gitea_pull_submit(gcli_submit_pull_options opts); +int gitea_pull_submit(gcli_ctx *ctx, gcli_submit_pull_options opts); -int gitea_pull_merge(char const *owner, - char const *reponame, - int pr_number, - enum gcli_merge_flags flags); +int gitea_pull_merge(gcli_ctx *ctx, char const *owner, char const *reponame, + int pr_number, enum gcli_merge_flags flags); -int gitea_pull_close(char const *owner, - char const *repo, +int gitea_pull_close(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number); -int gitea_pull_reopen(char const *owner, - char const *repo, +int gitea_pull_reopen(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number); -int gitea_print_pr_diff(FILE *stream, - char const *owner, - char const *repo, - int pr_number); +int gitea_print_pr_diff(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *repo, int pr_number); -int gitea_pull_checks(char const *owner, - char const *repo, +int gitea_pull_checks(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number); -int gitea_pull_set_milestone(char const *owner, - char const *repo, - int pr_number, - int milestone_id); +int gitea_pull_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, + int pr_number, int milestone_id); -int gitea_pull_clear_milestone(char const *owner, - char const *repo, - int pr_number); +int gitea_pull_clear_milestone(gcli_ctx *ctx, char const *owner, + char const *repo, int pr_number); #endif /* GITEA_PULLS_H */ diff --git a/include/gcli/gitea/releases.h b/include/gcli/gitea/releases.h index eee3e7dc..1a10ec1d 100644 --- a/include/gcli/gitea/releases.h +++ b/include/gcli/gitea/releases.h @@ -36,15 +36,12 @@ #include -int gitea_get_releases(char const *owner, - char const *repo, - int max, - gcli_release_list *list); +int gitea_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, + int max, gcli_release_list *list); -int gitea_create_release(gcli_new_release const *release); +int gitea_create_release(gcli_ctx *ctx, gcli_new_release const *release); -int gitea_delete_release(char const *owner, - char const *repo, +int gitea_delete_release(gcli_ctx *ctx, char const *owner, char const *repo, char const *id); #endif /* GITEA_RELEASES_H */ diff --git a/include/gcli/gitea/repos.h b/include/gcli/gitea/repos.h index 36894911..77d471af 100644 --- a/include/gcli/gitea/repos.h +++ b/include/gcli/gitea/repos.h @@ -36,17 +36,14 @@ #include -int gitea_get_repos(char const *owner, - int max, +int gitea_get_repos(gcli_ctx *ctx, char const *owner, int max, gcli_repo_list *out); -int gitea_get_own_repos(int max, - gcli_repo_list *out); +int gitea_get_own_repos(gcli_ctx *ctx, int max, gcli_repo_list *out); -int gitea_repo_create(gcli_repo_create_options const *options, +int gitea_repo_create(gcli_ctx *ctx, gcli_repo_create_options const *options, gcli_repo *out); -int gitea_repo_delete(char const *owner, - char const *repo); +int gitea_repo_delete(gcli_ctx *ctx, char const *owner, char const *repo); #endif /* GITEA_REPOS_H */ diff --git a/include/gcli/gitea/sshkeys.h b/include/gcli/gitea/sshkeys.h index 5f047573..04e20f5c 100644 --- a/include/gcli/gitea/sshkeys.h +++ b/include/gcli/gitea/sshkeys.h @@ -32,10 +32,11 @@ #include -int gitea_get_sshkeys(gcli_sshkey_list *out); -int gitea_add_sshkey(char const *title, - char const *public_key_data, - gcli_sshkey *out); -int gitea_delete_sshkey(int id); +int gitea_get_sshkeys(gcli_ctx *ctx, gcli_sshkey_list *out); + +int gitea_add_sshkey(gcli_ctx *ctx, char const *title, + char const *public_key_data, gcli_sshkey *out); + +int gitea_delete_sshkey(gcli_ctx *ctx, int id); #endif /* GCLI_GITEA_SSHKEYS_H */ diff --git a/include/gcli/github/api.h b/include/gcli/github/api.h index fc05d922..d27269ba 100644 --- a/include/gcli/github/api.h +++ b/include/gcli/github/api.h @@ -36,6 +36,6 @@ #include -char const *github_api_error_string(gcli_fetch_buffer *it); +char const *github_api_error_string(gcli_ctx *ctx, gcli_fetch_buffer *it); #endif /* GITHUB_API_H */ diff --git a/include/gcli/github/checks.h b/include/gcli/github/checks.h index 2a10ad57..cb234ecc 100644 --- a/include/gcli/github/checks.h +++ b/include/gcli/github/checks.h @@ -53,17 +53,15 @@ struct gcli_github_checks { size_t checks_size; }; -int github_get_checks(char const *owner, char const *repo, +int github_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, char const *ref, int max, gcli_github_checks *checks); -void github_print_checks(gcli_github_checks const *checks); +void github_print_checks(gcli_ctx *ctx, gcli_github_checks const *checks); void github_free_checks(gcli_github_checks *checks); -int github_checks(char const *owner, - char const *repo, - char const *ref, - int max); +int github_checks(gcli_ctx *ctx, char const *owner, char const *repo, + char const *ref, int max); #endif /* GITHUB_CHECKS_H */ diff --git a/include/gcli/github/comments.h b/include/gcli/github/comments.h index f8690589..bbaf2ddb 100644 --- a/include/gcli/github/comments.h +++ b/include/gcli/github/comments.h @@ -37,13 +37,10 @@ #include #include -int github_perform_submit_comment( - gcli_submit_comment_opts opts, - gcli_fetch_buffer *out); +int github_perform_submit_comment(gcli_ctx *ctx, gcli_submit_comment_opts opts, + gcli_fetch_buffer *out); -int github_get_comments(char const *owner, - char const *repo, - int issue, - gcli_comment_list *out); +int github_get_comments(gcli_ctx *ctx, char const *owner, char const *repo, + int issue, gcli_comment_list *out); #endif /* GITHUB_COMMENTS_H */ diff --git a/include/gcli/github/config.h b/include/gcli/github/config.h index fd3ef68d..e3089666 100644 --- a/include/gcli/github/config.h +++ b/include/gcli/github/config.h @@ -34,10 +34,12 @@ #include #endif +#include + #include -char *github_get_apibase(void); -char *github_get_authheader(void); -sn_sv github_get_account(void); +char *github_get_apibase(gcli_ctx *ctx); +char *github_get_authheader(gcli_ctx *ctx); +sn_sv github_get_account(gcli_ctx *ctx); #endif /* GITHUB_CONFIG_H */ diff --git a/include/gcli/github/forks.h b/include/gcli/github/forks.h index 1ac03b3e..4e02c582 100644 --- a/include/gcli/github/forks.h +++ b/include/gcli/github/forks.h @@ -36,13 +36,10 @@ #include -int github_get_forks(char const *owner, - char const *repo, - int max, - gcli_fork_list *out); +int github_get_forks(gcli_ctx *ctx, char const *owner, char const *repo, + int max, gcli_fork_list *out); -int github_fork_create(char const *owner, - char const *repo, +int github_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, char const *_in); #endif /* GITHUB_FORKS_H */ diff --git a/include/gcli/github/gists.h b/include/gcli/github/gists.h index a1fcad2c..3cbf731d 100644 --- a/include/gcli/github/gists.h +++ b/include/gcli/github/gists.h @@ -74,20 +74,17 @@ struct gcli_new_gist { char const *gist_description; }; -int gcli_get_gists(char const *user, - int max, +int gcli_get_gists(gcli_ctx *ctx, char const *user, int max, gcli_gist_list *list); -gcli_gist *gcli_get_gist(char const *gist_id); +gcli_gist *gcli_get_gist(gcli_ctx *ctx, char const *gist_id); -void gcli_print_gists(enum gcli_output_flags flags, - gcli_gist_list const *list, - int max); +void gcli_print_gists(gcli_ctx *ctx, enum gcli_output_flags flags, + gcli_gist_list const *list, int max); -void gcli_create_gist(gcli_new_gist); +void gcli_create_gist(gcli_ctx *ctx, gcli_new_gist); -void gcli_delete_gist(char const *gist_id, - bool always_yes); +void gcli_delete_gist(gcli_ctx *ctx, char const *gist_id, bool always_yes); void gcli_gists_free(gcli_gist_list *list); @@ -97,6 +94,7 @@ void gcli_gists_free(gcli_gist_list *list); * file names. The objects describing the files obviously contain the * file name again. Whatever...here's a hack. Blame GitHub. */ -void parse_github_gist_files_idiot_hack(json_stream *stream, gcli_gist *gist); +void parse_github_gist_files_idiot_hack(gcli_ctx *ctx, json_stream *stream, + gcli_gist *gist); #endif /* GCLI_GITHUB_GISTS_H */ diff --git a/include/gcli/github/issues.h b/include/gcli/github/issues.h index faca1b51..19782f75 100644 --- a/include/gcli/github/issues.h +++ b/include/gcli/github/issues.h @@ -37,55 +37,40 @@ #include #include -int github_fetch_issues(char *url, - int max, +int github_fetch_issues(gcli_ctx *ctx, char *url, int max, gcli_issue_list *out); -int github_get_issues(char const *owner, - char const *repo, - gcli_issue_fetch_details const *details, - int max, +int github_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_issue_fetch_details const *details, int max, gcli_issue_list *out); -int github_get_issue_summary(char const *owner, - char const *repo, - int issue_number, - gcli_issue *out); +int github_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, + int issue_number, gcli_issue *out); -int github_issue_close(char const *owner, - char const *repo, +int github_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, int issue_number); -int github_issue_reopen(char const *owner, - char const *repo, +int github_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, int issue_number); -int github_perform_submit_issue(gcli_submit_issue_options opts, +int github_perform_submit_issue(gcli_ctx *ctx, gcli_submit_issue_options opts, gcli_fetch_buffer *out); -int github_issue_assign(char const *owner, - char const *repo, - int issue_number, - char const *assignee); +int github_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, + int issue_number, char const *assignee); -int github_issue_add_labels(char const *owner, - char const *repo, - int issue, - char const *const labels[], +int github_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int issue, char const *const labels[], size_t labels_size); -int github_issue_remove_labels(char const *owner, - char const *repo, - int issue, - char const *const labels[], - size_t labels_size); +int github_issue_remove_labels(gcli_ctx *ctx, char const *owner, + char const *repo, int issue, + char const *const labels[], size_t labels_size); -int github_issue_set_milestone(char const *owner, - char const *repo, - int issue, - int milestone); +int github_issue_set_milestone(gcli_ctx *ctx, char const *owner, + char const *repo, int issue, int milestone); + +int github_issue_clear_milestone(gcli_ctx *ctx, char const *owner, + char const *repo, int issue); -int github_issue_clear_milestone(char const *owner, - char const *repo, - int issue); #endif /* GCLI_ISSUES_H */ diff --git a/include/gcli/github/labels.h b/include/gcli/github/labels.h index 1eda3364..1f318a77 100644 --- a/include/gcli/github/labels.h +++ b/include/gcli/github/labels.h @@ -36,17 +36,13 @@ #include -int github_get_labels(char const *owner, - char const *reponame, - int max, - gcli_label_list *out); +int github_get_labels(gcli_ctx *ctx, char const *owner, char const *reponame, + int max, gcli_label_list *out); -int github_create_label(char const *owner, - char const *repo, +int github_create_label(gcli_ctx *ctx, char const *owner, char const *repo, gcli_label *label); -int github_delete_label(char const *owner, - char const *repo, +int github_delete_label(gcli_ctx *ctx, char const *owner, char const *repo, char const *label); #endif /* GITHUB_LABELS_H */ diff --git a/include/gcli/github/milestones.h b/include/gcli/github/milestones.h index 6fb8be4e..c17fb40b 100644 --- a/include/gcli/github/milestones.h +++ b/include/gcli/github/milestones.h @@ -32,30 +32,24 @@ #include -int github_get_milestones(char const *owner, - char const *repo, - int max, - gcli_milestone_list *out); +int github_get_milestones(gcli_ctx *ctx, char const *owner, char const *repo, + int max, gcli_milestone_list *out); -int github_get_milestone(char const *owner, - char const *repo, - int milestone, - gcli_milestone *out); +int github_get_milestone(gcli_ctx *ctx, char const *owner, char const *repo, + int milestone, gcli_milestone *out); -int github_create_milestone(struct gcli_milestone_create_args const *args); +int github_create_milestone(gcli_ctx *ctx, + struct gcli_milestone_create_args const *args); -int github_delete_milestone(char const *owner, - char const *repo, +int github_delete_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int milestone); -int github_milestone_get_issues(char const *owner, - char const *repo, - int milestone, +int github_milestone_get_issues(gcli_ctx *ctx, char const *owner, + char const *repo, int milestone, gcli_issue_list *out); -int github_milestone_set_duedate(char const *owner, - char const *repo, - int milestone, +int github_milestone_set_duedate(gcli_ctx *ctx, char const *owner, + char const *repo, int milestone, char const *date); #endif /* GCLI_GITHUB_MILESTONES_H */ diff --git a/include/gcli/github/pulls.h b/include/gcli/github/pulls.h index 6a22ae03..dbe1ede2 100644 --- a/include/gcli/github/pulls.h +++ b/include/gcli/github/pulls.h @@ -37,48 +37,35 @@ #include #include -int github_fetch_pulls(char *url, - char const *filter_author, - int max, - gcli_pull_list *list); +int github_fetch_pulls(gcli_ctx *ctx, char *url, char const *filter_author, + int max, gcli_pull_list *list); -int github_get_pulls(char const *owner, - char const *reponame, - gcli_pull_fetch_details const *details, - int max, +int github_get_pulls(gcli_ctx *ctx, char const *owner, char const *reponame, + gcli_pull_fetch_details const *details, int max, gcli_pull_list *out); -int github_print_pull_diff(FILE *stream, - char const *owner, - char const *reponame, - int pr_number); +int github_print_pull_diff(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *reponame, int pr_number); -int github_pull_checks(char const *owner, - char const *repo, +int github_pull_checks(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number); -int github_pull_merge(char const *owner, - char const *reponame, - int pr_number, - enum gcli_merge_flags flags); +int github_pull_merge(gcli_ctx *ctx, char const *owner, char const *reponame, + int pr_number, enum gcli_merge_flags flags); -int github_pull_reopen(char const *owner, - char const *reponame, +int github_pull_reopen(gcli_ctx *ctx, char const *owner, char const *reponame, int pr_number); -int github_pull_close(char const *owner, - char const *reponame, +int github_pull_close(gcli_ctx *ctx, char const *owner, char const *reponame, int pr_number); -int github_perform_submit_pull(gcli_submit_pull_options opts); +int github_perform_submit_pull(gcli_ctx *ctx, gcli_submit_pull_options opts); -int github_get_pull_commits(char const *owner, char const *repo, +int github_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number, gcli_commit_list *out); -int github_get_pull(char const *owner, - char const *repo, - int pr_number, - gcli_pull *out); +int github_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, + int pr_number, gcli_pull *out); sn_sv github_pull_try_derive_head(void); diff --git a/include/gcli/github/releases.h b/include/gcli/github/releases.h index 36ff16fa..526dee02 100644 --- a/include/gcli/github/releases.h +++ b/include/gcli/github/releases.h @@ -36,15 +36,12 @@ #include -int github_get_releases(char const *owner, - char const *repo, - int max, - gcli_release_list *list); +int github_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, + int max, gcli_release_list *list); -int github_create_release(gcli_new_release const *release); +int github_create_release(gcli_ctx *ctx, gcli_new_release const *release); -int github_delete_release(char const *owner, - char const *repo, +int github_delete_release(gcli_ctx *ctx, char const *owner, char const *repo, char const *id); #endif /* GITHUB_RELEASES_H */ diff --git a/include/gcli/github/repos.h b/include/gcli/github/repos.h index fb318c52..c6f21ce0 100644 --- a/include/gcli/github/repos.h +++ b/include/gcli/github/repos.h @@ -36,17 +36,14 @@ #include -int github_get_repos(char const *owner, - int max, +int github_get_repos(gcli_ctx *ctx, char const *owner, int max, gcli_repo_list *out); -int github_get_own_repos(int max, - gcli_repo_list *out); +int github_get_own_repos(gcli_ctx *ctx, int max, gcli_repo_list *out); -int github_repo_delete(char const *owner, - char const *repo); +int github_repo_delete(gcli_ctx *ctx, char const *owner, char const *repo); -int github_repo_create(gcli_repo_create_options const *options, +int github_repo_create(gcli_ctx *ctx, gcli_repo_create_options const *options, gcli_repo *out); #endif /* GITHUB_REPOS_H */ diff --git a/include/gcli/github/review.h b/include/gcli/github/review.h index 92399b62..e2ce0b5a 100644 --- a/include/gcli/github/review.h +++ b/include/gcli/github/review.h @@ -36,7 +36,8 @@ #include -int github_review_get_reviews(char const *owner, char const *repo, - int pr, gcli_pr_review_list *out); +int github_review_get_reviews(gcli_ctx *ctx, char const *owner, + char const *repo, int pr, + gcli_pr_review_list *out); #endif /* GITHUB_REVIEW_H */ diff --git a/include/gcli/github/sshkeys.h b/include/gcli/github/sshkeys.h index a68144eb..584ea43b 100644 --- a/include/gcli/github/sshkeys.h +++ b/include/gcli/github/sshkeys.h @@ -32,10 +32,11 @@ #include -int github_get_sshkeys(gcli_sshkey_list *out); -int github_add_sshkey(char const *const title, - char const *const pubkey, - gcli_sshkey *out); -int github_delete_sshkey(int id); +int github_get_sshkeys(gcli_ctx *ctx, gcli_sshkey_list *out); + +int github_add_sshkey(gcli_ctx *ctx, char const *const title, + char const *const pubkey, gcli_sshkey *out); + +int github_delete_sshkey(gcli_ctx *ctx, int id); #endif /* GCLI_GITHUB_SSHKEYS_H */ diff --git a/include/gcli/github/status.h b/include/gcli/github/status.h index 2319dd11..fea2de88 100644 --- a/include/gcli/github/status.h +++ b/include/gcli/github/status.h @@ -36,8 +36,9 @@ #include -int github_get_notifications(gcli_notification **notifications, int count); +int github_get_notifications(gcli_ctx *ctx, + gcli_notification **notifications, int count); -int github_notification_mark_as_read(char const *id); +int github_notification_mark_as_read(gcli_ctx *ctx, char const *id); #endif /* GITHUB_STATUS_H */ diff --git a/include/gcli/gitlab/api.h b/include/gcli/gitlab/api.h index b0a8b24d..0de731a1 100644 --- a/include/gcli/gitlab/api.h +++ b/include/gcli/gitlab/api.h @@ -36,6 +36,6 @@ #include -char const *gitlab_api_error_string(gcli_fetch_buffer *buf); +char const *gitlab_api_error_string(gcli_ctx *ctx, gcli_fetch_buffer *buf); #endif /* GITLAB_API_H */ diff --git a/include/gcli/gitlab/comments.h b/include/gcli/gitlab/comments.h index 557335b6..fcee4621 100644 --- a/include/gcli/gitlab/comments.h +++ b/include/gcli/gitlab/comments.h @@ -37,13 +37,14 @@ #include #include -int gitlab_perform_submit_comment(gcli_submit_comment_opts opts, +int gitlab_perform_submit_comment(gcli_ctx *ctx, gcli_submit_comment_opts opts, gcli_fetch_buffer *out); -int gitlab_get_issue_comments(char const *owner, char const *repo, - int issue, gcli_comment_list *out); +int gitlab_get_issue_comments(gcli_ctx *ctx, char const *owner, + char const *repo, int issue, + gcli_comment_list *out); -int gitlab_get_mr_comments(char const *owner, char const *repo, +int gitlab_get_mr_comments(gcli_ctx *ctx, char const *owner, char const *repo, int issue, gcli_comment_list *out); #endif /* GITLAB_COMMENTS_H */ diff --git a/include/gcli/gitlab/config.h b/include/gcli/gitlab/config.h index f94527a3..693e29ae 100644 --- a/include/gcli/gitlab/config.h +++ b/include/gcli/gitlab/config.h @@ -36,8 +36,10 @@ #include -char *gitlab_get_apibase(void); -char *gitlab_get_authheader(void); -sn_sv gitlab_get_account(void); +#include + +char *gitlab_get_apibase(gcli_ctx *ctx); +char *gitlab_get_authheader(gcli_ctx *ctx); +sn_sv gitlab_get_account(gcli_ctx *ctx); #endif /* GITLAB_CONFIG_H */ diff --git a/include/gcli/gitlab/forks.h b/include/gcli/gitlab/forks.h index ec596186..5bc49269 100644 --- a/include/gcli/gitlab/forks.h +++ b/include/gcli/gitlab/forks.h @@ -36,13 +36,10 @@ #include -int gitlab_get_forks(char const *owner, - char const *repo, - int max, - gcli_fork_list *out); +int gitlab_get_forks(gcli_ctx *ctx, char const *owner, char const *repo, + int max, gcli_fork_list *out); -int gitlab_fork_create(char const *owner, - char const *repo, +int gitlab_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, char const *_in); #endif /* GITLAB_FORKS_H */ diff --git a/include/gcli/gitlab/issues.h b/include/gcli/gitlab/issues.h index 42e65aa2..1c61e8d8 100644 --- a/include/gcli/gitlab/issues.h +++ b/include/gcli/gitlab/issues.h @@ -37,56 +37,40 @@ #include #include -int gitlab_fetch_issues(char *url, - int max, +int gitlab_fetch_issues(gcli_ctx *ctx, char *url, int max, gcli_issue_list *out); -int gitlab_get_issues(char const *owner, - char const *repo, - gcli_issue_fetch_details const *details, - int max, +int gitlab_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_issue_fetch_details const *details, int max, gcli_issue_list *out); -int gitlab_get_issue_summary(char const *owner, - char const *repo, - int issue_number, - gcli_issue *out); +int gitlab_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, + int issue_number, gcli_issue *out); -int gitlab_issue_close(char const *owner, - char const *repo, +int gitlab_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, int issue_number); -int gitlab_issue_reopen(char const *owner, - char const *repo, +int gitlab_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, int issue_number); -int gitlab_issue_assign(char const *owner, - char const *repo, - int issue_number, - char const *assignee); +int gitlab_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, + int issue_number, char const *assignee); -int gitlab_perform_submit_issue(gcli_submit_issue_options opts, +int gitlab_perform_submit_issue(gcli_ctx *ctx, gcli_submit_issue_options opts, gcli_fetch_buffer *out); -int gitlab_issue_add_labels(char const *owner, - char const *repo, - int issue, - char const *const labels[], +int gitlab_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int issue, char const *const labels[], size_t labels_size); -int gitlab_issue_remove_labels(char const *owner, - char const *repo, - int issue, - char const *const labels[], - size_t labels_size); +int gitlab_issue_remove_labels(gcli_ctx *ctx, char const *owner, + char const *repo, int issue, + char const *const labels[], size_t labels_size); -int gitlab_issue_set_milestone(char const *owner, - char const *repo, - int issue, - int milestone); +int gitlab_issue_set_milestone(gcli_ctx *ctx, char const *owner, + char const *repo, int issue, int milestone); -int gitlab_issue_clear_milestone(char const *owner, - char const *repo, - int issue); +int gitlab_issue_clear_milestone(gcli_ctx *ctx, char const *owner, + char const *repo, int issue); #endif /* GITLAB_ISSUES_H */ diff --git a/include/gcli/gitlab/labels.h b/include/gcli/gitlab/labels.h index 43bcf652..e0323327 100644 --- a/include/gcli/gitlab/labels.h +++ b/include/gcli/gitlab/labels.h @@ -36,17 +36,13 @@ #include -int gitlab_get_labels(char const *owner, - char const *reponame, - int max, - gcli_label_list *out); +int gitlab_get_labels(gcli_ctx *ctx, char const *owner, char const *reponame, + int max, gcli_label_list *out); -int gitlab_create_label(char const *owner, - char const *repo, +int gitlab_create_label(gcli_ctx *ctx, char const *owner, char const *repo, gcli_label *label); -int gitlab_delete_label(char const *owner, - char const *repo, +int gitlab_delete_label(gcli_ctx *ctx, char const *owner, char const *repo, char const *label); #endif /* GITLAB_LABELS_H */ diff --git a/include/gcli/gitlab/merge_requests.h b/include/gcli/gitlab/merge_requests.h index 53dec57d..bc2a48e4 100644 --- a/include/gcli/gitlab/merge_requests.h +++ b/include/gcli/gitlab/merge_requests.h @@ -36,63 +36,47 @@ #include -int gitlab_fetch_mrs(char *url, - int max, +int gitlab_fetch_mrs(gcli_ctx *ctx, char *url, int max, gcli_pull_list *list); -int gitlab_get_mrs(char const *owner, +int gitlab_get_mrs(gcli_ctx *ctx, char const *owner, char const *reponame, gcli_pull_fetch_details const *details, int max, gcli_pull_list *out); -int gitlab_print_pr_diff(FILE *stream, - char const *owner, - char const *reponame, - int pr_number); +int gitlab_print_pr_diff(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *reponame, int pr_number); -int gitlab_mr_merge(char const *owner, - char const *reponame, - int mr_number, - enum gcli_merge_flags flags); +int gitlab_mr_merge(gcli_ctx *ctx, char const *owner, char const *reponame, + int mr_number, enum gcli_merge_flags flags); -int gitlab_mr_close(char const *owner, - char const *reponame, +int gitlab_mr_close(gcli_ctx *ctx, char const *owner, char const *reponame, int pr_number); -int gitlab_mr_reopen(char const *owner, - char const *reponame, +int gitlab_mr_reopen(gcli_ctx *ctx, char const *owner, char const *reponame, int pr_number); -int gitlab_get_pull(char const *owner, - char const *repo, - int pr_number, - gcli_pull *out); +int gitlab_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, + int pr_number, gcli_pull *out); -int gitlab_get_pull_commits(char const *owner, char const *repo, +int gitlab_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number, gcli_commit_list *out); -int gitlab_perform_submit_mr(gcli_submit_pull_options opts); +int gitlab_perform_submit_mr(gcli_ctx *ctx, gcli_submit_pull_options opts); -int gitlab_mr_add_labels(char const *owner, - char const *repo, - int mr, - char const *const labels[], +int gitlab_mr_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int mr, char const *const labels[], size_t labels_size); -int gitlab_mr_remove_labels(char const *owner, - char const *repo, - int mr, - char const *const labels[], +int gitlab_mr_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int mr, char const *const labels[], size_t labels_size); -int gitlab_mr_set_milestone(char const *owner, - char const *repo, - int mr, - int milestone_id); +int gitlab_mr_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, + int mr, int milestone_id); -int gitlab_mr_clear_milestone(char const *owner, - char const *repo, - int mr); +int gitlab_mr_clear_milestone(gcli_ctx *ctx, char const *owner, + char const *repo, int mr); #endif /* GITLAB_MERGE_REQUESTS_H */ diff --git a/include/gcli/gitlab/milestones.h b/include/gcli/gitlab/milestones.h index ce153725..597bea54 100644 --- a/include/gcli/gitlab/milestones.h +++ b/include/gcli/gitlab/milestones.h @@ -36,30 +36,24 @@ #include -int gitlab_get_milestones(char const *owner, - char const *repo, - int max, - gcli_milestone_list *const out); +int gitlab_get_milestones(gcli_ctx *ctx, char const *owner, char const *repo, + int max, gcli_milestone_list *const out); -int gitlab_create_milestone(struct gcli_milestone_create_args const *args); +int gitlab_create_milestone(gcli_ctx *ctx, + struct gcli_milestone_create_args const *args); -int gitlab_delete_milestone(char const *owner, - char const *repo, - int milestone); +int gitlab_delete_milestone(gcli_ctx *ctx, char const *owner, + char const *repo, int milestone); -int gitlab_get_milestone(char const *owner, - char const *repo, - int milestone, - gcli_milestone *out); +int gitlab_get_milestone(gcli_ctx *ctx, char const *owner, char const *repo, + int milestone, gcli_milestone *out); -int gitlab_milestone_get_issues(char const *owner, - char const *repo, - int milestone, +int gitlab_milestone_get_issues(gcli_ctx *ctx, char const *owner, + char const *repo, int milestone, gcli_issue_list *out); -int gitlab_milestone_set_duedate(char const *owner, - char const *repo, - int milestone, +int gitlab_milestone_set_duedate(gcli_ctx *ctx, char const *owner, + char const *repo, int milestone, char const *date); #endif /* GCLI_GITLAB_MILESTONES_H */ diff --git a/include/gcli/gitlab/pipelines.h b/include/gcli/gitlab/pipelines.h index fa2bf0ab..b46d6824 100644 --- a/include/gcli/gitlab/pipelines.h +++ b/include/gcli/gitlab/pipelines.h @@ -73,57 +73,45 @@ struct gitlab_job_list { size_t jobs_size; }; -int gitlab_get_pipelines(char const *owner, - char const *repo, - int max, - gitlab_pipeline_list *out); +int gitlab_get_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, + int max, gitlab_pipeline_list *out); -void gitlab_print_pipelines(gitlab_pipeline_list const *list); +void gitlab_print_pipelines(gcli_ctx *ctx, gitlab_pipeline_list const *list); void gitlab_free_pipelines(gitlab_pipeline_list *list); -void gitlab_pipelines(char const *owner, - char const *repo, +void gitlab_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, int count); -void gitlab_pipeline_jobs(char const *owner, - char const *repo, - long pipeline, - int count); +void gitlab_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, + long pipeline, int count); -int gitlab_get_pipeline_jobs(char const *owner, char const *repo, - long pipeline, int count, - gitlab_job_list *out); +int gitlab_get_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, + long pipeline, int count, gitlab_job_list *out); -void gitlab_print_jobs(gitlab_job_list const *jobs); +void gitlab_print_jobs(gcli_ctx *ctx, gitlab_job_list const *jobs); void gitlab_free_jobs(gitlab_job_list *jobs); void gitlab_free_job(gitlab_job *job); -int gitlab_job_get_log(char const *owner, - char const *repo, +int gitlab_job_get_log(gcli_ctx *ctx, char const *owner, char const *repo, long job_id); -int gitlab_job_status(char const *owner, - char const *repo, +int gitlab_job_status(gcli_ctx *ctx, char const *owner, char const *repo, long job_id); -int gitlab_job_cancel(char const *owner, - char const *repo, +int gitlab_job_cancel(gcli_ctx *ctx, char const *owner, char const *repo, long job_id); -int gitlab_job_retry(char const *owner, - char const *repo, +int gitlab_job_retry(gcli_ctx *ctx, char const *owner, char const *repo, long job_id); -int gitlab_mr_pipelines(char const *owner, - char const *repo, +int gitlab_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, int mr_id); -int gitlab_job_download_artifacts(char const *owner, - char const *repo, - long jid, +int gitlab_job_download_artifacts(gcli_ctx *ctx, char const *owner, + char const *repo, long jid, char const *outfile); #endif /* GITLAB_PIPELINES_H */ diff --git a/include/gcli/gitlab/releases.h b/include/gcli/gitlab/releases.h index 3367bde6..cf497774 100644 --- a/include/gcli/gitlab/releases.h +++ b/include/gcli/gitlab/releases.h @@ -36,15 +36,12 @@ #include -int gitlab_get_releases(char const *owner, - char const *repo, - int max, - gcli_release_list *list); +int gitlab_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, + int max, gcli_release_list *list); -int gitlab_create_release(gcli_new_release const *release); +int gitlab_create_release(gcli_ctx *ctx, gcli_new_release const *release); -int gitlab_delete_release(char const *owner, - char const *repo, +int gitlab_delete_release(gcli_ctx *ctx, char const *owner, char const *repo, char const *id); #endif /* GITLAB_RELEASES_H */ diff --git a/include/gcli/gitlab/repos.h b/include/gcli/gitlab/repos.h index c1c871d6..8cb64e87 100644 --- a/include/gcli/gitlab/repos.h +++ b/include/gcli/gitlab/repos.h @@ -36,20 +36,17 @@ #include -int gitlab_get_repo(char const *owner, - char const *repo, +int gitlab_get_repo(gcli_ctx *ctx, char const *owner, char const *repo, gcli_repo *out); -int gitlab_get_repos(char const *owner, - int max, +int gitlab_get_repos(gcli_ctx *ctx, char const *owner, int max, gcli_repo_list *out); -int gitlab_get_own_repos(int max, gcli_repo_list *out); +int gitlab_get_own_repos(gcli_ctx *ctx, int max, gcli_repo_list *out); -int gitlab_repo_delete(char const *owner, - char const *repo); +int gitlab_repo_delete(gcli_ctx *ctx, char const *owner, char const *repo); -int gitlab_repo_create(gcli_repo_create_options const *options, +int gitlab_repo_create(gcli_ctx *ctx, gcli_repo_create_options const *options, gcli_repo *out); #endif /* GITLAB_REPOS_H */ diff --git a/include/gcli/gitlab/review.h b/include/gcli/gitlab/review.h index 75c5f840..3d2a7bed 100644 --- a/include/gcli/gitlab/review.h +++ b/include/gcli/gitlab/review.h @@ -36,7 +36,8 @@ #include -int gitlab_review_get_reviews(char const *owner, char const *repo, - int pr, gcli_pr_review_list *out); +int gitlab_review_get_reviews(gcli_ctx *cxt, char const *owner, + char const *repo, int pr, + gcli_pr_review_list *out); #endif /* GITLAB_REVIEW_H */ diff --git a/include/gcli/gitlab/snippets.h b/include/gcli/gitlab/snippets.h index 201a67cd..d766a6a7 100644 --- a/include/gcli/gitlab/snippets.h +++ b/include/gcli/gitlab/snippets.h @@ -56,14 +56,13 @@ struct gcli_snippet_list { void gcli_snippets_free(gcli_snippet_list *list); -int gcli_snippets_get(int max, gcli_snippet_list *out); +int gcli_snippets_get(gcli_ctx *ctx, int max, gcli_snippet_list *out); -void gcli_snippets_print(enum gcli_output_flags flags, - gcli_snippet_list const *list, - int max); +void gcli_snippets_print(gcli_ctx *ctx, enum gcli_output_flags flags, + gcli_snippet_list const *list, int max); -int gcli_snippet_delete(char const *snippet_id); +int gcli_snippet_delete(gcli_ctx *ctx, char const *snippet_id); -int gcli_snippet_get(char const *snippet_id); +int gcli_snippet_get(gcli_ctx *ctx, char const *snippet_id); #endif /* GITLAB_SNIPPETS_H */ diff --git a/include/gcli/gitlab/sshkeys.h b/include/gcli/gitlab/sshkeys.h index a0e78521..5a5b7b6e 100644 --- a/include/gcli/gitlab/sshkeys.h +++ b/include/gcli/gitlab/sshkeys.h @@ -36,10 +36,11 @@ #include -int gitlab_get_sshkeys(gcli_sshkey_list *list); -int gitlab_add_sshkey(char const *const title, - char const *const pubkey, - gcli_sshkey *const out); -int gitlab_delete_sshkey(int id); +int gitlab_get_sshkeys(gcli_ctx *ctx, gcli_sshkey_list *list); + +int gitlab_add_sshkey(gcli_ctx *ctx, char const *const title, + char const *const pubkey, gcli_sshkey *const out); + +int gitlab_delete_sshkey(gcli_ctx *ctx, int id); #endif /* GCLI_GITLAB_SSHKEYS_H */ diff --git a/include/gcli/gitlab/status.h b/include/gcli/gitlab/status.h index 120f58f0..e7887340 100644 --- a/include/gcli/gitlab/status.h +++ b/include/gcli/gitlab/status.h @@ -36,8 +36,9 @@ #include -int gitlab_get_notifications(gcli_notification **notifications, int count); +int gitlab_get_notifications(gcli_ctx *ctx, gcli_notification **notifications, + int count); -int gitlab_notification_mark_as_read(char const *id); +int gitlab_notification_mark_as_read(gcli_ctx *ctx, char const *id); #endif /* GITLAB_STATUS_H */ diff --git a/include/gcli/issues.h b/include/gcli/issues.h index 6a6faf95..0ea47793 100644 --- a/include/gcli/issues.h +++ b/include/gcli/issues.h @@ -80,60 +80,46 @@ struct gcli_issue_fetch_details { char const *author; /* A username who issued */ }; -int gcli_get_issues(char const *owner, - char const *reponame, - gcli_issue_fetch_details const *details, - int max, +int gcli_get_issues(gcli_ctx *ctx, char const *owner, char const *reponame, + gcli_issue_fetch_details const *details, int max, gcli_issue_list *out); void gcli_issues_free(gcli_issue_list *); -void gcli_print_issues_table(enum gcli_output_flags flags, - gcli_issue_list const *list, - int max); +void gcli_print_issues_table(gcli_ctx *ctx, enum gcli_output_flags flags, + gcli_issue_list const *list, int max); -int gcli_get_issue(char const *owner, char const *reponame, +int gcli_get_issue(gcli_ctx *ctx, char const *owner, char const *reponame, int issue_number, gcli_issue *out); void gcli_issue_free(gcli_issue *it); -void gcli_issue_print_summary(gcli_issue const *it); +void gcli_issue_print_summary(gcli_ctx *ctx, gcli_issue const *it); void gcli_issue_print_op(gcli_issue const *it); -int gcli_issue_close(char const *owner, - char const *repo, +int gcli_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, int issue_number); -int gcli_issue_reopen(char const *owner, - char const *repo, +int gcli_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, int issue_number); -int gcli_issue_submit(gcli_submit_issue_options); +int gcli_issue_submit(gcli_ctx *ctx, gcli_submit_issue_options); -int gcli_issue_assign(char const *owner, - char const *repo, - int issue_number, - char const *assignee); +int gcli_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, + int issue_number, char const *assignee); -int gcli_issue_add_labels(char const *owner, - char const *repo, - int issue_number, - char const *const labels[], +int gcli_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int issue_number, char const *const labels[], size_t labels_size); -int gcli_issue_remove_labels(char const *owner, - char const *repo, - int issue_number, - char const *const labels[], +int gcli_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int issue_number, char const *const labels[], size_t labels_size); -int gcli_issue_set_milestone(char const *owner, - char const *repo, - int issue, - int milestone); +int gcli_issue_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, + int issue, int milestone); -int gcli_issue_clear_milestone(char const *owner, - char const *repo, - int issue); +int gcli_issue_clear_milestone(gcli_ctx *cxt, char const *owner, + char const *repo, int issue); #endif /* ISSUES_H */ diff --git a/include/gcli/json_util.h b/include/gcli/json_util.h index 18fc230e..fa8bedeb 100644 --- a/include/gcli/json_util.h +++ b/include/gcli/json_util.h @@ -42,47 +42,48 @@ #include -#define get_int(input) get_int_(input, __func__) -#define get_double(input) get_double_(input, __func__) -#define get_parse_int(input) get_parse_int_(input, __func__) -#define get_bool(input) get_bool_(input, __func__) -#define get_string(input) get_string_(input, __func__) -#define get_sv(input) get_sv_(input, __func__) -#define get_user(input) get_user_(input, __func__) -#define get_label(input) get_label_(input, __func__) -#define get_is_string(input) (json_next(input) == JSON_STRING) -#define get_int_to_sv(input) (sn_sv_fmt("%ld", get_int(input))) -#define get_int_to_string(input) (sn_asprintf("%ld", get_int(input))) +#define get_int(ctx, input) get_int_(ctx, input, __func__) +#define get_double(ctx, input) get_double_(ctx, input, __func__) +#define get_parse_int(ctx, input) get_parse_int_(ctx, input, __func__) +#define get_bool(ctx, input) get_bool_(ctx, input, __func__) +#define get_string(ctx, input) get_string_(ctx, input, __func__) +#define get_sv(ctx, input) get_sv_(ctx, input, __func__) +#define get_user(ctx, input) get_user_(ctx, input, __func__) +#define get_label(ctx, input) get_label_(ctx, input, __func__) +#define get_is_string(ctx, input) ((void)ctx, json_next(input) == JSON_STRING) +#define get_int_to_sv(ctx, input) (sn_sv_fmt("%ld", get_int(ctx, input))) +#define get_int_to_string(ctx, input) (sn_asprintf("%ld", get_int(ctx, input))) -long get_int_(json_stream *input, char const *function); -double get_double_(json_stream *input, char const *function); -long get_parse_int_(json_stream *input, char const *function); -bool get_bool_(json_stream *input, char const *function); -char *get_string_(json_stream *input, char const *function); -sn_sv get_sv_(json_stream *input, char const *function); -char *get_user_(json_stream *input, char const *function); +long get_int_(gcli_ctx *ctx, json_stream *input, char const *function); +double get_double_(gcli_ctx *ctx, json_stream *input, char const *function); +long get_parse_int_(gcli_ctx *ctx, json_stream *input, + char const *function); +bool get_bool_(gcli_ctx *ctx, json_stream *input, char const *function); +char *get_string_(gcli_ctx *ctx, json_stream *input, char const *function); +sn_sv get_sv_(gcli_ctx *ctx, json_stream *input, char const *function); +char *get_user_(gcli_ctx *ctx, json_stream *input, char const *function); char const *get_label_(json_stream *input, char const *function); sn_sv gcli_json_escape(sn_sv); #define gcli_json_escape_cstr(x) (gcli_json_escape(SV((char *)(x))).data) -void gcli_print_html_url(gcli_fetch_buffer); +void gcli_print_html_url(gcli_ctx *, gcli_fetch_buffer); void gcli_json_advance(json_stream *input, char const *fmt, ...); -uint32_t get_github_style_colour(json_stream *input); -uint32_t get_gitlab_style_colour(json_stream *input); -int get_github_is_pr(json_stream *input); -bool get_gitlab_can_be_merged(json_stream *input); -sn_sv get_gitea_visibility(json_stream *input); +uint32_t get_github_style_colour(gcli_ctx *ctx, json_stream *input); +uint32_t get_gitlab_style_colour(gcli_ctx *ctx, json_stream *input); +int get_github_is_pr(gcli_ctx *ctx, json_stream *input); +bool get_gitlab_can_be_merged(gcli_ctx *ctx, json_stream *input); +sn_sv get_gitea_visibility(gcli_ctx *ctx, json_stream *input); static inline sn_sv -get_user_sv(json_stream *input) +get_user_sv(gcli_ctx *ctx, json_stream *input) { - char *user_str = (char *)get_user(input); + char *user_str = (char *)get_user(ctx, input); return SV(user_str); } static inline void -parse_user(json_stream *input, sn_sv *out) +parse_user(gcli_ctx *ctx, json_stream *input, sn_sv *out) { - *out = get_user_sv(input); + *out = get_user_sv(ctx, input); } static inline char const * @@ -108,9 +109,10 @@ gcli_json_bool(bool it) } while (0) static inline void -parse_sv(json_stream *stream, sn_sv *out) +parse_sv(gcli_ctx *ctx, json_stream *stream, sn_sv *out) { - *out = get_sv(stream); + (void) *ctx; + *out = get_sv(ctx, stream); } #endif /* JSON_UTIL_H */ diff --git a/include/gcli/labels.h b/include/gcli/labels.h index 922e26af..2088e0ff 100644 --- a/include/gcli/labels.h +++ b/include/gcli/labels.h @@ -38,6 +38,8 @@ #include #include +#include + typedef struct gcli_label gcli_label; typedef struct gcli_label_list gcli_label_list; @@ -53,24 +55,19 @@ struct gcli_label_list { size_t labels_size; }; -int gcli_get_labels(char const *owner, - char const *reponame, - int max, - gcli_label_list *out); +int gcli_get_labels(gcli_ctx *ctx, char const *owner, char const *reponame, + int max, gcli_label_list *out); void gcli_free_label(gcli_label *label); void gcli_free_labels(gcli_label_list *labels); -void gcli_print_labels(gcli_label_list const *list, - int max); +void gcli_print_labels(gcli_ctx *ctx, gcli_label_list const *list, int max); -int gcli_create_label(char const *owner, - char const *repo, +int gcli_create_label(gcli_ctx *ctx, char const *owner, char const *repo, gcli_label *label); -int gcli_delete_label(char const *owner, - char const *repo, +int gcli_delete_label(gcli_ctx *ctx, char const *owner, char const *repo, char const *label); #endif /* LABELS_H */ diff --git a/include/gcli/milestones.h b/include/gcli/milestones.h index 0f91319e..865ae0f8 100644 --- a/include/gcli/milestones.h +++ b/include/gcli/milestones.h @@ -74,38 +74,32 @@ struct gcli_milestone_create_args { char const *repo; }; -int gcli_get_milestones(char const *owner, - char const *repo, - int max, - gcli_milestone_list *out); +int gcli_get_milestones(gcli_ctx *ctx, char const *owner, char const *repo, + int max, gcli_milestone_list *out); -int gcli_get_milestone(char const *owner, - char const *repo, - int max, - gcli_milestone *out); +int gcli_get_milestone(gcli_ctx *ctx, char const *owner, char const *repo, + int max, gcli_milestone *out); -int gcli_create_milestone(struct gcli_milestone_create_args const *args); +int gcli_create_milestone(gcli_ctx *ctx, + struct gcli_milestone_create_args const *args); -int gcli_delete_milestone(char const *owner, - char const *repo, +int gcli_delete_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int milestone); -void gcli_print_milestones(gcli_milestone_list const *it, +void gcli_print_milestones(gcli_ctx *ctx, gcli_milestone_list const *it, int max); -void gcli_print_milestone(gcli_milestone const *it); +void gcli_print_milestone(gcli_ctx *ctx, gcli_milestone const *it); void gcli_free_milestone(gcli_milestone *it); void gcli_free_milestones(gcli_milestone_list *it); -int gcli_milestone_get_issues(char const *owner, - char const *repo, - int milestone, +int gcli_milestone_get_issues(gcli_ctx *ctx, char const *owner, + char const *repo, int milestone, gcli_issue_list *out); -int gcli_milestone_set_duedate(char const *owner, - char const *repo, - int milestone, +int gcli_milestone_set_duedate(gcli_ctx *ctx, char const *owner, + char const *repo, int milestone, char const *date); #endif /* GCLI_MILESTONES_H */ diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index a9cf9992..363ff31f 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -106,39 +106,32 @@ struct gcli_pull_fetch_details { char const *author; }; -int gcli_get_pulls(char const *owner, - char const *reponame, - gcli_pull_fetch_details const *details, - int max, +int gcli_get_pulls(gcli_ctx *ctx, char const *owner, char const *reponame, + gcli_pull_fetch_details const *details, int max, gcli_pull_list *out); void gcli_pull_free(gcli_pull *it); void gcli_pulls_free(gcli_pull_list *list); -void gcli_print_pulls_table(enum gcli_output_flags flags, - gcli_pull_list const *list, - int max); +void gcli_print_pulls_table(gcli_ctx *ctx, enum gcli_output_flags flags, + gcli_pull_list const *list, int max); -void gcli_print_pull_diff(FILE *stream, - char const *owner, - char const *reponame, - int pr_number); +void gcli_print_pull_diff(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *reponame, int pr_number); -int gcli_pull_checks(char const *owner, - char const *repo, +int gcli_pull_checks(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number); -void gcli_pull_commits(char const *owner, - char const *repo, +void gcli_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number); -int gcli_get_pull(char const *owner, char const *repo, +int gcli_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number, gcli_pull *out); -int gcli_pull_submit(gcli_submit_pull_options); +int gcli_pull_submit(gcli_ctx *ctx, gcli_submit_pull_options); -void gcli_pull_print_status(gcli_pull const *it); +void gcli_pull_print_status(gcli_ctx *ctx, gcli_pull const *it); void gcli_pull_print_op(gcli_pull *summary); @@ -147,38 +140,27 @@ enum gcli_merge_flags { GCLI_PULL_MERGE_DELETEHEAD = 0x2, /* delete the source branch after merging */ }; -int gcli_pull_merge(char const *owner, - char const *reponame, - int pr_number, - enum gcli_merge_flags flags); +int gcli_pull_merge(gcli_ctx *ctx, char const *owner, char const *reponame, + int pr_number, enum gcli_merge_flags flags); -int gcli_pull_close(char const *owner, - char const *reponame, +int gcli_pull_close(gcli_ctx *ctx, char const *owner, char const *reponame, int pr_number); -int gcli_pull_reopen(char const *owner, - char const *reponame, +int gcli_pull_reopen(gcli_ctx *ctx, char const *owner, char const *reponame, int pr_number); -int gcli_pull_add_labels(char const *owner, - char const *repo, - int pr_number, - char const *const labels[], +int gcli_pull_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int pr_number, char const *const labels[], size_t labels_size); -int gcli_pull_remove_labels(char const *owner, - char const *repo, - int pr_number, - char const *const labels[], +int gcli_pull_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int pr_number, char const *const labels[], size_t labels_size); -int gcli_pull_set_milestone(char const *owner, - char const *repo, - int pr_number, - int milestone_id); +int gcli_pull_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, + int pr_number, int milestone_id); -int gcli_pull_clear_milestone(char const *owner, - char const *repo, +int gcli_pull_clear_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number); #endif /* PULLS_H */ diff --git a/include/gcli/releases.h b/include/gcli/releases.h index 2caa7e0e..b64555b5 100644 --- a/include/gcli/releases.h +++ b/include/gcli/releases.h @@ -87,24 +87,20 @@ struct gcli_new_release { size_t assets_size; }; -int gcli_get_releases(char const *owner, - char const *repo, - int max, - gcli_release_list *list); +int gcli_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, + int max, gcli_release_list *list); -void gcli_print_releases(enum gcli_output_flags flags, - gcli_release_list const *list, - int max); +void gcli_print_releases(gcli_ctx *ctx, enum gcli_output_flags flags, + gcli_release_list const *list, int max); void gcli_free_releases(gcli_release_list *); -int gcli_create_release(gcli_new_release const *); +int gcli_create_release(gcli_ctx *ctx, gcli_new_release const *); void gcli_release_push_asset(gcli_new_release *, gcli_release_asset_upload); -int gcli_delete_release(char const *owner, - char const *repo, +int gcli_delete_release(gcli_ctx *ctx, char const *owner, char const *repo, char const *id); #endif /* RELEASES_H */ diff --git a/include/gcli/repos.h b/include/gcli/repos.h index 4d875c0a..b04144e6 100644 --- a/include/gcli/repos.h +++ b/include/gcli/repos.h @@ -62,24 +62,22 @@ struct gcli_repo_create_options { bool private; }; -int gcli_get_repos(char const *owner, - int max, +int gcli_get_repos(gcli_ctx *ctx, char const *owner, int max, gcli_repo_list *list); -int gcli_get_own_repos(int max, - gcli_repo_list *list); +int gcli_get_own_repos(gcli_ctx *ctx, int max, gcli_repo_list *list); void gcli_repos_free(gcli_repo_list *list); void gcli_repo_free(gcli_repo *it); -void gcli_print_repos_table(enum gcli_output_flags flags, - gcli_repo_list const *repos, - int max); +void gcli_print_repos_table(gcli_ctx *ctx, enum gcli_output_flags flags, + gcli_repo_list const *repos, int max); -void gcli_repo_print(gcli_repo const *it); +void gcli_repo_print(gcli_ctx *ctx, gcli_repo const *it); -int gcli_repo_delete(char const *owner, char const *repo); +int gcli_repo_delete(gcli_ctx *ctx, char const *owner, char const *repo); -int gcli_repo_create(gcli_repo_create_options const *, gcli_repo *out); +int gcli_repo_create(gcli_ctx *ctx, gcli_repo_create_options const *, + gcli_repo *out); #endif /* REPOS_H */ diff --git a/include/gcli/review.h b/include/gcli/review.h index 2c0e9bca..3669a4f9 100644 --- a/include/gcli/review.h +++ b/include/gcli/review.h @@ -36,6 +36,8 @@ #include +#include + typedef struct gcli_pr_review gcli_pr_review; typedef struct gcli_pr_review_list gcli_pr_review_list; typedef struct gcli_pr_review_comment gcli_pr_review_comment; @@ -69,10 +71,11 @@ void gcli_review_reviews_free(gcli_pr_review_list *list); void gcli_review_comments_free(gcli_pr_review_comment *it, size_t size); -int gcli_review_get_reviews(char const *owner, char const *repo, +int gcli_review_get_reviews(gcli_ctx *ctx, char const *owner, char const *repo, int pr, gcli_pr_review_list *out); -void gcli_review_print_review_table(gcli_pr_review_list const *reviews); +void gcli_review_print_review_table(gcli_ctx *ctx, + gcli_pr_review_list const *reviews); void gcli_review_print_comments(gcli_pr_review_comment const *comments, size_t comments_size); diff --git a/include/gcli/sshkeys.h b/include/gcli/sshkeys.h index d594b26a..16e4c29d 100644 --- a/include/gcli/sshkeys.h +++ b/include/gcli/sshkeys.h @@ -36,6 +36,8 @@ #include +#include + struct gcli_sshkey { int id; char *title; @@ -51,12 +53,11 @@ struct gcli_sshkey_list { typedef struct gcli_sshkey gcli_sshkey; typedef struct gcli_sshkey_list gcli_sshkey_list; -int gcli_sshkeys_get_keys(gcli_sshkey_list *out); -int gcli_sshkeys_add_key(char const *title, - char const *public_key_path, - gcli_sshkey *out); -int gcli_sshkeys_delete_key(int id); -void gcli_sshkeys_print_keys(gcli_sshkey_list const *list); +int gcli_sshkeys_get_keys(gcli_ctx *ctx, gcli_sshkey_list *out); +int gcli_sshkeys_add_key(gcli_ctx *ctx, char const *title, + char const *public_key_path, gcli_sshkey *out); +int gcli_sshkeys_delete_key(gcli_ctx *ctx, int id); +void gcli_sshkeys_print_keys(gcli_ctx *ctx, gcli_sshkey_list const *list); void gcli_sshkeys_free_keys(gcli_sshkey_list *list); #endif /* GCLI_SSHKEYS_H */ diff --git a/include/gcli/status.h b/include/gcli/status.h index 081515b0..404f554d 100644 --- a/include/gcli/status.h +++ b/include/gcli/status.h @@ -34,6 +34,8 @@ #include #endif +#include + #include struct gcli_notification { @@ -47,11 +49,11 @@ struct gcli_notification { typedef struct gcli_notification gcli_notification; -void gcli_status(int count); +void gcli_status(gcli_ctx *ctx, int count); -int gcli_get_notifications(gcli_notification **out, int count); +int gcli_get_notifications(gcli_ctx *ctx, gcli_notification **out, int count); -int gcli_notification_mark_as_read(char const *id); +int gcli_notification_mark_as_read(gcli_ctx *ctx, char const *id); void gcli_free_notifications(gcli_notification *, size_t); diff --git a/include/gcli/table.h b/include/gcli/table.h index 4bf762ef..7939a83a 100644 --- a/include/gcli/table.h +++ b/include/gcli/table.h @@ -37,6 +37,8 @@ #include #include +#include + #include typedef struct gcli_tblcoldef gcli_tblcoldef; @@ -78,7 +80,7 @@ struct gcli_tblcoldef { }; /* Init a table printer */ -gcli_tbl gcli_tbl_begin(gcli_tblcoldef const *cols, +gcli_tbl gcli_tbl_begin(gcli_ctx *ctx, gcli_tblcoldef const *cols, size_t cols_size); /* Print the table contents and free all the resources allocated in @@ -88,7 +90,7 @@ void gcli_tbl_end(gcli_tbl table); /* Add a single to an initialized table */ int gcli_tbl_add_row(gcli_tbl table, ...); -gcli_dict gcli_dict_begin(void); +gcli_dict gcli_dict_begin(gcli_ctx *ctx); int gcli_dict_add(gcli_dict list, char const *key, diff --git a/src/cmd.c b/src/cmd.c index bd98e711..25e5e287 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -60,14 +60,14 @@ version(void) } void -check_owner_and_repo(const char **owner, const char **repo) +check_owner_and_repo(gcli_ctx *ctx, const char **owner, const char **repo) { /* If no remote was specified, try to autodetect */ if ((*owner == NULL) != (*repo == NULL)) errx(1, "error: missing either explicit owner or repo"); if (*owner == NULL) - gcli_config_get_repo(owner, repo); + gcli_config_get_repo(ctx, owner, repo); } /* Parses (and updates) the given argument list into two seperate lists: diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c new file mode 100644 index 00000000..0e8148ee --- /dev/null +++ b/src/cmd/gcli.c @@ -0,0 +1,173 @@ +/* + * Copyright 2021,2022 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#ifdef HAVE_GETOPT_h +#include +#endif + +#include +#include +#include +#include + +#include +#include + +static void usage(void); + +static int +subcommand_version(int argc, char *argv[]) +{ + (void) argc; + (void) argv; + + version(); + copyright(); + + return EXIT_SUCCESS; +} + +static struct subcommand { + char const *const cmd_name; + char const *const docstring; + int (*fn)(int, char **); +} subcommands[] = { + { .cmd_name = "ci", + .fn = subcommand_ci, + .docstring = "Github CI status info" }, + { .cmd_name = "comment", + .fn = subcommand_comment, + .docstring = "Comment under issues and PRs" }, + { .cmd_name = "config", + .fn = subcommand_config, + .docstring = "Configure forges" }, + { .cmd_name = "forks", + .fn = subcommand_forks, + .docstring = "Create, delete and list repository forks" }, + { .cmd_name = "gists", + .fn = subcommand_gists, + .docstring = "Create, fetch and list Github Gists" }, + { .cmd_name = "issues", + .fn = subcommand_issues, + .docstring = "Manage issues" }, + { .cmd_name = "labels", + .fn = subcommand_labels, + .docstring = "Manage issue and PR labels" }, + { .cmd_name = "milestones", + .fn = subcommand_milestones, + .docstring = "Milestone handling" }, + { .cmd_name = "pipelines", + .fn = subcommand_pipelines, + .docstring = "Gitlab CI management" }, + { .cmd_name = "pulls", + .fn = subcommand_pulls, + .docstring = "Create, view and manage PRs" }, + { .cmd_name = "releases", + .fn = subcommand_releases, + .docstring = "Manage releases of repositories" }, + { .cmd_name = "repos", + .fn = subcommand_repos, + .docstring = "Remote Repository management" }, + { .cmd_name = "snippets", + .fn = subcommand_snippets, + .docstring = "Fetch and list Gitlab snippets" }, + { .cmd_name = "status", + .fn = subcommand_status, + .docstring = "General user status and notifications" }, + { .cmd_name = "api", + .fn = subcommand_api, + .docstring = "Fetch plain JSON info from an API (for debugging purposes)" }, + { .cmd_name = "version", + .fn = subcommand_version, + .docstring = "Print version" }, +}; + +static void +usage(void) +{ + fprintf(stderr, "usage: gcli [options] subcommand\n\n"); + fprintf(stderr, "OPTIONS:\n"); + fprintf(stderr, " -a account Use the configured account instead of inferring it\n"); + fprintf(stderr, " -r remote Infer account from the given git remote\n"); + fprintf(stderr, " -t type Force the account type:\n"); + fprintf(stderr, " - github (default: github.com)\n"); + fprintf(stderr, " - gitlab (default: gitlab.com)\n"); + fprintf(stderr, " - gitea (default: codeberg.org)\n"); + fprintf(stderr, " -c Force colour and text formatting.\n"); + fprintf(stderr, " -q Be quiet. (Not implemented yet)\n\n"); + fprintf(stderr, " -v Be verbose.\n\n"); + fprintf(stderr, "SUBCOMMANDS:\n"); + for (size_t i = 0; i < ARRAY_SIZE(subcommands); ++i) { + fprintf(stderr, + " %-13.13s %s\n", + subcommands[i].cmd_name, + subcommands[i].docstring); + } + fprintf(stderr, "\n"); + version(); + copyright(); +} + +int +main(int argc, char *argv[]) +{ + gcli_ctx *ctx; + char const *errmsg; + + errmsg = gcli_init(&ctx); + if (errmsg) + errx(1, "error: %s", errmsg); + + /* Parse first arguments */ + if (gcli_config_parse_args(ctx, &argc, &argv)) { + usage(); + return EXIT_FAILURE; + } + + /* Make sure we have a subcommand */ + if (argc == 0) { + fprintf(stderr, "error: missing subcommand\n"); + usage(); + return EXIT_FAILURE; + } + + /* Find and invoke the subcommand handler */ + for (size_t i = 0; i < ARRAY_SIZE(subcommands); ++i) { + if (strcmp(subcommands[i].cmd_name, argv[0]) == 0) + return subcommands[i].fn(argc, argv); + } + + /* No subcommand matched */ + fprintf(stderr, "error: unknown subcommand %s\n", argv[0]); + usage(); + + return EXIT_FAILURE; +} diff --git a/src/colour.c b/src/colour.c index 654f6d2b..f0a07e01 100644 --- a/src/colour.c +++ b/src/colour.c @@ -64,12 +64,12 @@ colour_cache_insert(uint32_t const code, char *sequence) } char const * -gcli_setcolour256(uint32_t const code) +gcli_setcolour256(struct gcli_ctx *ctx, uint32_t const code) { char *result = NULL; char const *oldresult = NULL; - if (!gcli_config_have_colours()) + if (!gcli_config_have_colours(ctx)) return ""; if (colour_table_size == 0) @@ -90,18 +90,18 @@ gcli_setcolour256(uint32_t const code) } const char * -gcli_resetcolour(void) +gcli_resetcolour(gcli_ctx *ctx) { - if (!gcli_config_have_colours()) + if (!gcli_config_have_colours(ctx)) return ""; return "\033[m"; } const char * -gcli_setcolour(int code) +gcli_setcolour(gcli_ctx *ctx, int code) { - if (!gcli_config_have_colours()) + if (!gcli_config_have_colours(ctx)) return ""; switch (code) { @@ -121,28 +121,28 @@ gcli_setcolour(int code) } char const * -gcli_setbold(void) +gcli_setbold(gcli_ctx *ctx) { - if (!gcli_config_have_colours()) + if (!gcli_config_have_colours(ctx)) return ""; else return "\033[1m"; } char const * -gcli_resetbold(void) +gcli_resetbold(gcli_ctx *ctx) { - if (!gcli_config_have_colours()) + if (!gcli_config_have_colours(ctx)) return ""; else return "\033[22m"; } char const * -gcli_state_colour_str(char const *it) +gcli_state_colour_str(gcli_ctx *ctx, char const *it) { if (it) - return gcli_state_colour_sv(SV((char *)it)); + return gcli_state_colour_sv(ctx, SV((char *)it)); else return ""; } @@ -166,14 +166,14 @@ static const struct { char const *name; int code; } }; char const * -gcli_state_colour_sv(sn_sv const state) +gcli_state_colour_sv(gcli_ctx *ctx, sn_sv const state) { if (!sn_sv_null(state)) { for (size_t i = 0; i < ARRAY_SIZE(state_colour_table); ++i) { if (sn_sv_has_prefix(state, state_colour_table[i].name)) - return gcli_setcolour(state_colour_table[i].code); + return gcli_setcolour(ctx, state_colour_table[i].code); } } - return gcli_setcolour(GCLI_COLOR_DEFAULT); + return gcli_setcolour(ctx, GCLI_COLOR_DEFAULT); } diff --git a/src/comments.c b/src/comments.c index 64fb41b7..cf8c6b6b 100644 --- a/src/comments.c +++ b/src/comments.c @@ -56,12 +56,12 @@ gcli_comment_list_free(gcli_comment_list *list) } void -gcli_print_comment_list(gcli_comment_list const *const list) +gcli_print_comment_list(gcli_ctx *ctx, gcli_comment_list const *const list) { for (size_t i = 0; i < list->comments_size; ++i) { printf("AUTHOR : %s%s%s\n" "DATE : %s\n", - gcli_setbold(), list->comments[i].author, gcli_resetbold(), + gcli_setbold(ctx), list->comments[i].author, gcli_resetbold(ctx), list->comments[i].date); pretty_print(list->comments[i].body, 9, 80, stdout); putchar('\n'); @@ -69,55 +69,57 @@ gcli_print_comment_list(gcli_comment_list const *const list) } int -gcli_get_issue_comments(char const *owner, char const *repo, int const issue, - gcli_comment_list *out) +gcli_get_issue_comments(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue, gcli_comment_list *out) { - return gcli_forge()->get_issue_comments(owner, repo, issue, out); + return gcli_forge(ctx)->get_issue_comments(ctx, owner, repo, issue, out); } void -gcli_issue_comments(char const *owner, char const *repo, int const issue) +gcli_issue_comments(gcli_ctx *ctx, char const *owner, + char const *repo, int const issue) { gcli_comment_list list = {0}; - if (gcli_get_issue_comments(owner, repo, issue, &list) < 0) + if (gcli_get_issue_comments(ctx, owner, repo, issue, &list) < 0) errx(1, "error: failed to fetch comments"); - gcli_print_comment_list(&list); + gcli_print_comment_list(ctx, &list); gcli_comment_list_free(&list); } int -gcli_get_pull_comments(char const *owner, char const *repo, int const pull, - gcli_comment_list *out) +gcli_get_pull_comments(gcli_ctx *ctx, char const *owner, char const *repo, + int const pull, gcli_comment_list *out) { - return gcli_forge()->get_pull_comments(owner, repo, pull, out); + return gcli_forge(ctx)->get_pull_comments(ctx, owner, repo, pull, out); } void -gcli_pull_comments(char const *owner, char const *repo, int const issue) +gcli_pull_comments(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue) { gcli_comment_list list = {0}; - if (gcli_get_pull_comments(owner, repo, issue, &list) < 0) + if (gcli_get_pull_comments(ctx, owner, repo, issue, &list) < 0) errx(1, "error: failed to fetch pull request comments"); - gcli_print_comment_list(&list); + gcli_print_comment_list(ctx, &list); gcli_comment_list_free(&list); } static void -comment_init(FILE *f, void *_data) +comment_init(gcli_ctx *ctx, FILE *f, void *_data) { - gcli_submit_comment_opts *info = _data; - const char *target_type = NULL; + gcli_submit_comment_opts *info = _data; + const char *target_type = NULL; switch (info->target_type) { case ISSUE_COMMENT: target_type = "issue"; break; case PR_COMMENT: { - switch (gcli_config_get_forge_type()) { + switch (gcli_config_get_forge_type(ctx)) { case GCLI_FORGE_GITEA: case GCLI_FORGE_GITHUB: target_type = "Pull Request"; @@ -139,15 +141,15 @@ comment_init(FILE *f, void *_data) } static sn_sv -gcli_comment_get_message(gcli_submit_comment_opts *info) +gcli_comment_get_message(gcli_ctx *ctx, gcli_submit_comment_opts *info) { - return gcli_editor_get_user_message(comment_init, info); + return gcli_editor_get_user_message(ctx, comment_init, info); } int -gcli_comment_submit(gcli_submit_comment_opts opts) +gcli_comment_submit(gcli_ctx *ctx, gcli_submit_comment_opts opts) { - sn_sv const message = gcli_comment_get_message(&opts); + sn_sv const message = gcli_comment_get_message(ctx, &opts); opts.message = gcli_json_escape(message); int rc = 0; @@ -161,7 +163,7 @@ gcli_comment_submit(gcli_submit_comment_opts opts) errx(1, "Aborted by user"); } - rc = gcli_forge()->perform_submit_comment(opts, NULL); + rc = gcli_forge(ctx)->perform_submit_comment(ctx, opts, NULL); free(message.data); free(opts.message.data); diff --git a/src/config.c b/src/config.c index 276e7236..907af4b4 100644 --- a/src/config.c +++ b/src/config.c @@ -45,48 +45,55 @@ #include #include -#define CONFIG_MAX_ENTRIES 16 +#ifdef HAVE_SYS_QUEUE_H +#include +#endif /* HAVE_SYS_QUEUE_H */ + +struct gcli_config_entry { + TAILQ_ENTRY(gcli_config_entry) next; + sn_sv key; + sn_sv value; +}; + +TAILQ_HEAD(gcli_config_entries, gcli_config_entry); struct gcli_config_section { - struct gcli_config_entry { - sn_sv key; - sn_sv value; - } entries[CONFIG_MAX_ENTRIES]; - size_t entries_size; + TAILQ_ENTRY(gcli_config_section) next; + + struct gcli_config_entries entries; sn_sv title; }; #define CONFIG_MAX_SECTIONS 16 -static struct gcli_config { - struct gcli_config_section sections[CONFIG_MAX_SECTIONS]; - size_t sections_size; +struct gcli_config { + TAILQ_HEAD(gcli_config_sections, gcli_config_section) sections; char const *override_default_account; char const *override_remote; - int override_forgetype; - int colours_disabled; /* NO_COLOR set or output is not a TTY */ - int force_colours; /* -c option was given */ + int override_forgetype; + int colours_disabled; /* NO_COLOR set or output is not a TTY */ + int force_colours; /* -c option was given */ sn_sv buffer; void *mmap_pointer; bool inited; -} config; +}; -static struct gcli_dotgcli { - struct gcli_config_entry entries[128]; - size_t entries_size; +struct gcli_dotgcli { + struct gcli_config_entries entries; sn_sv buffer; void *mmap_pointer; bool has_been_searched_for; bool has_been_found; -} local_config; +}; static bool -should_init_dotgcli(void) +should_init_dotgcli(gcli_ctx *ctx) { - return !local_config.has_been_searched_for || - (local_config.has_been_searched_for && !local_config.has_been_found); + return !ctx->dotgcli->has_been_searched_for || + (ctx->dotgcli->has_been_searched_for && + !ctx->dotgcli->has_been_found); } static char const * @@ -162,31 +169,32 @@ find_dotgcli(void) } static void -init_local_config(void) +init_local_config(gcli_ctx *ctx) { - if (!should_init_dotgcli()) + if (!should_init_dotgcli(ctx)) { return; + } char const *path = find_dotgcli(); if (!path) { - local_config.has_been_searched_for = true; - local_config.has_been_found = false; + ctx->dotgcli->has_been_searched_for = true; + ctx->dotgcli->has_been_found = false; return; } - local_config.has_been_searched_for = true; - local_config.has_been_found = true; + ctx->dotgcli->has_been_searched_for = true; + ctx->dotgcli->has_been_found = true; - int len = sn_mmap_file(path, &local_config.mmap_pointer); + int len = sn_mmap_file(path, &ctx->dotgcli->mmap_pointer); if (len < 0) err(1, "Unable to open config file"); - local_config.buffer = sn_sv_from_parts(local_config.mmap_pointer, len); - local_config.buffer = sn_sv_trim_front(local_config.buffer); + ctx->dotgcli->buffer = sn_sv_from_parts(ctx->dotgcli->mmap_pointer, len); + ctx->dotgcli->buffer = sn_sv_trim_front(ctx->dotgcli->buffer); int curr_line = 1; - while (local_config.buffer.length > 0) { - sn_sv line = sn_sv_chop_until(&local_config.buffer, '\n'); + while (ctx->dotgcli->buffer.length > 0) { + sn_sv line = sn_sv_chop_until(&ctx->dotgcli->buffer, '\n'); line = sn_sv_trim(line); @@ -196,12 +204,12 @@ init_local_config(void) // Comments if (line.data[0] == '#') { - local_config.buffer = sn_sv_trim_front(local_config.buffer); + ctx->dotgcli->buffer = sn_sv_trim_front(ctx->dotgcli->buffer); curr_line++; continue; } - sn_sv key = sn_sv_chop_until(&line, '='); + sn_sv key = sn_sv_chop_until(&line, '='); key = sn_sv_trim(key); @@ -213,11 +221,13 @@ init_local_config(void) sn_sv value = sn_sv_trim(line); - local_config.entries[local_config.entries_size].key = key; - local_config.entries[local_config.entries_size].value = value; - local_config.entries_size++; + struct gcli_config_entry *entry = calloc(sizeof(*entry), 1); + TAILQ_INSERT_TAIL(&ctx->dotgcli->entries, entry, next); + + entry->key = key; + entry->value = value; - local_config.buffer = sn_sv_trim_front(local_config.buffer); + ctx->dotgcli->buffer = sn_sv_trim_front(ctx->dotgcli->buffer); curr_line++; } @@ -225,8 +235,8 @@ init_local_config(void) } struct config_parser { - sn_sv buffer; - int line; + sn_sv buffer; + int line; char const *filename; }; @@ -261,8 +271,12 @@ skip_ws_and_comments(struct config_parser *input) } static void -parse_keyvaluepair(struct config_parser *input, struct gcli_config_entry *out) +parse_section_entry(struct config_parser *input, + struct gcli_config_section *section) { + struct gcli_config_entry *entry = calloc(sizeof(*entry), 1); + TAILQ_INSERT_TAIL(§ion->entries, entry, next); + sn_sv key = sn_sv_chop_until(&input->buffer, '='); if (key.length == 0) @@ -273,8 +287,8 @@ parse_keyvaluepair(struct config_parser *input, struct gcli_config_entry *out) sn_sv value = sn_sv_chop_until(&input->buffer, '\n'); - out->key = sn_sv_trim(key); - out->value = sn_sv_trim(value); + entry->key = sn_sv_trim(key); + entry->value = sn_sv_trim(value); } static sn_sv @@ -309,25 +323,22 @@ parse_section_title(struct config_parser *input) } static void -parse_config_section(struct config_parser *input) +parse_config_section(struct gcli_config *cfg, + struct config_parser *input) { struct gcli_config_section *section = NULL; - if (config.sections_size == CONFIG_MAX_SECTIONS) - errx(1, "error: too many config sections"); - - section = &config.sections[config.sections_size++]; + section = calloc(sizeof(*section), 1); + TAILQ_INSERT_TAIL(&cfg->sections, section, next); section->title = parse_section_title(input); + section->entries = (struct gcli_config_entries) + TAILQ_HEAD_INITIALIZER(section->entries); + while (input->buffer.length > 0 && input->buffer.data[0] != '}') { skip_ws_and_comments(input); - - if (section->entries_size == CONFIG_MAX_ENTRIES) - errx(1, "error: too many config entries in section "SV_FMT, - SV_ARGS(section->title)); - - parse_keyvaluepair(input, §ion->entries[section->entries_size++]); + parse_section_entry(input, section); skip_ws_and_comments(input); } @@ -340,12 +351,13 @@ parse_config_section(struct config_parser *input) } static void -parse_config_file(struct config_parser *input) +parse_config_file(struct gcli_config *cfg, + struct config_parser *input) { skip_ws_and_comments(input); while (input->buffer.length > 0) { - parse_config_section(input); + parse_config_section(cfg, input); skip_ws_and_comments(input); } } @@ -355,15 +367,16 @@ parse_config_file(struct config_parser *input) * return 0. Otherwise return -1. */ static int -ensure_config(void) +ensure_config(gcli_ctx *ctx) { - char *file_path = NULL; - struct config_parser parser = {0}; + struct gcli_config *cfg = ctx->config; + char *file_path = NULL; + struct config_parser parser = {0}; - if (config.inited) + if (cfg->inited) return 0; - config.inited = true; + cfg->inited = true; file_path = getenv("XDG_CONFIG_PATH"); if (!file_path) { @@ -385,18 +398,18 @@ ensure_config(void) return -1; } - int len = sn_mmap_file(file_path, &config.mmap_pointer); + int len = sn_mmap_file(file_path, &cfg->mmap_pointer); if (len < 0) err(1, "Unable to open config file"); - config.buffer = sn_sv_from_parts(config.mmap_pointer, len); - config.buffer = sn_sv_trim_front(config.buffer); + cfg->buffer = sn_sv_from_parts(cfg->mmap_pointer, len); + cfg->buffer = sn_sv_trim_front(cfg->buffer); - parser.buffer = config.buffer; + parser.buffer = cfg->buffer; parser.line = 1; parser.filename = file_path; - parse_config_file(&parser); + parse_config_file(cfg, &parser); free((void *)file_path); @@ -426,14 +439,14 @@ checkyes(char const *const tmp) /* readenv: Read values of environment variables and pre-populate the * config structure. */ static void -readenv(void) +readenv(struct gcli_config *cfg) { char *tmp; /* A default override account. Can be overridden again by * specifying -a */ if ((tmp = getenv("GCLI_ACCOUNT"))) - config.override_default_account = tmp; + cfg->override_default_account = tmp; /* NO_COLOR: https://no-color.org/ * @@ -445,11 +458,24 @@ readenv(void) * violate the definition to get expected and sane behaviour. */ tmp = getenv("NO_COLOR"); if (tmp && tmp[0] != '\0') - config.colours_disabled = checkyes(tmp); + cfg->colours_disabled = checkyes(tmp); +} + +int +gcli_config_init_ctx(struct gcli_ctx *ctx) +{ + ctx->dotgcli = calloc(sizeof(*ctx->dotgcli), 1); + ctx->config = calloc(sizeof(*ctx->config), 1); + + ctx->config->sections = + (struct gcli_config_sections) + TAILQ_HEAD_INITIALIZER(ctx->config->sections); + + return 0; } int -gcli_config_init(int *argc, char ***argv) +gcli_config_parse_args(gcli_ctx *ctx, int *argc, char ***argv) { /* These are the very first options passed to the gcli command * itself. It is the first ever getopt call we do to parse any @@ -468,7 +494,7 @@ gcli_config_init(int *argc, char ***argv) .val = 'r' }, { .name = "colours", .has_arg = no_argument, - .flag = &config.colours_disabled, + .flag = &ctx->config->colours_disabled, .val = 0 }, { .name = "type", .has_arg = required_argument, @@ -490,21 +516,21 @@ gcli_config_init(int *argc, char ***argv) /* Before we parse options, invalidate the override type so it * doesn't get confused later */ - config.override_forgetype = -1; + ctx->config->override_forgetype = -1; /* Start off by pre-populating the config structure */ - readenv(); + readenv(ctx->config); while ((ch = getopt_long(*argc, *argv, "+a:r:cqvt:", options, NULL)) != -1) { switch (ch) { case 'a': { - config.override_default_account = optarg; + ctx->config->override_default_account = optarg; } break; case 'r': { - config.override_remote = optarg; + ctx->config->override_remote = optarg; } break; case 'c': { - config.force_colours = 1; + ctx->config->force_colours = 1; } break; case 'q': { sn_setverbosity(VERBOSITY_QUIET); @@ -514,11 +540,11 @@ gcli_config_init(int *argc, char ***argv) } break; case 't': { if (strcmp(optarg, "github") == 0) { - config.override_forgetype = GCLI_FORGE_GITHUB; + ctx->config->override_forgetype = GCLI_FORGE_GITHUB; } else if (strcmp(optarg, "gitlab") == 0) { - config.override_forgetype = GCLI_FORGE_GITLAB; + ctx->config->override_forgetype = GCLI_FORGE_GITLAB; } else if (strcmp(optarg, "gitea") == 0) { - config.override_forgetype = GCLI_FORGE_GITEA; + ctx->config->override_forgetype = GCLI_FORGE_GITEA; } else { fprintf(stderr, "error: unknown forge type '%s'. " "Have either github, gitlab or gitea.\n", optarg); @@ -543,100 +569,112 @@ gcli_config_init(int *argc, char ***argv) * working without it. */ optind = 0; - config.inited = false; + ctx->config->inited = false; return EXIT_SUCCESS; } static struct gcli_config_section const * -find_section(sn_sv name) +find_section(struct gcli_config *cfg, sn_sv name) { - for (size_t i = 0; i < config.sections_size; ++i) { - if (sn_sv_eq(config.sections[i].title, name)) - return &config.sections[i]; + struct gcli_config_section *section; + + TAILQ_FOREACH(section, &cfg->sections, next) { + if (sn_sv_eq(section->title, name)) + return section; } return NULL; } sn_sv -gcli_config_find_by_key(sn_sv const section_name, char const *key) +gcli_config_find_by_key(gcli_ctx *ctx, sn_sv const section_name, char const *key) { - ensure_config(); + struct gcli_config_entry *entry; + + ensure_config(ctx); struct gcli_config_section const *const section = - find_section(section_name); + find_section(ctx->config, section_name); if (!section) { warnx("no config section with name '"SV_FMT"'", SV_ARGS(section_name)); return SV_NULL; } - for (size_t i = 0; i < section->entries_size; ++i) - if (sn_sv_eq_to(section->entries[i].key, key)) - return section->entries[i].value; + TAILQ_FOREACH(entry, §ion->entries, next) { + if (sn_sv_eq_to(entry->key, key)) + return entry->value; + } return SV_NULL; } static sn_sv -gcli_local_config_find_by_key(char const *const key) +gcli_local_config_find_by_key(gcli_ctx *ctx, char const *const key) { - for (size_t i = 0; i < local_config.entries_size; ++i) - if (sn_sv_eq_to(local_config.entries[i].key, key)) - return local_config.entries[i].value; + struct gcli_dotgcli *lcfg = ctx->dotgcli; + struct gcli_config_entry *entry; + + TAILQ_FOREACH(entry, &lcfg->entries, next) { + if (sn_sv_eq_to(entry->key, key)) + return entry->value; + } + return SV_NULL; } char * -gcli_config_get_editor(void) +gcli_config_get_editor(gcli_ctx *ctx) { - ensure_config(); + ensure_config(ctx); - return sn_sv_to_cstr(gcli_config_find_by_key(SV("defaults"), "editor")); + return sn_sv_to_cstr(gcli_config_find_by_key(ctx, SV("defaults"), "editor")); } char * -gcli_config_get_authheader(void) +gcli_config_get_authheader(gcli_ctx *ctx) { - ensure_config(); + ensure_config(ctx); - return gcli_forge()->get_authheader(); + return gcli_forge(ctx)->get_authheader(ctx); } sn_sv -gcli_config_get_account(void) +gcli_config_get_account(gcli_ctx *ctx) { - ensure_config(); + ensure_config(ctx); - return gcli_forge()->get_account(); + return gcli_forge(ctx)->get_account(ctx); } sn_sv -gcli_config_get_upstream(void) +gcli_config_get_upstream(gcli_ctx *ctx) { - init_local_config(); + init_local_config(ctx); - return gcli_local_config_find_by_key("pr.upstream"); + return gcli_local_config_find_by_key(ctx, "pr.upstream"); } bool -gcli_config_pr_inhibit_delete_source_branch(void) +gcli_config_pr_inhibit_delete_source_branch(gcli_ctx *ctx) { sn_sv val; - init_local_config(); + init_local_config(ctx); + + val = gcli_local_config_find_by_key(ctx, "pr.inhibit-delete-source-branch"); - val = gcli_local_config_find_by_key("pr.inhibit-delete-source-branch"); return sn_sv_eq_to(val, "yes"); } void -gcli_config_get_upstream_parts(sn_sv *const owner, sn_sv *const repo) +gcli_config_get_upstream_parts(gcli_ctx *ctx, sn_sv *const owner, + sn_sv *const repo) { - ensure_config(); + ensure_config(ctx); - sn_sv upstream = gcli_config_get_upstream(); - *owner = sn_sv_chop_until(&upstream, '/'); + sn_sv upstream = gcli_config_get_upstream(ctx); + *owner = sn_sv_chop_until(&upstream, '/'); /* Sanity check: did we actually reach the '/'? */ if (*upstream.data != '/') @@ -648,45 +686,45 @@ gcli_config_get_upstream_parts(sn_sv *const owner, sn_sv *const repo) } sn_sv -gcli_config_get_base(void) +gcli_config_get_base(gcli_ctx *ctx) { - init_local_config(); + init_local_config(ctx); - return gcli_local_config_find_by_key("pr.base"); + return gcli_local_config_find_by_key(ctx, "pr.base"); } sn_sv -gcli_config_get_override_default_account(void) +gcli_config_get_override_default_account(gcli_ctx *ctx) { - init_local_config(); + init_local_config(ctx); - if (config.override_default_account) - return SV((char *)config.override_default_account); + if (ctx->config->override_default_account) + return SV((char *)ctx->config->override_default_account); else return SV_NULL; } static gcli_forge_type -gcli_config_get_forge_type_internal(void) +gcli_config_get_forge_type_internal(gcli_ctx *ctx) { /* Hard override */ - if (config.override_forgetype >= 0) - return config.override_forgetype; + if (ctx->config->override_forgetype >= 0) + return ctx->config->override_forgetype; - ensure_config(); - init_local_config(); + ensure_config(ctx); + init_local_config(ctx); sn_sv entry = {0}; - if (config.override_default_account) { - sn_sv const section = SV((char *)config.override_default_account); - entry = gcli_config_find_by_key(section, "forge-type"); + if (ctx->config->override_default_account) { + sn_sv const section = SV((char *)ctx->config->override_default_account); + entry = gcli_config_find_by_key(ctx, section, "forge-type"); if (sn_sv_null(entry)) errx(1, "error: given default override account not found or " "missing forge-type"); } else { - entry = gcli_local_config_find_by_key("forge-type"); + entry = gcli_local_config_find_by_key(ctx, "forge-type"); } if (!sn_sv_null(entry)) { @@ -701,7 +739,7 @@ gcli_config_get_forge_type_internal(void) } /* As a last resort, try to infer from the git remote */ - int const type = gcli_gitconfig_get_forgetype(config.override_remote); + int const type = gcli_gitconfig_get_forgetype(ctx, ctx->config->override_remote); if (type < 0) errx(1, "error: cannot infer forge type. " "use -t to overrride manually."); @@ -710,9 +748,9 @@ gcli_config_get_forge_type_internal(void) } gcli_forge_type -gcli_config_get_forge_type(void) +gcli_config_get_forge_type(gcli_ctx *ctx) { - gcli_forge_type const result = gcli_config_get_forge_type_internal(); + gcli_forge_type const result = gcli_config_get_forge_type_internal(ctx); /* print the type if verbose */ if (sn_verbose()) { @@ -733,25 +771,26 @@ gcli_config_get_forge_type(void) } void -gcli_config_get_repo(char const **const owner, char const **const repo) +gcli_config_get_repo(gcli_ctx *ctx, char const **const owner, + char const **const repo) { sn_sv upstream = {0}; - ensure_config(); + ensure_config(ctx); - if (config.override_remote) { + if (ctx->config->override_remote) { int const forge = gcli_gitconfig_repo_by_remote( - config.override_remote, owner, repo); + ctx->config->override_remote, owner, repo); if (forge >= 0) { - if ((int)(gcli_config_get_forge_type()) != forge) + if ((int)(gcli_config_get_forge_type(ctx)) != forge) errx(1, "error: forge types are inconsistent"); } return; } - if ((upstream = gcli_config_get_upstream()).length != 0) { + if ((upstream = gcli_config_get_upstream(ctx)).length != 0) { sn_sv const owner_sv = sn_sv_chop_until(&upstream, '/'); sn_sv const repo_sv = sn_sv_from_parts( upstream.data + 1, @@ -767,39 +806,39 @@ gcli_config_get_repo(char const **const owner, char const **const repo) } int -gcli_config_have_colours(void) +gcli_config_have_colours(gcli_ctx *ctx) { static int tested_tty = 0; - if (config.force_colours) + if (ctx->config->force_colours) return 1; - if (config.colours_disabled) + if (ctx->config->colours_disabled) return 0; if (tested_tty) - return !config.colours_disabled; + return !ctx->config->colours_disabled; if (isatty(STDOUT_FILENO)) - config.colours_disabled = false; + ctx->config->colours_disabled = false; else - config.colours_disabled = true; + ctx->config->colours_disabled = true; tested_tty = 1; - return !config.colours_disabled; + return !ctx->config->colours_disabled; } char const * -gcli_get_apibase(void) +gcli_get_apibase(gcli_ctx *ctx) { - switch (gcli_config_get_forge_type()) { + switch (gcli_config_get_forge_type(ctx)) { case GCLI_FORGE_GITHUB: - return github_get_apibase(); + return github_get_apibase(ctx); case GCLI_FORGE_GITEA: - return gitea_get_apibase(); + return gitea_get_apibase(ctx); case GCLI_FORGE_GITLAB: - return gitlab_get_apibase(); + return gitlab_get_apibase(ctx); default: assert(0 && "Not reached"); } diff --git a/src/curl.c b/src/curl.c index 1e2f2e9b..144ff146 100644 --- a/src/curl.c +++ b/src/curl.c @@ -90,8 +90,7 @@ gcli_curl_ensure(void) /* Check the given curl code for an OK result. If not, print an * appropriate error message and exit */ static int -gcli_curl_check_api_error(CURLcode code, - char const *url, +gcli_curl_check_api_error(gcli_ctx *ctx, CURLcode code, char const *url, gcli_fetch_buffer *const result) { long status_code = 0; @@ -113,7 +112,7 @@ gcli_curl_check_api_error(CURLcode code, "error: request to %s failed with code %ld\n" " : API error: %s", url, status_code, - gcli_forge()->get_api_error_string(result)); + gcli_forge(ctx)->get_api_error_string(ctx, result)); return -1; } @@ -143,12 +142,10 @@ fetch_write_callback(char *in, size_t size, size_t nmemb, void *data) * pagination_next returns the next url to query for paged results. * Results are placed into the gcli_fetch_buffer. */ int -gcli_fetch( - char const *url, - char **const pagination_next, - gcli_fetch_buffer *out) +gcli_fetch(gcli_ctx *ctx, char const *url, char **const pagination_next, + gcli_fetch_buffer *out) { - return gcli_fetch_with_method("GET", url, NULL, pagination_next, out); + return gcli_fetch_with_method(ctx, "GET", url, NULL, pagination_next, out); } /* Check the given url for a successful query */ @@ -199,7 +196,7 @@ gcli_curl_test_success(char const *url) * * content_type may be NULL. */ int -gcli_curl(FILE *stream, char const *url, char const *content_type) +gcli_curl(gcli_ctx *ctx, FILE *stream, char const *url, char const *content_type) { CURLcode ret; struct curl_slist *headers; @@ -212,8 +209,8 @@ gcli_curl(FILE *stream, char const *url, char const *content_type) if (content_type) headers = curl_slist_append(headers, content_type); - auth_header = gcli_config_get_authheader(); - headers = curl_slist_append(headers, auth_header); + auth_header = gcli_config_get_authheader(ctx); + headers = curl_slist_append(headers, auth_header); gcli_curl_ensure(); @@ -235,7 +232,7 @@ gcli_curl(FILE *stream, char const *url, char const *content_type) curl_easy_setopt(gcli_curl_session, CURLOPT_FOLLOWLOCATION, 1L); ret = curl_easy_perform(gcli_curl_session); - rc = gcli_curl_check_api_error(ret, url, &buffer); + rc = gcli_curl_check_api_error(ctx, ret, url, &buffer); if (rc == 0) fwrite(buffer.data, 1, buffer.length, stream); @@ -325,10 +322,11 @@ parse_link_header(char *_header) * will be set to NULL. */ int gcli_fetch_with_method( - char const *method, /* HTTP method. e.g. POST, GET, DELETE etc. */ - char const *url, /* Endpoint */ - char const *data, /* Form data */ - char **const pagination_next, /* Next URL for pagination */ + gcli_ctx *ctx, + char const *method, /* HTTP method. e.g. POST, GET, DELETE etc. */ + char const *url, /* Endpoint */ + char const *data, /* Form data */ + char **const pagination_next, /* Next URL for pagination */ gcli_fetch_buffer *const out) /* output buffer */ { CURLcode ret; @@ -338,7 +336,7 @@ gcli_fetch_with_method( char *link_header = NULL; int rc = 0; - char *auth_header = gcli_config_get_authheader(); + char *auth_header = gcli_config_get_authheader(ctx); if (sn_verbose()) fprintf(stderr, "info: cURL request %s %s...\n", method, url); @@ -382,7 +380,7 @@ gcli_fetch_with_method( curl_easy_setopt(gcli_curl_session, CURLOPT_FOLLOWLOCATION, 1L); ret = curl_easy_perform(gcli_curl_session); - rc = gcli_curl_check_api_error(ret, url, buf); + rc = gcli_curl_check_api_error(ctx, ret, url, buf); /* only parse these headers and continue if there was no error */ if (rc == 0) { @@ -416,17 +414,15 @@ gcli_fetch_with_method( * content_type may not be NULL. */ int -gcli_post_upload(char const *url, - char const *content_type, - void *buffer, - size_t const buffer_size, +gcli_post_upload(gcli_ctx *ctx, char const *url, char const *content_type, + void *buffer, size_t const buffer_size, gcli_fetch_buffer *const out) { CURLcode ret; struct curl_slist *headers; int rc = 0; - char *auth_header = gcli_config_get_authheader(); + char *auth_header = gcli_config_get_authheader(ctx); char *contenttype_header = sn_asprintf( "Content-Type: %s", content_type); @@ -458,7 +454,7 @@ gcli_post_upload(char const *url, curl_easy_setopt(gcli_curl_session, CURLOPT_WRITEFUNCTION, fetch_write_callback); ret = curl_easy_perform(gcli_curl_session); - rc = gcli_curl_check_api_error(ret, url, out); + rc = gcli_curl_check_api_error(ctx, ret, url, out); curl_slist_free_all(headers); headers = NULL; @@ -476,7 +472,7 @@ gcli_post_upload(char const *url, * code. */ int -gcli_curl_gitea_upload_attachment(char const *url, +gcli_curl_gitea_upload_attachment(gcli_ctx *ctx, char const *url, char const *filename, gcli_fetch_buffer *const out) { @@ -486,7 +482,7 @@ gcli_curl_gitea_upload_attachment(char const *url, struct curl_slist *headers; int rc = 0; - char *auth_header = gcli_config_get_authheader(); + char *auth_header = gcli_config_get_authheader(ctx); if (sn_verbose()) fprintf(stderr, "info: cURL upload POST %s...\n", url); @@ -521,7 +517,7 @@ gcli_curl_gitea_upload_attachment(char const *url, curl_easy_setopt(gcli_curl_session, CURLOPT_WRITEFUNCTION, fetch_write_callback); ret = curl_easy_perform(gcli_curl_session); - rc = gcli_curl_check_api_error(ret, url, out); + rc = gcli_curl_check_api_error(ctx, ret, url, out); /* Cleanup */ curl_slist_free_all(headers); @@ -596,7 +592,7 @@ gcli_urldecode(char const *input) * * If max is -1 then everything will be fetched. */ int -gcli_fetch_list(char *url, gcli_fetch_list_ctx *ctx) +gcli_fetch_list(gcli_ctx *ctx, char *url, gcli_fetch_list_ctx *fl) { char *next_url = NULL; int rc; @@ -604,14 +600,14 @@ gcli_fetch_list(char *url, gcli_fetch_list_ctx *ctx) do { gcli_fetch_buffer buffer = {0}; - rc = gcli_fetch(url, &next_url, &buffer); + rc = gcli_fetch(ctx, url, &next_url, &buffer); if (rc == 0) { struct json_stream stream = {0}; json_open_buffer(&stream, buffer.data, buffer.length); - ctx->parse(&stream, ctx->listp, ctx->sizep); - if (ctx->filter) - ctx->filter(ctx->listp, ctx->sizep, ctx->userdata); + fl->parse(&stream, fl->listp, fl->sizep); + if (fl->filter) + fl->filter(fl->listp, fl->sizep, fl->userdata); json_close(&stream); } @@ -622,7 +618,7 @@ gcli_fetch_list(char *url, gcli_fetch_list_ctx *ctx) if (rc < 0) break; - } while ((url = next_url) && (ctx->max == -1 || (int)(*ctx->sizep) < ctx->max)); + } while ((url = next_url) && (fl->max == -1 || (int)(*fl->sizep) < fl->max)); free(next_url); diff --git a/src/editor.c b/src/editor.c index 649e2d3d..14ef5912 100644 --- a/src/editor.c +++ b/src/editor.c @@ -50,13 +50,14 @@ sv_append(sn_sv this, sn_sv const that) sn_sv gcli_editor_get_user_message( - void (*file_initializer)(FILE *, void *), + gcli_ctx *ctx, + void (*file_initializer)(gcli_ctx *, FILE *, void *), void *user_data) { char *editor = getenv("EDITOR"); char *env_editor = editor; if (!editor) { - editor = gcli_config_get_editor(); + editor = gcli_config_get_editor(ctx); if (!editor) errx(1, "I have no editor. Either set editor=... in your config " @@ -67,7 +68,7 @@ gcli_editor_get_user_message( int fd = mkstemp(filename); FILE *file = fdopen(fd, "w"); - file_initializer(file, user_data); + file_initializer(ctx, file, user_data); fclose(file); pid_t pid = fork(); diff --git a/src/forges.c b/src/forges.c index 3c784ef8..6a0cfb87 100644 --- a/src/forges.c +++ b/src/forges.c @@ -279,9 +279,9 @@ gitea_forge_descriptor = }; gcli_forge_descriptor const * -gcli_forge(void) +gcli_forge(gcli_ctx *ctx) { - switch (gcli_config_get_forge_type()) { + switch (gcli_config_get_forge_type(ctx)) { case GCLI_FORGE_GITHUB: return &github_forge_descriptor; case GCLI_FORGE_GITLAB: diff --git a/src/forks.c b/src/forks.c index 0916ca3c..745c5702 100644 --- a/src/forks.c +++ b/src/forks.c @@ -34,18 +34,15 @@ #include int -gcli_get_forks(char const *owner, - char const *repo, - int const max, - gcli_fork_list *const out) +gcli_get_forks(gcli_ctx *ctx, char const *owner, char const *repo, + int const max, gcli_fork_list *const out) { - return gcli_forge()->get_forks(owner, repo, max, out); + return gcli_forge(ctx)->get_forks(ctx, owner, repo, max, out); } void -gcli_print_forks(enum gcli_output_flags const flags, - gcli_fork_list const *const list, - int const max) +gcli_print_forks(gcli_ctx *ctx, enum gcli_output_flags const flags, + gcli_fork_list const *const list, int const max) { size_t n; gcli_tbl table; @@ -67,7 +64,7 @@ gcli_print_forks(enum gcli_output_flags const flags, else n = max; - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not initialize table"); @@ -93,9 +90,10 @@ gcli_print_forks(enum gcli_output_flags const flags, } int -gcli_fork_create(char const *owner, char const *repo, char const *_in) +gcli_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, + char const *_in) { - return gcli_forge()->fork_create(owner, repo, _in); + return gcli_forge(ctx)->fork_create(ctx, owner, repo, _in); } void diff --git a/src/gcli.c b/src/gcli.c index e0d52d49..5f8aa0fb 100644 --- a/src/gcli.c +++ b/src/gcli.c @@ -1,5 +1,5 @@ /* - * Copyright 2021,2022 Nico Sonack + * Copyright 2023 Nico Sonack * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,140 +27,40 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include -#ifdef HAVE_GETOPT_h -#include -#endif - -#include +#include #include #include -#include - -#include -#include -static void usage(void); - -static int -subcommand_version(int argc, char *argv[]) +char const * +gcli_init(gcli_ctx **ctx) { - (void) argc; - (void) argv; + *ctx = calloc(sizeof (struct gcli_ctx), 1); + if (!(*ctx)) + return strerror(errno); - version(); - copyright(); + if (gcli_config_init_ctx(*ctx) < 0) + return (*ctx)->last_error; /* TODO: cleanup */ - return EXIT_SUCCESS; -} + (*ctx)->last_error = "imagine having useful error messages in the year 2023"; -static struct subcommand { - char const *const cmd_name; - char const *const docstring; - int (*fn)(int, char **); -} subcommands[] = { - { .cmd_name = "ci", - .fn = subcommand_ci, - .docstring = "Github CI status info" }, - { .cmd_name = "comment", - .fn = subcommand_comment, - .docstring = "Comment under issues and PRs" }, - { .cmd_name = "config", - .fn = subcommand_config, - .docstring = "Configure forges" }, - { .cmd_name = "forks", - .fn = subcommand_forks, - .docstring = "Create, delete and list repository forks" }, - { .cmd_name = "gists", - .fn = subcommand_gists, - .docstring = "Create, fetch and list Github Gists" }, - { .cmd_name = "issues", - .fn = subcommand_issues, - .docstring = "Manage issues" }, - { .cmd_name = "labels", - .fn = subcommand_labels, - .docstring = "Manage issue and PR labels" }, - { .cmd_name = "milestones", - .fn = subcommand_milestones, - .docstring = "Milestone handling" }, - { .cmd_name = "pipelines", - .fn = subcommand_pipelines, - .docstring = "Gitlab CI management" }, - { .cmd_name = "pulls", - .fn = subcommand_pulls, - .docstring = "Create, view and manage PRs" }, - { .cmd_name = "releases", - .fn = subcommand_releases, - .docstring = "Manage releases of repositories" }, - { .cmd_name = "repos", - .fn = subcommand_repos, - .docstring = "Remote Repository management" }, - { .cmd_name = "snippets", - .fn = subcommand_snippets, - .docstring = "Fetch and list Gitlab snippets" }, - { .cmd_name = "status", - .fn = subcommand_status, - .docstring = "General user status and notifications" }, - { .cmd_name = "api", - .fn = subcommand_api, - .docstring = "Fetch plain JSON info from an API (for debugging purposes)" }, - { .cmd_name = "version", - .fn = subcommand_version, - .docstring = "Print version" }, -}; - -static void -usage(void) -{ - fprintf(stderr, "usage: gcli [options] subcommand\n\n"); - fprintf(stderr, "OPTIONS:\n"); - fprintf(stderr, " -a account Use the configured account instead of inferring it\n"); - fprintf(stderr, " -r remote Infer account from the given git remote\n"); - fprintf(stderr, " -t type Force the account type:\n"); - fprintf(stderr, " - github (default: github.com)\n"); - fprintf(stderr, " - gitlab (default: gitlab.com)\n"); - fprintf(stderr, " - gitea (default: codeberg.org)\n"); - fprintf(stderr, " -c Force colour and text formatting.\n"); - fprintf(stderr, " -q Be quiet. (Not implemented yet)\n\n"); - fprintf(stderr, " -v Be verbose.\n\n"); - fprintf(stderr, "SUBCOMMANDS:\n"); - for (size_t i = 0; i < ARRAY_SIZE(subcommands); ++i) { - fprintf(stderr, - " %-13.13s %s\n", - subcommands[i].cmd_name, - subcommands[i].docstring); - } - fprintf(stderr, "\n"); - version(); - copyright(); + return NULL; } -int -main(int argc, char *argv[]) +void +gcli_destroy(gcli_ctx **ctx) { - /* Parse first arguments */ - if (gcli_config_init(&argc, &argv)) { - usage(); - return EXIT_FAILURE; - } - - /* Make sure we have a subcommand */ - if (argc == 0) { - fprintf(stderr, "error: missing subcommand\n"); - usage(); - return EXIT_FAILURE; - } + if (ctx && *ctx) { + free(*ctx); + *ctx = NULL; - /* Find and invoke the subcommand handler */ - for (size_t i = 0; i < ARRAY_SIZE(subcommands); ++i) { - if (strcmp(subcommands[i].cmd_name, argv[0]) == 0) - return subcommands[i].fn(argc, argv); + /* TODO: other deinit stuff? */ } +} - /* No subcommand matched */ - fprintf(stderr, "error: unknown subcommand %s\n", argv[0]); - usage(); - - return EXIT_FAILURE; +char const * +gcli_get_error(gcli_ctx *ctx) +{ + return ctx->last_error; } diff --git a/src/gitconfig.c b/src/gitconfig.c index a4768d99..4ff671a7 100644 --- a/src/gitconfig.c +++ b/src/gitconfig.c @@ -485,8 +485,9 @@ gcli_gitconfig_add_fork_remote(char const *org, char const *repo) * Return the gcli_forge_type for the given remote or -1 if * unknown */ int -gcli_gitconfig_get_forgetype(char const *const remote_name) +gcli_gitconfig_get_forgetype(gcli_ctx *ctx, char const *const remote_name) { + (void) ctx; gcli_gitconfig_read_gitconfig(); if (remote_name) { diff --git a/src/gitea/comments.c b/src/gitea/comments.c index 44241342..c58b7efd 100644 --- a/src/gitea/comments.c +++ b/src/gitea/comments.c @@ -31,15 +31,15 @@ #include int -gitea_get_comments(char const *owner, char const *repo, +gitea_get_comments(gcli_ctx *ctx, char const *owner, char const *repo, int const issue, gcli_comment_list *const out) { - return github_get_comments(owner, repo, issue, out); + return github_get_comments(ctx, owner, repo, issue, out); } int -gitea_perform_submit_comment(gcli_submit_comment_opts opts, +gitea_perform_submit_comment(gcli_ctx *ctx, gcli_submit_comment_opts opts, gcli_fetch_buffer *const out) { - return github_perform_submit_comment(opts, out); + return github_perform_submit_comment(ctx, opts, out); } diff --git a/src/gitea/config.c b/src/gitea/config.c index f0724e15..4e9572f6 100644 --- a/src/gitea/config.c +++ b/src/gitea/config.c @@ -33,16 +33,17 @@ #include static sn_sv -gitea_default_account_name(void) +gitea_default_account_name(gcli_ctx *ctx) { sn_sv section_name; /* Use default override account */ - section_name = gcli_config_get_override_default_account(); + section_name = gcli_config_get_override_default_account(ctx); /* If not manually overridden */ if (sn_sv_null(section_name)) { section_name = gcli_config_find_by_key( + ctx, SV("defaults"), "gitea-default-account"); @@ -55,13 +56,13 @@ gitea_default_account_name(void) } char * -gitea_get_apibase(void) +gitea_get_apibase(gcli_ctx *ctx) { - sn_sv const account = gitea_default_account_name(); + sn_sv const account = gitea_default_account_name(ctx); if (sn_sv_null(account)) goto default_val; - sn_sv const api_base = gcli_config_find_by_key(account, "apibase"); + sn_sv const api_base = gcli_config_find_by_key(ctx, account, "apibase"); if (sn_sv_null(api_base)) goto default_val; @@ -72,13 +73,13 @@ gitea_get_apibase(void) } char * -gitea_get_authheader(void) +gitea_get_authheader(gcli_ctx *ctx) { - sn_sv const account = gitea_default_account_name(); + sn_sv const account = gitea_default_account_name(ctx); if (sn_sv_null(account)) return NULL; - sn_sv const token = gcli_config_find_by_key(account, "token");; + sn_sv const token = gcli_config_find_by_key(ctx, account, "token");; if (sn_sv_null(token)) { warnx("Missing Gitea token"); return NULL; @@ -88,13 +89,13 @@ gitea_get_authheader(void) } sn_sv -gitea_get_account(void) +gitea_get_account(gcli_ctx *ctx) { - sn_sv const section = gitea_default_account_name(); + sn_sv const section = gitea_default_account_name(ctx); if (sn_sv_null(section)) return SV_NULL; - sn_sv const account = gcli_config_find_by_key(section, "account");; + sn_sv const account = gcli_config_find_by_key(ctx, section, "account");; if (!account.length) errx(1, "Missing Gitea account name"); return account; diff --git a/src/gitea/forks.c b/src/gitea/forks.c index 108e84ea..6ddf9cf3 100644 --- a/src/gitea/forks.c +++ b/src/gitea/forks.c @@ -33,18 +33,15 @@ #include int -gitea_get_forks(char const *owner, - char const *repo, - int const max, - gcli_fork_list *const out) +gitea_get_forks(gcli_ctx *ctx, char const *owner, char const *repo, + int const max, gcli_fork_list *const out) { - return github_get_forks(owner, repo, max, out); + return github_get_forks(ctx, owner, repo, max, out); } void -gitea_fork_create(char const *owner, - char const *repo, +gitea_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, char const *_in) { - github_fork_create(owner, repo, _in); + github_fork_create(ctx, owner, repo, _in); } diff --git a/src/gitea/issues.c b/src/gitea/issues.c index c851e0f3..eace78af 100644 --- a/src/gitea/issues.c +++ b/src/gitea/issues.c @@ -38,53 +38,49 @@ #include int -gitea_get_issues(char const *owner, - char const *repo, - gcli_issue_fetch_details const *details, - int const max, +gitea_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_issue_fetch_details const *details, int const max, gcli_issue_list *const out) { - return github_get_issues(owner, repo, details, max, out); + return github_get_issues(ctx, owner, repo, details, max, out); } int -gitea_get_issue_summary(char const *owner, char const *repo, +gitea_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, int const issue_number, gcli_issue *const out) { - return github_get_issue_summary(owner, repo, issue_number, out); + return github_get_issue_summary(ctx, owner, repo, issue_number, out); } int -gitea_submit_issue(gcli_submit_issue_options opts, +gitea_submit_issue(gcli_ctx *ctx, gcli_submit_issue_options opts, gcli_fetch_buffer *const out) { - return github_perform_submit_issue(opts, out); + return github_perform_submit_issue(ctx,opts, out); } /* Gitea has closed, Github has close ... go figure */ static int -gitea_issue_patch_state(char const *owner, - char const *repo, - int const issue_number, - char const *const state) +gitea_issue_patch_state(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue_number, char const *const state) { - char *url = NULL; - char *data = NULL; + char *url = NULL; + char *data = NULL; char *e_owner = NULL; - char *e_repo = NULL; - int rc = 0; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); url = sn_asprintf( "%s/repos/%s/%s/issues/%d", - gitea_get_apibase(), + gitea_get_apibase(ctx), e_owner, e_repo, issue_number); data = sn_asprintf("{ \"state\": \"%s\"}", state); - rc = gcli_fetch_with_method("PATCH", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PATCH", url, data, NULL, NULL); free(data); free(url); @@ -95,33 +91,29 @@ gitea_issue_patch_state(char const *owner, } int -gitea_issue_close(char const *owner, - char const *repo, +gitea_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, int const issue_number) { - return gitea_issue_patch_state(owner, repo, issue_number, "closed"); + return gitea_issue_patch_state(ctx, owner, repo, issue_number, "closed"); } int -gitea_issue_reopen(char const *owner, - char const *repo, +gitea_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, int const issue_number) { - return gitea_issue_patch_state(owner, repo, issue_number, "open"); + return gitea_issue_patch_state(ctx, owner, repo, issue_number, "open"); } int -gitea_issue_assign(char const *owner, - char const *repo, - int const issue_number, - char const *const assignee) +gitea_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue_number, char const *const assignee) { - sn_sv escaped_assignee = SV_NULL; - char *post_fields = NULL; - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - int rc = 0; + sn_sv escaped_assignee = SV_NULL; + char *post_fields = NULL; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; escaped_assignee = gcli_json_escape(SV((char *)assignee)); post_fields = sn_asprintf("{ \"assignees\": [\""SV_FMT"\"] }", @@ -132,9 +124,9 @@ gitea_issue_assign(char const *owner, url = sn_asprintf( "%s/repos/%s/%s/issues/%d", - gitea_get_apibase(), e_owner, e_repo, issue_number); + gitea_get_apibase(ctx), e_owner, e_repo, issue_number); - rc = gcli_fetch_with_method("PATCH", url, post_fields, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PATCH", url, post_fields, NULL, NULL); free(escaped_assignee.data); free(post_fields); @@ -157,16 +149,14 @@ get_id_of_label(char const *label_name, } static char ** -label_names_to_ids(char const *owner, - char const *repo, - char const *const names[], - size_t const names_size) +label_names_to_ids(gcli_ctx *ctx, char const *owner, char const *repo, + char const *const names[], size_t const names_size) { gcli_label_list list = {0}; char **ids = NULL; size_t ids_size = 0; - gitea_get_labels(owner, repo, -1, &list); + gitea_get_labels(ctx, owner, repo, -1, &list); for (size_t i = 0; i < names_size; ++i) { char *const label_id = get_id_of_label(names[i], &list); @@ -193,19 +183,17 @@ free_id_list(char *list[], size_t const list_size) } int -gitea_issue_add_labels(char const *owner, - char const *repo, - int const issue, - char const *const labels[], +gitea_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue, char const *const labels[], size_t const labels_size) { char *list = NULL; char *data = NULL; - char *url = NULL; - int rc = 0; + char *url = NULL; + int rc = 0; /* First, convert to ids */ - char **ids = label_names_to_ids(owner, repo, labels, labels_size); + char **ids = label_names_to_ids(ctx, owner, repo, labels, labels_size); /* Construct json payload */ @@ -214,9 +202,9 @@ gitea_issue_add_labels(char const *owner, data = sn_asprintf("{ \"labels\": [%s] }", list); url = sn_asprintf("%s/repos/%s/%s/issues/%d/labels", - gitea_get_apibase(), owner, repo, issue); + gitea_get_apibase(ctx), owner, repo, issue); - rc = gcli_fetch_with_method("POST", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "POST", url, data, NULL, NULL); free(list); free(data); @@ -227,24 +215,22 @@ gitea_issue_add_labels(char const *owner, } int -gitea_issue_remove_labels(char const *owner, - char const *repo, - int const issue, - char const *const labels[], +gitea_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue, char const *const labels[], size_t const labels_size) { int rc = 0; /* Unfortunately the gitea api does not give us an endpoint to * delete labels from an issue in bulk. So, just iterate over the * given labels and delete them one after another. */ - char **ids = label_names_to_ids(owner, repo, labels, labels_size); + char **ids = label_names_to_ids(ctx, owner, repo, labels, labels_size); for (size_t i = 0; i < labels_size; ++i) { char *url = NULL; url = sn_asprintf("%s/repos/%s/%s/issues/%d/labels/%s", - gitea_get_apibase(), owner, repo, issue, ids[i]); - rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + gitea_get_apibase(ctx), owner, repo, issue, ids[i]); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); @@ -258,18 +244,16 @@ gitea_issue_remove_labels(char const *owner, } int -gitea_issue_set_milestone(char const *const owner, - char const *const repo, - int const issue, +gitea_issue_set_milestone(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const issue, int const milestone) { - return github_issue_set_milestone(owner, repo, issue, milestone); + return github_issue_set_milestone(ctx, owner, repo, issue, milestone); } int -gitea_issue_clear_milestone(char const *owner, - char const *repo, - int issue) +gitea_issue_clear_milestone(gcli_ctx *ctx, char const *owner, + char const *repo, int issue) { - return github_issue_set_milestone(owner, repo, issue, 0); + return github_issue_set_milestone(ctx, owner, repo, issue, 0); } diff --git a/src/gitea/labels.c b/src/gitea/labels.c index e5059b88..1229cf2e 100644 --- a/src/gitea/labels.c +++ b/src/gitea/labels.c @@ -36,35 +36,31 @@ #include int -gitea_get_labels(char const *owner, - char const *reponame, - int max, - gcli_label_list *const list) +gitea_get_labels(gcli_ctx *ctx, char const *owner, char const *reponame, + int max, gcli_label_list *const list) { - return github_get_labels(owner, reponame, max, list); + return github_get_labels(ctx, owner, reponame, max, list); } int -gitea_create_label(char const *owner, - char const *repo, +gitea_create_label(gcli_ctx *ctx, char const *owner, char const *repo, gcli_label *const label) { - return github_create_label(owner, repo, label); + return github_create_label(ctx, owner, repo, label); } int -gitea_delete_label(char const *owner, - char const *repo, +gitea_delete_label(gcli_ctx *ctx, char const *owner, char const *repo, char const *label) { - char *url = NULL; - gcli_label_list list = {0}; - int id = -1; - int rc = 0; + char *url = NULL; + gcli_label_list list = {0}; + int id = -1; + int rc = 0; /* Gitea wants the id of the label, not its name. thus fetch all * the labels first to then find out what the id is we need. */ - rc = gitea_get_labels(owner, repo, -1, &list); + rc = gitea_get_labels(ctx, owner, repo, -1, &list); if (rc < 0) return rc; @@ -85,10 +81,10 @@ gitea_delete_label(char const *owner, /* DELETE /repos/{owner}/{repo}/labels/{} */ url = sn_asprintf("%s/repos/%s/%s/labels/%d", - gitea_get_apibase(), + gitea_get_apibase(ctx), owner, repo, id); - rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); gcli_free_labels(&list); free(url); diff --git a/src/gitea/milestones.c b/src/gitea/milestones.c index 976972f2..f07dfd78 100644 --- a/src/gitea/milestones.c +++ b/src/gitea/milestones.c @@ -40,15 +40,14 @@ #include int -gitea_get_milestones(char const *const owner, - char const *const repo, - int const max, +gitea_get_milestones(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const max, gcli_milestone_list *const out) { char *url; char *e_owner, *e_repo; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->milestones, .sizep = &out->milestones_size, .max = max, @@ -59,17 +58,18 @@ gitea_get_milestones(char const *const owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s/milestones", - gcli_get_apibase(), e_owner, e_repo); + gcli_get_apibase(ctx), e_owner, e_repo); free(e_owner); free(e_repo); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -gitea_get_milestone(char const *const owner, char const *const repo, - int const milestone, gcli_milestone *const out) +gitea_get_milestone(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const milestone, + gcli_milestone *const out) { char *url, *e_owner, *e_repo; gcli_fetch_buffer buffer = {0}; @@ -78,19 +78,19 @@ gitea_get_milestone(char const *const owner, char const *const repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/repos/%s/%s/milestones/%d", - gcli_get_apibase(), e_owner, e_repo, milestone); + url = sn_asprintf("%s/repos/%s/%s/milestones/%d", gcli_get_apibase(ctx), + e_owner, e_repo, milestone); free(e_owner); free(e_repo); - rc = gcli_fetch(url, NULL, &buffer); + rc = gcli_fetch(ctx, url, NULL, &buffer); if (rc == 0) { json_stream stream = {0}; json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitea_milestone(&stream, out); + parse_gitea_milestone(ctx, &stream, out); json_close(&stream); } @@ -101,15 +101,15 @@ gitea_get_milestone(char const *const owner, char const *const repo, } int -gitea_create_milestone(struct gcli_milestone_create_args const *args) +gitea_create_milestone(gcli_ctx *ctx, + struct gcli_milestone_create_args const *args) { - return github_create_milestone(args); + return github_create_milestone(ctx, args); } int -gitea_milestone_get_issues(char const *const owner, - char const *const repo, - int const milestone, +gitea_milestone_get_issues(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const milestone, gcli_issue_list *const out) { char *url, *e_owner, *e_repo; @@ -118,27 +118,25 @@ gitea_milestone_get_issues(char const *const owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s/issues?state=all&milestones=%d", - gcli_get_apibase(), e_owner, e_repo, milestone); + gcli_get_apibase(ctx), e_owner, e_repo, milestone); free(e_repo); free(e_owner); - return github_fetch_issues(url, -1, out); + return github_fetch_issues(ctx, url, -1, out); } int -gitea_delete_milestone(char const *const owner, - char const *const repo, - int const milestone) +gitea_delete_milestone(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const milestone) { - return github_delete_milestone(owner, repo, milestone); + return github_delete_milestone(ctx, owner, repo, milestone); } int -gitea_milestone_set_duedate(char const *const owner, - char const *const repo, - int const milestone, +gitea_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const milestone, char const *const date) { - return github_milestone_set_duedate(owner, repo, milestone, date); + return github_milestone_set_duedate(ctx, owner, repo, milestone, date); } diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index 811bd952..11e66a7c 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -33,46 +33,38 @@ #include int -gitea_get_pulls(char const *owner, - char const *repo, - gcli_pull_fetch_details const *const details, - int const max, +gitea_get_pulls(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_pull_fetch_details const *const details, int const max, gcli_pull_list *const out) { - return github_get_pulls(owner, repo, details, max, out); + return github_get_pulls(ctx, owner, repo, details, max, out); } int -gitea_get_pull(char const *owner, - char const *repo, - int const pr_number, - gcli_pull *const out) +gitea_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number, gcli_pull *const out) { - return github_get_pull(owner, repo, pr_number, out); + return github_get_pull(ctx, owner, repo, pr_number, out); } int -gitea_get_pull_commits(char const *owner, - char const *repo, - int const pr_number, - gcli_commit_list *const out) +gitea_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number, gcli_commit_list *const out) { - return github_get_pull_commits(owner, repo, pr_number, out); + return github_get_pull_commits(ctx, owner, repo, pr_number, out); } int -gitea_pull_submit(gcli_submit_pull_options opts) +gitea_pull_submit(gcli_ctx *ctx, gcli_submit_pull_options opts) { warnx("In case the following process errors out, see: " "https://github.com/go-gitea/gitea/issues/20175"); - return github_perform_submit_pull(opts); + return github_perform_submit_pull(ctx, opts); } int -gitea_pull_merge(char const *owner, - char const *repo, - int const pr_number, - enum gcli_merge_flags const flags) +gitea_pull_merge(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number, enum gcli_merge_flags const flags) { int rc = 0; char *url = NULL; @@ -85,12 +77,12 @@ gitea_pull_merge(char const *owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s/pulls/%d/merge", - gcli_get_apibase(), e_owner, e_repo, pr_number); + gcli_get_apibase(ctx), e_owner, e_repo, pr_number); data = sn_asprintf("{ \"Do\": \"%s\", \"delete_branch_after_merge\": %s }", squash ? "squash" : "merge", delete_branch ? "true" : "false"); - rc = gcli_fetch_with_method("POST", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "POST", url, data, NULL, NULL); free(url); free(e_owner); @@ -101,10 +93,8 @@ gitea_pull_merge(char const *owner, } static int -gitea_pulls_patch_state(char const *owner, - char const *repo, - int const pr_number, - char const *state) +gitea_pulls_patch_state(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number, char const *state) { char *url = NULL; char *data = NULL; @@ -117,12 +107,12 @@ gitea_pulls_patch_state(char const *owner, url = sn_asprintf( "%s/repos/%s/%s/pulls/%d", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state\": \"%s\"}", state); - rc = gcli_fetch_with_method("PATCH", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PATCH", url, data, NULL, NULL); free(data); free(url); @@ -133,26 +123,22 @@ gitea_pulls_patch_state(char const *owner, } int -gitea_pull_close(char const *owner, - char const *repo, +gitea_pull_close(gcli_ctx *ctx, char const *owner, char const *repo, int const pr_number) { - return gitea_pulls_patch_state(owner, repo, pr_number, "closed"); + return gitea_pulls_patch_state(ctx, owner, repo, pr_number, "closed"); } int -gitea_pull_reopen(char const *owner, - char const *repo, +gitea_pull_reopen(gcli_ctx *ctx, char const *owner, char const *repo, int const pr_number) { - return gitea_pulls_patch_state(owner, repo, pr_number, "open"); + return gitea_pulls_patch_state(ctx, owner, repo, pr_number, "open"); } int -gitea_print_pr_diff(FILE *const stream, - char const *owner, - char const *repo, - int const pr_number) +gitea_print_pr_diff(gcli_ctx *ctx, FILE *const stream, char const *owner, + char const *repo, int const pr_number) { char *url = NULL; char *e_owner = NULL; @@ -164,10 +150,10 @@ gitea_print_pr_diff(FILE *const stream, url = sn_asprintf( "%s/repos/%s/%s/pulls/%d.patch", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, pr_number); - rc = gcli_curl(stream, url, NULL); + rc = gcli_curl(ctx, stream, url, NULL); free(e_owner); free(e_repo); @@ -177,10 +163,10 @@ gitea_print_pr_diff(FILE *const stream, } int -gitea_pull_checks(char const *owner, - char const *repo, +gitea_pull_checks(gcli_ctx *ctx, char const *owner, char const *repo, int const pr_number) { + (void) ctx; (void) owner; (void) repo; (void) pr_number; @@ -191,22 +177,20 @@ gitea_pull_checks(char const *owner, } int -gitea_pull_set_milestone(char const *owner, - char const *repo, - int pr_number, - int milestone_id) +gitea_pull_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, + int pr_number, int milestone_id) { - return github_issue_set_milestone(owner, repo, pr_number, milestone_id); + return github_issue_set_milestone(ctx, owner, repo, pr_number, + milestone_id); } int -gitea_pull_clear_milestone(char const *owner, - char const *repo, +gitea_pull_clear_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number) { /* NOTE: The github routine for clearing issues sets the milestone * to null (not the integer zero). However this does not work in * the case of Gitea which clear the milestone by setting it to * the integer value zero. */ - return github_issue_set_milestone(owner, repo, pr_number, 0); + return github_issue_set_milestone(ctx, owner, repo, pr_number, 0); } diff --git a/src/gitea/releases.c b/src/gitea/releases.c index 57d7b15a..7f66f3b7 100644 --- a/src/gitea/releases.c +++ b/src/gitea/releases.c @@ -37,24 +37,24 @@ #include int -gitea_get_releases(char const *owner, char const *repo, +gitea_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, int const max, gcli_release_list *const list) { - return github_get_releases(owner, repo, max, list); + return github_get_releases(ctx, owner, repo, max, list); } static void -gitea_parse_release(gcli_fetch_buffer const *const buffer, +gitea_parse_release(gcli_ctx *ctx, gcli_fetch_buffer const *const buffer, gcli_release *const out) { json_stream stream = {0}; json_open_buffer(&stream, buffer->data, buffer->length); - parse_github_release(&stream, out); + parse_github_release(ctx, &stream, out); json_close(&stream); } static int -gitea_upload_release_asset(char *const url, +gitea_upload_release_asset(gcli_ctx *ctx, char *const url, gcli_release_asset_upload const asset) { char *e_assetname = NULL; @@ -65,7 +65,7 @@ gitea_upload_release_asset(char *const url, e_assetname = gcli_urlencode(asset.name); request = sn_asprintf("%s?name=%s", url, e_assetname); - rc = gcli_curl_gitea_upload_attachment(request, asset.path, &buffer); + rc = gcli_curl_gitea_upload_attachment(ctx, request, asset.path, &buffer); free(request); free(e_assetname); @@ -75,7 +75,7 @@ gitea_upload_release_asset(char *const url, } int -gitea_create_release(gcli_new_release const *release) +gitea_create_release(gcli_ctx *ctx, gcli_new_release const *release) { char *commitish_json = NULL; char *e_owner = NULL; @@ -95,7 +95,7 @@ gitea_create_release(gcli_new_release const *release) /* https://docs.github.com/en/rest/reference/repos#create-a-release */ url = sn_asprintf( "%s/repos/%s/%s/releases", - gcli_get_apibase(), e_owner, e_repo); + gcli_get_apibase(ctx), e_owner, e_repo); escaped_body = gcli_json_escape(release->body); @@ -123,21 +123,21 @@ gitea_create_release(gcli_new_release const *release) commitish_json ? commitish_json : "", name_json ? name_json : ""); - rc = gcli_fetch_with_method("POST", url, post_data, NULL, &buffer); + rc = gcli_fetch_with_method(ctx, "POST", url, post_data, NULL, &buffer); if (rc < 0) goto out; - gitea_parse_release(&buffer, &response); + gitea_parse_release(ctx, &buffer, &response); printf("INFO : Release at "SV_FMT"\n", SV_ARGS(response.html_url)); upload_url = sn_asprintf("%s/repos/%s/%s/releases/"SV_FMT"/assets", - gcli_get_apibase(), e_owner, e_repo, + gcli_get_apibase(ctx), e_owner, e_repo, SV_ARGS(response.id)); for (size_t i = 0; i < release->assets_size; ++i) { printf("INFO : Uploading asset %s...\n", release->assets[i].path); - rc = gitea_upload_release_asset(upload_url, release->assets[i]); + rc = gitea_upload_release_asset(ctx, upload_url, release->assets[i]); if (rc < 0) break; @@ -158,7 +158,8 @@ gitea_create_release(gcli_new_release const *release) } int -gitea_delete_release(char const *owner, char const *repo, char const *id) +gitea_delete_release(gcli_ctx *ctx, char const *owner, char const *repo, + char const *id) { - return github_delete_release(owner, repo, id); + return github_delete_release(ctx, owner, repo, id); } diff --git a/src/gitea/repos.c b/src/gitea/repos.c index 887ad26f..a8079aec 100644 --- a/src/gitea/repos.c +++ b/src/gitea/repos.c @@ -31,26 +31,27 @@ #include int -gitea_get_repos(char const *owner, int const max, gcli_repo_list *const list) +gitea_get_repos(gcli_ctx *ctx, char const *owner, int const max, + gcli_repo_list *const list) { - return github_get_repos(owner, max, list); + return github_get_repos(ctx, owner, max, list); } int -gitea_get_own_repos(int const max, gcli_repo_list *const list) +gitea_get_own_repos(gcli_ctx *ctx, int const max, gcli_repo_list *const list) { - return github_get_own_repos(max, list); + return github_get_own_repos(ctx, max, list); } int -gitea_repo_create(gcli_repo_create_options const *options, +gitea_repo_create(gcli_ctx *ctx, gcli_repo_create_options const *options, gcli_repo *const out) { - return github_repo_create(options, out); + return github_repo_create(ctx, options, out); } int -gitea_repo_delete(char const *owner, char const *repo) +gitea_repo_delete(gcli_ctx *ctx, char const *owner, char const *repo) { - return github_repo_delete(owner, repo); + return github_repo_delete(ctx, owner, repo); } diff --git a/src/gitea/sshkeys.c b/src/gitea/sshkeys.c index ae0c2532..3aa305e3 100644 --- a/src/gitea/sshkeys.c +++ b/src/gitea/sshkeys.c @@ -37,21 +37,20 @@ #include int -gitea_get_sshkeys(gcli_sshkey_list *list) +gitea_get_sshkeys(gcli_ctx *ctx, gcli_sshkey_list *list) { - return gitlab_get_sshkeys(list); + return gitlab_get_sshkeys(ctx, list); } int -gitea_add_sshkey(char const *const title, - char const *const pubkey, - gcli_sshkey *const out) +gitea_add_sshkey(gcli_ctx *ctx, char const *const title, + char const *const pubkey, gcli_sshkey *const out) { - return gitlab_add_sshkey(title, pubkey, out); + return gitlab_add_sshkey(ctx, title, pubkey, out); } int -gitea_delete_sshkey(int id) +gitea_delete_sshkey(gcli_ctx *ctx, int id) { - return gitlab_delete_sshkey(id); + return gitlab_delete_sshkey(ctx, id); } diff --git a/src/github/api.c b/src/github/api.c index 989501de..82a49e24 100644 --- a/src/github/api.c +++ b/src/github/api.c @@ -33,7 +33,7 @@ #include char const * -github_api_error_string(gcli_fetch_buffer *const it) +github_api_error_string(gcli_ctx *ctx, gcli_fetch_buffer *const it) { struct json_stream stream = {0}; enum json_type next = JSON_NULL; @@ -45,9 +45,9 @@ github_api_error_string(gcli_fetch_buffer *const it) json_set_streaming(&stream, true); while ((next = json_next(&stream)) != JSON_OBJECT_END) { - char *key = get_string(&stream); + char *key = get_string(ctx, &stream); if (strcmp(key, "message") == 0) - return get_string(&stream); + return get_string(ctx, &stream); free(key); } diff --git a/src/github/checks.c b/src/github/checks.c index 1b02f83b..bfaab5dd 100644 --- a/src/github/checks.c +++ b/src/github/checks.c @@ -42,9 +42,8 @@ #include int -github_get_checks(char const *owner, char const *repo, - char const *ref, int const max, - gcli_github_checks *const out) +github_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, + char const *ref, int const max, gcli_github_checks *const out) { gcli_fetch_buffer buffer = {0}; char *url = NULL, *next_url = NULL; @@ -53,16 +52,16 @@ github_get_checks(char const *owner, char const *repo, assert(out); url = sn_asprintf("%s/repos/%s/%s/commits/%s/check-runs", - gcli_get_apibase(), + gcli_get_apibase(ctx), owner, repo, ref); do { - rc = gcli_fetch(url, &next_url, &buffer); + rc = gcli_fetch(ctx, url, &next_url, &buffer); if (rc == 0) { struct json_stream stream = {0}; json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_checks(&stream, out); + parse_github_checks(ctx, &stream, out); json_close(&stream); } @@ -80,7 +79,7 @@ github_get_checks(char const *owner, char const *repo, } void -github_print_checks(gcli_github_checks const *const list) +github_print_checks(gcli_ctx *ctx, gcli_github_checks const *const list) { gcli_tbl table; gcli_tblcoldef cols[] = { @@ -98,7 +97,7 @@ github_print_checks(gcli_github_checks const *const list) return; } - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not init table"); @@ -128,17 +127,17 @@ github_free_checks(gcli_github_checks *const list) } int -github_checks(char const *owner, char const *repo, +github_checks(gcli_ctx *ctx, char const *owner, char const *repo, char const *ref, int const max) { gcli_github_checks checks = {0}; int rc; - rc = github_get_checks(owner, repo, ref, max, &checks); + rc = github_get_checks(ctx, owner, repo, ref, max, &checks); if (rc < 0) return rc; - github_print_checks(&checks); + github_print_checks(ctx, &checks); github_free_checks(&checks); return 0; diff --git a/src/github/comments.c b/src/github/comments.c index ff39461b..dbefcac0 100644 --- a/src/github/comments.c +++ b/src/github/comments.c @@ -37,7 +37,7 @@ #include int -github_perform_submit_comment(gcli_submit_comment_opts opts, +github_perform_submit_comment(gcli_ctx *ctx, gcli_submit_comment_opts opts, gcli_fetch_buffer *out) { int rc = 0; @@ -49,10 +49,10 @@ github_perform_submit_comment(gcli_submit_comment_opts opts, SV_ARGS(opts.message)); char *url = sn_asprintf( "%s/repos/%s/%s/issues/%d/comments", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, opts.target_id); - rc = gcli_fetch_with_method("POST", url, post_fields, NULL, out); + rc = gcli_fetch_with_method(ctx, "POST", url, post_fields, NULL, out); free(post_fields); free(e_owner); @@ -63,13 +63,13 @@ github_perform_submit_comment(gcli_submit_comment_opts opts, } int -github_get_comments(char const *owner, char const *repo, +github_get_comments(gcli_ctx *ctx, char const *owner, char const *repo, int const issue, gcli_comment_list *const out) { char *e_owner = NULL; char *e_repo = NULL; char *url = NULL; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->comments, .sizep = &out->comments_size, .parse = (parsefn)parse_github_comments, @@ -80,10 +80,10 @@ github_get_comments(char const *owner, char const *repo, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s/issues/%d/comments", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, issue); free(e_owner); free(e_repo); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } diff --git a/src/github/config.c b/src/github/config.c index 61331606..741079cf 100644 --- a/src/github/config.c +++ b/src/github/config.c @@ -32,14 +32,15 @@ #include static sn_sv -github_default_account_name(void) +github_default_account_name(gcli_ctx *ctx) { sn_sv section_name; - section_name = gcli_config_get_override_default_account(); + section_name = gcli_config_get_override_default_account(ctx); if (sn_sv_null(section_name)) { section_name = gcli_config_find_by_key( + ctx, SV("defaults"), "github-default-account"); @@ -51,13 +52,13 @@ github_default_account_name(void) } char * -github_get_apibase(void) +github_get_apibase(gcli_ctx *ctx) { - sn_sv account_name = github_default_account_name(); + sn_sv account_name = github_default_account_name(ctx); if (sn_sv_null(account_name)) goto default_val; - sn_sv api_base = gcli_config_find_by_key(account_name, "apibase"); + sn_sv api_base = gcli_config_find_by_key(ctx, account_name, "apibase"); if (sn_sv_null(api_base)) goto default_val; @@ -69,26 +70,26 @@ github_get_apibase(void) } char * -github_get_authheader(void) +github_get_authheader(gcli_ctx *ctx) { - sn_sv const account = github_default_account_name(); + sn_sv const account = github_default_account_name(ctx); if (sn_sv_null(account)) return NULL; - sn_sv const token = gcli_config_find_by_key(account, "token");; + sn_sv const token = gcli_config_find_by_key(ctx, account, "token"); if (sn_sv_null(token)) errx(1, "Missing Github token"); return sn_asprintf("Authorization: token "SV_FMT, SV_ARGS(token)); } sn_sv -github_get_account(void) +github_get_account(gcli_ctx *ctx) { - sn_sv const section = github_default_account_name(); + sn_sv const section = github_default_account_name(ctx); if (sn_sv_null(section)) return SV_NULL; - sn_sv const account = gcli_config_find_by_key(section, "account");; + sn_sv const account = gcli_config_find_by_key(ctx, section, "account");; if (!account.length) errx(1, "Missing Github account name"); return account; diff --git a/src/github/forks.c b/src/github/forks.c index b8f8d648..095e9278 100644 --- a/src/github/forks.c +++ b/src/github/forks.c @@ -38,14 +38,14 @@ #include int -github_get_forks(char const *owner, char const *repo, +github_get_forks(gcli_ctx *ctx, char const *owner, char const *repo, int const max, gcli_fork_list *const list) { char *url = NULL; char *e_owner = NULL; char *e_repo = NULL; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &list->forks, .sizep = &list->forks_size, .max = max, @@ -59,17 +59,18 @@ github_get_forks(char const *owner, char const *repo, url = sn_asprintf( "%s/repos/%s/%s/forks", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo); free(e_owner); free(e_repo); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -github_fork_create(char const *owner, char const *repo, char const *_in) +github_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, + char const *_in) { char *url = NULL; char *e_owner = NULL; @@ -82,7 +83,7 @@ github_fork_create(char const *owner, char const *repo, char const *_in) e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s/forks", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo); if (_in) { in = gcli_json_escape(SV((char *)_in)); @@ -90,7 +91,7 @@ github_fork_create(char const *owner, char const *repo, char const *_in) SV_ARGS(in)); } - rc = gcli_fetch_with_method("POST", url, post_data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "POST", url, post_data, NULL, NULL); free(in.data); free(url); diff --git a/src/github/gists.c b/src/github/gists.c index a6acbeeb..a09cdd50 100644 --- a/src/github/gists.c +++ b/src/github/gists.c @@ -42,8 +42,11 @@ /* /!\ Before changing this, see comment in gists.h /!\ */ void -parse_github_gist_files_idiot_hack(json_stream *stream, gcli_gist *const gist) +parse_github_gist_files_idiot_hack(gcli_ctx *ctx, json_stream *stream, + gcli_gist *const gist) { + (void) ctx; + enum json_type next = JSON_NULL; gist->files = NULL; @@ -55,7 +58,7 @@ parse_github_gist_files_idiot_hack(json_stream *stream, gcli_gist *const gist) while ((next = json_next(stream)) == JSON_STRING) { gist->files = realloc(gist->files, sizeof(*gist->files) * (gist->files_size + 1)); gcli_gist_file *it = &gist->files[gist->files_size++]; - parse_github_gist_file(stream, it); + parse_github_gist_file(ctx, stream, it); } if (next != JSON_OBJECT_END) @@ -63,10 +66,11 @@ parse_github_gist_files_idiot_hack(json_stream *stream, gcli_gist *const gist) } int -gcli_get_gists(char const *user, int const max, gcli_gist_list *const list) +gcli_get_gists(gcli_ctx *ctx, char const *user, int const max, + gcli_gist_list *const list) { char *url = NULL; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &list->gists, .sizep = &list->gists_size, .parse = (parsefn)(parse_github_gists), @@ -76,12 +80,12 @@ gcli_get_gists(char const *user, int const max, gcli_gist_list *const list) if (user) url = sn_asprintf( "%s/users/%s/gists", - github_get_apibase(), + github_get_apibase(ctx), user); else - url = sn_asprintf("%s/gists", github_get_apibase()); + url = sn_asprintf("%s/gists", github_get_apibase(ctx)); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } static char const * @@ -118,7 +122,8 @@ print_gist_file(gcli_gist_file const *const file) } static void -print_gist(enum gcli_output_flags const flags, gcli_gist const *const gist) +print_gist(gcli_ctx *ctx, enum gcli_output_flags const flags, + gcli_gist const *const gist) { (void) flags; @@ -128,8 +133,8 @@ print_gist(enum gcli_output_flags const flags, gcli_gist const *const gist) " DATE : "SV_FMT"\n" " URL : "SV_FMT"\n" " PULL : "SV_FMT"\n", - gcli_setcolour(GCLI_COLOR_YELLOW), SV_ARGS(gist->id), gcli_resetcolour(), - gcli_setbold(), SV_ARGS(gist->owner), gcli_resetbold(), + gcli_setcolour(ctx, GCLI_COLOR_YELLOW), SV_ARGS(gist->id), gcli_resetcolour(ctx), + gcli_setbold(ctx), SV_ARGS(gist->owner), gcli_resetbold(ctx), SV_ARGS(gist->description), SV_ARGS(gist->date), SV_ARGS(gist->url), @@ -144,9 +149,8 @@ print_gist(enum gcli_output_flags const flags, gcli_gist const *const gist) } static void -gcli_print_gists_long(enum gcli_output_flags const flags, - gcli_gist_list const *const list, - int const max) +gcli_print_gists_long(gcli_ctx *ctx, enum gcli_output_flags const flags, + gcli_gist_list const *const list, int const max) { size_t n; @@ -157,17 +161,16 @@ gcli_print_gists_long(enum gcli_output_flags const flags, if (flags & OUTPUT_SORTED) { for (size_t i = 0; i < n; ++i) - print_gist(flags, &list->gists[n-i-1]); + print_gist(ctx, flags, &list->gists[n-i-1]); } else { for (size_t i = 0; i < n; ++i) - print_gist(flags, &list->gists[i]); + print_gist(ctx, flags, &list->gists[i]); } } static void -gcli_print_gists_short(enum gcli_output_flags const flags, - gcli_gist_list const *const list, - int const max) +gcli_print_gists_short(gcli_ctx *ctx, enum gcli_output_flags const flags, + gcli_gist_list const *const list, int const max) { size_t n; gcli_tbl table; @@ -184,7 +187,7 @@ gcli_print_gists_short(enum gcli_output_flags const flags, else n = max; - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not init table"); @@ -212,9 +215,8 @@ gcli_print_gists_short(enum gcli_output_flags const flags, } void -gcli_print_gists(enum gcli_output_flags const flags, - gcli_gist_list const *const list, - int const max) +gcli_print_gists(gcli_ctx *ctx, enum gcli_output_flags const flags, + gcli_gist_list const *const list, int const max) { if (list->gists_size == 0) { puts("No Gists"); @@ -222,21 +224,21 @@ gcli_print_gists(enum gcli_output_flags const flags, } if (flags & OUTPUT_LONG) /* if we are in long mode (no pun intended) */ - gcli_print_gists_long(flags, list, max); + gcli_print_gists_long(ctx, flags, list, max); else /* real mode (bad joke, I know) */ - gcli_print_gists_short(flags, list, max); + gcli_print_gists_short(ctx, flags, list, max); } gcli_gist * -gcli_get_gist(char const *gist_id) +gcli_get_gist(gcli_ctx *ctx, char const *gist_id) { char *url = NULL; gcli_fetch_buffer buffer = {0}; gcli_gist *it = NULL; int rc = 0; - url = sn_asprintf("%s/gists/%s", github_get_apibase(), gist_id); - rc = gcli_fetch(url, NULL, &buffer); + url = sn_asprintf("%s/gists/%s", github_get_apibase(ctx), gist_id); + rc = gcli_fetch(ctx, url, NULL, &buffer); if (rc == 0) { struct json_stream stream = {0}; @@ -245,7 +247,7 @@ gcli_get_gist(char const *gist_id) json_set_streaming(&stream, 1); it = calloc(sizeof(gcli_gist), 1); - parse_github_gist(&stream, it); + parse_github_gist(ctx, &stream, it); json_close(&stream); } @@ -276,7 +278,7 @@ read_file(FILE *f, char **out) } void -gcli_create_gist(gcli_new_gist opts) +gcli_create_gist(gcli_ctx *ctx, gcli_new_gist opts) { char *url = NULL; char *post_data = NULL; @@ -306,7 +308,7 @@ gcli_create_gist(gcli_new_gist opts) */ /* TODO: Escape gist_description and file_name */ - url = sn_asprintf("%s/gists", github_get_apibase()); + url = sn_asprintf("%s/gists", github_get_apibase(ctx)); post_data = sn_asprintf( "{\"description\":\"%s\",\"public\":true,\"files\":" "{\"%s\": {\"content\":\""SV_FMT"\"}}}", @@ -314,8 +316,8 @@ gcli_create_gist(gcli_new_gist opts) opts.file_name, SV_ARGS(content)); - gcli_fetch_with_method("POST", url, post_data, NULL, &fetch_buffer); - gcli_print_html_url(fetch_buffer); + gcli_fetch_with_method(ctx, "POST", url, post_data, NULL, &fetch_buffer); + gcli_print_html_url(ctx, fetch_buffer); free(read_buffer.data); free(fetch_buffer.data); @@ -324,20 +326,20 @@ gcli_create_gist(gcli_new_gist opts) } void -gcli_delete_gist(char const *gist_id, bool const always_yes) +gcli_delete_gist(gcli_ctx *ctx, char const *gist_id, bool const always_yes) { char *url = NULL; gcli_fetch_buffer buffer = {0}; url = sn_asprintf( "%s/gists/%s", - github_get_apibase(), + github_get_apibase(ctx), gist_id); if (!always_yes && !sn_yesno("Are you sure you want to delete this gist?")) errx(1, "Aborted by user"); - gcli_fetch_with_method("DELETE", url, NULL, NULL, &buffer); + gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, &buffer); free(buffer.data); free(url); diff --git a/src/github/issues.c b/src/github/issues.c index 23999bb6..c66f9430 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -66,10 +66,10 @@ github_hack_fixup_issues_that_are_actually_pulls(gcli_issue **list, size_t *size } int -github_fetch_issues(char *url, int const max, +github_fetch_issues(gcli_ctx *ctx, char *url, int const max, gcli_issue_list *const out) { - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->issues, .sizep = &out->issues_size, .parse = (parsefn)(parse_github_issues), @@ -77,14 +77,12 @@ github_fetch_issues(char *url, int const max, .max = max, }; - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -github_get_issues(char const *owner, - char const *repo, - gcli_issue_fetch_details const *details, - int const max, +github_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_issue_fetch_details const *details, int const max, gcli_issue_list *const out) { char *url = NULL; @@ -103,7 +101,7 @@ github_get_issues(char const *owner, url = sn_asprintf( "%s/repos/%s/%s/issues?state=%s%s", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, details->all ? "all" : "open", e_author ? e_author : ""); @@ -112,11 +110,11 @@ github_get_issues(char const *owner, free(e_owner); free(e_repo); - return github_fetch_issues(url, max, out); + return github_fetch_issues(ctx, url, max, out); } int -github_get_issue_summary(char const *owner, char const *repo, +github_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, int const issue_number, gcli_issue *const out) { char *url = NULL; @@ -131,16 +129,16 @@ github_get_issue_summary(char const *owner, char const *repo, url = sn_asprintf( "%s/repos/%s/%s/issues/%d", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, issue_number); - rc = gcli_fetch(url, NULL, &buffer); + rc = gcli_fetch(ctx, url, NULL, &buffer); if (rc == 0) { json_open_buffer(&parser, buffer.data, buffer.length); json_set_streaming(&parser, true); - parse_github_issue(&parser, out); + parse_github_issue(ctx, &parser, out); json_close(&parser); } @@ -153,25 +151,26 @@ github_get_issue_summary(char const *owner, char const *repo, } int -github_issue_close(char const *owner, char const *repo, int const issue_number) +github_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue_number) { - char *url = NULL; - char *data = NULL; + char *url = NULL; + char *data = NULL; char *e_owner = NULL; - char *e_repo = NULL; - int rc = 0; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); url = sn_asprintf( "%s/repos/%s/%s/issues/%d", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, issue_number); data = sn_asprintf("{ \"state\": \"close\"}"); - rc = gcli_fetch_with_method("PATCH", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PATCH", url, data, NULL, NULL); free(data); free(url); @@ -182,25 +181,26 @@ github_issue_close(char const *owner, char const *repo, int const issue_number) } int -github_issue_reopen(char const *owner, char const *repo, int const issue_number) +github_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue_number) { - char *url = NULL; - char *data = NULL; + char *url = NULL; + char *data = NULL; char *e_owner = NULL; - char *e_repo = NULL; - int rc = 0; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); url = sn_asprintf( "%s/repos/%s/%s/issues/%d", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, issue_number); data = sn_asprintf("{ \"state\": \"open\"}"); - rc = gcli_fetch_with_method("PATCH", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PATCH", url, data, NULL, NULL); free(data); free(url); @@ -211,23 +211,23 @@ github_issue_reopen(char const *owner, char const *repo, int const issue_number) } int -github_perform_submit_issue(gcli_submit_issue_options opts, +github_perform_submit_issue(gcli_ctx *ctx, gcli_submit_issue_options opts, gcli_fetch_buffer *out) { - char *e_owner = gcli_urlencode(opts.owner); - char *e_repo = gcli_urlencode(opts.repo); - sn_sv e_title = gcli_json_escape(opts.title); - sn_sv e_body = gcli_json_escape(opts.body); - int rc = 0; + char *e_owner = gcli_urlencode(opts.owner); + char *e_repo = gcli_urlencode(opts.repo); + sn_sv e_title = gcli_json_escape(opts.title); + sn_sv e_body = gcli_json_escape(opts.body); + int rc = 0; char *post_fields = sn_asprintf( "{ \"title\": \""SV_FMT"\", \"body\": \""SV_FMT"\" }", SV_ARGS(e_title), SV_ARGS(e_body)); char *url = sn_asprintf("%s/repos/%s/%s/issues", - gcli_get_apibase(), e_owner, e_repo); + gcli_get_apibase(ctx), e_owner, e_repo); - rc = gcli_fetch_with_method("POST", url, post_fields, NULL, out); + rc = gcli_fetch_with_method(ctx, "POST", url, post_fields, NULL, out); free(e_owner); free(e_repo); @@ -240,30 +240,28 @@ github_perform_submit_issue(gcli_submit_issue_options opts, } int -github_issue_assign(char const *owner, - char const *repo, - int const issue_number, - char const *assignee) +github_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue_number, char const *assignee) { - sn_sv escaped_assignee = SV_NULL; - char *post_fields = NULL; - char *url = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - int rc = 0; + sn_sv escaped_assignee = SV_NULL; + char *post_fields = NULL; + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; escaped_assignee = gcli_json_escape(SV((char *)assignee)); post_fields = sn_asprintf("{ \"assignees\": [\""SV_FMT"\"] }", SV_ARGS(escaped_assignee)); e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); url = sn_asprintf( "%s/repos/%s/%s/issues/%d/assignees", - gcli_get_apibase(), e_owner, e_repo, issue_number); + gcli_get_apibase(ctx), e_owner, e_repo, issue_number); - rc = gcli_fetch_with_method("POST", url, post_fields, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "POST", url, post_fields, NULL, NULL); free(escaped_assignee.data); free(post_fields); @@ -275,26 +273,24 @@ github_issue_assign(char const *owner, } int -github_issue_add_labels(char const *owner, - char const *repo, - int const issue, - char const *const labels[], +github_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue, char const *const labels[], size_t const labels_size) { - char *url = NULL; + char *url = NULL; char *data = NULL; char *list = NULL; - int rc = 0; + int rc = 0; assert(labels_size > 0); url = sn_asprintf("%s/repos/%s/%s/issues/%d/labels", - gcli_get_apibase(), owner, repo, issue); + gcli_get_apibase(ctx), owner, repo, issue); list = sn_join_with(labels, labels_size, "\",\""); data = sn_asprintf("{ \"labels\": [\"%s\"]}", list); - rc = gcli_fetch_with_method("POST", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "POST", url, data, NULL, NULL); free(url); free(data); @@ -304,15 +300,13 @@ github_issue_add_labels(char const *owner, } int -github_issue_remove_labels(char const *owner, - char const *repo, - int const issue, - char const *const labels[], +github_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue, char const *const labels[], size_t const labels_size) { - char *url = NULL; + char *url = NULL; char *e_label = NULL; - int rc = 0; + int rc = 0; if (labels_size != 1) errx(1, "error: GitHub only supports removing labels from " @@ -321,9 +315,9 @@ github_issue_remove_labels(char const *owner, e_label = gcli_urlencode(labels[0]); url = sn_asprintf("%s/repos/%s/%s/issues/%d/labels/%s", - gcli_get_apibase(), owner, repo, issue, e_label); + gcli_get_apibase(ctx), owner, repo, issue, e_label); - rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); free(e_label); @@ -332,9 +326,8 @@ github_issue_remove_labels(char const *owner, } int -github_issue_set_milestone(char const *const owner, - char const *const repo, - int const issue, +github_issue_set_milestone(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const issue, int const milestone) { char *url, *e_owner, *e_repo, *body; @@ -344,12 +337,12 @@ github_issue_set_milestone(char const *const owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s/issues/%d", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, issue); body = sn_asprintf("{ \"milestone\": %d }", milestone); - rc = gcli_fetch_with_method("PATCH", url, body, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PATCH", url, body, NULL, NULL); free(body); free(url); @@ -360,9 +353,8 @@ github_issue_set_milestone(char const *const owner, } int -github_issue_clear_milestone(char const *const owner, - char const *const repo, - int const issue) +github_issue_clear_milestone(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const issue) { char *url, *e_owner, *e_repo, *body; int rc; @@ -371,12 +363,12 @@ github_issue_clear_milestone(char const *const owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s/issues/%d", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, issue); body = sn_asprintf("{ \"milestone\": null }"); - rc = gcli_fetch_with_method("PATCH", url, body, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PATCH", url, body, NULL, NULL); free(body); free(url); diff --git a/src/github/labels.c b/src/github/labels.c index 7b0e81ff..55def263 100644 --- a/src/github/labels.c +++ b/src/github/labels.c @@ -36,13 +36,11 @@ #include int -github_get_labels(char const *owner, - char const *reponame, - int const max, - gcli_label_list *const out) +github_get_labels(gcli_ctx *ctx, char const *owner, char const *reponame, + int const max, gcli_label_list *const out) { char *url = NULL; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->labels, .sizep= &out->labels_size, .parse = (parsefn)(parse_github_labels), @@ -53,27 +51,26 @@ github_get_labels(char const *owner, url = sn_asprintf( "%s/repos/%s/%s/labels", - gcli_get_apibase(), owner, reponame); + gcli_get_apibase(ctx), owner, reponame); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -github_create_label(char const *owner, - char const *repo, +github_create_label(gcli_ctx *ctx, char const *owner, char const *repo, gcli_label *const label) { - char *url = NULL; - char *data = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - char *colour = NULL; - sn_sv label_name = SV_NULL; - sn_sv label_descr = SV_NULL; - sn_sv label_colour = SV_NULL; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; - int rc = 0; + char *url = NULL; + char *data = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + char *colour = NULL; + sn_sv label_name = SV_NULL; + sn_sv label_descr = SV_NULL; + sn_sv label_colour = SV_NULL; + gcli_fetch_buffer buffer = {0}; + struct json_stream stream = {0}; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -86,7 +83,7 @@ github_create_label(char const *owner, /* /repos/{owner}/{repo}/labels */ url = sn_asprintf("%s/repos/%s/%s/labels", - gcli_get_apibase(), e_owner, e_repo); + gcli_get_apibase(ctx), e_owner, e_repo); data = sn_asprintf("{ " @@ -98,11 +95,11 @@ github_create_label(char const *owner, SV_ARGS(label_descr), SV_ARGS(label_colour)); - rc = gcli_fetch_with_method("POST", url, data, NULL, &buffer); + rc = gcli_fetch_with_method(ctx, "POST", url, data, NULL, &buffer); if (rc == 0) { json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_label(&stream, label); + parse_github_label(ctx, &stream, label); json_close(&stream); } @@ -120,22 +117,21 @@ github_create_label(char const *owner, } int -github_delete_label(char const *owner, - char const *repo, +github_delete_label(gcli_ctx *ctx, char const *owner, char const *repo, char const *label) { - char *url = NULL; + char *url = NULL; char *e_label = NULL; - int rc = 0; + int rc = 0; e_label = gcli_urlencode(label); /* DELETE /repos/{owner}/{repo}/labels/{name} */ url = sn_asprintf("%s/repos/%s/%s/labels/%s", - gcli_get_apibase(), + gcli_get_apibase(ctx), owner, repo, e_label); - rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); free(e_label); diff --git a/src/github/milestones.c b/src/github/milestones.c index d874324e..f5ce7a79 100644 --- a/src/github/milestones.c +++ b/src/github/milestones.c @@ -43,13 +43,12 @@ #include int -github_get_milestones(char const *const owner, - char const *const repo, - int const max, +github_get_milestones(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const max, gcli_milestone_list *const out) { char *url, *e_owner, *e_repo; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->milestones, .sizep = &out->milestones_size, .parse = (parsefn)parse_github_milestones, @@ -60,19 +59,18 @@ github_get_milestones(char const *const owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s/milestones", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo); free(e_owner); free(e_repo); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -github_get_milestone(char const *const owner, - char const *const repo, - int const milestone, +github_get_milestone(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const milestone, gcli_milestone *const out) { char *url, *e_owner, *e_repo; @@ -83,17 +81,17 @@ github_get_milestone(char const *const owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s/milestones/%d", - gcli_get_apibase(), e_owner, e_repo, milestone); + gcli_get_apibase(ctx), e_owner, e_repo, milestone); free(e_repo); free(e_owner); - rc = gcli_fetch(url, NULL, &buffer); + rc = gcli_fetch(ctx, url, NULL, &buffer); if (rc == 0) { json_stream stream = {0}; json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_milestone(&stream, out); + parse_github_milestone(ctx, &stream, out); json_close(&stream); } @@ -104,9 +102,8 @@ github_get_milestone(char const *const owner, } int -github_milestone_get_issues(char const *const owner, - char const *const repo, - int const milestone, +github_milestone_get_issues(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const milestone, gcli_issue_list *const out) { char *url, *e_owner, *e_repo; @@ -115,17 +112,18 @@ github_milestone_get_issues(char const *const owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s/issues?milestone=%d&state=all", - gcli_get_apibase(), e_owner, e_repo, milestone); + gcli_get_apibase(ctx), e_owner, e_repo, milestone); free(e_repo); free(e_owner); /* URL is freed by github_fetch_issues */ - return github_fetch_issues(url, -1, out); + return github_fetch_issues(ctx, url, -1, out); } int -github_create_milestone(struct gcli_milestone_create_args const *args) +github_create_milestone(gcli_ctx *ctx, + struct gcli_milestone_create_args const *args) { char *url, *e_owner, *e_repo; char *json_body, *description; @@ -150,9 +148,9 @@ github_create_milestone(struct gcli_milestone_create_args const *args) "}", args->title, description); url = sn_asprintf("%s/repos/%s/%s/milestones", - gcli_get_apibase(), e_owner, e_repo); + gcli_get_apibase(ctx), e_owner, e_repo); - rc = gcli_fetch_with_method("POST", url, json_body, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "POST", url, json_body, NULL, NULL); free(json_body); free(description); @@ -164,9 +162,8 @@ github_create_milestone(struct gcli_milestone_create_args const *args) } int -github_delete_milestone(char const *const owner, - char const *const repo, - int const milestone) +github_delete_milestone(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const milestone) { char *url, *e_owner, *e_repo; int rc = 0; @@ -175,11 +172,11 @@ github_delete_milestone(char const *const owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s/milestones/%d", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, milestone); - rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); free(e_repo); @@ -217,9 +214,8 @@ normalize_date_to_iso8601(char const *const input, } int -github_milestone_set_duedate(char const *const owner, - char const *const repo, - int const milestone, +github_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const milestone, char const *const date) { char *url, *e_owner, *e_repo, *payload, norm_date[21] = {0}; @@ -229,13 +225,13 @@ github_milestone_set_duedate(char const *const owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s/milestones/%d", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, milestone); normalize_date_to_iso8601(date, norm_date, sizeof norm_date); payload = sn_asprintf("{ \"due_on\": \"%s\"}", norm_date); - rc = gcli_fetch_with_method("PATCH", url, payload, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PATCH", url, payload, NULL, NULL); free(payload); free(url); diff --git a/src/github/pulls.c b/src/github/pulls.c index a51e7f51..30cf9ba3 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -69,10 +69,10 @@ github_pulls_filter_author(gcli_pull **listp, size_t *sizep, char const *const a } int -github_fetch_pulls(char *url, char const *const filter_author, +github_fetch_pulls(gcli_ctx *ctx, char *url, char const *const filter_author, int max, gcli_pull_list *const list) { - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &list->pulls, .sizep = &list->pulls_size, .parse = (parsefn)(parse_github_pulls), @@ -81,15 +81,13 @@ github_fetch_pulls(char *url, char const *const filter_author, .max = max, }; - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -github_get_pulls(char const *owner, - char const *repo, +github_get_pulls(gcli_ctx *ctx, char const *owner, char const *repo, gcli_pull_fetch_details const *const details, - int const max, - gcli_pull_list *const list) + int const max, gcli_pull_list *const list) { char *url = NULL; char *e_owner = NULL; @@ -103,19 +101,18 @@ github_get_pulls(char const *owner, url = sn_asprintf( "%s/repos/%s/%s/pulls?state=%s", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, details->all ? "all" : "open"); free(e_owner); free(e_repo); - return github_fetch_pulls(url, details->author, max, list); + return github_fetch_pulls(ctx, url, details->author, max, list); } int -github_print_pull_diff(FILE *stream, - char const *owner, char const *repo, - int const pr_number) +github_print_pull_diff(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *repo, int const pr_number) { char *url = NULL; char *e_owner = NULL; @@ -127,9 +124,9 @@ github_print_pull_diff(FILE *stream, url = sn_asprintf( "%s/repos/%s/%s/pulls/%d", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, pr_number); - rc = gcli_curl(stream, url, "Accept: application/vnd.github.v3.diff"); + rc = gcli_curl(ctx, stream, url, "Accept: application/vnd.github.v3.diff"); free(e_owner); free(e_repo); @@ -141,16 +138,15 @@ github_print_pull_diff(FILE *stream, /* TODO: figure out a way to get rid of the 3 consecutive urlencode * calls */ static int -github_pull_delete_head_branch(char const *owner, - char const *repo, - int const pr_number) +github_pull_delete_head_branch(gcli_ctx *ctx, char const *owner, + char const *repo, int const pr_number) { gcli_pull pull = {0}; char *url, *e_owner, *e_repo; char const *head_branch; int rc = 0; - github_get_pull(owner, repo, pr_number, &pull); + github_get_pull(ctx, owner, repo, pr_number, &pull); head_branch = strchr(pull.head_label, ':'); head_branch++; @@ -159,10 +155,10 @@ github_pull_delete_head_branch(char const *owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s/git/refs/heads/%s", - github_get_apibase(), e_owner, e_repo, + github_get_apibase(ctx), e_owner, e_repo, head_branch); - rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); free(e_owner); @@ -173,10 +169,8 @@ github_pull_delete_head_branch(char const *owner, } int -github_pull_merge(char const *owner, - char const *repo, - int const pr_number, - enum gcli_merge_flags const flags) +github_pull_merge(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number, enum gcli_merge_flags const flags) { char *url = NULL; char *e_owner = NULL; @@ -191,14 +185,14 @@ github_pull_merge(char const *owner, url = sn_asprintf( "%s/repos/%s/%s/pulls/%d/merge?merge_method=%s", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, pr_number, squash ? "squash" : "merge"); - rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); if (rc == 0 && delete_source) - rc = github_pull_delete_head_branch(owner, repo, pr_number); + rc = github_pull_delete_head_branch(ctx, owner, repo, pr_number); free(url); free(e_owner); @@ -208,7 +202,8 @@ github_pull_merge(char const *owner, } int -github_pull_close(char const *owner, char const *repo, int const pr_number) +github_pull_close(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number) { char *url = NULL; char *e_owner = NULL; @@ -221,11 +216,11 @@ github_pull_close(char const *owner, char const *repo, int const pr_number) url = sn_asprintf( "%s/repos/%s/%s/pulls/%d", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state\": \"closed\"}"); - rc = gcli_fetch_with_method("PATCH", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PATCH", url, data, NULL, NULL); free(url); free(e_repo); @@ -236,7 +231,8 @@ github_pull_close(char const *owner, char const *repo, int const pr_number) } int -github_pull_reopen(char const *owner, char const *repo, int const pr_number) +github_pull_reopen(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number) { char *url = NULL; char *data = NULL; @@ -249,11 +245,11 @@ github_pull_reopen(char const *owner, char const *repo, int const pr_number) url = sn_asprintf( "%s/repos/%s/%s/pulls/%d", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state\": \"open\"}"); - rc = gcli_fetch_with_method("PATCH", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PATCH", url, data, NULL, NULL); free(url); free(data); @@ -264,7 +260,7 @@ github_pull_reopen(char const *owner, char const *repo, int const pr_number) } int -github_perform_submit_pull(gcli_submit_pull_options opts) +github_perform_submit_pull(gcli_ctx *ctx, gcli_submit_pull_options opts) { sn_sv e_head, e_base, e_title, e_body; gcli_fetch_buffer fetch_buffer = {0}; @@ -286,18 +282,19 @@ github_perform_submit_pull(gcli_submit_pull_options opts) SV_ARGS(e_body)); char *url = sn_asprintf( "%s/repos/%s/%s/pulls", - gcli_get_apibase(), + gcli_get_apibase(ctx), opts.owner, opts.repo); - rc = gcli_fetch_with_method("POST", url, post_fields, NULL, &fetch_buffer); + rc = gcli_fetch_with_method(ctx, "POST", url, post_fields, NULL, + &fetch_buffer); /* Add labels if requested. GitHub doesn't allow us to do this all * with one request. */ if (rc == 0 && opts.labels_size) { json_open_buffer(&json, fetch_buffer.data, fetch_buffer.length); - parse_github_pull(&json, &pull); + parse_github_pull(ctx, &json, &pull); - github_issue_add_labels(opts.owner, opts.repo, pull.id, + github_issue_add_labels(ctx, opts.owner, opts.repo, pull.id, opts.labels, opts.labels_size); gcli_pull_free(&pull); @@ -316,14 +313,14 @@ github_perform_submit_pull(gcli_submit_pull_options opts) } int -github_get_pull_commits(char const *owner, char const *repo, +github_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, int const pr_number, gcli_commit_list *const out) { char *url = NULL; char *e_owner = NULL; char *e_repo = NULL; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->commits, .sizep = &out->commits_size, .max = -1, @@ -335,20 +332,18 @@ github_get_pull_commits(char const *owner, char const *repo, url = sn_asprintf( "%s/repos/%s/%s/pulls/%d/commits", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, pr_number); free(e_owner); free(e_repo); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -github_get_pull(char const *owner, - char const *repo, - int const pr_number, - gcli_pull *const out) +github_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number, gcli_pull *const out) { int rc = 0; gcli_fetch_buffer json_buffer = {0}; @@ -361,17 +356,17 @@ github_get_pull(char const *owner, url = sn_asprintf( "%s/repos/%s/%s/pulls/%d", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo, pr_number); free(e_owner); free(e_repo); - rc = gcli_fetch(url, NULL, &json_buffer); + rc = gcli_fetch(ctx, url, NULL, &json_buffer); if (rc == 0) { json_stream stream = {0}; json_open_buffer(&stream, json_buffer.data, json_buffer.length); - parse_github_pull(&stream, out); + parse_github_pull(ctx, &stream, out); json_close(&stream); } @@ -382,12 +377,13 @@ github_get_pull(char const *owner, } int -github_pull_checks(char const *owner, char const *repo, int const pr_number) +github_pull_checks(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number) { char refname[64] = {0}; /* This is kind of a hack, but it works! */ snprintf(refname, sizeof refname, "refs%%2Fpull%%2F%d%%2Fhead", pr_number); - return github_checks(owner, repo, refname, -1); + return github_checks(ctx, owner, repo, refname, -1); } diff --git a/src/github/releases.c b/src/github/releases.c index 814e8e87..cb666eac 100644 --- a/src/github/releases.c +++ b/src/github/releases.c @@ -39,14 +39,14 @@ #include int -github_get_releases(char const *owner, char const *repo, +github_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, int const max, gcli_release_list *const list) { char *url = NULL; char *e_owner = NULL; char *e_repo = NULL; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &list->releases, .sizep = &list->releases_size, .max = max, @@ -60,23 +60,24 @@ github_get_releases(char const *owner, char const *repo, url = sn_asprintf( "%s/repos/%s/%s/releases", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo); free(e_owner); free(e_repo); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } static void -github_parse_single_release(gcli_fetch_buffer buffer, gcli_release *const out) +github_parse_single_release(gcli_ctx *ctx, gcli_fetch_buffer buffer, + gcli_release *const out) { struct json_stream stream = {0}; json_open_buffer(&stream, buffer.data, buffer.length); json_set_streaming(&stream, 1); - parse_github_release(&stream, out); + parse_github_release(ctx, &stream, out); json_close(&stream); } @@ -92,7 +93,7 @@ github_get_upload_url(gcli_release *const it) } static int -github_upload_release_asset(char const *url, +github_upload_release_asset(gcli_ctx *ctx, char const *url, gcli_release_asset_upload const asset) { char *req = NULL; @@ -108,6 +109,7 @@ github_upload_release_asset(char const *url, req = sn_asprintf("%s?name=%s", url, asset.name); rc = gcli_post_upload( + ctx, req, "application/octet-stream", /* HACK */ file_content.data, @@ -121,7 +123,7 @@ github_upload_release_asset(char const *url, } int -github_create_release(gcli_new_release const *release) +github_create_release(gcli_ctx *ctx, gcli_new_release const *release) { char *url = NULL; char *e_owner = NULL; @@ -143,7 +145,7 @@ github_create_release(gcli_new_release const *release) /* https://docs.github.com/en/rest/reference/repos#create-a-release */ url = sn_asprintf( "%s/repos/%s/%s/releases", - gcli_get_apibase(), e_owner, e_repo); + gcli_get_apibase(ctx), e_owner, e_repo); escaped_body = gcli_json_escape(release->body); @@ -173,11 +175,11 @@ github_create_release(gcli_new_release const *release) commitish_json ? commitish_json : "", name_json ? name_json : ""); - rc = gcli_fetch_with_method("POST", url, post_data, NULL, &buffer); + rc = gcli_fetch_with_method(ctx, "POST", url, post_data, NULL, &buffer); if (rc < 0) goto out; - github_parse_single_release(buffer, &response); + github_parse_single_release(ctx, buffer, &response); printf("INFO : Release at "SV_FMT"\n", SV_ARGS(response.html_url)); @@ -185,7 +187,7 @@ github_create_release(gcli_new_release const *release) for (size_t i = 0; i < release->assets_size; ++i) { printf("INFO : Uploading asset %s...\n", release->assets[i].path); - rc = github_upload_release_asset(upload_url, release->assets[i]); + rc = github_upload_release_asset(ctx, upload_url, release->assets[i]); if (rc < 0) break; @@ -206,7 +208,8 @@ github_create_release(gcli_new_release const *release) } int -github_delete_release(char const *owner, char const *repo, char const *id) +github_delete_release(gcli_ctx *ctx, char const *owner, char const *repo, + char const *id) { char *url = NULL; char *e_owner = NULL; @@ -218,9 +221,9 @@ github_delete_release(char const *owner, char const *repo, char const *id) url = sn_asprintf( "%s/repos/%s/%s/releases/%s", - gcli_get_apibase(), e_owner, e_repo, id); + gcli_get_apibase(ctx), e_owner, e_repo, id); - rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); free(e_owner); diff --git a/src/github/repos.c b/src/github/repos.c index 1924e8ed..64f7e73d 100644 --- a/src/github/repos.c +++ b/src/github/repos.c @@ -38,11 +38,12 @@ #include int -github_get_repos(char const *owner, int const max, gcli_repo_list *const list) +github_get_repos(gcli_ctx *ctx, char const *owner, int const max, + gcli_repo_list *const list) { char *url = NULL; char *e_owner = NULL; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx lf = { .listp = &list->repos, .sizep = &list->repos_size, .max = max, @@ -54,44 +55,44 @@ github_get_repos(char const *owner, int const max, gcli_repo_list *const list) /* Github is a little stupid in that it distinguishes * organizations and users. Thus, we have to find out, whether the * param is a user or an actual organization. */ - url = sn_asprintf("%s/users/%s", gcli_get_apibase(), e_owner); + url = sn_asprintf("%s/users/%s", gcli_get_apibase(ctx), e_owner); if (gcli_curl_test_success(url)) { /* it is a user */ free(url); url = sn_asprintf("%s/users/%s/repos", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner); } else { /* this is an actual organization */ free(url); url = sn_asprintf("%s/orgs/%s/repos", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner); } free(e_owner); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &lf); } int -github_get_own_repos(int const max, gcli_repo_list *const list) +github_get_own_repos(gcli_ctx *ctx, int const max, gcli_repo_list *const list) { char *url = NULL; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &list->repos, .sizep = &list->repos_size, .max = max, .parse = (parsefn)(parse_github_repos), }; - url = sn_asprintf("%s/user/repos", gcli_get_apibase()); + url = sn_asprintf("%s/user/repos", gcli_get_apibase(ctx)); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -github_repo_delete(char const *owner, char const *repo) +github_repo_delete(gcli_ctx *ctx, char const *owner, char const *repo) { char *url = NULL; char *e_owner = NULL; @@ -102,10 +103,10 @@ github_repo_delete(char const *owner, char const *repo) e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/repos/%s/%s", - gcli_get_apibase(), + gcli_get_apibase(ctx), e_owner, e_repo); - rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(e_owner); free(e_repo); @@ -115,7 +116,7 @@ github_repo_delete(char const *owner, char const *repo) } int -github_repo_create(gcli_repo_create_options const *options, +github_repo_create(gcli_ctx *ctx, gcli_repo_create_options const *options, gcli_repo *const out) { char *url, *data; @@ -125,7 +126,7 @@ github_repo_create(gcli_repo_create_options const *options, int rc = 0; /* Request preparation */ - url = sn_asprintf("%s/user/repos", gcli_get_apibase()); + url = sn_asprintf("%s/user/repos", gcli_get_apibase(ctx)); /* JSON-escape repo name and description */ e_name = gcli_json_escape(options->name); @@ -139,11 +140,12 @@ github_repo_create(gcli_repo_create_options const *options, gcli_json_bool(options->private)); /* Fetch and parse result */ - rc = gcli_fetch_with_method("POST", url, data, NULL, out ? &buffer : NULL); + rc = gcli_fetch_with_method(ctx, "POST", url, data, NULL, + out ? &buffer : NULL); if (rc == 0 && out) { json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_repo(&stream, out); + parse_github_repo(ctx, &stream, out); json_close(&stream); } diff --git a/src/github/review.c b/src/github/review.c index cb7740d5..6f68242a 100644 --- a/src/github/review.c +++ b/src/github/review.c @@ -34,7 +34,8 @@ #include static void -github_parse_review_comment(json_stream *input, gcli_pr_review_comment *it) +github_parse_review_comment(gcli_ctx *ctx, json_stream *input, + gcli_pr_review_comment *it) { if (json_next(input) != JSON_OBJECT) errx(1, "Expected review comment object"); @@ -45,26 +46,27 @@ github_parse_review_comment(json_stream *input, gcli_pr_review_comment *it) char const *key = json_get_string(input, &len); if (strncmp("bodyText", key, len) == 0) - it->body = get_string(input); + it->body = get_string(ctx, input); else if (strncmp("id", key, len) == 0) - it->id = get_string(input); + it->id = get_string(ctx, input); else if (strncmp("createdAt", key, len) == 0) - it->date = get_string(input); + it->date = get_string(ctx, input); else if (strncmp("author", key, len) == 0) - it->author = get_user(input); + it->author = get_user(ctx, input); else if (strncmp("diffHunk", key, len) == 0) - it->diff = get_string(input); + it->diff = get_string(ctx, input); else if (strncmp("path", key, len) == 0) - it->path = get_string(input); + it->path = get_string(ctx, input); else if (strncmp("originalPosition", key, len) == 0) - it->original_position = get_int(input); + it->original_position = get_int(ctx, input); else SKIP_OBJECT_VALUE(input); } } static void -github_parse_review_comments(json_stream *input, gcli_pr_review *it) +github_parse_review_comments(gcli_ctx *ctx, json_stream *input, + gcli_pr_review *it) { gcli_json_advance(input, "{s[", "nodes"); while (json_peek(input) == JSON_OBJECT) { @@ -73,13 +75,14 @@ github_parse_review_comments(json_stream *input, gcli_pr_review *it) sizeof(*it->comments) * (it->comments_size + 1)); gcli_pr_review_comment *comment = &it->comments[it->comments_size++]; *comment = (gcli_pr_review_comment) {0}; - github_parse_review_comment(input, comment); + github_parse_review_comment(ctx, input, comment); } gcli_json_advance(input, "]}"); } static void -github_parse_review_header(json_stream *input, gcli_pr_review *it) +github_parse_review_header(gcli_ctx *ctx, json_stream *input, + gcli_pr_review *it) { if (json_next(input) != JSON_OBJECT) errx(1, "Expected review object"); @@ -90,17 +93,17 @@ github_parse_review_header(json_stream *input, gcli_pr_review *it) char const *key = json_get_string(input, &len); if (strncmp("bodyText", key, len) == 0) - it->body = get_string(input); + it->body = get_string(ctx, input); else if (strncmp("state", key, len) == 0) - it->state = get_string(input); + it->state = get_string(ctx, input); else if (strncmp("id", key, len) == 0) - it->id = get_string(input); + it->id = get_string(ctx, input); else if (strncmp("createdAt", key, len) == 0) - it->date = get_string(input); + it->date = get_string(ctx, input); else if (strncmp("author", key, len) == 0) - it->author = get_user(input); + it->author = get_user(ctx, input); else if (strncmp("comments", key, len) == 0) - github_parse_review_comments(input, it); + github_parse_review_comments(ctx, input, it); else SKIP_OBJECT_VALUE(input); } @@ -140,7 +143,7 @@ static char const *get_reviews_fmt = "}"; int -github_review_get_reviews(char const *owner, char const *repo, +github_review_get_reviews(gcli_ctx *ctx, char const *owner, char const *repo, int const pr, gcli_pr_review_list *const out) { gcli_fetch_buffer buffer = {0}; @@ -152,13 +155,13 @@ github_review_get_reviews(char const *owner, char const *repo, enum json_type next = JSON_NULL; int rc = 0; - url = sn_asprintf("%s/graphql", gcli_get_apibase()); + url = sn_asprintf("%s/graphql", gcli_get_apibase(ctx)); query = sn_asprintf(get_reviews_fmt, owner, repo, pr); query_escaped = gcli_json_escape(SV(query)); post_data = sn_asprintf("{\"query\": \""SV_FMT"\"}", SV_ARGS(query_escaped)); - rc = gcli_fetch_with_method("POST", url, post_data, NULL, &buffer); + rc = gcli_fetch_with_method(ctx, "POST", url, post_data, NULL, &buffer); free(url); free(query); free(query_escaped.data); @@ -185,7 +188,7 @@ github_review_get_reviews(char const *owner, char const *repo, *it = (gcli_pr_review) {0}; - github_parse_review_header(&stream, it); + github_parse_review_header(ctx, &stream, it); out->reviews_size++; } diff --git a/src/github/sshkeys.c b/src/github/sshkeys.c index f2cd61ae..99d40622 100644 --- a/src/github/sshkeys.c +++ b/src/github/sshkeys.c @@ -34,21 +34,20 @@ #include int -github_get_sshkeys(gcli_sshkey_list *out) +github_get_sshkeys(gcli_ctx *ctx, gcli_sshkey_list *out) { - return gitlab_get_sshkeys(out); + return gitlab_get_sshkeys(ctx, out); } int -github_add_sshkey(char const *const title, - char const *const pubkey, - gcli_sshkey *out) +github_add_sshkey(gcli_ctx *ctx, char const *const title, + char const *const pubkey, gcli_sshkey *out) { - return gitlab_add_sshkey(title, pubkey, out); + return gitlab_add_sshkey(ctx, title, pubkey, out); } int -github_delete_sshkey(int id) +github_delete_sshkey(gcli_ctx *ctx, int id) { - return gitlab_delete_sshkey(id); + return gitlab_delete_sshkey(ctx, id); } diff --git a/src/github/status.c b/src/github/status.c index ef1127cf..6e7e9452 100644 --- a/src/github/status.c +++ b/src/github/status.c @@ -38,7 +38,8 @@ #include int -github_get_notifications(gcli_notification **const notifications, +github_get_notifications(gcli_ctx *ctx, + gcli_notification **const notifications, int const count) { char *url = NULL; @@ -48,14 +49,15 @@ github_get_notifications(gcli_notification **const notifications, size_t notifications_size = 0; int rc = 0; - url = sn_asprintf("%s/notifications", gcli_get_apibase()); + url = sn_asprintf("%s/notifications", gcli_get_apibase(ctx)); do { - rc = gcli_fetch(url, &next_url, &buffer); + rc = gcli_fetch(ctx, url, &next_url, &buffer); if (rc == 0) { json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_notifications(&stream, notifications, ¬ifications_size); + parse_github_notifications(ctx, &stream, notifications, + ¬ifications_size); json_close(&stream); } @@ -74,16 +76,16 @@ github_get_notifications(gcli_notification **const notifications, } int -github_notification_mark_as_read(char const *id) +github_notification_mark_as_read(gcli_ctx *ctx, char const *id) { char *url = NULL; int rc = 0; url = sn_asprintf( "%s/notifications/threads/%s", - gcli_get_apibase(), + gcli_get_apibase(ctx), id); - rc = gcli_fetch_with_method("PATCH", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PATCH", url, NULL, NULL, NULL); free(url); diff --git a/src/gitlab/api.c b/src/gitlab/api.c index faf689ff..148dc7de 100644 --- a/src/gitlab/api.c +++ b/src/gitlab/api.c @@ -33,7 +33,7 @@ #include char const * -gitlab_api_error_string(gcli_fetch_buffer *const it) +gitlab_api_error_string(gcli_ctx *ctx, gcli_fetch_buffer *const it) { struct json_stream stream = {0}; enum json_type next = JSON_NULL; @@ -45,12 +45,12 @@ gitlab_api_error_string(gcli_fetch_buffer *const it) json_set_streaming(&stream, true); while ((next = json_next(&stream)) != JSON_OBJECT_END) { - char *key = get_string(&stream); + char *key = get_string(ctx, &stream); if (strcmp(key, "message") == 0) { if ((next = json_peek(&stream)) == JSON_STRING) - return get_string(&stream); + return get_string(ctx, &stream); else if ((next = json_next(&stream)) == JSON_ARRAY) - return get_string(&stream); + return get_string(ctx, &stream); else if (next == JSON_ARRAY_END) ; else diff --git a/src/gitlab/comments.c b/src/gitlab/comments.c index 3361b3e6..5792a6f7 100644 --- a/src/gitlab/comments.c +++ b/src/gitlab/comments.c @@ -34,7 +34,7 @@ #include int -gitlab_perform_submit_comment(gcli_submit_comment_opts opts, +gitlab_perform_submit_comment(gcli_ctx *ctx, gcli_submit_comment_opts opts, gcli_fetch_buffer *const out) { char const *type = NULL; @@ -57,12 +57,12 @@ gitlab_perform_submit_comment(gcli_submit_comment_opts opts, char *post_fields = sn_asprintf( "{ \"body\": \""SV_FMT"\" }", SV_ARGS(opts.message)); - char *url = sn_asprintf( + char *url = sn_asprintf( "%s/projects/%s%%2F%s/%s/%d/notes", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, type, opts.target_id); - rc = gcli_fetch_with_method("POST", url, post_fields, NULL, out); + rc = gcli_fetch_with_method(ctx, "POST", url, post_fields, NULL, out); free(post_fields); free(e_owner); @@ -73,14 +73,12 @@ gitlab_perform_submit_comment(gcli_submit_comment_opts opts, } int -gitlab_get_mr_comments(char const *owner, - char const *repo, - int const mr, - gcli_comment_list *const out) +gitlab_get_mr_comments(gcli_ctx *ctx, char const *owner, char const *repo, + int const mr, gcli_comment_list *const out) { char *e_owner = gcli_urlencode(owner); char *e_repo = gcli_urlencode(repo); - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->comments, .sizep = &out->comments_size, .parse = (parsefn)parse_gitlab_comments, @@ -89,22 +87,22 @@ gitlab_get_mr_comments(char const *owner, char *url = sn_asprintf( "%s/projects/%s%%2F%s/merge_requests/%d/notes", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, mr); free(e_owner); free(e_repo); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -gitlab_get_issue_comments(char const *owner, char const *repo, +gitlab_get_issue_comments(gcli_ctx *ctx, char const *owner, char const *repo, int const issue, gcli_comment_list *const out) { char *e_owner = gcli_urlencode(owner); char *e_repo = gcli_urlencode(repo); - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->comments, .sizep = &out->comments_size, .parse = (parsefn)parse_gitlab_comments, @@ -113,10 +111,10 @@ gitlab_get_issue_comments(char const *owner, char const *repo, char *url = sn_asprintf( "%s/projects/%s%%2F%s/issues/%d/notes", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, issue); free(e_owner); free(e_repo); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } diff --git a/src/gitlab/config.c b/src/gitlab/config.c index 0b2c27ac..0e446f1a 100644 --- a/src/gitlab/config.c +++ b/src/gitlab/config.c @@ -33,16 +33,17 @@ #include static sn_sv -gitlab_default_account_name(void) +gitlab_default_account_name(gcli_ctx *ctx) { sn_sv section_name; /* Use default override account */ - section_name = gcli_config_get_override_default_account(); + section_name = gcli_config_get_override_default_account(ctx); /* If not manually overridden */ if (sn_sv_null(section_name)) { section_name = gcli_config_find_by_key( + ctx, SV("defaults"), "gitlab-default-account"); @@ -55,13 +56,13 @@ gitlab_default_account_name(void) } char * -gitlab_get_apibase(void) +gitlab_get_apibase(gcli_ctx *ctx) { - sn_sv account = gitlab_default_account_name(); + sn_sv account = gitlab_default_account_name(ctx); if (sn_sv_null(account)) goto default_val; - sn_sv api_base = gcli_config_find_by_key(account, "apibase"); + sn_sv api_base = gcli_config_find_by_key(ctx, account, "apibase"); if (sn_sv_null(api_base)) goto default_val; @@ -72,26 +73,26 @@ gitlab_get_apibase(void) } char * -gitlab_get_authheader(void) +gitlab_get_authheader(gcli_ctx *ctx) { - sn_sv const account = gitlab_default_account_name(); + sn_sv const account = gitlab_default_account_name(ctx); if (sn_sv_null(account)) return NULL; - sn_sv const token = gcli_config_find_by_key(account, "token"); + sn_sv const token = gcli_config_find_by_key(ctx, account, "token"); if (sn_sv_null(token)) errx(1, "Missing GitLab token"); return sn_asprintf("PRIVATE-TOKEN: "SV_FMT, SV_ARGS(token)); } sn_sv -gitlab_get_account(void) +gitlab_get_account(gcli_ctx *ctx) { - sn_sv const section = gitlab_default_account_name(); + sn_sv const section = gitlab_default_account_name(ctx); if (sn_sv_null(section)) return SV_NULL; - sn_sv const account = gcli_config_find_by_key(section, "account");; + sn_sv const account = gcli_config_find_by_key(ctx, section, "account");; if (sn_sv_null(account)) errx(1, "Missing GitLab account name"); return account; diff --git a/src/gitlab/forks.c b/src/gitlab/forks.c index 12a027ce..b3eccd92 100644 --- a/src/gitlab/forks.c +++ b/src/gitlab/forks.c @@ -37,16 +37,14 @@ #include int -gitlab_get_forks(char const *owner, - char const *repo, - int const max, - gcli_fork_list *const list) +gitlab_get_forks(gcli_ctx *ctx, char const *owner, char const *repo, + int const max, gcli_fork_list *const list) { char *url = NULL; char *e_owner = NULL; char *e_repo = NULL; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &list->forks, .sizep = &list->forks_size, .parse = (parsefn)parse_gitlab_forks, @@ -60,17 +58,18 @@ gitlab_get_forks(char const *owner, url = sn_asprintf( "%s/projects/%s%%2F%s/forks", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo); free(e_owner); free(e_repo); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -gitlab_fork_create(char const *owner, char const *repo, char const *_in) +gitlab_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, + char const *_in) { char *url = NULL; char *e_owner = NULL; @@ -83,7 +82,7 @@ gitlab_fork_create(char const *owner, char const *repo, char const *_in) e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s/fork", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo); if (_in) { in = gcli_json_escape(SV((char *)_in)); @@ -91,7 +90,7 @@ gitlab_fork_create(char const *owner, char const *repo, char const *_in) SV_ARGS(in)); } - rc = gcli_fetch_with_method("POST", url, post_data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "POST", url, post_data, NULL, NULL); free(in.data); free(url); diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index 2f9cc70f..ce726147 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -39,24 +39,22 @@ /** Given the url fetch issues */ int -gitlab_fetch_issues(char *url, int const max, +gitlab_fetch_issues(gcli_ctx *ctx, char *url, int const max, gcli_issue_list *const out) { - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->issues, .sizep = &out->issues_size, .max = max, .parse = (parsefn)(parse_gitlab_issues), }; - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -gitlab_get_issues(char const *owner, - char const *repo, - gcli_issue_fetch_details const *details, - int const max, +gitlab_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_issue_fetch_details const *details, int const max, gcli_issue_list *const out) { char *url = NULL; @@ -77,7 +75,7 @@ gitlab_get_issues(char const *owner, url = sn_asprintf( "%s/projects/%s%%2F%s/issues%s%s", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, details->all ? "" : "?state=opened", e_author ? e_author : ""); @@ -86,11 +84,11 @@ gitlab_get_issues(char const *owner, free(e_owner); free(e_repo); - return gitlab_fetch_issues(url, max, out); + return gitlab_fetch_issues(ctx, url, max, out); } int -gitlab_get_issue_summary(char const *owner, char const *repo, +gitlab_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, int const issue_number, gcli_issue *const out) { char *url = NULL; @@ -101,19 +99,19 @@ gitlab_get_issue_summary(char const *owner, char const *repo, int rc = 0; e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); url = sn_asprintf( "%s/projects/%s%%2F%s/issues/%d", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, issue_number); - rc = gcli_fetch(url, NULL, &buffer); + rc = gcli_fetch(ctx, url, NULL, &buffer); if (rc == 0) { json_open_buffer(&parser, buffer.data, buffer.length); json_set_streaming(&parser, true); - parse_gitlab_issue(&parser, out); + parse_gitlab_issue(ctx, &parser, out); json_close(&parser); } @@ -126,25 +124,26 @@ gitlab_get_issue_summary(char const *owner, char const *repo, } int -gitlab_issue_close(char const *owner, char const *repo, int const issue_number) +gitlab_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue_number) { - char *url = NULL; - char *data = NULL; + char *url = NULL; + char *data = NULL; char *e_owner = NULL; - char *e_repo = NULL; - int rc = 0; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); url = sn_asprintf( "%s/projects/%s%%2F%s/issues/%d", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, issue_number); data = sn_asprintf("{ \"state_event\": \"close\"}"); - rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); free(data); free(url); @@ -155,25 +154,26 @@ gitlab_issue_close(char const *owner, char const *repo, int const issue_number) } int -gitlab_issue_reopen(char const *owner, char const *repo, int const issue_number) +gitlab_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue_number) { - char *url = NULL; - char *data = NULL; + char *url = NULL; + char *data = NULL; char *e_owner = NULL; - char *e_repo = NULL; - int rc = 0; + char *e_repo = NULL; + int rc = 0; e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); - url = sn_asprintf( + url = sn_asprintf( "%s/projects/%s%%2F%s/issues/%d", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, issue_number); data = sn_asprintf("{ \"state_event\": \"reopen\"}"); - rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); free(data); free(url); @@ -184,13 +184,13 @@ gitlab_issue_reopen(char const *owner, char const *repo, int const issue_number) } int -gitlab_perform_submit_issue(gcli_submit_issue_options opts, +gitlab_perform_submit_issue(gcli_ctx *ctx, gcli_submit_issue_options opts, gcli_fetch_buffer *const out) { char *e_owner = gcli_urlencode(opts.owner); - char *e_repo = gcli_urlencode(opts.repo); + char *e_repo = gcli_urlencode(opts.repo); sn_sv e_title = gcli_json_escape(opts.title); - sn_sv e_body = gcli_json_escape(opts.body); + sn_sv e_body = gcli_json_escape(opts.body); int rc = 0; char *post_fields = sn_asprintf( @@ -198,9 +198,9 @@ gitlab_perform_submit_issue(gcli_submit_issue_options opts, SV_ARGS(e_title), SV_ARGS(e_body)); char *url = sn_asprintf( "%s/projects/%s%%2F%s/issues", - gitlab_get_apibase(), e_owner, e_repo); + gitlab_get_apibase(ctx), e_owner, e_repo); - rc = gcli_fetch_with_method("POST", url, post_fields, NULL, out); + rc = gcli_fetch_with_method(ctx, "POST", url, post_fields, NULL, out); free(e_owner); free(e_repo); @@ -213,7 +213,7 @@ gitlab_perform_submit_issue(gcli_submit_issue_options opts, } static int -gitlab_user_id(char const *user_name) +gitlab_user_id(gcli_ctx *ctx, char const *user_name) { gcli_fetch_buffer buffer = {0}; struct json_stream stream = {0}; @@ -223,15 +223,16 @@ gitlab_user_id(char const *user_name) e_username = gcli_urlencode(user_name); - url = sn_asprintf("%s/users?username=%s", gitlab_get_apibase(), e_username); + url = sn_asprintf("%s/users?username=%s", + gitlab_get_apibase(ctx), e_username); - uid = gcli_fetch(url, NULL, &buffer); + uid = gcli_fetch(ctx, url, NULL, &buffer); if (uid == 0) { json_open_buffer(&stream, buffer.data, buffer.length); json_set_streaming(&stream, 1); gcli_json_advance(&stream, "[{s", "id"); - uid = get_int(&stream); + uid = get_int(ctx, &stream); json_close(&stream); } @@ -244,10 +245,8 @@ gitlab_user_id(char const *user_name) } int -gitlab_issue_assign(char const *owner, - char const *repo, - int const issue_number, - char const *assignee) +gitlab_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue_number, char const *assignee) { int assignee_uid = -1; char *url = NULL; @@ -256,7 +255,7 @@ gitlab_issue_assign(char const *owner, char *e_repo = NULL; int rc = 0; - assignee_uid = gitlab_user_id(assignee); + assignee_uid = gitlab_user_id(ctx, assignee); if (assignee_uid < 0) return assignee_uid; @@ -264,10 +263,10 @@ gitlab_issue_assign(char const *owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, issue_number); post_data = sn_asprintf("{ \"assignee_ids\": [ %d ] }", assignee_uid); - rc = gcli_fetch_with_method("PUT", url, post_data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PUT", url, post_data, NULL, NULL); free(e_owner); free(e_repo); @@ -278,24 +277,22 @@ gitlab_issue_assign(char const *owner, } int -gitlab_issue_add_labels(char const *owner, - char const *repo, - int const issue, - char const *const labels[], +gitlab_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue, char const *const labels[], size_t const labels_size) { - char *url = NULL; + char *url = NULL; char *data = NULL; char *list = NULL; - int rc = 0; + int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", - gitlab_get_apibase(), owner, repo, issue); + gitlab_get_apibase(ctx), owner, repo, issue); list = sn_join_with(labels, labels_size, ","); data = sn_asprintf("{ \"add_labels\": \"%s\"}", list); - rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); free(url); free(data); @@ -305,24 +302,22 @@ gitlab_issue_add_labels(char const *owner, } int -gitlab_issue_remove_labels(char const *owner, - char const *repo, - int const issue, - char const *const labels[], +gitlab_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue, char const *const labels[], size_t const labels_size) { - char *url = NULL; + char *url = NULL; char *data = NULL; char *list = NULL; - int rc = 0; + int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", - gitlab_get_apibase(), owner, repo, issue); + gitlab_get_apibase(ctx), owner, repo, issue); list = sn_join_with(labels, labels_size, ","); data = sn_asprintf("{ \"remove_labels\": \"%s\"}", list); - rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); free(url); free(data); @@ -332,9 +327,8 @@ gitlab_issue_remove_labels(char const *owner, } int -gitlab_issue_set_milestone(char const *const owner, - char const *const repo, - int const issue, +gitlab_issue_set_milestone(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const issue, int const milestone) { char *url, *e_owner, *e_repo; @@ -342,10 +336,11 @@ gitlab_issue_set_milestone(char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d?milestone_id=%d", - gitlab_get_apibase(), e_owner, e_repo, issue, milestone); + url = sn_asprintf( + "%s/projects/%s%%2F%s/issues/%d?milestone_id=%d", + gitlab_get_apibase(ctx), e_owner, e_repo, issue, milestone); - rc = gcli_fetch_with_method("PUT", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PUT", url, NULL, NULL, NULL); free(url); free(e_repo); @@ -355,9 +350,8 @@ gitlab_issue_set_milestone(char const *const owner, } int -gitlab_issue_clear_milestone(char const *const owner, - char const *const repo, - int const issue) +gitlab_issue_clear_milestone(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const issue) { char *url, *e_owner, *e_repo, *payload; int rc; @@ -376,11 +370,12 @@ gitlab_issue_clear_milestone(char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", - gitlab_get_apibase(), e_owner, e_repo, issue); + url = sn_asprintf( + "%s/projects/%s%%2F%s/issues/%d", + gitlab_get_apibase(ctx), e_owner, e_repo, issue); payload = sn_asprintf("{ \"milestone_id\": null }"); - rc = gcli_fetch_with_method("PUT", url, payload, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PUT", url, payload, NULL, NULL); free(payload); free(url); diff --git a/src/gitlab/labels.c b/src/gitlab/labels.c index 2175684e..d0495ced 100644 --- a/src/gitlab/labels.c +++ b/src/gitlab/labels.c @@ -36,11 +36,11 @@ #include int -gitlab_get_labels(char const *owner, char const *repo, +gitlab_get_labels(gcli_ctx *ctx, char const *owner, char const *repo, int const max, gcli_label_list *const out) { char *url = NULL; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->labels, .sizep = &out->labels_size, .max = max, @@ -50,26 +50,28 @@ gitlab_get_labels(char const *owner, char const *repo, *out = (gcli_label_list) {0}; url = sn_asprintf("%s/projects/%s%%2F%s/labels", - gitlab_get_apibase(), owner, repo); + gitlab_get_apibase(ctx), owner, repo); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -gitlab_create_label(char const *owner, char const *repo, gcli_label *const label) +gitlab_create_label(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_label *const label) { - char *url = NULL; - char *data = NULL; - char *colour_string = NULL; - sn_sv lname_escaped = SV_NULL; - sn_sv ldesc_escaped = SV_NULL; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; - int rc = 0; + char *url = NULL; + char *data = NULL; + char *colour_string = NULL; + sn_sv lname_escaped = SV_NULL; + sn_sv ldesc_escaped = SV_NULL; + gcli_fetch_buffer buffer = {0}; + struct json_stream stream = {0}; + int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/labels", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), owner, repo); + lname_escaped = gcli_json_escape(SV(label->name)); ldesc_escaped = gcli_json_escape(SV(label->description)); colour_string = sn_asprintf("%06X", (label->colour>>8)&0xFFFFFF); @@ -81,12 +83,12 @@ gitlab_create_label(char const *owner, char const *repo, gcli_label *const label colour_string, SV_ARGS(ldesc_escaped)); - rc = gcli_fetch_with_method("POST", url, data, NULL, &buffer); + rc = gcli_fetch_with_method(ctx, "POST", url, data, NULL, &buffer); if (rc == 0) { json_open_buffer(&stream, buffer.data, buffer.length); json_set_streaming(&stream, 1); - parse_gitlab_label(&stream, label); + parse_gitlab_label(ctx, &stream, label); json_close(&stream); } @@ -101,18 +103,19 @@ gitlab_create_label(char const *owner, char const *repo, gcli_label *const label } int -gitlab_delete_label(char const *owner, char const *repo, char const *label) +gitlab_delete_label(gcli_ctx *ctx, char const *owner, char const *repo, + char const *label) { - char *url = NULL; - char *e_label = NULL; + char *url = NULL; + char *e_label = NULL; int rc; e_label = gcli_urlencode(label); url = sn_asprintf("%s/projects/%s%%2F%s/labels/%s", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), owner, repo, e_label); - rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); free(e_label); diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index db2e718e..859c9996 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -48,18 +48,19 @@ gitlab_mrs_fixup(gcli_pull_list *const list) } int -gitlab_fetch_mrs(char *url, int const max, gcli_pull_list *const list) +gitlab_fetch_mrs(gcli_ctx *ctx, char *url, int const max, + gcli_pull_list *const list) { int rc = 0; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &list->pulls, .sizep = &list->pulls_size, .max = max, .parse = (parsefn)(parse_gitlab_mrs), }; - rc = gcli_fetch_list(url, &ctx); + rc = gcli_fetch_list(ctx, url, &fl); /* TODO: don't leak the list on error */ if (rc == 0) @@ -69,10 +70,8 @@ gitlab_fetch_mrs(char *url, int const max, gcli_pull_list *const list) } int -gitlab_get_mrs(char const *owner, - char const *repo, - gcli_pull_fetch_details const *const details, - int const max, +gitlab_get_mrs(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_pull_fetch_details const *const details, int const max, gcli_pull_list *const list) { char *url = NULL; @@ -100,7 +99,7 @@ gitlab_get_mrs(char const *owner, * substantially from Github's. */ url = sn_asprintf( "%s/projects/%s%%2F%s/merge_requests%s%s%s", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, e_author ? e_author : "", e_author ? (details->all ? "" : "&") : (details->all ? "" : "?"), @@ -110,15 +109,16 @@ gitlab_get_mrs(char const *owner, free(e_owner); free(e_repo); - return gitlab_fetch_mrs(url, max, list); + return gitlab_fetch_mrs(ctx, url, max, list); } int -gitlab_print_pr_diff(FILE *stream, +gitlab_print_pr_diff(gcli_ctx *ctx, FILE *stream, char const *owner, char const *repo, int const pr_number) { + (void)ctx; (void)owner; (void)repo; (void)pr_number; @@ -131,10 +131,8 @@ gitlab_print_pr_diff(FILE *stream, } int -gitlab_mr_merge(char const *owner, - char const *repo, - int const mr_number, - enum gcli_merge_flags const flags) +gitlab_mr_merge(gcli_ctx *ctx, char const *owner, char const *repo, + int const mr_number, enum gcli_merge_flags const flags) { gcli_fetch_buffer buffer = {0}; char *url = NULL; @@ -153,16 +151,16 @@ gitlab_mr_merge(char const *owner, "%s/projects/%s%%2F%s/merge_requests/%d/merge" "?squash=%s" "&should_remove_source_branch=%s", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, mr_number, squash ? "true" : "false", delete_source ? "true" : "false"); - rc = gcli_fetch_with_method("PUT", url, data, NULL, &buffer); + rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, &buffer); /* if verbose or normal noise level, print the url */ if (rc == 0 && !sn_quiet()) - gcli_print_html_url(buffer); + gcli_print_html_url(ctx, buffer); free(buffer.data); free(url); @@ -173,7 +171,7 @@ gitlab_mr_merge(char const *owner, } int -gitlab_get_pull(char const *owner, char const *repo, +gitlab_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, int const pr_number, gcli_pull *const out) { gcli_fetch_buffer json_buffer = {0}; @@ -188,16 +186,16 @@ gitlab_get_pull(char const *owner, char const *repo, /* GET /projects/:id/merge_requests/:merge_request_iid */ url = sn_asprintf( "%s/projects/%s%%2F%s/merge_requests/%d", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, pr_number); free(e_owner); free(e_repo); - rc = gcli_fetch(url, NULL, &json_buffer); + rc = gcli_fetch(ctx, url, NULL, &json_buffer); if (rc == 0) { json_stream stream = {0}; json_open_buffer(&stream, json_buffer.data, json_buffer.length); - parse_gitlab_mr(&stream, out); + parse_gitlab_mr(ctx, &stream, out); json_close(&stream); } @@ -208,14 +206,14 @@ gitlab_get_pull(char const *owner, char const *repo, } int -gitlab_get_pull_commits(char const *owner, char const *repo, +gitlab_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, int const pr_number, gcli_commit_list *const out) { char *url = NULL; char *e_owner = NULL; char *e_repo = NULL; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->commits, .sizep = &out->commits_size, .max = -1, @@ -228,17 +226,18 @@ gitlab_get_pull_commits(char const *owner, char const *repo, /* GET /projects/:id/merge_requests/:merge_request_iid/commits */ url = sn_asprintf( "%s/projects/%s%%2F%s/merge_requests/%d/commits", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, pr_number); free(e_owner); free(e_repo); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -gitlab_mr_close(char const *owner, char const *repo, int const pr_number) +gitlab_mr_close(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number) { char *url = NULL; char *data = NULL; @@ -251,11 +250,11 @@ gitlab_mr_close(char const *owner, char const *repo, int const pr_number) url = sn_asprintf( "%s/projects/%s%%2F%s/merge_requests/%d", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state_event\": \"close\"}"); - rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); free(url); free(e_owner); @@ -266,7 +265,8 @@ gitlab_mr_close(char const *owner, char const *repo, int const pr_number) } int -gitlab_mr_reopen(char const *owner, char const *repo, int const pr_number) +gitlab_mr_reopen(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number) { char *url = NULL; char *data = NULL; @@ -279,11 +279,11 @@ gitlab_mr_reopen(char const *owner, char const *repo, int const pr_number) url = sn_asprintf( "%s/projects/%s%%2F%s/merge_requests/%d", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state_event\": \"reopen\"}"); - rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); free(e_owner); free(e_repo); @@ -294,7 +294,7 @@ gitlab_mr_reopen(char const *owner, char const *repo, int const pr_number) } int -gitlab_perform_submit_mr(gcli_submit_pull_options opts) +gitlab_perform_submit_mr(gcli_ctx *ctx, gcli_submit_pull_options opts) { /* Note: this doesn't really allow merging into repos with * different names. We need to figure out a way to make this @@ -309,22 +309,22 @@ gitlab_perform_submit_mr(gcli_submit_pull_options opts) /* json escaped variants */ sn_sv e_source_branch, e_target_branch, e_title, e_body; - target_branch = opts.to; - source_branch = opts.from; - source_owner = sn_sv_chop_until(&source_branch, ':'); + target_branch = opts.to; + source_branch = opts.from; + source_owner = sn_sv_chop_until(&source_branch, ':'); source_branch.length -= 1; - source_branch.data += 1; + source_branch.data += 1; /* Figure out the project id */ - rc = gitlab_get_repo(opts.owner, opts.repo, &target); + rc = gitlab_get_repo(ctx, opts.owner, opts.repo, &target); if (rc < 0) return rc; /* escape things in the post payload */ e_source_branch = gcli_json_escape(source_branch); e_target_branch = gcli_json_escape(target_branch); - e_title = gcli_json_escape(opts.title); - e_body = gcli_json_escape(opts.body); + e_title = gcli_json_escape(opts.title); + e_body = gcli_json_escape(opts.body); /* Prepare the label list if needed */ if (opts.labels_size) { @@ -358,11 +358,11 @@ gitlab_perform_submit_mr(gcli_submit_pull_options opts) char *url = sn_asprintf( "%s/projects/%s%%2F%s/merge_requests", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo); /* perform request */ - rc = gcli_fetch_with_method("POST", url, post_fields, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "POST", url, post_fields, NULL, NULL); /* cleanup */ free(e_source_branch.data); @@ -379,10 +379,8 @@ gitlab_perform_submit_mr(gcli_submit_pull_options opts) } int -gitlab_mr_add_labels(char const *owner, - char const *repo, - int const mr, - char const *const labels[], +gitlab_mr_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int const mr, char const *const labels[], size_t const labels_size) { char *url = NULL; @@ -391,12 +389,12 @@ gitlab_mr_add_labels(char const *owner, int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", - gitlab_get_apibase(), owner, repo, mr); + gitlab_get_apibase(ctx), owner, repo, mr); list = sn_join_with(labels, labels_size, ","); data = sn_asprintf("{ \"add_labels\": \"%s\"}", list); - rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); free(url); free(data); @@ -406,24 +404,22 @@ gitlab_mr_add_labels(char const *owner, } int -gitlab_mr_remove_labels(char const *owner, - char const *repo, - int const mr, - char const *const labels[], +gitlab_mr_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int const mr, char const *const labels[], size_t const labels_size) { - char *url = NULL; + char *url = NULL; char *data = NULL; char *list = NULL; - int rc = 0; + int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", - gitlab_get_apibase(), owner, repo, mr); + gitlab_get_apibase(ctx), owner, repo, mr); list = sn_join_with(labels, labels_size, ","); data = sn_asprintf("{ \"remove_labels\": \"%s\"}", list); - rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); free(url); free(data); @@ -433,21 +429,19 @@ gitlab_mr_remove_labels(char const *owner, } int -gitlab_mr_set_milestone(char const *owner, - char const *repo, - int mr, - int milestone_id) +gitlab_mr_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, + int mr, int milestone_id) { - char *url = NULL; + char *url = NULL; char *data = NULL; int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", - gitlab_get_apibase(), owner, repo, mr); + gitlab_get_apibase(ctx), owner, repo, mr); data = sn_asprintf("{ \"milestone_id\": \"%d\"}", milestone_id); - rc = gcli_fetch_with_method("PUT", url, data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); free(url); free(data); @@ -456,8 +450,7 @@ gitlab_mr_set_milestone(char const *owner, } int -gitlab_mr_clear_milestone(char const *owner, - char const *repo, +gitlab_mr_clear_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int mr) { /* GitLab's REST API docs state: @@ -465,7 +458,5 @@ gitlab_mr_clear_milestone(char const *owner, * The global ID of a milestone to assign the merge request * to. Set to 0 or provide an empty value to unassign a * milestone. */ - gitlab_mr_set_milestone(owner, repo, mr, 0); - - return 0; + return gitlab_mr_set_milestone(ctx, owner, repo, mr, 0); } diff --git a/src/gitlab/milestones.c b/src/gitlab/milestones.c index ad72d457..65aac013 100644 --- a/src/gitlab/milestones.c +++ b/src/gitlab/milestones.c @@ -42,13 +42,13 @@ #include int -gitlab_get_milestones(char const *owner, char const *repo, +gitlab_get_milestones(gcli_ctx *ctx, char const *owner, char const *repo, int max, gcli_milestone_list *const out) { char *url; char *e_owner, *e_repo; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->milestones, .sizep = &out->milestones_size, .max = max, @@ -59,19 +59,17 @@ gitlab_get_milestones(char const *owner, char const *repo, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s/milestones", - gitlab_get_apibase(), e_owner, e_repo); + gitlab_get_apibase(ctx), e_owner, e_repo); free(e_owner); free(e_repo); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -gitlab_get_milestone(char const *owner, - char const *repo, - int const milestone, - gcli_milestone *const out) +gitlab_get_milestone(gcli_ctx *ctx, char const *owner, char const *repo, + int const milestone, gcli_milestone *const out) { char *url, *e_owner, *e_repo; gcli_fetch_buffer buffer = {0}; @@ -82,12 +80,12 @@ gitlab_get_milestone(char const *owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d", - gitlab_get_apibase(), e_owner, e_repo, milestone); + gitlab_get_apibase(ctx), e_owner, e_repo, milestone); - rc = gcli_fetch(url, NULL, &buffer); + rc = gcli_fetch(ctx, url, NULL, &buffer); if (rc == 0) { json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_milestone(&stream, out); + parse_gitlab_milestone(ctx, &stream, out); json_close(&stream); } @@ -100,9 +98,8 @@ gitlab_get_milestone(char const *owner, } int -gitlab_milestone_get_issues(char const *const owner, - char const *const repo, - int const milestone, +gitlab_milestone_get_issues(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const milestone, gcli_issue_list *const out) { char *url, *e_owner, *e_repo; @@ -111,17 +108,18 @@ gitlab_milestone_get_issues(char const *const owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d/issues", - gitlab_get_apibase(), e_owner, e_repo, milestone); + gitlab_get_apibase(ctx), e_owner, e_repo, milestone); free(e_repo); free(e_owner); /* URL is freed by the fetch_issues call */ - return gitlab_fetch_issues(url, -1, out);; + return gitlab_fetch_issues(ctx, url, -1, out);; } int -gitlab_create_milestone(struct gcli_milestone_create_args const *args) +gitlab_create_milestone(gcli_ctx *ctx, + struct gcli_milestone_create_args const *args) { char *url, *e_owner, *e_repo, *e_title, *json_body, *description = NULL; int rc = 0; @@ -130,7 +128,7 @@ gitlab_create_milestone(struct gcli_milestone_create_args const *args) e_repo = gcli_urlencode(args->repo); url = sn_asprintf("%s/projects/%s%%2F%s/milestones", - gitlab_get_apibase(), e_owner, e_repo); + gitlab_get_apibase(ctx), e_owner, e_repo); /* Escape and prepare the description if needed */ if (args->description) { @@ -147,7 +145,7 @@ gitlab_create_milestone(struct gcli_milestone_create_args const *args) "}", e_title, description ? description : ""); - rc = gcli_fetch_with_method("POST", url, json_body, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "POST", url, json_body, NULL, NULL); free(json_body); free(description); @@ -160,9 +158,8 @@ gitlab_create_milestone(struct gcli_milestone_create_args const *args) } int -gitlab_delete_milestone(char const *const owner, - char const *const repo, - int const milestone) +gitlab_delete_milestone(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const milestone) { char *url, *e_owner, *e_repo; int rc = 0; @@ -171,9 +168,9 @@ gitlab_delete_milestone(char const *const owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d", - gitlab_get_apibase(), e_owner, e_repo, milestone); + gitlab_get_apibase(ctx), e_owner, e_repo, milestone); - rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); free(e_repo); @@ -212,9 +209,8 @@ normalize_date_to_gitlab_format(char const *const input, char *output, } int -gitlab_milestone_set_duedate(char const *const owner, - char const *const repo, - int const milestone, +gitlab_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const milestone, char const *const date) { char *url, *e_owner, *e_repo, norm_date[9] = {0}; @@ -226,10 +222,10 @@ gitlab_milestone_set_duedate(char const *const owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d?due_date=%s", - gitlab_get_apibase(), e_owner, e_repo, milestone, + gitlab_get_apibase(ctx), e_owner, e_repo, milestone, norm_date); - rc = gcli_fetch_with_method("PUT", url, "", NULL, NULL); + rc = gcli_fetch_with_method(ctx, "PUT", url, "", NULL, NULL); free(url); free(e_repo); diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index 1c8778a9..a5f55899 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -40,47 +40,46 @@ #include static int -fetch_pipelines(char *url, int const max, gitlab_pipeline_list *const list) +fetch_pipelines(gcli_ctx *ctx, char *url, int const max, + gitlab_pipeline_list *const list) { - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &list->pipelines, .sizep = &list->pipelines_size, .max = max, .parse = (parsefn)(parse_gitlab_pipelines), }; - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -gitlab_get_pipelines(char const *owner, - char const *repo, - int const max, - gitlab_pipeline_list *const list) +gitlab_get_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, + int const max, gitlab_pipeline_list *const list) { char *url = NULL; url = sn_asprintf("%s/projects/%s%%2F%s/pipelines", - gitlab_get_apibase(), owner, repo); + gitlab_get_apibase(ctx), owner, repo); - return fetch_pipelines(url, max, list); + return fetch_pipelines(ctx, url, max, list); } static int -gitlab_get_mr_pipelines(char const *owner, char const *repo, int const mr_id, - gitlab_pipeline_list *const list) +gitlab_get_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, + int const mr_id, gitlab_pipeline_list *const list) { char *url = NULL; url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d/pipelines", - gitlab_get_apibase(), owner, repo, mr_id); + gitlab_get_apibase(ctx), owner, repo, mr_id); /* fetch everything */ - return fetch_pipelines(url, -1, list); + return fetch_pipelines(ctx, url, -1, list); } void -gitlab_print_pipelines(gitlab_pipeline_list const *const list) +gitlab_print_pipelines(gcli_ctx *ctx, gitlab_pipeline_list const *const list) { gcli_tbl table; gcli_tblcoldef cols[] = { @@ -96,7 +95,7 @@ gitlab_print_pipelines(gitlab_pipeline_list const *const list) return; } - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not init table"); @@ -130,41 +129,40 @@ gitlab_free_pipelines(gitlab_pipeline_list *const list) } void -gitlab_pipelines(char const *owner, char const *repo, int const count) +gitlab_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, + int const count) { gitlab_pipeline_list pipelines = {0}; - if (gitlab_get_pipelines(owner, repo, count, &pipelines) < 0) + if (gitlab_get_pipelines(ctx, owner, repo, count, &pipelines) < 0) errx(1,"error: could not fetch list of pipelines"); - gitlab_print_pipelines(&pipelines); + gitlab_print_pipelines(ctx, &pipelines); gitlab_free_pipelines(&pipelines); } void -gitlab_pipeline_jobs(char const *owner, - char const *repo, - long const id, - int const count) +gitlab_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, + long const id, int const count) { gitlab_job_list jobs = {0}; int rc; - rc = gitlab_get_pipeline_jobs(owner, repo, id, count, &jobs); + rc = gitlab_get_pipeline_jobs(ctx, owner, repo, id, count, &jobs); if (rc < 0) errx(1, "error: failed to get jobs"); - gitlab_print_jobs(&jobs); + gitlab_print_jobs(ctx, &jobs); gitlab_free_jobs(&jobs); } int -gitlab_get_pipeline_jobs(char const *owner, char const *repo, +gitlab_get_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, long const pipeline, int const max, gitlab_job_list *const out) { char *url = NULL; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->jobs, .sizep = &out->jobs_size, .max = max, @@ -172,13 +170,13 @@ gitlab_get_pipeline_jobs(char const *owner, char const *repo, }; url = sn_asprintf("%s/projects/%s%%2F%s/pipelines/%ld/jobs", - gitlab_get_apibase(), owner, repo, pipeline); + gitlab_get_apibase(ctx), owner, repo, pipeline); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } void -gitlab_print_jobs(gitlab_job_list const *const list) +gitlab_print_jobs(gcli_ctx *ctx, gitlab_job_list const *const list) { gcli_tbl table; gcli_tblcoldef cols[] = { @@ -196,7 +194,7 @@ gitlab_print_jobs(gitlab_job_list const *const list) return; } - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not initialize table"); @@ -241,16 +239,17 @@ gitlab_free_jobs(gitlab_job_list *list) } int -gitlab_job_get_log(char const *owner, char const *repo, long const job_id) +gitlab_job_get_log(gcli_ctx *ctx, char const *owner, char const *repo, + long const job_id) { gcli_fetch_buffer buffer = {0}; char *url = NULL; int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld/trace", - gitlab_get_apibase(), owner, repo, job_id); + gitlab_get_apibase(ctx), owner, repo, job_id); - rc = gcli_fetch(url, NULL, &buffer); + rc = gcli_fetch(ctx, url, NULL, &buffer); if (rc == 0) { fwrite(buffer.data, buffer.length, 1, stdout); } @@ -262,25 +261,23 @@ gitlab_job_get_log(char const *owner, char const *repo, long const job_id) } static int -gitlab_get_job(char const *owner, - char const *repo, - long const jid, - gitlab_job *const out) +gitlab_get_job(gcli_ctx *ctx, char const *owner, char const *repo, + long const jid, gitlab_job *const out) { gcli_fetch_buffer buffer = {0}; char *url = NULL; int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld", - gitlab_get_apibase(), owner, repo, jid); + gitlab_get_apibase(ctx), owner, repo, jid); - rc = gcli_fetch(url, NULL, &buffer); + rc = gcli_fetch(ctx, url, NULL, &buffer); if (rc == 0) { struct json_stream stream = {0}; json_open_buffer(&stream, buffer.data, buffer.length); json_set_streaming(&stream, 1); - parse_gitlab_job(&stream, out); + parse_gitlab_job(ctx, &stream, out); json_close(&stream); } @@ -291,11 +288,11 @@ gitlab_get_job(char const *owner, } static void -gitlab_print_job_status(gitlab_job const *const job) +gitlab_print_job_status(gcli_ctx *ctx, gitlab_job const *const job) { gcli_dict printer; - printer = gcli_dict_begin(); + printer = gcli_dict_begin(ctx); gcli_dict_add(printer, "ID", 0, 0, "%ld", job->id); gcli_dict_add_string(printer, "STATUS", GCLI_TBLCOL_STATECOLOURED, 0, job->status); @@ -313,14 +310,15 @@ gitlab_print_job_status(gitlab_job const *const job) } int -gitlab_job_status(char const *owner, char const *repo, long const jid) +gitlab_job_status(gcli_ctx *ctx, char const *owner, char const *repo, + long const jid) { gitlab_job job = {0}; int rc = 0; - rc = gitlab_get_job(owner, repo, jid, &job); + rc = gitlab_get_job(ctx, owner, repo, jid, &job); if (rc == 0) - gitlab_print_job_status(&job); + gitlab_print_job_status(ctx, &job); gitlab_free_job(&job); @@ -328,14 +326,15 @@ gitlab_job_status(char const *owner, char const *repo, long const jid) } int -gitlab_job_cancel(char const *owner, char const *repo, long const jid) +gitlab_job_cancel(gcli_ctx *ctx, char const *owner, char const *repo, + long const jid) { char *url = NULL; int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld/cancel", - gitlab_get_apibase(), owner, repo, jid); - rc = gcli_fetch_with_method("POST", url, NULL, NULL, NULL); + gitlab_get_apibase(ctx), owner, repo, jid); + rc = gcli_fetch_with_method(ctx, "POST", url, NULL, NULL, NULL); free(url); @@ -343,14 +342,15 @@ gitlab_job_cancel(char const *owner, char const *repo, long const jid) } int -gitlab_job_retry(char const *owner, char const *repo, long const jid) +gitlab_job_retry(gcli_ctx *ctx, char const *owner, char const *repo, + long const jid) { - int rc = 0; + int rc = 0; char *url = NULL; url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld/retry", - gitlab_get_apibase(), owner, repo, jid); - rc = gcli_fetch_with_method("POST", url, NULL, NULL, NULL); + gitlab_get_apibase(ctx), owner, repo, jid); + rc = gcli_fetch_with_method(ctx, "POST", url, NULL, NULL, NULL); free(url); @@ -358,14 +358,15 @@ gitlab_job_retry(char const *owner, char const *repo, long const jid) } int -gitlab_mr_pipelines(char const *owner, char const *repo, int const mr_id) +gitlab_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, + int const mr_id) { gitlab_pipeline_list list = {0}; int rc = 0; - rc = gitlab_get_mr_pipelines(owner, repo, mr_id, &list); + rc = gitlab_get_mr_pipelines(ctx, owner, repo, mr_id, &list); if (rc == 0) - gitlab_print_pipelines(&list); + gitlab_print_pipelines(ctx, &list); gitlab_free_pipelines(&list); @@ -373,8 +374,9 @@ gitlab_mr_pipelines(char const *owner, char const *repo, int const mr_id) } int -gitlab_job_download_artifacts(char const *owner, char const *repo, - long const jid, char const *const outfile) +gitlab_job_download_artifacts(gcli_ctx *ctx, char const *owner, + char const *repo, long const jid, + char const *const outfile) { char *url; char *e_owner, *e_repo; @@ -389,10 +391,10 @@ gitlab_job_download_artifacts(char const *owner, char const *repo, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld/artifacts", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, jid); - rc = gcli_curl(f, url, "application/zip"); + rc = gcli_curl(ctx, f, url, "application/zip"); fclose(f); free(url); diff --git a/src/gitlab/releases.c b/src/gitlab/releases.c index b9b14d12..f86763eb 100644 --- a/src/gitlab/releases.c +++ b/src/gitlab/releases.c @@ -59,7 +59,7 @@ fixup_release_asset_names(gcli_release_list *list) } int -gitlab_get_releases(char const *owner, char const *repo, +gitlab_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, int const max, gcli_release_list *const list) { char *url = NULL; @@ -67,7 +67,7 @@ gitlab_get_releases(char const *owner, char const *repo, char *e_repo = NULL; int rc = 0; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &list->releases, .sizep = &list->releases_size, .max = max, @@ -81,13 +81,13 @@ gitlab_get_releases(char const *owner, char const *repo, url = sn_asprintf( "%s/projects/%s%%2F%s/releases", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo); free(e_owner); free(e_repo); - rc = gcli_fetch_list(url, &ctx); + rc = gcli_fetch_list(ctx, url, &fl); if (rc == 0) fixup_release_asset_names(list); @@ -96,7 +96,7 @@ gitlab_get_releases(char const *owner, char const *repo, } int -gitlab_create_release(gcli_new_release const *release) +gitlab_create_release(gcli_ctx *ctx, gcli_new_release const *release) { char *url = NULL; char *upload_url = NULL; @@ -114,7 +114,7 @@ gitlab_create_release(gcli_new_release const *release) /* https://docs.github.com/en/rest/reference/repos#create-a-release */ url = sn_asprintf( "%s/projects/%s%%2F%s/releases", - gitlab_get_apibase(), e_owner, e_repo); + gitlab_get_apibase(ctx), e_owner, e_repo); escaped_body = gcli_json_escape(release->body); @@ -147,7 +147,7 @@ gitlab_create_release(gcli_new_release const *release) commitish_json ? commitish_json : "", name_json ? name_json : ""); - rc = gcli_fetch_with_method("POST", url, post_data, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "POST", url, post_data, NULL, NULL); if (release->assets_size) warnx("GitLab release asset uploads are not yet supported"); @@ -165,7 +165,7 @@ gitlab_create_release(gcli_new_release const *release) } int -gitlab_delete_release(char const *owner, char const *repo, char const *id) +gitlab_delete_release(gcli_ctx *ctx, char const *owner, char const *repo, char const *id) { char *url = NULL; char *e_owner = NULL; @@ -177,10 +177,10 @@ gitlab_delete_release(char const *owner, char const *repo, char const *id) url = sn_asprintf( "%s/projects/%s%%2F%s/releases/%s", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo, id); - rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); free(e_owner); diff --git a/src/gitlab/repos.c b/src/gitlab/repos.c index f9edb4ff..0c1b596c 100644 --- a/src/gitlab/repos.c +++ b/src/gitlab/repos.c @@ -37,8 +37,7 @@ #include int -gitlab_get_repo(char const *owner, - char const *repo, +gitlab_get_repo(gcli_ctx *ctx, char const *owner, char const *repo, gcli_repo *const out) { /* GET /projects/:id */ @@ -54,14 +53,14 @@ gitlab_get_repo(char const *owner, url = sn_asprintf( "%s/projects/%s%%2F%s", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo); - rc = gcli_fetch(url, NULL, &buffer); + rc = gcli_fetch(ctx, url, NULL, &buffer); if (rc == 0) { json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_repo(&stream, out); + parse_gitlab_repo(ctx, &stream, out); json_close(&stream); } @@ -92,14 +91,13 @@ gitlab_repos_fixup_missing_visibility(gcli_repo_list *const list) } int -gitlab_get_repos(char const *owner, - int const max, +gitlab_get_repos(gcli_ctx *ctx, char const *owner, int const max, gcli_repo_list *const list) { char *url = NULL; char *e_owner = NULL; int rc = 0; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &list->repos, .sizep = &list->repos_size, .parse = (parsefn)(parse_gitlab_repos), @@ -107,10 +105,10 @@ gitlab_get_repos(char const *owner, }; e_owner = gcli_urlencode(owner); - url = sn_asprintf("%s/users/%s/projects", gitlab_get_apibase(), e_owner); + url = sn_asprintf("%s/users/%s/projects", gitlab_get_apibase(ctx), e_owner); free(e_owner); - rc = gcli_fetch_list(url, &ctx); + rc = gcli_fetch_list(ctx, url, &fl); if (rc == 0) gitlab_repos_fixup_missing_visibility(list); @@ -119,19 +117,19 @@ gitlab_get_repos(char const *owner, } int -gitlab_get_own_repos(int const max, gcli_repo_list *const out) +gitlab_get_own_repos(gcli_ctx *ctx, int const max, gcli_repo_list *const out) { - char *_account = NULL; - sn_sv account = {0}; - int n; + char *_account = NULL; + sn_sv account = {0}; + int n; - account = gitlab_get_account(); + account = gitlab_get_account(ctx); if (!account.length) errx(1, "error: gitlab.account is not set"); _account = sn_sv_to_cstr(account); - n = gitlab_get_repos(_account, max, out); + n = gitlab_get_repos(ctx, _account, max, out); free(_account); @@ -139,7 +137,7 @@ gitlab_get_own_repos(int const max, gcli_repo_list *const out) } int -gitlab_repo_delete(char const *owner, char const *repo) +gitlab_repo_delete(gcli_ctx *ctx, char const *owner, char const *repo) { char *url = NULL; char *e_owner = NULL; @@ -147,13 +145,13 @@ gitlab_repo_delete(char const *owner, char const *repo) int rc = 0; e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), e_owner, e_repo); - rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); free(e_owner); @@ -163,7 +161,7 @@ gitlab_repo_delete(char const *owner, char const *repo) } int -gitlab_repo_create(gcli_repo_create_options const *options, +gitlab_repo_create(gcli_ctx *ctx, gcli_repo_create_options const *options, gcli_repo *out) { char *url, *data; @@ -172,7 +170,7 @@ gitlab_repo_create(gcli_repo_create_options const *options, int rc; /* Request preparation */ - url = sn_asprintf("%s/projects", gitlab_get_apibase()); + url = sn_asprintf("%s/projects", gitlab_get_apibase(ctx)); /* TODO: escape the repo name and the description */ data = sn_asprintf("{\"name\": \""SV_FMT"\"," " \"description\": \""SV_FMT"\"," @@ -182,10 +180,10 @@ gitlab_repo_create(gcli_repo_create_options const *options, options->private ? "private" : "public"); /* Fetch and parse result */ - rc = gcli_fetch_with_method("POST", url, data, NULL, out ? &buffer : NULL); + rc = gcli_fetch_with_method(ctx, "POST", url, data, NULL, out ? &buffer : NULL); if (rc == 0 && out) { json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_repo(&stream, out); + parse_gitlab_repo(ctx, &stream, out); json_close(&stream); } diff --git a/src/gitlab/review.c b/src/gitlab/review.c index 49eb4feb..bb779888 100644 --- a/src/gitlab/review.c +++ b/src/gitlab/review.c @@ -40,12 +40,12 @@ #include int -gitlab_review_get_reviews(char const *owner, char const *repo, +gitlab_review_get_reviews(gcli_ctx *ctx, char const *owner, char const *repo, int const pr, gcli_pr_review_list *const out) { char *url = NULL; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->reviews, .sizep = &out->reviews_size, .max = -1, @@ -54,7 +54,7 @@ gitlab_review_get_reviews(char const *owner, char const *repo, url = sn_asprintf( "%s/projects/%s%%2F%s/merge_requests/%d/notes?sort=asc", - gitlab_get_apibase(), owner, repo, pr); + gitlab_get_apibase(ctx), owner, repo, pr); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } diff --git a/src/gitlab/snippets.c b/src/gitlab/snippets.c index aa5b445f..6175d8d4 100644 --- a/src/gitlab/snippets.c +++ b/src/gitlab/snippets.c @@ -59,11 +59,11 @@ gcli_snippets_free(gcli_snippet_list *const list) } int -gcli_snippets_get(int const max, gcli_snippet_list *const out) +gcli_snippets_get(gcli_ctx *ctx, int const max, gcli_snippet_list *const out) { char *url = NULL; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &out->snippets, .sizep = &out->snippets_size, .max = max, @@ -71,20 +71,20 @@ gcli_snippets_get(int const max, gcli_snippet_list *const out) }; *out = (gcli_snippet_list) {0}; - url = sn_asprintf("%s/snippets", gitlab_get_apibase()); + url = sn_asprintf("%s/snippets", gitlab_get_apibase(ctx)); - return gcli_fetch_list(url, &ctx);; + return gcli_fetch_list(ctx, url, &fl); } static void -gcli_print_snippet(enum gcli_output_flags const flags, +gcli_print_snippet(gcli_ctx *ctx, enum gcli_output_flags const flags, gcli_snippet const *const it) { gcli_dict dict; (void) flags; - dict = gcli_dict_begin(); + dict = gcli_dict_begin(ctx); gcli_dict_add(dict, "ID", 0, 0, "%d", it->id); gcli_dict_add_string(dict, "TITLE", 0, 0, it->title); @@ -98,9 +98,8 @@ gcli_print_snippet(enum gcli_output_flags const flags, } static void -gcli_print_snippets_long(enum gcli_output_flags const flags, - gcli_snippet_list const *const list, - int const max) +gcli_print_snippets_long(gcli_ctx *ctx, enum gcli_output_flags const flags, + gcli_snippet_list const *const list, int const max) { int n; @@ -112,17 +111,16 @@ gcli_print_snippets_long(enum gcli_output_flags const flags, if (flags & OUTPUT_SORTED) { for (int i = 0; i < n; ++i) - gcli_print_snippet(flags, &list->snippets[n-i-1]); + gcli_print_snippet(ctx, flags, &list->snippets[n-i-1]); } else { for (int i = 0; i < n; ++i) - gcli_print_snippet(flags, &list->snippets[i]); + gcli_print_snippet(ctx, flags, &list->snippets[i]); } } static void -gcli_print_snippets_short(enum gcli_output_flags const flags, - gcli_snippet_list const *const list, - int const max) +gcli_print_snippets_short(gcli_ctx *ctx, enum gcli_output_flags const flags, + gcli_snippet_list const *const list, int const max) { int n; gcli_tbl table; @@ -141,7 +139,7 @@ gcli_print_snippets_short(enum gcli_output_flags const flags, n = max; /* Fill table */ - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not init table"); @@ -167,9 +165,8 @@ gcli_print_snippets_short(enum gcli_output_flags const flags, } void -gcli_snippets_print(enum gcli_output_flags const flags, - gcli_snippet_list const *const list, - int const max) +gcli_snippets_print(gcli_ctx *ctx, enum gcli_output_flags const flags, + gcli_snippet_list const *const list, int const max) { if (list->snippets_size == 0) { puts("No Snippets"); @@ -177,19 +174,19 @@ gcli_snippets_print(enum gcli_output_flags const flags, } if (flags & OUTPUT_LONG) - gcli_print_snippets_long(flags, list, max); + gcli_print_snippets_long(ctx, flags, list, max); else - gcli_print_snippets_short(flags, list, max); + gcli_print_snippets_short(ctx, flags, list, max); } int -gcli_snippet_delete(char const *snippet_id) +gcli_snippet_delete(gcli_ctx *ctx, char const *snippet_id) { int rc = 0; char *url; - url = sn_asprintf("%s/snippets/%s", gitlab_get_apibase(), snippet_id); - rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + url = sn_asprintf("%s/snippets/%s", gitlab_get_apibase(ctx), snippet_id); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); @@ -197,13 +194,13 @@ gcli_snippet_delete(char const *snippet_id) } int -gcli_snippet_get(char const *snippet_id) +gcli_snippet_get(gcli_ctx *ctx, char const *snippet_id) { int rc = 0; char *url = sn_asprintf("%s/snippets/%s/raw", - gitlab_get_apibase(), + gitlab_get_apibase(ctx), snippet_id); - rc = gcli_curl(stdout, url, NULL); + rc = gcli_curl(ctx, stdout, url, NULL); free(url); return rc; diff --git a/src/gitlab/sshkeys.c b/src/gitlab/sshkeys.c index 441af1b7..15e0100f 100644 --- a/src/gitlab/sshkeys.c +++ b/src/gitlab/sshkeys.c @@ -42,10 +42,10 @@ #include int -gitlab_get_sshkeys(gcli_sshkey_list *list) +gitlab_get_sshkeys(gcli_ctx *ctx, gcli_sshkey_list *list) { char *url; - gcli_fetch_list_ctx ctx = { + gcli_fetch_list_ctx fl = { .listp = &list->keys, .sizep = &list->keys_size, .max = -1, @@ -53,22 +53,21 @@ gitlab_get_sshkeys(gcli_sshkey_list *list) }; *list = (gcli_sshkey_list) {0}; - url = sn_asprintf("%s/user/keys", gcli_get_apibase()); + url = sn_asprintf("%s/user/keys", gcli_get_apibase(ctx)); - return gcli_fetch_list(url, &ctx); + return gcli_fetch_list(ctx, url, &fl); } int -gitlab_add_sshkey(char const *const title, - char const *const pubkey, - gcli_sshkey *const out) +gitlab_add_sshkey(gcli_ctx *ctx, char const *const title, + char const *const pubkey, gcli_sshkey *const out) { char *url, *payload; char *e_title, *e_key; gcli_fetch_buffer buf = {0}; int rc = 0; - url = sn_asprintf("%s/user/keys", gcli_get_apibase()); + url = sn_asprintf("%s/user/keys", gcli_get_apibase(ctx)); /* Prepare payload */ e_title = gcli_json_escape_cstr(title); @@ -79,12 +78,12 @@ gitlab_add_sshkey(char const *const title, free(e_title); free(e_key); - rc = gcli_fetch_with_method("POST", url, payload, NULL, &buf); + rc = gcli_fetch_with_method(ctx, "POST", url, payload, NULL, &buf); if (rc == 0 && out) { json_stream str; json_open_buffer(&str, buf.data, buf.length); - parse_gitlab_sshkey(&str, out); + parse_gitlab_sshkey(ctx, &str, out); json_close(&str); } @@ -94,13 +93,13 @@ gitlab_add_sshkey(char const *const title, } int -gitlab_delete_sshkey(int id) +gitlab_delete_sshkey(gcli_ctx *ctx, int id) { char *url; int rc = 0; - url = sn_asprintf("%s/user/keys/%d", gcli_get_apibase(), id); - rc = gcli_fetch_with_method("DELETE", url, NULL, NULL, NULL); + url = sn_asprintf("%s/user/keys/%d", gcli_get_apibase(ctx), id); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); diff --git a/src/gitlab/status.c b/src/gitlab/status.c index 8d0ee2fb..d8cca65d 100644 --- a/src/gitlab/status.c +++ b/src/gitlab/status.c @@ -38,7 +38,7 @@ #include int -gitlab_get_notifications(gcli_notification **const notifications, +gitlab_get_notifications(gcli_ctx *ctx, gcli_notification **const notifications, int const count) { char *url = NULL; @@ -48,14 +48,15 @@ gitlab_get_notifications(gcli_notification **const notifications, size_t notifications_size = 0; int rc = 0; - url = sn_asprintf("%s/todos", gitlab_get_apibase()); + url = sn_asprintf("%s/todos", gitlab_get_apibase(ctx)); do { - rc = gcli_fetch(url, &next_url, &buffer); + rc = gcli_fetch(ctx, url, &next_url, &buffer); if (rc == 0) { json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_todos(&stream, notifications, ¬ifications_size); + parse_gitlab_todos(ctx, &stream, notifications, + ¬ifications_size); json_close(&stream); } @@ -74,13 +75,13 @@ gitlab_get_notifications(gcli_notification **const notifications, } int -gitlab_notification_mark_as_read(char const *id) +gitlab_notification_mark_as_read(gcli_ctx *ctx, char const *id) { char *url = NULL; int rc = 0; - url = sn_asprintf("%s/todos/%s/mark_as_done", gitlab_get_apibase(), id); - rc = gcli_fetch_with_method("POST", url, NULL, NULL, NULL); + url = sn_asprintf("%s/todos/%s/mark_as_done", gitlab_get_apibase(ctx), id); + rc = gcli_fetch_with_method(ctx, "POST", url, NULL, NULL, NULL); free(url); diff --git a/src/issues.c b/src/issues.c index af7bbdfb..8f6ec767 100644 --- a/src/issues.c +++ b/src/issues.c @@ -65,19 +65,16 @@ gcli_issues_free(gcli_issue_list *const list) } int -gcli_get_issues(char const *owner, - char const *repo, - gcli_issue_fetch_details const *details, - int const max, +gcli_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_issue_fetch_details const *details, int const max, gcli_issue_list *const out) { - return gcli_forge()->get_issues(owner, repo, details, max, out); + return gcli_forge(ctx)->get_issues(ctx, owner, repo, details, max, out); } void -gcli_print_issues_table(enum gcli_output_flags const flags, - gcli_issue_list const *const list, - int const max) +gcli_print_issues_table(gcli_ctx *ctx, enum gcli_output_flags const flags, + gcli_issue_list const *const list, int const max) { int n, pruned = 0; gcli_tbl table; @@ -93,7 +90,7 @@ gcli_print_issues_table(enum gcli_output_flags const flags, return; } - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); if (!table) errx(1, "could not init table printer"); @@ -139,11 +136,11 @@ gcli_print_issues_table(enum gcli_output_flags const flags, } void -gcli_issue_print_summary(gcli_issue const *const it) +gcli_issue_print_summary(gcli_ctx *ctx, gcli_issue const *const it) { gcli_dict dict; - dict = gcli_dict_begin(); + dict = gcli_dict_begin(ctx); gcli_dict_add(dict, "NAME", 0, 0, "%d", it->number); gcli_dict_add(dict, "TITLE", 0, 0, SV_FMT, SV_ARGS(it->title)); @@ -184,27 +181,31 @@ gcli_issue_print_op(gcli_issue const *const it) } int -gcli_get_issue(char const *owner, char const *repo, +gcli_get_issue(gcli_ctx *ctx, char const *owner, char const *repo, int const issue_number, gcli_issue *const out) { - return gcli_forge()->get_issue_summary(owner, repo, issue_number, out); + return gcli_forge(ctx)->get_issue_summary( + ctx, owner, repo, issue_number, out); } int -gcli_issue_close(char const *owner, char const *repo, int const issue_number) +gcli_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue_number) { - return gcli_forge()->issue_close(owner, repo, issue_number); + return gcli_forge(ctx)->issue_close(ctx, owner, repo, issue_number); } int -gcli_issue_reopen(char const *owner, char const *repo, int const issue_number) +gcli_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue_number) { - return gcli_forge()->issue_reopen(owner, repo, issue_number); + return gcli_forge(ctx)->issue_reopen(ctx, owner, repo, issue_number); } static void -issue_init_user_file(FILE *stream, void *_opts) +issue_init_user_file(gcli_ctx *ctx, FILE *stream, void *_opts) { + (void) ctx; gcli_submit_issue_options *opts = _opts; fprintf( stream, @@ -215,18 +216,18 @@ issue_init_user_file(FILE *stream, void *_opts) } static sn_sv -gcli_issue_get_user_message(gcli_submit_issue_options *opts) +gcli_issue_get_user_message(gcli_ctx *ctx, gcli_submit_issue_options *opts) { - return gcli_editor_get_user_message(issue_init_user_file, opts); + return gcli_editor_get_user_message(ctx, issue_init_user_file, opts); } int -gcli_issue_submit(gcli_submit_issue_options opts) +gcli_issue_submit(gcli_ctx *ctx, gcli_submit_issue_options opts) { gcli_fetch_buffer json_buffer = {0}; int rc = 0; - opts.body = gcli_issue_get_user_message(&opts); + opts.body = gcli_issue_get_user_message(ctx, &opts); printf("The following issue will be created:\n" "\n" @@ -245,10 +246,10 @@ gcli_issue_submit(gcli_submit_issue_options opts) errx(1, "Submission aborted."); } - rc = gcli_forge()->perform_submit_issue(opts, &json_buffer); + rc = gcli_forge(ctx)->perform_submit_issue(ctx, opts, &json_buffer); if (rc == 0) - gcli_print_html_url(json_buffer); + gcli_print_html_url(ctx, json_buffer); free(opts.body.data); free(opts.body.data); @@ -258,47 +259,42 @@ gcli_issue_submit(gcli_submit_issue_options opts) } int -gcli_issue_assign(char const *owner, - char const *repo, - int const issue_number, - char const *assignee) +gcli_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue_number, char const *assignee) { - return gcli_forge()->issue_assign(owner, repo, issue_number, assignee); + return gcli_forge(ctx)->issue_assign(ctx, owner, repo, issue_number, assignee); } int -gcli_issue_add_labels(char const *owner, - char const *repo, - int const issue, - char const *const labels[], +gcli_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue, char const *const labels[], size_t const labels_size) { - return gcli_forge()->issue_add_labels(owner, repo, issue, labels, labels_size); + return gcli_forge(ctx)->issue_add_labels(ctx,owner, repo, issue, labels, + labels_size); } int -gcli_issue_remove_labels(char const *owner, - char const *repo, - int const issue, - char const *const labels[], +gcli_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int const issue, char const *const labels[], size_t const labels_size) { - return gcli_forge()->issue_remove_labels(owner, repo, issue, labels, labels_size); + return gcli_forge(ctx)->issue_remove_labels( + ctx, owner, repo, issue, labels, labels_size); } int -gcli_issue_set_milestone(char const *const owner, - char const *const repo, - int const issue, +gcli_issue_set_milestone(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const issue, int const milestone) { - return gcli_forge()->issue_set_milestone(owner, repo, issue, milestone); + return gcli_forge(ctx)->issue_set_milestone( + ctx, owner, repo, issue, milestone); } int -gcli_issue_clear_milestone(char const *const owner, - char const *const repo, - int const issue) +gcli_issue_clear_milestone(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const issue) { - return gcli_forge()->issue_clear_milestone(owner, repo, issue); + return gcli_forge(ctx)->issue_clear_milestone(ctx, owner, repo, issue); } diff --git a/src/json_util.c b/src/json_util.c index a3542a58..c13737ce 100644 --- a/src/json_util.c +++ b/src/json_util.c @@ -50,8 +50,10 @@ barf(char const *message, char const *where) } long -get_int_(json_stream *const input, char const *where) +get_int_(gcli_ctx *ctx, json_stream *const input, char const *where) { + (void) ctx; + if (json_next(input) != JSON_NUMBER) barf("unexpected non-integer field", where); @@ -59,8 +61,10 @@ get_int_(json_stream *const input, char const *where) } double -get_double_(json_stream *const input, char const *where) +get_double_(gcli_ctx *ctx, json_stream *const input, char const *where) { + (void) ctx; + enum json_type type = json_next(input); /* This is dumb but it fixes a couple of weirdnesses of the API */ @@ -74,8 +78,10 @@ get_double_(json_stream *const input, char const *where) } char * -get_string_(json_stream *const input, char const *where) +get_string_(gcli_ctx *ctx, json_stream *const input, char const *where) { + (void) ctx; + enum json_type const type = json_next(input); if (type == JSON_NULL) return strdup(""); @@ -93,8 +99,10 @@ get_string_(json_stream *const input, char const *where) } bool -get_bool_(json_stream *const input, char const *where) +get_bool_(gcli_ctx *ctx,json_stream *const input, char const *where) { + (void) ctx; + enum json_type value_type = json_next(input); if (value_type == JSON_TRUE) return true; @@ -108,12 +116,12 @@ get_bool_(json_stream *const input, char const *where) } char * -get_user_(json_stream *const input, char const *where) +get_user_(gcli_ctx *ctx, json_stream *const input, char const *where) { if (json_next(input) != JSON_OBJECT) barf("user field is not an object", where); - char const *expected_key = gcli_forge()->user_object_key; + char const *expected_key = gcli_forge(ctx)->user_object_key; char *result = NULL; while (json_next(input) == JSON_STRING) { @@ -178,8 +186,10 @@ gcli_json_escape(sn_sv const it) } sn_sv -get_sv_(json_stream *const input, char const *where) +get_sv_(gcli_ctx *ctx, json_stream *const input, char const *where) { + (void) ctx; + enum json_type type = json_next(input); if (type == JSON_NULL) return SV_NULL; @@ -194,7 +204,7 @@ get_sv_(json_stream *const input, char const *where) } void -gcli_print_html_url(gcli_fetch_buffer const buffer) +gcli_print_html_url(gcli_ctx *ctx, gcli_fetch_buffer const buffer) { json_stream stream = {0}; @@ -202,14 +212,14 @@ gcli_print_html_url(gcli_fetch_buffer const buffer) json_set_streaming(&stream, true); enum json_type next = json_next(&stream); - char const *expected_key = gcli_forge()->html_url_key; + char const *expected_key = gcli_forge(ctx)->html_url_key; while ((next = json_next(&stream)) == JSON_STRING) { size_t len; char const *key = json_get_string(&stream, &len); if (strncmp(key, expected_key, len) == 0) { - char *url = get_string(&stream); + char *url = get_string(ctx, &stream); puts(url); free(url); } else { @@ -306,11 +316,11 @@ gcli_json_advance(json_stream *const stream, char const *fmt, ...) } long -get_parse_int_(json_stream *const input, char const *function) +get_parse_int_(gcli_ctx *ctx, json_stream *const input, char const *function) { long result = 0; char *endptr = NULL; - char *string = get_string(input); + char *string = get_string(ctx, input); result = strtol(string, &endptr, 10); if (endptr != string + strlen(string)) @@ -321,10 +331,10 @@ get_parse_int_(json_stream *const input, char const *function) } uint32_t -get_github_style_colour(json_stream *const input) +get_github_style_colour(gcli_ctx *ctx, json_stream *const input) { - char *colour_str = get_string(input); - char *endptr = NULL; + char *colour_str = get_string(ctx, input); + char *endptr = NULL; unsigned long colour = strtoul(colour_str, &endptr, 16); if (endptr != colour_str + strlen(colour_str)) @@ -337,11 +347,11 @@ get_github_style_colour(json_stream *const input) } uint32_t -get_gitlab_style_colour(json_stream *const input) +get_gitlab_style_colour(gcli_ctx *ctx, json_stream *const input) { - char *colour = get_string(input); + char *colour = get_string(ctx, input); char *endptr = NULL; - long code = 0; + long code = 0; code = strtol(colour + 1, &endptr, 16); if (endptr != (colour + 1 + strlen(colour + 1))) @@ -353,10 +363,10 @@ get_gitlab_style_colour(json_stream *const input) } sn_sv -get_gitea_visibility(json_stream *const input) +get_gitea_visibility(gcli_ctx *ctx, json_stream *const input) { char *v = NULL; - if (get_bool(input)) + if (get_bool(ctx, input)) v = strdup("private"); else v = strdup("public"); @@ -364,17 +374,19 @@ get_gitea_visibility(json_stream *const input) } bool -get_gitlab_can_be_merged(json_stream *const input) +get_gitlab_can_be_merged(gcli_ctx *ctx, json_stream *const input) { - sn_sv tmp = get_sv(input); + sn_sv tmp = get_sv(ctx, input); bool result = sn_sv_eq_to(tmp, "can_be_merged"); free(tmp.data); return result; } int -get_github_is_pr(json_stream *input) +get_github_is_pr(gcli_ctx *ctx, json_stream *input) { + (void) ctx; + enum json_type next = json_peek(input); if (next == JSON_NULL) diff --git a/src/labels.c b/src/labels.c index 8f239f26..0bf724b5 100644 --- a/src/labels.c +++ b/src/labels.c @@ -34,12 +34,10 @@ #include int -gcli_get_labels(char const *owner, - char const *reponame, - int const max, - gcli_label_list *const out) +gcli_get_labels(gcli_ctx *ctx, char const *owner, char const *reponame, + int const max, gcli_label_list *const out) { - return gcli_forge()->get_labels(owner, reponame, max, out); + return gcli_forge(ctx)->get_labels(ctx, owner, reponame, max, out); } void @@ -61,7 +59,8 @@ gcli_free_labels(gcli_label_list *const list) } void -gcli_print_labels(gcli_label_list const *const list, int const max) +gcli_print_labels(gcli_ctx *ctx, gcli_label_list const *const list, + int const max) { size_t n; gcli_tbl table; @@ -79,7 +78,7 @@ gcli_print_labels(gcli_label_list const *const list, int const max) n = max; /* Fill table */ - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not init table"); @@ -87,7 +86,7 @@ gcli_print_labels(gcli_label_list const *const list, int const max) gcli_tbl_add_row(table, (long)list->labels[i].id, /* Cast is important here (#165) */ list->labels[i].colour, - gcli_config_have_colours() ? " " : "", + gcli_config_have_colours(ctx) ? " " : "", list->labels[i].name, list->labels[i].description); } @@ -96,13 +95,15 @@ gcli_print_labels(gcli_label_list const *const list, int const max) } int -gcli_create_label(char const *owner, char const *repo, gcli_label *const label) +gcli_create_label(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_label *const label) { - return gcli_forge()->create_label(owner, repo, label); + return gcli_forge(ctx)->create_label(ctx, owner, repo, label); } int -gcli_delete_label(char const *owner, char const *repo, char const *const label) +gcli_delete_label(gcli_ctx *ctx, char const *owner, char const *repo, + char const *const label) { - return gcli_forge()->delete_label(owner, repo, label); + return gcli_forge(ctx)->delete_label(ctx, owner, repo, label); } diff --git a/src/milestones.c b/src/milestones.c index c44564ad..529976e3 100644 --- a/src/milestones.c +++ b/src/milestones.c @@ -32,39 +32,36 @@ #include int -gcli_get_milestones(char const *const owner, - char const *const repo, - int const max, +gcli_get_milestones(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const max, gcli_milestone_list *const out) { - return gcli_forge()->get_milestones(owner, repo, max, out); + return gcli_forge(ctx)->get_milestones(ctx, owner, repo, max, out); } int -gcli_get_milestone(char const *owner, - char const *repo, - int const milestone, - gcli_milestone *const out) +gcli_get_milestone(gcli_ctx *ctx, char const *owner, char const *repo, + int const milestone, gcli_milestone *const out) { - return gcli_forge()->get_milestone(owner, repo, milestone, out); + return gcli_forge(ctx)->get_milestone(ctx, owner, repo, milestone, out); } int -gcli_create_milestone(struct gcli_milestone_create_args const *args) +gcli_create_milestone(gcli_ctx *ctx, + struct gcli_milestone_create_args const *args) { - return gcli_forge()->create_milestone(args); + return gcli_forge(ctx)->create_milestone(ctx, args); } int -gcli_delete_milestone(char const *const owner, - char const *const repo, - int const milestone) +gcli_delete_milestone(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const milestone) { - return gcli_forge()->delete_milestone(owner, repo, milestone); + return gcli_forge(ctx)->delete_milestone(ctx, owner, repo, milestone); } void -gcli_print_milestones(gcli_milestone_list const *const list, +gcli_print_milestones(gcli_ctx *ctx, gcli_milestone_list const *const list, int max) { size_t n; @@ -81,7 +78,7 @@ gcli_print_milestones(gcli_milestone_list const *const list, return; } - tbl = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + tbl = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); if (!tbl) errx(1, "error: could not init table printer"); @@ -102,12 +99,12 @@ gcli_print_milestones(gcli_milestone_list const *const list, } void -gcli_print_milestone(gcli_milestone const *const milestone) +gcli_print_milestone(gcli_ctx *ctx, gcli_milestone const *const milestone) { gcli_dict dict; - uint32_t const quirks = gcli_forge()->milestone_quirks; + uint32_t const quirks = gcli_forge(ctx)->milestone_quirks; - dict = gcli_dict_begin(); + dict = gcli_dict_begin(ctx); gcli_dict_add(dict, "ID", 0, 0, "%d", milestone->id); gcli_dict_add_string(dict, "TITLE", 0, 0, milestone->title); gcli_dict_add_string(dict, "STATE", GCLI_TBLCOL_STATECOLOURED, 0, milestone->state); @@ -163,19 +160,19 @@ gcli_free_milestones(gcli_milestone_list *const it) } int -gcli_milestone_get_issues(char const *const owner, - char const *const repo, - int const milestone, +gcli_milestone_get_issues(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const milestone, gcli_issue_list *const out) { - return gcli_forge()->get_milestone_issues(owner, repo, milestone, out); + return gcli_forge(ctx)->get_milestone_issues( + ctx, owner, repo, milestone, out); } int -gcli_milestone_set_duedate(char const *const owner, - char const *const repo, - int const milestone, +gcli_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, + char const *const repo, int const milestone, char const *const date) { - return gcli_forge()->milestone_set_duedate(owner, repo, milestone, date); + return gcli_forge(ctx)->milestone_set_duedate( + ctx, owner, repo, milestone, date); } diff --git a/src/pgen/dump_c.c b/src/pgen/dump_c.c index e7d034d3..25e5bb7b 100644 --- a/src/pgen/dump_c.c +++ b/src/pgen/dump_c.c @@ -36,7 +36,8 @@ pregen_array_parser(struct objparser *p, struct objentry *it) { fprintf(outfile, "static void\n" - "parse_%s_%s_array(struct json_stream *stream, %s *out)\n", + "parse_%s_%s_array(gcli_ctx *ctx, struct json_stream *stream, " + "%s *out)\n", p->name, it->name, p->returntype); fprintf(outfile, "{\n"); fprintf(outfile, "\tif (json_peek(stream) == JSON_NULL) {\n"); @@ -55,7 +56,7 @@ pregen_array_parser(struct objparser *p, struct objentry *it) it->name, it->name, it->name, it->name); fprintf(outfile, "\t\tmemset(&out->%s[out->%s_size], 0, sizeof(out->%s[out->%s_size]));\n", it->name, it->name, it->name, it->name); - fprintf(outfile, "\t\t%s(stream, &out->%s[out->%s_size++]);\n", + fprintf(outfile, "\t\t%s(ctx, stream, &out->%s[out->%s_size++]);\n", it->parser, it->name, it->name); fprintf(outfile, "\t}\n\n"); @@ -81,20 +82,23 @@ objparser_dump_entries(struct objparser *p) for (struct objentry *it = p->entries; it; it = it->next) { - fprintf(outfile, "\t\tif (strncmp(\"%s\", key, len) == 0)\n", it->jsonname); + fprintf(outfile, "\t\tif (strncmp(\"%s\", key, len) == 0)\n", + it->jsonname); if (it->kind == OBJENTRY_SIMPLE) { if (it->parser) - fprintf(outfile, "\t\t\t%s(stream, &out->%s);\n", it->parser, it->name); + fprintf(outfile, "\t\t\t%s(ctx, stream, &out->%s);\n", + it->parser, it->name); else - fprintf(outfile, "\t\t\tout->%s = get_%s(stream);\n", it->name, it->type); + fprintf(outfile, "\t\t\tout->%s = get_%s(ctx, stream);\n", it->name, + it->type); } else if (it->kind == OBJENTRY_ARRAY) { - fprintf(outfile, "\t\t\tparse_%s_%s_array(stream, out);\n", + fprintf(outfile, "\t\t\tparse_%s_%s_array(ctx, stream, out);\n", p->name, it->name); } else if (it->kind == OBJENTRY_CONTINUATION) { - fprintf(outfile, "\t\t\t%s(stream, out);\n", it->parser); + fprintf(outfile, "\t\t\t%s(ctx, stream, out);\n", it->parser); } fprintf(outfile, "\t\telse "); } @@ -111,7 +115,7 @@ objparser_dump_select(struct objparser *p) fprintf(outfile, "\t\tsize_t len;\n"); fprintf(outfile, "\t\tkey = json_get_string(stream, &len);\n"); fprintf(outfile, "\t\tif (strncmp(\"%s\", key, len) == 0)\n", p->select.fieldname); - fprintf(outfile, "\t\t\t*out = get_%s(stream);\n", p->select.fieldtype); + fprintf(outfile, "\t\t\t*out = get_%s(ctx, stream);\n", p->select.fieldtype); fprintf(outfile, "\t\telse "); fprintf(outfile, "\n\t\t\tSKIP_OBJECT_VALUE(stream);\n"); fprintf(outfile, "\t}\n"); @@ -124,7 +128,7 @@ objparser_dump_c(struct objparser *p) fprintf(outfile, "void\n" - "parse_%s(struct json_stream *stream, %s *out)\n", + "parse_%s(gcli_ctx *ctx, struct json_stream *stream, %s *out)\n", p->name, p->returntype); fprintf(outfile, "{\n"); fprintf(outfile, "\tenum json_type key_type;\n"); @@ -148,7 +152,8 @@ arrayparser_dump_c(struct arrayparser *p) { fprintf(outfile, "void\n" - "parse_%s(struct json_stream *stream, %s **out, size_t *out_size)\n", + "parse_%s(gcli_ctx *ctx, struct json_stream *stream, %s **out, " + "size_t *out_size)\n", p->name, p->returntype); fprintf(outfile, "{\n"); fprintf(outfile, "\tif (json_peek(stream) == JSON_NULL) {\n"); @@ -167,7 +172,7 @@ arrayparser_dump_c(struct arrayparser *p) fprintf(outfile, "\t\t*out = realloc(*out, sizeof(**out) * (*out_size + 1));\n"); fprintf(outfile, "\t\tit = &(*out)[(*out_size)++];\n"); fprintf(outfile, "\t\tmemset(it, 0, sizeof(*it));\n"); - fprintf(outfile, "\t\t%s(stream, it);\n", p->parser); + fprintf(outfile, "\t\t%s(ctx, stream, it);\n", p->parser); fprintf(outfile, "\t}\n\n"); fprintf(outfile, "\tassert(json_next(stream) == JSON_ARRAY_END);\n"); @@ -185,6 +190,7 @@ header_dump_c(void) { fprintf(outfile, "#include \n"); fprintf(outfile, "#include \n"); + fprintf(outfile, "#include \n"); fprintf(outfile, "#include \n"); fprintf(outfile, "#include \n"); fprintf(outfile, "#include \n"); diff --git a/src/pgen/dump_h.c b/src/pgen/dump_h.c index feca8410..62561bf6 100644 --- a/src/pgen/dump_h.c +++ b/src/pgen/dump_h.c @@ -73,7 +73,7 @@ header_dump_h(void) void objparser_dump_h(struct objparser *p) { - fprintf(outfile, "void parse_%s(struct json_stream *, %s *);\n", + fprintf(outfile, "void parse_%s(gcli_ctx *ctx, struct json_stream *, %s *);\n", p->name, p->returntype); } @@ -96,6 +96,7 @@ footer_dump_h(void) void arrayparser_dump_h(struct arrayparser *p) { - fprintf(outfile, "void parse_%s(struct json_stream *, %s **out, size_t *out_size);\n", + fprintf(outfile, "void parse_%s(gcli_ctx *ctx, struct json_stream *, " + "%s **out, size_t *out_size);\n", p->name, p->returntype); } diff --git a/src/pulls.c b/src/pulls.c index d4434928..3e91fe93 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -52,19 +52,16 @@ gcli_pulls_free(gcli_pull_list *const it) } int -gcli_get_pulls(char const *owner, - char const *repo, - gcli_pull_fetch_details const *const details, - int const max, +gcli_get_pulls(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_pull_fetch_details const *const details, int const max, gcli_pull_list *const out) { - return gcli_forge()->get_pulls(owner, repo, details, max, out); + return gcli_forge(ctx)->get_pulls(ctx, owner, repo, details, max, out); } void -gcli_print_pulls_table(enum gcli_output_flags const flags, - gcli_pull_list const *const list, - int const max) +gcli_print_pulls_table(gcli_ctx *ctx, enum gcli_output_flags const flags, + gcli_pull_list const *const list, int const max) { int n; gcli_tbl table; @@ -89,7 +86,7 @@ gcli_print_pulls_table(enum gcli_output_flags const flags, n = max; /* Fill the table */ - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: cannot init table"); @@ -119,21 +116,19 @@ gcli_print_pulls_table(enum gcli_output_flags const flags, } void -gcli_print_pull_diff(FILE *stream, - char const *owner, - char const *reponame, - int const pr_number) +gcli_print_pull_diff(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *reponame, int const pr_number) { - gcli_forge()->print_pull_diff(stream, owner, reponame, pr_number); + gcli_forge(ctx)->print_pull_diff(ctx, stream, owner, reponame, pr_number); } void -gcli_pull_print_status(gcli_pull const *const it) +gcli_pull_print_status(gcli_ctx *ctx, gcli_pull const *const it) { gcli_dict dict; - gcli_forge_descriptor const *const forge = gcli_forge(); + gcli_forge_descriptor const *const forge = gcli_forge(ctx); - dict = gcli_dict_begin(); + dict = gcli_dict_begin(ctx); gcli_dict_add(dict, "NUMBER", 0, 0, "%d", it->number); gcli_dict_add_string(dict, "TITLE", 0, 0, it->title); @@ -150,12 +145,12 @@ gcli_pull_print_status(gcli_pull const *const it) if (!(forge->pull_summary_quirks & GCLI_PRS_QUIRK_ADDDEL)) /* FIXME: move printing colours into the dictionary printer? */ gcli_dict_add(dict, "ADD:DEL", 0, 0, "%s%d%s:%s%d%s", - gcli_setcolour(GCLI_COLOR_GREEN), + gcli_setcolour(ctx, GCLI_COLOR_GREEN), it->additions, - gcli_resetcolour(), - gcli_setcolour(GCLI_COLOR_RED), + gcli_resetcolour(ctx), + gcli_setcolour(ctx, GCLI_COLOR_RED), it->deletions, - gcli_resetcolour()); + gcli_resetcolour(ctx)); if (!(forge->pull_summary_quirks & GCLI_PRS_QUIRK_COMMITS)) gcli_dict_add(dict, "COMMITS", 0, 0, "%d", it->commits); @@ -180,12 +175,10 @@ gcli_pull_print_status(gcli_pull const *const it) } static int -gcli_get_pull_commits(char const *owner, - char const *repo, - int const pr_number, - gcli_commit_list *const out) +gcli_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number, gcli_commit_list *const out) { - return gcli_forge()->get_pull_commits(owner, repo, pr_number, out); + return gcli_forge(ctx)->get_pull_commits(ctx, owner, repo, pr_number, out); } /** @@ -208,7 +201,7 @@ cut_newline(char const *const _it) } static void -gcli_print_commits_table(gcli_commit_list const *const list) +gcli_print_commits_table(gcli_ctx *ctx, gcli_commit_list const *const list) { gcli_tbl table; gcli_tblcoldef cols[] = { @@ -224,7 +217,7 @@ gcli_print_commits_table(gcli_commit_list const *const list) return; } - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not initialize table"); @@ -259,14 +252,15 @@ gcli_commits_free(gcli_commit_list *list) } void -gcli_pull_commits(char const *owner, char const *repo, int const pr_number) +gcli_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number) { gcli_commit_list commits = {0}; - if (gcli_get_pull_commits(owner, repo, pr_number, &commits) < 0) + if (gcli_get_pull_commits(ctx, owner, repo, pr_number, &commits) < 0) errx(1, "error: failed to fetch commits of the pull request"); - gcli_print_commits_table(&commits); + gcli_print_commits_table(ctx, &commits); gcli_commits_free(&commits); } @@ -289,10 +283,10 @@ gcli_pull_free(gcli_pull *const it) } int -gcli_get_pull(char const *owner, char const *repo, +gcli_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, int const pr_number, gcli_pull *const out) { - return gcli_forge()->get_pull(owner, repo, pr_number, out); + return gcli_forge(ctx)->get_pull(ctx, owner, repo, pr_number, out); } void @@ -303,15 +297,17 @@ gcli_pull_print_op(gcli_pull *const pull) } int -gcli_pull_checks(char const *owner, char const *repo, int const pr_number) +gcli_pull_checks(gcli_ctx *ctx, char const *owner, char const *repo, int const pr_number) { - return gcli_forge()->print_pull_checks(owner, repo, pr_number); + return gcli_forge(ctx)->print_pull_checks(ctx, owner, repo, pr_number); } static void -pull_init_user_file(FILE *stream, void *_opts) +pull_init_user_file(gcli_ctx *ctx, FILE *stream, void *_opts) { gcli_submit_pull_options *opts = _opts; + + (void) ctx; fprintf( stream, "! PR TITLE : "SV_FMT"\n" @@ -321,15 +317,15 @@ pull_init_user_file(FILE *stream, void *_opts) } static sn_sv -gcli_pull_get_user_message(gcli_submit_pull_options *opts) +gcli_pull_get_user_message(gcli_ctx *ctx, gcli_submit_pull_options *opts) { - return gcli_editor_get_user_message(pull_init_user_file, opts); + return gcli_editor_get_user_message(ctx, pull_init_user_file, opts); } int -gcli_pull_submit(gcli_submit_pull_options opts) +gcli_pull_submit(gcli_ctx *ctx, gcli_submit_pull_options opts) { - opts.body = gcli_pull_get_user_message(&opts); + opts.body = gcli_pull_get_user_message(ctx, &opts); fprintf(stdout, "The following PR will be created:\n" @@ -350,65 +346,59 @@ gcli_pull_submit(gcli_submit_pull_options opts) if (!sn_yesno("Do you want to continue?")) errx(1, "PR aborted."); - return gcli_forge()->perform_submit_pull(opts); + return gcli_forge(ctx)->perform_submit_pull(ctx, opts); } int -gcli_pull_merge(char const *owner, - char const *reponame, - int const pr_number, - enum gcli_merge_flags flags) +gcli_pull_merge(gcli_ctx *ctx, char const *owner, char const *reponame, + int const pr_number, enum gcli_merge_flags flags) { - return gcli_forge()->pull_merge(owner, reponame, pr_number, flags); + return gcli_forge(ctx)->pull_merge(ctx, owner, reponame, pr_number, flags); } int -gcli_pull_close(char const *owner, char const *reponame, int const pr_number) +gcli_pull_close(gcli_ctx *ctx, char const *owner, char const *reponame, + int const pr_number) { - return gcli_forge()->pull_close(owner, reponame, pr_number); + return gcli_forge(ctx)->pull_close(ctx, owner, reponame, pr_number); } int -gcli_pull_reopen(char const *owner, char const *reponame, int const pr_number) +gcli_pull_reopen(gcli_ctx *ctx, char const *owner, char const *reponame, + int const pr_number) { - return gcli_forge()->pull_reopen(owner, reponame, pr_number); + return gcli_forge(ctx)->pull_reopen(ctx, owner, reponame, pr_number); } int -gcli_pull_add_labels(char const *owner, - char const *repo, - int const pr_number, - char const *const labels[], +gcli_pull_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number, char const *const labels[], size_t const labels_size) { - return gcli_forge()->pull_add_labels( - owner, repo, pr_number, labels, labels_size); + return gcli_forge(ctx)->pull_add_labels( + ctx, owner, repo, pr_number, labels, labels_size); } int -gcli_pull_remove_labels(char const *owner, - char const *repo, - int const pr_number, - char const *const labels[], +gcli_pull_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number, char const *const labels[], size_t const labels_size) { - return gcli_forge()->pull_remove_labels( - owner, repo, pr_number, labels, labels_size); + return gcli_forge(ctx)->pull_remove_labels( + ctx, owner, repo, pr_number, labels, labels_size); } int -gcli_pull_set_milestone(char const *owner, - char const *repo, - int pr_number, - int milestone_id) +gcli_pull_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, + int pr_number, int milestone_id) { - return gcli_forge()->pull_set_milestone(owner, repo, pr_number, milestone_id); + return gcli_forge(ctx)->pull_set_milestone( + ctx, owner, repo, pr_number, milestone_id); } int -gcli_pull_clear_milestone(char const *owner, - char const *repo, +gcli_pull_clear_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number) { - return gcli_forge()->pull_clear_milestone(owner, repo, pr_number); + return gcli_forge(ctx)->pull_clear_milestone(ctx, owner, repo, pr_number); } diff --git a/src/releases.c b/src/releases.c index ab13c871..70fa08c6 100644 --- a/src/releases.c +++ b/src/releases.c @@ -36,21 +36,21 @@ #include int -gcli_get_releases(char const *owner, char const *repo, +gcli_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, int const max, gcli_release_list *const list) { - return gcli_forge()->get_releases(owner, repo, max, list); + return gcli_forge(ctx)->get_releases(ctx, owner, repo, max, list); } static void -gcli_print_release(enum gcli_output_flags const flags, +gcli_print_release(gcli_ctx *ctx, enum gcli_output_flags const flags, gcli_release const *const it) { gcli_dict dict; (void) flags; - dict = gcli_dict_begin(); + dict = gcli_dict_begin(ctx); gcli_dict_add(dict, "ID", 0, 0, SV_FMT, SV_ARGS(it->id)); gcli_dict_add(dict, "NAME", 0, 0, SV_FMT, SV_ARGS(it->name)); @@ -78,9 +78,8 @@ gcli_print_release(enum gcli_output_flags const flags, } static void -gcli_print_releases_long(enum gcli_output_flags const flags, - gcli_release_list const *const list, - int const max) +gcli_print_releases_long(gcli_ctx *ctx, enum gcli_output_flags const flags, + gcli_release_list const *const list, int const max) { int n; @@ -92,17 +91,16 @@ gcli_print_releases_long(enum gcli_output_flags const flags, if (flags & OUTPUT_SORTED) { for (int i = 0; i < n; ++i) - gcli_print_release(flags, &list->releases[n-i-1]); + gcli_print_release(ctx, flags, &list->releases[n-i-1]); } else { for (int i = 0; i < n; ++i) - gcli_print_release(flags, &list->releases[i]); + gcli_print_release(ctx, flags, &list->releases[i]); } } static void -gcli_print_releases_short(enum gcli_output_flags const flags, - gcli_release_list const *const list, - int const max) +gcli_print_releases_short(gcli_ctx *ctx, enum gcli_output_flags const flags, + gcli_release_list const *const list, int const max) { size_t n; gcli_tbl table; @@ -119,7 +117,7 @@ gcli_print_releases_short(enum gcli_output_flags const flags, else n = max; - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not init table"); @@ -147,9 +145,8 @@ gcli_print_releases_short(enum gcli_output_flags const flags, } void -gcli_print_releases(enum gcli_output_flags const flags, - gcli_release_list const *const list, - int const max) +gcli_print_releases(gcli_ctx *ctx, enum gcli_output_flags const flags, + gcli_release_list const *const list, int const max) { if (list->releases_size == 0) { puts("No releases"); @@ -157,9 +154,9 @@ gcli_print_releases(enum gcli_output_flags const flags, } if (flags & OUTPUT_LONG) - gcli_print_releases_long(flags, list, max); + gcli_print_releases_long(ctx, flags, list, max); else - gcli_print_releases_short(flags, list, max); + gcli_print_releases_short(ctx, flags, list, max); } void @@ -189,9 +186,9 @@ gcli_free_releases(gcli_release_list *const list) } int -gcli_create_release(gcli_new_release const *release) +gcli_create_release(gcli_ctx *ctx, gcli_new_release const *release) { - return gcli_forge()->create_release(release); + return gcli_forge(ctx)->create_release(ctx, release); } void @@ -205,9 +202,8 @@ gcli_release_push_asset(gcli_new_release *const release, } int -gcli_delete_release(char const *const owner, - char const *const repo, - char const *const id) +gcli_delete_release(gcli_ctx *ctx, char const *const owner, + char const *const repo, char const *const id) { - return gcli_forge()->delete_release(owner, repo, id); + return gcli_forge(ctx)->delete_release(ctx, owner, repo, id); } diff --git a/src/repos.c b/src/repos.c index 8ca730dd..33670917 100644 --- a/src/repos.c +++ b/src/repos.c @@ -35,16 +35,16 @@ #include int -gcli_get_repos(char const *owner, int const max, gcli_repo_list *const out) +gcli_get_repos(gcli_ctx *ctx, char const *owner, int const max, + gcli_repo_list *const out) { - return gcli_forge()->get_repos(owner, max, out); + return gcli_forge(ctx)->get_repos(ctx, owner, max, out); } void -gcli_print_repos_table(enum gcli_output_flags const flags, - gcli_repo_list const *const list, - int const max) +gcli_print_repos_table(gcli_ctx *ctx, enum gcli_output_flags const flags, + gcli_repo_list const *const list, int const max) { size_t n; gcli_tbl table; @@ -67,7 +67,7 @@ gcli_print_repos_table(enum gcli_output_flags const flags, n = max; /* init table */ - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not init table"); @@ -93,11 +93,11 @@ gcli_print_repos_table(enum gcli_output_flags const flags, } void -gcli_repo_print(gcli_repo const *it) +gcli_repo_print(gcli_ctx *ctx, gcli_repo const *it) { gcli_dict dict; - dict = gcli_dict_begin(); + dict = gcli_dict_begin(ctx); gcli_dict_add(dict, "ID", 0, 0, "%d", it->id); gcli_dict_add(dict, "FULL NAME", 0, 0, SV_FMT, SV_ARGS(it->full_name)); gcli_dict_add(dict, "NAME", 0, 0, SV_FMT, SV_ARGS(it->name)); @@ -134,19 +134,20 @@ gcli_repos_free(gcli_repo_list *const list) } int -gcli_get_own_repos(int const max, gcli_repo_list *const out) +gcli_get_own_repos(gcli_ctx *ctx, int const max, gcli_repo_list *const out) { - return gcli_forge()->get_own_repos(max, out); + return gcli_forge(ctx)->get_own_repos(ctx, max, out); } int -gcli_repo_delete(char const *owner, char const *repo) +gcli_repo_delete(gcli_ctx *ctx, char const *owner, char const *repo) { - return gcli_forge()->repo_delete(owner, repo); + return gcli_forge(ctx)->repo_delete(ctx, owner, repo); } int -gcli_repo_create(gcli_repo_create_options const *options, gcli_repo *out) +gcli_repo_create(gcli_ctx *ctx, gcli_repo_create_options const *options, + gcli_repo *out) { - return gcli_forge()->repo_create(options, out); + return gcli_forge(ctx)->repo_create(ctx, options, out); } diff --git a/src/review.c b/src/review.c index 7cbdc874..b977762b 100644 --- a/src/review.c +++ b/src/review.c @@ -40,19 +40,20 @@ #include void -gcli_review_print_review_table(gcli_pr_review_list const *const list) +gcli_review_print_review_table(gcli_ctx *ctx, + gcli_pr_review_list const *const list) { for (size_t i = 0; i < list->reviews_size; ++i) { if (list->reviews[i].state) { printf(" %s%s%s - %s - %s%s%s\n", - gcli_setbold(), list->reviews[i].author, gcli_resetbold(), + gcli_setbold(ctx), list->reviews[i].author, gcli_resetbold(ctx), list->reviews[i].date, - gcli_state_colour_str(list->reviews[i].state), + gcli_state_colour_str(ctx, list->reviews[i].state), list->reviews[i].state, - gcli_resetcolour()); + gcli_resetcolour(ctx)); } else { printf(" %s%s%s - %s\n", - gcli_setbold(), list->reviews[i].author, gcli_resetbold(), + gcli_setbold(ctx), list->reviews[i].author, gcli_resetbold(ctx), list->reviews[i].date); } @@ -121,8 +122,8 @@ gcli_review_comments_free(gcli_pr_review_comment *it, size_t const size) } int -gcli_review_get_reviews(char const *owner, char const *repo, +gcli_review_get_reviews(gcli_ctx *ctx, char const *owner, char const *repo, int const pr, gcli_pr_review_list *const out) { - return gcli_forge()->get_reviews(owner, repo, pr, out); + return gcli_forge(ctx)->get_reviews(ctx, owner, repo, pr, out); } diff --git a/src/sshkeys.c b/src/sshkeys.c index 9ae77473..e535678e 100644 --- a/src/sshkeys.c +++ b/src/sshkeys.c @@ -37,13 +37,13 @@ #include int -gcli_sshkeys_get_keys(gcli_sshkey_list *out) +gcli_sshkeys_get_keys(gcli_ctx *ctx, gcli_sshkey_list *out) { - return gcli_forge()->get_sshkeys(out); + return gcli_forge(ctx)->get_sshkeys(ctx, out); } void -gcli_sshkeys_print_keys(gcli_sshkey_list const *list) +gcli_sshkeys_print_keys(gcli_ctx *ctx, gcli_sshkey_list const *list) { gcli_tbl *tbl; gcli_tblcoldef cols[] = { @@ -57,7 +57,7 @@ gcli_sshkeys_print_keys(gcli_sshkey_list const *list) return; } - tbl = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + tbl = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); for (size_t i = 0; i < list->keys_size; ++i) { gcli_tbl_add_row(tbl, list->keys[i].id, list->keys[i].created_at, list->keys[i].title); @@ -82,9 +82,8 @@ gcli_sshkeys_free_keys(gcli_sshkey_list *list) } int -gcli_sshkeys_add_key(char const *title, - char const *public_key_path, - gcli_sshkey *out) +gcli_sshkeys_add_key(gcli_ctx *ctx, char const *title, + char const *public_key_path, gcli_sshkey *out) { int rc; char *buffer; @@ -93,14 +92,14 @@ gcli_sshkeys_add_key(char const *title, if (rc < 0) return rc; - rc = gcli_forge()->add_sshkey(title, buffer, out); + rc = gcli_forge(ctx)->add_sshkey(ctx, title, buffer, out); free(buffer); return rc; } int -gcli_sshkeys_delete_key(int id) +gcli_sshkeys_delete_key(gcli_ctx *ctx, int id) { - return gcli_forge()->delete_sshkey(id); + return gcli_forge(ctx)->delete_sshkey(ctx, id); } diff --git a/src/status.c b/src/status.c index 5e4ce487..fef01cb7 100644 --- a/src/status.c +++ b/src/status.c @@ -31,12 +31,12 @@ #include void -gcli_status(int const count) +gcli_status(gcli_ctx *ctx, int const count) { gcli_notification *notifications = NULL; int notifications_size = 0; - notifications_size = gcli_get_notifications(¬ifications, count); + notifications_size = gcli_get_notifications(ctx, ¬ifications, count); if (notifications_size < 0) errx(1, "error: failed to get notifications"); @@ -53,9 +53,10 @@ gcli_status(int const count) } int -gcli_get_notifications(gcli_notification **const out, int const count) +gcli_get_notifications(gcli_ctx *ctx, gcli_notification **const out, + int const count) { - return gcli_forge()->get_notifications(out, count); + return gcli_forge(ctx)->get_notifications(ctx, out, count); } void @@ -90,7 +91,7 @@ gcli_print_notifications(gcli_notification const *const notifications, } int -gcli_notification_mark_as_read(char const *id) +gcli_notification_mark_as_read(gcli_ctx *ctx, char const *id) { - return gcli_forge()->notification_mark_as_read(id); + return gcli_forge(ctx)->notification_mark_as_read(ctx, id); } diff --git a/src/table.c b/src/table.c index 2c3b49b4..a274c3ce 100644 --- a/src/table.c +++ b/src/table.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -43,6 +44,7 @@ struct gcli_tblrow; /* Internal state of a table printer. We return a handle to it in * gcli_table_init. */ struct gcli_tbl { + gcli_ctx *ctx; /* pointer to the gcli context */ gcli_tblcoldef const *cols; /* user provided column definitons */ int *col_widths; /* minimum width of the columns */ size_t cols_size; /* size of above arrays */ @@ -74,7 +76,8 @@ table_pushrow(struct gcli_tbl *const table, struct gcli_tblrow row) /** Initialize the internal state structure of the table printer. */ gcli_tbl -gcli_tbl_begin(gcli_tblcoldef const *const cols, size_t const cols_size) +gcli_tbl_begin(gcli_ctx *ctx, gcli_tblcoldef const *const cols, + size_t const cols_size) { struct gcli_tbl *tbl; @@ -83,6 +86,8 @@ gcli_tbl_begin(gcli_tblcoldef const *const cols, size_t const cols_size) if (!tbl) return NULL; + tbl->ctx = ctx; + /* Reserve memory for the column sizes */ tbl->col_widths = calloc(sizeof(*tbl->col_widths), cols_size); if (!tbl->col_widths) { @@ -127,12 +132,12 @@ tablerow_add_cell(struct gcli_tbl *const table, int code = va_arg(*vp, int); /* don't free that! it's allocated and free'ed inside colour.c */ - row->cells[col].colour = gcli_setcolour(code); + row->cells[col].colour = gcli_setcolour(table->ctx, code); } else if (table->cols[col].flags & GCLI_TBLCOL_256COLOUR) { uint64_t hexcode = va_arg(*vp, uint64_t); /* see comment above */ - row->cells[col].colour = gcli_setcolour256(hexcode); + row->cells[col].colour = gcli_setcolour256(table->ctx, hexcode); } @@ -245,14 +250,15 @@ dump_row(struct gcli_tbl const *const table, size_t const i) /* State colour */ if (table->cols[col].flags & GCLI_TBLCOL_STATECOLOURED) - printf("%s", gcli_state_colour_str(row->cells[col].text)); + printf("%s", gcli_state_colour_str( + table->ctx, row->cells[col].text)); else if (table->cols[col].flags & (GCLI_TBLCOL_COLOUREXPL|GCLI_TBLCOL_256COLOUR)) printf("%s", row->cells[col].colour); /* Bold */ if (table->cols[col].flags & GCLI_TBLCOL_BOLD) - printf("%s", gcli_setbold()); + printf("%s", gcli_setbold(table->ctx)); /* Print cell if it is not NULL, otherwise indicate it by * printing */ @@ -263,11 +269,11 @@ dump_row(struct gcli_tbl const *const table, size_t const i) (GCLI_TBLCOL_STATECOLOURED |GCLI_TBLCOL_COLOUREXPL |GCLI_TBLCOL_256COLOUR)) - printf("%s", gcli_resetcolour()); + printf("%s", gcli_resetcolour(table->ctx)); /* Stop printing in bold */ if (table->cols[col].flags & GCLI_TBLCOL_BOLD) - printf("%s", gcli_resetbold()); + printf("%s", gcli_resetbold(table->ctx)); /* If not last column, print padding of 2 spaces */ if ((col + 1) < table->cols_size) { @@ -348,13 +354,17 @@ struct gcli_dict { size_t entries_size; size_t max_key_len; + + gcli_ctx *ctx; }; /* Create a new long list printer and return a handle to it */ gcli_dict -gcli_dict_begin(void) +gcli_dict_begin(gcli_ctx *ctx) { - return calloc(sizeof(struct gcli_dict), 1); + struct gcli_dict *d = calloc(sizeof(struct gcli_dict), 1); + d->ctx = ctx; + return d; } static int @@ -479,26 +489,32 @@ gcli_dict_end(gcli_dict _list) printf("%s : ", list->entries[i].key); if (flags & GCLI_TBLCOL_BOLD) - printf("%s", gcli_setbold()); + printf("%s", gcli_setbold(list->ctx)); if (flags & GCLI_TBLCOL_COLOUREXPL) - printf("%s", gcli_setcolour(list->entries[i].colour_args)); + printf("%s", gcli_setcolour( + list->ctx, + list->entries[i].colour_args)); if (flags & GCLI_TBLCOL_STATECOLOURED) - printf("%s", gcli_state_colour_str(list->entries[i].value)); + printf("%s", gcli_state_colour_str( + list->ctx, + list->entries[i].value)); if (flags & GCLI_TBLCOL_256COLOUR) - printf("%s", gcli_setcolour256(list->entries[i].colour_args)); + printf("%s", gcli_setcolour256( + list->ctx, + list->entries[i].colour_args)); puts(list->entries[i].value); if (flags & (GCLI_TBLCOL_COLOUREXPL |GCLI_TBLCOL_STATECOLOURED |GCLI_TBLCOL_256COLOUR)) - printf("%s", gcli_resetcolour()); + printf("%s", gcli_resetcolour(list->ctx)); if (flags & GCLI_TBLCOL_BOLD) - printf("%s", gcli_resetbold()); + printf("%s", gcli_resetbold(list->ctx)); } gcli_dict_free(list); From 23242688fbed9832048e1747f2d283f3c251e74d Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 15 Aug 2023 18:54:31 +0200 Subject: [PATCH 103/236] Fix incorrect return type of gcli gists --- include/gcli/github/gists.h | 4 ++-- src/github/gists.c | 29 +++++++++++++++++------------ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/include/gcli/github/gists.h b/include/gcli/github/gists.h index 3cbf731d..3fd08cc5 100644 --- a/include/gcli/github/gists.h +++ b/include/gcli/github/gists.h @@ -82,9 +82,9 @@ gcli_gist *gcli_get_gist(gcli_ctx *ctx, char const *gist_id); void gcli_print_gists(gcli_ctx *ctx, enum gcli_output_flags flags, gcli_gist_list const *list, int max); -void gcli_create_gist(gcli_ctx *ctx, gcli_new_gist); +int gcli_create_gist(gcli_ctx *ctx, gcli_new_gist); -void gcli_delete_gist(gcli_ctx *ctx, char const *gist_id, bool always_yes); +int gcli_delete_gist(gcli_ctx *ctx, char const *gist_id, bool always_yes); void gcli_gists_free(gcli_gist_list *list); diff --git a/src/github/gists.c b/src/github/gists.c index a09cdd50..890c8904 100644 --- a/src/github/gists.c +++ b/src/github/gists.c @@ -277,14 +277,15 @@ read_file(FILE *f, char **out) return size; } -void +int gcli_create_gist(gcli_ctx *ctx, gcli_new_gist opts) { - char *url = NULL; - char *post_data = NULL; - gcli_fetch_buffer fetch_buffer = {0}; - sn_sv read_buffer = {0}; - sn_sv content = {0}; + char *url = NULL; + char *post_data = NULL; + gcli_fetch_buffer fetch_buffer = {0}; + sn_sv read_buffer = {0}; + sn_sv content = {0}; + int rc = 0; read_buffer.length = read_file(opts.file, &read_buffer.data); content = gcli_json_escape(read_buffer); @@ -316,20 +317,22 @@ gcli_create_gist(gcli_ctx *ctx, gcli_new_gist opts) opts.file_name, SV_ARGS(content)); - gcli_fetch_with_method(ctx, "POST", url, post_data, NULL, &fetch_buffer); - gcli_print_html_url(ctx, fetch_buffer); + rc = gcli_fetch_with_method(ctx, "POST", url, post_data, NULL, &fetch_buffer); free(read_buffer.data); free(fetch_buffer.data); free(url); free(post_data); + + return rc; } -void +int gcli_delete_gist(gcli_ctx *ctx, char const *gist_id, bool const always_yes) { - char *url = NULL; - gcli_fetch_buffer buffer = {0}; + char *url = NULL; + gcli_fetch_buffer buffer = {0}; + int rc = 0; url = sn_asprintf( "%s/gists/%s", @@ -339,10 +342,12 @@ gcli_delete_gist(gcli_ctx *ctx, char const *gist_id, bool const always_yes) if (!always_yes && !sn_yesno("Are you sure you want to delete this gist?")) errx(1, "Aborted by user"); - gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, &buffer); + rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, &buffer); free(buffer.data); free(url); + + return rc; } void From 106e6b93ec470789c583c62b63bbb7db7ee4d645 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 15 Aug 2023 18:55:21 +0200 Subject: [PATCH 104/236] Fix missing ctx in parser function pointer in fetchlist --- include/gcli/curl.h | 3 ++- src/curl.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/gcli/curl.h b/include/gcli/curl.h index 15058a69..4c5a19a6 100644 --- a/include/gcli/curl.h +++ b/include/gcli/curl.h @@ -43,7 +43,8 @@ #include #include -typedef void (*parsefn)(json_stream *stream, void *list, size_t *listsize); +typedef void (*parsefn)(gcli_ctx *, json_stream *stream, void *list, + size_t *listsize); typedef void (*filterfn)(void *list, size_t *listsize, void const *userdata); typedef struct gcli_fetch_buffer gcli_fetch_buffer; typedef struct gcli_fetch_list_ctx gcli_fetch_list_ctx; diff --git a/src/curl.c b/src/curl.c index 144ff146..16f12c2e 100644 --- a/src/curl.c +++ b/src/curl.c @@ -605,7 +605,7 @@ gcli_fetch_list(gcli_ctx *ctx, char *url, gcli_fetch_list_ctx *fl) struct json_stream stream = {0}; json_open_buffer(&stream, buffer.data, buffer.length); - fl->parse(&stream, fl->listp, fl->sizep); + fl->parse(ctx, &stream, fl->listp, fl->sizep); if (fl->filter) fl->filter(fl->listp, fl->sizep, fl->userdata); From 8c9c8e32bd2d49feda5d562b05a46a4af4947db5 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 15 Aug 2023 18:55:42 +0200 Subject: [PATCH 105/236] Update cmd code to work with new ctx --- configure.ac | 2 +- include/gcli/cmd.h | 4 ++- src/cmd.c | 6 ++--- src/cmd/api.c | 8 +++--- src/cmd/ci.c | 10 +++---- src/cmd/comment.c | 2 +- src/cmd/config.c | 8 +++--- src/cmd/forks.c | 20 +++++++------- src/cmd/gcli.c | 8 +++--- src/cmd/gists.c | 25 ++++++++++-------- src/cmd/issues.c | 28 ++++++++++---------- src/cmd/labels.c | 10 +++---- src/cmd/milestones.c | 35 +++++++++++++++--------- src/cmd/pipelines.c | 12 ++++----- src/cmd/pulls.c | 63 ++++++++++++++++++++++++-------------------- src/cmd/releases.c | 15 ++++++----- src/cmd/repos.c | 10 +++---- src/cmd/snippets.c | 8 +++--- src/cmd/status.c | 4 +-- src/config.c | 4 +++ 20 files changed, 155 insertions(+), 127 deletions(-) diff --git a/configure.ac b/configure.ac index b0675e63..42bd0350 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([gcli],[1.3.0-devel],[nsonack@herrhotzenplotz.de],[gcli],[https://gitlab.com/herrhotzenplotz/gcli/]) +AC_INIT([gcli],[2.0.0-devel],[nsonack@herrhotzenplotz.de],[gcli],[https://gitlab.com/herrhotzenplotz/gcli/]) AM_INIT_AUTOMAKE([1.0 foreign subdir-objects dist-bzip2 dist-xz -Wall]) dnl Release Date. diff --git a/include/gcli/cmd.h b/include/gcli/cmd.h index 15e2e342..095624ee 100644 --- a/include/gcli/cmd.h +++ b/include/gcli/cmd.h @@ -38,6 +38,8 @@ #include +extern gcli_ctx *g_clictx; + static inline char * shift(int *argc, char ***argv) { @@ -50,7 +52,7 @@ shift(int *argc, char ***argv) void version(void); void copyright(void); -void check_owner_and_repo(gcli_ctx *ctx, const char **owner, const char **repo); +void check_owner_and_repo(const char **owner, const char **repo); void parse_labels_options( int *argc, char ***argv, diff --git a/src/cmd.c b/src/cmd.c index 25e5e287..69b9ff17 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -60,14 +60,14 @@ version(void) } void -check_owner_and_repo(gcli_ctx *ctx, const char **owner, const char **repo) +check_owner_and_repo(const char **owner, const char **repo) { /* If no remote was specified, try to autodetect */ if ((*owner == NULL) != (*repo == NULL)) errx(1, "error: missing either explicit owner or repo"); if (*owner == NULL) - gcli_config_get_repo(ctx, owner, repo); + gcli_config_get_repo(g_clictx, owner, repo); } /* Parses (and updates) the given argument list into two seperate lists: @@ -132,6 +132,6 @@ delete_repo(bool always_yes, const char *owner, const char *repo) if (!delete) errx(1, "Operation aborted"); - if (gcli_repo_delete(owner, repo) < 0) + if (gcli_repo_delete(g_clictx, owner, repo) < 0) errx(1, "error: failed to delete repo"); } diff --git a/src/cmd/api.c b/src/cmd/api.c index f6a250a1..11d12057 100644 --- a/src/cmd/api.c +++ b/src/cmd/api.c @@ -64,7 +64,7 @@ fetch_all(char *_url) do { gcli_fetch_buffer buffer = {0}; - if (gcli_fetch(url, &next_url, &buffer) < 0) + if (gcli_fetch(g_clictx, url, &next_url, &buffer) < 0) errx(1, "error: failed to fetch data"); fwrite(buffer.data, buffer.length, 1, stdout); @@ -112,13 +112,13 @@ subcommand_api(int argc, char *argv[]) } if (path[0] == '/') - url = sn_asprintf("%s%s", gcli_get_apibase(), path); + url = sn_asprintf("%s%s", gcli_get_apibase(g_clictx), path); else - url = sn_asprintf("%s/%s", gcli_get_apibase(), path); + url = sn_asprintf("%s/%s", gcli_get_apibase(g_clictx), path); if (do_all) fetch_all(url); - else if (gcli_curl(stdout, url, "application/json") < 0) + else if (gcli_curl(g_clictx, stdout, url, "application/json") < 0) errx(1, "error: failed to fetch data"); free(url); diff --git a/src/cmd/ci.c b/src/cmd/ci.c index a15a858a..72843bd4 100644 --- a/src/cmd/ci.c +++ b/src/cmd/ci.c @@ -58,10 +58,10 @@ usage(void) int subcommand_ci(int argc, char *argv[]) { - int ch = 0; + int ch = 0; char const *owner = NULL, *repo = NULL; - char const *ref = NULL; - int count = -1; /* fetch all checks by default */ + char const *ref = NULL; + int count = -1; /* fetch all checks by default */ /* Parse options */ struct option const options[] = { @@ -116,11 +116,11 @@ subcommand_ci(int argc, char *argv[]) /* Make sure we are actually talking about a github remote because * we might be incorrectly inferring it */ - if (gcli_config_get_forge_type() != GCLI_FORGE_GITHUB) + if (gcli_config_get_forge_type(g_clictx) != GCLI_FORGE_GITHUB) errx(1, "error: The ci subcommand only works for GitHub. " "Use gcli -t github ... to force a GitHub remote."); - github_checks(owner, repo, ref, count); + github_checks(g_clictx, owner, repo, ref, count); return EXIT_SUCCESS; } diff --git a/src/cmd/comment.c b/src/cmd/comment.c index 7f6d1a47..bcd04b76 100644 --- a/src/cmd/comment.c +++ b/src/cmd/comment.c @@ -121,7 +121,7 @@ subcommand_comment(int argc, char *argv[]) return EXIT_FAILURE; } - rc = gcli_comment_submit((gcli_submit_comment_opts) { + rc = gcli_comment_submit(g_clictx, (gcli_submit_comment_opts) { .owner = owner, .repo = repo, .target_type = target_type, diff --git a/src/cmd/config.c b/src/cmd/config.c index 71d7f464..ea5ff403 100644 --- a/src/cmd/config.c +++ b/src/cmd/config.c @@ -60,12 +60,12 @@ list_sshkeys(void) { gcli_sshkey_list list = {0}; - if (gcli_sshkeys_get_keys(&list) < 0) { + if (gcli_sshkeys_get_keys(g_clictx, &list) < 0) { fprintf(stderr, "error: could not get list of SSH keys\n"); return EXIT_FAILURE; } - gcli_sshkeys_print_keys(&list); + gcli_sshkeys_print_keys(g_clictx, &list); gcli_sshkeys_free_keys(&list); return 0; @@ -116,7 +116,7 @@ add_sshkey(int argc, char *argv[]) return EXIT_FAILURE; } - if (gcli_sshkeys_add_key(title, keypath, NULL) < 0) + if (gcli_sshkeys_add_key(g_clictx, title, keypath, NULL) < 0) return EXIT_FAILURE; return EXIT_SUCCESS; @@ -145,7 +145,7 @@ delete_sshkey(int argc, char *argv[]) return EXIT_FAILURE; } - if (gcli_sshkeys_delete_key(id) < 0) + if (gcli_sshkeys_delete_key(g_clictx, id) < 0) return EXIT_FAILURE; return EXIT_SUCCESS; diff --git a/src/cmd/forks.c b/src/cmd/forks.c index 8ea5825b..7fcd30a6 100644 --- a/src/cmd/forks.c +++ b/src/cmd/forks.c @@ -110,7 +110,7 @@ subcommand_forks_create(int argc, char *argv[]) check_owner_and_repo(&owner, &repo); - if (gcli_fork_create(owner, repo, in) < 0) + if (gcli_fork_create(g_clictx, owner, repo, in) < 0) errx(1, "error: failed to fork repository"); if (!always_yes) { @@ -119,7 +119,7 @@ subcommand_forks_create(int argc, char *argv[]) } if (!in) - in = sn_sv_to_cstr(gcli_config_get_account()); + in = sn_sv_to_cstr(gcli_config_get_account(g_clictx)); gcli_gitconfig_add_fork_remote(in, repo); @@ -129,12 +129,12 @@ subcommand_forks_create(int argc, char *argv[]) int subcommand_forks(int argc, char *argv[]) { - gcli_fork_list forks = {0}; - char const *owner = NULL, *repo = NULL; - int ch = 0; - int count = 30; - bool always_yes = false; - enum gcli_output_flags flags = 0; + gcli_fork_list forks = {0}; + char const *owner = NULL, *repo = NULL; + int ch = 0; + int count = 30; + bool always_yes = false; + enum gcli_output_flags flags = 0; /* detect whether we wanna create a fork */ if (argc > 1 && (strcmp(argv[1], "create") == 0)) { @@ -203,10 +203,10 @@ subcommand_forks(int argc, char *argv[]) check_owner_and_repo(&owner, &repo); if (argc == 0) { - if (gcli_get_forks(owner, repo, count, &forks) < 0) + if (gcli_get_forks(g_clictx, owner, repo, count, &forks) < 0) errx(1, "error: could not get forks"); - gcli_print_forks(flags, &forks, count); + gcli_print_forks(g_clictx, flags, &forks, count); gcli_forks_free(&forks); return EXIT_SUCCESS; diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index 0e8148ee..9b53ac34 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -136,18 +136,20 @@ usage(void) copyright(); } +/** The CMD global gcli context */ +gcli_ctx *g_clictx = NULL; + int main(int argc, char *argv[]) { - gcli_ctx *ctx; char const *errmsg; - errmsg = gcli_init(&ctx); + errmsg = gcli_init(&g_clictx); if (errmsg) errx(1, "error: %s", errmsg); /* Parse first arguments */ - if (gcli_config_parse_args(ctx, &argc, &argv)) { + if (gcli_config_parse_args(g_clictx, &argc, &argv)) { usage(); return EXIT_FAILURE; } diff --git a/src/cmd/gists.c b/src/cmd/gists.c index 895f1629..32fc4e38 100644 --- a/src/cmd/gists.c +++ b/src/cmd/gists.c @@ -66,12 +66,12 @@ subcommand_gist_get(int argc, char *argv[]) { shift(&argc, &argv); /* Discard the *get* */ - char const *gist_id = shift(&argc, &argv); - char const *file_name = shift(&argc, &argv); - gcli_gist *gist = NULL; - gcli_gist_file *file = NULL; + char const *gist_id = shift(&argc, &argv); + char const *file_name = shift(&argc, &argv); + gcli_gist *gist = NULL; + gcli_gist_file *file = NULL; - gist = gcli_get_gist(gist_id); + gist = gcli_get_gist(g_clictx, gist_id); for (size_t f = 0; f < gist->files_size; ++f) { if (sn_sv_eq_to(gist->files[f].filename, file_name)) { @@ -88,7 +88,7 @@ subcommand_gist_get(int argc, char *argv[]) if (isatty(STDOUT_FILENO) && (file->size >= 4 * 1024 * 1024)) errx(1, "File is bigger than 4 MiB, refusing to print to stdout."); - if (gcli_curl(stdout, file->url.data, file->type.data) < 0) + if (gcli_curl(g_clictx, stdout, file->url.data, file->type.data) < 0) errx(1, "error: failed to fetch gist"); return EXIT_SUCCESS; @@ -149,7 +149,8 @@ subcommand_gist_create(int argc, char *argv[]) if (!opts.gist_description) opts.gist_description = "gcli paste"; - gcli_create_gist(opts); + if (gcli_create_gist(g_clictx, opts) < 0) + errx(1, "error: failed to create gist"); return EXIT_SUCCESS; } @@ -185,7 +186,7 @@ subcommand_gist_delete(int argc, char *argv[]) argv += optind; gist_id = shift(&argc, &argv); - gcli_delete_gist(gist_id, always_yes); + gcli_delete_gist(g_clictx, gist_id, always_yes); return EXIT_SUCCESS; } @@ -209,7 +210,7 @@ subcommand_gists(int argc, char *argv[]) enum gcli_output_flags flags = 0; /* Make sure we are looking at a GitHub forge */ - if (gcli_config_get_forge_type() != GCLI_FORGE_GITHUB) { + if (gcli_config_get_forge_type(g_clictx) != GCLI_FORGE_GITHUB) { errx(1, "error: The gists subcommand only works for Github " "forges. Please use either -a or -t to force using a " "Github account."); @@ -270,8 +271,10 @@ subcommand_gists(int argc, char *argv[]) argc -= optind; argv += optind; - gcli_get_gists(user, count, &gists); - gcli_print_gists(flags, &gists, count); + if (gcli_get_gists(g_clictx, user, count, &gists) < 0) + errx(1, "error: failed to get gists"); + + gcli_print_gists(g_clictx, flags, &gists, count); gcli_gists_free(&gists); return EXIT_SUCCESS; diff --git a/src/cmd/issues.c b/src/cmd/issues.c index 22d6f5dd..af0fdb07 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -127,7 +127,7 @@ subcommand_issue_create(int argc, char *argv[]) opts.title = SV(argv[0]); - if (gcli_issue_submit(opts) < 0) + if (gcli_issue_submit(g_clictx, opts) < 0) errx(1, "failed to submit issue"); return EXIT_SUCCESS; @@ -241,10 +241,10 @@ subcommand_issues(int argc, char *argv[]) /* No issue number was given, so list all open issues */ if (issue_id < 0) { - if (gcli_get_issues(owner, repo, &details, n, &list) < 0) + if (gcli_get_issues(g_clictx, owner, repo, &details, n, &list) < 0) errx(1, "error: could not get issues"); - gcli_print_issues_table(flags, &list, n); + gcli_print_issues_table(g_clictx, flags, &list, n); gcli_issues_free(&list); return EXIT_SUCCESS; @@ -269,7 +269,7 @@ ensure_issue(char const *const owner, char const *const repo, if (*have_fetched_issue) return; - if (gcli_get_issue(owner, repo, issue_id, issue) < 0) + if (gcli_get_issue(g_clictx, owner, repo, issue_id, issue) < 0) errx(1, "error: failed to retrieve issue data"); *have_fetched_issue = 1; @@ -298,7 +298,7 @@ handle_issue_labels_action(int *argc, char ***argv, /* actually go about deleting and adding the labels */ if (add_labels_size) { - rc = gcli_issue_add_labels(owner, repo, issue_id, + rc = gcli_issue_add_labels(g_clictx, owner, repo, issue_id, add_labels, add_labels_size); if (rc < 0) @@ -306,7 +306,7 @@ handle_issue_labels_action(int *argc, char ***argv, } if (remove_labels_size) { - rc = gcli_issue_remove_labels(owner, repo, issue_id, + rc = gcli_issue_remove_labels(g_clictx, owner, repo, issue_id, remove_labels, remove_labels_size); if (rc < 0) @@ -342,7 +342,7 @@ handle_issue_milestone_action(int *argc, char ***argv, /* Check if the milestone_str is -d indicating that we should * clear the milestone */ if (strcmp(milestone_str, "-d") == 0) { - rc = gcli_issue_clear_milestone(owner, repo, issue_id); + rc = gcli_issue_clear_milestone(g_clictx, owner, repo, issue_id); if (rc < 0) errx(1, "error: could not clear milestone of issue #%d", issue_id); return; @@ -359,7 +359,7 @@ handle_issue_milestone_action(int *argc, char ***argv, } /* Pass it to the dispatch */ - if (gcli_issue_set_milestone(owner, repo, issue_id, milestone) < 0) + if (gcli_issue_set_milestone(g_clictx, owner, repo, issue_id, milestone) < 0) errx(1, "error: could not assign milestone"); } @@ -387,7 +387,7 @@ handle_issues_actions(int argc, char *argv[], /* Make sure we have fetched the issue data */ ensure_issue(owner, repo, issue_id, &have_fetched_issue, &issue); - gcli_issue_print_summary(&issue); + gcli_issue_print_summary(g_clictx, &issue); puts("\nORIGINAL POST\n"); gcli_issue_print_op(&issue); @@ -395,7 +395,7 @@ handle_issues_actions(int argc, char *argv[], } else if (strcmp("comments", operation) == 0 || strcmp("notes", operation) == 0) { /* Doesn't require fetching the issue data */ - gcli_issue_comments(owner, repo, issue_id); + gcli_issue_comments(g_clictx, owner, repo, issue_id); } else if (strcmp("op", operation) == 0) { /* Make sure we have fetched the issue data */ @@ -407,22 +407,22 @@ handle_issues_actions(int argc, char *argv[], /* Make sure we have fetched the issue data */ ensure_issue(owner, repo, issue_id, &have_fetched_issue, &issue); - gcli_issue_print_summary(&issue); + gcli_issue_print_summary(g_clictx, &issue); } else if (strcmp("close", operation) == 0) { - if (gcli_issue_close(owner, repo, issue_id) < 0) + if (gcli_issue_close(g_clictx, owner, repo, issue_id) < 0) errx(1, "failed to close issue"); } else if (strcmp("reopen", operation) == 0) { - if (gcli_issue_reopen(owner, repo, issue_id) < 0) + if (gcli_issue_reopen(g_clictx, owner, repo, issue_id) < 0) errx(1, "failed to reopen issue"); } else if (strcmp("assign", operation) == 0) { char const *assignee = shift(&argc, &argv); - if (gcli_issue_assign(owner, repo, issue_id, assignee) < 0) + if (gcli_issue_assign(g_clictx, owner, repo, issue_id, assignee) < 0) errx(1, "failed to assign issue"); } else if (strcmp("labels", operation) == 0) { diff --git a/src/cmd/labels.c b/src/cmd/labels.c index 6c60331a..142f0c3b 100644 --- a/src/cmd/labels.c +++ b/src/cmd/labels.c @@ -94,7 +94,7 @@ subcommand_labels_delete(int argc, char *argv[]) return EXIT_FAILURE; } - rc = gcli_delete_label(owner, repo, argv[0]); + rc = gcli_delete_label(g_clictx, owner, repo, argv[0]); if (rc < 0) { fprintf(stderr, "error: couldn't delete label\n"); return EXIT_FAILURE; @@ -164,14 +164,14 @@ subcommand_labels_create(int argc, char *argv[]) return EXIT_FAILURE; } - if (gcli_create_label(owner, repo, &label) < 0) { + if (gcli_create_label(g_clictx, owner, repo, &label) < 0) { fprintf(stderr, "error: could not create label\n"); return EXIT_FAILURE; } /* only if we are not quieted */ if (!sn_quiet()) - gcli_print_labels(&labels, 1); + gcli_print_labels(g_clictx, &labels, 1); gcli_free_label(&label); @@ -246,10 +246,10 @@ subcommand_labels(int argc, char *argv[]) check_owner_and_repo(&owner, &repo); - if (gcli_get_labels(owner, repo, count, &labels) < 0) + if (gcli_get_labels(g_clictx, owner, repo, count, &labels) < 0) errx(1, "error: could not fetch list of labels"); - gcli_print_labels(&labels, count); + gcli_print_labels(g_clictx, &labels, count); gcli_free_labels(&labels); return EXIT_SUCCESS; diff --git a/src/cmd/milestones.c b/src/cmd/milestones.c index 6b20cd10..2993565c 100644 --- a/src/cmd/milestones.c +++ b/src/cmd/milestones.c @@ -125,7 +125,7 @@ subcommand_milestone_create(int argc, char *argv[]) errx(1, "error: missing milestone title"); /* actually create the milestone */ - if (gcli_create_milestone(&args) < 0) + if (gcli_create_milestone(g_clictx, &args) < 0) errx(1, "error: could not create milestone"); return 0; @@ -203,11 +203,11 @@ subcommand_milestones(int argc, char *argv[]) if (milestone_id < 0) { gcli_milestone_list list = {0}; - rc = gcli_get_milestones(owner, repo, max, &list); + rc = gcli_get_milestones(g_clictx, owner, repo, max, &list); if (rc < 0) errx(1, "error: cannot get list of milestones"); - gcli_print_milestones(&list, max); + gcli_print_milestones(g_clictx, &list, max); gcli_free_milestones(&list); return 0; @@ -228,7 +228,7 @@ ensure_milestone(char const *const owner, if (*fetched_milestone) return; - rc = gcli_get_milestone(owner, repo, milestone_id, milestone); + rc = gcli_get_milestone(g_clictx, owner, repo, milestone_id, milestone); if (rc < 0) errx(1, "error: could not get milestone %d", milestone_id); @@ -259,30 +259,36 @@ handle_milestone_actions(int argc, char *argv[], /* Dispatch */ if (strcmp(action, "all") == 0) { + int rc = 0; gcli_issue_list issues = {0}; ensure_milestone(owner, repo, milestone_id, &fetched_milestone, &milestone); - gcli_print_milestone(&milestone); - if (gcli_milestone_get_issues(owner, repo, milestone_id, &issues) < 0) + gcli_print_milestone(g_clictx, &milestone); + rc = gcli_milestone_get_issues(g_clictx, owner, repo, milestone_id, + &issues); + + if (rc < 0) errx(1, "error: failed to fetch issues"); printf("\nISSUES:\n"); - gcli_print_issues_table(0, &issues, -1); + gcli_print_issues_table(g_clictx, 0, &issues, -1); gcli_issues_free(&issues); } else if (strcmp(action, "issues") == 0) { - + int rc = 0; gcli_issue_list issues = {0}; /* Fetch list of issues associated with milestone */ - if (gcli_milestone_get_issues(owner, repo, milestone_id, &issues) < 0) + rc = gcli_milestone_get_issues(g_clictx, owner, repo, milestone_id, + &issues); + if (rc < 0) errx(1, "error: failed to fetch issues"); /* Print them as a table */ - gcli_print_issues_table(0, &issues, -1); + gcli_print_issues_table(g_clictx, 0, &issues, -1); /* Cleanup */ gcli_issues_free(&issues); @@ -294,16 +300,17 @@ handle_milestone_actions(int argc, char *argv[], &fetched_milestone, &milestone); /* Print meta */ - gcli_print_milestone(&milestone); + gcli_print_milestone(g_clictx, &milestone); } else if (strcmp(action, "delete") == 0) { /* Delete the milestone */ - if (gcli_delete_milestone(owner, repo, milestone_id) < 0) + if (gcli_delete_milestone(g_clictx, owner, repo, milestone_id) < 0) errx(1, "error: could not delete milestone"); } else if (strcmp(action, "set-duedate") == 0) { char *new_date = NULL; + int rc = 0; /* grab the the date that the user provided */ if (!argc) @@ -312,7 +319,9 @@ handle_milestone_actions(int argc, char *argv[], new_date = shift(&argc, &argv); /* Do it! */ - if (gcli_milestone_set_duedate(owner, repo, milestone_id, new_date) < 0) + rc = gcli_milestone_set_duedate(g_clictx, owner, repo, milestone_id, + new_date); + if (rc < 0) errx(1, "error: could not update milestone due date"); } else { diff --git a/src/cmd/pipelines.c b/src/cmd/pipelines.c index 239fe221..680c5f31 100644 --- a/src/cmd/pipelines.c +++ b/src/cmd/pipelines.c @@ -135,7 +135,7 @@ subcommand_pipelines(int argc, char *argv[]) /* Make sure we are actually talking about a gitlab remote because * we might be incorrectly inferring it */ - if (gcli_config_get_forge_type() != GCLI_FORGE_GITLAB) + if (gcli_config_get_forge_type(g_clictx) != GCLI_FORGE_GITLAB) errx(1, "error: The pipelines subcommand only works for GitLab. " "Use gcli -t gitlab ... to force a GitLab remote."); @@ -149,7 +149,7 @@ subcommand_pipelines(int argc, char *argv[]) return EXIT_FAILURE; } - gitlab_pipeline_jobs(owner, repo, pid, count); + gitlab_pipeline_jobs(g_clictx, owner, repo, pid, count); return EXIT_SUCCESS; } @@ -163,7 +163,7 @@ subcommand_pipelines(int argc, char *argv[]) return EXIT_FAILURE; } - gitlab_pipelines(owner, repo, count); + gitlab_pipelines(g_clictx, owner, repo, count); return EXIT_SUCCESS; } @@ -172,7 +172,7 @@ subcommand_pipelines(int argc, char *argv[]) /* Definition of the action list */ struct { char const *name; /* Name on the cli */ - int (*fn)(char const *, char const *, long); /* Function to be invoked for this action */ + int (*fn)(gcli_ctx *ctx, char const *, char const *, long); /* Function to be invoked for this action */ } job_actions[] = { { .name = "log", .fn = gitlab_job_get_log }, { .name = "status", .fn = gitlab_job_status }, @@ -202,7 +202,7 @@ subcommand_pipelines(int argc, char *argv[]) argc -= 2; argv += 2; } - if (gitlab_job_download_artifacts(owner, repo, jid, outfile) < 0) + if (gitlab_job_download_artifacts(g_clictx, owner, repo, jid, outfile) < 0) errx(1, "error: failed to download file"); goto next_action; } @@ -210,7 +210,7 @@ subcommand_pipelines(int argc, char *argv[]) /* Find the action and invoke it */ for (size_t i = 0; i < ARRAY_SIZE(job_actions); ++i) { if (strcmp(action, job_actions[i].name) == 0) { - if (job_actions[i].fn(owner, repo, jid) < 0) + if (job_actions[i].fn(g_clictx, owner, repo, jid) < 0) errx(1, "error: failed to perform action '%s'", action); goto next_action; } diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index ce34e051..6bc6157e 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -91,7 +91,7 @@ pr_try_derive_head(void) sn_sv account = {0}; sn_sv branch = {0}; - if (!(account = gcli_config_get_account()).length) + if (!(account = gcli_config_get_account(g_clictx)).length) errx(1, "error: Cannot derive PR head. Please specify --from or set the\n" " account in the users gcli config file."); @@ -178,7 +178,7 @@ subcommand_pull_create(int argc, char *argv[]) opts.from = pr_try_derive_head(); if (!opts.to.length) { - if (!(opts.to = gcli_config_get_base()).length) + if (!(opts.to = gcli_config_get_base(g_clictx)).length) errx(1, "error: PR base is missing. Please either specify " "--to branch-name or set pr.base in .gcli."); @@ -194,7 +194,7 @@ subcommand_pull_create(int argc, char *argv[]) opts.title = SV(argv[0]); - if (gcli_pull_submit(opts) < 0) + if (gcli_pull_submit(g_clictx, opts) < 0) errx(1, "error: failed to submit pull request"); free(opts.labels); @@ -311,10 +311,10 @@ subcommand_pulls(int argc, char *argv[]) /* In case no explicit PR number was specified, list all * open PRs and exit */ if (pr < 0) { - if (gcli_get_pulls(owner, repo, &details, n, &pulls) < 0) + if (gcli_get_pulls(g_clictx, owner, repo, &details, n, &pulls) < 0) errx(1, "error: could not fetch pull requests"); - gcli_print_pulls_table(flags, &pulls, n); + gcli_print_pulls_table(g_clictx, flags, &pulls, n); gcli_pulls_free(&pulls); return EXIT_SUCCESS; @@ -339,7 +339,7 @@ ensure_pull(char const *owner, char const *repo, int pr, if (*fetched_pull) return; - if (gcli_get_pull(owner, repo, pr, pull) < 0) + if (gcli_get_pull(g_clictx, owner, repo, pr, pull) < 0) errx(1, "error: failed to fetch pull request data"); *fetched_pull = 1; @@ -383,7 +383,7 @@ handle_pull_actions(int argc, char *argv[], ensure_pull(owner, repo, pr, &fetched_pull, &pull); /* Print meta */ - gcli_pull_print_status(&pull); + gcli_pull_print_status(g_clictx, &pull); /* OP */ puts("\nORIGINAL POST"); @@ -391,11 +391,11 @@ handle_pull_actions(int argc, char *argv[], /* Commits */ puts("\nCOMMITS"); - gcli_pull_commits(owner, repo, pr); + gcli_pull_commits(g_clictx, owner, repo, pr); /* Checks */ puts("\nCHECKS"); - if (gcli_pull_checks(owner, repo, pr) < 0) + if (gcli_pull_checks(g_clictx, owner, repo, pr) < 0) errx(1, "error: failed to fetch pull request checks"); } else if (strcmp(action, "op") == 0) { @@ -412,29 +412,29 @@ handle_pull_actions(int argc, char *argv[], ensure_pull(owner, repo, pr, &fetched_pull, &pull); /* Print meta information */ - gcli_pull_print_status(&pull); + gcli_pull_print_status(g_clictx, &pull); } else if (strcmp(action, "commits") == 0) { /* Does not require the summary */ - gcli_pull_commits(owner, repo, pr); + gcli_pull_commits(g_clictx, owner, repo, pr); } else if (strcmp(action, "diff") == 0) { - gcli_print_pull_diff(stdout, owner, repo, pr); + gcli_print_pull_diff(g_clictx, stdout, owner, repo, pr); } else if (strcmp(action, "comments") == 0 || strcmp(action, "notes") == 0) { - gcli_pull_comments(owner, repo, pr); + gcli_pull_comments(g_clictx, owner, repo, pr); } else if (strcmp(action, "ci") == 0) { - if (gcli_pull_checks(owner, repo, pr) < 0) + if (gcli_pull_checks(g_clictx, owner, repo, pr) < 0) errx(1, "error: failed to fetch pull request checks"); } else if (strcmp(action, "merge") == 0) { enum gcli_merge_flags flags = GCLI_PULL_MERGE_DELETEHEAD; /* Default behaviour */ - if (gcli_config_pr_inhibit_delete_source_branch()) + if (gcli_config_pr_inhibit_delete_source_branch(g_clictx)) flags = 0; if (argc > 0) { @@ -452,33 +452,33 @@ handle_pull_actions(int argc, char *argv[], } } - if (gcli_pull_merge(owner, repo, pr, flags) < 0) + if (gcli_pull_merge(g_clictx, owner, repo, pr, flags) < 0) errx(1, "error: failed to merge pull request"); } else if (strcmp(action, "close") == 0) { - if (gcli_pull_close(owner, repo, pr) < 0) + if (gcli_pull_close(g_clictx, owner, repo, pr) < 0) errx(1, "error: failed to close pull request"); } else if (strcmp(action, "reopen") == 0) { - if (gcli_pull_reopen(owner, repo, pr) < 0) + if (gcli_pull_reopen(g_clictx, owner, repo, pr) < 0) errx(1, "error: failed to reopen pull request"); } else if (strcmp(action, "reviews") == 0) { /* list reviews */ gcli_pr_review_list reviews = {0}; - if (gcli_review_get_reviews(owner, repo, pr, &reviews) < 0) + if (gcli_review_get_reviews(g_clictx, owner, repo, pr, &reviews) < 0) errx(1, "error: failed to fetch reviews"); - gcli_review_print_review_table(&reviews); + gcli_review_print_review_table(g_clictx, &reviews); gcli_review_reviews_free(&reviews); } else if (strcmp("labels", action) == 0) { - const char **add_labels = NULL; - size_t add_labels_size = 0; - const char **remove_labels = NULL; - size_t remove_labels_size = 0; - int rc = 0; + const char **add_labels = NULL; + size_t add_labels_size = 0; + const char **remove_labels = NULL; + size_t remove_labels_size = 0; + int rc = 0; if (argc == 0) { fprintf(stderr, "error: expected label action\n"); @@ -493,13 +493,15 @@ handle_pull_actions(int argc, char *argv[], /* actually go about deleting and adding the labels */ if (add_labels_size) { rc = gcli_pull_add_labels( - owner, repo, pr, add_labels, add_labels_size); + g_clictx, owner, repo, pr, add_labels, + add_labels_size); if (rc < 0) errx(1, "failed to add labels"); } if (remove_labels_size) { rc = gcli_pull_remove_labels( - owner, repo, pr, remove_labels, remove_labels_size); + g_clictx, owner, repo, pr, remove_labels, + remove_labels_size); if (rc < 0) errx(1, "failed to remove labels"); @@ -512,12 +514,13 @@ handle_pull_actions(int argc, char *argv[], char const *arg = shift(&argc, &argv); if (strcmp(arg, "-d") == 0) { - if (gcli_pull_clear_milestone(owner, repo, pr) < 0) + if (gcli_pull_clear_milestone(g_clictx, owner, repo, pr) < 0) errx(1, "failed to clear milestone"); } else { int milestone_id = 0; char *endptr; + int rc = 0; milestone_id = strtoul(arg, &endptr, 10); if (endptr != arg + strlen(arg)) { @@ -525,7 +528,9 @@ handle_pull_actions(int argc, char *argv[], return EXIT_FAILURE; } - if (gcli_pull_set_milestone(owner, repo, pr, milestone_id) < 0) + rc = gcli_pull_set_milestone(g_clictx, owner, repo, pr, + milestone_id); + if (rc < 0) errx(1, "error: failed to set milestone"); } } else { diff --git a/src/cmd/releases.c b/src/cmd/releases.c index 7f515254..3c631616 100644 --- a/src/cmd/releases.c +++ b/src/cmd/releases.c @@ -65,10 +65,12 @@ usage(void) } static void -releasemsg_init(FILE *f, void *_data) +releasemsg_init(gcli_ctx *ctx, FILE *f, void *_data) { gcli_new_release const *info = _data; + (void) ctx; + fprintf( f, "! Enter your release notes above, save and exit.\n" @@ -83,7 +85,8 @@ releasemsg_init(FILE *f, void *_data) static sn_sv get_release_message(gcli_new_release const *info) { - return gcli_editor_get_user_message(releasemsg_init, (void *)info); + return gcli_editor_get_user_message(g_clictx, releasemsg_init, + (void *)info); } static int @@ -192,7 +195,7 @@ subcommand_releases_create(int argc, char *argv[]) if (!sn_yesno("Do you want to create this release?")) errx(1, "Aborted by user"); - if (gcli_create_release(&release) < 0) + if (gcli_create_release(g_clictx, &release) < 0) errx(1, "failed to create release"); return EXIT_SUCCESS; @@ -255,7 +258,7 @@ subcommand_releases_delete(int argc, char *argv[]) if (!sn_yesno("Are you sure you want to delete this release?")) errx(1, "Aborted by user"); - if (gcli_delete_release(owner, repo, argv[0]) < 0) + if (gcli_delete_release(g_clictx, owner, repo, argv[0]) < 0) errx(1, "failed to delete the release"); return EXIT_SUCCESS; @@ -355,10 +358,10 @@ subcommand_releases(int argc, char *argv[]) check_owner_and_repo(&owner, &repo); - if (gcli_get_releases(owner, repo, count, &releases) < 0) + if (gcli_get_releases(g_clictx, owner, repo, count, &releases) < 0) errx(1, "error: could not get releases"); - gcli_print_releases(flags, &releases, count); + gcli_print_releases(g_clictx, flags, &releases, count); gcli_free_releases(&releases); return EXIT_SUCCESS; diff --git a/src/cmd/repos.c b/src/cmd/repos.c index 3dd00561..0be8cd28 100644 --- a/src/cmd/repos.c +++ b/src/cmd/repos.c @@ -107,10 +107,10 @@ subcommand_repos_create(int argc, char *argv[]) return EXIT_FAILURE; } - if (gcli_repo_create(&create_options, &repo) < 0) + if (gcli_repo_create(g_clictx, &create_options, &repo) < 0) errx(1, "error: failed to create repository"); - gcli_repo_print(&repo); + gcli_repo_print(g_clictx, &repo); gcli_repo_free(&repo); return EXIT_SUCCESS; @@ -200,14 +200,14 @@ subcommand_repos(int argc, char *argv[]) } if (!owner) - rc = gcli_get_own_repos(n, &repos); + rc = gcli_get_own_repos(g_clictx, n, &repos); else - rc = gcli_get_repos(owner, n, &repos); + rc = gcli_get_repos(g_clictx, owner, n, &repos); if (rc < 0) errx(1, "error: failed to fetch repos"); - gcli_print_repos_table(flags, &repos, n); + gcli_print_repos_table(g_clictx, flags, &repos, n); gcli_repos_free(&repos); } else { check_owner_and_repo(&owner, &repo); diff --git a/src/cmd/snippets.c b/src/cmd/snippets.c index c65c0121..09bf655f 100644 --- a/src/cmd/snippets.c +++ b/src/cmd/snippets.c @@ -74,7 +74,7 @@ subcommand_snippet_get(int argc, char *argv[]) return EXIT_FAILURE; } - gcli_snippet_get(snippet_id); + gcli_snippet_get(g_clictx, snippet_id); return EXIT_SUCCESS; } @@ -99,7 +99,7 @@ subcommand_snippet_delete(int argc, char *argv[]) return EXIT_FAILURE; } - if (gcli_snippet_delete(snippet_id) < 0) + if (gcli_snippet_delete(g_clictx, snippet_id) < 0) errx(1, "error: failed to delete snippet"); return EXIT_SUCCESS; @@ -173,10 +173,10 @@ subcommand_snippets(int argc, char *argv[]) argc -= optind; argv += optind; - if (gcli_snippets_get(count, &list) < 0) + if (gcli_snippets_get(g_clictx, count, &list) < 0) errx(1, "error: failed to fetch snippets"); - gcli_snippets_print(flags, &list, count); + gcli_snippets_print(g_clictx, flags, &list, count); gcli_snippets_free(&list); return EXIT_SUCCESS; diff --git a/src/cmd/status.c b/src/cmd/status.c index 7d94988f..3fbf49e9 100644 --- a/src/cmd/status.c +++ b/src/cmd/status.c @@ -89,7 +89,7 @@ subcommand_status(int argc, char *argv[]) argv += optind; if (!mark) { - gcli_status(count); + gcli_status(g_clictx, count); } else { if (count != 30) warnx("ignoring -n/--count argument"); @@ -106,7 +106,7 @@ subcommand_status(int argc, char *argv[]) return EXIT_FAILURE; } - if (gcli_notification_mark_as_read(argv[0]) < 0) + if (gcli_notification_mark_as_read(g_clictx, argv[0]) < 0) errx(1, "failed to mark the notification as read"); } diff --git a/src/config.c b/src/config.c index 907af4b4..1bfc014c 100644 --- a/src/config.c +++ b/src/config.c @@ -471,6 +471,10 @@ gcli_config_init_ctx(struct gcli_ctx *ctx) (struct gcli_config_sections) TAILQ_HEAD_INITIALIZER(ctx->config->sections); + ctx->dotgcli->entries = + (struct gcli_config_entries) + TAILQ_HEAD_INITIALIZER(ctx->dotgcli->entries); + return 0; } From 0038f9c302461cd91e8cc88b6aa7f88ba7969469 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Wed, 16 Aug 2023 10:43:34 +0200 Subject: [PATCH 106/236] Remove global curl context and store it in gcli_ctx --- Makefile.am | 1 + include/gcli/ctx.h | 3 + include/gcli/curl.h | 4 +- include/gcli/json_util.h | 2 +- src/ctx.c | 59 ++++++++++ src/curl.c | 244 ++++++++++++++++++++------------------- src/github/repos.c | 16 ++- src/gitlab/comments.c | 8 +- src/gitlab/forks.c | 4 +- src/gitlab/issues.c | 4 +- src/gitlab/releases.c | 10 +- todo.org | 6 + 12 files changed, 224 insertions(+), 137 deletions(-) create mode 100644 src/ctx.c diff --git a/Makefile.am b/Makefile.am index 1455bd61..f245e0e9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -109,6 +109,7 @@ TEMPLATES = \ templates/gitea/milestones.t libgcli_la_SOURCES = \ + include/gcli/ctx.h src/ctx.c \ include/gcli/gcli.h src/gcli.c \ src/colour.c include/gcli/colour.h \ src/comments.c include/gcli/comments.h \ diff --git a/include/gcli/ctx.h b/include/gcli/ctx.h index d76ad164..1b8df7c2 100644 --- a/include/gcli/ctx.h +++ b/include/gcli/ctx.h @@ -42,6 +42,9 @@ struct gcli_ctx { char *last_error; }; +/* Error routine */ +int gcli_error(struct gcli_ctx *ctx, char const *const fmt, ...); + /* Functions that are strictly called from the init / deinit routines * and not exposed to the public interface */ int gcli_config_init_ctx(struct gcli_ctx *); diff --git a/include/gcli/curl.h b/include/gcli/curl.h index 4c5a19a6..abb00634 100644 --- a/include/gcli/curl.h +++ b/include/gcli/curl.h @@ -81,10 +81,10 @@ int gcli_curl_gitea_upload_attachment(gcli_ctx *ctx, char const *url, char const *filename, gcli_fetch_buffer *out); -bool gcli_curl_test_success(char const *url); +int gcli_curl_test_success(gcli_ctx *ctx, char const *url); char *gcli_urlencode(char const *); sn_sv gcli_urlencode_sv(sn_sv const); -char *gcli_urldecode(char const *input); +char *gcli_urldecode(gcli_ctx *ctx, char const *input); int gcli_fetch_list(gcli_ctx *ctx, char *url, gcli_fetch_list_ctx *fctx); #endif /* CURL_H */ diff --git a/include/gcli/json_util.h b/include/gcli/json_util.h index fa8bedeb..44930d9a 100644 --- a/include/gcli/json_util.h +++ b/include/gcli/json_util.h @@ -111,7 +111,7 @@ gcli_json_bool(bool it) static inline void parse_sv(gcli_ctx *ctx, json_stream *stream, sn_sv *out) { - (void) *ctx; + (void) ctx; *out = get_sv(ctx, stream); } diff --git a/src/ctx.c b/src/ctx.c new file mode 100644 index 00000000..181c13f2 --- /dev/null +++ b/src/ctx.c @@ -0,0 +1,59 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include + +int +gcli_error(struct gcli_ctx *ctx, char const *const fmt, ...) +{ + va_list vp; + char *buf; + size_t len; + + va_start(vp, fmt); + len = vsnprintf(NULL, 0, fmt, vp); + va_end(vp); + + buf = malloc(len + 1); + + va_start(vp, fmt); + vsnprintf(buf, len + 1, fmt, vp); + va_end(vp); + + if (ctx->last_error) + free(ctx->last_error); + + ctx->last_error = buf; + + return -1; +} diff --git a/src/curl.c b/src/curl.c index 16f12c2e..1b8d5163 100644 --- a/src/curl.c +++ b/src/curl.c @@ -59,32 +59,29 @@ gcli_curl_isalnum(char const c) #endif /* __NetBSD and Oracle Solaris */ -/* Cached curl handle */ -static CURL *gcli_curl_session = NULL; - -/* Clean up the curl handle. Called by the atexit destructor chain */ -static void -gcli_cleanup_curl(void) +/* XXX move to gcli_ctx destructor */ +void +gcli_curl_ctx_destroy(gcli_ctx *ctx) { - if (gcli_curl_session) - curl_easy_cleanup(gcli_curl_session); - gcli_curl_session = NULL; + if (ctx->curl) + curl_easy_cleanup(ctx->curl); + ctx->curl = NULL; } /* Ensures a clean cURL handle. Call this whenever you wanna use the - * gcli_curl_session */ -static void -gcli_curl_ensure(void) + * ctx->curl */ +static int +gcli_curl_ensure(gcli_ctx *ctx) { - if (gcli_curl_session) { - curl_easy_reset(gcli_curl_session); + if (ctx->curl) { + curl_easy_reset(ctx->curl); } else { - gcli_curl_session = curl_easy_init(); - if (!gcli_curl_session) - errx(1, "error: cannot initialize curl"); - - atexit(gcli_cleanup_curl); + ctx->curl = curl_easy_init(); + if (!ctx->curl) + return gcli_error(ctx, "failed to initialise curl context"); } + + return 0; } /* Check the given curl code for an OK result. If not, print an @@ -105,7 +102,7 @@ gcli_curl_check_api_error(gcli_ctx *ctx, CURLcode code, char const *url, return -1; } - curl_easy_getinfo(gcli_curl_session, CURLINFO_RESPONSE_CODE, &status_code); + curl_easy_getinfo(ctx->curl, CURLINFO_RESPONSE_CODE, &status_code); if (status_code >= 300L) { fprintf(stderr, @@ -149,38 +146,40 @@ gcli_fetch(gcli_ctx *ctx, char const *url, char **const pagination_next, } /* Check the given url for a successful query */ -bool -gcli_curl_test_success(char const *url) +int +gcli_curl_test_success(gcli_ctx *ctx, char const *url) { - CURLcode ret; - gcli_fetch_buffer buffer = {0}; - long status_code; - bool is_success = true; - - gcli_curl_ensure(); - - curl_easy_setopt(gcli_curl_session, CURLOPT_URL, url); - curl_easy_setopt(gcli_curl_session, CURLOPT_BUFFERSIZE, 102400L); - curl_easy_setopt(gcli_curl_session, CURLOPT_NOPROGRESS, 1L); - curl_easy_setopt(gcli_curl_session, CURLOPT_MAXREDIRS, 50L); - curl_easy_setopt(gcli_curl_session, CURLOPT_FTP_SKIP_PASV_IP, 1L); - curl_easy_setopt(gcli_curl_session, CURLOPT_USERAGENT, "curl/7.78.0"); + CURLcode ret; + gcli_fetch_buffer buffer = {0}; + long status_code; + bool is_success = true; + int rc = 0; + + if ((rc = gcli_curl_ensure(ctx)) < 0) + return rc; + + curl_easy_setopt(ctx->curl, CURLOPT_URL, url); + curl_easy_setopt(ctx->curl, CURLOPT_BUFFERSIZE, 102400L); + curl_easy_setopt(ctx->curl, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(ctx->curl, CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(ctx->curl, CURLOPT_FTP_SKIP_PASV_IP, 1L); + curl_easy_setopt(ctx->curl, CURLOPT_USERAGENT, "curl/7.78.0"); #if defined(CURL_HTTP_VERSION_2TLS) curl_easy_setopt( - gcli_curl_session, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS); + ctx->curl, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS); #endif - curl_easy_setopt(gcli_curl_session, CURLOPT_TCP_KEEPALIVE, 1L); - curl_easy_setopt(gcli_curl_session, CURLOPT_WRITEDATA, &buffer); - curl_easy_setopt(gcli_curl_session, CURLOPT_WRITEFUNCTION, fetch_write_callback); - curl_easy_setopt(gcli_curl_session, CURLOPT_FAILONERROR, 0L); - curl_easy_setopt(gcli_curl_session, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(ctx->curl, CURLOPT_TCP_KEEPALIVE, 1L); + curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, &buffer); + curl_easy_setopt(ctx->curl, CURLOPT_WRITEFUNCTION, fetch_write_callback); + curl_easy_setopt(ctx->curl, CURLOPT_FAILONERROR, 0L); + curl_easy_setopt(ctx->curl, CURLOPT_FOLLOWLOCATION, 1L); - ret = curl_easy_perform(gcli_curl_session); + ret = curl_easy_perform(ctx->curl); if (ret != CURLE_OK) { is_success = false; } else { - curl_easy_getinfo(gcli_curl_session, CURLINFO_RESPONSE_CODE, &status_code); + curl_easy_getinfo(ctx->curl, CURLINFO_RESPONSE_CODE, &status_code); if (status_code >= 300L) is_success = false; @@ -206,32 +205,33 @@ gcli_curl(gcli_ctx *ctx, FILE *stream, char const *url, char const *content_type headers = NULL; + if ((rc = gcli_curl_ensure(ctx)) < 0) + return rc; + if (content_type) headers = curl_slist_append(headers, content_type); auth_header = gcli_config_get_authheader(ctx); headers = curl_slist_append(headers, auth_header); - gcli_curl_ensure(); - - curl_easy_setopt(gcli_curl_session, CURLOPT_URL, url); - curl_easy_setopt(gcli_curl_session, CURLOPT_BUFFERSIZE, 102400L); - curl_easy_setopt(gcli_curl_session, CURLOPT_NOPROGRESS, 1L); - curl_easy_setopt(gcli_curl_session, CURLOPT_MAXREDIRS, 50L); - curl_easy_setopt(gcli_curl_session, CURLOPT_FTP_SKIP_PASV_IP, 1L); - curl_easy_setopt(gcli_curl_session, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(gcli_curl_session, CURLOPT_USERAGENT, "curl/7.78.0"); + curl_easy_setopt(ctx->curl, CURLOPT_URL, url); + curl_easy_setopt(ctx->curl, CURLOPT_BUFFERSIZE, 102400L); + curl_easy_setopt(ctx->curl, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(ctx->curl, CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(ctx->curl, CURLOPT_FTP_SKIP_PASV_IP, 1L); + curl_easy_setopt(ctx->curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(ctx->curl, CURLOPT_USERAGENT, "curl/7.78.0"); #if defined(CURL_HTTP_VERSION_2TLS) curl_easy_setopt( - gcli_curl_session, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS); + ctx->curl, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS); #endif - curl_easy_setopt(gcli_curl_session, CURLOPT_TCP_KEEPALIVE, 1L); - curl_easy_setopt(gcli_curl_session, CURLOPT_WRITEDATA, &buffer); - curl_easy_setopt(gcli_curl_session, CURLOPT_WRITEFUNCTION, fetch_write_callback); - curl_easy_setopt(gcli_curl_session, CURLOPT_FAILONERROR, 0L); - curl_easy_setopt(gcli_curl_session, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(ctx->curl, CURLOPT_TCP_KEEPALIVE, 1L); + curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, &buffer); + curl_easy_setopt(ctx->curl, CURLOPT_WRITEFUNCTION, fetch_write_callback); + curl_easy_setopt(ctx->curl, CURLOPT_FAILONERROR, 0L); + curl_easy_setopt(ctx->curl, CURLOPT_FOLLOWLOCATION, 1L); - ret = curl_easy_perform(gcli_curl_session); + ret = curl_easy_perform(ctx->curl); rc = gcli_curl_check_api_error(ctx, ret, url, &buffer); if (rc == 0) @@ -333,9 +333,12 @@ gcli_fetch_with_method( struct curl_slist *headers; gcli_fetch_buffer tmp = {0}; /* used for error codes when out is NULL */ gcli_fetch_buffer *buf = NULL; - char *link_header = NULL; + char *link_header = NULL; int rc = 0; + if ((rc = gcli_curl_ensure(ctx)) < 0) + return rc; + char *auth_header = gcli_config_get_authheader(ctx); if (sn_verbose()) @@ -361,25 +364,23 @@ gcli_fetch_with_method( buf = &tmp; } - gcli_curl_ensure(); - - curl_easy_setopt(gcli_curl_session, CURLOPT_URL, url); + curl_easy_setopt(ctx->curl, CURLOPT_URL, url); if (data) - curl_easy_setopt(gcli_curl_session, CURLOPT_POSTFIELDS, data); - - curl_easy_setopt(gcli_curl_session, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(gcli_curl_session, CURLOPT_USERAGENT, "curl/7.79.1"); - curl_easy_setopt(gcli_curl_session, CURLOPT_CUSTOMREQUEST, method); - curl_easy_setopt(gcli_curl_session, CURLOPT_TCP_KEEPALIVE, 1L); - curl_easy_setopt(gcli_curl_session, CURLOPT_WRITEDATA, buf); - curl_easy_setopt(gcli_curl_session, CURLOPT_WRITEFUNCTION, fetch_write_callback); - curl_easy_setopt(gcli_curl_session, CURLOPT_FAILONERROR, 0L); - curl_easy_setopt(gcli_curl_session, CURLOPT_HEADERFUNCTION, fetch_header_callback); - curl_easy_setopt(gcli_curl_session, CURLOPT_HEADERDATA, &link_header); - curl_easy_setopt(gcli_curl_session, CURLOPT_FOLLOWLOCATION, 1L); - - ret = curl_easy_perform(gcli_curl_session); + curl_easy_setopt(ctx->curl, CURLOPT_POSTFIELDS, data); + + curl_easy_setopt(ctx->curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(ctx->curl, CURLOPT_USERAGENT, "curl/7.79.1"); + curl_easy_setopt(ctx->curl, CURLOPT_CUSTOMREQUEST, method); + curl_easy_setopt(ctx->curl, CURLOPT_TCP_KEEPALIVE, 1L); + curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, buf); + curl_easy_setopt(ctx->curl, CURLOPT_WRITEFUNCTION, fetch_write_callback); + curl_easy_setopt(ctx->curl, CURLOPT_FAILONERROR, 0L); + curl_easy_setopt(ctx->curl, CURLOPT_HEADERFUNCTION, fetch_header_callback); + curl_easy_setopt(ctx->curl, CURLOPT_HEADERDATA, &link_header); + curl_easy_setopt(ctx->curl, CURLOPT_FOLLOWLOCATION, 1L); + + ret = curl_easy_perform(ctx->curl); rc = gcli_curl_check_api_error(ctx, ret, url, buf); /* only parse these headers and continue if there was no error */ @@ -421,14 +422,16 @@ gcli_post_upload(gcli_ctx *ctx, char const *url, char const *content_type, CURLcode ret; struct curl_slist *headers; int rc = 0; + char *auth_header, *contenttype_header, *contentsize_header; - char *auth_header = gcli_config_get_authheader(ctx); - char *contenttype_header = sn_asprintf( - "Content-Type: %s", - content_type); - char *contentsize_header = sn_asprintf( - "Content-Length: %zu", - buffer_size); + if ((rc = gcli_curl_ensure(ctx)) < 0) + return rc; + + auth_header = gcli_config_get_authheader(ctx); + contenttype_header = sn_asprintf("Content-Type: %s", + content_type); + contentsize_header = sn_asprintf("Content-Length: %zu", + buffer_size); if (sn_verbose()) fprintf(stderr, "info: cURL upload POST %s...\n", url); @@ -441,19 +444,17 @@ gcli_post_upload(gcli_ctx *ctx, char const *url, char const *content_type, headers = curl_slist_append(headers, contenttype_header); headers = curl_slist_append(headers, contentsize_header); - gcli_curl_ensure(); + curl_easy_setopt(ctx->curl, CURLOPT_URL, url); + curl_easy_setopt(ctx->curl, CURLOPT_POST, 1L); + curl_easy_setopt(ctx->curl, CURLOPT_POSTFIELDS, buffer); + curl_easy_setopt(ctx->curl, CURLOPT_POSTFIELDSIZE, (long)buffer_size); - curl_easy_setopt(gcli_curl_session, CURLOPT_URL, url); - curl_easy_setopt(gcli_curl_session, CURLOPT_POST, 1L); - curl_easy_setopt(gcli_curl_session, CURLOPT_POSTFIELDS, buffer); - curl_easy_setopt(gcli_curl_session, CURLOPT_POSTFIELDSIZE, (long)buffer_size); + curl_easy_setopt(ctx->curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(ctx->curl, CURLOPT_USERAGENT, "curl/7.79.1"); + curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, out); + curl_easy_setopt(ctx->curl, CURLOPT_WRITEFUNCTION, fetch_write_callback); - curl_easy_setopt(gcli_curl_session, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(gcli_curl_session, CURLOPT_USERAGENT, "curl/7.79.1"); - curl_easy_setopt(gcli_curl_session, CURLOPT_WRITEDATA, out); - curl_easy_setopt(gcli_curl_session, CURLOPT_WRITEFUNCTION, fetch_write_callback); - - ret = curl_easy_perform(gcli_curl_session); + ret = curl_easy_perform(ctx->curl); rc = gcli_curl_check_api_error(ctx, ret, url, out); curl_slist_free_all(headers); @@ -481,8 +482,12 @@ gcli_curl_gitea_upload_attachment(gcli_ctx *ctx, char const *url, curl_mimepart *contentpart; struct curl_slist *headers; int rc = 0; + char *auth_header; - char *auth_header = gcli_config_get_authheader(ctx); + if ((rc = gcli_curl_ensure(ctx)) < 0) + return rc; + + auth_header = gcli_config_get_authheader(ctx); if (sn_verbose()) fprintf(stderr, "info: cURL upload POST %s...\n", url); @@ -493,10 +498,8 @@ gcli_curl_gitea_upload_attachment(gcli_ctx *ctx, char const *url, "Accept: application/json"); headers = curl_slist_append(headers, auth_header); - gcli_curl_ensure(); - /* The docs say we should be using this mime thing. */ - mime = curl_mime_init(gcli_curl_session); + mime = curl_mime_init(ctx->curl); contentpart = curl_mime_addpart(mime); /* Attach the file. It will be read when curl_easy_perform is @@ -509,14 +512,14 @@ gcli_curl_gitea_upload_attachment(gcli_ctx *ctx, char const *url, curl_easy_strerror(ret)); } - curl_easy_setopt(gcli_curl_session, CURLOPT_URL, url); - curl_easy_setopt(gcli_curl_session, CURLOPT_MIMEPOST, mime); + curl_easy_setopt(ctx->curl, CURLOPT_URL, url); + curl_easy_setopt(ctx->curl, CURLOPT_MIMEPOST, mime); - curl_easy_setopt(gcli_curl_session, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(gcli_curl_session, CURLOPT_WRITEDATA, out); - curl_easy_setopt(gcli_curl_session, CURLOPT_WRITEFUNCTION, fetch_write_callback); + curl_easy_setopt(ctx->curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, out); + curl_easy_setopt(ctx->curl, CURLOPT_WRITEFUNCTION, fetch_write_callback); - ret = curl_easy_perform(gcli_curl_session); + ret = curl_easy_perform(ctx->curl); rc = gcli_curl_check_api_error(ctx, ret, url, out); /* Cleanup */ @@ -531,15 +534,15 @@ gcli_curl_gitea_upload_attachment(gcli_ctx *ctx, char const *url, sn_sv gcli_urlencode_sv(sn_sv const _input) { - size_t input_len; - size_t output_len; - size_t i; - char *output; - char *input; - - input = _input.data; - input_len = _input.length; - output = calloc(1, 3 * input_len + 1); + size_t input_len; + size_t output_len; + size_t i; + char *output; + char *input; + + input = _input.data; + input_len = _input.length; + output = calloc(1, 3 * input_len + 1); output_len = 0; for (i = 0; i < input_len; ++i) { @@ -563,15 +566,18 @@ gcli_urlencode(char const *input) } char * -gcli_urldecode(char const *input) +gcli_urldecode(gcli_ctx *ctx, char const *input) { char *curlresult, *result; - gcli_curl_ensure(); + if (gcli_curl_ensure(ctx) < 0) + return NULL; - curlresult = curl_easy_unescape(gcli_curl_session, input, 0, NULL); - if (!curlresult) - errx(1, "error: could not url decode"); + curlresult = curl_easy_unescape(ctx->curl, input, 0, NULL); + if (!curlresult) { + gcli_error(ctx, "could not urldecode"); + return NULL; + } result = strdup(curlresult); diff --git a/src/github/repos.c b/src/github/repos.c index 64f7e73d..25a18e9a 100644 --- a/src/github/repos.c +++ b/src/github/repos.c @@ -43,6 +43,8 @@ github_get_repos(gcli_ctx *ctx, char const *owner, int const max, { char *url = NULL; char *e_owner = NULL; + int rc = 0; + gcli_fetch_list_ctx lf = { .listp = &list->repos, .sizep = &list->repos_size, @@ -56,7 +58,17 @@ github_get_repos(gcli_ctx *ctx, char const *owner, int const max, * organizations and users. Thus, we have to find out, whether the * param is a user or an actual organization. */ url = sn_asprintf("%s/users/%s", gcli_get_apibase(ctx), e_owner); - if (gcli_curl_test_success(url)) { + free(e_owner); + + /* 0 = failed, 1 = success, -1 = error (just like a BOOL in Win32 + * /sarc) */ + rc = gcli_curl_test_success(ctx, url); + if (rc < 0) { + free(url); + return rc; + } + + if (rc) { /* it is a user */ free(url); url = sn_asprintf("%s/users/%s/repos", @@ -70,8 +82,6 @@ github_get_repos(gcli_ctx *ctx, char const *owner, int const max, e_owner); } - free(e_owner); - return gcli_fetch_list(ctx, url, &lf); } diff --git a/src/gitlab/comments.c b/src/gitlab/comments.c index 5792a6f7..94e8ca50 100644 --- a/src/gitlab/comments.c +++ b/src/gitlab/comments.c @@ -43,7 +43,7 @@ gitlab_perform_submit_comment(gcli_ctx *ctx, gcli_submit_comment_opts opts, int rc = 0; e_owner = gcli_urlencode(opts.owner); - e_repo = gcli_urlencode(opts.repo); + e_repo = gcli_urlencode(opts.repo); switch (opts.target_type) { case ISSUE_COMMENT: @@ -77,7 +77,8 @@ gitlab_get_mr_comments(gcli_ctx *ctx, char const *owner, char const *repo, int const mr, gcli_comment_list *const out) { char *e_owner = gcli_urlencode(owner); - char *e_repo = gcli_urlencode(repo); + char *e_repo = gcli_urlencode(repo); + gcli_fetch_list_ctx fl = { .listp = &out->comments, .sizep = &out->comments_size, @@ -101,7 +102,8 @@ gitlab_get_issue_comments(gcli_ctx *ctx, char const *owner, char const *repo, int const issue, gcli_comment_list *const out) { char *e_owner = gcli_urlencode(owner); - char *e_repo = gcli_urlencode(repo); + char *e_repo = gcli_urlencode(repo); + gcli_fetch_list_ctx fl = { .listp = &out->comments, .sizep = &out->comments_size, diff --git a/src/gitlab/forks.c b/src/gitlab/forks.c index b3eccd92..d8fe4021 100644 --- a/src/gitlab/forks.c +++ b/src/gitlab/forks.c @@ -52,7 +52,7 @@ gitlab_get_forks(gcli_ctx *ctx, char const *owner, char const *repo, }; e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); *list = (gcli_fork_list) {0}; @@ -79,7 +79,7 @@ gitlab_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, int rc = 0; e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s/fork", gitlab_get_apibase(ctx), diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index ce726147..2670b52a 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -63,7 +63,7 @@ gitlab_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, char *e_author = NULL; e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); if (details->author) { char *tmp = gcli_urlencode(details->author); @@ -134,7 +134,7 @@ gitlab_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, int rc = 0; e_owner = gcli_urlencode(owner); - e_repo = gcli_urlencode(repo); + e_repo = gcli_urlencode(repo); url = sn_asprintf( "%s/projects/%s%%2F%s/issues/%d", diff --git a/src/gitlab/releases.c b/src/gitlab/releases.c index f86763eb..96ad5d56 100644 --- a/src/gitlab/releases.c +++ b/src/gitlab/releases.c @@ -39,21 +39,21 @@ #include static void -fixup_asset_name(gcli_release_asset *const asset) +fixup_asset_name(gcli_ctx *ctx, gcli_release_asset *const asset) { if (!asset->name) { - asset->name = gcli_urldecode(strrchr(asset->url, '/') + 1); + asset->name = gcli_urldecode(ctx, strrchr(asset->url, '/') + 1); } } static void -fixup_release_asset_names(gcli_release_list *list) +fixup_release_asset_names(gcli_ctx *ctx, gcli_release_list *list) { /* Iterate over releases */ for (size_t j = 0; j < list->releases_size; ++j) { /* iterate over releases */ for (size_t i = 0; i < list->releases[j].assets_size; ++i) { - fixup_asset_name(&list->releases[j].assets[i]); + fixup_asset_name(ctx, &list->releases[j].assets[i]); } } } @@ -90,7 +90,7 @@ gitlab_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, rc = gcli_fetch_list(ctx, url, &fl); if (rc == 0) - fixup_release_asset_names(list); + fixup_release_asset_names(ctx, list); return rc; } diff --git a/todo.org b/todo.org index 4ff56606..e0178ea4 100644 --- a/todo.org +++ b/todo.org @@ -123,7 +123,13 @@ + https://api.github.com/repos/zorchenhimer/MovieNight/pulls/156/reviews/611653998/comments * Big refactor for libraryfication +** TODO Fix test suite + - [ ] Add support for a testing gcli context ** TODO Check errx calls if they print "error: " ** TODO Check for calls to errx in submit routines ** TODO [[file:src/github/review.c::github_review_get_reviews(char const *owner)][github_review_get_reviews]] is garbage ** TODO Clean up the generic comments code +** TODO Move printing routines to cmd code +** TODO Build a shared library +** TODO Remove global curl handle +** TODO Return errors from parsers From 6cd9ff82956eced6807474ac39eaf50f635de98c Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Wed, 16 Aug 2023 10:45:19 +0200 Subject: [PATCH 107/236] Update TODO.org --- todo.org | 2 ++ 1 file changed, 2 insertions(+) diff --git a/todo.org b/todo.org index e0178ea4..b3511123 100644 --- a/todo.org +++ b/todo.org @@ -132,4 +132,6 @@ ** TODO Move printing routines to cmd code ** TODO Build a shared library ** TODO Remove global curl handle + - [X] Put it into the context + - [ ] Clean up handle on exit ** TODO Return errors from parsers From 94d953ced3186bb88d5404c965925fde79652c6b Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Wed, 16 Aug 2023 11:15:06 +0200 Subject: [PATCH 108/236] Build a shared libgcli.so library by default We also note that for debugging purposes you want static libs. --- HACKING.md | 12 ++++++++++-- Makefile.am | 20 +++++++++++++++++--- todo.org | 2 +- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/HACKING.md b/HACKING.md index 60e1559d..43454dd2 100644 --- a/HACKING.md +++ b/HACKING.md @@ -54,12 +54,19 @@ Then you can configure each build directory with appropriate options: $ ../configure \ CC=/usr/bin/cc \ CFLAGS='-std=iso9899:1999 -pedantic -Wall -Wextra -Wno-misleading-indentation -Werror -g -O0' \ - LDFLAGS='-g' + LDFLAGS='-g' \ + --disable-shared The above will give you a fully debuggable and build with strict C99 compiler errors. I very much suggest that you use those options while working on and debugging gcli. +*Note*: The `--disable-shared` is required because if you build a +shared version of libgcli, libtool will replace the gcli binary with a +shell script that alters the dld search path to read the correct +`libgcli.so`. Because of `build/gcli` now not being a an ELF +executable but a shell script debuggers can't load gcli properly. + #### Sanitized Builds I sometimes enable the sanitizer features of the C Compiler to check @@ -69,7 +76,8 @@ for common bugs: CFLAGS='-std=iso9899:1999 -pedantic -Wall -Wextra -Wno-misleading-indentation -Werror -g -O0 -fsanitize=address,undefined' \ - LDFLAGS=-g + LDFLAGS=-g \ + --disable-shared #### Cross-Compilation diff --git a/Makefile.am b/Makefile.am index f245e0e9..c5594abf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,11 +18,12 @@ pgen_SOURCES = \ src/pgen/parser.y \ src/pgen/lexer.l -noinst_LTLIBRARIES = libgcli.la libsn.la libpdjson.la +lib_LTLIBRARIES = libgcli.la +noinst_LTLIBRARIES = libsn.la libpdjson.la .NOTPARALLEL: pgen$(EXEEXT) $(builddir)/src/pgen/parser.c $(builddir)/src/pgen/parser.h $(builddir)/src/pgen/lexer.c -libgcli_la_DEPENDENCIES = pgen$(EXEEXT) +libgcli_la_DEPENDENCIES = pgen$(EXEEXT) libpdjson.la libsn.la $(BUILT_SOURCES): pgen$(EXEEXT) @@ -34,7 +35,9 @@ SUFFIXES = .t $(AM_V_GEN)./pgen -tc -o $@ $< bin_PROGRAMS = gcli$(EXEEXT) -gcli_LDADD = libgcli.la libpdjson.la libsn.la +gcli_LDADD = libgcli.la + +libgcli_la_LIBADD = libpdjson.la libsn.la dist_man_MANS = \ docs/gcli-api.1 \ @@ -108,6 +111,17 @@ TEMPLATES = \ templates/gitlab/snippets.t \ templates/gitea/milestones.t +include_HEADERS = \ + include/gcli/gcli.h include/gcli/comments.h \ + include/gcli/config.h include/gcli/curl.h \ + include/gcli/editor.h include/gcli/forks.h \ + include/gcli/gitconfig.h include/gcli/issues.h \ + include/gcli/labels.h include/gcli/milestones.h \ + include/gcli/pulls.h include/gcli/releases.h \ + include/gcli/repos.h include/gcli/review.h \ + include/gcli/gitlab/snippets.h include/gcli/status.h \ + include/gcli/sshkeys.h + libgcli_la_SOURCES = \ include/gcli/ctx.h src/ctx.c \ include/gcli/gcli.h src/gcli.c \ diff --git a/todo.org b/todo.org index b3511123..8fe232f3 100644 --- a/todo.org +++ b/todo.org @@ -130,7 +130,7 @@ ** TODO [[file:src/github/review.c::github_review_get_reviews(char const *owner)][github_review_get_reviews]] is garbage ** TODO Clean up the generic comments code ** TODO Move printing routines to cmd code -** TODO Build a shared library +** DONE Build a shared library ** TODO Remove global curl handle - [X] Put it into the context - [ ] Clean up handle on exit From d1a9d3d1657ba6cfeb76e929821719c2a61c739f Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Wed, 16 Aug 2023 22:54:20 +0200 Subject: [PATCH 109/236] Move table and cmd.[hc] to cmd directory This is done to then move all the printers to the cmd directory as well. After all that there should not be any reference to the table stuff in the library anymore. --- Makefile.am | 5 ++--- include/gcli/{ => cmd}/cmd.h | 6 +++--- include/gcli/{ => cmd}/table.h | 6 +++--- src/cmd/api.c | 2 +- src/cmd/ci.c | 2 +- src/{ => cmd}/cmd.c | 2 +- src/cmd/comment.c | 2 +- src/cmd/config.c | 2 +- src/cmd/forks.c | 2 +- src/cmd/gcli.c | 2 +- src/cmd/gists.c | 2 +- src/cmd/issues.c | 2 +- src/cmd/labels.c | 2 +- src/cmd/milestones.c | 2 +- src/cmd/pipelines.c | 2 +- src/cmd/pulls.c | 2 +- src/cmd/releases.c | 2 +- src/cmd/repos.c | 2 +- src/cmd/snippets.c | 2 +- src/cmd/status.c | 2 +- src/{ => cmd}/table.c | 2 +- src/forks.c | 2 +- src/github/checks.c | 2 +- src/github/gists.c | 2 +- src/gitlab/pipelines.c | 2 +- src/gitlab/snippets.c | 2 +- src/issues.c | 2 +- src/labels.c | 2 +- src/milestones.c | 2 +- src/pulls.c | 2 +- src/releases.c | 2 +- src/repos.c | 2 +- src/sshkeys.c | 2 +- 33 files changed, 38 insertions(+), 39 deletions(-) rename include/gcli/{ => cmd}/cmd.h (97%) rename include/gcli/{ => cmd}/table.h (97%) rename src/{ => cmd}/cmd.c (99%) rename src/{ => cmd}/table.c (99%) diff --git a/Makefile.am b/Makefile.am index c5594abf..039cb4d5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -57,8 +57,8 @@ dist_man_MANS = \ docs/gcli.1 gcli_SOURCES = \ - include/gcli/cmd.h \ - src/cmd.c \ + include/gcli/cmd/cmd.h src/cmd/cmd.c \ + include/gcli/cmd/table.h src/cmd/table.c \ src/cmd/api.c \ src/cmd/ci.c \ src/cmd/comment.c \ @@ -144,7 +144,6 @@ libgcli_la_SOURCES = \ src/gitlab/snippets.c include/gcli/gitlab/snippets.h \ src/status.c include/gcli/status.h \ src/sshkeys.c include/gcli/sshkeys.h \ - src/table.c include/gcli/table.h \ src/gitlab/api.c include/gcli/gitlab/api.h \ src/gitlab/comments.c include/gcli/gitlab/comments.h \ src/gitlab/config.c include/gcli/gitlab/config.h \ diff --git a/include/gcli/cmd.h b/include/gcli/cmd/cmd.h similarity index 97% rename from include/gcli/cmd.h rename to include/gcli/cmd/cmd.h index 095624ee..d04242eb 100644 --- a/include/gcli/cmd.h +++ b/include/gcli/cmd/cmd.h @@ -27,8 +27,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GCLI_CMD_H -#define GCLI_CMD_H +#ifndef GCLI_CMD_CMD_H +#define GCLI_CMD_CMD_H #ifdef HAVE_CONFIG_H #include @@ -78,4 +78,4 @@ int subcommand_repos(int argc, char *argv[]); int subcommand_snippets(int argc, char *argv[]); int subcommand_status(int argc, char *argv[]); -#endif /* GCLI_CMD_H */ +#endif /* GCLI_CMD_CMD_H */ diff --git a/include/gcli/table.h b/include/gcli/cmd/table.h similarity index 97% rename from include/gcli/table.h rename to include/gcli/cmd/table.h index 7939a83a..d29532a4 100644 --- a/include/gcli/table.h +++ b/include/gcli/cmd/table.h @@ -27,8 +27,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GCLI_TABLE_H -#define GCLI_TABLE_H +#ifndef GCLI_CMD_TABLE_H +#define GCLI_CMD_TABLE_H #ifdef HAVE_CONFIG_H #include @@ -112,4 +112,4 @@ int gcli_dict_add_sv_list(gcli_dict dict, int gcli_dict_end(gcli_dict _list); -#endif /* GCLI_TABLE_H */ +#endif /* GCLI_CMD_TABLE_H */ diff --git a/src/cmd/api.c b/src/cmd/api.c index 11d12057..d1606522 100644 --- a/src/cmd/api.c +++ b/src/cmd/api.c @@ -31,7 +31,7 @@ #include #endif -#include +#include #include #include diff --git a/src/cmd/ci.c b/src/cmd/ci.c index 72843bd4..9792ceb4 100644 --- a/src/cmd/ci.c +++ b/src/cmd/ci.c @@ -31,7 +31,7 @@ #include #endif -#include +#include #include #include #include diff --git a/src/cmd.c b/src/cmd/cmd.c similarity index 99% rename from src/cmd.c rename to src/cmd/cmd.c index 69b9ff17..99b77c81 100644 --- a/src/cmd.c +++ b/src/cmd/cmd.c @@ -31,7 +31,7 @@ #include #endif -#include +#include #include #include diff --git a/src/cmd/comment.c b/src/cmd/comment.c index bcd04b76..c6efbefc 100644 --- a/src/cmd/comment.c +++ b/src/cmd/comment.c @@ -29,7 +29,7 @@ #include -#include +#include #include #ifdef HAVE_GETOPT_H diff --git a/src/cmd/config.c b/src/cmd/config.c index ea5ff403..88aec8f5 100644 --- a/src/cmd/config.c +++ b/src/cmd/config.c @@ -31,7 +31,7 @@ #include #endif -#include +#include #include #include diff --git a/src/cmd/forks.c b/src/cmd/forks.c index 7fcd30a6..ed3f4525 100644 --- a/src/cmd/forks.c +++ b/src/cmd/forks.c @@ -35,7 +35,7 @@ #include -#include +#include #include #include #include diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index 9b53ac34..dd5698c8 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -38,7 +38,7 @@ #include #include -#include +#include #include static void usage(void); diff --git a/src/cmd/gists.c b/src/cmd/gists.c index 32fc4e38..016da6af 100644 --- a/src/cmd/gists.c +++ b/src/cmd/gists.c @@ -29,7 +29,7 @@ #include -#include +#include #include #include #include diff --git a/src/cmd/issues.c b/src/cmd/issues.c index af0fdb07..6c1c0f15 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -29,7 +29,7 @@ #include -#include +#include #include #include #include diff --git a/src/cmd/labels.c b/src/cmd/labels.c index 142f0c3b..382b2876 100644 --- a/src/cmd/labels.c +++ b/src/cmd/labels.c @@ -29,7 +29,7 @@ #include -#include +#include #include #ifdef HAVE_GETOPT_H diff --git a/src/cmd/milestones.c b/src/cmd/milestones.c index 2993565c..fcd26f48 100644 --- a/src/cmd/milestones.c +++ b/src/cmd/milestones.c @@ -29,7 +29,7 @@ #include -#include +#include #include #ifdef HAVE_GETOPT_H diff --git a/src/cmd/pipelines.c b/src/cmd/pipelines.c index 680c5f31..97571ea9 100644 --- a/src/cmd/pipelines.c +++ b/src/cmd/pipelines.c @@ -29,7 +29,7 @@ #include -#include +#include #include #include #include diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 6bc6157e..41c0c40a 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -29,7 +29,7 @@ #include -#include +#include #include #include #include diff --git a/src/cmd/releases.c b/src/cmd/releases.c index 3c631616..9733fdb3 100644 --- a/src/cmd/releases.c +++ b/src/cmd/releases.c @@ -29,7 +29,7 @@ #include -#include +#include #include #include diff --git a/src/cmd/repos.c b/src/cmd/repos.c index 0be8cd28..00be6624 100644 --- a/src/cmd/repos.c +++ b/src/cmd/repos.c @@ -29,7 +29,7 @@ #include -#include +#include #include #ifdef HAVE_GETOPT_H diff --git a/src/cmd/snippets.c b/src/cmd/snippets.c index 09bf655f..df3a8ce0 100644 --- a/src/cmd/snippets.c +++ b/src/cmd/snippets.c @@ -29,7 +29,7 @@ #include -#include +#include #include #ifdef HAVE_GETOPT_H diff --git a/src/cmd/status.c b/src/cmd/status.c index 3fbf49e9..e398196e 100644 --- a/src/cmd/status.c +++ b/src/cmd/status.c @@ -29,7 +29,7 @@ #include -#include +#include #include #ifdef HAVE_GETOPT_H diff --git a/src/table.c b/src/cmd/table.c similarity index 99% rename from src/table.c rename to src/cmd/table.c index a274c3ce..608fe95f 100644 --- a/src/table.c +++ b/src/cmd/table.c @@ -27,7 +27,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include #include #include diff --git a/src/forks.c b/src/forks.c index 745c5702..035de210 100644 --- a/src/forks.c +++ b/src/forks.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include int gcli_get_forks(gcli_ctx *ctx, char const *owner, char const *repo, diff --git a/src/github/checks.c b/src/github/checks.c index bfaab5dd..765eb8cc 100644 --- a/src/github/checks.c +++ b/src/github/checks.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include diff --git a/src/github/gists.c b/src/github/gists.c index 890c8904..de8f5221 100644 --- a/src/github/gists.c +++ b/src/github/gists.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index a5f55899..3c1aa97f 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/gitlab/snippets.c b/src/gitlab/snippets.c index 6175d8d4..b8ead61e 100644 --- a/src/gitlab/snippets.c +++ b/src/gitlab/snippets.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/issues.c b/src/issues.c index 8f6ec767..bb5e9765 100644 --- a/src/issues.c +++ b/src/issues.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include void diff --git a/src/labels.c b/src/labels.c index 0bf724b5..477a3928 100644 --- a/src/labels.c +++ b/src/labels.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include int gcli_get_labels(gcli_ctx *ctx, char const *owner, char const *reponame, diff --git a/src/milestones.c b/src/milestones.c index 529976e3..57649483 100644 --- a/src/milestones.c +++ b/src/milestones.c @@ -29,7 +29,7 @@ #include #include -#include +#include int gcli_get_milestones(gcli_ctx *ctx, char const *const owner, diff --git a/src/pulls.c b/src/pulls.c index 3e91fe93..7d45ccfe 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include void diff --git a/src/releases.c b/src/releases.c index 70fa08c6..542180cf 100644 --- a/src/releases.c +++ b/src/releases.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/repos.c b/src/repos.c index 33670917..a6d0773d 100644 --- a/src/repos.c +++ b/src/repos.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include diff --git a/src/sshkeys.c b/src/sshkeys.c index e535678e..945d929d 100644 --- a/src/sshkeys.c +++ b/src/sshkeys.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include int gcli_sshkeys_get_keys(gcli_ctx *ctx, gcli_sshkey_list *out) From 0154b9d536ba601f246a78efbb3d9fa09ee48650 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Wed, 16 Aug 2023 23:38:26 +0200 Subject: [PATCH 110/236] Remove context passing to table calls --- Makefile.am | 2 +- include/gcli/{ => cmd}/colour.h | 14 +++++----- include/gcli/cmd/table.h | 4 +-- src/{ => cmd}/colour.c | 34 +++++++++++++------------ src/cmd/table.c | 45 ++++++++++++--------------------- src/comments.c | 6 +++-- src/forks.c | 8 +++--- src/github/checks.c | 8 +++--- src/github/gists.c | 13 ++++++---- src/gitlab/pipelines.c | 16 ++++++++---- src/gitlab/snippets.c | 7 +++-- src/issues.c | 12 ++++++--- src/labels.c | 6 ++--- src/milestones.c | 6 +++-- src/pulls.c | 22 +++++++++------- src/releases.c | 7 +++-- src/repos.c | 8 ++++-- src/review.c | 12 +++++---- src/sshkeys.c | 5 +++- 19 files changed, 132 insertions(+), 103 deletions(-) rename include/gcli/{ => cmd}/colour.h (82%) rename src/{ => cmd}/colour.c (86%) diff --git a/Makefile.am b/Makefile.am index 039cb4d5..45f0e57b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -58,6 +58,7 @@ dist_man_MANS = \ gcli_SOURCES = \ include/gcli/cmd/cmd.h src/cmd/cmd.c \ + include/gcli/cmd/colour.h src/cmd/colour.c \ include/gcli/cmd/table.h src/cmd/table.c \ src/cmd/api.c \ src/cmd/ci.c \ @@ -125,7 +126,6 @@ include_HEADERS = \ libgcli_la_SOURCES = \ include/gcli/ctx.h src/ctx.c \ include/gcli/gcli.h src/gcli.c \ - src/colour.c include/gcli/colour.h \ src/comments.c include/gcli/comments.h \ src/config.c include/gcli/config.h \ src/curl.c include/gcli/curl.h \ diff --git a/include/gcli/colour.h b/include/gcli/cmd/colour.h similarity index 82% rename from include/gcli/colour.h rename to include/gcli/cmd/colour.h index 9444b3a1..5c7d131b 100644 --- a/include/gcli/colour.h +++ b/include/gcli/cmd/colour.h @@ -55,12 +55,12 @@ enum { GCLI_COLOR_DEFAULT, }; -char const *gcli_setcolour256(gcli_ctx *ctx, uint32_t colourcode); -char const *gcli_resetcolour(gcli_ctx *ctx); -char const *gcli_setcolour(gcli_ctx *ctx, int colour); -char const *gcli_state_colour_sv(gcli_ctx *ctx, sn_sv const state); -char const *gcli_state_colour_str(gcli_ctx *ctx, char const *it); -char const *gcli_setbold(gcli_ctx *ctx); -char const *gcli_resetbold(gcli_ctx *ctx); +char const *gcli_setcolour256(uint32_t colourcode); +char const *gcli_resetcolour(void); +char const *gcli_setcolour(int colour); +char const *gcli_state_colour_sv(sn_sv const state); +char const *gcli_state_colour_str(char const *it); +char const *gcli_setbold(void); +char const *gcli_resetbold(void); #endif /* COLOR_H */ diff --git a/include/gcli/cmd/table.h b/include/gcli/cmd/table.h index d29532a4..347bc984 100644 --- a/include/gcli/cmd/table.h +++ b/include/gcli/cmd/table.h @@ -80,7 +80,7 @@ struct gcli_tblcoldef { }; /* Init a table printer */ -gcli_tbl gcli_tbl_begin(gcli_ctx *ctx, gcli_tblcoldef const *cols, +gcli_tbl gcli_tbl_begin(gcli_tblcoldef const *cols, size_t cols_size); /* Print the table contents and free all the resources allocated in @@ -90,7 +90,7 @@ void gcli_tbl_end(gcli_tbl table); /* Add a single to an initialized table */ int gcli_tbl_add_row(gcli_tbl table, ...); -gcli_dict gcli_dict_begin(gcli_ctx *ctx); +gcli_dict gcli_dict_begin(void); int gcli_dict_add(gcli_dict list, char const *key, diff --git a/src/colour.c b/src/cmd/colour.c similarity index 86% rename from src/colour.c rename to src/cmd/colour.c index f0a07e01..836a54ec 100644 --- a/src/colour.c +++ b/src/cmd/colour.c @@ -27,7 +27,9 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include +#include + #include #include @@ -64,12 +66,12 @@ colour_cache_insert(uint32_t const code, char *sequence) } char const * -gcli_setcolour256(struct gcli_ctx *ctx, uint32_t const code) +gcli_setcolour256(uint32_t const code) { char *result = NULL; char const *oldresult = NULL; - if (!gcli_config_have_colours(ctx)) + if (!gcli_config_have_colours(g_clictx)) return ""; if (colour_table_size == 0) @@ -90,18 +92,18 @@ gcli_setcolour256(struct gcli_ctx *ctx, uint32_t const code) } const char * -gcli_resetcolour(gcli_ctx *ctx) +gcli_resetcolour(void) { - if (!gcli_config_have_colours(ctx)) + if (!gcli_config_have_colours(g_clictx)) return ""; return "\033[m"; } const char * -gcli_setcolour(gcli_ctx *ctx, int code) +gcli_setcolour(int code) { - if (!gcli_config_have_colours(ctx)) + if (!gcli_config_have_colours(g_clictx)) return ""; switch (code) { @@ -121,28 +123,28 @@ gcli_setcolour(gcli_ctx *ctx, int code) } char const * -gcli_setbold(gcli_ctx *ctx) +gcli_setbold(void) { - if (!gcli_config_have_colours(ctx)) + if (!gcli_config_have_colours(g_clictx)) return ""; else return "\033[1m"; } char const * -gcli_resetbold(gcli_ctx *ctx) +gcli_resetbold(void) { - if (!gcli_config_have_colours(ctx)) + if (!gcli_config_have_colours(g_clictx)) return ""; else return "\033[22m"; } char const * -gcli_state_colour_str(gcli_ctx *ctx, char const *it) +gcli_state_colour_str(char const *it) { if (it) - return gcli_state_colour_sv(ctx, SV((char *)it)); + return gcli_state_colour_sv(SV((char *)it)); else return ""; } @@ -166,14 +168,14 @@ static const struct { char const *name; int code; } }; char const * -gcli_state_colour_sv(gcli_ctx *ctx, sn_sv const state) +gcli_state_colour_sv(sn_sv const state) { if (!sn_sv_null(state)) { for (size_t i = 0; i < ARRAY_SIZE(state_colour_table); ++i) { if (sn_sv_has_prefix(state, state_colour_table[i].name)) - return gcli_setcolour(ctx, state_colour_table[i].code); + return gcli_setcolour(state_colour_table[i].code); } } - return gcli_setcolour(ctx, GCLI_COLOR_DEFAULT); + return gcli_setcolour(GCLI_COLOR_DEFAULT); } diff --git a/src/cmd/table.c b/src/cmd/table.c index 608fe95f..fa2f58a4 100644 --- a/src/cmd/table.c +++ b/src/cmd/table.c @@ -27,9 +27,9 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include -#include #include #include @@ -44,7 +44,6 @@ struct gcli_tblrow; /* Internal state of a table printer. We return a handle to it in * gcli_table_init. */ struct gcli_tbl { - gcli_ctx *ctx; /* pointer to the gcli context */ gcli_tblcoldef const *cols; /* user provided column definitons */ int *col_widths; /* minimum width of the columns */ size_t cols_size; /* size of above arrays */ @@ -76,8 +75,7 @@ table_pushrow(struct gcli_tbl *const table, struct gcli_tblrow row) /** Initialize the internal state structure of the table printer. */ gcli_tbl -gcli_tbl_begin(gcli_ctx *ctx, gcli_tblcoldef const *const cols, - size_t const cols_size) +gcli_tbl_begin(gcli_tblcoldef const *const cols, size_t const cols_size) { struct gcli_tbl *tbl; @@ -86,8 +84,6 @@ gcli_tbl_begin(gcli_ctx *ctx, gcli_tblcoldef const *const cols, if (!tbl) return NULL; - tbl->ctx = ctx; - /* Reserve memory for the column sizes */ tbl->col_widths = calloc(sizeof(*tbl->col_widths), cols_size); if (!tbl->col_widths) { @@ -132,12 +128,12 @@ tablerow_add_cell(struct gcli_tbl *const table, int code = va_arg(*vp, int); /* don't free that! it's allocated and free'ed inside colour.c */ - row->cells[col].colour = gcli_setcolour(table->ctx, code); + row->cells[col].colour = gcli_setcolour(code); } else if (table->cols[col].flags & GCLI_TBLCOL_256COLOUR) { uint64_t hexcode = va_arg(*vp, uint64_t); /* see comment above */ - row->cells[col].colour = gcli_setcolour256(table->ctx, hexcode); + row->cells[col].colour = gcli_setcolour256(hexcode); } @@ -250,15 +246,14 @@ dump_row(struct gcli_tbl const *const table, size_t const i) /* State colour */ if (table->cols[col].flags & GCLI_TBLCOL_STATECOLOURED) - printf("%s", gcli_state_colour_str( - table->ctx, row->cells[col].text)); + printf("%s", gcli_state_colour_str(row->cells[col].text)); else if (table->cols[col].flags & (GCLI_TBLCOL_COLOUREXPL|GCLI_TBLCOL_256COLOUR)) printf("%s", row->cells[col].colour); /* Bold */ if (table->cols[col].flags & GCLI_TBLCOL_BOLD) - printf("%s", gcli_setbold(table->ctx)); + printf("%s", gcli_setbold()); /* Print cell if it is not NULL, otherwise indicate it by * printing */ @@ -269,11 +264,11 @@ dump_row(struct gcli_tbl const *const table, size_t const i) (GCLI_TBLCOL_STATECOLOURED |GCLI_TBLCOL_COLOUREXPL |GCLI_TBLCOL_256COLOUR)) - printf("%s", gcli_resetcolour(table->ctx)); + printf("%s", gcli_resetcolour()); /* Stop printing in bold */ if (table->cols[col].flags & GCLI_TBLCOL_BOLD) - printf("%s", gcli_resetbold(table->ctx)); + printf("%s", gcli_resetbold()); /* If not last column, print padding of 2 spaces */ if ((col + 1) < table->cols_size) { @@ -360,11 +355,9 @@ struct gcli_dict { /* Create a new long list printer and return a handle to it */ gcli_dict -gcli_dict_begin(gcli_ctx *ctx) +gcli_dict_begin(void) { - struct gcli_dict *d = calloc(sizeof(struct gcli_dict), 1); - d->ctx = ctx; - return d; + return calloc(sizeof(struct gcli_dict), 1); } static int @@ -489,32 +482,26 @@ gcli_dict_end(gcli_dict _list) printf("%s : ", list->entries[i].key); if (flags & GCLI_TBLCOL_BOLD) - printf("%s", gcli_setbold(list->ctx)); + printf("%s", gcli_setbold()); if (flags & GCLI_TBLCOL_COLOUREXPL) - printf("%s", gcli_setcolour( - list->ctx, - list->entries[i].colour_args)); + printf("%s", gcli_setcolour(list->entries[i].colour_args)); if (flags & GCLI_TBLCOL_STATECOLOURED) - printf("%s", gcli_state_colour_str( - list->ctx, - list->entries[i].value)); + printf("%s", gcli_state_colour_str(list->entries[i].value)); if (flags & GCLI_TBLCOL_256COLOUR) - printf("%s", gcli_setcolour256( - list->ctx, - list->entries[i].colour_args)); + printf("%s", gcli_setcolour256(list->entries[i].colour_args)); puts(list->entries[i].value); if (flags & (GCLI_TBLCOL_COLOUREXPL |GCLI_TBLCOL_STATECOLOURED |GCLI_TBLCOL_256COLOUR)) - printf("%s", gcli_resetcolour(list->ctx)); + printf("%s", gcli_resetcolour()); if (flags & GCLI_TBLCOL_BOLD) - printf("%s", gcli_resetbold(list->ctx)); + printf("%s", gcli_resetbold()); } gcli_dict_free(list); diff --git a/src/comments.c b/src/comments.c index cf8c6b6b..93ff9aa5 100644 --- a/src/comments.c +++ b/src/comments.c @@ -27,7 +27,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include + #include #include #include @@ -58,10 +59,11 @@ gcli_comment_list_free(gcli_comment_list *list) void gcli_print_comment_list(gcli_ctx *ctx, gcli_comment_list const *const list) { + (void) ctx; for (size_t i = 0; i < list->comments_size; ++i) { printf("AUTHOR : %s%s%s\n" "DATE : %s\n", - gcli_setbold(ctx), list->comments[i].author, gcli_resetbold(ctx), + gcli_setbold(), list->comments[i].author, gcli_resetbold(), list->comments[i].date); pretty_print(list->comments[i].body, 9, 80, stdout); putchar('\n'); diff --git a/src/forks.c b/src/forks.c index 035de210..efeb8ef5 100644 --- a/src/forks.c +++ b/src/forks.c @@ -27,11 +27,11 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include +#include #include #include #include -#include int gcli_get_forks(gcli_ctx *ctx, char const *owner, char const *repo, @@ -53,6 +53,8 @@ gcli_print_forks(gcli_ctx *ctx, enum gcli_output_flags const flags, { .name = "FULLNAME", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, }; + (void) ctx; + if (list->forks_size == 0) { puts("No forks"); return; @@ -64,7 +66,7 @@ gcli_print_forks(gcli_ctx *ctx, enum gcli_output_flags const flags, else n = max; - table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not initialize table"); diff --git a/src/github/checks.c b/src/github/checks.c index 765eb8cc..670836fb 100644 --- a/src/github/checks.c +++ b/src/github/checks.c @@ -29,13 +29,13 @@ #include -#include +#include +#include #include #include #include #include #include -#include #include @@ -91,13 +91,15 @@ github_print_checks(gcli_ctx *ctx, gcli_github_checks const *const list) { .name = "NAME", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, }; + (void) ctx; + if (!list->checks_size) { fprintf(stderr, "No checks\n"); return; } - table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not init table"); diff --git a/src/github/gists.c b/src/github/gists.c index de8f5221..ad30b6d3 100644 --- a/src/github/gists.c +++ b/src/github/gists.c @@ -27,12 +27,12 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include +#include #include #include #include #include -#include #include @@ -125,6 +125,7 @@ static void print_gist(gcli_ctx *ctx, enum gcli_output_flags const flags, gcli_gist const *const gist) { + (void) ctx; (void) flags; printf(" ID : %s"SV_FMT"%s\n" @@ -133,8 +134,8 @@ print_gist(gcli_ctx *ctx, enum gcli_output_flags const flags, " DATE : "SV_FMT"\n" " URL : "SV_FMT"\n" " PULL : "SV_FMT"\n", - gcli_setcolour(ctx, GCLI_COLOR_YELLOW), SV_ARGS(gist->id), gcli_resetcolour(ctx), - gcli_setbold(ctx), SV_ARGS(gist->owner), gcli_resetbold(ctx), + gcli_setcolour(GCLI_COLOR_YELLOW), SV_ARGS(gist->id), gcli_resetcolour(), + gcli_setbold(), SV_ARGS(gist->owner), gcli_resetbold(), SV_ARGS(gist->description), SV_ARGS(gist->date), SV_ARGS(gist->url), @@ -182,12 +183,14 @@ gcli_print_gists_short(gcli_ctx *ctx, enum gcli_output_flags const flags, { .name = "DESCRIPTION", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, }; + (void) ctx; + if (max < 0 || (size_t)(max) > list->gists_size) n = list->gists_size; else n = max; - table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not init table"); diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index 3c1aa97f..2a4bce4f 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -27,11 +27,11 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include +#include #include #include #include -#include #include #include @@ -90,12 +90,14 @@ gitlab_print_pipelines(gcli_ctx *ctx, gitlab_pipeline_list const *const list) { .name = "REF", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, }; + (void) ctx; + if (!list->pipelines_size) { printf("No pipelines\n"); return; } - table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not init table"); @@ -189,12 +191,14 @@ gitlab_print_jobs(gcli_ctx *ctx, gitlab_job_list const *const list) { .name = "REF", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, }; + (void) ctx; + if (!list->jobs_size) { printf("No jobs\n"); return; } - table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not initialize table"); @@ -292,7 +296,9 @@ gitlab_print_job_status(gcli_ctx *ctx, gitlab_job const *const job) { gcli_dict printer; - printer = gcli_dict_begin(ctx); + (void) ctx; + + printer = gcli_dict_begin(); gcli_dict_add(printer, "ID", 0, 0, "%ld", job->id); gcli_dict_add_string(printer, "STATUS", GCLI_TBLCOL_STATECOLOURED, 0, job->status); diff --git a/src/gitlab/snippets.c b/src/gitlab/snippets.c index b8ead61e..22d75f0e 100644 --- a/src/gitlab/snippets.c +++ b/src/gitlab/snippets.c @@ -82,9 +82,10 @@ gcli_print_snippet(gcli_ctx *ctx, enum gcli_output_flags const flags, { gcli_dict dict; + (void) ctx; (void) flags; - dict = gcli_dict_begin(ctx); + dict = gcli_dict_begin(); gcli_dict_add(dict, "ID", 0, 0, "%d", it->id); gcli_dict_add_string(dict, "TITLE", 0, 0, it->title); @@ -132,6 +133,8 @@ gcli_print_snippets_short(gcli_ctx *ctx, enum gcli_output_flags const flags, { .name = "TITLE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, }; + (void) ctx; + /* Determine number of items to print */ if (max < 0 || (size_t)(max) > list->snippets_size) n = list->snippets_size; @@ -139,7 +142,7 @@ gcli_print_snippets_short(gcli_ctx *ctx, enum gcli_output_flags const flags, n = max; /* Fill table */ - table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not init table"); diff --git a/src/issues.c b/src/issues.c index bb5e9765..cb2d772c 100644 --- a/src/issues.c +++ b/src/issues.c @@ -27,13 +27,13 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include +#include #include #include #include #include #include -#include #include void @@ -85,12 +85,14 @@ gcli_print_issues_table(gcli_ctx *ctx, enum gcli_output_flags const flags, { .name = "TITLE", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, }; + (void) ctx; + if (list->issues_size == 0) { puts("No issues"); return; } - table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); if (!table) errx(1, "could not init table printer"); @@ -140,7 +142,9 @@ gcli_issue_print_summary(gcli_ctx *ctx, gcli_issue const *const it) { gcli_dict dict; - dict = gcli_dict_begin(ctx); + (void) ctx; + + dict = gcli_dict_begin(); gcli_dict_add(dict, "NAME", 0, 0, "%d", it->number); gcli_dict_add(dict, "TITLE", 0, 0, SV_FMT, SV_ARGS(it->title)); diff --git a/src/labels.c b/src/labels.c index 477a3928..45a75ec6 100644 --- a/src/labels.c +++ b/src/labels.c @@ -27,11 +27,11 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include +#include #include #include #include -#include int gcli_get_labels(gcli_ctx *ctx, char const *owner, char const *reponame, @@ -78,7 +78,7 @@ gcli_print_labels(gcli_ctx *ctx, gcli_label_list const *const list, n = max; /* Fill table */ - table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not init table"); diff --git a/src/milestones.c b/src/milestones.c index 57649483..2b0f6411 100644 --- a/src/milestones.c +++ b/src/milestones.c @@ -73,12 +73,14 @@ gcli_print_milestones(gcli_ctx *ctx, gcli_milestone_list const *const list, { .name = "TITLE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, }; + (void) ctx; + if (!list->milestones_size) { puts("No milestones"); return; } - tbl = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); + tbl = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); if (!tbl) errx(1, "error: could not init table printer"); @@ -104,7 +106,7 @@ gcli_print_milestone(gcli_ctx *ctx, gcli_milestone const *const milestone) gcli_dict dict; uint32_t const quirks = gcli_forge(ctx)->milestone_quirks; - dict = gcli_dict_begin(ctx); + dict = gcli_dict_begin(); gcli_dict_add(dict, "ID", 0, 0, "%d", milestone->id); gcli_dict_add_string(dict, "TITLE", 0, 0, milestone->title); gcli_dict_add_string(dict, "STATE", GCLI_TBLCOL_STATECOLOURED, 0, milestone->state); diff --git a/src/pulls.c b/src/pulls.c index 7d45ccfe..e85dbe84 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -27,7 +27,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include +#include #include #include #include @@ -36,7 +37,6 @@ #include #include #include -#include #include void @@ -74,6 +74,8 @@ gcli_print_pulls_table(gcli_ctx *ctx, enum gcli_output_flags const flags, { .name = "TITLE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, }; + (void) ctx; + if (list->pulls_size == 0) { puts("No Pull Requests"); return; @@ -86,7 +88,7 @@ gcli_print_pulls_table(gcli_ctx *ctx, enum gcli_output_flags const flags, n = max; /* Fill the table */ - table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: cannot init table"); @@ -128,7 +130,7 @@ gcli_pull_print_status(gcli_ctx *ctx, gcli_pull const *const it) gcli_dict dict; gcli_forge_descriptor const *const forge = gcli_forge(ctx); - dict = gcli_dict_begin(ctx); + dict = gcli_dict_begin(); gcli_dict_add(dict, "NUMBER", 0, 0, "%d", it->number); gcli_dict_add_string(dict, "TITLE", 0, 0, it->title); @@ -145,12 +147,12 @@ gcli_pull_print_status(gcli_ctx *ctx, gcli_pull const *const it) if (!(forge->pull_summary_quirks & GCLI_PRS_QUIRK_ADDDEL)) /* FIXME: move printing colours into the dictionary printer? */ gcli_dict_add(dict, "ADD:DEL", 0, 0, "%s%d%s:%s%d%s", - gcli_setcolour(ctx, GCLI_COLOR_GREEN), + gcli_setcolour(GCLI_COLOR_GREEN), it->additions, - gcli_resetcolour(ctx), - gcli_setcolour(ctx, GCLI_COLOR_RED), + gcli_resetcolour(), + gcli_setcolour(GCLI_COLOR_RED), it->deletions, - gcli_resetcolour(ctx)); + gcli_resetcolour()); if (!(forge->pull_summary_quirks & GCLI_PRS_QUIRK_COMMITS)) gcli_dict_add(dict, "COMMITS", 0, 0, "%d", it->commits); @@ -212,12 +214,14 @@ gcli_print_commits_table(gcli_ctx *ctx, gcli_commit_list const *const list) { .name = "MESSAGE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, }; + (void) ctx; + if (list->commits_size == 0) { puts("No commits"); return; } - table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not initialize table"); diff --git a/src/releases.c b/src/releases.c index 542180cf..31a59de1 100644 --- a/src/releases.c +++ b/src/releases.c @@ -48,9 +48,10 @@ gcli_print_release(gcli_ctx *ctx, enum gcli_output_flags const flags, { gcli_dict dict; + (void) ctx; (void) flags; - dict = gcli_dict_begin(ctx); + dict = gcli_dict_begin(); gcli_dict_add(dict, "ID", 0, 0, SV_FMT, SV_ARGS(it->id)); gcli_dict_add(dict, "NAME", 0, 0, SV_FMT, SV_ARGS(it->name)); @@ -112,12 +113,14 @@ gcli_print_releases_short(gcli_ctx *ctx, enum gcli_output_flags const flags, { .name = "NAME", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, }; + (void) ctx; + if (max < 0 || (size_t)(max) > list->releases_size) n = list->releases_size; else n = max; - table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not init table"); diff --git a/src/repos.c b/src/repos.c index a6d0773d..b6058c98 100644 --- a/src/repos.c +++ b/src/repos.c @@ -55,6 +55,8 @@ gcli_print_repos_table(gcli_ctx *ctx, enum gcli_output_flags const flags, { .name = "FULLNAME", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, }; + (void) ctx; + if (list->repos_size == 0) { puts("No repos"); return; @@ -67,7 +69,7 @@ gcli_print_repos_table(gcli_ctx *ctx, enum gcli_output_flags const flags, n = max; /* init table */ - table = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); if (!table) errx(1, "error: could not init table"); @@ -97,7 +99,9 @@ gcli_repo_print(gcli_ctx *ctx, gcli_repo const *it) { gcli_dict dict; - dict = gcli_dict_begin(ctx); + (void) ctx; + + dict = gcli_dict_begin(); gcli_dict_add(dict, "ID", 0, 0, "%d", it->id); gcli_dict_add(dict, "FULL NAME", 0, 0, SV_FMT, SV_ARGS(it->full_name)); gcli_dict_add(dict, "NAME", 0, 0, SV_FMT, SV_ARGS(it->name)); diff --git a/src/review.c b/src/review.c index b977762b..aa5c96bb 100644 --- a/src/review.c +++ b/src/review.c @@ -27,7 +27,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include #include #include #include @@ -43,17 +43,19 @@ void gcli_review_print_review_table(gcli_ctx *ctx, gcli_pr_review_list const *const list) { + (void) ctx; + for (size_t i = 0; i < list->reviews_size; ++i) { if (list->reviews[i].state) { printf(" %s%s%s - %s - %s%s%s\n", - gcli_setbold(ctx), list->reviews[i].author, gcli_resetbold(ctx), + gcli_setbold(), list->reviews[i].author, gcli_resetbold(), list->reviews[i].date, - gcli_state_colour_str(ctx, list->reviews[i].state), + gcli_state_colour_str(list->reviews[i].state), list->reviews[i].state, - gcli_resetcolour(ctx)); + gcli_resetcolour()); } else { printf(" %s%s%s - %s\n", - gcli_setbold(ctx), list->reviews[i].author, gcli_resetbold(ctx), + gcli_setbold(), list->reviews[i].author, gcli_resetbold(), list->reviews[i].date); } diff --git a/src/sshkeys.c b/src/sshkeys.c index 945d929d..61380352 100644 --- a/src/sshkeys.c +++ b/src/sshkeys.c @@ -52,12 +52,15 @@ gcli_sshkeys_print_keys(gcli_ctx *ctx, gcli_sshkey_list const *list) { .name = "TITLE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, }; + (void) ctx; + + if (list->keys_size == 0) { printf("No SSH keys\n"); return; } - tbl = gcli_tbl_begin(ctx, cols, ARRAY_SIZE(cols)); + tbl = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); for (size_t i = 0; i < list->keys_size; ++i) { gcli_tbl_add_row(tbl, list->keys[i].id, list->keys[i].created_at, list->keys[i].title); From bc6845dba6dfb7f07030a754858f3433c451df00 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Wed, 16 Aug 2023 23:43:45 +0200 Subject: [PATCH 111/236] Move printing code for releases out of the library --- Makefile.am | 2 +- include/gcli/cmd/releases.h | 42 ++++++++++++ include/gcli/releases.h | 3 - src/cmd/releases.c | 123 +++++++++++++++++++++++++++++++++++- src/releases.c | 121 ----------------------------------- 5 files changed, 165 insertions(+), 126 deletions(-) create mode 100644 include/gcli/cmd/releases.h diff --git a/Makefile.am b/Makefile.am index 45f0e57b..e9eb4898 100644 --- a/Makefile.am +++ b/Makefile.am @@ -72,7 +72,7 @@ gcli_SOURCES = \ src/cmd/milestones.c \ src/cmd/pipelines.c \ src/cmd/pulls.c \ - src/cmd/releases.c \ + include/gcli/cmd/releases.h src/cmd/releases.c \ src/cmd/repos.c \ src/cmd/snippets.c \ src/cmd/status.c diff --git a/include/gcli/cmd/releases.h b/include/gcli/cmd/releases.h new file mode 100644 index 00000000..4a0760d0 --- /dev/null +++ b/include/gcli/cmd/releases.h @@ -0,0 +1,42 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CMD_RELEASES_H +#define GCLI_CMD_RELEASES_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +void gcli_releases_print(enum gcli_output_flags flags, + gcli_release_list const *list, int max); + +#endif /* GCLI_CMD_RELEASES_H */ diff --git a/include/gcli/releases.h b/include/gcli/releases.h index b64555b5..f79afd29 100644 --- a/include/gcli/releases.h +++ b/include/gcli/releases.h @@ -90,9 +90,6 @@ struct gcli_new_release { int gcli_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, int max, gcli_release_list *list); -void gcli_print_releases(gcli_ctx *ctx, enum gcli_output_flags flags, - gcli_release_list const *list, int max); - void gcli_free_releases(gcli_release_list *); int gcli_create_release(gcli_ctx *ctx, gcli_new_release const *); diff --git a/src/cmd/releases.c b/src/cmd/releases.c index 9733fdb3..4cd72156 100644 --- a/src/cmd/releases.c +++ b/src/cmd/releases.c @@ -30,6 +30,9 @@ #include #include +#include +#include + #include #include @@ -64,6 +67,123 @@ usage(void) copyright(); } +static void +gcli_print_release(enum gcli_output_flags const flags, + gcli_release const *const it) +{ + gcli_dict dict; + + (void) flags; + + dict = gcli_dict_begin(); + + gcli_dict_add(dict, "ID", 0, 0, SV_FMT, SV_ARGS(it->id)); + gcli_dict_add(dict, "NAME", 0, 0, SV_FMT, SV_ARGS(it->name)); + gcli_dict_add(dict, "AUTHOR", 0, 0, SV_FMT, SV_ARGS(it->author)); + gcli_dict_add(dict, "DATE", 0, 0, SV_FMT, SV_ARGS(it->date)); + gcli_dict_add_string(dict, "DRAFT", 0, 0, sn_bool_yesno(it->draft)); + gcli_dict_add_string(dict, "PRERELEASE", 0, 0, sn_bool_yesno(it->prerelease)); + gcli_dict_add_string(dict, "ASSETS", 0, 0, ""); + + /* asset urls */ + for (size_t i = 0; i < it->assets_size; ++i) { + gcli_dict_add(dict, "", 0, 0, "• %s", it->assets[i].name); + gcli_dict_add(dict, "", 0, 0, " %s", it->assets[i].url); + } + + gcli_dict_end(dict); + + /* body */ + if (it->body.length) { + putchar('\n'); + pretty_print(it->body.data, 13, 80, stdout); + } + + putchar('\n'); +} + +static void +gcli_releases_print_long(enum gcli_output_flags const flags, + gcli_release_list const *const list, int const max) +{ + int n; + + /* Determine how many items to print */ + if (max < 0 || (size_t)(max) > list->releases_size) + n = list->releases_size; + else + n = max; + + if (flags & OUTPUT_SORTED) { + for (int i = 0; i < n; ++i) + gcli_print_release(flags, &list->releases[n-i-1]); + } else { + for (int i = 0; i < n; ++i) + gcli_print_release(flags, &list->releases[i]); + } +} + +static void +gcli_releases_print_short(enum gcli_output_flags const flags, + gcli_release_list const *const list, int const max) +{ + size_t n; + gcli_tbl table; + gcli_tblcoldef cols[] = { + { .name = "ID", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, + { .name = "DATE", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, + { .name = "DRAFT", .type = GCLI_TBLCOLTYPE_BOOL, .flags = 0 }, + { .name = "PRERELEASE", .type = GCLI_TBLCOLTYPE_BOOL, .flags = 0 }, + { .name = "NAME", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, + }; + + if (max < 0 || (size_t)(max) > list->releases_size) + n = list->releases_size; + else + n = max; + + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + if (!table) + errx(1, "error: could not init table"); + + if (flags & OUTPUT_SORTED) { + for (size_t i = 0; i < n; ++i) { + gcli_tbl_add_row(table, + list->releases[n-i-1].id, + list->releases[n-i-1].date, + list->releases[n-i-1].draft, + list->releases[n-i-1].prerelease, + list->releases[n-i-1].name); + } + } else { + for (size_t i = 0; i < n; ++i) { + gcli_tbl_add_row(table, + list->releases[i].id, + list->releases[i].date, + list->releases[i].draft, + list->releases[i].prerelease, + list->releases[i].name); + } + } + + gcli_tbl_end(table); +} + +void +gcli_releases_print(enum gcli_output_flags const flags, + gcli_release_list const *const list, int const max) +{ + if (list->releases_size == 0) { + puts("No releases"); + return; + } + + if (flags & OUTPUT_LONG) + gcli_releases_print_long(flags, list, max); + else + gcli_releases_print_short(flags, list, max); +} + static void releasemsg_init(gcli_ctx *ctx, FILE *f, void *_data) { @@ -361,7 +481,8 @@ subcommand_releases(int argc, char *argv[]) if (gcli_get_releases(g_clictx, owner, repo, count, &releases) < 0) errx(1, "error: could not get releases"); - gcli_print_releases(g_clictx, flags, &releases, count); + gcli_releases_print(flags, &releases, count); + gcli_free_releases(&releases); return EXIT_SUCCESS; diff --git a/src/releases.c b/src/releases.c index 31a59de1..14403f19 100644 --- a/src/releases.c +++ b/src/releases.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -42,126 +41,6 @@ gcli_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, return gcli_forge(ctx)->get_releases(ctx, owner, repo, max, list); } -static void -gcli_print_release(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_release const *const it) -{ - gcli_dict dict; - - (void) ctx; - (void) flags; - - dict = gcli_dict_begin(); - - gcli_dict_add(dict, "ID", 0, 0, SV_FMT, SV_ARGS(it->id)); - gcli_dict_add(dict, "NAME", 0, 0, SV_FMT, SV_ARGS(it->name)); - gcli_dict_add(dict, "AUTHOR", 0, 0, SV_FMT, SV_ARGS(it->author)); - gcli_dict_add(dict, "DATE", 0, 0, SV_FMT, SV_ARGS(it->date)); - gcli_dict_add_string(dict, "DRAFT", 0, 0, sn_bool_yesno(it->draft)); - gcli_dict_add_string(dict, "PRERELEASE", 0, 0, sn_bool_yesno(it->prerelease)); - gcli_dict_add_string(dict, "ASSETS", 0, 0, ""); - - /* asset urls */ - for (size_t i = 0; i < it->assets_size; ++i) { - gcli_dict_add(dict, "", 0, 0, "• %s", it->assets[i].name); - gcli_dict_add(dict, "", 0, 0, " %s", it->assets[i].url); - } - - gcli_dict_end(dict); - - /* body */ - if (it->body.length) { - putchar('\n'); - pretty_print(it->body.data, 13, 80, stdout); - } - - putchar('\n'); -} - -static void -gcli_print_releases_long(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_release_list const *const list, int const max) -{ - int n; - - /* Determine how many items to print */ - if (max < 0 || (size_t)(max) > list->releases_size) - n = list->releases_size; - else - n = max; - - if (flags & OUTPUT_SORTED) { - for (int i = 0; i < n; ++i) - gcli_print_release(ctx, flags, &list->releases[n-i-1]); - } else { - for (int i = 0; i < n; ++i) - gcli_print_release(ctx, flags, &list->releases[i]); - } -} - -static void -gcli_print_releases_short(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_release_list const *const list, int const max) -{ - size_t n; - gcli_tbl table; - gcli_tblcoldef cols[] = { - { .name = "ID", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, - { .name = "DATE", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, - { .name = "DRAFT", .type = GCLI_TBLCOLTYPE_BOOL, .flags = 0 }, - { .name = "PRERELEASE", .type = GCLI_TBLCOLTYPE_BOOL, .flags = 0 }, - { .name = "NAME", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, - }; - - (void) ctx; - - if (max < 0 || (size_t)(max) > list->releases_size) - n = list->releases_size; - else - n = max; - - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); - if (!table) - errx(1, "error: could not init table"); - - if (flags & OUTPUT_SORTED) { - for (size_t i = 0; i < n; ++i) { - gcli_tbl_add_row(table, - list->releases[n-i-1].id, - list->releases[n-i-1].date, - list->releases[n-i-1].draft, - list->releases[n-i-1].prerelease, - list->releases[n-i-1].name); - } - } else { - for (size_t i = 0; i < n; ++i) { - gcli_tbl_add_row(table, - list->releases[i].id, - list->releases[i].date, - list->releases[i].draft, - list->releases[i].prerelease, - list->releases[i].name); - } - } - - gcli_tbl_end(table); -} - -void -gcli_print_releases(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_release_list const *const list, int const max) -{ - if (list->releases_size == 0) { - puts("No releases"); - return; - } - - if (flags & OUTPUT_LONG) - gcli_print_releases_long(ctx, flags, list, max); - else - gcli_print_releases_short(ctx, flags, list, max); -} - void gcli_free_releases(gcli_release_list *const list) { From b6b5233f6ce282ef03900172846ed69c5bb1e045 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Wed, 16 Aug 2023 23:45:22 +0200 Subject: [PATCH 112/236] Update todo --- todo.org | 1 + 1 file changed, 1 insertion(+) diff --git a/todo.org b/todo.org index 8fe232f3..d98f0c54 100644 --- a/todo.org +++ b/todo.org @@ -135,3 +135,4 @@ - [X] Put it into the context - [ ] Clean up handle on exit ** TODO Return errors from parsers +** TODO [[file:src/releases.c::gcli_release_push_asset(gcli_new_release *const release,][push_asset]] should not call errx but return an error code From 0c00e6c45b15821006da3c984aac7554f4249262 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 17 Aug 2023 00:01:16 +0200 Subject: [PATCH 113/236] Move label printing code out of library --- Makefile.am | 2 +- include/gcli/cmd/cmd.h | 2 -- include/gcli/cmd/labels.h | 43 ++++++++++++++++++++++++++++++++++ include/gcli/cmd/releases.h | 2 ++ include/gcli/labels.h | 2 -- src/cmd/gcli.c | 3 +++ src/cmd/labels.c | 46 ++++++++++++++++++++++++++++++++++--- src/labels.c | 39 ------------------------------- 8 files changed, 92 insertions(+), 47 deletions(-) create mode 100644 include/gcli/cmd/labels.h diff --git a/Makefile.am b/Makefile.am index e9eb4898..2ad32777 100644 --- a/Makefile.am +++ b/Makefile.am @@ -68,7 +68,7 @@ gcli_SOURCES = \ src/cmd/gcli.c \ src/cmd/gists.c \ src/cmd/issues.c \ - src/cmd/labels.c \ + include/gcli/cmd/labels.h src/cmd/labels.c \ src/cmd/milestones.c \ src/cmd/pipelines.c \ src/cmd/pulls.c \ diff --git a/include/gcli/cmd/cmd.h b/include/gcli/cmd/cmd.h index d04242eb..ea1a3171 100644 --- a/include/gcli/cmd/cmd.h +++ b/include/gcli/cmd/cmd.h @@ -69,11 +69,9 @@ int subcommand_config(int argc, char *argv[]); int subcommand_forks(int argc, char *argv[]); int subcommand_gists(int argc, char *argv[]); int subcommand_issues(int argc, char *argv[]); -int subcommand_labels(int argc, char *argv[]); int subcommand_milestones(int argc, char *argv[]); int subcommand_pipelines(int argc, char *argv[]); int subcommand_pulls(int argc, char *argv[]); -int subcommand_releases(int argc, char *argv[]); int subcommand_repos(int argc, char *argv[]); int subcommand_snippets(int argc, char *argv[]); int subcommand_status(int argc, char *argv[]); diff --git a/include/gcli/cmd/labels.h b/include/gcli/cmd/labels.h new file mode 100644 index 00000000..83217fac --- /dev/null +++ b/include/gcli/cmd/labels.h @@ -0,0 +1,43 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CMD_LABELS_H +#define GCLI_CMD_LABELS_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +void gcli_labels_print(gcli_label_list const *list, int max); + +int subcommand_labels(int argc, char *argv[]); + +#endif /* GCLI_CMD_LABELS_H */ diff --git a/include/gcli/cmd/releases.h b/include/gcli/cmd/releases.h index 4a0760d0..6b1c7414 100644 --- a/include/gcli/cmd/releases.h +++ b/include/gcli/cmd/releases.h @@ -39,4 +39,6 @@ void gcli_releases_print(enum gcli_output_flags flags, gcli_release_list const *list, int max); +int subcommand_releases(int argc, char *argv[]); + #endif /* GCLI_CMD_RELEASES_H */ diff --git a/include/gcli/labels.h b/include/gcli/labels.h index 2088e0ff..0a5086e2 100644 --- a/include/gcli/labels.h +++ b/include/gcli/labels.h @@ -62,8 +62,6 @@ void gcli_free_label(gcli_label *label); void gcli_free_labels(gcli_label_list *labels); -void gcli_print_labels(gcli_ctx *ctx, gcli_label_list const *list, int max); - int gcli_create_label(gcli_ctx *ctx, char const *owner, char const *repo, gcli_label *label); diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index dd5698c8..aee2785f 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -39,6 +39,9 @@ #include #include +#include +#include + #include static void usage(void); diff --git a/src/cmd/labels.c b/src/cmd/labels.c index 382b2876..98f5429b 100644 --- a/src/cmd/labels.c +++ b/src/cmd/labels.c @@ -29,9 +29,13 @@ #include -#include +#include #include +#include +#include +#include + #ifdef HAVE_GETOPT_H #include #endif @@ -57,6 +61,41 @@ usage(void) copyright(); } +void +gcli_labels_print(gcli_label_list const *const list, int const max) +{ + size_t n; + gcli_tbl table; + gcli_tblcoldef cols[] = { + { .name = "ID", .type = GCLI_TBLCOLTYPE_LONG, .flags = GCLI_TBLCOL_JUSTIFYR }, + { .name = "", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_256COLOUR|GCLI_TBLCOL_TIGHT }, + { .name = "NAME", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "DESCRIPTION", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + }; + + /* Determine number of items to print */ + if (max < 0 || (size_t)(max) > list->labels_size) + n = list->labels_size; + else + n = max; + + /* Fill table */ + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + if (!table) + errx(1, "error: could not init table"); + + for (size_t i = 0; i < n; ++i) { + gcli_tbl_add_row(table, + (long)list->labels[i].id, /* Cast is important here (#165) */ + list->labels[i].colour, + gcli_config_have_colours(g_clictx) ? " " : "", + list->labels[i].name, + list->labels[i].description); + } + + gcli_tbl_end(table); +} + static int subcommand_labels_delete(int argc, char *argv[]) { @@ -171,7 +210,7 @@ subcommand_labels_create(int argc, char *argv[]) /* only if we are not quieted */ if (!sn_quiet()) - gcli_print_labels(g_clictx, &labels, 1); + gcli_labels_print(&labels, 1); gcli_free_label(&label); @@ -249,7 +288,8 @@ subcommand_labels(int argc, char *argv[]) if (gcli_get_labels(g_clictx, owner, repo, count, &labels) < 0) errx(1, "error: could not fetch list of labels"); - gcli_print_labels(g_clictx, &labels, count); + gcli_labels_print(&labels, count); + gcli_free_labels(&labels); return EXIT_SUCCESS; diff --git a/src/labels.c b/src/labels.c index 45a75ec6..18375c7a 100644 --- a/src/labels.c +++ b/src/labels.c @@ -27,9 +27,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include #include #include @@ -58,42 +55,6 @@ gcli_free_labels(gcli_label_list *const list) list->labels_size = 0; } -void -gcli_print_labels(gcli_ctx *ctx, gcli_label_list const *const list, - int const max) -{ - size_t n; - gcli_tbl table; - gcli_tblcoldef cols[] = { - { .name = "ID", .type = GCLI_TBLCOLTYPE_LONG, .flags = GCLI_TBLCOL_JUSTIFYR }, - { .name = "", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_256COLOUR|GCLI_TBLCOL_TIGHT }, - { .name = "NAME", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "DESCRIPTION", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - }; - - /* Determine number of items to print */ - if (max < 0 || (size_t)(max) > list->labels_size) - n = list->labels_size; - else - n = max; - - /* Fill table */ - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); - if (!table) - errx(1, "error: could not init table"); - - for (size_t i = 0; i < n; ++i) { - gcli_tbl_add_row(table, - (long)list->labels[i].id, /* Cast is important here (#165) */ - list->labels[i].colour, - gcli_config_have_colours(ctx) ? " " : "", - list->labels[i].name, - list->labels[i].description); - } - - gcli_tbl_end(table); -} - int gcli_create_label(gcli_ctx *ctx, char const *owner, char const *repo, gcli_label *const label) From a8b7a34a0fc2c0ce9d67b099c09c563945d25f42 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 17 Aug 2023 00:08:48 +0200 Subject: [PATCH 114/236] Move milestones printing routines out of library --- Makefile.am | 2 +- include/gcli/cmd/cmd.h | 1 - include/gcli/cmd/milestones.h | 46 ++++++++++++++++++++ include/gcli/milestones.h | 5 --- src/cmd/gcli.c | 1 + src/cmd/milestones.c | 79 +++++++++++++++++++++++++++++++++-- src/milestones.c | 73 -------------------------------- 7 files changed, 124 insertions(+), 83 deletions(-) create mode 100644 include/gcli/cmd/milestones.h diff --git a/Makefile.am b/Makefile.am index 2ad32777..bd310bb2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -69,7 +69,7 @@ gcli_SOURCES = \ src/cmd/gists.c \ src/cmd/issues.c \ include/gcli/cmd/labels.h src/cmd/labels.c \ - src/cmd/milestones.c \ + include/gcli/cmd/milestones.h src/cmd/milestones.c \ src/cmd/pipelines.c \ src/cmd/pulls.c \ include/gcli/cmd/releases.h src/cmd/releases.c \ diff --git a/include/gcli/cmd/cmd.h b/include/gcli/cmd/cmd.h index ea1a3171..e43ff45c 100644 --- a/include/gcli/cmd/cmd.h +++ b/include/gcli/cmd/cmd.h @@ -69,7 +69,6 @@ int subcommand_config(int argc, char *argv[]); int subcommand_forks(int argc, char *argv[]); int subcommand_gists(int argc, char *argv[]); int subcommand_issues(int argc, char *argv[]); -int subcommand_milestones(int argc, char *argv[]); int subcommand_pipelines(int argc, char *argv[]); int subcommand_pulls(int argc, char *argv[]); int subcommand_repos(int argc, char *argv[]); diff --git a/include/gcli/cmd/milestones.h b/include/gcli/cmd/milestones.h new file mode 100644 index 00000000..1ebd03f5 --- /dev/null +++ b/include/gcli/cmd/milestones.h @@ -0,0 +1,46 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CMD_MILESTONES_H +#define GCLI_CMD_MILESTONES_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +void gcli_print_milestones(gcli_ctx *ctx, gcli_milestone_list const *it, + int max); + +void gcli_print_milestone(gcli_ctx *ctx, gcli_milestone const *it); + +int subcommand_milestones(int argc, char *argv[]); + +#endif /* GCLI_CMD_MILESTONES_H */ diff --git a/include/gcli/milestones.h b/include/gcli/milestones.h index 865ae0f8..55ae3c01 100644 --- a/include/gcli/milestones.h +++ b/include/gcli/milestones.h @@ -86,11 +86,6 @@ int gcli_create_milestone(gcli_ctx *ctx, int gcli_delete_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int milestone); -void gcli_print_milestones(gcli_ctx *ctx, gcli_milestone_list const *it, - int max); - -void gcli_print_milestone(gcli_ctx *ctx, gcli_milestone const *it); - void gcli_free_milestone(gcli_milestone *it); void gcli_free_milestones(gcli_milestone_list *it); diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index aee2785f..00487efe 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -40,6 +40,7 @@ #include #include +#include #include #include diff --git a/src/cmd/milestones.c b/src/cmd/milestones.c index fcd26f48..9dad318b 100644 --- a/src/cmd/milestones.c +++ b/src/cmd/milestones.c @@ -30,6 +30,9 @@ #include #include +#include + +#include #include #ifdef HAVE_GETOPT_H @@ -59,6 +62,75 @@ usage(void) copyright(); } +void +gcli_print_milestones(gcli_milestone_list const *const list, int max) +{ + size_t n; + gcli_tbl tbl; + gcli_tblcoldef cols[] = { + { .name = "ID", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, + { .name = "STATE", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_STATECOLOURED }, + { .name = "CREATED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "TITLE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + }; + + if (!list->milestones_size) { + puts("No milestones"); + return; + } + + tbl = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + if (!tbl) + errx(1, "error: could not init table printer"); + + if (max < 0 || (size_t)(max) > list->milestones_size) + n = list->milestones_size; + else + n = max; + + for (size_t i = 0; i < n; ++i) { + gcli_tbl_add_row(tbl, + list->milestones[i].id, + list->milestones[i].state, + list->milestones[i].created_at, + list->milestones[i].title); + } + + gcli_tbl_end(tbl); +} + +void +gcli_print_milestone(gcli_milestone const *const milestone) +{ + gcli_dict dict; + uint32_t const quirks = gcli_forge(g_clictx)->milestone_quirks; + + dict = gcli_dict_begin(); + gcli_dict_add(dict, "ID", 0, 0, "%d", milestone->id); + gcli_dict_add_string(dict, "TITLE", 0, 0, milestone->title); + gcli_dict_add_string(dict, "STATE", GCLI_TBLCOL_STATECOLOURED, 0, milestone->state); + gcli_dict_add_string(dict, "CREATED", 0, 0, milestone->created_at); + gcli_dict_add_string(dict, "UPDATED", 0, 0, milestone->created_at); + + if ((quirks & GCLI_MILESTONE_QUIRKS_DUEDATE) == 0) + gcli_dict_add_string(dict, "DUE", 0, 0, milestone->due_date); + + if ((quirks & GCLI_MILESTONE_QUIRKS_EXPIRED) == 0) + gcli_dict_add_string(dict, "EXPIRED", 0, 0, sn_bool_yesno(milestone->expired)); + + if ((quirks & GCLI_MILESTONE_QUIRKS_NISSUES) == 0) { + gcli_dict_add(dict, "OPEN ISSUES", 0, 0, "%d", milestone->open_issues); + gcli_dict_add(dict, "CLOSED ISSUES", 0, 0, "%d", milestone->closed_issues); + } + + gcli_dict_end(dict); + + if (milestone->description && strlen(milestone->description)) { + printf("\nDESCRIPTION:\n"); + pretty_print(milestone->description, 4, 80, stdout); + } +} + static int handle_milestone_actions(int argc, char *argv[], char const *const owner, char const *const repo, @@ -207,7 +279,8 @@ subcommand_milestones(int argc, char *argv[]) if (rc < 0) errx(1, "error: cannot get list of milestones"); - gcli_print_milestones(g_clictx, &list, max); + gcli_print_milestones(&list, max); + gcli_free_milestones(&list); return 0; @@ -266,7 +339,7 @@ handle_milestone_actions(int argc, char *argv[], ensure_milestone(owner, repo, milestone_id, &fetched_milestone, &milestone); - gcli_print_milestone(g_clictx, &milestone); + gcli_print_milestone(&milestone); rc = gcli_milestone_get_issues(g_clictx, owner, repo, milestone_id, &issues); @@ -300,7 +373,7 @@ handle_milestone_actions(int argc, char *argv[], &fetched_milestone, &milestone); /* Print meta */ - gcli_print_milestone(g_clictx, &milestone); + gcli_print_milestone(&milestone); } else if (strcmp(action, "delete") == 0) { /* Delete the milestone */ diff --git a/src/milestones.c b/src/milestones.c index 2b0f6411..2b09fb15 100644 --- a/src/milestones.c +++ b/src/milestones.c @@ -29,7 +29,6 @@ #include #include -#include int gcli_get_milestones(gcli_ctx *ctx, char const *const owner, @@ -60,78 +59,6 @@ gcli_delete_milestone(gcli_ctx *ctx, char const *const owner, return gcli_forge(ctx)->delete_milestone(ctx, owner, repo, milestone); } -void -gcli_print_milestones(gcli_ctx *ctx, gcli_milestone_list const *const list, - int max) -{ - size_t n; - gcli_tbl tbl; - gcli_tblcoldef cols[] = { - { .name = "ID", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, - { .name = "STATE", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_STATECOLOURED }, - { .name = "CREATED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "TITLE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - }; - - (void) ctx; - - if (!list->milestones_size) { - puts("No milestones"); - return; - } - - tbl = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); - if (!tbl) - errx(1, "error: could not init table printer"); - - if (max < 0 || (size_t)(max) > list->milestones_size) - n = list->milestones_size; - else - n = max; - - for (size_t i = 0; i < n; ++i) { - gcli_tbl_add_row(tbl, - list->milestones[i].id, - list->milestones[i].state, - list->milestones[i].created_at, - list->milestones[i].title); - } - - gcli_tbl_end(tbl); -} - -void -gcli_print_milestone(gcli_ctx *ctx, gcli_milestone const *const milestone) -{ - gcli_dict dict; - uint32_t const quirks = gcli_forge(ctx)->milestone_quirks; - - dict = gcli_dict_begin(); - gcli_dict_add(dict, "ID", 0, 0, "%d", milestone->id); - gcli_dict_add_string(dict, "TITLE", 0, 0, milestone->title); - gcli_dict_add_string(dict, "STATE", GCLI_TBLCOL_STATECOLOURED, 0, milestone->state); - gcli_dict_add_string(dict, "CREATED", 0, 0, milestone->created_at); - gcli_dict_add_string(dict, "UPDATED", 0, 0, milestone->created_at); - - if ((quirks & GCLI_MILESTONE_QUIRKS_DUEDATE) == 0) - gcli_dict_add_string(dict, "DUE", 0, 0, milestone->due_date); - - if ((quirks & GCLI_MILESTONE_QUIRKS_EXPIRED) == 0) - gcli_dict_add_string(dict, "EXPIRED", 0, 0, sn_bool_yesno(milestone->expired)); - - if ((quirks & GCLI_MILESTONE_QUIRKS_NISSUES) == 0) { - gcli_dict_add(dict, "OPEN ISSUES", 0, 0, "%d", milestone->open_issues); - gcli_dict_add(dict, "CLOSED ISSUES", 0, 0, "%d", milestone->closed_issues); - } - - gcli_dict_end(dict); - - if (milestone->description && strlen(milestone->description)) { - printf("\nDESCRIPTION:\n"); - pretty_print(milestone->description, 4, 80, stdout); - } -} - void gcli_free_milestone(gcli_milestone *const it) { From e21b6e5b6e99bbc1f6e076aebf1ec353bb1b61a3 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 17 Aug 2023 01:43:14 +0200 Subject: [PATCH 115/236] Move issue printing routines out of library --- Makefile.am | 2 +- include/gcli/cmd/cmd.h | 1 - include/gcli/cmd/issues.h | 48 ++++++++++++++++ include/gcli/issues.h | 6 -- src/cmd/gcli.c | 1 + src/cmd/issues.c | 116 +++++++++++++++++++++++++++++++++++++- src/cmd/milestones.c | 5 +- src/issues.c | 114 ------------------------------------- 8 files changed, 166 insertions(+), 127 deletions(-) create mode 100644 include/gcli/cmd/issues.h diff --git a/Makefile.am b/Makefile.am index bd310bb2..a68ee305 100644 --- a/Makefile.am +++ b/Makefile.am @@ -67,7 +67,7 @@ gcli_SOURCES = \ src/cmd/forks.c \ src/cmd/gcli.c \ src/cmd/gists.c \ - src/cmd/issues.c \ + include/gcli/cmd/issues.h src/cmd/issues.c \ include/gcli/cmd/labels.h src/cmd/labels.c \ include/gcli/cmd/milestones.h src/cmd/milestones.c \ src/cmd/pipelines.c \ diff --git a/include/gcli/cmd/cmd.h b/include/gcli/cmd/cmd.h index e43ff45c..1061e42f 100644 --- a/include/gcli/cmd/cmd.h +++ b/include/gcli/cmd/cmd.h @@ -68,7 +68,6 @@ int subcommand_comment(int argc, char *argv[]); int subcommand_config(int argc, char *argv[]); int subcommand_forks(int argc, char *argv[]); int subcommand_gists(int argc, char *argv[]); -int subcommand_issues(int argc, char *argv[]); int subcommand_pipelines(int argc, char *argv[]); int subcommand_pulls(int argc, char *argv[]); int subcommand_repos(int argc, char *argv[]); diff --git a/include/gcli/cmd/issues.h b/include/gcli/cmd/issues.h new file mode 100644 index 00000000..f45e9690 --- /dev/null +++ b/include/gcli/cmd/issues.h @@ -0,0 +1,48 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CMD_ISSUES_H +#define GCLI_CMD_ISSUES_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +void gcli_print_issues(enum gcli_output_flags const flags, + gcli_issue_list const *const list, int const max); + +void gcli_issue_print_summary(gcli_issue const *const it); + +void gcli_issue_print_op(gcli_issue const *const it); + +int subcommand_issues(int argc, char *argv[]); + +#endif /* GCLI_CMD_ISSUES_H */ diff --git a/include/gcli/issues.h b/include/gcli/issues.h index 0ea47793..afb95841 100644 --- a/include/gcli/issues.h +++ b/include/gcli/issues.h @@ -86,17 +86,11 @@ int gcli_get_issues(gcli_ctx *ctx, char const *owner, char const *reponame, void gcli_issues_free(gcli_issue_list *); -void gcli_print_issues_table(gcli_ctx *ctx, enum gcli_output_flags flags, - gcli_issue_list const *list, int max); - int gcli_get_issue(gcli_ctx *ctx, char const *owner, char const *reponame, int issue_number, gcli_issue *out); void gcli_issue_free(gcli_issue *it); -void gcli_issue_print_summary(gcli_ctx *ctx, gcli_issue const *it); -void gcli_issue_print_op(gcli_issue const *it); - int gcli_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, int issue_number); diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index 00487efe..291fa228 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -39,6 +39,7 @@ #include #include +#include #include #include #include diff --git a/src/cmd/issues.c b/src/cmd/issues.c index 6c1c0f15..1d294e7f 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -30,6 +30,8 @@ #include #include +#include + #include #include #include @@ -74,6 +76,114 @@ usage(void) copyright(); } +void +gcli_print_issues(enum gcli_output_flags const flags, + gcli_issue_list const *const list, int const max) +{ + int n, pruned = 0; + gcli_tbl table; + gcli_tblcoldef cols[] = { + { .name = "NUMBER", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, + { .name = "NOTES", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, + { .name = "STATE", .type = GCLI_TBLCOLTYPE_SV, .flags = GCLI_TBLCOL_STATECOLOURED }, + { .name = "TITLE", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, + }; + + if (list->issues_size == 0) { + puts("No issues"); + return; + } + + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + if (!table) + errx(1, "could not init table printer"); + + /* Determine the correct number of items to print */ + if (max < 0 || (size_t)(max) > list->issues_size) + n = list->issues_size; + else + n = max; + + /* Iterate depending on the output order */ + if (flags & OUTPUT_SORTED) { + for (int i = 0; i < n; ++i) { + if (!list->issues[n - 1 - 1].is_pr) { + gcli_tbl_add_row(table, + list->issues[n - i - 1].number, + list->issues[n - i - 1].comments, + list->issues[n - i - 1].state, + list->issues[n - i - 1].title); + } else { + pruned++; + } + } + } else { + for (int i = 0; i < n; ++i) { + if (!list->issues[i].is_pr) { + gcli_tbl_add_row(table, + list->issues[i].number, + list->issues[i].comments, + list->issues[i].state, + list->issues[i].title); + } else { + pruned++; + } + } + } + + /* Dump the table */ + gcli_tbl_end(table); + + /* Inform the user that we pruned pull requests from the output */ + if (pruned && sn_getverbosity() != VERBOSITY_QUIET) + fprintf(stderr, "info: %d pull requests pruned\n", pruned); +} + +void +gcli_issue_print_summary(gcli_issue const *const it) +{ + gcli_dict dict; + + dict = gcli_dict_begin(); + + gcli_dict_add(dict, "NAME", 0, 0, "%d", it->number); + gcli_dict_add(dict, "TITLE", 0, 0, SV_FMT, SV_ARGS(it->title)); + gcli_dict_add(dict, "CREATED", 0, 0, SV_FMT, SV_ARGS(it->created_at)); + gcli_dict_add(dict, "AUTHOR", GCLI_TBLCOL_BOLD, 0, + SV_FMT, SV_ARGS(it->author)); + gcli_dict_add(dict, "STATE", GCLI_TBLCOL_STATECOLOURED, 0, + SV_FMT, SV_ARGS(it->state)); + gcli_dict_add(dict, "COMMENTS", 0, 0, "%d", it->comments); + gcli_dict_add(dict, "LOCKED", 0, 0, "%s", sn_bool_yesno(it->locked)); + + if (it->milestone.length) + gcli_dict_add(dict, "MILESTONE", 0, 0, SV_FMT, SV_ARGS(it->milestone)); + + if (it->labels_size) { + gcli_dict_add_sv_list(dict, "LABELS", it->labels, it->labels_size); + } else { + gcli_dict_add(dict, "LABELS", 0, 0, "none"); + } + + if (it->assignees_size) { + gcli_dict_add_sv_list(dict, "ASSIGNEES", + it->assignees, it->assignees_size); + } else { + gcli_dict_add(dict, "ASSIGNEES", 0, 0, "none"); + } + + /* Dump the dictionary */ + gcli_dict_end(dict); + +} + +void +gcli_issue_print_op(gcli_issue const *const it) +{ + if (it->body.length && it->body.data) + pretty_print(it->body.data, 4, 80, stdout); +} + static int subcommand_issue_create(int argc, char *argv[]) { @@ -244,7 +354,7 @@ subcommand_issues(int argc, char *argv[]) if (gcli_get_issues(g_clictx, owner, repo, &details, n, &list) < 0) errx(1, "error: could not get issues"); - gcli_print_issues_table(g_clictx, flags, &list, n); + gcli_print_issues(flags, &list, n); gcli_issues_free(&list); return EXIT_SUCCESS; @@ -387,7 +497,7 @@ handle_issues_actions(int argc, char *argv[], /* Make sure we have fetched the issue data */ ensure_issue(owner, repo, issue_id, &have_fetched_issue, &issue); - gcli_issue_print_summary(g_clictx, &issue); + gcli_issue_print_summary(&issue); puts("\nORIGINAL POST\n"); gcli_issue_print_op(&issue); @@ -407,7 +517,7 @@ handle_issues_actions(int argc, char *argv[], /* Make sure we have fetched the issue data */ ensure_issue(owner, repo, issue_id, &have_fetched_issue, &issue); - gcli_issue_print_summary(g_clictx, &issue); + gcli_issue_print_summary(&issue); } else if (strcmp("close", operation) == 0) { diff --git a/src/cmd/milestones.c b/src/cmd/milestones.c index 9dad318b..ddfa8e9f 100644 --- a/src/cmd/milestones.c +++ b/src/cmd/milestones.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -347,7 +348,7 @@ handle_milestone_actions(int argc, char *argv[], errx(1, "error: failed to fetch issues"); printf("\nISSUES:\n"); - gcli_print_issues_table(g_clictx, 0, &issues, -1); + gcli_print_issues(0, &issues, -1); gcli_issues_free(&issues); } else if (strcmp(action, "issues") == 0) { @@ -361,7 +362,7 @@ handle_milestone_actions(int argc, char *argv[], errx(1, "error: failed to fetch issues"); /* Print them as a table */ - gcli_print_issues_table(g_clictx, 0, &issues, -1); + gcli_print_issues(0, &issues, -1); /* Cleanup */ gcli_issues_free(&issues); diff --git a/src/issues.c b/src/issues.c index cb2d772c..d49cc39d 100644 --- a/src/issues.c +++ b/src/issues.c @@ -27,8 +27,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include -#include #include #include #include @@ -72,118 +70,6 @@ gcli_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, return gcli_forge(ctx)->get_issues(ctx, owner, repo, details, max, out); } -void -gcli_print_issues_table(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_issue_list const *const list, int const max) -{ - int n, pruned = 0; - gcli_tbl table; - gcli_tblcoldef cols[] = { - { .name = "NUMBER", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, - { .name = "NOTES", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, - { .name = "STATE", .type = GCLI_TBLCOLTYPE_SV, .flags = GCLI_TBLCOL_STATECOLOURED }, - { .name = "TITLE", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, - }; - - (void) ctx; - - if (list->issues_size == 0) { - puts("No issues"); - return; - } - - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); - if (!table) - errx(1, "could not init table printer"); - - /* Determine the correct number of items to print */ - if (max < 0 || (size_t)(max) > list->issues_size) - n = list->issues_size; - else - n = max; - - /* Iterate depending on the output order */ - if (flags & OUTPUT_SORTED) { - for (int i = 0; i < n; ++i) { - if (!list->issues[n - 1 - 1].is_pr) { - gcli_tbl_add_row(table, - list->issues[n - i - 1].number, - list->issues[n - i - 1].comments, - list->issues[n - i - 1].state, - list->issues[n - i - 1].title); - } else { - pruned++; - } - } - } else { - for (int i = 0; i < n; ++i) { - if (!list->issues[i].is_pr) { - gcli_tbl_add_row(table, - list->issues[i].number, - list->issues[i].comments, - list->issues[i].state, - list->issues[i].title); - } else { - pruned++; - } - } - } - - /* Dump the table */ - gcli_tbl_end(table); - - /* Inform the user that we pruned pull requests from the output */ - if (pruned && sn_getverbosity() != VERBOSITY_QUIET) - fprintf(stderr, "info: %d pull requests pruned\n", pruned); -} - -void -gcli_issue_print_summary(gcli_ctx *ctx, gcli_issue const *const it) -{ - gcli_dict dict; - - (void) ctx; - - dict = gcli_dict_begin(); - - gcli_dict_add(dict, "NAME", 0, 0, "%d", it->number); - gcli_dict_add(dict, "TITLE", 0, 0, SV_FMT, SV_ARGS(it->title)); - gcli_dict_add(dict, "CREATED", 0, 0, SV_FMT, SV_ARGS(it->created_at)); - gcli_dict_add(dict, "AUTHOR", GCLI_TBLCOL_BOLD, 0, - SV_FMT, SV_ARGS(it->author)); - gcli_dict_add(dict, "STATE", GCLI_TBLCOL_STATECOLOURED, 0, - SV_FMT, SV_ARGS(it->state)); - gcli_dict_add(dict, "COMMENTS", 0, 0, "%d", it->comments); - gcli_dict_add(dict, "LOCKED", 0, 0, "%s", sn_bool_yesno(it->locked)); - - if (it->milestone.length) - gcli_dict_add(dict, "MILESTONE", 0, 0, SV_FMT, SV_ARGS(it->milestone)); - - if (it->labels_size) { - gcli_dict_add_sv_list(dict, "LABELS", it->labels, it->labels_size); - } else { - gcli_dict_add(dict, "LABELS", 0, 0, "none"); - } - - if (it->assignees_size) { - gcli_dict_add_sv_list(dict, "ASSIGNEES", - it->assignees, it->assignees_size); - } else { - gcli_dict_add(dict, "ASSIGNEES", 0, 0, "none"); - } - - /* Dump the dictionary */ - gcli_dict_end(dict); - -} - -void -gcli_issue_print_op(gcli_issue const *const it) -{ - if (it->body.length && it->body.data) - pretty_print(it->body.data, 4, 80, stdout); -} - int gcli_get_issue(gcli_ctx *ctx, char const *owner, char const *repo, int const issue_number, gcli_issue *const out) From 8f44d5b9a50713de3ea7afb1931b371e6cae8f4d Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 17 Aug 2023 18:23:58 +0200 Subject: [PATCH 116/236] Move pull print routines to cmd code --- Makefile.am | 2 +- include/gcli/cmd/pulls.h | 49 ++++++++++++++ include/gcli/pulls.h | 11 +--- src/cmd/pulls.c | 136 +++++++++++++++++++++++++++++++++++++-- src/pulls.c | 122 +---------------------------------- 5 files changed, 187 insertions(+), 133 deletions(-) create mode 100644 include/gcli/cmd/pulls.h diff --git a/Makefile.am b/Makefile.am index a68ee305..9a52d121 100644 --- a/Makefile.am +++ b/Makefile.am @@ -71,7 +71,7 @@ gcli_SOURCES = \ include/gcli/cmd/labels.h src/cmd/labels.c \ include/gcli/cmd/milestones.h src/cmd/milestones.c \ src/cmd/pipelines.c \ - src/cmd/pulls.c \ + include/gcli/cmd/pulls.h src/cmd/pulls.c \ include/gcli/cmd/releases.h src/cmd/releases.c \ src/cmd/repos.c \ src/cmd/snippets.c \ diff --git a/include/gcli/cmd/pulls.h b/include/gcli/cmd/pulls.h new file mode 100644 index 00000000..35eee71c --- /dev/null +++ b/include/gcli/cmd/pulls.h @@ -0,0 +1,49 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CMD_PULLS_H +#define GCLI_CMD_PULLS_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +void gcli_print_pulls(enum gcli_output_flags flags, gcli_pull_list const *list, + int max); + +void gcli_print_pull_diff(FILE *stream, char const *owner, char const *reponame, + int pr_number); + +void gcli_print_pull(gcli_pull const *pull); + +void gcli_pull_print_op(gcli_pull const *pull); + +#endif /* GCLI_CMD_PULLS_H */ diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index 363ff31f..e17c964f 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -114,11 +114,8 @@ void gcli_pull_free(gcli_pull *it); void gcli_pulls_free(gcli_pull_list *list); -void gcli_print_pulls_table(gcli_ctx *ctx, enum gcli_output_flags flags, - gcli_pull_list const *list, int max); - -void gcli_print_pull_diff(gcli_ctx *ctx, FILE *stream, char const *owner, - char const *reponame, int pr_number); +void gcli_pull_get_diff(gcli_ctx *ctx, FILE *fout, char const *owner, + char const *repo, int pr_number); int gcli_pull_checks(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number); @@ -131,10 +128,6 @@ int gcli_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, int gcli_pull_submit(gcli_ctx *ctx, gcli_submit_pull_options); -void gcli_pull_print_status(gcli_ctx *ctx, gcli_pull const *it); - -void gcli_pull_print_op(gcli_pull *summary); - enum gcli_merge_flags { GCLI_PULL_MERGE_SQUASH = 0x1, /* squash commits when merging */ GCLI_PULL_MERGE_DELETEHEAD = 0x2, /* delete the source branch after merging */ diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 41c0c40a..2fa32110 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -30,8 +30,13 @@ #include #include +#include +#include +#include + #include #include +#include #include #include #include @@ -85,6 +90,129 @@ usage(void) copyright(); } +void +gcli_print_pulls(enum gcli_output_flags const flags, + gcli_pull_list const *const list, int const max) +{ + int n; + gcli_tbl table; + gcli_tblcoldef cols[] = { + { .name = "NUMBER", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, + { .name = "STATE", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_STATECOLOURED }, + { .name = "MERGED", .type = GCLI_TBLCOLTYPE_BOOL, .flags = 0 }, + { .name = "CREATOR", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_BOLD }, + { .name = "NOTES", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, + { .name = "TITLE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + }; + + if (list->pulls_size == 0) { + puts("No Pull Requests"); + return; + } + + /* Determine number of items to print */ + if (max < 0 || (size_t)(max) > list->pulls_size) + n = list->pulls_size; + else + n = max; + + /* Fill the table */ + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + if (!table) + errx(1, "error: cannot init table"); + + if (flags & OUTPUT_SORTED) { + for (int i = 0; i < n; ++i) { + gcli_tbl_add_row(table, + list->pulls[n-i-1].number, + list->pulls[n-i-1].state, + list->pulls[n-i-1].merged, + list->pulls[n-i-1].author, + list->pulls[n-i-1].comments, + list->pulls[n-i-1].title); + } + } else { + for (int i = 0; i < n; ++i) { + gcli_tbl_add_row(table, + list->pulls[i].number, + list->pulls[i].state, + list->pulls[i].merged, + list->pulls[i].author, + list->pulls[i].comments, + list->pulls[i].title); + } + } + + gcli_tbl_end(table); +} + +void +gcli_print_pull_diff(FILE *stream, char const *owner, char const *reponame, + int pr_number) +{ + gcli_pull_get_diff(g_clictx, stream, owner, reponame, pr_number); +} + +void +gcli_pull_print(gcli_pull const *const it) +{ + gcli_dict dict; + gcli_forge_descriptor const *const forge = gcli_forge(g_clictx); + int const quirks = forge->pull_summary_quirks; + + dict = gcli_dict_begin(); + + gcli_dict_add(dict, "NUMBER", 0, 0, "%d", it->number); + gcli_dict_add_string(dict, "TITLE", 0, 0, it->title); + gcli_dict_add_string(dict, "HEAD", 0, 0, it->head_label); + gcli_dict_add_string(dict, "BASE", 0, 0, it->base_label); + gcli_dict_add_string(dict, "CREATED", 0, 0, it->created_at); + gcli_dict_add_string(dict, "AUTHOR", GCLI_TBLCOL_BOLD, 0, it->author); + gcli_dict_add_string(dict, "STATE", GCLI_TBLCOL_STATECOLOURED, 0, it->state); + gcli_dict_add(dict, "COMMENTS", 0, 0, "%d", it->comments); + + if (it->milestone) + gcli_dict_add_string(dict, "MILESTONE", 0, 0, it->milestone); + + if ((quirks & GCLI_PRS_QUIRK_ADDDEL) == 0) + /* FIXME: move printing colours into the dictionary printer? */ + gcli_dict_add(dict, "ADD:DEL", 0, 0, "%s%d%s:%s%d%s", + gcli_setcolour(GCLI_COLOR_GREEN), + it->additions, + gcli_resetcolour(), + gcli_setcolour(GCLI_COLOR_RED), + it->deletions, + gcli_resetcolour()); + + if ((quirks & GCLI_PRS_QUIRK_COMMITS) == 0) + gcli_dict_add(dict, "COMMITS", 0, 0, "%d", it->commits); + + if ((quirks & GCLI_PRS_QUIRK_CHANGES) == 0) + gcli_dict_add(dict, "CHANGED", 0, 0, "%d", it->changed_files); + + if ((quirks & GCLI_PRS_QUIRK_MERGED) == 0) + gcli_dict_add_string(dict, "MERGED", 0, 0, sn_bool_yesno(it->merged)); + + gcli_dict_add_string(dict, "MERGEABLE", 0, 0, sn_bool_yesno(it->mergeable)); + if ((quirks & GCLI_PRS_QUIRK_DRAFT) == 0) + gcli_dict_add_string(dict, "DRAFT", 0, 0, sn_bool_yesno(it->draft)); + + if (it->labels_size) { + gcli_dict_add_sv_list(dict, "LABELS", it->labels, it->labels_size); + } else { + gcli_dict_add_string(dict, "LABELS", 0, 0, "none"); + } + + gcli_dict_end(dict); +} + +void +gcli_pull_print_op(gcli_pull const *const pull) +{ + if (pull->body) + pretty_print(pull->body, 4, 80, stdout); +} + static sn_sv pr_try_derive_head(void) { @@ -314,7 +442,7 @@ subcommand_pulls(int argc, char *argv[]) if (gcli_get_pulls(g_clictx, owner, repo, &details, n, &pulls) < 0) errx(1, "error: could not fetch pull requests"); - gcli_print_pulls_table(g_clictx, flags, &pulls, n); + gcli_print_pulls(flags, &pulls, n); gcli_pulls_free(&pulls); return EXIT_SUCCESS; @@ -383,7 +511,7 @@ handle_pull_actions(int argc, char *argv[], ensure_pull(owner, repo, pr, &fetched_pull, &pull); /* Print meta */ - gcli_pull_print_status(g_clictx, &pull); + gcli_pull_print(&pull); /* OP */ puts("\nORIGINAL POST"); @@ -412,7 +540,7 @@ handle_pull_actions(int argc, char *argv[], ensure_pull(owner, repo, pr, &fetched_pull, &pull); /* Print meta information */ - gcli_pull_print_status(g_clictx, &pull); + gcli_pull_print(&pull); } else if (strcmp(action, "commits") == 0) { @@ -420,7 +548,7 @@ handle_pull_actions(int argc, char *argv[], gcli_pull_commits(g_clictx, owner, repo, pr); } else if (strcmp(action, "diff") == 0) { - gcli_print_pull_diff(g_clictx, stdout, owner, repo, pr); + gcli_print_pull_diff(stdout, owner, repo, pr); } else if (strcmp(action, "comments") == 0 || strcmp(action, "notes") == 0) { diff --git a/src/pulls.c b/src/pulls.c index e85dbe84..ef6a21fb 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -60,122 +60,12 @@ gcli_get_pulls(gcli_ctx *ctx, char const *owner, char const *repo, } void -gcli_print_pulls_table(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_pull_list const *const list, int const max) -{ - int n; - gcli_tbl table; - gcli_tblcoldef cols[] = { - { .name = "NUMBER", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, - { .name = "STATE", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_STATECOLOURED }, - { .name = "MERGED", .type = GCLI_TBLCOLTYPE_BOOL, .flags = 0 }, - { .name = "CREATOR", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_BOLD }, - { .name = "NOTES", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, - { .name = "TITLE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - }; - - (void) ctx; - - if (list->pulls_size == 0) { - puts("No Pull Requests"); - return; - } - - /* Determine number of items to print */ - if (max < 0 || (size_t)(max) > list->pulls_size) - n = list->pulls_size; - else - n = max; - - /* Fill the table */ - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); - if (!table) - errx(1, "error: cannot init table"); - - if (flags & OUTPUT_SORTED) { - for (int i = 0; i < n; ++i) { - gcli_tbl_add_row(table, - list->pulls[n-i-1].number, - list->pulls[n-i-1].state, - list->pulls[n-i-1].merged, - list->pulls[n-i-1].author, - list->pulls[n-i-1].comments, - list->pulls[n-i-1].title); - } - } else { - for (int i = 0; i < n; ++i) { - gcli_tbl_add_row(table, - list->pulls[i].number, - list->pulls[i].state, - list->pulls[i].merged, - list->pulls[i].author, - list->pulls[i].comments, - list->pulls[i].title); - } - } - - gcli_tbl_end(table); -} - -void -gcli_print_pull_diff(gcli_ctx *ctx, FILE *stream, char const *owner, - char const *reponame, int const pr_number) +gcli_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *reponame, int const pr_number) { gcli_forge(ctx)->print_pull_diff(ctx, stream, owner, reponame, pr_number); } -void -gcli_pull_print_status(gcli_ctx *ctx, gcli_pull const *const it) -{ - gcli_dict dict; - gcli_forge_descriptor const *const forge = gcli_forge(ctx); - - dict = gcli_dict_begin(); - - gcli_dict_add(dict, "NUMBER", 0, 0, "%d", it->number); - gcli_dict_add_string(dict, "TITLE", 0, 0, it->title); - gcli_dict_add_string(dict, "HEAD", 0, 0, it->head_label); - gcli_dict_add_string(dict, "BASE", 0, 0, it->base_label); - gcli_dict_add_string(dict, "CREATED", 0, 0, it->created_at); - gcli_dict_add_string(dict, "AUTHOR", GCLI_TBLCOL_BOLD, 0, it->author); - gcli_dict_add_string(dict, "STATE", GCLI_TBLCOL_STATECOLOURED, 0, it->state); - gcli_dict_add(dict, "COMMENTS", 0, 0, "%d", it->comments); - - if (it->milestone) - gcli_dict_add_string(dict, "MILESTONE", 0, 0, it->milestone); - - if (!(forge->pull_summary_quirks & GCLI_PRS_QUIRK_ADDDEL)) - /* FIXME: move printing colours into the dictionary printer? */ - gcli_dict_add(dict, "ADD:DEL", 0, 0, "%s%d%s:%s%d%s", - gcli_setcolour(GCLI_COLOR_GREEN), - it->additions, - gcli_resetcolour(), - gcli_setcolour(GCLI_COLOR_RED), - it->deletions, - gcli_resetcolour()); - - if (!(forge->pull_summary_quirks & GCLI_PRS_QUIRK_COMMITS)) - gcli_dict_add(dict, "COMMITS", 0, 0, "%d", it->commits); - - if (!(forge->pull_summary_quirks & GCLI_PRS_QUIRK_CHANGES)) - gcli_dict_add(dict, "CHANGED", 0, 0, "%d", it->changed_files); - - if (!(forge->pull_summary_quirks & GCLI_PRS_QUIRK_MERGED)) - gcli_dict_add_string(dict, "MERGED", 0, 0, sn_bool_yesno(it->merged)); - - gcli_dict_add_string(dict, "MERGEABLE", 0, 0, sn_bool_yesno(it->mergeable)); - if (!(forge->pull_summary_quirks & GCLI_PRS_QUIRK_DRAFT)) - gcli_dict_add_string(dict, "DRAFT", 0, 0, sn_bool_yesno(it->draft)); - - if (it->labels_size) { - gcli_dict_add_sv_list(dict, "LABELS", it->labels, it->labels_size); - } else { - gcli_dict_add_string(dict, "LABELS", 0, 0, "none"); - } - - gcli_dict_end(dict); -} - static int gcli_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, int const pr_number, gcli_commit_list *const out) @@ -293,13 +183,7 @@ gcli_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, return gcli_forge(ctx)->get_pull(ctx, owner, repo, pr_number, out); } -void -gcli_pull_print_op(gcli_pull *const pull) -{ - if (pull->body) - pretty_print(pull->body, 4, 80, stdout); -} - +/* This one is going to be nasty */ int gcli_pull_checks(gcli_ctx *ctx, char const *owner, char const *repo, int const pr_number) { From d9e29cd0de3c5662ef76e792a4c9e745ae90ee90 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 17 Aug 2023 20:35:14 +0200 Subject: [PATCH 117/236] Move checks printing code out of library This is a bit hackier and more involved as it looks. The problem is the circular dependency of the definitions of the underlying struct types. Right now we just type pun a struct with the same layout into the right list type and dump things into it. It is the run time's job to determine the correct routines to call on the data. --- include/gcli/cmd/ci.h | 43 +++++++++++++++ include/gcli/cmd/cmd.h | 2 - include/gcli/cmd/pulls.h | 4 ++ include/gcli/forges.h | 19 ++++--- include/gcli/gitea/pulls.h | 4 +- include/gcli/github/checks.h | 17 +++--- include/gcli/github/pulls.h | 4 +- include/gcli/gitlab/pipelines.h | 9 ++-- include/gcli/pulls.h | 95 +++++++++++++++++++-------------- src/cmd/ci.c | 17 +++++- src/cmd/gcli.c | 2 + src/cmd/pulls.c | 48 ++++++++++++++++- src/forges.c | 6 +-- src/gitea/pulls.c | 9 ++-- src/github/checks.c | 23 ++------ src/github/pulls.c | 7 +-- src/gitlab/pipelines.c | 5 +- src/pulls.c | 23 ++++++-- templates/github/checks.t | 2 +- 19 files changed, 232 insertions(+), 107 deletions(-) create mode 100644 include/gcli/cmd/ci.h diff --git a/include/gcli/cmd/ci.h b/include/gcli/cmd/ci.h new file mode 100644 index 00000000..cfa329a3 --- /dev/null +++ b/include/gcli/cmd/ci.h @@ -0,0 +1,43 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CMD_CI_H +#define GCLI_CMD_CI_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +void github_print_checks(github_check_list const *checks); + +int subcommand_ci(int argc, char *argv[]); + +#endif /* GCLI_CMD_CI_H */ diff --git a/include/gcli/cmd/cmd.h b/include/gcli/cmd/cmd.h index 1061e42f..f7f34a4f 100644 --- a/include/gcli/cmd/cmd.h +++ b/include/gcli/cmd/cmd.h @@ -63,13 +63,11 @@ void delete_repo(bool always_yes, const char *owner, const char *repo); /* List of subcommand entry points */ int subcommand_api(int argc, char *argv[]); -int subcommand_ci(int argc, char *argv[]); int subcommand_comment(int argc, char *argv[]); int subcommand_config(int argc, char *argv[]); int subcommand_forks(int argc, char *argv[]); int subcommand_gists(int argc, char *argv[]); int subcommand_pipelines(int argc, char *argv[]); -int subcommand_pulls(int argc, char *argv[]); int subcommand_repos(int argc, char *argv[]); int subcommand_snippets(int argc, char *argv[]); int subcommand_status(int argc, char *argv[]); diff --git a/include/gcli/cmd/pulls.h b/include/gcli/cmd/pulls.h index 35eee71c..8590ea22 100644 --- a/include/gcli/cmd/pulls.h +++ b/include/gcli/cmd/pulls.h @@ -46,4 +46,8 @@ void gcli_print_pull(gcli_pull const *pull); void gcli_pull_print_op(gcli_pull const *pull); +int gcli_pull_checks(char const *owner, char const *repo, int pr_number); + +int subcommand_pulls(int argc, char *argv[]); + #endif /* GCLI_CMD_PULLS_H */ diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 0fdea189..d8ea1ba7 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -49,6 +49,11 @@ typedef struct gcli_forge_descriptor gcli_forge_descriptor; +/* Hopefully temporary hack */ +typedef int (*gcli_get_pull_checks_cb)( + gcli_ctx *, char const *, char const *, int, + gcli_pull_checks_list *); + /** * Struct of function pointers to perform actions in the given * forge. It is like a plugin system to dispatch. */ @@ -261,17 +266,11 @@ struct gcli_forge_descriptor { int pr_number); /** - * Print a list of checks associated with the given pull. + * Return a list of checks associated with the given pull. * - * NOTE(Nico): This is a print routine here because the CI systems - * underlying the forge are so different that we cannot properly - * unify them. For Gitlab this will call into the pipelines code, - * for Github into the actions code. */ - int (*print_pull_checks)( - gcli_ctx *ctx, - char const *owner, - char const *reponame, - int pr_number); + * The type of the returned list depends on the forge type. See + * the definition of gcli_pull_checks_list. */ + gcli_get_pull_checks_cb get_pull_checks; /** * Merge the given PR/MR */ diff --git a/include/gcli/gitea/pulls.h b/include/gcli/gitea/pulls.h index 565d0ee6..b23e07b7 100644 --- a/include/gcli/gitea/pulls.h +++ b/include/gcli/gitea/pulls.h @@ -61,8 +61,8 @@ int gitea_pull_reopen(gcli_ctx *ctx, char const *owner, char const *repo, int gitea_print_pr_diff(gcli_ctx *ctx, FILE *stream, char const *owner, char const *repo, int pr_number); -int gitea_pull_checks(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number); +int gitea_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, + int pr_number, gcli_pull_checks_list *out); int gitea_pull_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number, int milestone_id); diff --git a/include/gcli/github/checks.h b/include/gcli/github/checks.h index cb234ecc..e9778291 100644 --- a/include/gcli/github/checks.h +++ b/include/gcli/github/checks.h @@ -34,10 +34,12 @@ #include #endif +#include + #include typedef struct gcli_github_check gcli_github_check; -typedef struct gcli_github_checks gcli_github_checks; +typedef struct github_check_list github_check_list; struct gcli_github_check { char *name; @@ -48,20 +50,15 @@ struct gcli_github_check { long id; }; -struct gcli_github_checks { +struct github_check_list { gcli_github_check *checks; - size_t checks_size; + size_t checks_size; }; int github_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, char const *ref, int max, - gcli_github_checks *checks); - -void github_print_checks(gcli_ctx *ctx, gcli_github_checks const *checks); - -void github_free_checks(gcli_github_checks *checks); + github_check_list *checks); -int github_checks(gcli_ctx *ctx, char const *owner, char const *repo, - char const *ref, int max); +void github_free_checks(github_check_list *checks); #endif /* GITHUB_CHECKS_H */ diff --git a/include/gcli/github/pulls.h b/include/gcli/github/pulls.h index dbe1ede2..144c15a6 100644 --- a/include/gcli/github/pulls.h +++ b/include/gcli/github/pulls.h @@ -47,8 +47,8 @@ int github_get_pulls(gcli_ctx *ctx, char const *owner, char const *reponame, int github_print_pull_diff(gcli_ctx *ctx, FILE *stream, char const *owner, char const *reponame, int pr_number); -int github_pull_checks(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number); +int github_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, + int pr_number, gcli_pull_checks_list *out); int github_pull_merge(gcli_ctx *ctx, char const *owner, char const *reponame, int pr_number, enum gcli_merge_flags flags); diff --git a/include/gcli/gitlab/pipelines.h b/include/gcli/gitlab/pipelines.h index b46d6824..422af087 100644 --- a/include/gcli/gitlab/pipelines.h +++ b/include/gcli/gitlab/pipelines.h @@ -34,6 +34,8 @@ #include #endif +#include + typedef struct gitlab_pipeline gitlab_pipeline; typedef struct gitlab_pipeline_list gitlab_pipeline_list; typedef struct gitlab_job gitlab_job; @@ -107,11 +109,12 @@ int gitlab_job_cancel(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_job_retry(gcli_ctx *ctx, char const *owner, char const *repo, long job_id); -int gitlab_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, - int mr_id); - int gitlab_job_download_artifacts(gcli_ctx *ctx, char const *owner, char const *repo, long jid, char const *outfile); +int gitlab_get_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, + int mr_id, gitlab_pipeline_list *list); + + #endif /* GITLAB_PIPELINES_H */ diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index e17c964f..ad24cbee 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -40,12 +40,13 @@ #include #include -typedef struct gcli_pull gcli_pull; -typedef struct gcli_pull_fetch_details gcli_pull_fetch_details; +typedef struct gcli_pull gcli_pull; +typedef struct gcli_pull_fetch_details gcli_pull_fetch_details; typedef struct gcli_submit_pull_options gcli_submit_pull_options; -typedef struct gcli_commit gcli_commit; -typedef struct gcli_commit_list gcli_commit_list; -typedef struct gcli_pull_list gcli_pull_list; +typedef struct gcli_commit gcli_commit; +typedef struct gcli_commit_list gcli_commit_list; +typedef struct gcli_pull_list gcli_pull_list; +typedef struct gcli_pull_checks_list gcli_pull_checks_list; struct gcli_pull_list { gcli_pull *pulls; @@ -53,29 +54,29 @@ struct gcli_pull_list { }; struct gcli_pull { - char *author; - char *state; - char *title; - char *body; - char *created_at; - char *commits_link; - char *head_label; - char *base_label; - char *head_sha; - char *milestone; - int id; - int number; - int comments; - int additions; - int deletions; - int commits; - int changed_files; - int head_pipeline_id; /* This is GitLab specific */ - sn_sv *labels; - size_t labels_size; - bool merged; - bool mergeable; - bool draft; + char *author; + char *state; + char *title; + char *body; + char *created_at; + char *commits_link; + char *head_label; + char *base_label; + char *head_sha; + char *milestone; + int id; + int number; + int comments; + int additions; + int deletions; + int commits; + int changed_files; + int head_pipeline_id; /* This is GitLab specific */ + sn_sv *labels; + size_t labels_size; + bool merged; + bool mergeable; + bool draft; }; struct gcli_commit { @@ -89,16 +90,16 @@ struct gcli_commit_list { /* Options to submit to the gh api for creating a PR */ struct gcli_submit_pull_options { - char const *owner; - char const *repo; - sn_sv from; - sn_sv to; - sn_sv title; - sn_sv body; + char const *owner; + char const *repo; + sn_sv from; + sn_sv to; + sn_sv title; + sn_sv body; char const **labels; - size_t labels_size; - int draft; - bool always_yes; + size_t labels_size; + int draft; + bool always_yes; }; struct gcli_pull_fetch_details { @@ -106,6 +107,20 @@ struct gcli_pull_fetch_details { char const *author; }; +/** Generic list of checks ran on a pull request + * + * NOTE: KEEP THIS ORDER! WE DEPEND ON THE ABI HERE. + * + * For github the type of checks is gitlab_check* + * For gitlab the type of checks is gitlab_pipeline* + * + * You can cast this type to the list type of either one of them. */ +struct gcli_pull_checks_list { + void *checks; + size_t checks_size; + int forge_type; +}; + int gcli_get_pulls(gcli_ctx *ctx, char const *owner, char const *reponame, gcli_pull_fetch_details const *details, int max, gcli_pull_list *out); @@ -117,8 +132,10 @@ void gcli_pulls_free(gcli_pull_list *list); void gcli_pull_get_diff(gcli_ctx *ctx, FILE *fout, char const *owner, char const *repo, int pr_number); -int gcli_pull_checks(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number); +int gcli_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, + int pr_number, gcli_pull_checks_list *out); + +void gcli_pull_checks_free(gcli_pull_checks_list *list); void gcli_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number); diff --git a/src/cmd/ci.c b/src/cmd/ci.c index 9792ceb4..ac32b59a 100644 --- a/src/cmd/ci.c +++ b/src/cmd/ci.c @@ -31,7 +31,9 @@ #include #endif +#include #include + #include #include #include @@ -55,6 +57,19 @@ usage(void) copyright(); } +void +github_checks(char const *const owner, char const *const repo, + char const *const ref, int const max) +{ + github_check_list list = {0}; + if (github_get_checks(g_clictx, owner, repo, ref, max, &list) < 0) + errx(1, "error: failed to get github checks: %s", + gcli_get_error(g_clictx)); + + github_print_checks(&list); + github_free_checks(&list); +} + int subcommand_ci(int argc, char *argv[]) { @@ -120,7 +135,7 @@ subcommand_ci(int argc, char *argv[]) errx(1, "error: The ci subcommand only works for GitHub. " "Use gcli -t github ... to force a GitHub remote."); - github_checks(g_clictx, owner, repo, ref, count); + github_checks(owner, repo, ref, count); return EXIT_SUCCESS; } diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index 291fa228..0b329931 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -38,10 +38,12 @@ #include #include +#include #include #include #include #include +#include #include #include diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 2fa32110..2666586b 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -29,6 +29,7 @@ #include +#include #include #include #include @@ -38,6 +39,7 @@ #include #include #include +#include #include #include @@ -45,6 +47,7 @@ #include #endif +#include #include static void @@ -213,6 +216,47 @@ gcli_pull_print_op(gcli_pull const *const pull) pretty_print(pull->body, 4, 80, stdout); } +static void +gcli_print_checks_list(gcli_pull_checks_list const *const list) +{ + switch (list->forge_type) { + case GCLI_FORGE_GITHUB: + github_print_checks((github_check_list const *)(list)); + break; + case GCLI_FORGE_GITLAB: + gitlab_print_pipelines(g_clictx, (gitlab_pipeline_list const*)(list)); + break; + default: + assert(0 && "unreachable"); + } +} + +int +gcli_pull_checks(char const *owner, char const *repo, int pr_number) +{ + gcli_pull_checks_list list = {0}; + gcli_forge_type t = gcli_config_get_forge_type(g_clictx); + + list.forge_type = t; + + switch (t) { + case GCLI_FORGE_GITHUB: + case GCLI_FORGE_GITLAB: { + int rc = gcli_pull_get_checks(g_clictx, owner, repo, pr_number, &list); + if (rc < 0) + return rc; + + gcli_print_checks_list(&list); + gcli_pull_checks_free(&list); + + return 0; + } break; + default: + puts("No checks."); + return 0; /* no CI support / not implemented */ + } +} + static sn_sv pr_try_derive_head(void) { @@ -523,7 +567,7 @@ handle_pull_actions(int argc, char *argv[], /* Checks */ puts("\nCHECKS"); - if (gcli_pull_checks(g_clictx, owner, repo, pr) < 0) + if (gcli_pull_checks(owner, repo, pr) < 0) errx(1, "error: failed to fetch pull request checks"); } else if (strcmp(action, "op") == 0) { @@ -555,7 +599,7 @@ handle_pull_actions(int argc, char *argv[], gcli_pull_comments(g_clictx, owner, repo, pr); } else if (strcmp(action, "ci") == 0) { - if (gcli_pull_checks(g_clictx, owner, repo, pr) < 0) + if (gcli_pull_checks(owner, repo, pr) < 0) errx(1, "error: failed to fetch pull request checks"); } else if (strcmp(action, "merge") == 0) { diff --git a/src/forges.c b/src/forges.c index 6a0cfb87..e269489f 100644 --- a/src/forges.c +++ b/src/forges.c @@ -98,7 +98,7 @@ github_forge_descriptor = .get_milestone_issues = github_milestone_get_issues, .get_pulls = github_get_pulls, .print_pull_diff = github_print_pull_diff, - .print_pull_checks = github_pull_checks, + .get_pull_checks = github_pull_get_checks, .pull_merge = github_pull_merge, .pull_reopen = github_pull_reopen, .pull_close = github_pull_close, @@ -173,7 +173,7 @@ gitlab_forge_descriptor = .issue_clear_milestone = gitlab_issue_clear_milestone, .get_pulls = gitlab_get_mrs, .print_pull_diff = gitlab_print_pr_diff, - .print_pull_checks = gitlab_mr_pipelines, + .get_pull_checks = (gcli_get_pull_checks_cb)gitlab_get_mr_pipelines, .pull_merge = gitlab_mr_merge, .pull_reopen = gitlab_mr_reopen, .pull_close = gitlab_mr_close, @@ -237,7 +237,7 @@ gitea_forge_descriptor = .create_label = gitea_create_label, .delete_label = gitea_delete_label, .get_pulls = gitea_get_pulls, - .print_pull_checks = gitea_pull_checks, /* stub */ + .get_pull_checks = gitea_pull_get_checks, /* stub, will always return an error */ .pull_merge = gitea_pull_merge, .pull_reopen = gitea_pull_reopen, .pull_close = gitea_pull_close, diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index 11e66a7c..ec314922 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -163,17 +163,16 @@ gitea_print_pr_diff(gcli_ctx *ctx, FILE *const stream, char const *owner, } int -gitea_pull_checks(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number) +gitea_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number, gcli_pull_checks_list *out) { (void) ctx; (void) owner; (void) repo; (void) pr_number; + (void) out; - warnx("PR checks are not available on Gitea"); - - return 0; + return gcli_error(ctx, "Pull Request checks are not available on Gitea"); } int diff --git a/src/github/checks.c b/src/github/checks.c index 670836fb..d93b7e6a 100644 --- a/src/github/checks.c +++ b/src/github/checks.c @@ -43,7 +43,7 @@ int github_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, - char const *ref, int const max, gcli_github_checks *const out) + char const *ref, int const max, github_check_list *const out) { gcli_fetch_buffer buffer = {0}; char *url = NULL, *next_url = NULL; @@ -79,7 +79,7 @@ github_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, } void -github_print_checks(gcli_ctx *ctx, gcli_github_checks const *const list) +github_print_checks(gcli_ctx *ctx, github_check_list const *const list) { gcli_tbl table; gcli_tblcoldef cols[] = { @@ -113,7 +113,7 @@ github_print_checks(gcli_ctx *ctx, gcli_github_checks const *const list) } void -github_free_checks(gcli_github_checks *const list) +github_free_checks(github_check_list *const list) { for (size_t i = 0; i < list->checks_size; ++i) { free(list->checks[i].name); @@ -127,20 +127,3 @@ github_free_checks(gcli_github_checks *const list) list->checks = NULL; list->checks_size = 0; } - -int -github_checks(gcli_ctx *ctx, char const *owner, char const *repo, - char const *ref, int const max) -{ - gcli_github_checks checks = {0}; - int rc; - - rc = github_get_checks(ctx, owner, repo, ref, max, &checks); - if (rc < 0) - return rc; - - github_print_checks(ctx, &checks); - github_free_checks(&checks); - - return 0; -} diff --git a/src/github/pulls.c b/src/github/pulls.c index 30cf9ba3..58a2bff5 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -377,13 +377,14 @@ github_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, } int -github_pull_checks(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number) +github_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number, gcli_pull_checks_list *out) { char refname[64] = {0}; /* This is kind of a hack, but it works! */ snprintf(refname, sizeof refname, "refs%%2Fpull%%2F%d%%2Fhead", pr_number); - return github_checks(ctx, owner, repo, refname, -1); + return github_get_checks(ctx, owner, repo, refname, -1, + (github_check_list *)out); } diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index 2a4bce4f..648d1541 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -29,9 +29,12 @@ #include #include + #include #include #include +#include + #include #include @@ -65,7 +68,7 @@ gitlab_get_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, return fetch_pipelines(ctx, url, max, list); } -static int +int gitlab_get_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, int const mr_id, gitlab_pipeline_list *const list) { diff --git a/src/pulls.c b/src/pulls.c index ef6a21fb..cf205ed7 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -39,6 +39,8 @@ #include #include +#include + void gcli_pulls_free(gcli_pull_list *const it) { @@ -183,11 +185,26 @@ gcli_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, return gcli_forge(ctx)->get_pull(ctx, owner, repo, pr_number, out); } -/* This one is going to be nasty */ int -gcli_pull_checks(gcli_ctx *ctx, char const *owner, char const *repo, int const pr_number) +gcli_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, + int const pr_number, gcli_pull_checks_list *out) +{ + return gcli_forge(ctx)->get_pull_checks(ctx, owner, repo, pr_number, out); +} + +void +gcli_pull_checks_free(gcli_pull_checks_list *list) { - return gcli_forge(ctx)->print_pull_checks(ctx, owner, repo, pr_number); + switch (list->forge_type) { + case GCLI_FORGE_GITHUB: + github_free_checks((github_check_list *)list); + break; + case GCLI_FORGE_GITLAB: + gitlab_free_pipelines((gitlab_pipeline_list *)list); + break; + default: + assert(0 && "unreachable"); + } } static void diff --git a/templates/github/checks.t b/templates/github/checks.t index 06f2a869..e2448f3f 100644 --- a/templates/github/checks.t +++ b/templates/github/checks.t @@ -10,6 +10,6 @@ object of gcli_github_check with "id" => id as int); parser github_checks is -object of gcli_github_checks with +object of github_check_list with ("check_runs" => checks as array of gcli_github_check use parse_github_check); \ No newline at end of file From 9af409413b48e0be2d793f5db234edc49522b30a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 17 Aug 2023 20:35:27 +0200 Subject: [PATCH 118/236] Update todo --- todo.org | 1 + 1 file changed, 1 insertion(+) diff --git a/todo.org b/todo.org index d98f0c54..369e71c0 100644 --- a/todo.org +++ b/todo.org @@ -136,3 +136,4 @@ - [ ] Clean up handle on exit ** TODO Return errors from parsers ** TODO [[file:src/releases.c::gcli_release_push_asset(gcli_new_release *const release,][push_asset]] should not call errx but return an error code +** TODO Make [[file:src/pulls.c::gcli_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner,][getting a pull diff]] return an error code From f12c3fb96b18e7794658c5de71a1d08a5c26b477 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 18 Aug 2023 22:44:36 +0200 Subject: [PATCH 119/236] Move commit printing code out of library --- include/gcli/cmd/pulls.h | 2 ++ include/gcli/pulls.h | 6 ++-- src/cmd/pulls.c | 75 ++++++++++++++++++++++++++++++++++++++-- src/pulls.c | 74 ++------------------------------------- 4 files changed, 82 insertions(+), 75 deletions(-) diff --git a/include/gcli/cmd/pulls.h b/include/gcli/cmd/pulls.h index 8590ea22..8fae857b 100644 --- a/include/gcli/cmd/pulls.h +++ b/include/gcli/cmd/pulls.h @@ -48,6 +48,8 @@ void gcli_pull_print_op(gcli_pull const *pull); int gcli_pull_checks(char const *owner, char const *repo, int pr_number); +void gcli_print_commits(gcli_commit_list const *const list); + int subcommand_pulls(int argc, char *argv[]); #endif /* GCLI_CMD_PULLS_H */ diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index ad24cbee..461754e8 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -137,8 +137,10 @@ int gcli_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, void gcli_pull_checks_free(gcli_pull_checks_list *list); -void gcli_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number); +int gcli_pull_get_commits(gcli_ctx *ctx, char const *owner, char const *repo, + int pr_number, gcli_commit_list *out); + +void gcli_commits_free(gcli_commit_list *list); int gcli_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number, gcli_pull *out); diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 2666586b..d0911d8a 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -257,6 +257,76 @@ gcli_pull_checks(char const *owner, char const *repo, int pr_number) } } +/** + * Get a copy of the first line of the passed string. + */ +static char * +cut_newline(char const *const _it) +{ + char *it = strdup(_it); + char *foo = it; + while (*foo) { + if (*foo == '\n') { + *foo = 0; + break; + } + foo += 1; + } + + return it; +} + +void +gcli_print_commits(gcli_commit_list const *const list) +{ + gcli_tbl table; + gcli_tblcoldef cols[] = { + { .name = "SHA", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_COLOUREXPL }, + { .name = "AUTHOR", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_BOLD }, + { .name = "EMAIL", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "DATE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "MESSAGE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + }; + + if (list->commits_size == 0) { + puts("No commits"); + return; + } + + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + if (!table) + errx(1, "error: could not initialize table"); + + for (size_t i = 0; i < list->commits_size; ++i) { + char *message = cut_newline(list->commits[i].message); + gcli_tbl_add_row(table, GCLI_COLOR_YELLOW, list->commits[i].sha, + list->commits[i].author, + list->commits[i].email, + list->commits[i].date, + message); + free(message); /* message is copied by the function above */ + } + + gcli_tbl_end(table); +} + +int +gcli_pull_commits(char const *owner, char const *repo, + int const pr_number) +{ + gcli_commit_list commits = {0}; + int rc = 0; + + rc = gcli_pull_get_commits(g_clictx, owner, repo, pr_number, &commits); + if (rc < 0) + return rc; + + gcli_print_commits(&commits); + gcli_commits_free(&commits); + + return rc; +} + static sn_sv pr_try_derive_head(void) { @@ -563,7 +633,8 @@ handle_pull_actions(int argc, char *argv[], /* Commits */ puts("\nCOMMITS"); - gcli_pull_commits(g_clictx, owner, repo, pr); + if (gcli_pull_commits(owner, repo, pr) < 0) + errx(1, "error: failed to fetch pull request checks"); /* Checks */ puts("\nCHECKS"); @@ -589,7 +660,7 @@ handle_pull_actions(int argc, char *argv[], } else if (strcmp(action, "commits") == 0) { /* Does not require the summary */ - gcli_pull_commits(g_clictx, owner, repo, pr); + gcli_pull_commits(owner, repo, pr); } else if (strcmp(action, "diff") == 0) { gcli_print_pull_diff(stdout, owner, repo, pr); diff --git a/src/pulls.c b/src/pulls.c index cf205ed7..1fcd2e6c 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -68,69 +68,14 @@ gcli_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner, gcli_forge(ctx)->print_pull_diff(ctx, stream, owner, reponame, pr_number); } -static int -gcli_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, +int +gcli_pull_get_commits(gcli_ctx *ctx, char const *owner, char const *repo, int const pr_number, gcli_commit_list *const out) { return gcli_forge(ctx)->get_pull_commits(ctx, owner, repo, pr_number, out); } -/** - * Get a copy of the first line of the passed string. - */ -static char * -cut_newline(char const *const _it) -{ - char *it = strdup(_it); - char *foo = it; - while (*foo) { - if (*foo == '\n') { - *foo = 0; - break; - } - foo += 1; - } - - return it; -} - -static void -gcli_print_commits_table(gcli_ctx *ctx, gcli_commit_list const *const list) -{ - gcli_tbl table; - gcli_tblcoldef cols[] = { - { .name = "SHA", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_COLOUREXPL }, - { .name = "AUTHOR", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_BOLD }, - { .name = "EMAIL", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "DATE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "MESSAGE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - }; - - (void) ctx; - - if (list->commits_size == 0) { - puts("No commits"); - return; - } - - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); - if (!table) - errx(1, "error: could not initialize table"); - - for (size_t i = 0; i < list->commits_size; ++i) { - char *message = cut_newline(list->commits[i].message); - gcli_tbl_add_row(table, GCLI_COLOR_YELLOW, list->commits[i].sha, - list->commits[i].author, - list->commits[i].email, - list->commits[i].date, - message); - free(message); /* message is copied by the function above */ - } - - gcli_tbl_end(table); -} - -static void +void gcli_commits_free(gcli_commit_list *list) { for (size_t i = 0; i < list->commits_size; ++i) { @@ -147,19 +92,6 @@ gcli_commits_free(gcli_commit_list *list) list->commits_size = 0; } -void -gcli_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number) -{ - gcli_commit_list commits = {0}; - - if (gcli_get_pull_commits(ctx, owner, repo, pr_number, &commits) < 0) - errx(1, "error: failed to fetch commits of the pull request"); - - gcli_print_commits_table(ctx, &commits); - gcli_commits_free(&commits); -} - void gcli_pull_free(gcli_pull *const it) { From 9bee0572214acd7f6365e4375db3239dc75a6f43 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 18 Aug 2023 23:03:44 +0200 Subject: [PATCH 120/236] Move pipeline printing code out of the library --- Makefile.am | 2 +- include/gcli/cmd/cmd.h | 1 - include/gcli/cmd/pipelines.h | 42 ++++++++++++++++++++++++ include/gcli/gitlab/pipelines.h | 5 --- src/cmd/gcli.c | 1 + src/cmd/pipelines.c | 57 ++++++++++++++++++++++++++++++++- src/cmd/pulls.c | 3 +- src/gitlab/pipelines.c | 51 ++--------------------------- 8 files changed, 104 insertions(+), 58 deletions(-) create mode 100644 include/gcli/cmd/pipelines.h diff --git a/Makefile.am b/Makefile.am index 9a52d121..5de84ca8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -70,7 +70,7 @@ gcli_SOURCES = \ include/gcli/cmd/issues.h src/cmd/issues.c \ include/gcli/cmd/labels.h src/cmd/labels.c \ include/gcli/cmd/milestones.h src/cmd/milestones.c \ - src/cmd/pipelines.c \ + include/gcli/cmd/pipelines.h src/cmd/pipelines.c \ include/gcli/cmd/pulls.h src/cmd/pulls.c \ include/gcli/cmd/releases.h src/cmd/releases.c \ src/cmd/repos.c \ diff --git a/include/gcli/cmd/cmd.h b/include/gcli/cmd/cmd.h index f7f34a4f..c5dfe586 100644 --- a/include/gcli/cmd/cmd.h +++ b/include/gcli/cmd/cmd.h @@ -67,7 +67,6 @@ int subcommand_comment(int argc, char *argv[]); int subcommand_config(int argc, char *argv[]); int subcommand_forks(int argc, char *argv[]); int subcommand_gists(int argc, char *argv[]); -int subcommand_pipelines(int argc, char *argv[]); int subcommand_repos(int argc, char *argv[]); int subcommand_snippets(int argc, char *argv[]); int subcommand_status(int argc, char *argv[]); diff --git a/include/gcli/cmd/pipelines.h b/include/gcli/cmd/pipelines.h new file mode 100644 index 00000000..c2efba70 --- /dev/null +++ b/include/gcli/cmd/pipelines.h @@ -0,0 +1,42 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CMD_PIPELINES_H +#define GCLI_CMD_PIPELINES_H + +#include + +#include + +void gitlab_print_pipelines(gitlab_pipeline_list const *const list); +int gitlab_pipelines(char const *owner, char const *repo, int const count); + +int subcommand_pipelines(int argc, char *argv[]); + +#endif /* GCLI_CMD_PIPELINES_H */ diff --git a/include/gcli/gitlab/pipelines.h b/include/gcli/gitlab/pipelines.h index 422af087..3cde55ba 100644 --- a/include/gcli/gitlab/pipelines.h +++ b/include/gcli/gitlab/pipelines.h @@ -78,13 +78,8 @@ struct gitlab_job_list { int gitlab_get_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, int max, gitlab_pipeline_list *out); -void gitlab_print_pipelines(gcli_ctx *ctx, gitlab_pipeline_list const *list); - void gitlab_free_pipelines(gitlab_pipeline_list *list); -void gitlab_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, - int count); - void gitlab_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, long pipeline, int count); diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index 0b329931..53d64a1c 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include diff --git a/src/cmd/pipelines.c b/src/cmd/pipelines.c index 97571ea9..8563de98 100644 --- a/src/cmd/pipelines.c +++ b/src/cmd/pipelines.c @@ -30,8 +30,11 @@ #include #include +#include + #include #include + #include #ifdef HAVE_GETOPT_H @@ -64,6 +67,55 @@ usage(void) copyright(); } +void +gitlab_print_pipelines(gitlab_pipeline_list const *const list) +{ + gcli_tbl table; + gcli_tblcoldef cols[] = { + { .name = "ID", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, + { .name = "STATUS", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_STATECOLOURED }, + { .name = "CREATED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "UPDATED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "REF", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + }; + + if (!list->pipelines_size) { + printf("No pipelines\n"); + return; + } + + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + if (!table) + errx(1, "error: could not init table"); + + for (size_t i = 0; i < list->pipelines_size; ++i) { + gcli_tbl_add_row(table, + (int)(list->pipelines[i].id), + list->pipelines[i].status, + list->pipelines[i].created_at, + list->pipelines[i].updated_at, + list->pipelines[i].ref); + } + + gcli_tbl_end(table); +} + +int +gitlab_pipelines(char const *owner, char const *repo, int const count) +{ + gitlab_pipeline_list pipelines = {0}; + int rc = 0; + + rc = gitlab_get_pipelines(g_clictx, owner, repo, count, &pipelines); + if (rc < 0) + return rc; + + gitlab_print_pipelines(&pipelines); + gitlab_free_pipelines(&pipelines); + + return rc; +} + int subcommand_pipelines(int argc, char *argv[]) { @@ -163,7 +215,10 @@ subcommand_pipelines(int argc, char *argv[]) return EXIT_FAILURE; } - gitlab_pipelines(g_clictx, owner, repo, count); + if (gitlab_pipelines(owner, repo, count) < 0) + errx(1, "error: failed to get pipelines: %s", + gcli_get_error(g_clictx)); + return EXIT_SUCCESS; } diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index d0911d8a..37ddfbae 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -224,7 +225,7 @@ gcli_print_checks_list(gcli_pull_checks_list const *const list) github_print_checks((github_check_list const *)(list)); break; case GCLI_FORGE_GITLAB: - gitlab_print_pipelines(g_clictx, (gitlab_pipeline_list const*)(list)); + gitlab_print_pipelines((gitlab_pipeline_list const*)(list)); break; default: assert(0 && "unreachable"); diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index 648d1541..36256f5a 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -28,6 +28,7 @@ */ #include +#include #include #include @@ -81,41 +82,6 @@ gitlab_get_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, return fetch_pipelines(ctx, url, -1, list); } -void -gitlab_print_pipelines(gcli_ctx *ctx, gitlab_pipeline_list const *const list) -{ - gcli_tbl table; - gcli_tblcoldef cols[] = { - { .name = "ID", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, - { .name = "STATUS", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_STATECOLOURED }, - { .name = "CREATED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "UPDATED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "REF", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - }; - - (void) ctx; - - if (!list->pipelines_size) { - printf("No pipelines\n"); - return; - } - - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); - if (!table) - errx(1, "error: could not init table"); - - for (size_t i = 0; i < list->pipelines_size; ++i) { - gcli_tbl_add_row(table, - (int)(list->pipelines[i].id), - list->pipelines[i].status, - list->pipelines[i].created_at, - list->pipelines[i].updated_at, - list->pipelines[i].ref); - } - - gcli_tbl_end(table); -} - void gitlab_free_pipelines(gitlab_pipeline_list *const list) { @@ -133,19 +99,6 @@ gitlab_free_pipelines(gitlab_pipeline_list *const list) list->pipelines_size = 0; } -void -gitlab_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, - int const count) -{ - gitlab_pipeline_list pipelines = {0}; - - if (gitlab_get_pipelines(ctx, owner, repo, count, &pipelines) < 0) - errx(1,"error: could not fetch list of pipelines"); - - gitlab_print_pipelines(ctx, &pipelines); - gitlab_free_pipelines(&pipelines); -} - void gitlab_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, long const id, int const count) @@ -375,7 +328,7 @@ gitlab_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, rc = gitlab_get_mr_pipelines(ctx, owner, repo, mr_id, &list); if (rc == 0) - gitlab_print_pipelines(ctx, &list); + gitlab_print_pipelines(&list); gitlab_free_pipelines(&list); From 5d4537039b3107a46084c4c7408ddd0000ac96f3 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 18 Aug 2023 23:27:22 +0200 Subject: [PATCH 121/236] Move printing pipeline jobs out of library code --- include/gcli/cmd/pipelines.h | 4 +++ include/gcli/gitlab/pipelines.h | 5 --- src/cmd/pipelines.c | 58 ++++++++++++++++++++++++++++++++- src/gitlab/pipelines.c | 54 ------------------------------ 4 files changed, 61 insertions(+), 60 deletions(-) diff --git a/include/gcli/cmd/pipelines.h b/include/gcli/cmd/pipelines.h index c2efba70..8deea130 100644 --- a/include/gcli/cmd/pipelines.h +++ b/include/gcli/cmd/pipelines.h @@ -37,6 +37,10 @@ void gitlab_print_pipelines(gitlab_pipeline_list const *const list); int gitlab_pipelines(char const *owner, char const *repo, int const count); +int gitlab_pipeline_jobs(char const *owner, char const *repo, long pipeline, + int count); +void gitlab_print_jobs(gitlab_job_list const *const list); + int subcommand_pipelines(int argc, char *argv[]); #endif /* GCLI_CMD_PIPELINES_H */ diff --git a/include/gcli/gitlab/pipelines.h b/include/gcli/gitlab/pipelines.h index 3cde55ba..1601be24 100644 --- a/include/gcli/gitlab/pipelines.h +++ b/include/gcli/gitlab/pipelines.h @@ -80,14 +80,9 @@ int gitlab_get_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, void gitlab_free_pipelines(gitlab_pipeline_list *list); -void gitlab_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, - long pipeline, int count); - int gitlab_get_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, long pipeline, int count, gitlab_job_list *out); -void gitlab_print_jobs(gcli_ctx *ctx, gitlab_job_list const *jobs); - void gitlab_free_jobs(gitlab_job_list *jobs); void gitlab_free_job(gitlab_job *job); diff --git a/src/cmd/pipelines.c b/src/cmd/pipelines.c index 8563de98..94c579af 100644 --- a/src/cmd/pipelines.c +++ b/src/cmd/pipelines.c @@ -116,6 +116,60 @@ gitlab_pipelines(char const *owner, char const *repo, int const count) return rc; } +void +gitlab_print_jobs(gitlab_job_list const *const list) +{ + gcli_tbl table; + gcli_tblcoldef cols[] = { + { .name = "ID", .type = GCLI_TBLCOLTYPE_LONG, .flags = GCLI_TBLCOL_JUSTIFYR }, + { .name = "NAME", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "STATUS", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_STATECOLOURED }, + { .name = "STARTED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "FINISHED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "RUNNERDESC", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "REF", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + }; + + if (!list->jobs_size) { + printf("No jobs\n"); + return; + } + + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + if (!table) + errx(1, "error: could not initialize table"); + + for (size_t i = 0; i < list->jobs_size; ++i) { + gcli_tbl_add_row(table, + list->jobs[i].id, + list->jobs[i].name, + list->jobs[i].status, + list->jobs[i].started_at, + list->jobs[i].finished_at, + list->jobs[i].runner_description, + list->jobs[i].ref); + } + + gcli_tbl_end(table); +} + +int +gitlab_pipeline_jobs(char const *owner, char const *repo, + long const id, int const count) +{ + gitlab_job_list jobs = {0}; + int rc = 0; + + rc = gitlab_get_pipeline_jobs(g_clictx, owner, repo, id, count, &jobs); + if (rc < 0) + return rc; + + gitlab_print_jobs(&jobs); + gitlab_free_jobs(&jobs); + + return rc; +} + int subcommand_pipelines(int argc, char *argv[]) { @@ -201,7 +255,9 @@ subcommand_pipelines(int argc, char *argv[]) return EXIT_FAILURE; } - gitlab_pipeline_jobs(g_clictx, owner, repo, pid, count); + if (gitlab_pipeline_jobs(owner, repo, pid, count) < 0) + errx(1, "error: failed to get pipeline jobs: %s", + gcli_get_error(g_clictx)); return EXIT_SUCCESS; } diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index 36256f5a..31f560cf 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -99,21 +99,6 @@ gitlab_free_pipelines(gitlab_pipeline_list *const list) list->pipelines_size = 0; } -void -gitlab_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, - long const id, int const count) -{ - gitlab_job_list jobs = {0}; - int rc; - - rc = gitlab_get_pipeline_jobs(ctx, owner, repo, id, count, &jobs); - if (rc < 0) - errx(1, "error: failed to get jobs"); - - gitlab_print_jobs(ctx, &jobs); - gitlab_free_jobs(&jobs); -} - int gitlab_get_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, long const pipeline, int const max, @@ -133,45 +118,6 @@ gitlab_get_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, return gcli_fetch_list(ctx, url, &fl); } -void -gitlab_print_jobs(gcli_ctx *ctx, gitlab_job_list const *const list) -{ - gcli_tbl table; - gcli_tblcoldef cols[] = { - { .name = "ID", .type = GCLI_TBLCOLTYPE_LONG, .flags = GCLI_TBLCOL_JUSTIFYR }, - { .name = "NAME", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "STATUS", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_STATECOLOURED }, - { .name = "STARTED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "FINISHED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "RUNNERDESC", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "REF", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - }; - - (void) ctx; - - if (!list->jobs_size) { - printf("No jobs\n"); - return; - } - - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); - if (!table) - errx(1, "error: could not initialize table"); - - for (size_t i = 0; i < list->jobs_size; ++i) { - gcli_tbl_add_row(table, - list->jobs[i].id, - list->jobs[i].name, - list->jobs[i].status, - list->jobs[i].started_at, - list->jobs[i].finished_at, - list->jobs[i].runner_description, - list->jobs[i].ref); - } - - gcli_tbl_end(table); -} - void gitlab_free_job(gitlab_job *const job) { From b143a5bc52a6075eab71028addbb1e1e06cdb523 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 18 Aug 2023 23:39:08 +0200 Subject: [PATCH 122/236] Move job status out of library code --- include/gcli/cmd/pipelines.h | 3 ++ include/gcli/gitlab/pipelines.h | 5 +-- src/cmd/pipelines.c | 70 ++++++++++++++++++++++++++++++--- src/gitlab/pipelines.c | 42 +------------------- 4 files changed, 70 insertions(+), 50 deletions(-) diff --git a/include/gcli/cmd/pipelines.h b/include/gcli/cmd/pipelines.h index 8deea130..7d1fde81 100644 --- a/include/gcli/cmd/pipelines.h +++ b/include/gcli/cmd/pipelines.h @@ -41,6 +41,9 @@ int gitlab_pipeline_jobs(char const *owner, char const *repo, long pipeline, int count); void gitlab_print_jobs(gitlab_job_list const *const list); +void gitlab_print_job_status(gitlab_job const *const job); +int gitlab_job_status(char const *owner, char const *repo, long const jid); + int subcommand_pipelines(int argc, char *argv[]); #endif /* GCLI_CMD_PIPELINES_H */ diff --git a/include/gcli/gitlab/pipelines.h b/include/gcli/gitlab/pipelines.h index 1601be24..6b49c0cd 100644 --- a/include/gcli/gitlab/pipelines.h +++ b/include/gcli/gitlab/pipelines.h @@ -90,9 +90,6 @@ void gitlab_free_job(gitlab_job *job); int gitlab_job_get_log(gcli_ctx *ctx, char const *owner, char const *repo, long job_id); -int gitlab_job_status(gcli_ctx *ctx, char const *owner, char const *repo, - long job_id); - int gitlab_job_cancel(gcli_ctx *ctx, char const *owner, char const *repo, long job_id); @@ -106,5 +103,7 @@ int gitlab_job_download_artifacts(gcli_ctx *ctx, char const *owner, int gitlab_get_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, int mr_id, gitlab_pipeline_list *list); +int gitlab_get_job(gcli_ctx *ctx, char const *owner, char const *repo, + long const jid, gitlab_job *const out); #endif /* GITLAB_PIPELINES_H */ diff --git a/src/cmd/pipelines.c b/src/cmd/pipelines.c index 94c579af..e1f30bec 100644 --- a/src/cmd/pipelines.c +++ b/src/cmd/pipelines.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -170,6 +171,63 @@ gitlab_pipeline_jobs(char const *owner, char const *repo, return rc; } +void +gitlab_print_job_status(gitlab_job const *const job) +{ + gcli_dict printer; + + printer = gcli_dict_begin(); + + gcli_dict_add(printer, "ID", 0, 0, "%ld", job->id); + gcli_dict_add_string(printer, "STATUS", GCLI_TBLCOL_STATECOLOURED, 0, job->status); + gcli_dict_add_string(printer, "STAGE", 0, 0, job->stage); + gcli_dict_add_string(printer, "NAME", GCLI_TBLCOL_BOLD, 0, job->name); + gcli_dict_add_string(printer, "REF", GCLI_TBLCOL_COLOUREXPL, GCLI_COLOR_YELLOW, job->ref); + gcli_dict_add_string(printer, "CREATED", 0, 0, job->created_at); + gcli_dict_add_string(printer, "STARTED", 0, 0, job->started_at); + gcli_dict_add_string(printer, "FINISHED", 0, 0, job->finished_at); + gcli_dict_add(printer, "DURATION", 0, 0, "%-.2lfs", job->duration); + gcli_dict_add_string(printer, "RUNNER NAME", 0, 0, job->runner_name); + gcli_dict_add_string(printer, "RUNNER DESCR", 0, 0, job->runner_description); + + gcli_dict_end(printer); +} + +int +gitlab_job_status(char const *owner, char const *repo, long const jid) +{ + gitlab_job job = {0}; + int rc = 0; + + rc = gitlab_get_job(g_clictx, owner, repo, jid, &job); + if (rc < 0) + return rc; + + gitlab_print_job_status(&job); + gitlab_free_job(&job); + + return rc; +} + +/* Wrappers that pass in the context to the library functions */ +static int +gitlab_job_log_cb(char const *owner, char const *repo, long const jid) +{ + return gitlab_job_get_log(g_clictx, owner, repo, jid); +} + +static int +gitlab_job_cancel_cb(char const *owner, char const *repo, long const jid) +{ + return gitlab_job_cancel(g_clictx, owner, repo, jid); +} + +static int +gitlab_job_retry_cb(char const *owner, char const *repo, long const jid) +{ + return gitlab_job_retry(g_clictx, owner, repo, jid); +} + int subcommand_pipelines(int argc, char *argv[]) { @@ -283,12 +341,12 @@ subcommand_pipelines(int argc, char *argv[]) /* Definition of the action list */ struct { char const *name; /* Name on the cli */ - int (*fn)(gcli_ctx *ctx, char const *, char const *, long); /* Function to be invoked for this action */ + int (*fn)(char const *, char const *, long); /* Function to be invoked for this action */ } job_actions[] = { - { .name = "log", .fn = gitlab_job_get_log }, - { .name = "status", .fn = gitlab_job_status }, - { .name = "cancel", .fn = gitlab_job_cancel }, - { .name = "retry", .fn = gitlab_job_retry }, + { .name = "log", .fn = gitlab_job_log_cb }, + { .name = "status", .fn = gitlab_job_status }, + { .name = "cancel", .fn = gitlab_job_cancel_cb }, + { .name = "retry", .fn = gitlab_job_retry_cb }, }; /* Check if the user missed out on supplying actions */ @@ -321,7 +379,7 @@ subcommand_pipelines(int argc, char *argv[]) /* Find the action and invoke it */ for (size_t i = 0; i < ARRAY_SIZE(job_actions); ++i) { if (strcmp(action, job_actions[i].name) == 0) { - if (job_actions[i].fn(g_clictx, owner, repo, jid) < 0) + if (job_actions[i].fn(owner, repo, jid) < 0) errx(1, "error: failed to perform action '%s'", action); goto next_action; } diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index 31f560cf..25f91389 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -166,7 +166,7 @@ gitlab_job_get_log(gcli_ctx *ctx, char const *owner, char const *repo, return rc; } -static int +int gitlab_get_job(gcli_ctx *ctx, char const *owner, char const *repo, long const jid, gitlab_job *const out) { @@ -193,46 +193,6 @@ gitlab_get_job(gcli_ctx *ctx, char const *owner, char const *repo, return rc; } -static void -gitlab_print_job_status(gcli_ctx *ctx, gitlab_job const *const job) -{ - gcli_dict printer; - - (void) ctx; - - printer = gcli_dict_begin(); - - gcli_dict_add(printer, "ID", 0, 0, "%ld", job->id); - gcli_dict_add_string(printer, "STATUS", GCLI_TBLCOL_STATECOLOURED, 0, job->status); - gcli_dict_add_string(printer, "STAGE", 0, 0, job->stage); - gcli_dict_add_string(printer, "NAME", GCLI_TBLCOL_BOLD, 0, job->name); - gcli_dict_add_string(printer, "REF", GCLI_TBLCOL_COLOUREXPL, GCLI_COLOR_YELLOW, job->ref); - gcli_dict_add_string(printer, "CREATED", 0, 0, job->created_at); - gcli_dict_add_string(printer, "STARTED", 0, 0, job->started_at); - gcli_dict_add_string(printer, "FINISHED", 0, 0, job->finished_at); - gcli_dict_add(printer, "DURATION", 0, 0, "%-.2lfs", job->duration); - gcli_dict_add_string(printer, "RUNNER NAME", 0, 0, job->runner_name); - gcli_dict_add_string(printer, "RUNNER DESCR", 0, 0, job->runner_description); - - gcli_dict_end(printer); -} - -int -gitlab_job_status(gcli_ctx *ctx, char const *owner, char const *repo, - long const jid) -{ - gitlab_job job = {0}; - int rc = 0; - - rc = gitlab_get_job(ctx, owner, repo, jid, &job); - if (rc == 0) - gitlab_print_job_status(ctx, &job); - - gitlab_free_job(&job); - - return rc; -} - int gitlab_job_cancel(gcli_ctx *ctx, char const *owner, char const *repo, long const jid) From cfff65555fca45810e709f48e08eacc470856056 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 18 Aug 2023 23:40:56 +0200 Subject: [PATCH 123/236] Make gitlab_job_get_log accept a file stream to dump output to --- include/gcli/gitlab/pipelines.h | 2 +- src/cmd/pipelines.c | 2 +- src/gitlab/pipelines.c | 9 ++------- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/include/gcli/gitlab/pipelines.h b/include/gcli/gitlab/pipelines.h index 6b49c0cd..9bef2e5d 100644 --- a/include/gcli/gitlab/pipelines.h +++ b/include/gcli/gitlab/pipelines.h @@ -88,7 +88,7 @@ void gitlab_free_job(gitlab_job *job); int gitlab_job_get_log(gcli_ctx *ctx, char const *owner, char const *repo, - long job_id); + long job_id, FILE *stream); int gitlab_job_cancel(gcli_ctx *ctx, char const *owner, char const *repo, long job_id); diff --git a/src/cmd/pipelines.c b/src/cmd/pipelines.c index e1f30bec..77393b46 100644 --- a/src/cmd/pipelines.c +++ b/src/cmd/pipelines.c @@ -213,7 +213,7 @@ gitlab_job_status(char const *owner, char const *repo, long const jid) static int gitlab_job_log_cb(char const *owner, char const *repo, long const jid) { - return gitlab_job_get_log(g_clictx, owner, repo, jid); + return gitlab_job_get_log(g_clictx, owner, repo, jid, stdout); } static int diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index 25f91389..ff497a02 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -146,21 +146,16 @@ gitlab_free_jobs(gitlab_job_list *list) int gitlab_job_get_log(gcli_ctx *ctx, char const *owner, char const *repo, - long const job_id) + long const job_id, FILE *stream) { - gcli_fetch_buffer buffer = {0}; char *url = NULL; int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld/trace", gitlab_get_apibase(ctx), owner, repo, job_id); - rc = gcli_fetch(ctx, url, NULL, &buffer); - if (rc == 0) { - fwrite(buffer.data, buffer.length, 1, stdout); - } + rc = gcli_curl(ctx, stream, url, NULL); - free(buffer.data); free(url); return rc; From 89b7ec67190702f07d5629a510f7b198c0200d6e Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 18 Aug 2023 23:49:57 +0200 Subject: [PATCH 124/236] Move subcommand_repos forward declaration to separate header file --- Makefile.am | 2 +- include/gcli/cmd/cmd.h | 1 - include/gcli/cmd/repos.h | 42 ++++++++++++++++++++++++++++++++++++++++ src/cmd/gcli.c | 1 + 4 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 include/gcli/cmd/repos.h diff --git a/Makefile.am b/Makefile.am index 5de84ca8..1c9bd44d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -73,7 +73,7 @@ gcli_SOURCES = \ include/gcli/cmd/pipelines.h src/cmd/pipelines.c \ include/gcli/cmd/pulls.h src/cmd/pulls.c \ include/gcli/cmd/releases.h src/cmd/releases.c \ - src/cmd/repos.c \ + include/gcli/cmd/repos.h src/cmd/repos.c \ src/cmd/snippets.c \ src/cmd/status.c diff --git a/include/gcli/cmd/cmd.h b/include/gcli/cmd/cmd.h index c5dfe586..a53fdbee 100644 --- a/include/gcli/cmd/cmd.h +++ b/include/gcli/cmd/cmd.h @@ -67,7 +67,6 @@ int subcommand_comment(int argc, char *argv[]); int subcommand_config(int argc, char *argv[]); int subcommand_forks(int argc, char *argv[]); int subcommand_gists(int argc, char *argv[]); -int subcommand_repos(int argc, char *argv[]); int subcommand_snippets(int argc, char *argv[]); int subcommand_status(int argc, char *argv[]); diff --git a/include/gcli/cmd/repos.h b/include/gcli/cmd/repos.h new file mode 100644 index 00000000..88f204a4 --- /dev/null +++ b/include/gcli/cmd/repos.h @@ -0,0 +1,42 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CMD_REPOS_H +#define GCLI_CMD_REPOS_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +int subcommand_repos(int argc, char *argv[]); + +#endif /* GCLI_CMD_REPOS_H */ diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index 53d64a1c..fa610d97 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -46,6 +46,7 @@ #include #include #include +#include #include From ca12de6362c172d98eb46548b402a0fa28d59952 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 18 Aug 2023 23:51:04 +0200 Subject: [PATCH 125/236] Move repo printing routines out of the library code --- include/gcli/cmd/repos.h | 5 +++ include/gcli/repos.h | 5 --- src/cmd/repos.c | 74 ++++++++++++++++++++++++++++++++++++++-- src/repos.c | 72 -------------------------------------- 4 files changed, 77 insertions(+), 79 deletions(-) diff --git a/include/gcli/cmd/repos.h b/include/gcli/cmd/repos.h index 88f204a4..c7ab4653 100644 --- a/include/gcli/cmd/repos.h +++ b/include/gcli/cmd/repos.h @@ -37,6 +37,11 @@ #include #include +void gcli_print_repos(enum gcli_output_flags flags, gcli_repo_list const *repos, + int max); + +void gcli_repo_print(gcli_repo const *it); + int subcommand_repos(int argc, char *argv[]); #endif /* GCLI_CMD_REPOS_H */ diff --git a/include/gcli/repos.h b/include/gcli/repos.h index b04144e6..311bc37d 100644 --- a/include/gcli/repos.h +++ b/include/gcli/repos.h @@ -70,11 +70,6 @@ int gcli_get_own_repos(gcli_ctx *ctx, int max, gcli_repo_list *list); void gcli_repos_free(gcli_repo_list *list); void gcli_repo_free(gcli_repo *it); -void gcli_print_repos_table(gcli_ctx *ctx, enum gcli_output_flags flags, - gcli_repo_list const *repos, int max); - -void gcli_repo_print(gcli_ctx *ctx, gcli_repo const *it); - int gcli_repo_delete(gcli_ctx *ctx, char const *owner, char const *repo); int gcli_repo_create(gcli_ctx *ctx, gcli_repo_create_options const *, diff --git a/src/cmd/repos.c b/src/cmd/repos.c index 00be6624..4a4fd8f0 100644 --- a/src/cmd/repos.c +++ b/src/cmd/repos.c @@ -30,6 +30,9 @@ #include #include +#include +#include + #include #ifdef HAVE_GETOPT_H @@ -55,6 +58,73 @@ usage(void) copyright(); } +void +gcli_print_repos(enum gcli_output_flags const flags, + gcli_repo_list const *const list, int const max) +{ + size_t n; + gcli_tbl table; + gcli_tblcoldef cols[] = { + { .name = "FORK", .type = GCLI_TBLCOLTYPE_BOOL, .flags = 0 }, + { .name = "VISBLTY", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, + { .name = "DATE", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, + { .name = "FULLNAME", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, + }; + + if (list->repos_size == 0) { + puts("No repos"); + return; + } + + /* Determine number of repos to print */ + if (max < 0 || (size_t)(max) > list->repos_size) + n = list->repos_size; + else + n = max; + + /* init table */ + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + if (!table) + errx(1, "error: could not init table"); + + /* put data into table */ + if (flags & OUTPUT_SORTED) { + for (size_t i = 0; i < n; ++i) + gcli_tbl_add_row(table, + list->repos[n-i-1].is_fork, + list->repos[n-i-1].visibility, + list->repos[n-i-1].date, + list->repos[n-i-1].full_name); + } else { + for (size_t i = 0; i < n; ++i) + gcli_tbl_add_row(table, + list->repos[i].is_fork, + list->repos[i].visibility, + list->repos[i].date, + list->repos[i].full_name); + } + + /* print it */ + gcli_tbl_end(table); +} + +void +gcli_repo_print(gcli_repo const *it) +{ + gcli_dict dict; + + dict = gcli_dict_begin(); + gcli_dict_add(dict, "ID", 0, 0, "%d", it->id); + gcli_dict_add(dict, "FULL NAME", 0, 0, SV_FMT, SV_ARGS(it->full_name)); + gcli_dict_add(dict, "NAME", 0, 0, SV_FMT, SV_ARGS(it->name)); + gcli_dict_add(dict, "OWNER", 0, 0, SV_FMT, SV_ARGS(it->owner)); + gcli_dict_add(dict, "DATE", 0, 0, SV_FMT, SV_ARGS(it->date)); + gcli_dict_add(dict, "VISIBILITY", 0, 0, SV_FMT, SV_ARGS(it->visibility)); + gcli_dict_add(dict, "IS FORK", 0, 0, "%s", sn_bool_yesno(it->is_fork)); + + gcli_dict_end(dict); +} + static int subcommand_repos_create(int argc, char *argv[]) { @@ -110,7 +180,7 @@ subcommand_repos_create(int argc, char *argv[]) if (gcli_repo_create(g_clictx, &create_options, &repo) < 0) errx(1, "error: failed to create repository"); - gcli_repo_print(g_clictx, &repo); + gcli_repo_print(&repo); gcli_repo_free(&repo); return EXIT_SUCCESS; @@ -207,7 +277,7 @@ subcommand_repos(int argc, char *argv[]) if (rc < 0) errx(1, "error: failed to fetch repos"); - gcli_print_repos_table(g_clictx, flags, &repos, n); + gcli_print_repos(flags, &repos, n); gcli_repos_free(&repos); } else { check_owner_and_repo(&owner, &repo); diff --git a/src/repos.c b/src/repos.c index b6058c98..89c59673 100644 --- a/src/repos.c +++ b/src/repos.c @@ -41,78 +41,6 @@ gcli_get_repos(gcli_ctx *ctx, char const *owner, int const max, return gcli_forge(ctx)->get_repos(ctx, owner, max, out); } - -void -gcli_print_repos_table(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_repo_list const *const list, int const max) -{ - size_t n; - gcli_tbl table; - gcli_tblcoldef cols[] = { - { .name = "FORK", .type = GCLI_TBLCOLTYPE_BOOL, .flags = 0 }, - { .name = "VISBLTY", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, - { .name = "DATE", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, - { .name = "FULLNAME", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, - }; - - (void) ctx; - - if (list->repos_size == 0) { - puts("No repos"); - return; - } - - /* Determine number of repos to print */ - if (max < 0 || (size_t)(max) > list->repos_size) - n = list->repos_size; - else - n = max; - - /* init table */ - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); - if (!table) - errx(1, "error: could not init table"); - - /* put data into table */ - if (flags & OUTPUT_SORTED) { - for (size_t i = 0; i < n; ++i) - gcli_tbl_add_row(table, - list->repos[n-i-1].is_fork, - list->repos[n-i-1].visibility, - list->repos[n-i-1].date, - list->repos[n-i-1].full_name); - } else { - for (size_t i = 0; i < n; ++i) - gcli_tbl_add_row(table, - list->repos[i].is_fork, - list->repos[i].visibility, - list->repos[i].date, - list->repos[i].full_name); - } - - /* print it */ - gcli_tbl_end(table); -} - -void -gcli_repo_print(gcli_ctx *ctx, gcli_repo const *it) -{ - gcli_dict dict; - - (void) ctx; - - dict = gcli_dict_begin(); - gcli_dict_add(dict, "ID", 0, 0, "%d", it->id); - gcli_dict_add(dict, "FULL NAME", 0, 0, SV_FMT, SV_ARGS(it->full_name)); - gcli_dict_add(dict, "NAME", 0, 0, SV_FMT, SV_ARGS(it->name)); - gcli_dict_add(dict, "OWNER", 0, 0, SV_FMT, SV_ARGS(it->owner)); - gcli_dict_add(dict, "DATE", 0, 0, SV_FMT, SV_ARGS(it->date)); - gcli_dict_add(dict, "VISIBILITY", 0, 0, SV_FMT, SV_ARGS(it->visibility)); - gcli_dict_add(dict, "IS FORK", 0, 0, "%s", sn_bool_yesno(it->is_fork)); - - gcli_dict_end(dict); -} - void gcli_repo_free(gcli_repo *it) { From e33e69981ab07d63db20ad9a7667a1b4c247f15a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 18 Aug 2023 23:54:53 +0200 Subject: [PATCH 126/236] Create new cmd header for forks and move subcommand declaration to it --- Makefile.am | 2 +- include/gcli/cmd/cmd.h | 1 - include/gcli/cmd/forks.h | 41 ++++++++++++++++++++++++++++++++++++++++ src/cmd/gcli.c | 1 + 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 include/gcli/cmd/forks.h diff --git a/Makefile.am b/Makefile.am index 1c9bd44d..c36d561e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -64,7 +64,7 @@ gcli_SOURCES = \ src/cmd/ci.c \ src/cmd/comment.c \ src/cmd/config.c \ - src/cmd/forks.c \ + include/gcli/cmd/forks.h src/cmd/forks.c \ src/cmd/gcli.c \ src/cmd/gists.c \ include/gcli/cmd/issues.h src/cmd/issues.c \ diff --git a/include/gcli/cmd/cmd.h b/include/gcli/cmd/cmd.h index a53fdbee..b21b07da 100644 --- a/include/gcli/cmd/cmd.h +++ b/include/gcli/cmd/cmd.h @@ -65,7 +65,6 @@ void delete_repo(bool always_yes, const char *owner, const char *repo); int subcommand_api(int argc, char *argv[]); int subcommand_comment(int argc, char *argv[]); int subcommand_config(int argc, char *argv[]); -int subcommand_forks(int argc, char *argv[]); int subcommand_gists(int argc, char *argv[]); int subcommand_snippets(int argc, char *argv[]); int subcommand_status(int argc, char *argv[]); diff --git a/include/gcli/cmd/forks.h b/include/gcli/cmd/forks.h new file mode 100644 index 00000000..a22476fc --- /dev/null +++ b/include/gcli/cmd/forks.h @@ -0,0 +1,41 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CMD_FORKS_H +#define GCLI_CMD_FORKS_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +int subcommand_forks(int argc, char *argv[]); + +#endif /* GCLI_CMD_FORKS_H */ diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index fa610d97..bdfa0985 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -40,6 +40,7 @@ #include #include +#include #include #include #include From ed9c89f6213373d9af870b3adccf8ac16153b34e Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 18 Aug 2023 23:58:16 +0200 Subject: [PATCH 127/236] Move fork printing code out of the library --- include/gcli/cmd/forks.h | 4 +++ include/gcli/forks.h | 3 --- src/cmd/forks.c | 57 ++++++++++++++++++++++++++++++++++++++-- src/forks.c | 51 ----------------------------------- 4 files changed, 59 insertions(+), 56 deletions(-) diff --git a/include/gcli/cmd/forks.h b/include/gcli/cmd/forks.h index a22476fc..9c40d781 100644 --- a/include/gcli/cmd/forks.h +++ b/include/gcli/cmd/forks.h @@ -34,8 +34,12 @@ #include #endif +#include #include int subcommand_forks(int argc, char *argv[]); +void gcli_print_forks(enum gcli_output_flags flags, gcli_fork_list const *list, + int max); + #endif /* GCLI_CMD_FORKS_H */ diff --git a/include/gcli/forks.h b/include/gcli/forks.h index d493d789..b913faa9 100644 --- a/include/gcli/forks.h +++ b/include/gcli/forks.h @@ -58,9 +58,6 @@ int gcli_get_forks(gcli_ctx *ctx, char const *owner, char const *reponame, int gcli_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, char const *in); -void gcli_print_forks(gcli_ctx *ctx, enum gcli_output_flags flags, - gcli_fork_list const *list, int max); - void gcli_fork_delete(char const *owner, char const *repo); diff --git a/src/cmd/forks.c b/src/cmd/forks.c index ed3f4525..6559ce5f 100644 --- a/src/cmd/forks.c +++ b/src/cmd/forks.c @@ -36,6 +36,9 @@ #include #include +#include +#include + #include #include #include @@ -57,6 +60,55 @@ usage(void) copyright(); } +void +gcli_print_forks(enum gcli_output_flags const flags, + gcli_fork_list const *const list, int const max) +{ + size_t n; + gcli_tbl table; + gcli_tblcoldef cols[] = { + { .name = "OWNER", .type = GCLI_TBLCOLTYPE_SV, .flags = GCLI_TBLCOL_BOLD }, + { .name = "DATE", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, + { .name = "FORKS", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, + { .name = "FULLNAME", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, + }; + + if (list->forks_size == 0) { + puts("No forks"); + return; + } + + /* Determine number of items to print */ + if (max < 0 || (size_t)(max) > list->forks_size) + n = list->forks_size; + else + n = max; + + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + if (!table) + errx(1, "error: could not initialize table"); + + if (flags & OUTPUT_SORTED) { + for (size_t i = 0; i < n; ++i) { + gcli_tbl_add_row(table, + list->forks[n-i-1].owner, + list->forks[n-i-1].date, + list->forks[n-i-1].forks, + list->forks[n-i-1].full_name); + } + } else { + for (size_t i = 0; i < n; ++i) { + gcli_tbl_add_row(table, + list->forks[i].owner, + list->forks[i].date, + list->forks[i].forks, + list->forks[i].full_name); + } + } + + gcli_tbl_end(table); +} + static int subcommand_forks_create(int argc, char *argv[]) { @@ -204,9 +256,10 @@ subcommand_forks(int argc, char *argv[]) if (argc == 0) { if (gcli_get_forks(g_clictx, owner, repo, count, &forks) < 0) - errx(1, "error: could not get forks"); + errx(1, "error: could not get forks: %s", + gcli_get_error(g_clictx)); - gcli_print_forks(g_clictx, flags, &forks, count); + gcli_print_forks(flags, &forks, count); gcli_forks_free(&forks); return EXIT_SUCCESS; diff --git a/src/forks.c b/src/forks.c index efeb8ef5..e8656064 100644 --- a/src/forks.c +++ b/src/forks.c @@ -40,57 +40,6 @@ gcli_get_forks(gcli_ctx *ctx, char const *owner, char const *repo, return gcli_forge(ctx)->get_forks(ctx, owner, repo, max, out); } -void -gcli_print_forks(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_fork_list const *const list, int const max) -{ - size_t n; - gcli_tbl table; - gcli_tblcoldef cols[] = { - { .name = "OWNER", .type = GCLI_TBLCOLTYPE_SV, .flags = GCLI_TBLCOL_BOLD }, - { .name = "DATE", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, - { .name = "FORKS", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, - { .name = "FULLNAME", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, - }; - - (void) ctx; - - if (list->forks_size == 0) { - puts("No forks"); - return; - } - - /* Determine number of items to print */ - if (max < 0 || (size_t)(max) > list->forks_size) - n = list->forks_size; - else - n = max; - - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); - if (!table) - errx(1, "error: could not initialize table"); - - if (flags & OUTPUT_SORTED) { - for (size_t i = 0; i < n; ++i) { - gcli_tbl_add_row(table, - list->forks[n-i-1].owner, - list->forks[n-i-1].date, - list->forks[n-i-1].forks, - list->forks[n-i-1].full_name); - } - } else { - for (size_t i = 0; i < n; ++i) { - gcli_tbl_add_row(table, - list->forks[i].owner, - list->forks[i].date, - list->forks[i].forks, - list->forks[i].full_name); - } - } - - gcli_tbl_end(table); -} - int gcli_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, char const *_in) From 43c8b3d239bdaaa624ecd1f7e2a002102eff1b00 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 18 Aug 2023 23:59:24 +0200 Subject: [PATCH 128/236] Add missing ci.h cmd header to Makefile.am --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index c36d561e..ff227ab1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -61,7 +61,7 @@ gcli_SOURCES = \ include/gcli/cmd/colour.h src/cmd/colour.c \ include/gcli/cmd/table.h src/cmd/table.c \ src/cmd/api.c \ - src/cmd/ci.c \ + include/gcli/cmd/ci.h src/cmd/ci.c \ src/cmd/comment.c \ src/cmd/config.c \ include/gcli/cmd/forks.h src/cmd/forks.c \ From 921c72454506f6ddb47517e5548daafd15421341 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 19 Aug 2023 00:02:05 +0200 Subject: [PATCH 129/236] Add new config cmd header and move subcommand declaration to it --- Makefile.am | 2 +- include/gcli/cmd/cmd.h | 1 - include/gcli/cmd/config.h | 41 +++++++++++++++++++++++++++++++++++++++ src/cmd/gcli.c | 1 + 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 include/gcli/cmd/config.h diff --git a/Makefile.am b/Makefile.am index ff227ab1..98b29142 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,7 +63,7 @@ gcli_SOURCES = \ src/cmd/api.c \ include/gcli/cmd/ci.h src/cmd/ci.c \ src/cmd/comment.c \ - src/cmd/config.c \ + include/gcli/cmd/config.h src/cmd/config.c \ include/gcli/cmd/forks.h src/cmd/forks.c \ src/cmd/gcli.c \ src/cmd/gists.c \ diff --git a/include/gcli/cmd/cmd.h b/include/gcli/cmd/cmd.h index b21b07da..23053495 100644 --- a/include/gcli/cmd/cmd.h +++ b/include/gcli/cmd/cmd.h @@ -64,7 +64,6 @@ void delete_repo(bool always_yes, const char *owner, const char *repo); /* List of subcommand entry points */ int subcommand_api(int argc, char *argv[]); int subcommand_comment(int argc, char *argv[]); -int subcommand_config(int argc, char *argv[]); int subcommand_gists(int argc, char *argv[]); int subcommand_snippets(int argc, char *argv[]); int subcommand_status(int argc, char *argv[]); diff --git a/include/gcli/cmd/config.h b/include/gcli/cmd/config.h new file mode 100644 index 00000000..06107ffd --- /dev/null +++ b/include/gcli/cmd/config.h @@ -0,0 +1,41 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CMD_CONFIG_H +#define GCLI_CMD_CONFIG_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +int subcommand_config(int argc, char *argv[]); + +#endif /* GCLI_CMD_CONFIG_H */ diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index bdfa0985..6819b793 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -40,6 +40,7 @@ #include #include +#include #include #include #include From 719c9c2588024044150706130d4b81575d45d5bc Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 19 Aug 2023 00:05:13 +0200 Subject: [PATCH 130/236] Move ssh key printing code out of library --- include/gcli/cmd/config.h | 3 +++ include/gcli/sshkeys.h | 1 - src/cmd/config.c | 30 +++++++++++++++++++++++++++++- src/sshkeys.c | 27 --------------------------- 4 files changed, 32 insertions(+), 29 deletions(-) diff --git a/include/gcli/cmd/config.h b/include/gcli/cmd/config.h index 06107ffd..7e0ce117 100644 --- a/include/gcli/cmd/config.h +++ b/include/gcli/cmd/config.h @@ -35,6 +35,9 @@ #endif #include +#include + +void gcli_sshkeys_print_keys(gcli_sshkey_list const *list); int subcommand_config(int argc, char *argv[]); diff --git a/include/gcli/sshkeys.h b/include/gcli/sshkeys.h index 16e4c29d..9ebf2cce 100644 --- a/include/gcli/sshkeys.h +++ b/include/gcli/sshkeys.h @@ -57,7 +57,6 @@ int gcli_sshkeys_get_keys(gcli_ctx *ctx, gcli_sshkey_list *out); int gcli_sshkeys_add_key(gcli_ctx *ctx, char const *title, char const *public_key_path, gcli_sshkey *out); int gcli_sshkeys_delete_key(gcli_ctx *ctx, int id); -void gcli_sshkeys_print_keys(gcli_ctx *ctx, gcli_sshkey_list const *list); void gcli_sshkeys_free_keys(gcli_sshkey_list *list); #endif /* GCLI_SSHKEYS_H */ diff --git a/src/cmd/config.c b/src/cmd/config.c index 88aec8f5..226b5704 100644 --- a/src/cmd/config.c +++ b/src/cmd/config.c @@ -32,6 +32,9 @@ #endif #include +#include +#include + #include #include @@ -55,6 +58,31 @@ usage(void) copyright(); } +void +gcli_sshkeys_print_keys(gcli_sshkey_list const *list) +{ + gcli_tbl *tbl; + gcli_tblcoldef cols[] = { + { .name = "ID", .type = GCLI_TBLCOLTYPE_INT, .flags = 0 }, + { .name = "CREATED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "TITLE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + }; + + if (list->keys_size == 0) { + printf("No SSH keys\n"); + return; + } + + tbl = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + + for (size_t i = 0; i < list->keys_size; ++i) { + gcli_tbl_add_row(tbl, list->keys[i].id, list->keys[i].created_at, + list->keys[i].title); + } + + gcli_tbl_end(tbl); +} + static int list_sshkeys(void) { @@ -65,7 +93,7 @@ list_sshkeys(void) return EXIT_FAILURE; } - gcli_sshkeys_print_keys(g_clictx, &list); + gcli_sshkeys_print_keys(&list); gcli_sshkeys_free_keys(&list); return 0; diff --git a/src/sshkeys.c b/src/sshkeys.c index 61380352..ad9f47f5 100644 --- a/src/sshkeys.c +++ b/src/sshkeys.c @@ -42,33 +42,6 @@ gcli_sshkeys_get_keys(gcli_ctx *ctx, gcli_sshkey_list *out) return gcli_forge(ctx)->get_sshkeys(ctx, out); } -void -gcli_sshkeys_print_keys(gcli_ctx *ctx, gcli_sshkey_list const *list) -{ - gcli_tbl *tbl; - gcli_tblcoldef cols[] = { - { .name = "ID", .type = GCLI_TBLCOLTYPE_INT, .flags = 0 }, - { .name = "CREATED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "TITLE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - }; - - (void) ctx; - - - if (list->keys_size == 0) { - printf("No SSH keys\n"); - return; - } - - tbl = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); - - for (size_t i = 0; i < list->keys_size; ++i) { - gcli_tbl_add_row(tbl, list->keys[i].id, list->keys[i].created_at, list->keys[i].title); - } - - gcli_tbl_end(tbl); -} - void gcli_sshkeys_free_keys(gcli_sshkey_list *list) { From 720182604ff80ffeefcc0ad566ec5e3cde9bd3bb Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 19 Aug 2023 00:07:34 +0200 Subject: [PATCH 131/236] Add new comment cmd header and move subcommand declaration to it --- Makefile.am | 2 +- include/gcli/cmd/cmd.h | 1 - include/gcli/cmd/comment.h | 41 ++++++++++++++++++++++++++++++++++++++ src/cmd/gcli.c | 1 + 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 include/gcli/cmd/comment.h diff --git a/Makefile.am b/Makefile.am index 98b29142..9ce19fbe 100644 --- a/Makefile.am +++ b/Makefile.am @@ -62,7 +62,7 @@ gcli_SOURCES = \ include/gcli/cmd/table.h src/cmd/table.c \ src/cmd/api.c \ include/gcli/cmd/ci.h src/cmd/ci.c \ - src/cmd/comment.c \ + include/gcli/cmd/comment.h src/cmd/comment.c \ include/gcli/cmd/config.h src/cmd/config.c \ include/gcli/cmd/forks.h src/cmd/forks.c \ src/cmd/gcli.c \ diff --git a/include/gcli/cmd/cmd.h b/include/gcli/cmd/cmd.h index 23053495..49205d46 100644 --- a/include/gcli/cmd/cmd.h +++ b/include/gcli/cmd/cmd.h @@ -63,7 +63,6 @@ void delete_repo(bool always_yes, const char *owner, const char *repo); /* List of subcommand entry points */ int subcommand_api(int argc, char *argv[]); -int subcommand_comment(int argc, char *argv[]); int subcommand_gists(int argc, char *argv[]); int subcommand_snippets(int argc, char *argv[]); int subcommand_status(int argc, char *argv[]); diff --git a/include/gcli/cmd/comment.h b/include/gcli/cmd/comment.h new file mode 100644 index 00000000..311efc02 --- /dev/null +++ b/include/gcli/cmd/comment.h @@ -0,0 +1,41 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CMD_COMMENT_H +#define GCLI_CMD_COMMENT_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +int subcommand_comment(int argc, char *argv[]); + +#endif /* GCLI_CMD_COMMENT_H */ diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index 6819b793..230853db 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -40,6 +40,7 @@ #include #include +#include #include #include #include From 21bdfb86127a49c43d5d9b2656a26f10f2145a58 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 19 Aug 2023 00:21:21 +0200 Subject: [PATCH 132/236] Move comment printing routines out of library code --- include/gcli/cmd/comment.h | 4 ++++ include/gcli/comments.h | 13 ++++++----- src/cmd/comment.c | 48 ++++++++++++++++++++++++++++++++++++++ src/cmd/issues.c | 5 +++- src/cmd/pulls.c | 5 +++- src/comments.c | 40 ------------------------------- 6 files changed, 67 insertions(+), 48 deletions(-) diff --git a/include/gcli/cmd/comment.h b/include/gcli/cmd/comment.h index 311efc02..ce7a429b 100644 --- a/include/gcli/cmd/comment.h +++ b/include/gcli/cmd/comment.h @@ -34,8 +34,12 @@ #include #endif +#include #include +int gcli_issue_comments(char const *owner, char const *repo, int issue); +int gcli_pull_comments(char const *owner, char const *repo, int pull); +void gcli_print_comment_list(gcli_comment_list const *list); int subcommand_comment(int argc, char *argv[]); #endif /* GCLI_CMD_COMMENT_H */ diff --git a/include/gcli/comments.h b/include/gcli/comments.h index c39d3648..9c51f8a8 100644 --- a/include/gcli/comments.h +++ b/include/gcli/comments.h @@ -66,12 +66,13 @@ struct gcli_submit_comment_opts { }; void gcli_comment_list_free(gcli_comment_list *list); -void gcli_print_comment_list(gcli_ctx *, gcli_comment_list const *list); -void gcli_issue_comments(gcli_ctx *ctx, - char const *owner, char const *repo, - int issue); -void gcli_pull_comments(gcli_ctx *ctx, char const *owner, char const *repo, - int issue); + +int gcli_get_issue_comments(gcli_ctx *ctx, char const *owner, char const *repo, + int issue, gcli_comment_list *out); + +int gcli_get_pull_comments(gcli_ctx *ctx, char const *owner, char const *repo, + int issue, gcli_comment_list *out); + int gcli_comment_submit(gcli_ctx *ctx, gcli_submit_comment_opts opts); #endif /* COMMENTS_H */ diff --git a/src/cmd/comment.c b/src/cmd/comment.c index c6efbefc..b1036a5b 100644 --- a/src/cmd/comment.c +++ b/src/cmd/comment.c @@ -30,6 +30,9 @@ #include #include +#include +#include + #include #ifdef HAVE_GETOPT_H @@ -50,6 +53,51 @@ usage(void) copyright(); } +int +gcli_issue_comments(char const *owner, char const *repo, int const issue) +{ + gcli_comment_list list = {0}; + int rc = 0; + + rc = gcli_get_issue_comments(g_clictx, owner, repo, issue, &list); + if (rc < 0) + return rc; + + gcli_print_comment_list(&list); + gcli_comment_list_free(&list); + + return rc; +} + +int +gcli_pull_comments(char const *owner, char const *repo, int const pull) +{ + gcli_comment_list list = {0}; + int rc = 0; + + rc = gcli_get_pull_comments(g_clictx, owner, repo, pull, &list); + if (rc < 0) + return rc; + + gcli_print_comment_list(&list); + gcli_comment_list_free(&list); + + return rc; +} + +void +gcli_print_comment_list(gcli_comment_list const *const list) +{ + for (size_t i = 0; i < list->comments_size; ++i) { + printf("AUTHOR : %s%s%s\n" + "DATE : %s\n", + gcli_setbold(), list->comments[i].author, gcli_resetbold(), + list->comments[i].date); + pretty_print(list->comments[i].body, 9, 80, stdout); + putchar('\n'); + } +} + int subcommand_comment(int argc, char *argv[]) { diff --git a/src/cmd/issues.c b/src/cmd/issues.c index 1d294e7f..8ee8263c 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -505,7 +506,9 @@ handle_issues_actions(int argc, char *argv[], } else if (strcmp("comments", operation) == 0 || strcmp("notes", operation) == 0) { /* Doesn't require fetching the issue data */ - gcli_issue_comments(g_clictx, owner, repo, issue_id); + if (gcli_issue_comments(owner, repo, issue_id) < 0) + errx(1, "error: failed to fetch issue comments: %s", + gcli_get_error(g_clictx)); } else if (strcmp("op", operation) == 0) { /* Make sure we have fetched the issue data */ diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 37ddfbae..88c7bf30 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -668,7 +669,9 @@ handle_pull_actions(int argc, char *argv[], } else if (strcmp(action, "comments") == 0 || strcmp(action, "notes") == 0) { - gcli_pull_comments(g_clictx, owner, repo, pr); + if (gcli_pull_comments(owner, repo, pr) < 0) + errx(1, "error: failed to fetch pull comments: %s", + gcli_get_error(g_clictx)); } else if (strcmp(action, "ci") == 0) { if (gcli_pull_checks(owner, repo, pr) < 0) diff --git a/src/comments.c b/src/comments.c index 93ff9aa5..341a24f2 100644 --- a/src/comments.c +++ b/src/comments.c @@ -56,20 +56,6 @@ gcli_comment_list_free(gcli_comment_list *list) list->comments_size = 0; } -void -gcli_print_comment_list(gcli_ctx *ctx, gcli_comment_list const *const list) -{ - (void) ctx; - for (size_t i = 0; i < list->comments_size; ++i) { - printf("AUTHOR : %s%s%s\n" - "DATE : %s\n", - gcli_setbold(), list->comments[i].author, gcli_resetbold(), - list->comments[i].date); - pretty_print(list->comments[i].body, 9, 80, stdout); - putchar('\n'); - } -} - int gcli_get_issue_comments(gcli_ctx *ctx, char const *owner, char const *repo, int const issue, gcli_comment_list *out) @@ -77,19 +63,6 @@ gcli_get_issue_comments(gcli_ctx *ctx, char const *owner, char const *repo, return gcli_forge(ctx)->get_issue_comments(ctx, owner, repo, issue, out); } -void -gcli_issue_comments(gcli_ctx *ctx, char const *owner, - char const *repo, int const issue) -{ - gcli_comment_list list = {0}; - - if (gcli_get_issue_comments(ctx, owner, repo, issue, &list) < 0) - errx(1, "error: failed to fetch comments"); - - gcli_print_comment_list(ctx, &list); - gcli_comment_list_free(&list); -} - int gcli_get_pull_comments(gcli_ctx *ctx, char const *owner, char const *repo, int const pull, gcli_comment_list *out) @@ -97,19 +70,6 @@ gcli_get_pull_comments(gcli_ctx *ctx, char const *owner, char const *repo, return gcli_forge(ctx)->get_pull_comments(ctx, owner, repo, pull, out); } -void -gcli_pull_comments(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue) -{ - gcli_comment_list list = {0}; - - if (gcli_get_pull_comments(ctx, owner, repo, issue, &list) < 0) - errx(1, "error: failed to fetch pull request comments"); - - gcli_print_comment_list(ctx, &list); - gcli_comment_list_free(&list); -} - static void comment_init(gcli_ctx *ctx, FILE *f, void *_data) { From 6e7fedbeec33e7cfab09987bd743214a1aa04ebd Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 19 Aug 2023 00:23:21 +0200 Subject: [PATCH 133/236] Add new cmd header for ci and move subcommand_ci declaration to it --- Makefile.am | 2 +- include/gcli/cmd/cmd.h | 1 - include/gcli/cmd/gists.h | 39 +++++++++++++++++++++++++++++++++++++++ src/cmd/gcli.c | 1 + 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 include/gcli/cmd/gists.h diff --git a/Makefile.am b/Makefile.am index 9ce19fbe..e13ba0ef 100644 --- a/Makefile.am +++ b/Makefile.am @@ -66,7 +66,7 @@ gcli_SOURCES = \ include/gcli/cmd/config.h src/cmd/config.c \ include/gcli/cmd/forks.h src/cmd/forks.c \ src/cmd/gcli.c \ - src/cmd/gists.c \ + include/gcli/cmd/gists.h src/cmd/gists.c \ include/gcli/cmd/issues.h src/cmd/issues.c \ include/gcli/cmd/labels.h src/cmd/labels.c \ include/gcli/cmd/milestones.h src/cmd/milestones.c \ diff --git a/include/gcli/cmd/cmd.h b/include/gcli/cmd/cmd.h index 49205d46..df7caa0c 100644 --- a/include/gcli/cmd/cmd.h +++ b/include/gcli/cmd/cmd.h @@ -63,7 +63,6 @@ void delete_repo(bool always_yes, const char *owner, const char *repo); /* List of subcommand entry points */ int subcommand_api(int argc, char *argv[]); -int subcommand_gists(int argc, char *argv[]); int subcommand_snippets(int argc, char *argv[]); int subcommand_status(int argc, char *argv[]); diff --git a/include/gcli/cmd/gists.h b/include/gcli/cmd/gists.h new file mode 100644 index 00000000..d547e8cb --- /dev/null +++ b/include/gcli/cmd/gists.h @@ -0,0 +1,39 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CMD_GISTS_H +#define GCLI_CMD_GISTS_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +int subcommand_gists(int argc, char *argv[]); + +#endif /* GCLI_CMD_GISTS_H */ diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index 230853db..f8ed5927 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include From f2f3cf932e093922a6e1f96632ccde267c6291b8 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 19 Aug 2023 00:27:00 +0200 Subject: [PATCH 134/236] Move github ci print routines out of library code --- include/gcli/cmd/ci.h | 4 +++- src/cmd/ci.c | 47 +++++++++++++++++++++++++++++++++++++++---- src/github/checks.c | 34 ------------------------------- 3 files changed, 46 insertions(+), 39 deletions(-) diff --git a/include/gcli/cmd/ci.h b/include/gcli/cmd/ci.h index cfa329a3..e7767c98 100644 --- a/include/gcli/cmd/ci.h +++ b/include/gcli/cmd/ci.h @@ -37,7 +37,9 @@ #include void github_print_checks(github_check_list const *checks); - +void github_print_checks(github_check_list const *const list); +int github_checks(char const *const owner, char const *const repo, + char const *const ref, int const max); int subcommand_ci(int argc, char *argv[]); #endif /* GCLI_CMD_CI_H */ diff --git a/src/cmd/ci.c b/src/cmd/ci.c index ac32b59a..bfef0856 100644 --- a/src/cmd/ci.c +++ b/src/cmd/ci.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -58,16 +59,51 @@ usage(void) } void +github_print_checks(github_check_list const *const list) +{ + gcli_tbl table; + gcli_tblcoldef cols[] = { + { .name = "ID", .type = GCLI_TBLCOLTYPE_LONG, .flags = GCLI_TBLCOL_JUSTIFYR }, + { .name = "STATUS", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "CONCLUSION", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_STATECOLOURED }, + { .name = "STARTED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "COMPLETED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "NAME", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + }; + + if (!list->checks_size) { + fprintf(stderr, "No checks\n"); + return; + } + + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + if (!table) + errx(1, "error: could not init table"); + + for (size_t i = 0; i < list->checks_size; ++i) { + gcli_tbl_add_row(table, list->checks[i].id, list->checks[i].status, + list->checks[i].conclusion, list->checks[i].started_at, + list->checks[i].completed_at, list->checks[i].name); + } + + gcli_tbl_end(table); +} + +int github_checks(char const *const owner, char const *const repo, char const *const ref, int const max) { github_check_list list = {0}; - if (github_get_checks(g_clictx, owner, repo, ref, max, &list) < 0) - errx(1, "error: failed to get github checks: %s", - gcli_get_error(g_clictx)); + int rc = 0; + + rc = github_get_checks(g_clictx, owner, repo, ref, max, &list); + if (rc < 0) + return rc; github_print_checks(&list); github_free_checks(&list); + + return rc; } int @@ -135,7 +171,10 @@ subcommand_ci(int argc, char *argv[]) errx(1, "error: The ci subcommand only works for GitHub. " "Use gcli -t github ... to force a GitHub remote."); - github_checks(owner, repo, ref, count); + if (github_checks(owner, repo, ref, count) < 0) + errx(1, "error: failed to get github checks: %s", + gcli_get_error(g_clictx)); + return EXIT_SUCCESS; } diff --git a/src/github/checks.c b/src/github/checks.c index d93b7e6a..c83dc29a 100644 --- a/src/github/checks.c +++ b/src/github/checks.c @@ -78,40 +78,6 @@ github_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, return rc; } -void -github_print_checks(gcli_ctx *ctx, github_check_list const *const list) -{ - gcli_tbl table; - gcli_tblcoldef cols[] = { - { .name = "ID", .type = GCLI_TBLCOLTYPE_LONG, .flags = GCLI_TBLCOL_JUSTIFYR }, - { .name = "STATUS", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "CONCLUSION", .type = GCLI_TBLCOLTYPE_STRING, .flags = GCLI_TBLCOL_STATECOLOURED }, - { .name = "STARTED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "COMPLETED", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "NAME", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - }; - - (void) ctx; - - - if (!list->checks_size) { - fprintf(stderr, "No checks\n"); - return; - } - - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); - if (!table) - errx(1, "error: could not init table"); - - for (size_t i = 0; i < list->checks_size; ++i) { - gcli_tbl_add_row(table, list->checks[i].id, list->checks[i].status, - list->checks[i].conclusion, list->checks[i].started_at, - list->checks[i].completed_at, list->checks[i].name); - } - - gcli_tbl_end(table); -} - void github_free_checks(github_check_list *const list) { From ce3f5b5f19d14299b4e5a5de714d5b3eab17a2f5 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 19 Aug 2023 00:28:52 +0200 Subject: [PATCH 135/236] Move snippets cmd declaration to separate header --- Makefile.am | 2 +- include/gcli/cmd/cmd.h | 1 - include/gcli/cmd/snippets.h | 41 +++++++++++++++++++++++++++++++++++++ src/cmd/gcli.c | 1 + 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 include/gcli/cmd/snippets.h diff --git a/Makefile.am b/Makefile.am index e13ba0ef..d775598c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -74,7 +74,7 @@ gcli_SOURCES = \ include/gcli/cmd/pulls.h src/cmd/pulls.c \ include/gcli/cmd/releases.h src/cmd/releases.c \ include/gcli/cmd/repos.h src/cmd/repos.c \ - src/cmd/snippets.c \ + include/gcli/cmd/snippets.h src/cmd/snippets.c \ src/cmd/status.c libsn_la_SOURCES = \ diff --git a/include/gcli/cmd/cmd.h b/include/gcli/cmd/cmd.h index df7caa0c..048878e5 100644 --- a/include/gcli/cmd/cmd.h +++ b/include/gcli/cmd/cmd.h @@ -63,7 +63,6 @@ void delete_repo(bool always_yes, const char *owner, const char *repo); /* List of subcommand entry points */ int subcommand_api(int argc, char *argv[]); -int subcommand_snippets(int argc, char *argv[]); int subcommand_status(int argc, char *argv[]); #endif /* GCLI_CMD_CMD_H */ diff --git a/include/gcli/cmd/snippets.h b/include/gcli/cmd/snippets.h new file mode 100644 index 00000000..1ce7f073 --- /dev/null +++ b/include/gcli/cmd/snippets.h @@ -0,0 +1,41 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CMD_SNIPPETS_H +#define GCLI_CMD_SNIPPETS_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +int subcommand_snippets(int argc, char *argv[]); + +#endif /* GCLI_CMD_SNIPPETS_H */ diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index f8ed5927..237c4721 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -51,6 +51,7 @@ #include #include #include +#include #include From 7eb438aecd579ed3720e84a1b0932880b1cdcd10 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 19 Aug 2023 00:32:07 +0200 Subject: [PATCH 136/236] Move snippet printing code out of the library --- include/gcli/cmd/snippets.h | 4 ++ include/gcli/gitlab/snippets.h | 3 - src/cmd/snippets.c | 107 ++++++++++++++++++++++++++++++++- src/gitlab/snippets.c | 106 -------------------------------- 4 files changed, 110 insertions(+), 110 deletions(-) diff --git a/include/gcli/cmd/snippets.h b/include/gcli/cmd/snippets.h index 1ce7f073..68fdc5da 100644 --- a/include/gcli/cmd/snippets.h +++ b/include/gcli/cmd/snippets.h @@ -36,6 +36,10 @@ #include +#include + +void gcli_snippets_print(enum gcli_output_flags const flags, + gcli_snippet_list const *const list, int const max); int subcommand_snippets(int argc, char *argv[]); #endif /* GCLI_CMD_SNIPPETS_H */ diff --git a/include/gcli/gitlab/snippets.h b/include/gcli/gitlab/snippets.h index d766a6a7..6aca6d5f 100644 --- a/include/gcli/gitlab/snippets.h +++ b/include/gcli/gitlab/snippets.h @@ -58,9 +58,6 @@ void gcli_snippets_free(gcli_snippet_list *list); int gcli_snippets_get(gcli_ctx *ctx, int max, gcli_snippet_list *out); -void gcli_snippets_print(gcli_ctx *ctx, enum gcli_output_flags flags, - gcli_snippet_list const *list, int max); - int gcli_snippet_delete(gcli_ctx *ctx, char const *snippet_id); int gcli_snippet_get(gcli_ctx *ctx, char const *snippet_id); diff --git a/src/cmd/snippets.c b/src/cmd/snippets.c index df3a8ce0..04c20609 100644 --- a/src/cmd/snippets.c +++ b/src/cmd/snippets.c @@ -30,6 +30,8 @@ #include #include +#include + #include #ifdef HAVE_GETOPT_H @@ -54,6 +56,109 @@ usage(void) copyright(); } +static void +gcli_print_snippet(enum gcli_output_flags const flags, + gcli_snippet const *const it) +{ + gcli_dict dict; + + (void) flags; + + dict = gcli_dict_begin(); + + gcli_dict_add(dict, "ID", 0, 0, "%d", it->id); + gcli_dict_add_string(dict, "TITLE", 0, 0, it->title); + gcli_dict_add_string(dict, "AUTHOR", 0, 0, it->author); + gcli_dict_add_string(dict, "FILE", 0, 0, it->filename); + gcli_dict_add_string(dict, "DATE", 0, 0, it->date); + gcli_dict_add_string(dict, "VSBLTY", 0, 0, it->visibility); + gcli_dict_add_string(dict, "URL", 0, 0, it->raw_url); + + gcli_dict_end(dict); +} + +static void +gcli_print_snippets_long(enum gcli_output_flags const flags, + gcli_snippet_list const *const list, int const max) +{ + int n; + + /* Determine number of items to print */ + if (max < 0 || (size_t)(max) > list->snippets_size) + n = list->snippets_size; + else + n = max; + + if (flags & OUTPUT_SORTED) { + for (int i = 0; i < n; ++i) + gcli_print_snippet(flags, &list->snippets[n-i-1]); + } else { + for (int i = 0; i < n; ++i) + gcli_print_snippet(flags, &list->snippets[i]); + } +} + +static void +gcli_print_snippets_short(enum gcli_output_flags const flags, + gcli_snippet_list const *const list, int const max) +{ + int n; + gcli_tbl table; + gcli_tblcoldef cols[] = { + { .name = "ID", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, + { .name = "DATE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "VISIBILITY", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "AUTHOR", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + { .name = "TITLE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, + }; + + /* Determine number of items to print */ + if (max < 0 || (size_t)(max) > list->snippets_size) + n = list->snippets_size; + else + n = max; + + /* Fill table */ + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + if (!table) + errx(1, "error: could not init table"); + + if (flags & OUTPUT_SORTED) { + for (int i = 0; i < n; ++i) + gcli_tbl_add_row(table, + list->snippets[n-i-1].id, + list->snippets[n-i-1].date, + list->snippets[n-i-1].visibility, + list->snippets[n-i-1].author, + list->snippets[n-i-1].title); + } else { + for (int i = 0; i < n; ++i) + gcli_tbl_add_row(table, + list->snippets[i].id, + list->snippets[i].date, + list->snippets[i].visibility, + list->snippets[i].author, + list->snippets[i].title); + } + + gcli_tbl_end(table); +} + +void +gcli_snippets_print(enum gcli_output_flags const flags, + gcli_snippet_list const *const list, int const max) +{ + if (list->snippets_size == 0) { + puts("No Snippets"); + return; + } + + if (flags & OUTPUT_LONG) + gcli_print_snippets_long(flags, list, max); + else + gcli_print_snippets_short(flags, list, max); +} + static int subcommand_snippet_get(int argc, char *argv[]) { @@ -176,7 +281,7 @@ subcommand_snippets(int argc, char *argv[]) if (gcli_snippets_get(g_clictx, count, &list) < 0) errx(1, "error: failed to fetch snippets"); - gcli_snippets_print(g_clictx, flags, &list, count); + gcli_snippets_print(flags, &list, count); gcli_snippets_free(&list); return EXIT_SUCCESS; diff --git a/src/gitlab/snippets.c b/src/gitlab/snippets.c index 22d75f0e..de101c42 100644 --- a/src/gitlab/snippets.c +++ b/src/gitlab/snippets.c @@ -76,112 +76,6 @@ gcli_snippets_get(gcli_ctx *ctx, int const max, gcli_snippet_list *const out) return gcli_fetch_list(ctx, url, &fl); } -static void -gcli_print_snippet(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_snippet const *const it) -{ - gcli_dict dict; - - (void) ctx; - (void) flags; - - dict = gcli_dict_begin(); - - gcli_dict_add(dict, "ID", 0, 0, "%d", it->id); - gcli_dict_add_string(dict, "TITLE", 0, 0, it->title); - gcli_dict_add_string(dict, "AUTHOR", 0, 0, it->author); - gcli_dict_add_string(dict, "FILE", 0, 0, it->filename); - gcli_dict_add_string(dict, "DATE", 0, 0, it->date); - gcli_dict_add_string(dict, "VSBLTY", 0, 0, it->visibility); - gcli_dict_add_string(dict, "URL", 0, 0, it->raw_url); - - gcli_dict_end(dict); -} - -static void -gcli_print_snippets_long(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_snippet_list const *const list, int const max) -{ - int n; - - /* Determine number of items to print */ - if (max < 0 || (size_t)(max) > list->snippets_size) - n = list->snippets_size; - else - n = max; - - if (flags & OUTPUT_SORTED) { - for (int i = 0; i < n; ++i) - gcli_print_snippet(ctx, flags, &list->snippets[n-i-1]); - } else { - for (int i = 0; i < n; ++i) - gcli_print_snippet(ctx, flags, &list->snippets[i]); - } -} - -static void -gcli_print_snippets_short(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_snippet_list const *const list, int const max) -{ - int n; - gcli_tbl table; - gcli_tblcoldef cols[] = { - { .name = "ID", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, - { .name = "DATE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "VISIBILITY", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "AUTHOR", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - { .name = "TITLE", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 }, - }; - - (void) ctx; - - /* Determine number of items to print */ - if (max < 0 || (size_t)(max) > list->snippets_size) - n = list->snippets_size; - else - n = max; - - /* Fill table */ - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); - if (!table) - errx(1, "error: could not init table"); - - if (flags & OUTPUT_SORTED) { - for (int i = 0; i < n; ++i) - gcli_tbl_add_row(table, - list->snippets[n-i-1].id, - list->snippets[n-i-1].date, - list->snippets[n-i-1].visibility, - list->snippets[n-i-1].author, - list->snippets[n-i-1].title); - } else { - for (int i = 0; i < n; ++i) - gcli_tbl_add_row(table, - list->snippets[i].id, - list->snippets[i].date, - list->snippets[i].visibility, - list->snippets[i].author, - list->snippets[i].title); - } - - gcli_tbl_end(table); -} - -void -gcli_snippets_print(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_snippet_list const *const list, int const max) -{ - if (list->snippets_size == 0) { - puts("No Snippets"); - return; - } - - if (flags & OUTPUT_LONG) - gcli_print_snippets_long(ctx, flags, list, max); - else - gcli_print_snippets_short(ctx, flags, list, max); -} - int gcli_snippet_delete(gcli_ctx *ctx, char const *snippet_id) { From 7d5e0301f07665aa5ea0ff5c5416b6f9aeb725b4 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 19 Aug 2023 00:34:21 +0200 Subject: [PATCH 137/236] Allow passing in an output file to gcli_snippet_get --- include/gcli/gitlab/snippets.h | 2 +- src/cmd/snippets.c | 4 +++- src/gitlab/snippets.c | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/gcli/gitlab/snippets.h b/include/gcli/gitlab/snippets.h index 6aca6d5f..f0403baf 100644 --- a/include/gcli/gitlab/snippets.h +++ b/include/gcli/gitlab/snippets.h @@ -60,6 +60,6 @@ int gcli_snippets_get(gcli_ctx *ctx, int max, gcli_snippet_list *out); int gcli_snippet_delete(gcli_ctx *ctx, char const *snippet_id); -int gcli_snippet_get(gcli_ctx *ctx, char const *snippet_id); +int gcli_snippet_get(gcli_ctx *ctx, char const *snippet_id, FILE *stream); #endif /* GITLAB_SNIPPETS_H */ diff --git a/src/cmd/snippets.c b/src/cmd/snippets.c index 04c20609..0903ec6a 100644 --- a/src/cmd/snippets.c +++ b/src/cmd/snippets.c @@ -179,7 +179,9 @@ subcommand_snippet_get(int argc, char *argv[]) return EXIT_FAILURE; } - gcli_snippet_get(g_clictx, snippet_id); + if (gcli_snippet_get(g_clictx, snippet_id, stdout) < 0) + errx(1, "error: failed to fetch snippet contents: %s", + gcli_get_error(g_clictx)); return EXIT_SUCCESS; } diff --git a/src/gitlab/snippets.c b/src/gitlab/snippets.c index de101c42..4e439d90 100644 --- a/src/gitlab/snippets.c +++ b/src/gitlab/snippets.c @@ -91,13 +91,13 @@ gcli_snippet_delete(gcli_ctx *ctx, char const *snippet_id) } int -gcli_snippet_get(gcli_ctx *ctx, char const *snippet_id) +gcli_snippet_get(gcli_ctx *ctx, char const *snippet_id, FILE *stream) { int rc = 0; char *url = sn_asprintf("%s/snippets/%s/raw", gitlab_get_apibase(ctx), snippet_id); - rc = gcli_curl(ctx, stdout, url, NULL); + rc = gcli_curl(ctx, stream, url, NULL); free(url); return rc; From bfd5c40e5e3faf3145fe3c9b7f28be005f450dc5 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 19 Aug 2023 01:03:33 +0200 Subject: [PATCH 138/236] Clean up notifications api and move print functions out of the library --- Makefile.am | 2 +- include/gcli/cmd/cmd.h | 1 - include/gcli/cmd/status.h | 44 +++++++++++++++++++++++++ include/gcli/forges.h | 4 +-- include/gcli/github/status.h | 4 +-- include/gcli/gitlab/status.h | 4 +-- include/gcli/status.h | 18 +++++----- src/cmd/gcli.c | 1 + src/cmd/status.c | 35 +++++++++++++++++++- src/github/status.c | 41 ++++++----------------- src/gitlab/status.c | 39 ++++++---------------- src/status.c | 64 ++++++++---------------------------- 12 files changed, 127 insertions(+), 130 deletions(-) create mode 100644 include/gcli/cmd/status.h diff --git a/Makefile.am b/Makefile.am index d775598c..72bce50b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -75,7 +75,7 @@ gcli_SOURCES = \ include/gcli/cmd/releases.h src/cmd/releases.c \ include/gcli/cmd/repos.h src/cmd/repos.c \ include/gcli/cmd/snippets.h src/cmd/snippets.c \ - src/cmd/status.c + include/gcli/cmd/status.h src/cmd/status.c libsn_la_SOURCES = \ thirdparty/sn/sn.c \ diff --git a/include/gcli/cmd/cmd.h b/include/gcli/cmd/cmd.h index 048878e5..367fc544 100644 --- a/include/gcli/cmd/cmd.h +++ b/include/gcli/cmd/cmd.h @@ -63,6 +63,5 @@ void delete_repo(bool always_yes, const char *owner, const char *repo); /* List of subcommand entry points */ int subcommand_api(int argc, char *argv[]); -int subcommand_status(int argc, char *argv[]); #endif /* GCLI_CMD_CMD_H */ diff --git a/include/gcli/cmd/status.h b/include/gcli/cmd/status.h new file mode 100644 index 00000000..73654d9a --- /dev/null +++ b/include/gcli/cmd/status.h @@ -0,0 +1,44 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_CMD_STATUS_H +#define GCLI_CMD_STATUS_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +int gcli_status(int count); +void gcli_print_notifications(gcli_notification_list const *); +int subcommand_status(int argc, char *argv[]); + +#endif /* GCLI_CMD_STATUS_H */ diff --git a/include/gcli/forges.h b/include/gcli/forges.h index d8ea1ba7..6beae329 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -457,8 +457,8 @@ struct gcli_forge_descriptor { * Status summary for the account */ int (*get_notifications)( gcli_ctx *ctx, - gcli_notification **notifications, - int count); + int max, + gcli_notification_list *notifications); /** * Mark notification with the given id as read diff --git a/include/gcli/github/status.h b/include/gcli/github/status.h index fea2de88..bd474bf8 100644 --- a/include/gcli/github/status.h +++ b/include/gcli/github/status.h @@ -36,9 +36,7 @@ #include -int github_get_notifications(gcli_ctx *ctx, - gcli_notification **notifications, int count); - +int github_get_notifications(gcli_ctx *ctx, int max, gcli_notification_list *out); int github_notification_mark_as_read(gcli_ctx *ctx, char const *id); #endif /* GITHUB_STATUS_H */ diff --git a/include/gcli/gitlab/status.h b/include/gcli/gitlab/status.h index e7887340..83667ed6 100644 --- a/include/gcli/gitlab/status.h +++ b/include/gcli/gitlab/status.h @@ -36,9 +36,7 @@ #include -int gitlab_get_notifications(gcli_ctx *ctx, gcli_notification **notifications, - int count); - +int gitlab_get_notifications(gcli_ctx *ctx, int max, gcli_notification_list *out); int gitlab_notification_mark_as_read(gcli_ctx *ctx, char const *id); #endif /* GITLAB_STATUS_H */ diff --git a/include/gcli/status.h b/include/gcli/status.h index 404f554d..52601a58 100644 --- a/include/gcli/status.h +++ b/include/gcli/status.h @@ -38,6 +38,9 @@ #include +typedef struct gcli_notification gcli_notification; +typedef struct gcli_notification_list gcli_notification_list; + struct gcli_notification { char *id; char *title; @@ -47,16 +50,13 @@ struct gcli_notification { char *repository; }; -typedef struct gcli_notification gcli_notification; - -void gcli_status(gcli_ctx *ctx, int count); - -int gcli_get_notifications(gcli_ctx *ctx, gcli_notification **out, int count); +struct gcli_notification_list { + gcli_notification *notifications; + size_t notifications_size; +}; +int gcli_get_notifications(gcli_ctx *ctx, int count, gcli_notification_list *out); int gcli_notification_mark_as_read(gcli_ctx *ctx, char const *id); - -void gcli_free_notifications(gcli_notification *, size_t); - -void gcli_print_notifications(gcli_notification const *, size_t); +void gcli_free_notifications(gcli_notification_list *); #endif /* STATUS_H */ diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index 237c4721..2fe749db 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -52,6 +52,7 @@ #include #include #include +#include #include diff --git a/src/cmd/status.c b/src/cmd/status.c index e398196e..1fd75ddf 100644 --- a/src/cmd/status.c +++ b/src/cmd/status.c @@ -30,6 +30,8 @@ #include #include +#include + #include #ifdef HAVE_GETOPT_H @@ -49,6 +51,37 @@ usage(void) copyright(); } +int +gcli_status(int const count) +{ + gcli_notification_list list = {0}; + int rc = 0; + + rc = gcli_get_notifications(g_clictx, count, &list); + if (rc < 0) + return rc; + + gcli_print_notifications(&list); + gcli_free_notifications(&list); + + return rc; +} + +void +gcli_print_notifications(gcli_notification_list const *const list) +{ + for (size_t i = 0; i < list->notifications_size; ++i) { + printf("%s - %s - %s - %s - %s\n", + list->notifications[i].id, + list->notifications[i].repository, + list->notifications[i].type, list->notifications[i].date, + list->notifications[i].reason); + + pretty_print(list->notifications[i].title, 4, 80, stdout); + putchar('\n'); + } +} + int subcommand_status(int argc, char *argv[]) { @@ -89,7 +122,7 @@ subcommand_status(int argc, char *argv[]) argv += optind; if (!mark) { - gcli_status(g_clictx, count); + gcli_status(count); } else { if (count != 30) warnx("ignoring -n/--count argument"); diff --git a/src/github/status.c b/src/github/status.c index 6e7e9452..e1360fd5 100644 --- a/src/github/status.c +++ b/src/github/status.c @@ -38,41 +38,20 @@ #include int -github_get_notifications(gcli_ctx *ctx, - gcli_notification **const notifications, - int const count) +github_get_notifications(gcli_ctx *ctx, int const max, + gcli_notification_list *const out) { char *url = NULL; - char *next_url = NULL; - gcli_fetch_buffer buffer = {0}; - struct json_stream stream = {0}; - size_t notifications_size = 0; - int rc = 0; - - url = sn_asprintf("%s/notifications", gcli_get_apibase(ctx)); - - do { - rc = gcli_fetch(ctx, url, &next_url, &buffer); - if (rc == 0) { - json_open_buffer(&stream, buffer.data, buffer.length); - parse_github_notifications(ctx, &stream, notifications, - ¬ifications_size); - json_close(&stream); - } + gcli_fetch_list_ctx fl = { + .listp = &out->notifications, + .sizep = &out->notifications_size, + .parse = (parsefn)(parse_github_notifications), + .max = max, + }; - free(url); - free(buffer.data); - - if (rc < 0) - break; - } while ((url = next_url) && (count < 0 || ((int)notifications_size < count))); - - /* TODO: don't leak the list on error */ - if (rc < 0) - return rc; - - return (int)(notifications_size); + url = sn_asprintf("%s/notifications", gcli_get_apibase(ctx)); + return gcli_fetch_list(ctx, url, &fl); } int diff --git a/src/gitlab/status.c b/src/gitlab/status.c index d8cca65d..0eb75d2f 100644 --- a/src/gitlab/status.c +++ b/src/gitlab/status.c @@ -38,40 +38,21 @@ #include int -gitlab_get_notifications(gcli_ctx *ctx, gcli_notification **const notifications, - int const count) +gitlab_get_notifications(gcli_ctx *ctx, int const max, + gcli_notification_list *const out) { char *url = NULL; - char *next_url = NULL; - gcli_fetch_buffer buffer = {0}; - json_stream stream = {0}; - size_t notifications_size = 0; - int rc = 0; - - url = sn_asprintf("%s/todos", gitlab_get_apibase(ctx)); - - do { - rc = gcli_fetch(ctx, url, &next_url, &buffer); - if (rc == 0) { - json_open_buffer(&stream, buffer.data, buffer.length); - parse_gitlab_todos(ctx, &stream, notifications, - ¬ifications_size); - json_close(&stream); - } + gcli_fetch_list_ctx fl = { + .listp = &out->notifications, + .sizep = &out->notifications_size, + .parse = (parsefn)(parse_gitlab_todos), + .max = max, + }; - free(url); - free(buffer.data); - - if (rc < 0) - break; - } while ((url = next_url) && (count < 0 || (int)notifications_size < count)); - - /* TODO: don't leak the list on error */ - if (rc < 0) - return rc; + url = sn_asprintf("%s/todos", gitlab_get_apibase(ctx)); - return (int)(notifications_size); + return gcli_fetch_list(ctx, url, &fl); } int diff --git a/src/status.c b/src/status.c index fef01cb7..140f445e 100644 --- a/src/status.c +++ b/src/status.c @@ -30,64 +30,28 @@ #include #include -void -gcli_status(gcli_ctx *ctx, int const count) -{ - gcli_notification *notifications = NULL; - int notifications_size = 0; - - notifications_size = gcli_get_notifications(ctx, ¬ifications, count); - if (notifications_size < 0) - errx(1, "error: failed to get notifications"); - - if (count < 0) { - gcli_print_notifications(notifications, notifications_size); - } else { - gcli_print_notifications( - notifications, - (size_t)(count < (int)notifications_size - ? count : notifications_size)); - } - - gcli_free_notifications(notifications, notifications_size); -} - int -gcli_get_notifications(gcli_ctx *ctx, gcli_notification **const out, - int const count) +gcli_get_notifications(gcli_ctx *ctx, int const max, + gcli_notification_list *const out) { - return gcli_forge(ctx)->get_notifications(ctx, out, count); + return gcli_forge(ctx)->get_notifications(ctx, max, out); } void -gcli_free_notifications(gcli_notification *notifications, - size_t const notifications_size) +gcli_free_notifications(gcli_notification_list *list) { - for (size_t i = 0; i < notifications_size; ++i) { - free(notifications[i].id); - free(notifications[i].title); - free(notifications[i].reason); - free(notifications[i].date); - free(notifications[i].type); - free(notifications[i].repository); + for (size_t i = 0; i < list->notifications_size; ++i) { + free(list->notifications[i].id); + free(list->notifications[i].title); + free(list->notifications[i].reason); + free(list->notifications[i].date); + free(list->notifications[i].type); + free(list->notifications[i].repository); } - free(notifications); -} - -void -gcli_print_notifications(gcli_notification const *const notifications, - size_t const notifications_size) -{ - for (size_t i = 0; i < notifications_size; ++i) { - printf("%s - %s - %s - %s - %s\n", - notifications[i].id, notifications[i].repository, - notifications[i].type, notifications[i].date, - notifications[i].reason); - - pretty_print(notifications[i].title, 4, 80, stdout); - putchar('\n'); - } + free(list->notifications); + list->notifications = NULL; + list->notifications_size = 0; } int From 2915e29653dc08952415f2c50a61130a9866a36f Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 19 Aug 2023 01:45:16 +0200 Subject: [PATCH 139/236] Fix dependency on libbsd-dev on Linux The header file sys/queue.h seems to be in libbsd. --- .gitlab-ci.yml | 4 ++-- src/github/repos.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d4c9d0e9..60782a7e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,7 +12,7 @@ alpine-amd64: - linux image: alpine:3.17 script: - - apk add libcurl gcc autoconf automake libtool make pkgconf musl-dev curl-dev flex bison xz gzip bzip2 + - apk add libcurl gcc autoconf automake libtool make pkgconf musl-dev curl-dev flex bison xz gzip bzip2 libbsd-dev - ./autogen.sh - ./configure CFLAGS='-std=c99 -pedantic -Wall -Wextra -Werror' CPPFLAGS='-D_XOPEN_SOURCE=600' || (cat config.log && exit 42) - make @@ -50,7 +50,7 @@ debian-amd64: image: debian:bullseye script: - apt-get update - - apt-get install -y --no-install-recommends build-essential libcurl4-openssl-dev pkgconf autotools-dev bison flex make autoconf automake libtool + - apt-get install -y --no-install-recommends build-essential libcurl4-openssl-dev pkgconf autotools-dev bison flex make autoconf automake libtool libbsd-dev - ./autogen.sh - ./configure CFLAGS='-std=c99 -pedantic -Wall -Wextra -Werror -Wno-misleading-indentation' CPPFLAGS='-D_XOPEN_SOURCE=600' || (cat config.log && exit 42) - make diff --git a/src/github/repos.c b/src/github/repos.c index 25a18e9a..4619380f 100644 --- a/src/github/repos.c +++ b/src/github/repos.c @@ -58,7 +58,6 @@ github_get_repos(gcli_ctx *ctx, char const *owner, int const max, * organizations and users. Thus, we have to find out, whether the * param is a user or an actual organization. */ url = sn_asprintf("%s/users/%s", gcli_get_apibase(ctx), e_owner); - free(e_owner); /* 0 = failed, 1 = success, -1 = error (just like a BOOL in Win32 * /sarc) */ @@ -82,6 +81,8 @@ github_get_repos(gcli_ctx *ctx, char const *owner, int const max, e_owner); } + free(e_owner); + return gcli_fetch_list(ctx, url, &lf); } From efbf4276ab3774e421880bdcda63797b696620e5 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 19 Aug 2023 11:42:18 +0200 Subject: [PATCH 140/236] Move interactive editor requests out of the library --- Makefile.am | 30 ++++++------- include/gcli/{ => cmd}/editor.h | 6 +-- include/gcli/comments.h | 1 - include/gcli/issues.h | 1 - include/gcli/pulls.h | 1 - src/cmd/comment.c | 76 ++++++++++++++++++++++++++++++--- src/{ => cmd}/editor.c | 3 +- src/cmd/issues.c | 62 ++++++++++++++++++++++++--- src/cmd/pulls.c | 55 ++++++++++++++++++++++-- src/cmd/releases.c | 2 +- src/comments.c | 61 +------------------------- src/issues.c | 41 ------------------ src/pulls.c | 42 ------------------ 13 files changed, 202 insertions(+), 179 deletions(-) rename include/gcli/{ => cmd}/editor.h (95%) rename src/{ => cmd}/editor.c (99%) diff --git a/Makefile.am b/Makefile.am index 72bce50b..42e491b1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -57,15 +57,13 @@ dist_man_MANS = \ docs/gcli.1 gcli_SOURCES = \ + include/gcli/cmd/ci.h src/cmd/ci.c \ include/gcli/cmd/cmd.h src/cmd/cmd.c \ include/gcli/cmd/colour.h src/cmd/colour.c \ - include/gcli/cmd/table.h src/cmd/table.c \ - src/cmd/api.c \ - include/gcli/cmd/ci.h src/cmd/ci.c \ include/gcli/cmd/comment.h src/cmd/comment.c \ include/gcli/cmd/config.h src/cmd/config.c \ + include/gcli/cmd/editor.h src/cmd/editor.c \ include/gcli/cmd/forks.h src/cmd/forks.c \ - src/cmd/gcli.c \ include/gcli/cmd/gists.h src/cmd/gists.c \ include/gcli/cmd/issues.h src/cmd/issues.c \ include/gcli/cmd/labels.h src/cmd/labels.c \ @@ -75,7 +73,10 @@ gcli_SOURCES = \ include/gcli/cmd/releases.h src/cmd/releases.c \ include/gcli/cmd/repos.h src/cmd/repos.c \ include/gcli/cmd/snippets.h src/cmd/snippets.c \ - include/gcli/cmd/status.h src/cmd/status.c + include/gcli/cmd/status.h src/cmd/status.c \ + include/gcli/cmd/table.h src/cmd/table.c \ + src/cmd/api.c \ + src/cmd/gcli.c libsn_la_SOURCES = \ thirdparty/sn/sn.c \ @@ -112,16 +113,14 @@ TEMPLATES = \ templates/gitlab/snippets.t \ templates/gitea/milestones.t -include_HEADERS = \ - include/gcli/gcli.h include/gcli/comments.h \ - include/gcli/config.h include/gcli/curl.h \ - include/gcli/editor.h include/gcli/forks.h \ - include/gcli/gitconfig.h include/gcli/issues.h \ - include/gcli/labels.h include/gcli/milestones.h \ - include/gcli/pulls.h include/gcli/releases.h \ - include/gcli/repos.h include/gcli/review.h \ - include/gcli/gitlab/snippets.h include/gcli/status.h \ - include/gcli/sshkeys.h +include_HEADERS = include/gcli/gcli.h include/gcli/comments.h \ + include/gcli/config.h include/gcli/curl.h \ + include/gcli/forks.h include/gcli/gitconfig.h \ + include/gcli/issues.h include/gcli/labels.h \ + include/gcli/milestones.h include/gcli/pulls.h \ + include/gcli/releases.h include/gcli/repos.h \ + include/gcli/review.h include/gcli/gitlab/snippets.h \ + include/gcli/status.h include/gcli/sshkeys.h libgcli_la_SOURCES = \ include/gcli/ctx.h src/ctx.c \ @@ -129,7 +128,6 @@ libgcli_la_SOURCES = \ src/comments.c include/gcli/comments.h \ src/config.c include/gcli/config.h \ src/curl.c include/gcli/curl.h \ - src/editor.c include/gcli/editor.h \ src/forges.c include/gcli/forges.h \ src/forks.c include/gcli/forks.h \ src/gitconfig.c include/gcli/gitconfig.h \ diff --git a/include/gcli/editor.h b/include/gcli/cmd/editor.h similarity index 95% rename from include/gcli/editor.h rename to include/gcli/cmd/editor.h index 9b53c8a0..27062856 100644 --- a/include/gcli/editor.h +++ b/include/gcli/cmd/editor.h @@ -27,8 +27,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef EDITOR_H -#define EDITOR_H +#ifndef GCLI_CMD_EDITOR_H +#define GCLI_CMD_EDITOR_H #ifdef HAVE_CONFIG_H #include @@ -43,4 +43,4 @@ sn_sv gcli_editor_get_user_message( void (*initializer)(gcli_ctx *, FILE *, void *), void *user_data); -#endif /* EDITOR_H */ +#endif /* GCLI_CMD_EDITOR_H */ diff --git a/include/gcli/comments.h b/include/gcli/comments.h index 9c51f8a8..72b08a6d 100644 --- a/include/gcli/comments.h +++ b/include/gcli/comments.h @@ -62,7 +62,6 @@ struct gcli_submit_comment_opts { char const *owner, *repo; int target_id; sn_sv message; - bool always_yes; }; void gcli_comment_list_free(gcli_comment_list *list); diff --git a/include/gcli/issues.h b/include/gcli/issues.h index afb95841..212cd55c 100644 --- a/include/gcli/issues.h +++ b/include/gcli/issues.h @@ -67,7 +67,6 @@ struct gcli_submit_issue_options { char const *repo; sn_sv title; sn_sv body; - bool always_yes; }; struct gcli_issue_list { diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index 461754e8..2d91d925 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -99,7 +99,6 @@ struct gcli_submit_pull_options { char const **labels; size_t labels_size; int draft; - bool always_yes; }; struct gcli_pull_fetch_details { diff --git a/src/cmd/comment.c b/src/cmd/comment.c index b1036a5b..5cdd8527 100644 --- a/src/cmd/comment.c +++ b/src/cmd/comment.c @@ -32,8 +32,11 @@ #include #include #include +#include #include +#include +#include #ifdef HAVE_GETOPT_H #include @@ -53,6 +56,69 @@ usage(void) copyright(); } +static void +comment_init(gcli_ctx *ctx, FILE *f, void *_data) +{ + gcli_submit_comment_opts *info = _data; + const char *target_type = NULL; + + switch (info->target_type) { + case ISSUE_COMMENT: + target_type = "issue"; + break; + case PR_COMMENT: { + switch (gcli_config_get_forge_type(ctx)) { + case GCLI_FORGE_GITEA: + case GCLI_FORGE_GITHUB: + target_type = "Pull Request"; + break; + case GCLI_FORGE_GITLAB: + target_type = "Merge Request"; + break; + } + } break; + } + + fprintf( + f, + "! Enter your comment above, save and exit.\n" + "! All lines with a leading '!' are discarded and will not\n" + "! appear in your comment.\n" + "! COMMENT IN : %s/%s %s #%d\n", + info->owner, info->repo, target_type, info->target_id); +} + +static sn_sv +gcli_comment_get_message(gcli_submit_comment_opts *info) +{ + return gcli_editor_get_user_message(g_clictx, comment_init, info); +} + +static int +comment_submit(gcli_submit_comment_opts opts, int always_yes) +{ + sn_sv const message = gcli_comment_get_message(&opts); + opts.message = gcli_json_escape(message); + int rc = 0; + + fprintf( + stdout, + "You will be commenting the following in %s/%s #%d:\n"SV_FMT"\n", + opts.owner, opts.repo, opts.target_id, SV_ARGS(message)); + + if (!always_yes) { + if (!sn_yesno("Is this okay?")) + errx(1, "Aborted by user"); + } + + rc = gcli_comment_submit(g_clictx, opts); + + free(message.data); + free(opts.message.data); + + return rc; +} + int gcli_issue_comments(char const *owner, char const *repo, int const issue) { @@ -169,12 +235,12 @@ subcommand_comment(int argc, char *argv[]) return EXIT_FAILURE; } - rc = gcli_comment_submit(g_clictx, (gcli_submit_comment_opts) { - .owner = owner, - .repo = repo, + rc = comment_submit((gcli_submit_comment_opts) { + .owner = owner, + .repo = repo, .target_type = target_type, - .target_id = target_id, - .always_yes = always_yes }); + .target_id = target_id }, + always_yes); if (rc < 0) errx(1, "error: failed to submit comment"); diff --git a/src/editor.c b/src/cmd/editor.c similarity index 99% rename from src/editor.c rename to src/cmd/editor.c index 14ef5912..c0512778 100644 --- a/src/editor.c +++ b/src/cmd/editor.c @@ -27,7 +27,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include + #include #include diff --git a/src/cmd/issues.c b/src/cmd/issues.c index 8ee8263c..8a29c643 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -185,12 +186,63 @@ gcli_issue_print_op(gcli_issue const *const it) pretty_print(it->body.data, 4, 80, stdout); } +static void +issue_init_user_file(gcli_ctx *ctx, FILE *stream, void *_opts) +{ + (void) ctx; + gcli_submit_issue_options *opts = _opts; + fprintf( + stream, + "! ISSUE TITLE : "SV_FMT"\n" + "! Enter issue description above.\n" + "! All lines starting with '!' will be discarded.\n", + SV_ARGS(opts->title)); +} + +static sn_sv +gcli_issue_get_user_message(gcli_submit_issue_options *opts) +{ + return gcli_editor_get_user_message(g_clictx, issue_init_user_file, opts); +} + +static int +create_issue(gcli_submit_issue_options opts, int always_yes) +{ + int rc; + + opts.body = gcli_issue_get_user_message(&opts); + + printf("The following issue will be created:\n" + "\n" + "TITLE : "SV_FMT"\n" + "OWNER : %s\n" + "REPO : %s\n" + "MESSAGE :\n"SV_FMT"\n", + SV_ARGS(opts.title), + opts.owner, opts.repo, + SV_ARGS(opts.body)); + + putchar('\n'); + + if (!always_yes) { + if (!sn_yesno("Do you want to continue?")) + errx(1, "Submission aborted."); + } + + rc = gcli_issue_submit(g_clictx, opts); + + free(opts.body.data); + free(opts.body.data); + + return rc; +} + static int subcommand_issue_create(int argc, char *argv[]) { - /* we'll use getopt_long here to parse the arguments */ - int ch; - gcli_submit_issue_options opts = {0}; + int ch; + gcli_submit_issue_options opts = {0}; + int always_yes = 0; const struct option options[] = { { .name = "owner", @@ -217,7 +269,7 @@ subcommand_issue_create(int argc, char *argv[]) opts.repo = optarg; break; case 'y': - opts.always_yes = true; + always_yes = 1; break; default: usage(); @@ -238,7 +290,7 @@ subcommand_issue_create(int argc, char *argv[]) opts.title = SV(argv[0]); - if (gcli_issue_submit(g_clictx, opts) < 0) + if (create_issue(opts, always_yes) < 0) errx(1, "failed to submit issue"); return EXIT_SUCCESS; diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 88c7bf30..c9237f92 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -329,6 +330,53 @@ gcli_pull_commits(char const *owner, char const *repo, return rc; } +static void +pull_init_user_file(gcli_ctx *ctx, FILE *stream, void *_opts) +{ + gcli_submit_pull_options *opts = _opts; + + (void) ctx; + fprintf( + stream, + "! PR TITLE : "SV_FMT"\n" + "! Enter PR comments above.\n" + "! All lines starting with '!' will be discarded.\n", + SV_ARGS(opts->title)); +} + +static sn_sv +gcli_pull_get_user_message(gcli_submit_pull_options *opts) +{ + return gcli_editor_get_user_message(g_clictx, pull_init_user_file, opts); +} + +static int +create_pull(gcli_submit_pull_options opts, int always_yes) +{ + opts.body = gcli_pull_get_user_message(&opts); + + fprintf(stdout, + "The following PR will be created:\n" + "\n" + "TITLE : "SV_FMT"\n" + "BASE : "SV_FMT"\n" + "HEAD : "SV_FMT"\n" + "IN : %s/%s\n" + "MESSAGE :\n"SV_FMT"\n", + SV_ARGS(opts.title),SV_ARGS(opts.to), + SV_ARGS(opts.from), + opts.owner, opts.repo, + SV_ARGS(opts.body)); + + fputc('\n', stdout); + + if (!always_yes) + if (!sn_yesno("Do you want to continue?")) + errx(1, "PR aborted."); + + return gcli_pull_submit(g_clictx, opts); +} + static sn_sv pr_try_derive_head(void) { @@ -353,8 +401,9 @@ static int subcommand_pull_create(int argc, char *argv[]) { /* we'll use getopt_long here to parse the arguments */ - int ch; + int ch; gcli_submit_pull_options opts = {0}; + int always_yes = 0; const struct option options[] = { { .name = "from", @@ -407,7 +456,7 @@ subcommand_pull_create(int argc, char *argv[]) opts.labels[opts.labels_size++] = optarg; break; case 'y': - opts.always_yes = true; + always_yes = 1; break; default: usage(); @@ -438,7 +487,7 @@ subcommand_pull_create(int argc, char *argv[]) opts.title = SV(argv[0]); - if (gcli_pull_submit(g_clictx, opts) < 0) + if (create_pull(opts, always_yes) < 0) errx(1, "error: failed to submit pull request"); free(opts.labels); diff --git a/src/cmd/releases.c b/src/cmd/releases.c index 4cd72156..952ec8cb 100644 --- a/src/cmd/releases.c +++ b/src/cmd/releases.c @@ -32,8 +32,8 @@ #include #include #include +#include -#include #include #ifdef HAVE_GETOPT_H diff --git a/src/comments.c b/src/comments.c index 341a24f2..a8be6edc 100644 --- a/src/comments.c +++ b/src/comments.c @@ -28,10 +28,10 @@ */ #include +#include #include #include -#include #include #include #include @@ -70,65 +70,8 @@ gcli_get_pull_comments(gcli_ctx *ctx, char const *owner, char const *repo, return gcli_forge(ctx)->get_pull_comments(ctx, owner, repo, pull, out); } -static void -comment_init(gcli_ctx *ctx, FILE *f, void *_data) -{ - gcli_submit_comment_opts *info = _data; - const char *target_type = NULL; - - switch (info->target_type) { - case ISSUE_COMMENT: - target_type = "issue"; - break; - case PR_COMMENT: { - switch (gcli_config_get_forge_type(ctx)) { - case GCLI_FORGE_GITEA: - case GCLI_FORGE_GITHUB: - target_type = "Pull Request"; - break; - case GCLI_FORGE_GITLAB: - target_type = "Merge Request"; - break; - } - } break; - } - - fprintf( - f, - "! Enter your comment above, save and exit.\n" - "! All lines with a leading '!' are discarded and will not\n" - "! appear in your comment.\n" - "! COMMENT IN : %s/%s %s #%d\n", - info->owner, info->repo, target_type, info->target_id); -} - -static sn_sv -gcli_comment_get_message(gcli_ctx *ctx, gcli_submit_comment_opts *info) -{ - return gcli_editor_get_user_message(ctx, comment_init, info); -} - int gcli_comment_submit(gcli_ctx *ctx, gcli_submit_comment_opts opts) { - sn_sv const message = gcli_comment_get_message(ctx, &opts); - opts.message = gcli_json_escape(message); - int rc = 0; - - fprintf( - stdout, - "You will be commenting the following in %s/%s #%d:\n"SV_FMT"\n", - opts.owner, opts.repo, opts.target_id, SV_ARGS(message)); - - if (!opts.always_yes) { - if (!sn_yesno("Is this okay?")) - errx(1, "Aborted by user"); - } - - rc = gcli_forge(ctx)->perform_submit_comment(ctx, opts, NULL); - - free(message.data); - free(opts.message.data); - - return rc; + return gcli_forge(ctx)->perform_submit_comment(ctx, opts, NULL); } diff --git a/src/issues.c b/src/issues.c index d49cc39d..2e468ef0 100644 --- a/src/issues.c +++ b/src/issues.c @@ -27,7 +27,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include @@ -92,57 +91,17 @@ gcli_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, return gcli_forge(ctx)->issue_reopen(ctx, owner, repo, issue_number); } -static void -issue_init_user_file(gcli_ctx *ctx, FILE *stream, void *_opts) -{ - (void) ctx; - gcli_submit_issue_options *opts = _opts; - fprintf( - stream, - "! ISSUE TITLE : "SV_FMT"\n" - "! Enter issue description above.\n" - "! All lines starting with '!' will be discarded.\n", - SV_ARGS(opts->title)); -} - -static sn_sv -gcli_issue_get_user_message(gcli_ctx *ctx, gcli_submit_issue_options *opts) -{ - return gcli_editor_get_user_message(ctx, issue_init_user_file, opts); -} - int gcli_issue_submit(gcli_ctx *ctx, gcli_submit_issue_options opts) { gcli_fetch_buffer json_buffer = {0}; int rc = 0; - opts.body = gcli_issue_get_user_message(ctx, &opts); - - printf("The following issue will be created:\n" - "\n" - "TITLE : "SV_FMT"\n" - "OWNER : %s\n" - "REPO : %s\n" - "MESSAGE :\n"SV_FMT"\n", - SV_ARGS(opts.title), - opts.owner, opts.repo, - SV_ARGS(opts.body)); - - putchar('\n'); - - if (!opts.always_yes) { - if (!sn_yesno("Do you want to continue?")) - errx(1, "Submission aborted."); - } - rc = gcli_forge(ctx)->perform_submit_issue(ctx, opts, &json_buffer); if (rc == 0) gcli_print_html_url(ctx, json_buffer); - free(opts.body.data); - free(opts.body.data); free(json_buffer.data); return rc; diff --git a/src/pulls.c b/src/pulls.c index 1fcd2e6c..35c78f54 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -139,50 +138,9 @@ gcli_pull_checks_free(gcli_pull_checks_list *list) } } -static void -pull_init_user_file(gcli_ctx *ctx, FILE *stream, void *_opts) -{ - gcli_submit_pull_options *opts = _opts; - - (void) ctx; - fprintf( - stream, - "! PR TITLE : "SV_FMT"\n" - "! Enter PR comments above.\n" - "! All lines starting with '!' will be discarded.\n", - SV_ARGS(opts->title)); -} - -static sn_sv -gcli_pull_get_user_message(gcli_ctx *ctx, gcli_submit_pull_options *opts) -{ - return gcli_editor_get_user_message(ctx, pull_init_user_file, opts); -} - int gcli_pull_submit(gcli_ctx *ctx, gcli_submit_pull_options opts) { - opts.body = gcli_pull_get_user_message(ctx, &opts); - - fprintf(stdout, - "The following PR will be created:\n" - "\n" - "TITLE : "SV_FMT"\n" - "BASE : "SV_FMT"\n" - "HEAD : "SV_FMT"\n" - "IN : %s/%s\n" - "MESSAGE :\n"SV_FMT"\n", - SV_ARGS(opts.title),SV_ARGS(opts.to), - SV_ARGS(opts.from), - opts.owner, opts.repo, - SV_ARGS(opts.body)); - - fputc('\n', stdout); - - if (!opts.always_yes) - if (!sn_yesno("Do you want to continue?")) - errx(1, "PR aborted."); - return gcli_forge(ctx)->perform_submit_pull(ctx, opts); } From aed49581bde240bca020a72c3146ebafaf577734 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 20 Aug 2023 18:24:26 +0200 Subject: [PATCH 141/236] Update .hgignore --- .hgignore | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/.hgignore b/.hgignore index ad253f1c..ba3045c3 100644 --- a/.hgignore +++ b/.hgignore @@ -3,15 +3,7 @@ build/* Makefile.in aclocal.m4 ar-lib -autom4te.cache/output.0 -autom4te.cache/output.1 -autom4te.cache/output.2 -autom4te.cache/output.3 -autom4te.cache/requests -autom4te.cache/traces.0 -autom4te.cache/traces.1 -autom4te.cache/traces.2 -autom4te.cache/traces.3 +autom4te.cache/ compile config.guess config.h.in @@ -31,3 +23,4 @@ ylwrap *~ docs/tutorial/*.html TAGS +build-*/ From d76bc0f5be65635edce3440756dbbeb3e6831f19 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 22 Aug 2023 19:58:38 +0200 Subject: [PATCH 142/236] Return error code from get_pull_diff routines --- include/gcli/cmd/pulls.h | 4 ++-- include/gcli/pulls.h | 4 ++-- src/cmd/pulls.c | 8 +++++--- src/pulls.c | 4 ++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/include/gcli/cmd/pulls.h b/include/gcli/cmd/pulls.h index 8fae857b..0099ca33 100644 --- a/include/gcli/cmd/pulls.h +++ b/include/gcli/cmd/pulls.h @@ -39,8 +39,8 @@ void gcli_print_pulls(enum gcli_output_flags flags, gcli_pull_list const *list, int max); -void gcli_print_pull_diff(FILE *stream, char const *owner, char const *reponame, - int pr_number); +int gcli_print_pull_diff(FILE *stream, char const *owner, char const *reponame, + int pr_number); void gcli_print_pull(gcli_pull const *pull); diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index 2d91d925..c42c656c 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -128,8 +128,8 @@ void gcli_pull_free(gcli_pull *it); void gcli_pulls_free(gcli_pull_list *list); -void gcli_pull_get_diff(gcli_ctx *ctx, FILE *fout, char const *owner, - char const *repo, int pr_number); +int gcli_pull_get_diff(gcli_ctx *ctx, FILE *fout, char const *owner, + char const *repo, int pr_number); int gcli_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, int pr_number, gcli_pull_checks_list *out); diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index c9237f92..d9f97c82 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -152,11 +152,11 @@ gcli_print_pulls(enum gcli_output_flags const flags, gcli_tbl_end(table); } -void +int gcli_print_pull_diff(FILE *stream, char const *owner, char const *reponame, int pr_number) { - gcli_pull_get_diff(g_clictx, stream, owner, reponame, pr_number); + return gcli_pull_get_diff(g_clictx, stream, owner, reponame, pr_number); } void @@ -714,7 +714,9 @@ handle_pull_actions(int argc, char *argv[], gcli_pull_commits(owner, repo, pr); } else if (strcmp(action, "diff") == 0) { - gcli_print_pull_diff(stdout, owner, repo, pr); + if (gcli_print_pull_diff(stdout, owner, repo, pr) < 0) + errx(1, "error: failed to fetch diff: %s", + gcli_get_error(g_clictx)); } else if (strcmp(action, "comments") == 0 || strcmp(action, "notes") == 0) { diff --git a/src/pulls.c b/src/pulls.c index 35c78f54..a5c8a811 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -60,11 +60,11 @@ gcli_get_pulls(gcli_ctx *ctx, char const *owner, char const *repo, return gcli_forge(ctx)->get_pulls(ctx, owner, repo, details, max, out); } -void +int gcli_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner, char const *reponame, int const pr_number) { - gcli_forge(ctx)->print_pull_diff(ctx, stream, owner, reponame, pr_number); + return gcli_forge(ctx)->print_pull_diff(ctx, stream, owner, reponame, pr_number); } int From 0f446b357fad8670a5d57adb629ee0947ac796f7 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 22 Aug 2023 20:48:46 +0200 Subject: [PATCH 143/236] (#197) Fix 'malloc: Cannot allocate memory' error Fixes #197 --- src/cmd/pulls.c | 3 ++- src/gcli.c | 7 ++++--- src/gitlab/merge_requests.c | 3 +++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index d9f97c82..a92c55f8 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -488,7 +488,8 @@ subcommand_pull_create(int argc, char *argv[]) opts.title = SV(argv[0]); if (create_pull(opts, always_yes) < 0) - errx(1, "error: failed to submit pull request"); + errx(1, "error: failed to submit pull request: %s", + gcli_get_error(g_clictx)); free(opts.labels); diff --git a/src/gcli.c b/src/gcli.c index 5f8aa0fb..27c67169 100644 --- a/src/gcli.c +++ b/src/gcli.c @@ -43,8 +43,6 @@ gcli_init(gcli_ctx **ctx) if (gcli_config_init_ctx(*ctx) < 0) return (*ctx)->last_error; /* TODO: cleanup */ - (*ctx)->last_error = "imagine having useful error messages in the year 2023"; - return NULL; } @@ -62,5 +60,8 @@ gcli_destroy(gcli_ctx **ctx) char const * gcli_get_error(gcli_ctx *ctx) { - return ctx->last_error; + if (ctx->last_error) + return ctx->last_error; + else + return "No error"; } diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index 859c9996..aa5ce3ad 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -312,6 +312,9 @@ gitlab_perform_submit_mr(gcli_ctx *ctx, gcli_submit_pull_options opts) target_branch = opts.to; source_branch = opts.from; source_owner = sn_sv_chop_until(&source_branch, ':'); + if (source_branch.length == 0) + return gcli_error(ctx, "bad merge request source: expected 'owner:branch'"); + source_branch.length -= 1; source_branch.data += 1; From 0d77e8e65de00dc35d15382094e6c3c3bfa6ccb7 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Wed, 23 Aug 2023 22:59:50 +0200 Subject: [PATCH 144/236] Make get_account routines return an error code instead of calling errx() --- include/gcli/config.h | 2 +- include/gcli/forges.h | 2 +- include/gcli/gitea/config.h | 2 +- include/gcli/github/config.h | 2 +- include/gcli/gitlab/config.h | 2 +- src/cmd/forks.c | 10 ++++++++-- src/cmd/pulls.c | 9 ++++++--- src/config.c | 6 +++--- src/gitea/config.c | 13 ++++++++----- src/github/config.c | 15 +++++++++------ src/gitlab/config.c | 15 +++++++++------ src/gitlab/repos.c | 14 ++++++-------- 12 files changed, 54 insertions(+), 38 deletions(-) diff --git a/include/gcli/config.h b/include/gcli/config.h index 1274949a..cad237c8 100644 --- a/include/gcli/config.h +++ b/include/gcli/config.h @@ -47,7 +47,7 @@ sn_sv gcli_config_find_by_key(gcli_ctx *ctx, char *gcli_config_get_editor(gcli_ctx *ctx); char *gcli_config_get_authheader(gcli_ctx *ctx); -sn_sv gcli_config_get_account(gcli_ctx *ctx); +int gcli_config_get_account(gcli_ctx *ctx, sn_sv *out); sn_sv gcli_config_get_upstream(gcli_ctx *ctx); sn_sv gcli_config_get_base(gcli_ctx *ctx); gcli_forge_type gcli_config_get_forge_type(gcli_ctx *ctx); diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 6beae329..09b0e055 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -474,7 +474,7 @@ struct gcli_forge_descriptor { /** * Get the user account name */ - sn_sv (*get_account)(gcli_ctx *ctx); + int (*get_account)(gcli_ctx *ctx, sn_sv *out); /** * Get list of SSH keys */ diff --git a/include/gcli/gitea/config.h b/include/gcli/gitea/config.h index eefa19c9..2ca53df9 100644 --- a/include/gcli/gitea/config.h +++ b/include/gcli/gitea/config.h @@ -40,6 +40,6 @@ char *gitea_get_apibase(gcli_ctx *ctx); char *gitea_get_authheader(gcli_ctx *ctx); -sn_sv gitea_get_account(gcli_ctx *ctx); +int gitea_get_account(gcli_ctx *ctx, sn_sv *out); #endif /* GITEA_CONFIG_H */ diff --git a/include/gcli/github/config.h b/include/gcli/github/config.h index e3089666..b086c2cc 100644 --- a/include/gcli/github/config.h +++ b/include/gcli/github/config.h @@ -40,6 +40,6 @@ char *github_get_apibase(gcli_ctx *ctx); char *github_get_authheader(gcli_ctx *ctx); -sn_sv github_get_account(gcli_ctx *ctx); +int github_get_account(gcli_ctx *ctx, sn_sv *out); #endif /* GITHUB_CONFIG_H */ diff --git a/include/gcli/gitlab/config.h b/include/gcli/gitlab/config.h index 693e29ae..243989ad 100644 --- a/include/gcli/gitlab/config.h +++ b/include/gcli/gitlab/config.h @@ -40,6 +40,6 @@ char *gitlab_get_apibase(gcli_ctx *ctx); char *gitlab_get_authheader(gcli_ctx *ctx); -sn_sv gitlab_get_account(gcli_ctx *ctx); +int gitlab_get_account(gcli_ctx *ctx, sn_sv *out); #endif /* GITLAB_CONFIG_H */ diff --git a/src/cmd/forks.c b/src/cmd/forks.c index 6559ce5f..5fb709b5 100644 --- a/src/cmd/forks.c +++ b/src/cmd/forks.c @@ -170,8 +170,14 @@ subcommand_forks_create(int argc, char *argv[]) return EXIT_SUCCESS; } - if (!in) - in = sn_sv_to_cstr(gcli_config_get_account(g_clictx)); + if (!in) { + sn_sv act; + if (gcli_config_get_account(g_clictx, &act) < 0) { + errx(1, "error: could not fetch account: %s", + gcli_get_error(g_clictx)); + } + in = sn_sv_to_cstr(act); + } gcli_gitconfig_add_fork_remote(in, repo); diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index a92c55f8..a0a9ef5e 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -383,16 +383,19 @@ pr_try_derive_head(void) sn_sv account = {0}; sn_sv branch = {0}; - if (!(account = gcli_config_get_account(g_clictx)).length) + if (gcli_config_get_account(g_clictx, &account) < 0) { errx(1, "error: Cannot derive PR head. Please specify --from or set the\n" - " account in the users gcli config file."); + " account in the users gcli config file.\n" + "note: %s", + gcli_get_error(g_clictx)); + } if (!(branch = gcli_gitconfig_get_current_branch()).length) errx(1, "error: Cannot derive PR head. Please specify --from or, if you\n" " are in »detached HEAD« state, checkout the branch you \n" - " want to pull request."); + " want to pull request.\n"); return sn_sv_fmt(SV_FMT":"SV_FMT, SV_ARGS(account), SV_ARGS(branch)); } diff --git a/src/config.c b/src/config.c index 1bfc014c..91629a62 100644 --- a/src/config.c +++ b/src/config.c @@ -643,12 +643,12 @@ gcli_config_get_authheader(gcli_ctx *ctx) return gcli_forge(ctx)->get_authheader(ctx); } -sn_sv -gcli_config_get_account(gcli_ctx *ctx) +int +gcli_config_get_account(gcli_ctx *ctx, sn_sv *out) { ensure_config(ctx); - return gcli_forge(ctx)->get_account(ctx); + return gcli_forge(ctx)->get_account(ctx, out); } sn_sv diff --git a/src/gitea/config.c b/src/gitea/config.c index 4e9572f6..d68a2b9a 100644 --- a/src/gitea/config.c +++ b/src/gitea/config.c @@ -88,15 +88,18 @@ gitea_get_authheader(gcli_ctx *ctx) return sn_asprintf("Authorization: token "SV_FMT, SV_ARGS(token)); } -sn_sv -gitea_get_account(gcli_ctx *ctx) +int +gitea_get_account(gcli_ctx *ctx, sn_sv *out) { sn_sv const section = gitea_default_account_name(ctx); if (sn_sv_null(section)) - return SV_NULL; + return gcli_error(ctx, "no default gitea account"); sn_sv const account = gcli_config_find_by_key(ctx, section, "account");; if (!account.length) - errx(1, "Missing Gitea account name"); - return account; + return gcli_error(ctx, "missing account name for default gitea account"); + + *out = account; + + return 0; } diff --git a/src/github/config.c b/src/github/config.c index 741079cf..f177b294 100644 --- a/src/github/config.c +++ b/src/github/config.c @@ -82,15 +82,18 @@ github_get_authheader(gcli_ctx *ctx) return sn_asprintf("Authorization: token "SV_FMT, SV_ARGS(token)); } -sn_sv -github_get_account(gcli_ctx *ctx) +int +github_get_account(gcli_ctx *ctx, sn_sv *out) { sn_sv const section = github_default_account_name(ctx); if (sn_sv_null(section)) - return SV_NULL; + return gcli_error(ctx, "no default github account"); - sn_sv const account = gcli_config_find_by_key(ctx, section, "account");; + sn_sv const account = gcli_config_find_by_key(ctx, section, "account"); if (!account.length) - errx(1, "Missing Github account name"); - return account; + return gcli_error(ctx, "Missing Github account name"); + + *out = account; + + return 0; } diff --git a/src/gitlab/config.c b/src/gitlab/config.c index 0e446f1a..e888b784 100644 --- a/src/gitlab/config.c +++ b/src/gitlab/config.c @@ -85,15 +85,18 @@ gitlab_get_authheader(gcli_ctx *ctx) return sn_asprintf("PRIVATE-TOKEN: "SV_FMT, SV_ARGS(token)); } -sn_sv -gitlab_get_account(gcli_ctx *ctx) +int +gitlab_get_account(gcli_ctx *ctx, sn_sv *out) { sn_sv const section = gitlab_default_account_name(ctx); if (sn_sv_null(section)) - return SV_NULL; + return gcli_error(ctx, "no default gitlab account"); - sn_sv const account = gcli_config_find_by_key(ctx, section, "account");; + sn_sv const account = gcli_config_find_by_key(ctx, section, "account"); if (sn_sv_null(account)) - errx(1, "Missing GitLab account name"); - return account; + return gcli_error(ctx, "missing account name in default gitlab account"); + + *out = account; + + return 0; } diff --git a/src/gitlab/repos.c b/src/gitlab/repos.c index 0c1b596c..10e8aa0d 100644 --- a/src/gitlab/repos.c +++ b/src/gitlab/repos.c @@ -121,19 +121,17 @@ gitlab_get_own_repos(gcli_ctx *ctx, int const max, gcli_repo_list *const out) { char *_account = NULL; sn_sv account = {0}; - int n; + int rc = 0; - account = gitlab_get_account(ctx); - if (!account.length) - errx(1, "error: gitlab.account is not set"); + rc = gitlab_get_account(ctx, &account); + if (rc < 0) + return rc; _account = sn_sv_to_cstr(account); - - n = gitlab_get_repos(ctx, _account, max, out); - + rc = gitlab_get_repos(ctx, _account, max, out); free(_account); - return n; + return rc; } int From cd9ef9dc067ab0527f7a3b6fcf3b69f3e2cbc90f Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Wed, 23 Aug 2023 22:59:59 +0200 Subject: [PATCH 145/236] Update todo.org --- todo.org | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/todo.org b/todo.org index 369e71c0..5dc4ed9a 100644 --- a/todo.org +++ b/todo.org @@ -129,11 +129,11 @@ ** TODO Check for calls to errx in submit routines ** TODO [[file:src/github/review.c::github_review_get_reviews(char const *owner)][github_review_get_reviews]] is garbage ** TODO Clean up the generic comments code -** TODO Move printing routines to cmd code +** DONE Move printing routines to cmd code ** DONE Build a shared library ** TODO Remove global curl handle - [X] Put it into the context - [ ] Clean up handle on exit ** TODO Return errors from parsers ** TODO [[file:src/releases.c::gcli_release_push_asset(gcli_new_release *const release,][push_asset]] should not call errx but return an error code -** TODO Make [[file:src/pulls.c::gcli_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner,][getting a pull diff]] return an error code +** DONE Make [[file:src/pulls.c::gcli_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner,][getting a pull diff]] return an error code From 8b1188570226049a482574639d0dd5f46ff75c42 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Wed, 23 Aug 2023 23:30:24 +0200 Subject: [PATCH 146/236] Fix segfault when filtering Github pulls by author --- src/github/pulls.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/github/pulls.c b/src/github/pulls.c index 58a2bff5..feeeb8af 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -58,13 +58,12 @@ github_pulls_filter_author(gcli_pull **listp, size_t *sizep, char const *const a for (size_t i = *sizep; i > 0; --i) { gcli_pull *pulls = *listp; - if (strcmp(author, pulls[i-1].author) == 0) - continue; + if (author && strcmp(author, pulls[i-1].author)) { + gcli_pull_free(&pulls[i - 1]); - gcli_pull_free(&pulls[i - 1]); - - memmove(&pulls[i - 1], &pulls[i], sizeof(*pulls) * (*sizep - i)); - *listp = realloc(pulls, sizeof(*pulls) * (--(*sizep))); + memmove(&pulls[i - 1], &pulls[i], sizeof(*pulls) * (*sizep - i)); + *listp = realloc(pulls, sizeof(*pulls) * (--(*sizep))); + } } } From e6562e49d25cb82ac1242358225daf8bbcadaee1 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Wed, 23 Aug 2023 23:38:35 +0200 Subject: [PATCH 147/236] Remove call to errx --- src/github/releases.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/github/releases.c b/src/github/releases.c index cb666eac..50bae7ba 100644 --- a/src/github/releases.c +++ b/src/github/releases.c @@ -81,15 +81,17 @@ github_parse_single_release(gcli_ctx *ctx, gcli_fetch_buffer buffer, json_close(&stream); } -static char * -github_get_upload_url(gcli_release *const it) +static int +github_get_upload_url(gcli_ctx *ctx, gcli_release *const it, char **out) { char *delim = strchr(it->upload_url.data, '{'); if (delim == NULL) - errx(1, "GitHub API returned an invalid upload url"); + return gcli_error(ctx, "GitHub API returned an invalid upload url"); size_t len = delim - it->upload_url.data; - return sn_strndup(it->upload_url.data, len); + *out = sn_strndup(it->upload_url.data, len); + + return 0; } static int @@ -183,7 +185,9 @@ github_create_release(gcli_ctx *ctx, gcli_new_release const *release) printf("INFO : Release at "SV_FMT"\n", SV_ARGS(response.html_url)); - upload_url = github_get_upload_url(&response); + rc = github_get_upload_url(ctx, &response, &upload_url); + if (rc < 0) + goto out; for (size_t i = 0; i < release->assets_size; ++i) { printf("INFO : Uploading asset %s...\n", release->assets[i].path); From ef546f9542200fc441953841e949aad03c72c796 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 00:07:50 +0200 Subject: [PATCH 148/236] Move gist printing routines out of library I accidentially forgot to move these with the previous pile of patches. --- include/gcli/cmd/gists.h | 5 ++ include/gcli/github/gists.h | 5 +- src/cmd/gists.c | 151 +++++++++++++++++++++++++++++++++++- src/github/gists.c | 149 +---------------------------------- 4 files changed, 156 insertions(+), 154 deletions(-) diff --git a/include/gcli/cmd/gists.h b/include/gcli/cmd/gists.h index d547e8cb..61ad96b3 100644 --- a/include/gcli/cmd/gists.h +++ b/include/gcli/cmd/gists.h @@ -34,6 +34,11 @@ #include #endif +#include + int subcommand_gists(int argc, char *argv[]); +void gcli_print_gists(enum gcli_output_flags flags, gcli_gist_list const *list, + int max); + #endif /* GCLI_CMD_GISTS_H */ diff --git a/include/gcli/github/gists.h b/include/gcli/github/gists.h index 3fd08cc5..3ee4e60c 100644 --- a/include/gcli/github/gists.h +++ b/include/gcli/github/gists.h @@ -79,12 +79,9 @@ int gcli_get_gists(gcli_ctx *ctx, char const *user, int max, gcli_gist *gcli_get_gist(gcli_ctx *ctx, char const *gist_id); -void gcli_print_gists(gcli_ctx *ctx, enum gcli_output_flags flags, - gcli_gist_list const *list, int max); - int gcli_create_gist(gcli_ctx *ctx, gcli_new_gist); -int gcli_delete_gist(gcli_ctx *ctx, char const *gist_id, bool always_yes); +int gcli_delete_gist(gcli_ctx *ctx, char const *gist_id); void gcli_gists_free(gcli_gist_list *list); diff --git a/src/cmd/gists.c b/src/cmd/gists.c index 016da6af..3d80ee41 100644 --- a/src/cmd/gists.c +++ b/src/cmd/gists.c @@ -30,6 +30,9 @@ #include #include +#include +#include + #include #include #include @@ -61,6 +64,146 @@ usage(void) copyright(); } +static char const * +human_readable_size(size_t const s) +{ + if (s < 1024) + return sn_asprintf("%zu B", s); + + if (s < 1024 * 1024) + return sn_asprintf("%zu KiB", s / 1024); + + if (s < 1024 * 1024 * 1024) + return sn_asprintf("%zu MiB", s / (1024 * 1024)); + + return sn_asprintf("%zu GiB", s / (1024 * 1024 * 1024)); +} + +static inline char const * +language_fmt(char const *it) +{ + if (it) + return it; + else + return "Unknown"; +} + +static void +print_gist_file(gcli_gist_file const *const file) +{ + printf(" • %-15.15s %-8.8s %-s\n", + language_fmt(file->language.data), + human_readable_size(file->size), + file->filename.data); +} + +static void +print_gist(enum gcli_output_flags const flags, gcli_gist const *const gist) +{ + (void) flags; + + printf(" ID : %s"SV_FMT"%s\n" + "OWNER : %s"SV_FMT"%s\n" + "DESCR : "SV_FMT"\n" + " DATE : "SV_FMT"\n" + " URL : "SV_FMT"\n" + " PULL : "SV_FMT"\n", + gcli_setcolour(GCLI_COLOR_YELLOW), SV_ARGS(gist->id), gcli_resetcolour(), + gcli_setbold(), SV_ARGS(gist->owner), gcli_resetbold(), + SV_ARGS(gist->description), + SV_ARGS(gist->date), + SV_ARGS(gist->url), + SV_ARGS(gist->git_pull_url)); + printf("FILES : %-15.15s %-8.8s %-s\n", + "LANGUAGE", "SIZE", "FILENAME"); + + for (size_t i = 0; i < gist->files_size; ++i) + print_gist_file(&gist->files[i]); + + printf("\n"); +} + +static void +gcli_print_gists_long(enum gcli_output_flags const flags, + gcli_gist_list const *const list, int const max) +{ + size_t n; + + if (max < 0 || (size_t)(max) > list->gists_size) + n = list->gists_size; + else + n = max; + + if (flags & OUTPUT_SORTED) { + for (size_t i = 0; i < n; ++i) + print_gist(flags, &list->gists[n-i-1]); + } else { + for (size_t i = 0; i < n; ++i) + print_gist(flags, &list->gists[i]); + } +} + +static void +gcli_print_gists_short(enum gcli_output_flags const flags, + gcli_gist_list const *const list, int const max) +{ + size_t n; + gcli_tbl table; + gcli_tblcoldef cols[] = { + { .name = "ID", .type = GCLI_TBLCOLTYPE_SV, .flags = GCLI_TBLCOL_COLOUREXPL }, + { .name = "OWNER", .type = GCLI_TBLCOLTYPE_SV, .flags = GCLI_TBLCOL_BOLD }, + { .name = "DATE", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, + { .name = "FILES", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, + { .name = "DESCRIPTION", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, + }; + + if (max < 0 || (size_t)(max) > list->gists_size) + n = list->gists_size; + else + n = max; + + table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); + if (!table) + errx(1, "error: could not init table"); + + if (flags & OUTPUT_SORTED) { + for (size_t i = 0; i < n; ++i) { + gcli_tbl_add_row(table, + GCLI_COLOR_YELLOW, list->gists[n-i-1].id, + list->gists[n-i-1].owner, + list->gists[n-i-1].date, + (int)list->gists[n-i-1].files_size, /* For safety pass it as int */ + list->gists[n-i-1].description); + } + } else { + for (size_t i = 0; i < n; ++i) { + gcli_tbl_add_row(table, + GCLI_COLOR_YELLOW, list->gists[i].id, + list->gists[i].owner, + list->gists[i].date, + (int)list->gists[i].files_size, + list->gists[i].description); + } + } + + gcli_tbl_end(table); +} + +void +gcli_print_gists(enum gcli_output_flags const flags, + gcli_gist_list const *const list, int const max) +{ + if (list->gists_size == 0) { + puts("No Gists"); + return; + } + + if (flags & OUTPUT_LONG) /* if we are in long mode (no pun intended) */ + gcli_print_gists_long(flags, list, max); + else /* real mode (bad joke, I know) */ + gcli_print_gists_short(flags, list, max); +} + static int subcommand_gist_get(int argc, char *argv[]) { @@ -186,7 +329,11 @@ subcommand_gist_delete(int argc, char *argv[]) argv += optind; gist_id = shift(&argc, &argv); - gcli_delete_gist(g_clictx, gist_id, always_yes); + + if (!always_yes && !sn_yesno("Are you sure you want to delete this gist?")) + errx(1, "Aborted by user"); + + gcli_delete_gist(g_clictx, gist_id); return EXIT_SUCCESS; } @@ -274,7 +421,7 @@ subcommand_gists(int argc, char *argv[]) if (gcli_get_gists(g_clictx, user, count, &gists) < 0) errx(1, "error: failed to get gists"); - gcli_print_gists(g_clictx, flags, &gists, count); + gcli_print_gists(flags, &gists, count); gcli_gists_free(&gists); return EXIT_SUCCESS; diff --git a/src/github/gists.c b/src/github/gists.c index ad30b6d3..92909c70 100644 --- a/src/github/gists.c +++ b/src/github/gists.c @@ -88,150 +88,6 @@ gcli_get_gists(gcli_ctx *ctx, char const *user, int const max, return gcli_fetch_list(ctx, url, &fl); } -static char const * -human_readable_size(size_t const s) -{ - if (s < 1024) - return sn_asprintf("%zu B", s); - - if (s < 1024 * 1024) - return sn_asprintf("%zu KiB", s / 1024); - - if (s < 1024 * 1024 * 1024) - return sn_asprintf("%zu MiB", s / (1024 * 1024)); - - return sn_asprintf("%zu GiB", s / (1024 * 1024 * 1024)); -} - -static inline char const * -language_fmt(char const *it) -{ - if (it) - return it; - else - return "Unknown"; -} - -static void -print_gist_file(gcli_gist_file const *const file) -{ - printf(" • %-15.15s %-8.8s %-s\n", - language_fmt(file->language.data), - human_readable_size(file->size), - file->filename.data); -} - -static void -print_gist(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_gist const *const gist) -{ - (void) ctx; - (void) flags; - - printf(" ID : %s"SV_FMT"%s\n" - "OWNER : %s"SV_FMT"%s\n" - "DESCR : "SV_FMT"\n" - " DATE : "SV_FMT"\n" - " URL : "SV_FMT"\n" - " PULL : "SV_FMT"\n", - gcli_setcolour(GCLI_COLOR_YELLOW), SV_ARGS(gist->id), gcli_resetcolour(), - gcli_setbold(), SV_ARGS(gist->owner), gcli_resetbold(), - SV_ARGS(gist->description), - SV_ARGS(gist->date), - SV_ARGS(gist->url), - SV_ARGS(gist->git_pull_url)); - printf("FILES : %-15.15s %-8.8s %-s\n", - "LANGUAGE", "SIZE", "FILENAME"); - - for (size_t i = 0; i < gist->files_size; ++i) - print_gist_file(&gist->files[i]); - - printf("\n"); -} - -static void -gcli_print_gists_long(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_gist_list const *const list, int const max) -{ - size_t n; - - if (max < 0 || (size_t)(max) > list->gists_size) - n = list->gists_size; - else - n = max; - - if (flags & OUTPUT_SORTED) { - for (size_t i = 0; i < n; ++i) - print_gist(ctx, flags, &list->gists[n-i-1]); - } else { - for (size_t i = 0; i < n; ++i) - print_gist(ctx, flags, &list->gists[i]); - } -} - -static void -gcli_print_gists_short(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_gist_list const *const list, int const max) -{ - size_t n; - gcli_tbl table; - gcli_tblcoldef cols[] = { - { .name = "ID", .type = GCLI_TBLCOLTYPE_SV, .flags = GCLI_TBLCOL_COLOUREXPL }, - { .name = "OWNER", .type = GCLI_TBLCOLTYPE_SV, .flags = GCLI_TBLCOL_BOLD }, - { .name = "DATE", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, - { .name = "FILES", .type = GCLI_TBLCOLTYPE_INT, .flags = GCLI_TBLCOL_JUSTIFYR }, - { .name = "DESCRIPTION", .type = GCLI_TBLCOLTYPE_SV, .flags = 0 }, - }; - - (void) ctx; - - if (max < 0 || (size_t)(max) > list->gists_size) - n = list->gists_size; - else - n = max; - - table = gcli_tbl_begin(cols, ARRAY_SIZE(cols)); - if (!table) - errx(1, "error: could not init table"); - - if (flags & OUTPUT_SORTED) { - for (size_t i = 0; i < n; ++i) { - gcli_tbl_add_row(table, - GCLI_COLOR_YELLOW, list->gists[n-i-1].id, - list->gists[n-i-1].owner, - list->gists[n-i-1].date, - (int)list->gists[n-i-1].files_size, /* For safety pass it as int */ - list->gists[n-i-1].description); - } - } else { - for (size_t i = 0; i < n; ++i) { - gcli_tbl_add_row(table, - GCLI_COLOR_YELLOW, list->gists[i].id, - list->gists[i].owner, - list->gists[i].date, - (int)list->gists[i].files_size, - list->gists[i].description); - } - } - - gcli_tbl_end(table); -} - -void -gcli_print_gists(gcli_ctx *ctx, enum gcli_output_flags const flags, - gcli_gist_list const *const list, int const max) -{ - if (list->gists_size == 0) { - puts("No Gists"); - return; - } - - if (flags & OUTPUT_LONG) /* if we are in long mode (no pun intended) */ - gcli_print_gists_long(ctx, flags, list, max); - else /* real mode (bad joke, I know) */ - gcli_print_gists_short(ctx, flags, list, max); -} - gcli_gist * gcli_get_gist(gcli_ctx *ctx, char const *gist_id) { @@ -331,7 +187,7 @@ gcli_create_gist(gcli_ctx *ctx, gcli_new_gist opts) } int -gcli_delete_gist(gcli_ctx *ctx, char const *gist_id, bool const always_yes) +gcli_delete_gist(gcli_ctx *ctx, char const *gist_id) { char *url = NULL; gcli_fetch_buffer buffer = {0}; @@ -342,9 +198,6 @@ gcli_delete_gist(gcli_ctx *ctx, char const *gist_id, bool const always_yes) github_get_apibase(ctx), gist_id); - if (!always_yes && !sn_yesno("Are you sure you want to delete this gist?")) - errx(1, "Aborted by user"); - rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, &buffer); free(buffer.data); From d8ce4941d12dd643ba4b67f31778aea0ae124ecc Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 00:10:27 +0200 Subject: [PATCH 149/236] Remove call to errx --- src/github/issues.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/github/issues.c b/src/github/issues.c index c66f9430..f0bde57a 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -308,9 +308,10 @@ github_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, char *e_label = NULL; int rc = 0; - if (labels_size != 1) - errx(1, "error: GitHub only supports removing labels from " - "issues one by one."); + if (labels_size != 1) { + return gcli_error(ctx, "GitHub only supports removing labels from " + "issues one by one."); + } e_label = gcli_urlencode(labels[0]); From 065d5881a585d44d8cb856054bcb62041fc9298a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 00:15:01 +0200 Subject: [PATCH 150/236] Make normalize_date_to_iso8601 return an error code instead of calling errx --- src/github/milestones.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/github/milestones.c b/src/github/milestones.c index f5ce7a79..f47ce92b 100644 --- a/src/github/milestones.c +++ b/src/github/milestones.c @@ -185,9 +185,9 @@ github_delete_milestone(gcli_ctx *ctx, char const *const owner, return rc; } -static void -normalize_date_to_iso8601(char const *const input, - char *output, size_t const output_size) +static int +normalize_date_to_iso8601(gcli_ctx *ctx, char const *const input, char *output, + size_t const output_size) { struct tm tm_buf = {0}; struct tm *utm_buf; @@ -199,7 +199,7 @@ normalize_date_to_iso8601(char const *const input, /* Parse input time */ endptr = strptime(input, "%Y-%m-%d", &tm_buf); if (endptr == NULL || *endptr != '\0') - errx(1, "error: date »%s« is invalid: want YYYY-MM-DD", input); + return gcli_error(ctx, "date »%s« is invalid: want YYYY-MM-DD", input); /* Convert to UTC: Really, we should be using the _r versions of * these functions for thread-safety but since gcli doesn't do @@ -211,6 +211,8 @@ normalize_date_to_iso8601(char const *const input, /* Format the output string - now in UTC */ strftime(output, output_size, "%Y-%m-%dT%H:%M:%SZ", utm_buf); + + return 0; } int @@ -221,6 +223,10 @@ github_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, char *url, *e_owner, *e_repo, *payload, norm_date[21] = {0}; int rc = 0; + rc = normalize_date_to_iso8601(ctx, date, norm_date, sizeof norm_date); + if (rc < 0) + return rc; + e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); @@ -228,8 +234,6 @@ github_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, gcli_get_apibase(ctx), e_owner, e_repo, milestone); - normalize_date_to_iso8601(date, norm_date, sizeof norm_date); - payload = sn_asprintf("{ \"due_on\": \"%s\"}", norm_date); rc = gcli_fetch_with_method(ctx, "PATCH", url, payload, NULL, NULL); From e5734bd385952847660d417ed716161b007a015d Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 00:29:03 +0200 Subject: [PATCH 151/236] Make gitea label_names_to_ids return error codes --- src/cmd/labels.c | 3 ++- src/curl.c | 19 ++++++------------- src/gitea/issues.c | 31 ++++++++++++++++++++----------- src/gitea/labels.c | 10 ++++------ 4 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/cmd/labels.c b/src/cmd/labels.c index 98f5429b..c0838021 100644 --- a/src/cmd/labels.c +++ b/src/cmd/labels.c @@ -286,7 +286,8 @@ subcommand_labels(int argc, char *argv[]) check_owner_and_repo(&owner, &repo); if (gcli_get_labels(g_clictx, owner, repo, count, &labels) < 0) - errx(1, "error: could not fetch list of labels"); + errx(1, "error: could not fetch list of labels: %s", + gcli_get_error(g_clictx)); gcli_labels_print(&labels, count); diff --git a/src/curl.c b/src/curl.c index 1b8d5163..31d3ea91 100644 --- a/src/curl.c +++ b/src/curl.c @@ -93,24 +93,17 @@ gcli_curl_check_api_error(gcli_ctx *ctx, CURLcode code, char const *url, long status_code = 0; if (code != CURLE_OK) { - fprintf(stderr, - "error: request to %s failed\n" - " : curl error: %s", - url, - curl_easy_strerror(code)); - - return -1; + return gcli_error(ctx, "request to %s failed: curl error: %s", + url, curl_easy_strerror(code)); } curl_easy_getinfo(ctx->curl, CURLINFO_RESPONSE_CODE, &status_code); if (status_code >= 300L) { - fprintf(stderr, - "error: request to %s failed with code %ld\n" - " : API error: %s", - url, status_code, - gcli_forge(ctx)->get_api_error_string(ctx, result)); - return -1; + return gcli_error(ctx, + "request to %s failed with code %ld: API error: %s", + url, status_code, + gcli_forge(ctx)->get_api_error_string(ctx, result)); } return 0; diff --git a/src/gitea/issues.c b/src/gitea/issues.c index eace78af..970dd03e 100644 --- a/src/gitea/issues.c +++ b/src/gitea/issues.c @@ -148,6 +148,15 @@ get_id_of_label(char const *label_name, return NULL; } +static void +free_id_list(char *list[], size_t const list_size) +{ + for (size_t i = 0; i < list_size; ++i) { + free(list[i]); + } + free(list); +} + static char ** label_names_to_ids(gcli_ctx *ctx, char const *owner, char const *repo, char const *const names[], size_t const names_size) @@ -161,27 +170,23 @@ label_names_to_ids(gcli_ctx *ctx, char const *owner, char const *repo, for (size_t i = 0; i < names_size; ++i) { char *const label_id = get_id_of_label(names[i], &list); - if (!label_id) - errx(1, "error: no such label '%s'", names[i]); + if (!label_id) { + free_id_list(ids, ids_size); + ids = NULL; + gcli_error(ctx, "no such label '%s'", names[i]); + goto out; + } ids = realloc(ids, sizeof(*ids) * (ids_size +1)); ids[ids_size++] = label_id; } +out: gcli_free_labels(&list); return ids; } -static void -free_id_list(char *list[], size_t const list_size) -{ - for (size_t i = 0; i < list_size; ++i) { - free(list[i]); - } - free(list); -} - int gitea_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, int const issue, char const *const labels[], @@ -194,6 +199,8 @@ gitea_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, /* First, convert to ids */ char **ids = label_names_to_ids(ctx, owner, repo, labels, labels_size); + if (!ids) + return -1; /* Construct json payload */ @@ -224,6 +231,8 @@ gitea_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, * delete labels from an issue in bulk. So, just iterate over the * given labels and delete them one after another. */ char **ids = label_names_to_ids(ctx, owner, repo, labels, labels_size); + if (!ids) + return -1; for (size_t i = 0; i < labels_size; ++i) { char *url = NULL; diff --git a/src/gitea/labels.c b/src/gitea/labels.c index 1229cf2e..c53f318a 100644 --- a/src/gitea/labels.c +++ b/src/gitea/labels.c @@ -72,12 +72,11 @@ gitea_delete_label(gcli_ctx *ctx, char const *owner, char const *repo, } } + gcli_free_labels(&list); + /* did we find a label? */ - if (id < 0) { - /* TODO: Save error message - * errx(1, "error: label '%s' does not exist", label); */ - return -1; - } + if (id < 0) + return gcli_error(ctx, "label '%s' does not exist", label); /* DELETE /repos/{owner}/{repo}/labels/{} */ url = sn_asprintf("%s/repos/%s/%s/labels/%d", @@ -86,7 +85,6 @@ gitea_delete_label(gcli_ctx *ctx, char const *owner, char const *repo, rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); - gcli_free_labels(&list); free(url); return rc; From 459d01a6310630d71b4067a2830c18ea7bda37fa Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 01:00:44 +0200 Subject: [PATCH 152/236] Move formatting and normalising date/time This provides a semi-generic interface for parsing date/time stamps. Hooked up to milestones. Also, print proper error messages in milestone subcommand. --- Makefile.am | 1 + include/gcli/date_time.h | 47 ++++++++++++++++++++++++ src/cmd/milestones.c | 21 +++++++---- src/date_time.c | 77 ++++++++++++++++++++++++++++++++++++++++ src/github/milestones.c | 34 ++---------------- src/gitlab/milestones.c | 35 +++--------------- 6 files changed, 147 insertions(+), 68 deletions(-) create mode 100644 include/gcli/date_time.h create mode 100644 src/date_time.c diff --git a/Makefile.am b/Makefile.am index 42e491b1..251ecd64 100644 --- a/Makefile.am +++ b/Makefile.am @@ -125,6 +125,7 @@ include_HEADERS = include/gcli/gcli.h include/gcli/comments.h \ libgcli_la_SOURCES = \ include/gcli/ctx.h src/ctx.c \ include/gcli/gcli.h src/gcli.c \ + include/gcli/date_time.h src/date_time.c \ src/comments.c include/gcli/comments.h \ src/config.c include/gcli/config.h \ src/curl.c include/gcli/curl.h \ diff --git a/include/gcli/date_time.h b/include/gcli/date_time.h new file mode 100644 index 00000000..e8e790cb --- /dev/null +++ b/include/gcli/date_time.h @@ -0,0 +1,47 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_DATE_TIME_H +#define GCLI_DATE_TIME_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +enum { + DATEFMT_ISO8601, + DATEFMT_GITLAB, +}; + +int gcli_normalize_date(gcli_ctx *ctx, int fmt, char const *const input, + char *output, size_t const output_size); + +#endif /* GCLI_DATE_TIME_H */ diff --git a/src/cmd/milestones.c b/src/cmd/milestones.c index ddfa8e9f..6fa479ba 100644 --- a/src/cmd/milestones.c +++ b/src/cmd/milestones.c @@ -199,7 +199,8 @@ subcommand_milestone_create(int argc, char *argv[]) /* actually create the milestone */ if (gcli_create_milestone(g_clictx, &args) < 0) - errx(1, "error: could not create milestone"); + errx(1, "error: could not create milestone: %s", + gcli_get_error(g_clictx)); return 0; } @@ -278,7 +279,8 @@ subcommand_milestones(int argc, char *argv[]) rc = gcli_get_milestones(g_clictx, owner, repo, max, &list); if (rc < 0) - errx(1, "error: cannot get list of milestones"); + errx(1, "error: cannot get list of milestones: %s", + gcli_get_error(g_clictx)); gcli_print_milestones(&list, max); @@ -304,7 +306,8 @@ ensure_milestone(char const *const owner, rc = gcli_get_milestone(g_clictx, owner, repo, milestone_id, milestone); if (rc < 0) - errx(1, "error: could not get milestone %d", milestone_id); + errx(1, "error: could not get milestone %d: %s", milestone_id, + gcli_get_error(g_clictx)); *fetched_milestone = 1; } @@ -345,7 +348,8 @@ handle_milestone_actions(int argc, char *argv[], &issues); if (rc < 0) - errx(1, "error: failed to fetch issues"); + errx(1, "error: failed to fetch issues: %s", + gcli_get_error(g_clictx)); printf("\nISSUES:\n"); gcli_print_issues(0, &issues, -1); @@ -359,7 +363,8 @@ handle_milestone_actions(int argc, char *argv[], rc = gcli_milestone_get_issues(g_clictx, owner, repo, milestone_id, &issues); if (rc < 0) - errx(1, "error: failed to fetch issues"); + errx(1, "error: failed to fetch issues: %s", + gcli_get_error(g_clictx)); /* Print them as a table */ gcli_print_issues(0, &issues, -1); @@ -379,7 +384,8 @@ handle_milestone_actions(int argc, char *argv[], /* Delete the milestone */ if (gcli_delete_milestone(g_clictx, owner, repo, milestone_id) < 0) - errx(1, "error: could not delete milestone"); + errx(1, "error: could not delete milestone: %s", + gcli_get_error(g_clictx)); } else if (strcmp(action, "set-duedate") == 0) { @@ -396,7 +402,8 @@ handle_milestone_actions(int argc, char *argv[], rc = gcli_milestone_set_duedate(g_clictx, owner, repo, milestone_id, new_date); if (rc < 0) - errx(1, "error: could not update milestone due date"); + errx(1, "error: could not update milestone due date: %s", + gcli_get_error(g_clictx));; } else { diff --git a/src/date_time.c b/src/date_time.c new file mode 100644 index 00000000..713a2bf9 --- /dev/null +++ b/src/date_time.c @@ -0,0 +1,77 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include + +#include +#include + +int +gcli_normalize_date(gcli_ctx *ctx, int fmt, char const *const input, + char *output, size_t const output_size) +{ + struct tm tm_buf = {0}; + struct tm *utm_buf; + char *endptr; + time_t utctime; + char const *sfmt; + + switch (fmt) { + case DATEFMT_ISO8601: + sfmt = "%Y-%m-%dT%H:%M:%SZ"; + assert(output_size == 21); + break; + case DATEFMT_GITLAB: + sfmt = "%Y%m%d"; + assert(output_size == 9); + break; + default: + return gcli_error(ctx, "bad date format"); + } + + /* Parse input time */ + endptr = strptime(input, "%Y-%m-%d", &tm_buf); + if (endptr == NULL || *endptr != '\0') + return gcli_error(ctx, "date »%s« is invalid: want YYYY-MM-DD", input); + + /* Convert to UTC: Really, we should be using the _r versions of + * these functions for thread-safety but since gcli doesn't do + * multithreading (except for inside libcurl) we do not need to be + * worried about the storage behind the pointer returned by gmtime + * to be altered by another thread. */ + utctime = mktime(&tm_buf); + utm_buf = gmtime(&utctime); + + /* Format the output string - now in UTC */ + strftime(output, output_size, sfmt, utm_buf); + + return 0; +} diff --git a/src/github/milestones.c b/src/github/milestones.c index f47ce92b..c82325db 100644 --- a/src/github/milestones.c +++ b/src/github/milestones.c @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -185,36 +186,6 @@ github_delete_milestone(gcli_ctx *ctx, char const *const owner, return rc; } -static int -normalize_date_to_iso8601(gcli_ctx *ctx, char const *const input, char *output, - size_t const output_size) -{ - struct tm tm_buf = {0}; - struct tm *utm_buf; - char *endptr; - time_t utctime; - - assert(output_size == 21); - - /* Parse input time */ - endptr = strptime(input, "%Y-%m-%d", &tm_buf); - if (endptr == NULL || *endptr != '\0') - return gcli_error(ctx, "date »%s« is invalid: want YYYY-MM-DD", input); - - /* Convert to UTC: Really, we should be using the _r versions of - * these functions for thread-safety but since gcli doesn't do - * multithreading (except for inside libcurl) we do not need to be - * worried about the storage behind the pointer returned by gmtime - * to be altered by another thread. */ - utctime = mktime(&tm_buf); - utm_buf = gmtime(&utctime); - - /* Format the output string - now in UTC */ - strftime(output, output_size, "%Y-%m-%dT%H:%M:%SZ", utm_buf); - - return 0; -} - int github_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, char const *const repo, int const milestone, @@ -223,7 +194,8 @@ github_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, char *url, *e_owner, *e_repo, *payload, norm_date[21] = {0}; int rc = 0; - rc = normalize_date_to_iso8601(ctx, date, norm_date, sizeof norm_date); + rc = gcli_normalize_date(ctx, DATEFMT_ISO8601, date, norm_date, + sizeof norm_date); if (rc < 0) return rc; diff --git a/src/gitlab/milestones.c b/src/gitlab/milestones.c index 65aac013..716884ef 100644 --- a/src/gitlab/milestones.c +++ b/src/gitlab/milestones.c @@ -28,6 +28,7 @@ */ #include +#include #include #include #include @@ -179,35 +180,6 @@ gitlab_delete_milestone(gcli_ctx *ctx, char const *const owner, return rc; } -/* TODO: merge this with the github code */ -static void -normalize_date_to_gitlab_format(char const *const input, char *output, - size_t const output_size) -{ - struct tm tm_buf = {0}; - struct tm *utm_buf; - char *endptr; - time_t utctime; - - assert(output_size == 9); - - /* Parse input time */ - endptr = strptime(input, "%Y-%m-%d", &tm_buf); - if (endptr == NULL || *endptr != '\0') - errx(1, "error: date »%s« is invalid: want YYYY-MM-DD", input); - - /* Convert to UTC: Really, we should be using the _r versions of - * these functions for thread-safety but since gcli doesn't do - * multithreading (except for inside libcurl) we do not need to be - * worried about the storage behind the pointer returned by gmtime - * to be altered by another thread. */ - utctime = mktime(&tm_buf); - utm_buf = gmtime(&utctime); - - /* Format the output string - now in UTC */ - strftime(output, output_size, "%Y%m%d", utm_buf); -} - int gitlab_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, char const *const repo, int const milestone, @@ -216,7 +188,10 @@ gitlab_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, char *url, *e_owner, *e_repo, norm_date[9] = {0}; int rc = 0; - normalize_date_to_gitlab_format(date, norm_date, sizeof norm_date); + rc = gcli_normalize_date(ctx, DATEFMT_GITLAB, date, norm_date, + sizeof norm_date); + if (rc < 0) + return rc; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); From 9c0a232aac60a8e4def5edf50754dd0945546189 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 01:02:19 +0200 Subject: [PATCH 153/236] Remove invalid warning --- src/github/pulls.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/github/pulls.c b/src/github/pulls.c index feeeb8af..e0fde179 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -95,9 +95,6 @@ github_get_pulls(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - if (details->author) - warnx("author is ignored by the GitHub routines"); - url = sn_asprintf( "%s/repos/%s/%s/pulls?state=%s", gcli_get_apibase(ctx), From 8ade92b1d43104276d1a4bc726d285233a2e0cc2 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 01:07:51 +0200 Subject: [PATCH 154/236] issue subcommand: print error messages from library in case of error --- src/cmd/issues.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/cmd/issues.c b/src/cmd/issues.c index 8a29c643..26e40cd3 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -291,7 +291,7 @@ subcommand_issue_create(int argc, char *argv[]) opts.title = SV(argv[0]); if (create_issue(opts, always_yes) < 0) - errx(1, "failed to submit issue"); + errx(1, "error: failed to submit issue: %s", gcli_get_error(g_clictx)); return EXIT_SUCCESS; } @@ -405,7 +405,7 @@ subcommand_issues(int argc, char *argv[]) /* No issue number was given, so list all open issues */ if (issue_id < 0) { if (gcli_get_issues(g_clictx, owner, repo, &details, n, &list) < 0) - errx(1, "error: could not get issues"); + errx(1, "error: could not get issues: %s", gcli_get_error(g_clictx)); gcli_print_issues(flags, &list, n); @@ -433,7 +433,8 @@ ensure_issue(char const *const owner, char const *const repo, return; if (gcli_get_issue(g_clictx, owner, repo, issue_id, issue) < 0) - errx(1, "error: failed to retrieve issue data"); + errx(1, "error: failed to retrieve issue data: %s", + gcli_get_error(g_clictx)); *have_fetched_issue = 1; } @@ -464,16 +465,20 @@ handle_issue_labels_action(int *argc, char ***argv, rc = gcli_issue_add_labels(g_clictx, owner, repo, issue_id, add_labels, add_labels_size); - if (rc < 0) - errx(1, "failed to add labels"); + if (rc < 0) { + errx(1, "error: failed to add labels: %s", + gcli_get_error(g_clictx)); + } } if (remove_labels_size) { rc = gcli_issue_remove_labels(g_clictx, owner, repo, issue_id, remove_labels, remove_labels_size); - if (rc < 0) - errx(1, "failed to remove labels"); + if (rc < 0) { + errx(1, "error: failed to remove labels: %s", + gcli_get_error(g_clictx)); + } } free(add_labels); @@ -506,8 +511,10 @@ handle_issue_milestone_action(int *argc, char ***argv, * clear the milestone */ if (strcmp(milestone_str, "-d") == 0) { rc = gcli_issue_clear_milestone(g_clictx, owner, repo, issue_id); - if (rc < 0) - errx(1, "error: could not clear milestone of issue #%d", issue_id); + if (rc < 0) { + errx(1, "error: could not clear milestone of issue #%d: %s", + issue_id, gcli_get_error(g_clictx)); + } return; } @@ -523,7 +530,8 @@ handle_issue_milestone_action(int *argc, char ***argv, /* Pass it to the dispatch */ if (gcli_issue_set_milestone(g_clictx, owner, repo, issue_id, milestone) < 0) - errx(1, "error: could not assign milestone"); + errx(1, "error: could not assign milestone: %s", + gcli_get_error(g_clictx)); } static inline int @@ -577,18 +585,21 @@ handle_issues_actions(int argc, char *argv[], } else if (strcmp("close", operation) == 0) { if (gcli_issue_close(g_clictx, owner, repo, issue_id) < 0) - errx(1, "failed to close issue"); + errx(1, "error: failed to close issue: %s", + gcli_get_error(g_clictx)); } else if (strcmp("reopen", operation) == 0) { if (gcli_issue_reopen(g_clictx, owner, repo, issue_id) < 0) - errx(1, "failed to reopen issue"); + errx(1, "error: failed to reopen issue: %s", + gcli_get_error(g_clictx)); } else if (strcmp("assign", operation) == 0) { char const *assignee = shift(&argc, &argv); if (gcli_issue_assign(g_clictx, owner, repo, issue_id, assignee) < 0) - errx(1, "failed to assign issue"); + errx(1, "error: failed to assign issue: %s", + gcli_get_error(g_clictx)); } else if (strcmp("labels", operation) == 0) { From 71fc21d60523e81d126201590651c809191a2058 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 01:36:53 +0200 Subject: [PATCH 155/236] Make all error cases in the cmd code print the library errors --- src/cmd/comment.c | 2 +- src/cmd/forks.c | 5 ++--- src/cmd/gists.c | 13 ++++++------- src/cmd/labels.c | 6 ++---- src/cmd/pipelines.c | 17 +++++++++-------- src/cmd/pulls.c | 39 ++++++++++++++++++++++++++------------- src/cmd/releases.c | 6 +++--- src/cmd/repos.c | 4 ++-- src/cmd/snippets.c | 6 ++++-- src/cmd/status.c | 3 ++- 10 files changed, 57 insertions(+), 44 deletions(-) diff --git a/src/cmd/comment.c b/src/cmd/comment.c index 5cdd8527..0990bbbe 100644 --- a/src/cmd/comment.c +++ b/src/cmd/comment.c @@ -243,7 +243,7 @@ subcommand_comment(int argc, char *argv[]) always_yes); if (rc < 0) - errx(1, "error: failed to submit comment"); + errx(1, "error: failed to submit comment: %s", gcli_get_error(g_clictx)); return EXIT_SUCCESS; } diff --git a/src/cmd/forks.c b/src/cmd/forks.c index 5fb709b5..d290fbf9 100644 --- a/src/cmd/forks.c +++ b/src/cmd/forks.c @@ -163,7 +163,7 @@ subcommand_forks_create(int argc, char *argv[]) check_owner_and_repo(&owner, &repo); if (gcli_fork_create(g_clictx, owner, repo, in) < 0) - errx(1, "error: failed to fork repository"); + errx(1, "error: failed to fork repository: %s", gcli_get_error(g_clictx)); if (!always_yes) { if (!sn_yesno("Do you want to add a remote for the fork?")) @@ -262,8 +262,7 @@ subcommand_forks(int argc, char *argv[]) if (argc == 0) { if (gcli_get_forks(g_clictx, owner, repo, count, &forks) < 0) - errx(1, "error: could not get forks: %s", - gcli_get_error(g_clictx)); + errx(1, "error: could not get forks: %s", gcli_get_error(g_clictx)); gcli_print_forks(flags, &forks, count); gcli_forks_free(&forks); diff --git a/src/cmd/gists.c b/src/cmd/gists.c index 3d80ee41..18714605 100644 --- a/src/cmd/gists.c +++ b/src/cmd/gists.c @@ -223,16 +223,15 @@ subcommand_gist_get(int argc, char *argv[]) } } - errx(1, "gists get: %s: no such file in gist with id %s", - file_name, gist_id); + errx(1, "gists get: %s: no such file in gist with id %s", file_name, gist_id); file_found: if (isatty(STDOUT_FILENO) && (file->size >= 4 * 1024 * 1024)) - errx(1, "File is bigger than 4 MiB, refusing to print to stdout."); + errx(1, "error: File is bigger than 4 MiB, refusing to print to stdout."); if (gcli_curl(g_clictx, stdout, file->url.data, file->type.data) < 0) - errx(1, "error: failed to fetch gist"); + errx(1, "error: failed to fetch gist: %s", gcli_get_error(g_clictx)); return EXIT_SUCCESS; } @@ -284,7 +283,7 @@ subcommand_gist_create(int argc, char *argv[]) if (file) { if ((opts.file = fopen(file, "r")) == NULL) - err(1, "gists create: cannot open file"); + err(1, "error: gists create: cannot open file"); } else { opts.file = stdin; } @@ -293,7 +292,7 @@ subcommand_gist_create(int argc, char *argv[]) opts.gist_description = "gcli paste"; if (gcli_create_gist(g_clictx, opts) < 0) - errx(1, "error: failed to create gist"); + errx(1, "error: failed to create gist: %s", gcli_get_error(g_clictx)); return EXIT_SUCCESS; } @@ -419,7 +418,7 @@ subcommand_gists(int argc, char *argv[]) argv += optind; if (gcli_get_gists(g_clictx, user, count, &gists) < 0) - errx(1, "error: failed to get gists"); + errx(1, "error: failed to get gists: %s", gcli_get_error(g_clictx)); gcli_print_gists(flags, &gists, count); gcli_gists_free(&gists); diff --git a/src/cmd/labels.c b/src/cmd/labels.c index c0838021..3a625d29 100644 --- a/src/cmd/labels.c +++ b/src/cmd/labels.c @@ -203,10 +203,8 @@ subcommand_labels_create(int argc, char *argv[]) return EXIT_FAILURE; } - if (gcli_create_label(g_clictx, owner, repo, &label) < 0) { - fprintf(stderr, "error: could not create label\n"); - return EXIT_FAILURE; - } + if (gcli_create_label(g_clictx, owner, repo, &label) < 0) + errx(1, "error: failed to create label: %s", gcli_get_error(g_clictx)); /* only if we are not quieted */ if (!sn_quiet()) diff --git a/src/cmd/pipelines.c b/src/cmd/pipelines.c index 77393b46..d6ce0f21 100644 --- a/src/cmd/pipelines.c +++ b/src/cmd/pipelines.c @@ -231,11 +231,11 @@ gitlab_job_retry_cb(char const *owner, char const *repo, long const jid) int subcommand_pipelines(int argc, char *argv[]) { - int ch = 0; + int ch = 0; char const *owner = NULL, *repo = NULL; - int count = 30; - long pid = -1; /* pipeline id */ - long jid = -1; /* job id. these are mutually exclusive. */ + int count = 30; + long pid = -1; /* pipeline id */ + long jid = -1; /* job id. these are mutually exclusive. */ /* Parse options */ const struct option options[] = { @@ -257,13 +257,13 @@ subcommand_pipelines(int argc, char *argv[]) break; case 'n': { char *endptr = NULL; - count = strtol(optarg, &endptr, 10); + count = strtol(optarg, &endptr, 10); if (endptr != (optarg + strlen(optarg))) err(1, "ci: cannot parse argument to -n"); } break; case 'p': { char *endptr = NULL; - pid = strtol(optarg, &endptr, 10); + pid = strtol(optarg, &endptr, 10); if (endptr != (optarg + strlen(optarg))) err(1, "ci: cannot parse argument to -p"); if (pid < 0) { @@ -272,7 +272,7 @@ subcommand_pipelines(int argc, char *argv[]) } break; case 'j': { char *endptr = NULL; - jid = strtol(optarg, &endptr, 10); + jid = strtol(optarg, &endptr, 10); if (endptr != (optarg + strlen(optarg))) err(1, "ci: cannot parse argument to -j"); if (jid < 0) { @@ -372,7 +372,8 @@ subcommand_pipelines(int argc, char *argv[]) argv += 2; } if (gitlab_job_download_artifacts(g_clictx, owner, repo, jid, outfile) < 0) - errx(1, "error: failed to download file"); + errx(1, "error: failed to download file: %s", + gcli_get_error(g_clictx)); goto next_action; } diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index a0a9ef5e..6c406d6c 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -609,7 +609,8 @@ subcommand_pulls(int argc, char *argv[]) * open PRs and exit */ if (pr < 0) { if (gcli_get_pulls(g_clictx, owner, repo, &details, n, &pulls) < 0) - errx(1, "error: could not fetch pull requests"); + errx(1, "error: could not fetch pull requests: %s", + gcli_get_error(g_clictx)); gcli_print_pulls(flags, &pulls, n); gcli_pulls_free(&pulls); @@ -637,7 +638,8 @@ ensure_pull(char const *owner, char const *repo, int pr, return; if (gcli_get_pull(g_clictx, owner, repo, pr, pull) < 0) - errx(1, "error: failed to fetch pull request data"); + errx(1, "error: failed to fetch pull request data: %s", + gcli_get_error(g_clictx)); *fetched_pull = 1; } @@ -689,12 +691,14 @@ handle_pull_actions(int argc, char *argv[], /* Commits */ puts("\nCOMMITS"); if (gcli_pull_commits(owner, repo, pr) < 0) - errx(1, "error: failed to fetch pull request checks"); + errx(1, "error: failed to fetch pull request checks: %s", + gcli_get_error(g_clictx)); /* Checks */ puts("\nCHECKS"); if (gcli_pull_checks(owner, repo, pr) < 0) - errx(1, "error: failed to fetch pull request checks"); + errx(1, "error: failed to fetch pull request checks: %s", + gcli_get_error(g_clictx)); } else if (strcmp(action, "op") == 0) { @@ -730,7 +734,8 @@ handle_pull_actions(int argc, char *argv[], } else if (strcmp(action, "ci") == 0) { if (gcli_pull_checks(owner, repo, pr) < 0) - errx(1, "error: failed to fetch pull request checks"); + errx(1, "error: failed to fetch pull request checks: %s", + gcli_get_error(g_clictx)); } else if (strcmp(action, "merge") == 0) { enum gcli_merge_flags flags = GCLI_PULL_MERGE_DELETEHEAD; @@ -755,22 +760,26 @@ handle_pull_actions(int argc, char *argv[], } if (gcli_pull_merge(g_clictx, owner, repo, pr, flags) < 0) - errx(1, "error: failed to merge pull request"); + errx(1, "error: failed to merge pull request: %s", + gcli_get_error(g_clictx)); } else if (strcmp(action, "close") == 0) { if (gcli_pull_close(g_clictx, owner, repo, pr) < 0) - errx(1, "error: failed to close pull request"); + errx(1, "error: failed to close pull request: %s", + gcli_get_error(g_clictx)); } else if (strcmp(action, "reopen") == 0) { if (gcli_pull_reopen(g_clictx, owner, repo, pr) < 0) - errx(1, "error: failed to reopen pull request"); + errx(1, "error: failed to reopen pull request: %s", + gcli_get_error(g_clictx)); } else if (strcmp(action, "reviews") == 0) { /* list reviews */ gcli_pr_review_list reviews = {0}; if (gcli_review_get_reviews(g_clictx, owner, repo, pr, &reviews) < 0) - errx(1, "error: failed to fetch reviews"); + errx(1, "error: failed to fetch reviews: %s", + gcli_get_error(g_clictx)); gcli_review_print_review_table(g_clictx, &reviews); gcli_review_reviews_free(&reviews); @@ -798,7 +807,8 @@ handle_pull_actions(int argc, char *argv[], g_clictx, owner, repo, pr, add_labels, add_labels_size); if (rc < 0) - errx(1, "failed to add labels"); + errx(1, "error: failed to add labels: %s", + gcli_get_error(g_clictx)); } if (remove_labels_size) { rc = gcli_pull_remove_labels( @@ -806,7 +816,8 @@ handle_pull_actions(int argc, char *argv[], remove_labels_size); if (rc < 0) - errx(1, "failed to remove labels"); + errx(1, "error: failed to remove labels: %s", + gcli_get_error(g_clictx)); } free(add_labels); @@ -817,7 +828,8 @@ handle_pull_actions(int argc, char *argv[], if (strcmp(arg, "-d") == 0) { if (gcli_pull_clear_milestone(g_clictx, owner, repo, pr) < 0) - errx(1, "failed to clear milestone"); + errx(1, "error: failed to clear milestone: %s", + gcli_get_error(g_clictx)); } else { int milestone_id = 0; @@ -833,7 +845,8 @@ handle_pull_actions(int argc, char *argv[], rc = gcli_pull_set_milestone(g_clictx, owner, repo, pr, milestone_id); if (rc < 0) - errx(1, "error: failed to set milestone"); + errx(1, "error: failed to set milestone: %s", + gcli_get_error(g_clictx)); } } else { /* At this point we found an unknown action / stray diff --git a/src/cmd/releases.c b/src/cmd/releases.c index 952ec8cb..84197fb9 100644 --- a/src/cmd/releases.c +++ b/src/cmd/releases.c @@ -316,7 +316,7 @@ subcommand_releases_create(int argc, char *argv[]) errx(1, "Aborted by user"); if (gcli_create_release(g_clictx, &release) < 0) - errx(1, "failed to create release"); + errx(1, "failed to create release: %s", gcli_get_error(g_clictx)); return EXIT_SUCCESS; } @@ -379,7 +379,7 @@ subcommand_releases_delete(int argc, char *argv[]) errx(1, "Aborted by user"); if (gcli_delete_release(g_clictx, owner, repo, argv[0]) < 0) - errx(1, "failed to delete the release"); + errx(1, "failed to delete the release: %s", gcli_get_error(g_clictx)); return EXIT_SUCCESS; } @@ -479,7 +479,7 @@ subcommand_releases(int argc, char *argv[]) check_owner_and_repo(&owner, &repo); if (gcli_get_releases(g_clictx, owner, repo, count, &releases) < 0) - errx(1, "error: could not get releases"); + errx(1, "error: could not get releases: %s", gcli_get_error(g_clictx)); gcli_releases_print(flags, &releases, count); diff --git a/src/cmd/repos.c b/src/cmd/repos.c index 4a4fd8f0..a224f772 100644 --- a/src/cmd/repos.c +++ b/src/cmd/repos.c @@ -178,7 +178,7 @@ subcommand_repos_create(int argc, char *argv[]) } if (gcli_repo_create(g_clictx, &create_options, &repo) < 0) - errx(1, "error: failed to create repository"); + errx(1, "error: failed to create repository: %s", gcli_get_error(g_clictx)); gcli_repo_print(&repo); gcli_repo_free(&repo); @@ -275,7 +275,7 @@ subcommand_repos(int argc, char *argv[]) rc = gcli_get_repos(g_clictx, owner, n, &repos); if (rc < 0) - errx(1, "error: failed to fetch repos"); + errx(1, "error: failed to fetch repos: %s", gcli_get_error(g_clictx)); gcli_print_repos(flags, &repos, n); gcli_repos_free(&repos); diff --git a/src/cmd/snippets.c b/src/cmd/snippets.c index 0903ec6a..5195b3d5 100644 --- a/src/cmd/snippets.c +++ b/src/cmd/snippets.c @@ -207,7 +207,8 @@ subcommand_snippet_delete(int argc, char *argv[]) } if (gcli_snippet_delete(g_clictx, snippet_id) < 0) - errx(1, "error: failed to delete snippet"); + errx(1, "error: failed to delete snippet: %s", + gcli_get_error(g_clictx)); return EXIT_SUCCESS; } @@ -281,7 +282,8 @@ subcommand_snippets(int argc, char *argv[]) argv += optind; if (gcli_snippets_get(g_clictx, count, &list) < 0) - errx(1, "error: failed to fetch snippets"); + errx(1, "error: failed to fetch snippets: %s", + gcli_get_error(g_clictx)); gcli_snippets_print(flags, &list, count); gcli_snippets_free(&list); diff --git a/src/cmd/status.c b/src/cmd/status.c index 1fd75ddf..3fc7659e 100644 --- a/src/cmd/status.c +++ b/src/cmd/status.c @@ -140,7 +140,8 @@ subcommand_status(int argc, char *argv[]) } if (gcli_notification_mark_as_read(g_clictx, argv[0]) < 0) - errx(1, "failed to mark the notification as read"); + errx(1, "error: failed to mark the notification as read: %s", + gcli_get_error(g_clictx)); } return EXIT_SUCCESS; From 2500a18a90e6c82540b699909bacfba263996736 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 01:42:02 +0200 Subject: [PATCH 156/236] Make gcli_release_push_asset return error code instead of calling errx --- include/gcli/releases.h | 4 ++-- src/cmd/releases.c | 3 ++- src/releases.c | 8 +++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/gcli/releases.h b/include/gcli/releases.h index f79afd29..0ec64096 100644 --- a/include/gcli/releases.h +++ b/include/gcli/releases.h @@ -94,8 +94,8 @@ void gcli_free_releases(gcli_release_list *); int gcli_create_release(gcli_ctx *ctx, gcli_new_release const *); -void gcli_release_push_asset(gcli_new_release *, - gcli_release_asset_upload); +int gcli_release_push_asset(gcli_ctx *, gcli_new_release *, + gcli_release_asset_upload); int gcli_delete_release(gcli_ctx *ctx, char const *owner, char const *repo, char const *id); diff --git a/src/cmd/releases.c b/src/cmd/releases.c index 84197fb9..10f067eb 100644 --- a/src/cmd/releases.c +++ b/src/cmd/releases.c @@ -286,7 +286,8 @@ subcommand_releases_create(int argc, char *argv[]) .name = optarg, .label = "unused", }; - gcli_release_push_asset(&release, asset); + if (gcli_release_push_asset(g_clictx, &release, asset) < 0) + errx(1, "failed to add asset: %s", gcli_get_error(g_clictx)); } break; case 'y': { always_yes = true; diff --git a/src/releases.c b/src/releases.c index 14403f19..be1f0684 100644 --- a/src/releases.c +++ b/src/releases.c @@ -73,14 +73,16 @@ gcli_create_release(gcli_ctx *ctx, gcli_new_release const *release) return gcli_forge(ctx)->create_release(ctx, release); } -void -gcli_release_push_asset(gcli_new_release *const release, +int +gcli_release_push_asset(gcli_ctx *ctx, gcli_new_release *const release, gcli_release_asset_upload const asset) { if (release->assets_size == GCLI_RELEASE_MAX_ASSETS) - errx(1, "Too many assets"); + return gcli_error(ctx, "too many assets"); release->assets[release->assets_size++] = asset; + + return 0; } int From 5b7a54d222adc78fc606388ea56e3ca157c6d939 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 01:44:45 +0200 Subject: [PATCH 157/236] Reformat the gcli_releases struct --- include/gcli/releases.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/gcli/releases.h b/include/gcli/releases.h index 0ec64096..160428c8 100644 --- a/include/gcli/releases.h +++ b/include/gcli/releases.h @@ -75,16 +75,16 @@ struct gcli_release_asset_upload { #define GCLI_RELEASE_MAX_ASSETS 16 struct gcli_new_release { - char const *owner; - char const *repo; - char const *tag; - char const *name; - sn_sv body; - char const *commitish; - bool draft; - bool prerelease; - gcli_release_asset_upload assets[GCLI_RELEASE_MAX_ASSETS]; - size_t assets_size; + char const *owner; + char const *repo; + char const *tag; + char const *name; + sn_sv body; + char const *commitish; + bool draft; + bool prerelease; + gcli_release_asset_upload assets[GCLI_RELEASE_MAX_ASSETS]; + size_t assets_size; }; int gcli_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, From 03ba6bc1396b9003321e33c086aeab77c3f8951c Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 01:44:56 +0200 Subject: [PATCH 158/236] Update todo.org --- todo.org | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/todo.org b/todo.org index 5dc4ed9a..65546d88 100644 --- a/todo.org +++ b/todo.org @@ -125,8 +125,8 @@ * Big refactor for libraryfication ** TODO Fix test suite - [ ] Add support for a testing gcli context -** TODO Check errx calls if they print "error: " -** TODO Check for calls to errx in submit routines +** DONE Check errx calls if they print "error: " +** DONE Check for calls to errx in submit routines ** TODO [[file:src/github/review.c::github_review_get_reviews(char const *owner)][github_review_get_reviews]] is garbage ** TODO Clean up the generic comments code ** DONE Move printing routines to cmd code @@ -135,5 +135,5 @@ - [X] Put it into the context - [ ] Clean up handle on exit ** TODO Return errors from parsers -** TODO [[file:src/releases.c::gcli_release_push_asset(gcli_new_release *const release,][push_asset]] should not call errx but return an error code +** DONE [[file:src/releases.c::gcli_release_push_asset(gcli_new_release *const release,][push_asset]] should not call errx but return an error code ** DONE Make [[file:src/pulls.c::gcli_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner,][getting a pull diff]] return an error code From 97b67007dfbec522b18612d31575b79d86b0c4a0 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 16:54:00 +0200 Subject: [PATCH 159/236] (#194) Make gcli_get_gist return gist through out paramater This way we do not allocate the gist inside the library code and can put the result on the stack instead. Fixes #194 --- include/gcli/github/gists.h | 3 ++- src/cmd/gists.c | 21 ++++++++------- src/github/gists.c | 51 ++++++++++++++++++++----------------- 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/include/gcli/github/gists.h b/include/gcli/github/gists.h index 3ee4e60c..20978ef3 100644 --- a/include/gcli/github/gists.h +++ b/include/gcli/github/gists.h @@ -77,13 +77,14 @@ struct gcli_new_gist { int gcli_get_gists(gcli_ctx *ctx, char const *user, int max, gcli_gist_list *list); -gcli_gist *gcli_get_gist(gcli_ctx *ctx, char const *gist_id); +int gcli_get_gist(gcli_ctx *ctx, char const *gist_id, gcli_gist *out); int gcli_create_gist(gcli_ctx *ctx, gcli_new_gist); int gcli_delete_gist(gcli_ctx *ctx, char const *gist_id); void gcli_gists_free(gcli_gist_list *list); +void gcli_gist_free(gcli_gist *g); /** * NOTE(Nico): Because of idiots designing a web API, we get a list of diff --git a/src/cmd/gists.c b/src/cmd/gists.c index 18714605..07da14f9 100644 --- a/src/cmd/gists.c +++ b/src/cmd/gists.c @@ -211,21 +211,22 @@ subcommand_gist_get(int argc, char *argv[]) char const *gist_id = shift(&argc, &argv); char const *file_name = shift(&argc, &argv); - gcli_gist *gist = NULL; + gcli_gist gist = {0}; gcli_gist_file *file = NULL; - gist = gcli_get_gist(g_clictx, gist_id); + if (gcli_get_gist(g_clictx, gist_id, &gist) < 0) + errx(1, "error: failed to get gist: %s", gcli_get_error(g_clictx)); - for (size_t f = 0; f < gist->files_size; ++f) { - if (sn_sv_eq_to(gist->files[f].filename, file_name)) { - file = &gist->files[f]; - goto file_found; + for (size_t f = 0; f < gist.files_size; ++f) { + if (sn_sv_eq_to(gist.files[f].filename, file_name)) { + file = &gist.files[f]; + break; } } - errx(1, "gists get: %s: no such file in gist with id %s", file_name, gist_id); - -file_found: + if (!file) + errx(1, "error: gists get: %s: no such file in gist with id %s", + file_name, gist_id); if (isatty(STDOUT_FILENO) && (file->size >= 4 * 1024 * 1024)) errx(1, "error: File is bigger than 4 MiB, refusing to print to stdout."); @@ -233,6 +234,8 @@ subcommand_gist_get(int argc, char *argv[]) if (gcli_curl(g_clictx, stdout, file->url.data, file->type.data) < 0) errx(1, "error: failed to fetch gist: %s", gcli_get_error(g_clictx)); + gcli_gist_free(&gist); + return EXIT_SUCCESS; } diff --git a/src/github/gists.c b/src/github/gists.c index 92909c70..cc69e823 100644 --- a/src/github/gists.c +++ b/src/github/gists.c @@ -88,12 +88,11 @@ gcli_get_gists(gcli_ctx *ctx, char const *user, int const max, return gcli_fetch_list(ctx, url, &fl); } -gcli_gist * -gcli_get_gist(gcli_ctx *ctx, char const *gist_id) +int +gcli_get_gist(gcli_ctx *ctx, char const *gist_id, gcli_gist *out) { char *url = NULL; gcli_fetch_buffer buffer = {0}; - gcli_gist *it = NULL; int rc = 0; url = sn_asprintf("%s/gists/%s", github_get_apibase(ctx), gist_id); @@ -105,8 +104,7 @@ gcli_get_gist(gcli_ctx *ctx, char const *gist_id) json_open_buffer(&stream, buffer.data, buffer.length); json_set_streaming(&stream, 1); - it = calloc(sizeof(gcli_gist), 1); - parse_github_gist(ctx, &stream, it); + parse_github_gist(ctx, &stream, out); json_close(&stream); } @@ -114,7 +112,7 @@ gcli_get_gist(gcli_ctx *ctx, char const *gist_id) free(buffer.data); free(url); - return it; + return rc; } #define READ_SZ 4096 @@ -207,26 +205,33 @@ gcli_delete_gist(gcli_ctx *ctx, char const *gist_id) } void -gcli_gists_free(gcli_gist_list *const list) +gcli_gist_free(gcli_gist *g) { - for (size_t i = 0; i < list->gists_size; ++i) { - free(list->gists[i].id.data); - free(list->gists[i].owner.data); - free(list->gists[i].url.data); - free(list->gists[i].date.data); - free(list->gists[i].git_pull_url.data); - free(list->gists[i].description.data); - - for (size_t j = 0; j < list->gists[i].files_size; ++j) { - free(list->gists[i].files[j].filename.data); - free(list->gists[i].files[j].language.data); - free(list->gists[i].files[j].url.data); - free(list->gists[i].files[j].type.data); - } - - free(list->gists[i].files); + free(g->id.data); + free(g->owner.data); + free(g->url.data); + free(g->date.data); + free(g->git_pull_url.data); + free(g->description.data); + + for (size_t j = 0; j < g->files_size; ++j) { + free(g->files[j].filename.data); + free(g->files[j].language.data); + free(g->files[j].url.data); + free(g->files[j].type.data); } + free(g->files); + + memset(g, 0, sizeof(*g)); +} + +void +gcli_gists_free(gcli_gist_list *const list) +{ + for (size_t i = 0; i < list->gists_size; ++i) + gcli_gist_free(&list->gists[i]); + free(list->gists); list->gists = NULL; From 91c94af642ff782dd2c94b7007a78b8332081dfb Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 17:01:00 +0200 Subject: [PATCH 160/236] Update todo.org --- todo.org | 2 ++ 1 file changed, 2 insertions(+) diff --git a/todo.org b/todo.org index 65546d88..8ac5b697 100644 --- a/todo.org +++ b/todo.org @@ -137,3 +137,5 @@ ** TODO Return errors from parsers ** DONE [[file:src/releases.c::gcli_release_push_asset(gcli_new_release *const release,][push_asset]] should not call errx but return an error code ** DONE Make [[file:src/pulls.c::gcli_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner,][getting a pull diff]] return an error code +** TODO Add a real changelog file +** TODO include [[file:docs/pgen.org][docs/pgen.org]] in the distribution tarball From 7405a49b37ca1d1d37315727c6f5ab9b37f87127 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 22:42:53 +0200 Subject: [PATCH 161/236] Make parsers return error codes This is one of the last few steps of making gcli more library friendly. All the generated parsers now return error codes in case they stumble on a case where they cannot continue. This also replaces the error message parsers by generated parsers such that we can remove the ugly mess that these parser were previously. Signed-off-by: Nico Sonack --- Makefile.am | 2 + include/gcli/comments.h | 6 +- include/gcli/forks.h | 2 +- include/gcli/github/checks.h | 2 +- include/gcli/github/gists.h | 28 +-- include/gcli/gitlab/pipelines.h | 2 +- include/gcli/json_util.h | 102 +++++++---- include/gcli/milestones.h | 3 +- src/cmd/api.c | 6 +- src/github/api.c | 34 ++-- src/github/gists.c | 11 +- src/github/review.c | 145 ++++++++++----- src/gitlab/api.c | 38 ++-- src/gitlab/issues.c | 11 +- src/json_util.c | 308 +++++++++++++++++++------------- src/pgen/dump_c.c | 75 +++++--- src/pgen/dump_h.c | 4 +- templates/github/api.t | 1 + templates/github/gists.t | 2 +- templates/github/labels.t | 2 +- templates/gitlab/api.t | 1 + templates/gitlab/labels.t | 2 +- templates/gitlab/pipelines.t | 4 +- todo.org | 5 +- 24 files changed, 478 insertions(+), 318 deletions(-) create mode 100644 templates/github/api.t create mode 100644 templates/gitlab/api.t diff --git a/Makefile.am b/Makefile.am index 251ecd64..5bc87e90 100644 --- a/Makefile.am +++ b/Makefile.am @@ -87,6 +87,7 @@ libpdjson_la_SOURCES = \ thirdparty/pdjson/pdjson.h TEMPLATES = \ + templates/github/api.t \ templates/github/checks.t \ templates/github/comments.t \ templates/github/forks.t \ @@ -98,6 +99,7 @@ TEMPLATES = \ templates/github/repos.t \ templates/github/status.t \ templates/github/milestones.t \ + templates/gitlab/api.t \ templates/gitlab/comments.t \ templates/gitlab/forks.t \ templates/gitlab/issues.t \ diff --git a/include/gcli/comments.h b/include/gcli/comments.h index 72b08a6d..c38850e9 100644 --- a/include/gcli/comments.h +++ b/include/gcli/comments.h @@ -46,10 +46,10 @@ typedef struct gcli_comment_list gcli_comment_list; typedef struct gcli_submit_comment_opts gcli_submit_comment_opts; struct gcli_comment { - char const *author; /* Login name of the comment author */ - char const *date; /* Creation date of the comment */ + char *author; /* Login name of the comment author */ + char *date; /* Creation date of the comment */ int id; /* id of the comment */ - char const *body; /* Raw text of the comment */ + char *body; /* Raw text of the comment */ }; struct gcli_comment_list { diff --git a/include/gcli/forks.h b/include/gcli/forks.h index b913faa9..927ff78f 100644 --- a/include/gcli/forks.h +++ b/include/gcli/forks.h @@ -44,7 +44,7 @@ struct gcli_fork { sn_sv full_name; sn_sv owner; sn_sv date; - int forks; + int forks; }; struct gcli_fork_list { diff --git a/include/gcli/github/checks.h b/include/gcli/github/checks.h index e9778291..65cc5773 100644 --- a/include/gcli/github/checks.h +++ b/include/gcli/github/checks.h @@ -47,7 +47,7 @@ struct gcli_github_check { char *conclusion; char *started_at; char *completed_at; - long id; + int id; }; struct github_check_list { diff --git a/include/gcli/github/gists.h b/include/gcli/github/gists.h index 20978ef3..ddcc99c5 100644 --- a/include/gcli/github/gists.h +++ b/include/gcli/github/gists.h @@ -45,10 +45,10 @@ typedef struct gcli_gist_file gcli_gist_file; typedef struct gcli_new_gist gcli_new_gist; struct gcli_gist_file { - sn_sv filename; - sn_sv language; - sn_sv url; - sn_sv type; + sn_sv filename; + sn_sv language; + sn_sv url; + sn_sv type; size_t size; }; @@ -58,18 +58,18 @@ struct gcli_gist_list { }; struct gcli_gist { - sn_sv id; - sn_sv owner; - sn_sv url; - sn_sv date; - sn_sv git_pull_url; - sn_sv description; + sn_sv id; + sn_sv owner; + sn_sv url; + sn_sv date; + sn_sv git_pull_url; + sn_sv description; gcli_gist_file *files; - size_t files_size; + size_t files_size; }; struct gcli_new_gist { - FILE *file; + FILE *file; char const *file_name; char const *gist_description; }; @@ -92,7 +92,7 @@ void gcli_gist_free(gcli_gist *g); * file names. The objects describing the files obviously contain the * file name again. Whatever...here's a hack. Blame GitHub. */ -void parse_github_gist_files_idiot_hack(gcli_ctx *ctx, json_stream *stream, - gcli_gist *gist); +int parse_github_gist_files_idiot_hack(gcli_ctx *ctx, json_stream *stream, + gcli_gist *gist); #endif /* GCLI_GITHUB_GISTS_H */ diff --git a/include/gcli/gitlab/pipelines.h b/include/gcli/gitlab/pipelines.h index 9bef2e5d..1ca62cd9 100644 --- a/include/gcli/gitlab/pipelines.h +++ b/include/gcli/gitlab/pipelines.h @@ -42,7 +42,7 @@ typedef struct gitlab_job gitlab_job; typedef struct gitlab_job_list gitlab_job_list; struct gitlab_pipeline { - long id; + long id; char *status; char *created_at; char *updated_at; diff --git a/include/gcli/json_util.h b/include/gcli/json_util.h index 44930d9a..edbeb477 100644 --- a/include/gcli/json_util.h +++ b/include/gcli/json_util.h @@ -42,48 +42,59 @@ #include -#define get_int(ctx, input) get_int_(ctx, input, __func__) -#define get_double(ctx, input) get_double_(ctx, input, __func__) -#define get_parse_int(ctx, input) get_parse_int_(ctx, input, __func__) -#define get_bool(ctx, input) get_bool_(ctx, input, __func__) -#define get_string(ctx, input) get_string_(ctx, input, __func__) -#define get_sv(ctx, input) get_sv_(ctx, input, __func__) -#define get_user(ctx, input) get_user_(ctx, input, __func__) -#define get_label(ctx, input) get_label_(ctx, input, __func__) -#define get_is_string(ctx, input) ((void)ctx, json_next(input) == JSON_STRING) -#define get_int_to_sv(ctx, input) (sn_sv_fmt("%ld", get_int(ctx, input))) -#define get_int_to_string(ctx, input) (sn_asprintf("%ld", get_int(ctx, input))) - -long get_int_(gcli_ctx *ctx, json_stream *input, char const *function); -double get_double_(gcli_ctx *ctx, json_stream *input, char const *function); -long get_parse_int_(gcli_ctx *ctx, json_stream *input, - char const *function); -bool get_bool_(gcli_ctx *ctx, json_stream *input, char const *function); -char *get_string_(gcli_ctx *ctx, json_stream *input, char const *function); -sn_sv get_sv_(gcli_ctx *ctx, json_stream *input, char const *function); -char *get_user_(gcli_ctx *ctx, json_stream *input, char const *function); -char const *get_label_(json_stream *input, char const *function); -sn_sv gcli_json_escape(sn_sv); +#define get_int(ctx, input, out) get_int_(ctx, input, out, __func__) +#define get_long(ctx, input, out) get_long_(ctx, input, out, __func__) +#define get_size_t(ctx, input, out) get_size_t_(ctx, input, out, __func__) +#define get_double(ctx, input, out) get_double_(ctx, input, out, __func__) +#define get_parse_int(ctx, input, out) get_parse_int_(ctx, input, out, __func__) +#define get_bool(ctx, input, out) get_bool_(ctx, input, out, __func__) +#define get_string(ctx, input, out) get_string_(ctx, input, out, __func__) +#define get_sv(ctx, input, out) get_sv_(ctx, input, out, __func__) +#define get_user(ctx, input, out) get_user_(ctx, input, out, __func__) +#define get_label(ctx, input, out) get_label_(ctx, input, out, __func__) +#define get_is_string(ctx, input, out) ((void)ctx, (*out = json_next(input) == JSON_STRING), 1) +#define get_int_to_sv(ctx, input, out) get_int_to_sv_(ctx, input, out, __func__) +#define get_int_to_string(ctx, input, out) get_int_to_string_(ctx, input, out, __func__) + +int get_int_(gcli_ctx *ctx, json_stream *input, int *out, char const *function); +int get_long_(gcli_ctx *ctx, json_stream *input, long *out, char const *function); +int get_size_t_(gcli_ctx *ctx, json_stream *input, size_t *out, char const *function); +int get_double_(gcli_ctx *ctx, json_stream *input, double *out, char const *function); +int get_parse_int_(gcli_ctx *ctx, json_stream *input, long *out, char const *function); +int get_bool_(gcli_ctx *ctx, json_stream *input, bool *out, char const *function); +int get_string_(gcli_ctx *ctx, json_stream *input, char **out, char const *function); +int get_sv_(gcli_ctx *ctx, json_stream *input, sn_sv *out, char const *function); +int get_user_(gcli_ctx *ctx, json_stream *input, char **out, char const *function); +int get_label_(gcli_ctx *ctx, json_stream *input, char const **out, char const *function); +int get_github_style_colour(gcli_ctx *ctx, json_stream *input, uint32_t *out); +int get_gitlab_style_colour(gcli_ctx *ctx, json_stream *input, uint32_t *out); +int get_github_is_pr(gcli_ctx *ctx, json_stream *input, int *out); +int get_gitlab_can_be_merged(gcli_ctx *ctx, json_stream *input, bool *out); +int get_gitea_visibility(gcli_ctx *ctx, json_stream *input, sn_sv *out); +int get_int_to_sv_(gcli_ctx *ctx, json_stream *input, sn_sv *out, + char const *function); +sn_sv gcli_json_escape(sn_sv); #define gcli_json_escape_cstr(x) (gcli_json_escape(SV((char *)(x))).data) void gcli_print_html_url(gcli_ctx *, gcli_fetch_buffer); -void gcli_json_advance(json_stream *input, char const *fmt, ...); -uint32_t get_github_style_colour(gcli_ctx *ctx, json_stream *input); -uint32_t get_gitlab_style_colour(gcli_ctx *ctx, json_stream *input); -int get_github_is_pr(gcli_ctx *ctx, json_stream *input); -bool get_gitlab_can_be_merged(gcli_ctx *ctx, json_stream *input); -sn_sv get_gitea_visibility(gcli_ctx *ctx, json_stream *input); - -static inline sn_sv -get_user_sv(gcli_ctx *ctx, json_stream *input) +int gcli_json_advance(gcli_ctx *ctx, json_stream *input, char const *fmt, ...); + +static inline int +get_user_sv(gcli_ctx *ctx, json_stream *input, sn_sv *out) { - char *user_str = (char *)get_user(ctx, input); - return SV(user_str); + char *user_str; + int rc = get_user(ctx, input, &user_str); + if (rc < 0) + return rc; + + *out = SV(user_str); + + return 0; } -static inline void +static inline int parse_user(gcli_ctx *ctx, json_stream *input, sn_sv *out) { - *out = get_user_sv(ctx, input); + return get_user_sv(ctx, input, out); } static inline char const * @@ -92,6 +103,22 @@ gcli_json_bool(bool it) return it ? "true" : "false"; } +static inline int +get_int_to_string_(gcli_ctx *ctx, json_stream *input, char **out, + char const *const fn) +{ + int rc; + long val; + + rc = get_long_(ctx, input, &val, fn); + if (rc < 0) + return rc; + + *out = sn_asprintf("%ld", val); + + return 0; +} + #define SKIP_OBJECT_VALUE(stream) \ do { \ enum json_type value_type = json_next(stream); \ @@ -108,11 +135,10 @@ gcli_json_bool(bool it) } \ } while (0) -static inline void +static inline int parse_sv(gcli_ctx *ctx, json_stream *stream, sn_sv *out) { - (void) ctx; - *out = get_sv(ctx, stream); + return get_sv(ctx, stream, out); } #endif /* JSON_UTIL_H */ diff --git a/include/gcli/milestones.h b/include/gcli/milestones.h index 55ae3c01..298b95af 100644 --- a/include/gcli/milestones.h +++ b/include/gcli/milestones.h @@ -34,6 +34,7 @@ #include #endif +#include #include #include @@ -52,7 +53,7 @@ struct gcli_milestone { char *description; char *updated_at; char *due_date; - int expired; + bool expired; /* Github and Gitea Specific */ int open_issues; diff --git a/src/cmd/api.c b/src/cmd/api.c index d1606522..802f1b8c 100644 --- a/src/cmd/api.c +++ b/src/cmd/api.c @@ -65,7 +65,8 @@ fetch_all(char *_url) gcli_fetch_buffer buffer = {0}; if (gcli_fetch(g_clictx, url, &next_url, &buffer) < 0) - errx(1, "error: failed to fetch data"); + errx(1, "error: failed to fetch data: %s", + gcli_get_error(g_clictx)); fwrite(buffer.data, buffer.length, 1, stdout); @@ -119,7 +120,8 @@ subcommand_api(int argc, char *argv[]) if (do_all) fetch_all(url); else if (gcli_curl(g_clictx, stdout, url, "application/json") < 0) - errx(1, "error: failed to fetch data"); + errx(1, "error: failed to fetch data: %s", + gcli_get_error(g_clictx)); free(url); diff --git a/src/github/api.c b/src/github/api.c index 82a49e24..251e3d0d 100644 --- a/src/github/api.c +++ b/src/github/api.c @@ -30,27 +30,23 @@ #include #include +#include + #include char const * -github_api_error_string(gcli_ctx *ctx, gcli_fetch_buffer *const it) +github_api_error_string(gcli_ctx *ctx, gcli_fetch_buffer *const buf) { - struct json_stream stream = {0}; - enum json_type next = JSON_NULL; - - if (!it->length) - return NULL; - - json_open_buffer(&stream, it->data, it->length); - json_set_streaming(&stream, true); - - while ((next = json_next(&stream)) != JSON_OBJECT_END) { - char *key = get_string(ctx, &stream); - if (strcmp(key, "message") == 0) - return get_string(ctx, &stream); - - free(key); - } - - return ""; + json_stream stream = {0}; + int rc; + char *msg; + + json_open_buffer(&stream, buf->data, buf->length); + rc = parse_github_get_error(ctx, &stream, &msg); + json_close(&stream); + + if (rc < 0) + return strdup("no message: failed to parser error response"); + else + return msg; } diff --git a/src/github/gists.c b/src/github/gists.c index cc69e823..aa49950b 100644 --- a/src/github/gists.c +++ b/src/github/gists.c @@ -41,7 +41,7 @@ #include /* /!\ Before changing this, see comment in gists.h /!\ */ -void +int parse_github_gist_files_idiot_hack(gcli_ctx *ctx, json_stream *stream, gcli_gist *const gist) { @@ -53,16 +53,19 @@ parse_github_gist_files_idiot_hack(gcli_ctx *ctx, json_stream *stream, gist->files_size = 0; if ((next = json_next(stream)) != JSON_OBJECT) - errx(1, "Expected Gist Files Object"); + return gcli_error(ctx, "expected Gist Files Object"); while ((next = json_next(stream)) == JSON_STRING) { gist->files = realloc(gist->files, sizeof(*gist->files) * (gist->files_size + 1)); gcli_gist_file *it = &gist->files[gist->files_size++]; - parse_github_gist_file(ctx, stream, it); + if (parse_github_gist_file(ctx, stream, it) < 0) + return -1; } if (next != JSON_OBJECT_END) - errx(1, "Unclosed Gist Files Object"); + return gcli_error(ctx, "unclosed Gist Files Object"); + + return 0; } int diff --git a/src/github/review.c b/src/github/review.c index 6f68242a..68bd1994 100644 --- a/src/github/review.c +++ b/src/github/review.c @@ -33,80 +33,118 @@ #include -static void +static int github_parse_review_comment(gcli_ctx *ctx, json_stream *input, gcli_pr_review_comment *it) { if (json_next(input) != JSON_OBJECT) - errx(1, "Expected review comment object"); + return gcli_error(ctx, "%s: expected review comment object", + __func__); enum json_type key_type; while ((key_type = json_next(input)) == JSON_STRING) { - size_t len = 0; + size_t len = 0; char const *key = json_get_string(input, &len); - if (strncmp("bodyText", key, len) == 0) - it->body = get_string(ctx, input); - else if (strncmp("id", key, len) == 0) - it->id = get_string(ctx, input); - else if (strncmp("createdAt", key, len) == 0) - it->date = get_string(ctx, input); - else if (strncmp("author", key, len) == 0) - it->author = get_user(ctx, input); - else if (strncmp("diffHunk", key, len) == 0) - it->diff = get_string(ctx, input); - else if (strncmp("path", key, len) == 0) - it->path = get_string(ctx, input); - else if (strncmp("originalPosition", key, len) == 0) - it->original_position = get_int(ctx, input); - else + if (strncmp("bodyText", key, len) == 0) { + if (get_string(ctx, input, &it->body) < 0) + return -1; + + } else if (strncmp("id", key, len) == 0) { + if (get_string(ctx, input, &it->id) < 0) + return -1; + + } else if (strncmp("createdAt", key, len) == 0) { + if (get_string(ctx, input, &it->date) < 0) + return -1; + + } else if (strncmp("author", key, len) == 0) { + if (get_user(ctx, input, &it->author) < 0) + return -1; + + } else if (strncmp("diffHunk", key, len) == 0) { + if (get_string(ctx, input, &it->diff) < 0) + return -1; + + } else if (strncmp("path", key, len) == 0) { + if (get_string(ctx, input, &it->path) < 0) + return -1; + + } else if (strncmp("originalPosition", key, len) == 0) { + if (get_int(ctx, input, &it->original_position) < 0) + return -1; + + } else { SKIP_OBJECT_VALUE(input); + } } + + return 0; } -static void +static int github_parse_review_comments(gcli_ctx *ctx, json_stream *input, gcli_pr_review *it) { - gcli_json_advance(input, "{s[", "nodes"); + if (gcli_json_advance(ctx, input, "{s[", "nodes") < 0) + return -1; + while (json_peek(input) == JSON_OBJECT) { it->comments = realloc( it->comments, sizeof(*it->comments) * (it->comments_size + 1)); gcli_pr_review_comment *comment = &it->comments[it->comments_size++]; *comment = (gcli_pr_review_comment) {0}; - github_parse_review_comment(ctx, input, comment); + + if (github_parse_review_comment(ctx, input, comment) < 0) + return -1; } - gcli_json_advance(input, "]}"); + + if (gcli_json_advance(ctx, input, "]}") < 0) + return -1; + + return 0; } -static void +static int github_parse_review_header(gcli_ctx *ctx, json_stream *input, gcli_pr_review *it) { if (json_next(input) != JSON_OBJECT) - errx(1, "Expected review object"); + return gcli_error(ctx, "%s: expected an object", __func__); enum json_type key_type; while ((key_type = json_next(input)) == JSON_STRING) { size_t len = 0; char const *key = json_get_string(input, &len); - if (strncmp("bodyText", key, len) == 0) - it->body = get_string(ctx, input); - else if (strncmp("state", key, len) == 0) - it->state = get_string(ctx, input); - else if (strncmp("id", key, len) == 0) - it->id = get_string(ctx, input); - else if (strncmp("createdAt", key, len) == 0) - it->date = get_string(ctx, input); - else if (strncmp("author", key, len) == 0) - it->author = get_user(ctx, input); - else if (strncmp("comments", key, len) == 0) - github_parse_review_comments(ctx, input, it); - else + if (strncmp("bodyText", key, len) == 0) { + if (get_string(ctx, input, &it->body) < 0) + return -1; + + } else if (strncmp("state", key, len) == 0) { + if (get_string(ctx, input, &it->state) < 0) + return -1; + + } else if (strncmp("id", key, len) == 0) { + if (get_string(ctx, input, &it->id) < 0) + return -1; + + } else if (strncmp("createdAt", key, len) == 0) { + if (get_string(ctx, input, &it->date) < 0) + return -1; + } else if (strncmp("author", key, len) == 0) { + if (get_user(ctx, input, &it->author) < 0) + return -1; + } else if (strncmp("comments", key, len) == 0) { + if (github_parse_review_comments(ctx, input, it) < 0) + return -1; + } else { SKIP_OBJECT_VALUE(input); + } } + + return 0; } static char const *get_reviews_fmt = @@ -168,18 +206,22 @@ github_review_get_reviews(gcli_ctx *ctx, char const *owner, char const *repo, free(post_data); if (rc < 0) - return rc; + goto error_fetch; json_open_buffer(&stream, buffer.data, buffer.length); json_set_streaming(&stream, true); - gcli_json_advance( - &stream, "{s{s{s{s{s", - "data", "repository", "pullRequest", "reviews", "nodes"); + rc = gcli_json_advance(ctx, &stream, "{s{s{s{s{s", + "data", "repository", "pullRequest", + "reviews", "nodes"); + if (rc < 0) + goto error_json; next = json_next(&stream); - if (next != JSON_ARRAY) - errx(1, "error: expected json array for review list"); + if (next != JSON_ARRAY) { + rc = gcli_error(ctx, "expected json array for review list"); + goto error_json; + } while ((next = json_peek(&stream)) == JSON_OBJECT) { out->reviews = realloc(out->reviews, @@ -188,18 +230,25 @@ github_review_get_reviews(gcli_ctx *ctx, char const *owner, char const *repo, *it = (gcli_pr_review) {0}; - github_parse_review_header(ctx, &stream, it); + rc = github_parse_review_header(ctx, &stream, it); + if (rc < 0) + goto error_json; out->reviews_size++; } - if (json_next(&stream) != JSON_ARRAY_END) - errx(1, "error: expected end of json array"); + if (json_next(&stream) != JSON_ARRAY_END) { + rc = gcli_error(ctx, "expected end of json array"); + goto error_json; + } - gcli_json_advance(&stream, "}}}}}"); + rc = gcli_json_advance(ctx, &stream, "}}}}}"); + +error_json: json_close(&stream); +error_fetch: free(buffer.data); - return 0; + return rc; } diff --git a/src/gitlab/api.c b/src/gitlab/api.c index 148dc7de..ffaa8a11 100644 --- a/src/gitlab/api.c +++ b/src/gitlab/api.c @@ -30,35 +30,23 @@ #include #include +#include + #include char const * -gitlab_api_error_string(gcli_ctx *ctx, gcli_fetch_buffer *const it) +gitlab_api_error_string(gcli_ctx *ctx, gcli_fetch_buffer *const buf) { - struct json_stream stream = {0}; - enum json_type next = JSON_NULL; - - if (!it->length) - return NULL; - - json_open_buffer(&stream, it->data, it->length); - json_set_streaming(&stream, true); + char *msg; + int rc; + json_stream stream = {0}; - while ((next = json_next(&stream)) != JSON_OBJECT_END) { - char *key = get_string(ctx, &stream); - if (strcmp(key, "message") == 0) { - if ((next = json_peek(&stream)) == JSON_STRING) - return get_string(ctx, &stream); - else if ((next = json_next(&stream)) == JSON_ARRAY) - return get_string(ctx, &stream); - else if (next == JSON_ARRAY_END) - ; - else - errx(1, "error retrieving error message from GitLab " - "API response"); - } - free(key); - } + json_open_buffer(&stream, buf->data, buf->length); + rc = parse_gitlab_get_error(ctx, &stream, &msg); + json_close(&stream); - return ""; + if (rc < 0) + return strdup("no error message: failed to parse error response"); + else + return msg; } diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index 2670b52a..76c3c4f8 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -219,7 +219,8 @@ gitlab_user_id(gcli_ctx *ctx, char const *user_name) struct json_stream stream = {0}; char *url = NULL; char *e_username; - int uid = -1; + long uid = -1; + int rc; e_username = gcli_urlencode(user_name); @@ -231,10 +232,12 @@ gitlab_user_id(gcli_ctx *ctx, char const *user_name) json_open_buffer(&stream, buffer.data, buffer.length); json_set_streaming(&stream, 1); - gcli_json_advance(&stream, "[{s", "id"); - uid = get_int(ctx, &stream); + uid = rc = gcli_json_advance(ctx, &stream, "[{s", "id"); - json_close(&stream); + if (rc == 0) { + rc = get_long(ctx, &stream, &uid); + json_close(&stream); + } } free(e_username); diff --git a/src/json_util.c b/src/json_util.c index c13737ce..666b4b5d 100644 --- a/src/json_util.c +++ b/src/json_util.c @@ -36,112 +36,122 @@ #include #include -static inline void -barf(char const *message, char const *where) +int +get_int_(gcli_ctx *ctx, json_stream *const input, int *out, char const *where) { - errx(1, - "error: %s.\n" - " This might be an error on the GitHub api or the result of\n" - " incorrect usage of cli flags. See gcli(1) to make sure your\n" - " flags are correct. If you are certain that all your options\n" - " were correct, please submit a bug report including the\n" - " command you invoked and the following information about the\n" - " error location: function = %s", message, where); + if (json_next(input) != JSON_NUMBER) + return gcli_error(ctx, "unexpected non-integer field in %s", where); + + *out = json_get_number(input); + + return 0; } -long -get_int_(gcli_ctx *ctx, json_stream *const input, char const *where) +int +get_long_(gcli_ctx *ctx, json_stream *const input, long *out, char const *where) { - (void) ctx; - if (json_next(input) != JSON_NUMBER) - barf("unexpected non-integer field", where); + return gcli_error(ctx, "unexpected non-integer field in %s", where); + + *out = json_get_number(input); - return json_get_number(input); + return 0; } -double -get_double_(gcli_ctx *ctx, json_stream *const input, char const *where) +int +get_size_t_(gcli_ctx *ctx, json_stream *const input, size_t *out, char const *where) { - (void) ctx; + if (json_next(input) != JSON_NUMBER) + return gcli_error(ctx, "unexpected non-integer field in %s", where); + + *out = json_get_number(input); + return 0; +} + +int +get_double_(gcli_ctx *ctx, json_stream *const input, double *out, char const *where) +{ enum json_type type = json_next(input); /* This is dumb but it fixes a couple of weirdnesses of the API */ - if (type == JSON_NULL) + if (type == JSON_NULL) { + *out = 0; return 0; - if (type == JSON_NUMBER) - return json_get_number(input); + } + + if (type == JSON_NUMBER) { + *out = json_get_number(input); + return 0; + } - barf("unexpected non-double field", where); - return 0; /* NOTREACHED */ + return gcli_error(ctx, "unexpected non-double field in %s", where); } -char * -get_string_(gcli_ctx *ctx, json_stream *const input, char const *where) +int +get_string_(gcli_ctx *ctx, json_stream *const input, char **out, + char const *where) { - (void) ctx; - enum json_type const type = json_next(input); - if (type == JSON_NULL) - return strdup(""); + if (type == JSON_NULL) { + *out = strdup(""); + return 0; + } if (type != JSON_STRING) - barf("unexpected non-string field", where); + return gcli_error(ctx, "unexpected non-string field in %s", where); size_t len; char const *it = json_get_string(input, &len); if (!it) - return strdup(""); + *out = strdup(""); else - return sn_strndup(it, len); + *out = sn_strndup(it, len); + + return 0; } -bool -get_bool_(gcli_ctx *ctx,json_stream *const input, char const *where) +int +get_bool_(gcli_ctx *ctx,json_stream *const input, bool *out, char const *where) { - (void) ctx; - enum json_type value_type = json_next(input); - if (value_type == JSON_TRUE) - return true; - else if (value_type == JSON_FALSE || value_type == JSON_NULL) // HACK - return false; - else - barf("unexpected non-boolean value", where); + if (value_type == JSON_TRUE) { + *out = true; + return 0; + } else if (value_type == JSON_FALSE || value_type == JSON_NULL) { // HACK + *out = false; + return 0; + } - errx(42, "%s: unreachable", where); - return false; + return gcli_error(ctx, "unexpected non-boolean value in %s", where); } -char * -get_user_(gcli_ctx *ctx, json_stream *const input, char const *where) +int +get_user_(gcli_ctx *ctx, json_stream *const input, char **out, + char const *where) { if (json_next(input) != JSON_OBJECT) - barf("user field is not an object", where); + return gcli_error(ctx, "%s: user field is not an object", where); char const *expected_key = gcli_forge(ctx)->user_object_key; - char *result = NULL; while (json_next(input) == JSON_STRING) { - size_t len = 0; + size_t len = 0; char const *key = json_get_string(input, &len); if (strncmp(expected_key, key, len) == 0) { if (json_next(input) != JSON_STRING) - barf( - "login of the pull request creator is not a string", - where); + return gcli_error(ctx, "%s: login isn't a string", where); char const *tmp = json_get_string(input, &len); - result = sn_strndup(tmp, len); + *out = sn_strndup(tmp, len); } else { json_next(input); } } - return result; + return 0; } static struct { @@ -185,22 +195,24 @@ gcli_json_escape(sn_sv const it) return result; } -sn_sv -get_sv_(gcli_ctx *ctx, json_stream *const input, char const *where) +int +get_sv_(gcli_ctx *ctx, json_stream *const input, sn_sv *out, char const *where) { - (void) ctx; - enum json_type type = json_next(input); - if (type == JSON_NULL) - return SV_NULL; + if (type == JSON_NULL) { + *out = SV_NULL; + return 0; + } if (type != JSON_STRING) - barf("unexpected non-string field", where); + return gcli_error(ctx, "unexpected non-string field in %s", where); size_t len; - char const *it = json_get_string(input, &len); - char *copy = sn_strndup(it, len); - return SV(copy); + char const *it = json_get_string(input, &len); + char *copy = sn_strndup(it, len); + *out = SV(copy); + + return 0; } void @@ -219,7 +231,10 @@ gcli_print_html_url(gcli_ctx *ctx, gcli_fetch_buffer const buffer) char const *key = json_get_string(&stream, &len); if (strncmp(key, expected_key, len) == 0) { - char *url = get_string(ctx, &stream); + char *url; + if (get_string(ctx, &stream, &url) < 0) + abort(); + puts(url); free(url); } else { @@ -239,40 +254,40 @@ gcli_print_html_url(gcli_ctx *ctx, gcli_fetch_buffer const buffer) } if (next != JSON_OBJECT_END) - barf("unexpected key type in json object", __func__); + abort(); json_close(&stream); } -char const * -get_label_(json_stream *const input, char const *where) +int +get_label_(gcli_ctx *ctx, json_stream *const input, char const **out, + char const *where) { if (json_next(input) != JSON_OBJECT) - barf("label field is not an object", where); + return gcli_error(ctx, "%s: label field is not an object", where); - char const *result = NULL; while (json_next(input) == JSON_STRING) { - size_t len = 0; + size_t len = 0; char const *key = json_get_string(input, &len); if (strncmp("name", key, len) == 0) { if (json_next(input) != JSON_STRING) - barf("name of the label is not a string", where); + return gcli_error(ctx, "%s: name of the label is not a string", + where); - result = json_get_string(input, &len); - result = sn_strndup(result, len); + *out = json_get_string(input, &len); + *out = sn_strndup(*out, len); } else { json_next(input); } } - return result; + return 0; } - -void -gcli_json_advance(json_stream *const stream, char const *fmt, ...) +int +gcli_json_advance(gcli_ctx *ctx, json_stream *const stream, char const *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -281,118 +296,165 @@ gcli_json_advance(json_stream *const stream, char const *fmt, ...) switch (*fmt++) { case '[': { if (json_next(stream) != JSON_ARRAY) - errx(1, "Expected array begin"); + return gcli_error(ctx, "expected array begin"); } break; case '{': { if (json_next(stream) != JSON_OBJECT) - errx(1, "Expected array begin"); + return gcli_error(ctx, "expected array begin"); } break; case 's': { if (json_next(stream) != JSON_STRING) - errx(1, "Expected string"); + return gcli_error(ctx, "expected string"); - char *it = va_arg(ap, char *); - size_t len = 0; + char *it = va_arg(ap, char *); + size_t len = 0; char const *other = json_get_string(stream, &len); if (strncmp(it, other, len)) - errx(1, "String unmatched"); + return gcli_error(ctx, "string unmatched"); } break; case ']': { if (json_next(stream) != JSON_ARRAY_END) - errx(1, "Expected array end"); + return gcli_error(ctx, "expected array end"); } break; case '}': { if (json_next(stream) != JSON_OBJECT_END) - errx(1, "Expected object end"); + return gcli_error(ctx, "expected object end"); } break; case 'i': { if (json_next(stream) != JSON_NUMBER) - errx(1, "Expected integer"); + return gcli_error(ctx, "expected integer"); } break; } } va_end(ap); + + return 0; } -long -get_parse_int_(gcli_ctx *ctx, json_stream *const input, char const *function) +int +get_parse_int_(gcli_ctx *ctx, json_stream *const input, long *out, + char const *function) { - long result = 0; char *endptr = NULL; - char *string = get_string(ctx, input); + char *string; + + int rc = get_string_(ctx, input, &string, function); + if (rc < 0) + return rc; - result = strtol(string, &endptr, 10); + *out = strtol(string, &endptr, 10); if (endptr != string + strlen(string)) - err(1, "in %s: unable to parse string field into decimal integer", - function); + return gcli_error(ctx, "%s: cannot parse %s as integer", function, + string); - return result; + return 0; } -uint32_t -get_github_style_colour(gcli_ctx *ctx, json_stream *const input) +int +get_github_style_colour(gcli_ctx *ctx, json_stream *const input, uint32_t *out) { - char *colour_str = get_string(ctx, input); + char *colour_str; char *endptr = NULL; + int rc; + + rc = get_string(ctx, input, &colour_str); + if (rc < 0) + return rc; unsigned long colour = strtoul(colour_str, &endptr, 16); if (endptr != colour_str + strlen(colour_str)) - errx(1, "error: the api returned an" - "invalid hexadecimal colour code"); + return gcli_error(ctx, "%s: bad colour code returned by API", + colour_str); free(colour_str); - return ((uint32_t)(colour)) << 8; + *out = ((uint32_t)(colour)) << 8; + return 0; } -uint32_t -get_gitlab_style_colour(gcli_ctx *ctx, json_stream *const input) +int +get_gitlab_style_colour(gcli_ctx *ctx, json_stream *const input, uint32_t *out) { - char *colour = get_string(ctx, input); + char *colour; char *endptr = NULL; long code = 0; + int rc = 0; + + rc = get_string(ctx, input, &colour); + if (rc < 0) + return rc; code = strtol(colour + 1, &endptr, 16); if (endptr != (colour + 1 + strlen(colour + 1))) - err(1, "error: colour code is invalid"); + return gcli_error(ctx, "%s: invalid colour code"); free(colour); - return ((uint32_t)(code) << 8); + *out = ((uint32_t)(code) << 8); + + return 0; } -sn_sv -get_gitea_visibility(gcli_ctx *ctx, json_stream *const input) +int +get_gitea_visibility(gcli_ctx *ctx, json_stream *const input, sn_sv *out) { char *v = NULL; - if (get_bool(ctx, input)) - v = strdup("private"); - else - v = strdup("public"); - return SV(v); + bool is_private; + int rc = get_bool(ctx, input, &is_private); + if (rc < 0) + return rc; + + v = strdup(is_private ? "private" : "public"); + *out = SV(v); + + return 0; } -bool -get_gitlab_can_be_merged(gcli_ctx *ctx, json_stream *const input) +int +get_gitlab_can_be_merged(gcli_ctx *ctx, json_stream *const input, bool *out) { - sn_sv tmp = get_sv(ctx, input); - bool result = sn_sv_eq_to(tmp, "can_be_merged"); + sn_sv tmp; + int rc = 0; + + rc = get_sv(ctx, input, &tmp); + if (rc < 0) + return rc; + + *out = sn_sv_eq_to(tmp, "can_be_merged"); free(tmp.data); - return result; + + return rc; } int -get_github_is_pr(gcli_ctx *ctx, json_stream *input) +get_github_is_pr(gcli_ctx *ctx, json_stream *input, int *out) { - (void) ctx; - enum json_type next = json_peek(input); + (void) ctx; + if (next == JSON_NULL) json_next(input); else SKIP_OBJECT_VALUE(input); - return next == JSON_OBJECT; + *out = (next == JSON_OBJECT); + + return 0; +} + +int +get_int_to_sv_(gcli_ctx *ctx, json_stream *input, sn_sv *out, + char const *function) +{ + int rc, val; + + rc = get_int_(ctx, input, &val, function); + if (rc < 0) + return rc; + + *out = sn_sv_fmt("%d", val); + + return 0; } diff --git a/src/pgen/dump_c.c b/src/pgen/dump_c.c index 25e5bb7b..e296535a 100644 --- a/src/pgen/dump_c.c +++ b/src/pgen/dump_c.c @@ -30,25 +30,27 @@ #include #include +#include static void pregen_array_parser(struct objparser *p, struct objentry *it) { fprintf(outfile, - "static void\n" + "static int\n" "parse_%s_%s_array(gcli_ctx *ctx, struct json_stream *stream, " "%s *out)\n", p->name, it->name, p->returntype); fprintf(outfile, "{\n"); + fprintf(outfile, "\tint rc = 0;\n"); fprintf(outfile, "\tif (json_peek(stream) == JSON_NULL) {\n"); fprintf(outfile, "\t\tjson_next(stream);\n"); fprintf(outfile, "\t\tout->%s = NULL;\n", it->name); fprintf(outfile, "\t\tout->%s_size = 0;\n", it->name); - fprintf(outfile, "\t\treturn;\n"); + fprintf(outfile, "\t\treturn 0;\n"); fprintf(outfile, "\t}\n\n"); fprintf(outfile, "\tif (json_next(stream) != JSON_ARRAY)\n"); - fprintf(outfile, "\t\terrx(1, \"Expected array for %s array in %s\");\n\n", + fprintf(outfile, "\t\treturn gcli_error(ctx, \"expected array for %s array in %s\");\n\n", it->name, p->name); fprintf(outfile, "\twhile (json_peek(stream) != JSON_ARRAY_END) {\n"); @@ -56,11 +58,15 @@ pregen_array_parser(struct objparser *p, struct objentry *it) it->name, it->name, it->name, it->name); fprintf(outfile, "\t\tmemset(&out->%s[out->%s_size], 0, sizeof(out->%s[out->%s_size]));\n", it->name, it->name, it->name, it->name); - fprintf(outfile, "\t\t%s(ctx, stream, &out->%s[out->%s_size++]);\n", + fprintf(outfile, "\t\trc = %s(ctx, stream, &out->%s[out->%s_size++]);\n", it->parser, it->name, it->name); + fprintf(outfile, "\t\tif (rc < 0)\n\t\t\treturn rc;\n"); fprintf(outfile, "\t}\n\n"); - fprintf(outfile, "\tassert(json_next(stream) == JSON_ARRAY_END);\n"); + fprintf(outfile, "\tif (json_next(stream) != JSON_ARRAY_END)\n"); + fprintf(outfile, "\t\treturn gcli_error(ctx, \"unexpected element in array " + "while parsing %s\");\n", p->name); + fprintf(outfile, "\treturn 0;\n"); fprintf(outfile, "}\n\n"); } @@ -82,25 +88,29 @@ objparser_dump_entries(struct objparser *p) for (struct objentry *it = p->entries; it; it = it->next) { - fprintf(outfile, "\t\tif (strncmp(\"%s\", key, len) == 0)\n", + fprintf(outfile, "\t\tif (strncmp(\"%s\", key, len) == 0) {\n", it->jsonname); if (it->kind == OBJENTRY_SIMPLE) { - if (it->parser) - fprintf(outfile, "\t\t\t%s(ctx, stream, &out->%s);\n", + if (it->parser) { + fprintf(outfile, "\t\t\tif (%s(ctx, stream, &out->%s) < 0)\n", it->parser, it->name); - else - fprintf(outfile, "\t\t\tout->%s = get_%s(ctx, stream);\n", it->name, - it->type); + } else { + fprintf(outfile, "\t\t\tif (get_%s(ctx, stream, &out->%s) < 0)\n", + it->type, it->name); + } + fprintf(outfile, "\t\t\t\treturn -1;\n"); } else if (it->kind == OBJENTRY_ARRAY) { - fprintf(outfile, "\t\t\tparse_%s_%s_array(ctx, stream, out);\n", + fprintf(outfile, "\t\t\tif (parse_%s_%s_array(ctx, stream, out) < 0)\n", p->name, it->name); + fprintf(outfile, "\t\t\t\treturn -1;\n"); } else if (it->kind == OBJENTRY_CONTINUATION) { - fprintf(outfile, "\t\t\t%s(ctx, stream, out);\n", it->parser); + fprintf(outfile, "\t\t\tif (%s(ctx, stream, out) < 0)\n", it->parser); + fprintf(outfile, "\t\t\t\treturn -1;\n"); } - fprintf(outfile, "\t\telse "); + fprintf(outfile, "\t\t} else "); } fprintf(outfile, "\n\t\t\tSKIP_OBJECT_VALUE(stream);\n"); @@ -114,9 +124,10 @@ objparser_dump_select(struct objparser *p) fprintf(outfile, "\twhile ((key_type = json_next(stream)) == JSON_STRING) {\n"); fprintf(outfile, "\t\tsize_t len;\n"); fprintf(outfile, "\t\tkey = json_get_string(stream, &len);\n"); - fprintf(outfile, "\t\tif (strncmp(\"%s\", key, len) == 0)\n", p->select.fieldname); - fprintf(outfile, "\t\t\t*out = get_%s(ctx, stream);\n", p->select.fieldtype); - fprintf(outfile, "\t\telse "); + fprintf(outfile, "\t\tif (strncmp(\"%s\", key, len) == 0) {\n", p->select.fieldname); + fprintf(outfile, "\t\t\tif (get_%s(ctx, stream, out) < 0)\n", p->select.fieldtype); + fprintf(outfile, "\t\t\t\treturn -1;\n"); + fprintf(outfile, "\t\t} else "); fprintf(outfile, "\n\t\t\tSKIP_OBJECT_VALUE(stream);\n"); fprintf(outfile, "\t}\n"); } @@ -127,14 +138,15 @@ objparser_dump_c(struct objparser *p) objparser_pregen_array_parsers(p); fprintf(outfile, - "void\n" + "int\n" "parse_%s(gcli_ctx *ctx, struct json_stream *stream, %s *out)\n", p->name, p->returntype); fprintf(outfile, "{\n"); fprintf(outfile, "\tenum json_type key_type;\n"); fprintf(outfile, "\tconst char *key;\n\n"); - fprintf(outfile, "\tif(json_next(stream) == JSON_NULL)\n"); - fprintf(outfile, "\t\treturn;\n\n"); + fprintf(outfile, "\tif (json_next(stream) == JSON_NULL)\n"); + fprintf(outfile, "\t\treturn gcli_error(ctx, " + "\"expected a JSON object in parse_%s\");\n\n", p->name); switch (p->kind) { case OBJPARSER_ENTRIES: objparser_dump_entries(p); break; @@ -143,7 +155,10 @@ objparser_dump_c(struct objparser *p) } fprintf(outfile, "\tif (key_type != JSON_OBJECT_END)\n"); - fprintf(outfile, "\t\terrx(1, \"unexpected object key type\");\n"); + fprintf(outfile, "\t\treturn gcli_error(ctx, \"unexpected object key type " + "in parse_%s\");\n", p->name); + + fprintf(outfile, "\treturn 0;\n"); fprintf(outfile, "}\n\n"); } @@ -151,7 +166,7 @@ void arrayparser_dump_c(struct arrayparser *p) { fprintf(outfile, - "void\n" + "int\n" "parse_%s(gcli_ctx *ctx, struct json_stream *stream, %s **out, " "size_t *out_size)\n", p->name, p->returntype); @@ -160,22 +175,28 @@ arrayparser_dump_c(struct arrayparser *p) fprintf(outfile, "\t\tjson_next(stream);\n"); fprintf(outfile, "\t\t*out = NULL;\n"); fprintf(outfile, "\t\t*out_size = 0;\n"); - fprintf(outfile, "\t\treturn;\n"); + fprintf(outfile, "\t\treturn 0;\n"); fprintf(outfile, "\t}\n\n"); fprintf(outfile, "\tif (json_next(stream) != JSON_ARRAY)\n"); - fprintf(outfile, "\t\terrx(1, \"Expected array of %s array in parse_%s\");\n\n", + fprintf(outfile, "\t\treturn gcli_error(ctx, \"Expected array of %s array in parse_%s\");\n\n", p->returntype, p->name); fprintf(outfile, "\twhile (json_peek(stream) != JSON_ARRAY_END) {\n"); + fprintf(outfile, "\t\tint rc;\n"); fprintf(outfile, "\t\t%s *it;\n", p->returntype); fprintf(outfile, "\t\t*out = realloc(*out, sizeof(**out) * (*out_size + 1));\n"); fprintf(outfile, "\t\tit = &(*out)[(*out_size)++];\n"); fprintf(outfile, "\t\tmemset(it, 0, sizeof(*it));\n"); - fprintf(outfile, "\t\t%s(ctx, stream, it);\n", p->parser); + fprintf(outfile, "\t\trc = %s(ctx, stream, it);\n", p->parser); + fprintf(outfile, "\t\tif (rc < 0)\n"); + fprintf(outfile, "\t\t\treturn rc;\n"); fprintf(outfile, "\t}\n\n"); - fprintf(outfile, "\tassert(json_next(stream) == JSON_ARRAY_END);\n"); + fprintf(outfile, "\tif (json_next(stream) != JSON_ARRAY_END)\n"); + fprintf(outfile, "\t\treturn gcli_error(ctx, \"unexpected element in array " + "while parsing %s\");\n", p->name); + fprintf(outfile, "\treturn 0;\n"); fprintf(outfile, "}\n\n"); } @@ -194,4 +215,6 @@ header_dump_c(void) fprintf(outfile, "#include \n"); fprintf(outfile, "#include \n"); fprintf(outfile, "#include \n"); + fprintf(outfile, "#include <%.*s.h>\n", + (int)(strlen(outfilename) - 2), outfilename); } diff --git a/src/pgen/dump_h.c b/src/pgen/dump_h.c index 62561bf6..0ce194e0 100644 --- a/src/pgen/dump_h.c +++ b/src/pgen/dump_h.c @@ -73,7 +73,7 @@ header_dump_h(void) void objparser_dump_h(struct objparser *p) { - fprintf(outfile, "void parse_%s(gcli_ctx *ctx, struct json_stream *, %s *);\n", + fprintf(outfile, "int parse_%s(gcli_ctx *ctx, struct json_stream *, %s *);\n", p->name, p->returntype); } @@ -96,7 +96,7 @@ footer_dump_h(void) void arrayparser_dump_h(struct arrayparser *p) { - fprintf(outfile, "void parse_%s(gcli_ctx *ctx, struct json_stream *, " + fprintf(outfile, "int parse_%s(gcli_ctx *ctx, struct json_stream *, " "%s **out, size_t *out_size);\n", p->name, p->returntype); } diff --git a/templates/github/api.t b/templates/github/api.t new file mode 100644 index 00000000..ed9f1b19 --- /dev/null +++ b/templates/github/api.t @@ -0,0 +1 @@ +parser github_get_error is object of char* select "message" as string; diff --git a/templates/github/gists.t b/templates/github/gists.t index 7195558f..be625efe 100644 --- a/templates/github/gists.t +++ b/templates/github/gists.t @@ -6,7 +6,7 @@ object of gcli_gist_file with ("filename" => filename as sv, "language" => language as sv, "raw_url" => url as sv, - "size" => size as int, + "size" => size as size_t, "type" => type as sv); parser github_gist is diff --git a/templates/github/labels.t b/templates/github/labels.t index 38a558d0..cb008e6b 100644 --- a/templates/github/labels.t +++ b/templates/github/labels.t @@ -4,7 +4,7 @@ parser github_label_text is object of sn_sv select "name" as sv; parser github_label is object of gcli_label with - ("id" => id as int, + ("id" => id as long, "name" => name as string, "description" => description as string, "color" => colour as github_style_colour); diff --git a/templates/gitlab/api.t b/templates/gitlab/api.t new file mode 100644 index 00000000..605b6128 --- /dev/null +++ b/templates/gitlab/api.t @@ -0,0 +1 @@ +parser gitlab_get_error is object of char* select "message" as string; diff --git a/templates/gitlab/labels.t b/templates/gitlab/labels.t index 0f078edc..050808f8 100644 --- a/templates/gitlab/labels.t +++ b/templates/gitlab/labels.t @@ -5,6 +5,6 @@ object of gcli_label with ("name" => name as string, "description" => description as string, "color" => colour as gitlab_style_colour, - "id" => id as int); + "id" => id as long); parser gitlab_labels is array of gcli_label use parse_gitlab_label; diff --git a/templates/gitlab/pipelines.t b/templates/gitlab/pipelines.t index 6dac0140..05e73283 100644 --- a/templates/gitlab/pipelines.t +++ b/templates/gitlab/pipelines.t @@ -8,7 +8,7 @@ object of gitlab_pipeline with "ref" => ref as string, "sha" => sha as string, "source" => source as string, - "id" => id as int); + "id" => id as long); parser gitlab_pipelines is array of gitlab_pipeline use parse_gitlab_pipeline; @@ -29,7 +29,7 @@ object of gitlab_job with "finished_at" => finished_at as string, "runner" => use parse_gitlab_job_runner, "duration" => duration as double, - "id" => id as int); + "id" => id as long); parser gitlab_jobs is array of gitlab_job use parse_gitlab_job; \ No newline at end of file diff --git a/todo.org b/todo.org index 65546d88..8d341a6b 100644 --- a/todo.org +++ b/todo.org @@ -134,6 +134,9 @@ ** TODO Remove global curl handle - [X] Put it into the context - [ ] Clean up handle on exit -** TODO Return errors from parsers +** DONE Return errors from parsers ** DONE [[file:src/releases.c::gcli_release_push_asset(gcli_new_release *const release,][push_asset]] should not call errx but return an error code ** DONE Make [[file:src/pulls.c::gcli_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner,][getting a pull diff]] return an error code +** TODO Add a real changelog file +** TODO include [[file:docs/pgen.org][docs/pgen.org]] in the distribution tarball +** TODO remove gcli_print_html_url From 134f82665509245b63d51433e6c9785430f1b07b Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 22:55:52 +0200 Subject: [PATCH 162/236] Remove gcli_print_html_url This function was used in rare cases and not really useful anyways. Remove it entirely from the library. --- include/gcli/json_util.h | 1 - src/gitlab/merge_requests.c | 4 ---- src/issues.c | 4 ---- src/json_util.c | 45 ------------------------------------- todo.org | 2 +- 5 files changed, 1 insertion(+), 55 deletions(-) diff --git a/include/gcli/json_util.h b/include/gcli/json_util.h index edbeb477..22921dfc 100644 --- a/include/gcli/json_util.h +++ b/include/gcli/json_util.h @@ -75,7 +75,6 @@ int get_int_to_sv_(gcli_ctx *ctx, json_stream *input, sn_sv *out, char const *function); sn_sv gcli_json_escape(sn_sv); #define gcli_json_escape_cstr(x) (gcli_json_escape(SV((char *)(x))).data) -void gcli_print_html_url(gcli_ctx *, gcli_fetch_buffer); int gcli_json_advance(gcli_ctx *ctx, json_stream *input, char const *fmt, ...); static inline int diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index aa5ce3ad..f42cd63d 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -158,10 +158,6 @@ gitlab_mr_merge(gcli_ctx *ctx, char const *owner, char const *repo, rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, &buffer); - /* if verbose or normal noise level, print the url */ - if (rc == 0 && !sn_quiet()) - gcli_print_html_url(ctx, buffer); - free(buffer.data); free(url); free(e_owner); diff --git a/src/issues.c b/src/issues.c index 2e468ef0..2169810e 100644 --- a/src/issues.c +++ b/src/issues.c @@ -98,10 +98,6 @@ gcli_issue_submit(gcli_ctx *ctx, gcli_submit_issue_options opts) int rc = 0; rc = gcli_forge(ctx)->perform_submit_issue(ctx, opts, &json_buffer); - - if (rc == 0) - gcli_print_html_url(ctx, json_buffer); - free(json_buffer.data); return rc; diff --git a/src/json_util.c b/src/json_util.c index 666b4b5d..2c14a643 100644 --- a/src/json_util.c +++ b/src/json_util.c @@ -215,51 +215,6 @@ get_sv_(gcli_ctx *ctx, json_stream *const input, sn_sv *out, char const *where) return 0; } -void -gcli_print_html_url(gcli_ctx *ctx, gcli_fetch_buffer const buffer) -{ - json_stream stream = {0}; - - json_open_buffer(&stream, buffer.data, buffer.length); - json_set_streaming(&stream, true); - - enum json_type next = json_next(&stream); - char const *expected_key = gcli_forge(ctx)->html_url_key; - - while ((next = json_next(&stream)) == JSON_STRING) { - size_t len; - - char const *key = json_get_string(&stream, &len); - if (strncmp(key, expected_key, len) == 0) { - char *url; - if (get_string(ctx, &stream, &url) < 0) - abort(); - - puts(url); - free(url); - } else { - enum json_type value_type = json_next(&stream); - - switch (value_type) { - case JSON_ARRAY: - json_skip_until(&stream, JSON_ARRAY_END); - break; - case JSON_OBJECT: - json_skip_until(&stream, JSON_OBJECT_END); - break; - default: - break; - } - } - } - - if (next != JSON_OBJECT_END) - abort(); - - json_close(&stream); -} - - int get_label_(gcli_ctx *ctx, json_stream *const input, char const **out, char const *where) diff --git a/todo.org b/todo.org index 8d341a6b..6a86a433 100644 --- a/todo.org +++ b/todo.org @@ -139,4 +139,4 @@ ** DONE Make [[file:src/pulls.c::gcli_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner,][getting a pull diff]] return an error code ** TODO Add a real changelog file ** TODO include [[file:docs/pgen.org][docs/pgen.org]] in the distribution tarball -** TODO remove gcli_print_html_url +** DONE remove gcli_print_html_url From f09b2c288c24ee162d9759329387fc206e317183 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 22:59:47 +0200 Subject: [PATCH 163/236] Include pgen.org in dist tarball --- Makefile.am | 3 ++- todo.org | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 5bc87e90..b5e00b3d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -201,7 +201,8 @@ EXTRA_DIST = \ README.md \ HACKING.md \ autogen.sh \ - m4/.gitkeep + m4/.gitkeep \ + docs/pgen.org ########################################### # Tests diff --git a/todo.org b/todo.org index 6a86a433..37960021 100644 --- a/todo.org +++ b/todo.org @@ -138,5 +138,5 @@ ** DONE [[file:src/releases.c::gcli_release_push_asset(gcli_new_release *const release,][push_asset]] should not call errx but return an error code ** DONE Make [[file:src/pulls.c::gcli_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner,][getting a pull diff]] return an error code ** TODO Add a real changelog file -** TODO include [[file:docs/pgen.org][docs/pgen.org]] in the distribution tarball +** DONE include [[file:docs/pgen.org][docs/pgen.org]] in the distribution tarball ** DONE remove gcli_print_html_url From 96dc691038ea84058a37f3fcf4d6c8f8afd5f035 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 23:26:29 +0200 Subject: [PATCH 164/236] Remove printing gcli_mr_pipelines function from library --- include/gcli/cmd/pipelines.h | 2 ++ src/cmd/pipelines.c | 16 ++++++++++++++++ src/gitlab/pipelines.c | 16 ---------------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/include/gcli/cmd/pipelines.h b/include/gcli/cmd/pipelines.h index 7d1fde81..4d7e2d65 100644 --- a/include/gcli/cmd/pipelines.h +++ b/include/gcli/cmd/pipelines.h @@ -37,6 +37,8 @@ void gitlab_print_pipelines(gitlab_pipeline_list const *const list); int gitlab_pipelines(char const *owner, char const *repo, int const count); +int gitlab_mr_pipelines(char const *owner, char const *repo, int const mr_id); + int gitlab_pipeline_jobs(char const *owner, char const *repo, long pipeline, int count); void gitlab_print_jobs(gitlab_job_list const *const list); diff --git a/src/cmd/pipelines.c b/src/cmd/pipelines.c index d6ce0f21..7f733964 100644 --- a/src/cmd/pipelines.c +++ b/src/cmd/pipelines.c @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -68,6 +69,21 @@ usage(void) copyright(); } +int +gitlab_mr_pipelines(char const *owner, char const *repo, int const mr_id) +{ + gitlab_pipeline_list list = {0}; + int rc = 0; + + rc = gitlab_get_mr_pipelines(g_clictx, owner, repo, mr_id, &list); + if (rc == 0) + gitlab_print_pipelines(&list); + + gitlab_free_pipelines(&list); + + return rc; +} + void gitlab_print_pipelines(gitlab_pipeline_list const *const list) { diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index ff497a02..230cfacc 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -220,22 +220,6 @@ gitlab_job_retry(gcli_ctx *ctx, char const *owner, char const *repo, return rc; } -int -gitlab_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, - int const mr_id) -{ - gitlab_pipeline_list list = {0}; - int rc = 0; - - rc = gitlab_get_mr_pipelines(ctx, owner, repo, mr_id, &list); - if (rc == 0) - gitlab_print_pipelines(&list); - - gitlab_free_pipelines(&list); - - return rc; -} - int gitlab_job_download_artifacts(gcli_ctx *ctx, char const *owner, char const *repo, long const jid, From 677c807eb41c961c4b761dc44fff2e92451d8733 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 24 Aug 2023 23:44:34 +0200 Subject: [PATCH 165/236] Move all config to the frontend tool This allows the library to have no state at all. It will not call into any routines that may read configuration files. The benefit is that this allows us to implement the test suite in a cleaner way. --- Makefile.am | 7 +- docs/gcli-pulls.1.in | 2 - include/gcli/{config.h => cmd/cmdconfig.h} | 18 +- include/gcli/{ => cmd}/gitconfig.h | 6 +- include/gcli/ctx.h | 13 +- include/gcli/curl.h | 4 +- include/gcli/forges.h | 13 +- include/gcli/gcli.h | 16 +- include/gcli/gitea/config.h | 4 +- include/gcli/github/config.h | 4 +- include/gcli/gitlab/config.h | 4 +- include/gcli/repos.h | 2 - src/cmd/api.c | 4 +- src/cmd/ci.c | 2 +- src/cmd/cmd.c | 2 +- src/{config.c => cmd/cmdconfig.c} | 267 ++++++++++++++------- src/cmd/colour.c | 2 +- src/cmd/comment.c | 2 +- src/cmd/config.c | 2 +- src/cmd/editor.c | 3 +- src/cmd/forks.c | 9 +- src/cmd/gcli.c | 9 +- src/cmd/gists.c | 2 +- src/{ => cmd}/gitconfig.c | 5 +- src/cmd/issues.c | 2 +- src/cmd/labels.c | 2 +- src/cmd/pipelines.c | 2 +- src/cmd/pulls.c | 24 +- src/cmd/repos.c | 6 +- src/comments.c | 1 - src/ctx.c | 33 +++ src/curl.c | 11 +- src/forges.c | 15 +- src/gcli.c | 8 +- src/gitea/config.c | 72 +----- src/gitea/issues.c | 18 +- src/gitea/labels.c | 3 +- src/gitea/milestones.c | 1 - src/gitea/pulls.c | 1 - src/gitea/releases.c | 1 - src/github/checks.c | 1 - src/github/comments.c | 1 - src/github/config.c | 67 +----- src/github/forks.c | 1 - src/github/gists.c | 17 +- src/github/issues.c | 1 - src/github/labels.c | 1 - src/github/milestones.c | 1 - src/github/pulls.c | 7 +- src/github/releases.c | 1 - src/github/repos.c | 1 - src/github/review.c | 1 - src/github/status.c | 1 - src/gitlab/comments.c | 6 +- src/gitlab/config.c | 69 +----- src/gitlab/forks.c | 9 +- src/gitlab/issues.c | 61 ++--- src/gitlab/labels.c | 10 +- src/gitlab/merge_requests.c | 64 +++-- src/gitlab/milestones.c | 20 +- src/gitlab/pipelines.c | 23 +- src/gitlab/releases.c | 35 ++- src/gitlab/repos.c | 31 +-- src/gitlab/review.c | 5 +- src/gitlab/snippets.c | 6 +- src/gitlab/sshkeys.c | 1 - src/gitlab/status.c | 4 +- src/pgen/dump_c.c | 3 +- src/pulls.c | 3 - src/repos.c | 6 - src/review.c | 48 ---- src/sshkeys.c | 1 - tests/pgen-tests.c | 15 +- todo.org | 6 + 74 files changed, 449 insertions(+), 680 deletions(-) rename include/gcli/{config.h => cmd/cmdconfig.h} (86%) rename include/gcli/{ => cmd}/gitconfig.h (95%) rename src/{config.c => cmd/cmdconfig.c} (76%) rename src/{ => cmd}/gitconfig.c (99%) diff --git a/Makefile.am b/Makefile.am index b5e00b3d..ea83fe14 100644 --- a/Makefile.am +++ b/Makefile.am @@ -58,6 +58,7 @@ dist_man_MANS = \ gcli_SOURCES = \ include/gcli/cmd/ci.h src/cmd/ci.c \ + include/gcli/cmd/cmdconfig.h src/cmd/cmdconfig.c \ include/gcli/cmd/cmd.h src/cmd/cmd.c \ include/gcli/cmd/colour.h src/cmd/colour.c \ include/gcli/cmd/comment.h src/cmd/comment.c \ @@ -65,6 +66,7 @@ gcli_SOURCES = \ include/gcli/cmd/editor.h src/cmd/editor.c \ include/gcli/cmd/forks.h src/cmd/forks.c \ include/gcli/cmd/gists.h src/cmd/gists.c \ + include/gcli/cmd/gitconfig.h src/cmd/gitconfig.c \ include/gcli/cmd/issues.h src/cmd/issues.c \ include/gcli/cmd/labels.h src/cmd/labels.c \ include/gcli/cmd/milestones.h src/cmd/milestones.c \ @@ -116,8 +118,7 @@ TEMPLATES = \ templates/gitea/milestones.t include_HEADERS = include/gcli/gcli.h include/gcli/comments.h \ - include/gcli/config.h include/gcli/curl.h \ - include/gcli/forks.h include/gcli/gitconfig.h \ + include/gcli/curl.h include/gcli/forks.h \ include/gcli/issues.h include/gcli/labels.h \ include/gcli/milestones.h include/gcli/pulls.h \ include/gcli/releases.h include/gcli/repos.h \ @@ -129,11 +130,9 @@ libgcli_la_SOURCES = \ include/gcli/gcli.h src/gcli.c \ include/gcli/date_time.h src/date_time.c \ src/comments.c include/gcli/comments.h \ - src/config.c include/gcli/config.h \ src/curl.c include/gcli/curl.h \ src/forges.c include/gcli/forges.h \ src/forks.c include/gcli/forks.h \ - src/gitconfig.c include/gcli/gitconfig.h \ src/issues.c include/gcli/issues.h \ src/json_util.c include/gcli/json_util.h \ src/labels.c include/gcli/labels.h \ diff --git a/docs/gcli-pulls.1.in b/docs/gcli-pulls.1.in index 855683de..3e49f53b 100644 --- a/docs/gcli-pulls.1.in +++ b/docs/gcli-pulls.1.in @@ -150,8 +150,6 @@ Clear a set milestone on the pull request. Alias for the .Cm comments action that prints a list of comments associated with the PR. -.It Cm reviews -Print reviews including comments under them. .It Cm labels Op Ar options The following options can be specified more than once: .Bl -tag -width indent diff --git a/include/gcli/config.h b/include/gcli/cmd/cmdconfig.h similarity index 86% rename from include/gcli/config.h rename to include/gcli/cmd/cmdconfig.h index cad237c8..801ed745 100644 --- a/include/gcli/config.h +++ b/include/gcli/cmd/cmdconfig.h @@ -27,8 +27,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CONFIG_H -#define CONFIG_H +#ifndef GCLI_CMD_CMDCONFIG_H +#define GCLI_CMD_CMDCONFIG_H #ifdef HAVE_CONFIG_H #include @@ -38,16 +38,15 @@ #include int gcli_config_parse_args(gcli_ctx *ctx, int *argc, char ***argv); - +int gcli_config_init_ctx(gcli_ctx *ctx); void gcli_config_get_upstream_parts(gcli_ctx *ctx, sn_sv *owner, sn_sv *repo); - -sn_sv gcli_config_find_by_key(gcli_ctx *ctx, - sn_sv const section_name, +char *gcli_config_get_apibase(gcli_ctx *); +sn_sv gcli_config_find_by_key(gcli_ctx *ctx, char const *section_name, char const *key); char *gcli_config_get_editor(gcli_ctx *ctx); -char *gcli_config_get_authheader(gcli_ctx *ctx); -int gcli_config_get_account(gcli_ctx *ctx, sn_sv *out); +char *gcli_config_get_token(gcli_ctx *ctx); +char *gcli_config_get_account_name(gcli_ctx *ctx); sn_sv gcli_config_get_upstream(gcli_ctx *ctx); sn_sv gcli_config_get_base(gcli_ctx *ctx); gcli_forge_type gcli_config_get_forge_type(gcli_ctx *ctx); @@ -55,6 +54,5 @@ sn_sv gcli_config_get_override_default_account(gcli_ctx *ctx); bool gcli_config_pr_inhibit_delete_source_branch(gcli_ctx *ctx); void gcli_config_get_repo(gcli_ctx *ctx, char const **, char const **); int gcli_config_have_colours(gcli_ctx *ctx); -char const *gcli_get_apibase(gcli_ctx *ctx); -#endif /* CONFIG_H */ +#endif /* GCLI_CMD_CMDCONFIG_H */ diff --git a/include/gcli/gitconfig.h b/include/gcli/cmd/gitconfig.h similarity index 95% rename from include/gcli/gitconfig.h rename to include/gcli/cmd/gitconfig.h index 73eea15c..084feaa0 100644 --- a/include/gcli/gitconfig.h +++ b/include/gcli/cmd/gitconfig.h @@ -27,8 +27,8 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GITCONFIG_H -#define GITCONFIG_H +#ifndef GCLI_CMD_GITCONFIG_H +#define GCLI_CMD_GITCONFIG_H #ifdef HAVE_CONFIG_H #include @@ -56,4 +56,4 @@ int gcli_gitconfig_repo_by_remote(char const *remote_name, char const **owner, char const **repo); -#endif /* GITCONFIG_H */ +#endif /* GCLI_CMD_GITCONFIG_H */ diff --git a/include/gcli/ctx.h b/include/gcli/ctx.h index 1b8df7c2..6cc2d20b 100644 --- a/include/gcli/ctx.h +++ b/include/gcli/ctx.h @@ -36,17 +36,20 @@ * data */ struct gcli_ctx { CURL *curl; - struct gcli_config *config; - struct gcli_dotgcli *dotgcli; + void *usrdata; char *last_error; + + /* ?? freed internally? */ + char *(*get_token)(struct gcli_ctx *); + gcli_forge_type (*get_forge_type)(struct gcli_ctx *ctx); + char *(*get_apibase)(struct gcli_ctx *); }; /* Error routine */ int gcli_error(struct gcli_ctx *ctx, char const *const fmt, ...); -/* Functions that are strictly called from the init / deinit routines - * and not exposed to the public interface */ -int gcli_config_init_ctx(struct gcli_ctx *); +char *gcli_get_apibase(struct gcli_ctx *ctx); +char *gcli_get_authheader(struct gcli_ctx *ctx); #endif /* GCLI_CTX_H */ diff --git a/include/gcli/curl.h b/include/gcli/curl.h index abb00634..4920b5d0 100644 --- a/include/gcli/curl.h +++ b/include/gcli/curl.h @@ -43,8 +43,8 @@ #include #include -typedef void (*parsefn)(gcli_ctx *, json_stream *stream, void *list, - size_t *listsize); +typedef int (*parsefn)(gcli_ctx *, json_stream *stream, void *list, + size_t *listsize); typedef void (*filterfn)(void *list, size_t *listsize, void const *userdata); typedef struct gcli_fetch_buffer gcli_fetch_buffer; typedef struct gcli_fetch_list_ctx gcli_fetch_list_ctx; diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 09b0e055..4b10cc06 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -426,13 +426,6 @@ struct gcli_forge_descriptor { int max, gcli_repo_list *out); - /** - * Get a list of your own repos */ - int (*get_own_repos)( - gcli_ctx *ctx, - int max, - gcli_repo_list *out); - /** * Create the given repo */ int (*repo_create)( @@ -470,11 +463,7 @@ struct gcli_forge_descriptor { /** * Get an the http authentication header for use by curl */ - char *(*get_authheader)(gcli_ctx *ctx); - - /** - * Get the user account name */ - int (*get_account)(gcli_ctx *ctx, sn_sv *out); + char *(*make_authheader)(gcli_ctx *ctx, char const *token); /** * Get list of SSH keys */ diff --git a/include/gcli/gcli.h b/include/gcli/gcli.h index a84c3bf3..767997f7 100644 --- a/include/gcli/gcli.h +++ b/include/gcli/gcli.h @@ -34,10 +34,6 @@ #include #endif -#ifdef IN_LIBGCLI -#include -#endif /* IN_LIBGCLI */ - enum gcli_output_flags { OUTPUT_SORTED = (1 << 0), OUTPUT_LONG = (1 << 1), @@ -49,9 +45,19 @@ typedef enum gcli_forge_type { GCLI_FORGE_GITEA, } gcli_forge_type; +#ifdef IN_LIBGCLI +#include +#endif /* IN_LIBGCLI */ + typedef struct gcli_ctx gcli_ctx; -char const *gcli_init(gcli_ctx **); +char const *gcli_init(gcli_ctx **, + gcli_forge_type (*get_forge_type)(gcli_ctx *), + char *(*get_authheader)(gcli_ctx *), + char *(*get_apibase)(gcli_ctx *)); + +void *gcli_get_userdata(struct gcli_ctx const *); +void gcli_set_userdata(struct gcli_ctx *, void *usrdata); void gcli_destroy(gcli_ctx **ctx); char const *gcli_get_error(gcli_ctx *ctx); diff --git a/include/gcli/gitea/config.h b/include/gcli/gitea/config.h index 2ca53df9..fc509606 100644 --- a/include/gcli/gitea/config.h +++ b/include/gcli/gitea/config.h @@ -38,8 +38,6 @@ #include -char *gitea_get_apibase(gcli_ctx *ctx); -char *gitea_get_authheader(gcli_ctx *ctx); -int gitea_get_account(gcli_ctx *ctx, sn_sv *out); +char *gitea_make_authheader(gcli_ctx *ctx, char const *token); #endif /* GITEA_CONFIG_H */ diff --git a/include/gcli/github/config.h b/include/gcli/github/config.h index b086c2cc..33a848b7 100644 --- a/include/gcli/github/config.h +++ b/include/gcli/github/config.h @@ -38,8 +38,6 @@ #include -char *github_get_apibase(gcli_ctx *ctx); -char *github_get_authheader(gcli_ctx *ctx); -int github_get_account(gcli_ctx *ctx, sn_sv *out); +char *github_make_authheader(gcli_ctx *ctx, char const *token); #endif /* GITHUB_CONFIG_H */ diff --git a/include/gcli/gitlab/config.h b/include/gcli/gitlab/config.h index 243989ad..981dac26 100644 --- a/include/gcli/gitlab/config.h +++ b/include/gcli/gitlab/config.h @@ -38,8 +38,6 @@ #include -char *gitlab_get_apibase(gcli_ctx *ctx); -char *gitlab_get_authheader(gcli_ctx *ctx); -int gitlab_get_account(gcli_ctx *ctx, sn_sv *out); +char *gitlab_make_authheader(gcli_ctx *ctx, char const *token); #endif /* GITLAB_CONFIG_H */ diff --git a/include/gcli/repos.h b/include/gcli/repos.h index 311bc37d..4d6134f2 100644 --- a/include/gcli/repos.h +++ b/include/gcli/repos.h @@ -65,8 +65,6 @@ struct gcli_repo_create_options { int gcli_get_repos(gcli_ctx *ctx, char const *owner, int max, gcli_repo_list *list); -int gcli_get_own_repos(gcli_ctx *ctx, int max, gcli_repo_list *list); - void gcli_repos_free(gcli_repo_list *list); void gcli_repo_free(gcli_repo *it); diff --git a/src/cmd/api.c b/src/cmd/api.c index 802f1b8c..1f995bf3 100644 --- a/src/cmd/api.c +++ b/src/cmd/api.c @@ -32,7 +32,9 @@ #endif #include -#include +#include + +#include #include #include diff --git a/src/cmd/ci.c b/src/cmd/ci.c index bfef0856..75bc7d97 100644 --- a/src/cmd/ci.c +++ b/src/cmd/ci.c @@ -33,9 +33,9 @@ #include #include +#include #include -#include #include #include diff --git a/src/cmd/cmd.c b/src/cmd/cmd.c index 99b77c81..f2523e31 100644 --- a/src/cmd/cmd.c +++ b/src/cmd/cmd.c @@ -32,7 +32,7 @@ #endif #include -#include +#include #include #include diff --git a/src/config.c b/src/cmd/cmdconfig.c similarity index 76% rename from src/config.c rename to src/cmd/cmdconfig.c index 91629a62..824a9534 100644 --- a/src/config.c +++ b/src/cmd/cmdconfig.c @@ -29,12 +29,13 @@ #include -#include +#include +#include + +#include +#include #include #include -#include -#include -#include #include #include @@ -88,12 +89,32 @@ struct gcli_dotgcli { bool has_been_found; }; +struct cmd_ctx { + struct gcli_config config; + struct gcli_dotgcli local_config; +}; + +static inline struct gcli_dotgcli * +ctx_dotgcli(struct gcli_ctx *ctx) +{ + struct cmd_ctx *cctx = gcli_get_userdata(ctx); + return &cctx->local_config; +} + +static inline struct gcli_config * +ctx_config(struct gcli_ctx *ctx) +{ + struct cmd_ctx *cctx = gcli_get_userdata(ctx); + return &cctx->config; +} + static bool should_init_dotgcli(gcli_ctx *ctx) { - return !ctx->dotgcli->has_been_searched_for || - (ctx->dotgcli->has_been_searched_for && - !ctx->dotgcli->has_been_found); + struct gcli_dotgcli *dgcli = ctx_dotgcli(ctx); + + return !dgcli->has_been_searched_for || + (dgcli->has_been_searched_for && !dgcli->has_been_found); } static char const * @@ -176,25 +197,27 @@ init_local_config(gcli_ctx *ctx) } char const *path = find_dotgcli(); + struct gcli_dotgcli *dgcli = ctx_dotgcli(ctx); + if (!path) { - ctx->dotgcli->has_been_searched_for = true; - ctx->dotgcli->has_been_found = false; + dgcli->has_been_searched_for = true; + dgcli->has_been_found = false; return; } - ctx->dotgcli->has_been_searched_for = true; - ctx->dotgcli->has_been_found = true; + dgcli->has_been_searched_for = true; + dgcli->has_been_found = true; - int len = sn_mmap_file(path, &ctx->dotgcli->mmap_pointer); + int len = sn_mmap_file(path, &dgcli->mmap_pointer); if (len < 0) err(1, "Unable to open config file"); - ctx->dotgcli->buffer = sn_sv_from_parts(ctx->dotgcli->mmap_pointer, len); - ctx->dotgcli->buffer = sn_sv_trim_front(ctx->dotgcli->buffer); + dgcli->buffer = sn_sv_from_parts(dgcli->mmap_pointer, len); + dgcli->buffer = sn_sv_trim_front(dgcli->buffer); int curr_line = 1; - while (ctx->dotgcli->buffer.length > 0) { - sn_sv line = sn_sv_chop_until(&ctx->dotgcli->buffer, '\n'); + while (dgcli->buffer.length > 0) { + sn_sv line = sn_sv_chop_until(&dgcli->buffer, '\n'); line = sn_sv_trim(line); @@ -204,7 +227,7 @@ init_local_config(gcli_ctx *ctx) // Comments if (line.data[0] == '#') { - ctx->dotgcli->buffer = sn_sv_trim_front(ctx->dotgcli->buffer); + dgcli->buffer = sn_sv_trim_front(dgcli->buffer); curr_line++; continue; } @@ -222,12 +245,12 @@ init_local_config(gcli_ctx *ctx) sn_sv value = sn_sv_trim(line); struct gcli_config_entry *entry = calloc(sizeof(*entry), 1); - TAILQ_INSERT_TAIL(&ctx->dotgcli->entries, entry, next); + TAILQ_INSERT_TAIL(&dgcli->entries, entry, next); entry->key = key; entry->value = value; - ctx->dotgcli->buffer = sn_sv_trim_front(ctx->dotgcli->buffer); + dgcli->buffer = sn_sv_trim_front(dgcli->buffer); curr_line++; } @@ -366,15 +389,15 @@ parse_config_file(struct gcli_config *cfg, * Try to load up the local config file if it exists. If we succeed, * return 0. Otherwise return -1. */ -static int +static struct gcli_config * ensure_config(gcli_ctx *ctx) { - struct gcli_config *cfg = ctx->config; + struct gcli_config *cfg = ctx_config(ctx); char *file_path = NULL; struct config_parser parser = {0}; if (cfg->inited) - return 0; + return cfg; cfg->inited = true; @@ -383,7 +406,7 @@ ensure_config(gcli_ctx *ctx) file_path = getenv("HOME"); if (!file_path) { warnx("Neither XDG_CONFIG_PATH nor HOME set in env"); - return -1; + return cfg; } /* @@ -395,7 +418,7 @@ ensure_config(gcli_ctx *ctx) if (access(file_path, R_OK) < 0) { warn("Cannot access config file at %s", file_path); - return -1; + return cfg; } int len = sn_mmap_file(file_path, &cfg->mmap_pointer); @@ -413,7 +436,7 @@ ensure_config(gcli_ctx *ctx) free((void *)file_path); - return 0; + return cfg; } /** Check input for a value that indicates yes/true */ @@ -464,16 +487,16 @@ readenv(struct gcli_config *cfg) int gcli_config_init_ctx(struct gcli_ctx *ctx) { - ctx->dotgcli = calloc(sizeof(*ctx->dotgcli), 1); - ctx->config = calloc(sizeof(*ctx->config), 1); + struct cmd_ctx *cctx = calloc(sizeof(*cctx), 1); + gcli_set_userdata(ctx, cctx); - ctx->config->sections = + cctx->config.sections = (struct gcli_config_sections) - TAILQ_HEAD_INITIALIZER(ctx->config->sections); + TAILQ_HEAD_INITIALIZER(cctx->config.sections); - ctx->dotgcli->entries = + cctx->local_config.entries = (struct gcli_config_entries) - TAILQ_HEAD_INITIALIZER(ctx->dotgcli->entries); + TAILQ_HEAD_INITIALIZER(cctx->local_config.entries); return 0; } @@ -486,6 +509,8 @@ gcli_config_parse_args(gcli_ctx *ctx, int *argc, char ***argv) * arguments. Only global options that do not alter subcommand * specific behaviour should be accepted here. */ + struct gcli_config *cfg = ctx_config(ctx); + int ch; const struct option options[] = { { .name = "account", @@ -498,7 +523,7 @@ gcli_config_parse_args(gcli_ctx *ctx, int *argc, char ***argv) .val = 'r' }, { .name = "colours", .has_arg = no_argument, - .flag = &ctx->config->colours_disabled, + .flag = &cfg->colours_disabled, .val = 0 }, { .name = "type", .has_arg = required_argument, @@ -520,21 +545,21 @@ gcli_config_parse_args(gcli_ctx *ctx, int *argc, char ***argv) /* Before we parse options, invalidate the override type so it * doesn't get confused later */ - ctx->config->override_forgetype = -1; + cfg->override_forgetype = -1; /* Start off by pre-populating the config structure */ - readenv(ctx->config); + readenv(cfg); while ((ch = getopt_long(*argc, *argv, "+a:r:cqvt:", options, NULL)) != -1) { switch (ch) { case 'a': { - ctx->config->override_default_account = optarg; + cfg->override_default_account = optarg; } break; case 'r': { - ctx->config->override_remote = optarg; + cfg->override_remote = optarg; } break; case 'c': { - ctx->config->force_colours = 1; + cfg->force_colours = 1; } break; case 'q': { sn_setverbosity(VERBOSITY_QUIET); @@ -544,11 +569,11 @@ gcli_config_parse_args(gcli_ctx *ctx, int *argc, char ***argv) } break; case 't': { if (strcmp(optarg, "github") == 0) { - ctx->config->override_forgetype = GCLI_FORGE_GITHUB; + cfg->override_forgetype = GCLI_FORGE_GITHUB; } else if (strcmp(optarg, "gitlab") == 0) { - ctx->config->override_forgetype = GCLI_FORGE_GITLAB; + cfg->override_forgetype = GCLI_FORGE_GITLAB; } else if (strcmp(optarg, "gitea") == 0) { - ctx->config->override_forgetype = GCLI_FORGE_GITEA; + cfg->override_forgetype = GCLI_FORGE_GITEA; } else { fprintf(stderr, "error: unknown forge type '%s'. " "Have either github, gitlab or gitea.\n", optarg); @@ -573,35 +598,34 @@ gcli_config_parse_args(gcli_ctx *ctx, int *argc, char ***argv) * working without it. */ optind = 0; - ctx->config->inited = false; + cfg->inited = false; return EXIT_SUCCESS; } static struct gcli_config_section const * -find_section(struct gcli_config *cfg, sn_sv name) +find_section(struct gcli_config *cfg, char const *name) { struct gcli_config_section *section; TAILQ_FOREACH(section, &cfg->sections, next) { - if (sn_sv_eq(section->title, name)) + if (sn_sv_eq_to(section->title, name)) return section; } return NULL; } sn_sv -gcli_config_find_by_key(gcli_ctx *ctx, sn_sv const section_name, char const *key) +gcli_config_find_by_key(gcli_ctx *ctx, char const *section_name, char const *key) { struct gcli_config_entry *entry; - - ensure_config(ctx); + struct gcli_config *cfg = ensure_config(ctx); struct gcli_config_section const *const section = - find_section(ctx->config, section_name); + find_section(cfg, section_name); if (!section) { - warnx("no config section with name '"SV_FMT"'", SV_ARGS(section_name)); + warnx("no config section with name '%s'", section_name); return SV_NULL; } @@ -616,7 +640,7 @@ gcli_config_find_by_key(gcli_ctx *ctx, sn_sv const section_name, char const *key static sn_sv gcli_local_config_find_by_key(gcli_ctx *ctx, char const *const key) { - struct gcli_dotgcli *lcfg = ctx->dotgcli; + struct gcli_dotgcli *lcfg = ctx_dotgcli(ctx); struct gcli_config_entry *entry; TAILQ_FOREACH(entry, &lcfg->entries, next) { @@ -632,23 +656,98 @@ gcli_config_get_editor(gcli_ctx *ctx) { ensure_config(ctx); - return sn_sv_to_cstr(gcli_config_find_by_key(ctx, SV("defaults"), "editor")); + return sn_sv_to_cstr(gcli_config_find_by_key(ctx, "defaults", "editor")); +} + +static char const *const +default_account_entry_names[] = { + [GCLI_FORGE_GITHUB] = "github-default-account", + [GCLI_FORGE_GITLAB] = "gitlab-default-account", + [GCLI_FORGE_GITEA] = "gitea-default-account", }; + +static char const * +get_default_account(gcli_ctx *ctx, gcli_forge_type ftype) +{ + char const *const defaultname = default_account_entry_names[ftype]; + sn_sv act = gcli_config_find_by_key(ctx, "defaults", defaultname); + + if (!act.length) + return NULL; + + return sn_sv_to_cstr(act); } +static char const * +gcli_config_get_account(gcli_ctx *ctx) +{ + struct gcli_config *cfg = ctx_config(ctx); + gcli_forge_type ftype = gcli_config_get_forge_type(ctx); + char const *account; + + if (cfg->override_default_account) { + account = cfg->override_default_account; + } else { + account = get_default_account(ctx, ftype); + } + + return account; +} + +static char const *const default_urls[] = { + [GCLI_FORGE_GITHUB] = "https://api.github.com", + [GCLI_FORGE_GITLAB] = "https://gitlab.com/api/v4", + [GCLI_FORGE_GITEA] = "https://codeberg.org/api/v1", +}; + char * -gcli_config_get_authheader(gcli_ctx *ctx) +gcli_config_get_apibase(gcli_ctx *ctx) { - ensure_config(ctx); + char const *acct = gcli_config_get_account(ctx); + char *url = NULL; + + if (acct) { + sn_sv url_sv = gcli_config_find_by_key(ctx, acct, "apibase"); + if (url_sv.length) + url = sn_sv_to_cstr(url_sv); + } + + if (!url) + url = strdup(default_urls[gcli_config_get_forge_type(ctx)]); - return gcli_forge(ctx)->get_authheader(ctx); + return url; } -int -gcli_config_get_account(gcli_ctx *ctx, sn_sv *out) +char * +gcli_config_get_account_name(gcli_ctx *ctx) +{ + char const *account = gcli_config_get_account(ctx); + sn_sv actname = gcli_config_find_by_key( + ctx, account, "account"); + + return sn_sv_to_cstr(actname); +} + +static char * +get_account_token(gcli_ctx *ctx) +{ + char const *account; + sn_sv token; + + account = gcli_config_get_account(ctx); + if (!account) + return NULL; + + token = gcli_config_find_by_key(ctx, account, "token"); + + return sn_sv_to_cstr(token); +} + +char * +gcli_config_get_token(gcli_ctx *ctx) { ensure_config(ctx); - return gcli_forge(ctx)->get_account(ctx, out); + return get_account_token(ctx); } sn_sv @@ -700,10 +799,13 @@ gcli_config_get_base(gcli_ctx *ctx) sn_sv gcli_config_get_override_default_account(gcli_ctx *ctx) { + struct gcli_config *cfg; + init_local_config(ctx); + cfg = ctx_config(ctx); - if (ctx->config->override_default_account) - return SV((char *)ctx->config->override_default_account); + if (cfg->override_default_account) + return SV((char *)cfg->override_default_account); else return SV_NULL; } @@ -711,17 +813,19 @@ gcli_config_get_override_default_account(gcli_ctx *ctx) static gcli_forge_type gcli_config_get_forge_type_internal(gcli_ctx *ctx) { + struct gcli_config *cfg = ctx_config(ctx); + /* Hard override */ - if (ctx->config->override_forgetype >= 0) - return ctx->config->override_forgetype; + if (cfg->override_forgetype >= 0) + return cfg->override_forgetype; ensure_config(ctx); init_local_config(ctx); sn_sv entry = {0}; - if (ctx->config->override_default_account) { - sn_sv const section = SV((char *)ctx->config->override_default_account); + if (cfg->override_default_account) { + char const *section = cfg->override_default_account; entry = gcli_config_find_by_key(ctx, section, "forge-type"); if (sn_sv_null(entry)) errx(1, @@ -743,7 +847,7 @@ gcli_config_get_forge_type_internal(gcli_ctx *ctx) } /* As a last resort, try to infer from the git remote */ - int const type = gcli_gitconfig_get_forgetype(ctx, ctx->config->override_remote); + int const type = gcli_gitconfig_get_forgetype(ctx, cfg->override_remote); if (type < 0) errx(1, "error: cannot infer forge type. " "use -t to overrride manually."); @@ -779,12 +883,13 @@ gcli_config_get_repo(gcli_ctx *ctx, char const **const owner, char const **const repo) { sn_sv upstream = {0}; + struct gcli_config *cfg; - ensure_config(ctx); + cfg = ensure_config(ctx); - if (ctx->config->override_remote) { + if (cfg->override_remote) { int const forge = gcli_gitconfig_repo_by_remote( - ctx->config->override_remote, owner, repo); + cfg->override_remote, owner, repo); if (forge >= 0) { if ((int)(gcli_config_get_forge_type(ctx)) != forge) @@ -813,37 +918,25 @@ int gcli_config_have_colours(gcli_ctx *ctx) { static int tested_tty = 0; + struct gcli_config *cfg; - if (ctx->config->force_colours) + cfg = ctx_config(ctx); + + if (cfg->force_colours) return 1; - if (ctx->config->colours_disabled) + if (cfg->colours_disabled) return 0; if (tested_tty) - return !ctx->config->colours_disabled; + return !cfg->colours_disabled; if (isatty(STDOUT_FILENO)) - ctx->config->colours_disabled = false; + cfg->colours_disabled = false; else - ctx->config->colours_disabled = true; + cfg->colours_disabled = true; tested_tty = 1; - return !ctx->config->colours_disabled; -} - -char const * -gcli_get_apibase(gcli_ctx *ctx) -{ - switch (gcli_config_get_forge_type(ctx)) { - case GCLI_FORGE_GITHUB: - return github_get_apibase(ctx); - case GCLI_FORGE_GITEA: - return gitea_get_apibase(ctx); - case GCLI_FORGE_GITLAB: - return gitlab_get_apibase(ctx); - default: - assert(0 && "Not reached"); - } + return !cfg->colours_disabled; } diff --git a/src/cmd/colour.c b/src/cmd/colour.c index 836a54ec..ca84d628 100644 --- a/src/cmd/colour.c +++ b/src/cmd/colour.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include diff --git a/src/cmd/comment.c b/src/cmd/comment.c index 0990bbbe..20463444 100644 --- a/src/cmd/comment.c +++ b/src/cmd/comment.c @@ -30,12 +30,12 @@ #include #include +#include #include #include #include #include -#include #include #ifdef HAVE_GETOPT_H diff --git a/src/cmd/config.c b/src/cmd/config.c index 226b5704..1e9d4bb5 100644 --- a/src/cmd/config.c +++ b/src/cmd/config.c @@ -32,10 +32,10 @@ #endif #include +#include #include #include -#include #include #include diff --git a/src/cmd/editor.c b/src/cmd/editor.c index c0512778..244359e7 100644 --- a/src/cmd/editor.c +++ b/src/cmd/editor.c @@ -27,10 +27,9 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include -#include - #include #include diff --git a/src/cmd/forks.c b/src/cmd/forks.c index d290fbf9..64d5d596 100644 --- a/src/cmd/forks.c +++ b/src/cmd/forks.c @@ -36,11 +36,12 @@ #include #include +#include +#include #include +#include #include -#include -#include #include static void @@ -171,12 +172,10 @@ subcommand_forks_create(int argc, char *argv[]) } if (!in) { - sn_sv act; - if (gcli_config_get_account(g_clictx, &act) < 0) { + if ((in = gcli_config_get_account_name(g_clictx)) == NULL) { errx(1, "error: could not fetch account: %s", gcli_get_error(g_clictx)); } - in = sn_sv_to_cstr(act); } gcli_gitconfig_add_fork_remote(in, repo); diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index 2fe749db..a5f803f5 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -54,8 +55,6 @@ #include #include -#include - static void usage(void); static int @@ -159,10 +158,14 @@ main(int argc, char *argv[]) { char const *errmsg; - errmsg = gcli_init(&g_clictx); + errmsg = gcli_init(&g_clictx, gcli_config_get_forge_type, + gcli_config_get_token, gcli_config_get_apibase); if (errmsg) errx(1, "error: %s", errmsg); + if (gcli_config_init_ctx(g_clictx) < 0) + errx(1, "error: failed to init context: %s", gcli_get_error(g_clictx)); + /* Parse first arguments */ if (gcli_config_parse_args(g_clictx, &argc, &argv)) { usage(); diff --git a/src/cmd/gists.c b/src/cmd/gists.c index 07da14f9..ac1c5df5 100644 --- a/src/cmd/gists.c +++ b/src/cmd/gists.c @@ -30,10 +30,10 @@ #include #include +#include #include #include -#include #include #include diff --git a/src/gitconfig.c b/src/cmd/gitconfig.c similarity index 99% rename from src/gitconfig.c rename to src/cmd/gitconfig.c index 4ff671a7..d83fb747 100644 --- a/src/gitconfig.c +++ b/src/cmd/gitconfig.c @@ -27,9 +27,10 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include +#include + #include -#include #include #include diff --git a/src/cmd/issues.c b/src/cmd/issues.c index 26e40cd3..f11f06af 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -30,12 +30,12 @@ #include #include +#include #include #include #include #include -#include #include #include diff --git a/src/cmd/labels.c b/src/cmd/labels.c index 3a625d29..615a4534 100644 --- a/src/cmd/labels.c +++ b/src/cmd/labels.c @@ -29,10 +29,10 @@ #include -#include #include #include +#include #include #include diff --git a/src/cmd/pipelines.c b/src/cmd/pipelines.c index 7f733964..56359348 100644 --- a/src/cmd/pipelines.c +++ b/src/cmd/pipelines.c @@ -30,11 +30,11 @@ #include #include +#include #include #include #include -#include #include #include diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 6c406d6c..85a74604 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -31,20 +31,19 @@ #include #include +#include #include #include #include +#include #include #include #include #include -#include #include -#include #include #include -#include #ifdef HAVE_GETOPT_H #include @@ -90,7 +89,7 @@ usage(void) fprintf(stderr, " add \n"); fprintf(stderr, " remove \n"); fprintf(stderr, " diff Display changes as diff\n"); - fprintf(stderr, " reviews Display reviews\n"); + fprintf(stderr, "\n"); version(); copyright(); @@ -380,10 +379,10 @@ create_pull(gcli_submit_pull_options opts, int always_yes) static sn_sv pr_try_derive_head(void) { - sn_sv account = {0}; + char const *account; sn_sv branch = {0}; - if (gcli_config_get_account(g_clictx, &account) < 0) { + if ((account = gcli_config_get_account_name(g_clictx)) == NULL) { errx(1, "error: Cannot derive PR head. Please specify --from or set the\n" " account in the users gcli config file.\n" @@ -397,7 +396,7 @@ pr_try_derive_head(void) " are in »detached HEAD« state, checkout the branch you \n" " want to pull request.\n"); - return sn_sv_fmt(SV_FMT":"SV_FMT, SV_ARGS(account), SV_ARGS(branch)); + return sn_sv_fmt("%s:"SV_FMT, account, SV_ARGS(branch)); } static int @@ -773,17 +772,6 @@ handle_pull_actions(int argc, char *argv[], errx(1, "error: failed to reopen pull request: %s", gcli_get_error(g_clictx)); - } else if (strcmp(action, "reviews") == 0) { - /* list reviews */ - gcli_pr_review_list reviews = {0}; - - if (gcli_review_get_reviews(g_clictx, owner, repo, pr, &reviews) < 0) - errx(1, "error: failed to fetch reviews: %s", - gcli_get_error(g_clictx)); - - gcli_review_print_review_table(g_clictx, &reviews); - gcli_review_reviews_free(&reviews); - } else if (strcmp("labels", action) == 0) { const char **add_labels = NULL; size_t add_labels_size = 0; diff --git a/src/cmd/repos.c b/src/cmd/repos.c index a224f772..45b83106 100644 --- a/src/cmd/repos.c +++ b/src/cmd/repos.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -270,10 +271,9 @@ subcommand_repos(int argc, char *argv[]) } if (!owner) - rc = gcli_get_own_repos(g_clictx, n, &repos); - else - rc = gcli_get_repos(g_clictx, owner, n, &repos); + owner = gcli_config_get_account_name(g_clictx); + rc = gcli_get_repos(g_clictx, owner, n, &repos); if (rc < 0) errx(1, "error: failed to fetch repos: %s", gcli_get_error(g_clictx)); diff --git a/src/comments.c b/src/comments.c index a8be6edc..5440632f 100644 --- a/src/comments.c +++ b/src/comments.c @@ -31,7 +31,6 @@ #include #include -#include #include #include #include diff --git a/src/ctx.c b/src/ctx.c index 181c13f2..638cb430 100644 --- a/src/ctx.c +++ b/src/ctx.c @@ -27,6 +27,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include @@ -57,3 +58,35 @@ gcli_error(struct gcli_ctx *ctx, char const *const fmt, ...) return -1; } + +void * +gcli_get_userdata(struct gcli_ctx const *ctx) +{ + return ctx->usrdata; +} + +void +gcli_set_userdata(struct gcli_ctx *ctx, void *usrdata) +{ + ctx->usrdata = usrdata; +} + +char * +gcli_get_apibase(struct gcli_ctx *ctx) +{ + return ctx->get_apibase(ctx); +} + +char * +gcli_get_authheader(struct gcli_ctx *ctx) +{ + char *hdr = NULL; + char *token = ctx->get_token(ctx); + + if (token) { + hdr = gcli_forge(ctx)->make_authheader(ctx, token); + free(token); + } + + return hdr; +} diff --git a/src/curl.c b/src/curl.c index 31d3ea91..9c2f7880 100644 --- a/src/curl.c +++ b/src/curl.c @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -204,7 +203,7 @@ gcli_curl(gcli_ctx *ctx, FILE *stream, char const *url, char const *content_type if (content_type) headers = curl_slist_append(headers, content_type); - auth_header = gcli_config_get_authheader(ctx); + auth_header = gcli_get_authheader(ctx); headers = curl_slist_append(headers, auth_header); curl_easy_setopt(ctx->curl, CURLOPT_URL, url); @@ -332,7 +331,7 @@ gcli_fetch_with_method( if ((rc = gcli_curl_ensure(ctx)) < 0) return rc; - char *auth_header = gcli_config_get_authheader(ctx); + char *auth_header = gcli_get_authheader(ctx); if (sn_verbose()) fprintf(stderr, "info: cURL request %s %s...\n", method, url); @@ -420,7 +419,7 @@ gcli_post_upload(gcli_ctx *ctx, char const *url, char const *content_type, if ((rc = gcli_curl_ensure(ctx)) < 0) return rc; - auth_header = gcli_config_get_authheader(ctx); + auth_header = gcli_get_authheader(ctx); contenttype_header = sn_asprintf("Content-Type: %s", content_type); contentsize_header = sn_asprintf("Content-Length: %zu", @@ -480,7 +479,7 @@ gcli_curl_gitea_upload_attachment(gcli_ctx *ctx, char const *url, if ((rc = gcli_curl_ensure(ctx)) < 0) return rc; - auth_header = gcli_config_get_authheader(ctx); + auth_header = gcli_get_authheader(ctx); if (sn_verbose()) fprintf(stderr, "info: cURL upload POST %s...\n", url); @@ -604,7 +603,7 @@ gcli_fetch_list(gcli_ctx *ctx, char *url, gcli_fetch_list_ctx *fl) struct json_stream stream = {0}; json_open_buffer(&stream, buffer.data, buffer.length); - fl->parse(ctx, &stream, fl->listp, fl->sizep); + rc = fl->parse(ctx, &stream, fl->listp, fl->sizep); if (fl->filter) fl->filter(fl->listp, fl->sizep, fl->userdata); diff --git a/src/forges.c b/src/forges.c index e269489f..b24a6986 100644 --- a/src/forges.c +++ b/src/forges.c @@ -29,7 +29,6 @@ #include -#include #include #include @@ -125,7 +124,6 @@ github_forge_descriptor = .create_label = github_create_label, .delete_label = github_delete_label, .get_repos = github_get_repos, - .get_own_repos = github_get_own_repos, .get_reviews = github_review_get_reviews, .repo_create = github_repo_create, .repo_delete = github_repo_delete, @@ -136,8 +134,7 @@ github_forge_descriptor = .get_notifications = github_get_notifications, .notification_mark_as_read = github_notification_mark_as_read, - .get_authheader = github_get_authheader, - .get_account = github_get_account, + .make_authheader = github_make_authheader, .get_api_error_string = github_api_error_string, .user_object_key = "login", .html_url_key = "html_url", @@ -191,14 +188,12 @@ gitlab_forge_descriptor = .create_label = gitlab_create_label, .delete_label = gitlab_delete_label, .get_repos = gitlab_get_repos, - .get_own_repos = gitlab_get_own_repos, .get_reviews = gitlab_review_get_reviews, .repo_create = gitlab_repo_create, .repo_delete = gitlab_repo_delete, .get_notifications = gitlab_get_notifications, .notification_mark_as_read = gitlab_notification_mark_as_read, - .get_authheader = gitlab_get_authheader, - .get_account = gitlab_get_account, + .make_authheader = gitlab_make_authheader, .get_sshkeys = gitlab_get_sshkeys, .add_sshkey = gitlab_add_sshkey, .delete_sshkey = gitlab_delete_sshkey, @@ -257,7 +252,6 @@ gitea_forge_descriptor = .pull_add_labels = gitea_issue_add_labels, .pull_remove_labels = gitea_issue_remove_labels, .get_repos = gitea_get_repos, - .get_own_repos = gitea_get_own_repos, .repo_create = gitea_repo_create, .repo_delete = gitea_repo_delete, @@ -265,8 +259,7 @@ gitea_forge_descriptor = .add_sshkey = gitea_add_sshkey, .delete_sshkey = gitea_delete_sshkey, - .get_authheader = gitea_get_authheader, - .get_account = gitea_get_account, + .make_authheader = gitea_make_authheader, .get_api_error_string = github_api_error_string, /* hack! */ .user_object_key = "username", .html_url_key = "web_url", @@ -281,7 +274,7 @@ gitea_forge_descriptor = gcli_forge_descriptor const * gcli_forge(gcli_ctx *ctx) { - switch (gcli_config_get_forge_type(ctx)) { + switch (ctx->get_forge_type(ctx)) { case GCLI_FORGE_GITHUB: return &github_forge_descriptor; case GCLI_FORGE_GITLAB: diff --git a/src/gcli.c b/src/gcli.c index 27c67169..8b6e2fee 100644 --- a/src/gcli.c +++ b/src/gcli.c @@ -34,14 +34,16 @@ #include char const * -gcli_init(gcli_ctx **ctx) +gcli_init(gcli_ctx **ctx, gcli_forge_type (*get_forge_type)(gcli_ctx *), + char *(*get_token)(gcli_ctx *), char *(*get_apibase)(gcli_ctx *)) { *ctx = calloc(sizeof (struct gcli_ctx), 1); if (!(*ctx)) return strerror(errno); - if (gcli_config_init_ctx(*ctx) < 0) - return (*ctx)->last_error; /* TODO: cleanup */ + (*ctx)->get_forge_type = get_forge_type; + (*ctx)->get_token = get_token; + (*ctx)->get_apibase = get_apibase; return NULL; } diff --git a/src/gitea/config.c b/src/gitea/config.c index d68a2b9a..748ae1ea 100644 --- a/src/gitea/config.c +++ b/src/gitea/config.c @@ -28,78 +28,12 @@ */ #include -#include #include -static sn_sv -gitea_default_account_name(gcli_ctx *ctx) -{ - sn_sv section_name; - - /* Use default override account */ - section_name = gcli_config_get_override_default_account(ctx); - - /* If not manually overridden */ - if (sn_sv_null(section_name)) { - section_name = gcli_config_find_by_key( - ctx, - SV("defaults"), - "gitea-default-account"); - - /* Welp, no luck here */ - if (sn_sv_null(section_name)) - warnx("Config file does not name a default Gitea account name."); - } - - return section_name; -} - -char * -gitea_get_apibase(gcli_ctx *ctx) -{ - sn_sv const account = gitea_default_account_name(ctx); - if (sn_sv_null(account)) - goto default_val; - - sn_sv const api_base = gcli_config_find_by_key(ctx, account, "apibase"); - if (sn_sv_null(api_base)) - goto default_val; - - return sn_sv_to_cstr(api_base); - -default_val: - return "https://codeberg.org/api/v1"; -} - char * -gitea_get_authheader(gcli_ctx *ctx) +gitea_make_authheader(gcli_ctx *ctx, char const *token) { - sn_sv const account = gitea_default_account_name(ctx); - if (sn_sv_null(account)) - return NULL; - - sn_sv const token = gcli_config_find_by_key(ctx, account, "token");; - if (sn_sv_null(token)) { - warnx("Missing Gitea token"); - return NULL; - } - - return sn_asprintf("Authorization: token "SV_FMT, SV_ARGS(token)); -} - -int -gitea_get_account(gcli_ctx *ctx, sn_sv *out) -{ - sn_sv const section = gitea_default_account_name(ctx); - if (sn_sv_null(section)) - return gcli_error(ctx, "no default gitea account"); - - sn_sv const account = gcli_config_find_by_key(ctx, section, "account");; - if (!account.length) - return gcli_error(ctx, "missing account name for default gitea account"); - - *out = account; - - return 0; + (void) ctx; + return sn_asprintf("Authorization: %s", token); } diff --git a/src/gitea/issues.c b/src/gitea/issues.c index 970dd03e..dd6f87a6 100644 --- a/src/gitea/issues.c +++ b/src/gitea/issues.c @@ -73,11 +73,8 @@ gitea_issue_patch_state(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/repos/%s/%s/issues/%d", - gitea_get_apibase(ctx), - e_owner, e_repo, - issue_number); + url = sn_asprintf("%s/repos/%s/%s/issues/%d", gcli_get_apibase(ctx), + e_owner, e_repo, issue_number); data = sn_asprintf("{ \"state\": \"%s\"}", state); rc = gcli_fetch_with_method(ctx, "PATCH", url, data, NULL, NULL); @@ -122,9 +119,8 @@ gitea_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/repos/%s/%s/issues/%d", - gitea_get_apibase(ctx), e_owner, e_repo, issue_number); + url = sn_asprintf("%s/repos/%s/%s/issues/%d", gcli_get_apibase(ctx), + e_owner, e_repo, issue_number); rc = gcli_fetch_with_method(ctx, "PATCH", url, post_fields, NULL, NULL); @@ -208,8 +204,8 @@ gitea_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, list = sn_join_with((char const **)ids, labels_size, ","); data = sn_asprintf("{ \"labels\": [%s] }", list); - url = sn_asprintf("%s/repos/%s/%s/issues/%d/labels", - gitea_get_apibase(ctx), owner, repo, issue); + url = sn_asprintf("%s/repos/%s/%s/issues/%d/labels", gcli_get_apibase(ctx), + owner, repo, issue); rc = gcli_fetch_with_method(ctx, "POST", url, data, NULL, NULL); @@ -238,7 +234,7 @@ gitea_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, char *url = NULL; url = sn_asprintf("%s/repos/%s/%s/issues/%d/labels/%s", - gitea_get_apibase(ctx), owner, repo, issue, ids[i]); + gcli_get_apibase(ctx), owner, repo, issue, ids[i]); rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); diff --git a/src/gitea/labels.c b/src/gitea/labels.c index c53f318a..b5d5ccdc 100644 --- a/src/gitea/labels.c +++ b/src/gitea/labels.c @@ -79,8 +79,7 @@ gitea_delete_label(gcli_ctx *ctx, char const *owner, char const *repo, return gcli_error(ctx, "label '%s' does not exist", label); /* DELETE /repos/{owner}/{repo}/labels/{} */ - url = sn_asprintf("%s/repos/%s/%s/labels/%d", - gitea_get_apibase(ctx), + url = sn_asprintf("%s/repos/%s/%s/labels/%d", gcli_get_apibase(ctx), owner, repo, id); rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); diff --git a/src/gitea/milestones.c b/src/gitea/milestones.c index f07dfd78..cab50eec 100644 --- a/src/gitea/milestones.c +++ b/src/gitea/milestones.c @@ -30,7 +30,6 @@ #include #include -#include #include #include diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index ec314922..17351865 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -27,7 +27,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include diff --git a/src/gitea/releases.c b/src/gitea/releases.c index 7f66f3b7..091b7970 100644 --- a/src/gitea/releases.c +++ b/src/gitea/releases.c @@ -30,7 +30,6 @@ #include #include -#include #include #include diff --git a/src/github/checks.c b/src/github/checks.c index c83dc29a..96ab3d07 100644 --- a/src/github/checks.c +++ b/src/github/checks.c @@ -31,7 +31,6 @@ #include #include -#include #include #include #include diff --git a/src/github/comments.c b/src/github/comments.c index dbefcac0..90f7a09e 100644 --- a/src/github/comments.c +++ b/src/github/comments.c @@ -27,7 +27,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include diff --git a/src/github/config.c b/src/github/config.c index f177b294..edcc0f68 100644 --- a/src/github/config.c +++ b/src/github/config.c @@ -28,72 +28,11 @@ */ #include -#include #include -static sn_sv -github_default_account_name(gcli_ctx *ctx) -{ - sn_sv section_name; - - section_name = gcli_config_get_override_default_account(ctx); - - if (sn_sv_null(section_name)) { - section_name = gcli_config_find_by_key( - ctx, - SV("defaults"), - "github-default-account"); - - if (sn_sv_null(section_name)) - warnx("Config file does not name a default GitHub account name."); - } - - return section_name; -} - -char * -github_get_apibase(gcli_ctx *ctx) -{ - sn_sv account_name = github_default_account_name(ctx); - if (sn_sv_null(account_name)) - goto default_val; - - sn_sv api_base = gcli_config_find_by_key(ctx, account_name, "apibase"); - - if (sn_sv_null(api_base)) - goto default_val; - - return sn_sv_to_cstr(api_base); - -default_val: - return "https://api.github.com"; -} - char * -github_get_authheader(gcli_ctx *ctx) +github_make_authheader(gcli_ctx *ctx, char const *token) { - sn_sv const account = github_default_account_name(ctx); - if (sn_sv_null(account)) - return NULL; - - sn_sv const token = gcli_config_find_by_key(ctx, account, "token"); - if (sn_sv_null(token)) - errx(1, "Missing Github token"); - return sn_asprintf("Authorization: token "SV_FMT, SV_ARGS(token)); -} - -int -github_get_account(gcli_ctx *ctx, sn_sv *out) -{ - sn_sv const section = github_default_account_name(ctx); - if (sn_sv_null(section)) - return gcli_error(ctx, "no default github account"); - - sn_sv const account = gcli_config_find_by_key(ctx, section, "account"); - if (!account.length) - return gcli_error(ctx, "Missing Github account name"); - - *out = account; - - return 0; + (void) ctx; + return sn_asprintf("Authorization: token %s", token); } diff --git a/src/github/forks.c b/src/github/forks.c index 095e9278..68373f49 100644 --- a/src/github/forks.c +++ b/src/github/forks.c @@ -27,7 +27,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include diff --git a/src/github/gists.c b/src/github/gists.c index aa49950b..177a8673 100644 --- a/src/github/gists.c +++ b/src/github/gists.c @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -81,12 +80,9 @@ gcli_get_gists(gcli_ctx *ctx, char const *user, int const max, }; if (user) - url = sn_asprintf( - "%s/users/%s/gists", - github_get_apibase(ctx), - user); + url = sn_asprintf("%s/users/%s/gists", gcli_get_apibase(ctx), user); else - url = sn_asprintf("%s/gists", github_get_apibase(ctx)); + url = sn_asprintf("%s/gists", gcli_get_apibase(ctx)); return gcli_fetch_list(ctx, url, &fl); } @@ -98,7 +94,7 @@ gcli_get_gist(gcli_ctx *ctx, char const *gist_id, gcli_gist *out) gcli_fetch_buffer buffer = {0}; int rc = 0; - url = sn_asprintf("%s/gists/%s", github_get_apibase(ctx), gist_id); + url = sn_asprintf("%s/gists/%s", gcli_get_apibase(ctx), gist_id); rc = gcli_fetch(ctx, url, NULL, &buffer); if (rc == 0) { @@ -169,7 +165,7 @@ gcli_create_gist(gcli_ctx *ctx, gcli_new_gist opts) */ /* TODO: Escape gist_description and file_name */ - url = sn_asprintf("%s/gists", github_get_apibase(ctx)); + url = sn_asprintf("%s/gists", gcli_get_apibase(ctx)); post_data = sn_asprintf( "{\"description\":\"%s\",\"public\":true,\"files\":" "{\"%s\": {\"content\":\""SV_FMT"\"}}}", @@ -194,10 +190,7 @@ gcli_delete_gist(gcli_ctx *ctx, char const *gist_id) gcli_fetch_buffer buffer = {0}; int rc = 0; - url = sn_asprintf( - "%s/gists/%s", - github_get_apibase(ctx), - gist_id); + url = sn_asprintf("%s/gists/%s", gcli_get_apibase(ctx), gist_id); rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, &buffer); diff --git a/src/github/issues.c b/src/github/issues.c index f0bde57a..6d8b0d02 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -27,7 +27,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include diff --git a/src/github/labels.c b/src/github/labels.c index 55def263..46a344a3 100644 --- a/src/github/labels.c +++ b/src/github/labels.c @@ -28,7 +28,6 @@ */ #include -#include #include #include diff --git a/src/github/milestones.c b/src/github/milestones.c index c82325db..3d533eaa 100644 --- a/src/github/milestones.c +++ b/src/github/milestones.c @@ -29,7 +29,6 @@ #include -#include #include #include #include diff --git a/src/github/pulls.c b/src/github/pulls.c index e0fde179..e01f2401 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -27,9 +27,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include -#include #include #include #include @@ -150,9 +148,8 @@ github_pull_delete_head_branch(gcli_ctx *ctx, char const *owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/repos/%s/%s/git/refs/heads/%s", - github_get_apibase(ctx), e_owner, e_repo, - head_branch); + url = sn_asprintf("%s/repos/%s/%s/git/refs/heads/%s", gcli_get_apibase(ctx), + e_owner, e_repo, head_branch); rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); diff --git a/src/github/releases.c b/src/github/releases.c index 50bae7ba..9a0f5373 100644 --- a/src/github/releases.c +++ b/src/github/releases.c @@ -27,7 +27,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include diff --git a/src/github/repos.c b/src/github/repos.c index 4619380f..7253690d 100644 --- a/src/github/repos.c +++ b/src/github/repos.c @@ -27,7 +27,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include diff --git a/src/github/review.c b/src/github/review.c index 68bd1994..ba468ca1 100644 --- a/src/github/review.c +++ b/src/github/review.c @@ -28,7 +28,6 @@ */ #include -#include #include #include diff --git a/src/github/status.c b/src/github/status.c index e1360fd5..8e0d4757 100644 --- a/src/github/status.c +++ b/src/github/status.c @@ -29,7 +29,6 @@ #include #include -#include #include #include diff --git a/src/gitlab/comments.c b/src/gitlab/comments.c index 94e8ca50..6137e10c 100644 --- a/src/gitlab/comments.c +++ b/src/gitlab/comments.c @@ -59,7 +59,7 @@ gitlab_perform_submit_comment(gcli_ctx *ctx, gcli_submit_comment_opts opts, SV_ARGS(opts.message)); char *url = sn_asprintf( "%s/projects/%s%%2F%s/%s/%d/notes", - gitlab_get_apibase(ctx), + gcli_get_apibase(ctx), e_owner, e_repo, type, opts.target_id); rc = gcli_fetch_with_method(ctx, "POST", url, post_fields, NULL, out); @@ -88,7 +88,7 @@ gitlab_get_mr_comments(gcli_ctx *ctx, char const *owner, char const *repo, char *url = sn_asprintf( "%s/projects/%s%%2F%s/merge_requests/%d/notes", - gitlab_get_apibase(ctx), + gcli_get_apibase(ctx), e_owner, e_repo, mr); free(e_owner); @@ -113,7 +113,7 @@ gitlab_get_issue_comments(gcli_ctx *ctx, char const *owner, char const *repo, char *url = sn_asprintf( "%s/projects/%s%%2F%s/issues/%d/notes", - gitlab_get_apibase(ctx), + gcli_get_apibase(ctx), e_owner, e_repo, issue); free(e_owner); free(e_repo); diff --git a/src/gitlab/config.c b/src/gitlab/config.c index e888b784..dc911f16 100644 --- a/src/gitlab/config.c +++ b/src/gitlab/config.c @@ -27,76 +27,13 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include -static sn_sv -gitlab_default_account_name(gcli_ctx *ctx) -{ - sn_sv section_name; - - /* Use default override account */ - section_name = gcli_config_get_override_default_account(ctx); - - /* If not manually overridden */ - if (sn_sv_null(section_name)) { - section_name = gcli_config_find_by_key( - ctx, - SV("defaults"), - "gitlab-default-account"); - - /* Welp, no luck here */ - if (sn_sv_null(section_name)) - warnx("Config file does not name a default GitLab account name."); - } - - return section_name; -} - char * -gitlab_get_apibase(gcli_ctx *ctx) +gitlab_make_authheader(gcli_ctx *ctx, char const *token) { - sn_sv account = gitlab_default_account_name(ctx); - if (sn_sv_null(account)) - goto default_val; - - sn_sv api_base = gcli_config_find_by_key(ctx, account, "apibase"); - if (sn_sv_null(api_base)) - goto default_val; - - return sn_sv_to_cstr(api_base); - -default_val: - return "https://gitlab.com/api/v4"; -} - -char * -gitlab_get_authheader(gcli_ctx *ctx) -{ - sn_sv const account = gitlab_default_account_name(ctx); - if (sn_sv_null(account)) - return NULL; - - sn_sv const token = gcli_config_find_by_key(ctx, account, "token"); - if (sn_sv_null(token)) - errx(1, "Missing GitLab token"); - return sn_asprintf("PRIVATE-TOKEN: "SV_FMT, SV_ARGS(token)); -} - -int -gitlab_get_account(gcli_ctx *ctx, sn_sv *out) -{ - sn_sv const section = gitlab_default_account_name(ctx); - if (sn_sv_null(section)) - return gcli_error(ctx, "no default gitlab account"); - - sn_sv const account = gcli_config_find_by_key(ctx, section, "account"); - if (sn_sv_null(account)) - return gcli_error(ctx, "missing account name in default gitlab account"); - - *out = account; - - return 0; + (void) ctx; + return sn_asprintf("PRIVATE-TOKEN: %s", token); } diff --git a/src/gitlab/forks.c b/src/gitlab/forks.c index d8fe4021..a0a63d1e 100644 --- a/src/gitlab/forks.c +++ b/src/gitlab/forks.c @@ -56,10 +56,8 @@ gitlab_get_forks(gcli_ctx *ctx, char const *owner, char const *repo, *list = (gcli_fork_list) {0}; - url = sn_asprintf( - "%s/projects/%s%%2F%s/forks", - gitlab_get_apibase(ctx), - e_owner, e_repo); + url = sn_asprintf("%s/projects/%s%%2F%s/forks", gcli_get_apibase(ctx), + e_owner, e_repo); free(e_owner); free(e_repo); @@ -81,8 +79,7 @@ gitlab_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/fork", - gitlab_get_apibase(ctx), + url = sn_asprintf("%s/projects/%s%%2F%s/fork", gcli_get_apibase(ctx), e_owner, e_repo); if (_in) { in = gcli_json_escape(SV((char *)_in)); diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index 76c3c4f8..b0e36b6f 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -27,7 +27,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include @@ -73,12 +72,9 @@ gitlab_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, free(tmp); } - url = sn_asprintf( - "%s/projects/%s%%2F%s/issues%s%s", - gitlab_get_apibase(ctx), - e_owner, e_repo, - details->all ? "" : "?state=opened", - e_author ? e_author : ""); + url = sn_asprintf("%s/projects/%s%%2F%s/issues%s%s", gcli_get_apibase(ctx), + e_owner, e_repo, details->all ? "" : "?state=opened", + e_author ? e_author : ""); free(e_author); free(e_owner); @@ -101,11 +97,8 @@ gitlab_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/projects/%s%%2F%s/issues/%d", - gitlab_get_apibase(ctx), - e_owner, e_repo, - issue_number); + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gcli_get_apibase(ctx), + e_owner, e_repo, issue_number); rc = gcli_fetch(ctx, url, NULL, &buffer); if (rc == 0) { @@ -136,11 +129,8 @@ gitlab_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/projects/%s%%2F%s/issues/%d", - gitlab_get_apibase(ctx), - e_owner, e_repo, - issue_number); + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gcli_get_apibase(ctx), + e_owner, e_repo, issue_number); data = sn_asprintf("{ \"state_event\": \"close\"}"); rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); @@ -166,11 +156,8 @@ gitlab_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/projects/%s%%2F%s/issues/%d", - gitlab_get_apibase(ctx), - e_owner, e_repo, - issue_number); + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gcli_get_apibase(ctx), + e_owner, e_repo, issue_number); data = sn_asprintf("{ \"state_event\": \"reopen\"}"); rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); @@ -196,9 +183,8 @@ gitlab_perform_submit_issue(gcli_ctx *ctx, gcli_submit_issue_options opts, char *post_fields = sn_asprintf( "{ \"title\": \""SV_FMT"\", \"description\": \""SV_FMT"\" }", SV_ARGS(e_title), SV_ARGS(e_body)); - char *url = sn_asprintf( - "%s/projects/%s%%2F%s/issues", - gitlab_get_apibase(ctx), e_owner, e_repo); + char *url = sn_asprintf("%s/projects/%s%%2F%s/issues", gcli_get_apibase(ctx), + e_owner, e_repo); rc = gcli_fetch_with_method(ctx, "POST", url, post_fields, NULL, out); @@ -224,8 +210,8 @@ gitlab_user_id(gcli_ctx *ctx, char const *user_name) e_username = gcli_urlencode(user_name); - url = sn_asprintf("%s/users?username=%s", - gitlab_get_apibase(ctx), e_username); + url = sn_asprintf("%s/users?username=%s", gcli_get_apibase(ctx), + e_username); uid = gcli_fetch(ctx, url, NULL, &buffer); if (uid == 0) { @@ -265,8 +251,7 @@ gitlab_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", - gitlab_get_apibase(ctx), + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gcli_get_apibase(ctx), e_owner, e_repo, issue_number); post_data = sn_asprintf("{ \"assignee_ids\": [ %d ] }", assignee_uid); rc = gcli_fetch_with_method(ctx, "PUT", url, post_data, NULL, NULL); @@ -289,8 +274,8 @@ gitlab_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, char *list = NULL; int rc = 0; - url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", - gitlab_get_apibase(ctx), owner, repo, issue); + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gcli_get_apibase(ctx), + owner, repo, issue); list = sn_join_with(labels, labels_size, ","); data = sn_asprintf("{ \"add_labels\": \"%s\"}", list); @@ -314,8 +299,8 @@ gitlab_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, char *list = NULL; int rc = 0; - url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", - gitlab_get_apibase(ctx), owner, repo, issue); + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gcli_get_apibase(ctx), + owner, repo, issue); list = sn_join_with(labels, labels_size, ","); data = sn_asprintf("{ \"remove_labels\": \"%s\"}", list); @@ -339,9 +324,8 @@ gitlab_issue_set_milestone(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/projects/%s%%2F%s/issues/%d?milestone_id=%d", - gitlab_get_apibase(ctx), e_owner, e_repo, issue, milestone); + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d?milestone_id=%d", + gcli_get_apibase(ctx), e_owner, e_repo, issue, milestone); rc = gcli_fetch_with_method(ctx, "PUT", url, NULL, NULL, NULL); @@ -373,9 +357,8 @@ gitlab_issue_clear_milestone(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/projects/%s%%2F%s/issues/%d", - gitlab_get_apibase(ctx), e_owner, e_repo, issue); + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gcli_get_apibase(ctx), + e_owner, e_repo, issue); payload = sn_asprintf("{ \"milestone_id\": null }"); rc = gcli_fetch_with_method(ctx, "PUT", url, payload, NULL, NULL); diff --git a/src/gitlab/labels.c b/src/gitlab/labels.c index d0495ced..67421e6e 100644 --- a/src/gitlab/labels.c +++ b/src/gitlab/labels.c @@ -49,8 +49,8 @@ gitlab_get_labels(gcli_ctx *ctx, char const *owner, char const *repo, *out = (gcli_label_list) {0}; - url = sn_asprintf("%s/projects/%s%%2F%s/labels", - gitlab_get_apibase(ctx), owner, repo); + url = sn_asprintf("%s/projects/%s%%2F%s/labels", gcli_get_apibase(ctx), + owner, repo); return gcli_fetch_list(ctx, url, &fl); } @@ -68,8 +68,7 @@ gitlab_create_label(gcli_ctx *ctx, char const *owner, char const *repo, struct json_stream stream = {0}; int rc = 0; - url = sn_asprintf("%s/projects/%s%%2F%s/labels", - gitlab_get_apibase(ctx), + url = sn_asprintf("%s/projects/%s%%2F%s/labels", gcli_get_apibase(ctx), owner, repo); lname_escaped = gcli_json_escape(SV(label->name)); @@ -111,8 +110,7 @@ gitlab_delete_label(gcli_ctx *ctx, char const *owner, char const *repo, int rc; e_label = gcli_urlencode(label); - url = sn_asprintf("%s/projects/%s%%2F%s/labels/%s", - gitlab_get_apibase(ctx), + url = sn_asprintf("%s/projects/%s%%2F%s/labels/%s", gcli_get_apibase(ctx), owner, repo, e_label); rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index f42cd63d..db32f163 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -97,13 +97,12 @@ gitlab_get_mrs(gcli_ctx *ctx, char const *owner, char const *repo, * to make sure we insert the right character into the param * list. Again, note that this behaviour differs quite * substantially from Github's. */ - url = sn_asprintf( - "%s/projects/%s%%2F%s/merge_requests%s%s%s", - gitlab_get_apibase(ctx), - e_owner, e_repo, - e_author ? e_author : "", - e_author ? (details->all ? "" : "&") : (details->all ? "" : "?"), - details->all ? "" : "state=opened"); + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests%s%s%s", + gcli_get_apibase(ctx), + e_owner, e_repo, + e_author ? e_author : "", + e_author ? (details->all ? "" : "&") : (details->all ? "" : "?"), + details->all ? "" : "state=opened"); free(e_author); free(e_owner); @@ -147,14 +146,13 @@ gitlab_mr_merge(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); /* PUT /projects/:id/merge_requests/:merge_request_iid/merge */ - url = sn_asprintf( - "%s/projects/%s%%2F%s/merge_requests/%d/merge" - "?squash=%s" - "&should_remove_source_branch=%s", - gitlab_get_apibase(ctx), - e_owner, e_repo, mr_number, - squash ? "true" : "false", - delete_source ? "true" : "false"); + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d/merge" + "?squash=%s" + "&should_remove_source_branch=%s", + gcli_get_apibase(ctx), + e_owner, e_repo, mr_number, + squash ? "true" : "false", + delete_source ? "true" : "false"); rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, &buffer); @@ -180,10 +178,9 @@ gitlab_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); /* GET /projects/:id/merge_requests/:merge_request_iid */ - url = sn_asprintf( - "%s/projects/%s%%2F%s/merge_requests/%d", - gitlab_get_apibase(ctx), - e_owner, e_repo, pr_number); + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", + gcli_get_apibase(ctx), + e_owner, e_repo, pr_number); free(e_owner); free(e_repo); @@ -220,10 +217,8 @@ gitlab_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); /* GET /projects/:id/merge_requests/:merge_request_iid/commits */ - url = sn_asprintf( - "%s/projects/%s%%2F%s/merge_requests/%d/commits", - gitlab_get_apibase(ctx), - e_owner, e_repo, pr_number); + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d/commits", + gcli_get_apibase(ctx), e_owner, e_repo, pr_number); free(e_owner); free(e_repo); @@ -244,10 +239,8 @@ gitlab_mr_close(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/projects/%s%%2F%s/merge_requests/%d", - gitlab_get_apibase(ctx), - e_owner, e_repo, pr_number); + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", + gcli_get_apibase(ctx), e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state_event\": \"close\"}"); rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); @@ -273,10 +266,8 @@ gitlab_mr_reopen(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/projects/%s%%2F%s/merge_requests/%d", - gitlab_get_apibase(ctx), - e_owner, e_repo, pr_number); + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", + gcli_get_apibase(ctx), e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state_event\": \"reopen\"}"); rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); @@ -355,9 +346,8 @@ gitlab_perform_submit_mr(gcli_ctx *ctx, gcli_submit_pull_options opts) char *e_owner = gcli_urlencode_sv(source_owner).data; char *e_repo = gcli_urlencode(opts.repo); - char *url = sn_asprintf( - "%s/projects/%s%%2F%s/merge_requests", - gitlab_get_apibase(ctx), + char *url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests", + gcli_get_apibase(ctx), e_owner, e_repo); /* perform request */ @@ -388,7 +378,7 @@ gitlab_mr_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", - gitlab_get_apibase(ctx), owner, repo, mr); + gcli_get_apibase(ctx), owner, repo, mr); list = sn_join_with(labels, labels_size, ","); data = sn_asprintf("{ \"add_labels\": \"%s\"}", list); @@ -413,7 +403,7 @@ gitlab_mr_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", - gitlab_get_apibase(ctx), owner, repo, mr); + gcli_get_apibase(ctx), owner, repo, mr); list = sn_join_with(labels, labels_size, ","); data = sn_asprintf("{ \"remove_labels\": \"%s\"}", list); @@ -436,7 +426,7 @@ gitlab_mr_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", - gitlab_get_apibase(ctx), owner, repo, mr); + gcli_get_apibase(ctx), owner, repo, mr); data = sn_asprintf("{ \"milestone_id\": \"%d\"}", milestone_id); diff --git a/src/gitlab/milestones.c b/src/gitlab/milestones.c index 716884ef..54872222 100644 --- a/src/gitlab/milestones.c +++ b/src/gitlab/milestones.c @@ -59,8 +59,8 @@ gitlab_get_milestones(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/milestones", - gitlab_get_apibase(ctx), e_owner, e_repo); + url = sn_asprintf("%s/projects/%s%%2F%s/milestones", gcli_get_apibase(ctx), + e_owner, e_repo); free(e_owner); free(e_repo); @@ -80,8 +80,8 @@ gitlab_get_milestone(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d", - gitlab_get_apibase(ctx), e_owner, e_repo, milestone); + url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d", gcli_get_apibase(ctx), + e_owner, e_repo, milestone); rc = gcli_fetch(ctx, url, NULL, &buffer); if (rc == 0) { @@ -109,7 +109,7 @@ gitlab_milestone_get_issues(gcli_ctx *ctx, char const *const owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d/issues", - gitlab_get_apibase(ctx), e_owner, e_repo, milestone); + gcli_get_apibase(ctx), e_owner, e_repo, milestone); free(e_repo); free(e_owner); @@ -128,8 +128,8 @@ gitlab_create_milestone(gcli_ctx *ctx, e_owner = gcli_urlencode(args->owner); e_repo = gcli_urlencode(args->repo); - url = sn_asprintf("%s/projects/%s%%2F%s/milestones", - gitlab_get_apibase(ctx), e_owner, e_repo); + url = sn_asprintf("%s/projects/%s%%2F%s/milestones", gcli_get_apibase(ctx), + e_owner, e_repo); /* Escape and prepare the description if needed */ if (args->description) { @@ -168,8 +168,8 @@ gitlab_delete_milestone(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d", - gitlab_get_apibase(ctx), e_owner, e_repo, milestone); + url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d", gcli_get_apibase(ctx), + e_owner, e_repo, milestone); rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); @@ -197,7 +197,7 @@ gitlab_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d?due_date=%s", - gitlab_get_apibase(ctx), e_owner, e_repo, milestone, + gcli_get_apibase(ctx), e_owner, e_repo, milestone, norm_date); rc = gcli_fetch_with_method(ctx, "PUT", url, "", NULL, NULL); diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index 230cfacc..7842171e 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -63,8 +63,8 @@ gitlab_get_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, { char *url = NULL; - url = sn_asprintf("%s/projects/%s%%2F%s/pipelines", - gitlab_get_apibase(ctx), owner, repo); + url = sn_asprintf("%s/projects/%s%%2F%s/pipelines", gcli_get_apibase(ctx), + owner, repo); return fetch_pipelines(ctx, url, max, list); } @@ -76,7 +76,7 @@ gitlab_get_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, char *url = NULL; url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d/pipelines", - gitlab_get_apibase(ctx), owner, repo, mr_id); + gcli_get_apibase(ctx), owner, repo, mr_id); /* fetch everything */ return fetch_pipelines(ctx, url, -1, list); @@ -113,7 +113,7 @@ gitlab_get_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, }; url = sn_asprintf("%s/projects/%s%%2F%s/pipelines/%ld/jobs", - gitlab_get_apibase(ctx), owner, repo, pipeline); + gcli_get_apibase(ctx), owner, repo, pipeline); return gcli_fetch_list(ctx, url, &fl); } @@ -152,7 +152,7 @@ gitlab_job_get_log(gcli_ctx *ctx, char const *owner, char const *repo, int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld/trace", - gitlab_get_apibase(ctx), owner, repo, job_id); + gcli_get_apibase(ctx), owner, repo, job_id); rc = gcli_curl(ctx, stream, url, NULL); @@ -169,8 +169,8 @@ gitlab_get_job(gcli_ctx *ctx, char const *owner, char const *repo, char *url = NULL; int rc = 0; - url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld", - gitlab_get_apibase(ctx), owner, repo, jid); + url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld", gcli_get_apibase(ctx), + owner, repo, jid); rc = gcli_fetch(ctx, url, NULL, &buffer); if (rc == 0) { @@ -196,7 +196,7 @@ gitlab_job_cancel(gcli_ctx *ctx, char const *owner, char const *repo, int rc = 0; url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld/cancel", - gitlab_get_apibase(ctx), owner, repo, jid); + gcli_get_apibase(ctx), owner, repo, jid); rc = gcli_fetch_with_method(ctx, "POST", url, NULL, NULL, NULL); free(url); @@ -211,8 +211,8 @@ gitlab_job_retry(gcli_ctx *ctx, char const *owner, char const *repo, int rc = 0; char *url = NULL; - url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld/retry", - gitlab_get_apibase(ctx), owner, repo, jid); + url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld/retry", gcli_get_apibase(ctx), + owner, repo, jid); rc = gcli_fetch_with_method(ctx, "POST", url, NULL, NULL, NULL); free(url); @@ -238,8 +238,7 @@ gitlab_job_download_artifacts(gcli_ctx *ctx, char const *owner, e_repo = gcli_urlencode(repo); url = sn_asprintf("%s/projects/%s%%2F%s/jobs/%ld/artifacts", - gitlab_get_apibase(ctx), - e_owner, e_repo, jid); + gcli_get_apibase(ctx), e_owner, e_repo, jid); rc = gcli_curl(ctx, f, url, "application/zip"); diff --git a/src/gitlab/releases.c b/src/gitlab/releases.c index 96ad5d56..3c2a78e7 100644 --- a/src/gitlab/releases.c +++ b/src/gitlab/releases.c @@ -79,10 +79,8 @@ gitlab_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/projects/%s%%2F%s/releases", - gitlab_get_apibase(ctx), - e_owner, e_repo); + url = sn_asprintf("%s/projects/%s%%2F%s/releases", gcli_get_apibase(ctx), + e_owner, e_repo); free(e_owner); free(e_repo); @@ -98,23 +96,22 @@ gitlab_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_create_release(gcli_ctx *ctx, gcli_new_release const *release) { - char *url = NULL; - char *upload_url = NULL; - char *post_data = NULL; - char *name_json = NULL; - char *e_owner = NULL; - char *e_repo = NULL; - char *commitish_json = NULL; - sn_sv escaped_body = {0}; - int rc = 0; + char *url = NULL; + char *upload_url = NULL; + char *post_data = NULL; + char *name_json = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + char *commitish_json = NULL; + sn_sv escaped_body = {0}; + int rc = 0; e_owner = gcli_urlencode(release->owner); e_repo = gcli_urlencode(release->repo); /* https://docs.github.com/en/rest/reference/repos#create-a-release */ - url = sn_asprintf( - "%s/projects/%s%%2F%s/releases", - gitlab_get_apibase(ctx), e_owner, e_repo); + url = sn_asprintf("%s/projects/%s%%2F%s/releases", gcli_get_apibase(ctx), + e_owner, e_repo); escaped_body = gcli_json_escape(release->body); @@ -175,10 +172,8 @@ gitlab_delete_release(gcli_ctx *ctx, char const *owner, char const *repo, char c e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/projects/%s%%2F%s/releases/%s", - gitlab_get_apibase(ctx), - e_owner, e_repo, id); + url = sn_asprintf("%s/projects/%s%%2F%s/releases/%s", gcli_get_apibase(ctx), + e_owner, e_repo, id); rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); diff --git a/src/gitlab/repos.c b/src/gitlab/repos.c index 10e8aa0d..b150e6b4 100644 --- a/src/gitlab/repos.c +++ b/src/gitlab/repos.c @@ -51,10 +51,8 @@ gitlab_get_repo(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf( - "%s/projects/%s%%2F%s", - gitlab_get_apibase(ctx), - e_owner, e_repo); + url = sn_asprintf("%s/projects/%s%%2F%s", gcli_get_apibase(ctx), + e_owner, e_repo); rc = gcli_fetch(ctx, url, NULL, &buffer); @@ -105,7 +103,7 @@ gitlab_get_repos(gcli_ctx *ctx, char const *owner, int const max, }; e_owner = gcli_urlencode(owner); - url = sn_asprintf("%s/users/%s/projects", gitlab_get_apibase(ctx), e_owner); + url = sn_asprintf("%s/users/%s/projects", gcli_get_apibase(ctx), e_owner); free(e_owner); rc = gcli_fetch_list(ctx, url, &fl); @@ -116,24 +114,6 @@ gitlab_get_repos(gcli_ctx *ctx, char const *owner, int const max, return rc; } -int -gitlab_get_own_repos(gcli_ctx *ctx, int const max, gcli_repo_list *const out) -{ - char *_account = NULL; - sn_sv account = {0}; - int rc = 0; - - rc = gitlab_get_account(ctx, &account); - if (rc < 0) - return rc; - - _account = sn_sv_to_cstr(account); - rc = gitlab_get_repos(ctx, _account, max, out); - free(_account); - - return rc; -} - int gitlab_repo_delete(gcli_ctx *ctx, char const *owner, char const *repo) { @@ -145,8 +125,7 @@ gitlab_repo_delete(gcli_ctx *ctx, char const *owner, char const *repo) e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s", - gitlab_get_apibase(ctx), + url = sn_asprintf("%s/projects/%s%%2F%s", gcli_get_apibase(ctx), e_owner, e_repo); rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); @@ -168,7 +147,7 @@ gitlab_repo_create(gcli_ctx *ctx, gcli_repo_create_options const *options, int rc; /* Request preparation */ - url = sn_asprintf("%s/projects", gitlab_get_apibase(ctx)); + url = sn_asprintf("%s/projects", gcli_get_apibase(ctx)); /* TODO: escape the repo name and the description */ data = sn_asprintf("{\"name\": \""SV_FMT"\"," " \"description\": \""SV_FMT"\"," diff --git a/src/gitlab/review.c b/src/gitlab/review.c index bb779888..43af83b3 100644 --- a/src/gitlab/review.c +++ b/src/gitlab/review.c @@ -52,9 +52,8 @@ gitlab_review_get_reviews(gcli_ctx *ctx, char const *owner, char const *repo, .parse = (parsefn)(parse_gitlab_reviews), }; - url = sn_asprintf( - "%s/projects/%s%%2F%s/merge_requests/%d/notes?sort=asc", - gitlab_get_apibase(ctx), owner, repo, pr); + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d/notes?sort=asc", + gcli_get_apibase(ctx), owner, repo, pr); return gcli_fetch_list(ctx, url, &fl); } diff --git a/src/gitlab/snippets.c b/src/gitlab/snippets.c index 4e439d90..3bb8064f 100644 --- a/src/gitlab/snippets.c +++ b/src/gitlab/snippets.c @@ -71,7 +71,7 @@ gcli_snippets_get(gcli_ctx *ctx, int const max, gcli_snippet_list *const out) }; *out = (gcli_snippet_list) {0}; - url = sn_asprintf("%s/snippets", gitlab_get_apibase(ctx)); + url = sn_asprintf("%s/snippets", gcli_get_apibase(ctx)); return gcli_fetch_list(ctx, url, &fl); } @@ -82,7 +82,7 @@ gcli_snippet_delete(gcli_ctx *ctx, char const *snippet_id) int rc = 0; char *url; - url = sn_asprintf("%s/snippets/%s", gitlab_get_apibase(ctx), snippet_id); + url = sn_asprintf("%s/snippets/%s", gcli_get_apibase(ctx), snippet_id); rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); @@ -95,7 +95,7 @@ gcli_snippet_get(gcli_ctx *ctx, char const *snippet_id, FILE *stream) { int rc = 0; char *url = sn_asprintf("%s/snippets/%s/raw", - gitlab_get_apibase(ctx), + gcli_get_apibase(ctx), snippet_id); rc = gcli_curl(ctx, stream, url, NULL); free(url); diff --git a/src/gitlab/sshkeys.c b/src/gitlab/sshkeys.c index 15e0100f..4cef2bf0 100644 --- a/src/gitlab/sshkeys.c +++ b/src/gitlab/sshkeys.c @@ -32,7 +32,6 @@ #endif /* HAVE_CONFIG_H */ #include -#include #include #include diff --git a/src/gitlab/status.c b/src/gitlab/status.c index 0eb75d2f..ee53bc74 100644 --- a/src/gitlab/status.c +++ b/src/gitlab/status.c @@ -50,7 +50,7 @@ gitlab_get_notifications(gcli_ctx *ctx, int const max, .max = max, }; - url = sn_asprintf("%s/todos", gitlab_get_apibase(ctx)); + url = sn_asprintf("%s/todos", gcli_get_apibase(ctx)); return gcli_fetch_list(ctx, url, &fl); } @@ -61,7 +61,7 @@ gitlab_notification_mark_as_read(gcli_ctx *ctx, char const *id) char *url = NULL; int rc = 0; - url = sn_asprintf("%s/todos/%s/mark_as_done", gitlab_get_apibase(ctx), id); + url = sn_asprintf("%s/todos/%s/mark_as_done", gcli_get_apibase(ctx), id); rc = gcli_fetch_with_method(ctx, "POST", url, NULL, NULL, NULL); free(url); diff --git a/src/pgen/dump_c.c b/src/pgen/dump_c.c index e296535a..c555484b 100644 --- a/src/pgen/dump_c.c +++ b/src/pgen/dump_c.c @@ -145,8 +145,7 @@ objparser_dump_c(struct objparser *p) fprintf(outfile, "\tenum json_type key_type;\n"); fprintf(outfile, "\tconst char *key;\n\n"); fprintf(outfile, "\tif (json_next(stream) == JSON_NULL)\n"); - fprintf(outfile, "\t\treturn gcli_error(ctx, " - "\"expected a JSON object in parse_%s\");\n\n", p->name); + fprintf(outfile, "\t\treturn 0;\n"); /* not ideal */ switch (p->kind) { case OBJPARSER_ENTRIES: objparser_dump_entries(p); break; diff --git a/src/pulls.c b/src/pulls.c index a5c8a811..ef37e89c 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -27,9 +27,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include #include #include #include diff --git a/src/repos.c b/src/repos.c index 89c59673..c7bd58be 100644 --- a/src/repos.c +++ b/src/repos.c @@ -65,12 +65,6 @@ gcli_repos_free(gcli_repo_list *const list) list->repos_size = 0; } -int -gcli_get_own_repos(gcli_ctx *ctx, int const max, gcli_repo_list *const out) -{ - return gcli_forge(ctx)->get_own_repos(ctx, max, out); -} - int gcli_repo_delete(gcli_ctx *ctx, char const *owner, char const *repo) { diff --git a/src/review.c b/src/review.c index aa5c96bb..1d388cf4 100644 --- a/src/review.c +++ b/src/review.c @@ -27,8 +27,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include -#include #include #include #include @@ -39,52 +37,6 @@ #include -void -gcli_review_print_review_table(gcli_ctx *ctx, - gcli_pr_review_list const *const list) -{ - (void) ctx; - - for (size_t i = 0; i < list->reviews_size; ++i) { - if (list->reviews[i].state) { - printf(" %s%s%s - %s - %s%s%s\n", - gcli_setbold(), list->reviews[i].author, gcli_resetbold(), - list->reviews[i].date, - gcli_state_colour_str(list->reviews[i].state), - list->reviews[i].state, - gcli_resetcolour()); - } else { - printf(" %s%s%s - %s\n", - gcli_setbold(), list->reviews[i].author, gcli_resetbold(), - list->reviews[i].date); - } - - pretty_print(list->reviews[i].body, 9, 80, stdout); - - gcli_review_print_comments( - list->reviews[i].comments, - list->reviews[i].comments_size); - - putchar('\n'); - } -} - -void -gcli_review_print_comments(gcli_pr_review_comment const *const comments, - size_t const comments_size) -{ - for (size_t i = 0; i < comments_size; ++i) { - putchar('\n'); - printf(" PATH : %s\n" - " DIFF :\n", - comments[i].path); - - pretty_print(comments[i].diff, 20, INT_MAX, stdout); - putchar('\n'); - pretty_print(comments[i].body, 16, 80, stdout); - } -} - void gcli_review_reviews_free(gcli_pr_review_list *list) { diff --git a/src/sshkeys.c b/src/sshkeys.c index ad9f47f5..653d9021 100644 --- a/src/sshkeys.c +++ b/src/sshkeys.c @@ -31,7 +31,6 @@ #include #endif -#include #include #include #include diff --git a/tests/pgen-tests.c b/tests/pgen-tests.c index 8c97cd46..92ec466e 100644 --- a/tests/pgen-tests.c +++ b/tests/pgen-tests.c @@ -1,7 +1,11 @@ +#define GCLI_IN_LIBRARY 1 + #include #include #include +#include + #include #include #include @@ -9,13 +13,14 @@ static void issues(struct json_stream *stream) { - struct json_stream str = {0}; - gcli_issue issue = {0}; + struct json_stream str = {0}; + gcli_issue issue = {0}; + gcli_ctx ctx = {0}; (void) stream; json_open_stream(&str, stdin); - parse_github_issue(&str, &issue); + parse_github_issue(&ctx, &str, &issue); printf("title\t"SV_FMT"\n", SV_ARGS(issue.title)); printf("number\t%d\n", issue.number); @@ -31,7 +36,7 @@ pulls(struct json_stream *stream) { gcli_pull pull = {0}; - parse_github_pull(stream, &pull); + parse_github_pull(NULL, stream, &pull); printf("title\t%s\n", pull.title); printf("state\t%s\n", pull.state); @@ -46,7 +51,7 @@ labels(struct json_stream *stream) { gcli_label label = {0}; - parse_github_label(stream, &label); + parse_github_label(NULL, stream, &label); printf("id\t%ld\n", label.id); printf("name\t%s\n", label.name); diff --git a/todo.org b/todo.org index 37960021..a898c0f8 100644 --- a/todo.org +++ b/todo.org @@ -124,6 +124,12 @@ * Big refactor for libraryfication ** TODO Fix test suite + - [ ] Move config stuff to cmd and have callbacks that given the + context give you the account details etc. + + This would allow you to create a mock context that returns only + values that make sense in test contexts. + - [ ] Add support for a testing gcli context ** DONE Check errx calls if they print "error: " ** DONE Check for calls to errx in submit routines From b9f95c7e8129ba89ef43cbc128e25762743d6d24 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 01:24:31 +0200 Subject: [PATCH 166/236] Update List of known-to-work OSes --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a1636d37..248d8fe9 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,8 @@ Tested Operating Systems so far: - Solaris 10 and 11, sparc64 - SunOS 5.11 i86pc (OmniOS) - Devuan GNU/Linux Chimaera x86_64 -- Debian GNU/Linux 5.18.11 ppc64 +- Debian GNU/Linux ppc64, ppc64le +- Gentoo Linux sparc64, ia64 - Fedora 34 x86_64 - Haiku x86_64 - Minix 3.4.0 (GENERIC) i386 From 0790da24e4b069363042037377fb845b8b3379b0 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 01:36:41 +0200 Subject: [PATCH 167/236] Fix test suite --- tests/pgen-tests.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/tests/pgen-tests.c b/tests/pgen-tests.c index 92ec466e..b971a629 100644 --- a/tests/pgen-tests.c +++ b/tests/pgen-tests.c @@ -1,26 +1,32 @@ -#define GCLI_IN_LIBRARY 1 - #include #include #include #include +#ifdef NDEBUG +#undef NDEBUG +#endif +#include #include #include #include +static gcli_forge_type +get_github_forge_type(gcli_ctx *ctx) +{ + (void) ctx; + return GCLI_FORGE_GITHUB; +} + static void issues(struct json_stream *stream) { - struct json_stream str = {0}; gcli_issue issue = {0}; - gcli_ctx ctx = {0}; - - (void) stream; + gcli_ctx *ctx; - json_open_stream(&str, stdin); - parse_github_issue(&ctx, &str, &issue); + assert(gcli_init(&ctx, get_github_forge_type, NULL, NULL) == NULL); + parse_github_issue(ctx, stream, &issue); printf("title\t"SV_FMT"\n", SV_ARGS(issue.title)); printf("number\t%d\n", issue.number); @@ -35,8 +41,10 @@ static void pulls(struct json_stream *stream) { gcli_pull pull = {0}; + gcli_ctx *ctx; - parse_github_pull(NULL, stream, &pull); + assert(gcli_init(&ctx, get_github_forge_type, NULL, NULL) == NULL); + parse_github_pull(ctx, stream, &pull); printf("title\t%s\n", pull.title); printf("state\t%s\n", pull.state); @@ -50,8 +58,10 @@ static void labels(struct json_stream *stream) { gcli_label label = {0}; + gcli_ctx *ctx; - parse_github_label(NULL, stream, &label); + assert(gcli_init(&ctx, get_github_forge_type, NULL, NULL) == NULL); + parse_github_label(ctx, stream, &label); printf("id\t%ld\n", label.id); printf("name\t%s\n", label.name); @@ -67,6 +77,7 @@ main(int argc, char *argv[]) (void) argc; json_open_stream(&str, stdin); + json_set_streaming(&str, 1); if (strcmp(argv[1], "issues") == 0) issues(&str); From 710e441247e2534b77a66d0f3983e9985f05217e Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 18:10:46 +0200 Subject: [PATCH 168/236] Use kyua and atf-c for tests --- .gitlab-ci.yml | 4 ++-- Makefile.am | 43 ++++++++++++++-------------------- configure.ac | 41 +++++++++++++++++++++++++++++++- tests/Kyuafile.in | 5 ++++ tests/json-escape.c | 57 ++++++++++++++++++++++++++++++++++----------- 5 files changed, 107 insertions(+), 43 deletions(-) create mode 100644 tests/Kyuafile.in diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 60782a7e..96cd51ec 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,7 +12,7 @@ alpine-amd64: - linux image: alpine:3.17 script: - - apk add libcurl gcc autoconf automake libtool make pkgconf musl-dev curl-dev flex bison xz gzip bzip2 libbsd-dev + - apk add libcurl gcc autoconf automake libtool make pkgconf musl-dev curl-dev flex bison xz gzip bzip2 libbsd-dev kyua atf-dev - ./autogen.sh - ./configure CFLAGS='-std=c99 -pedantic -Wall -Wextra -Werror' CPPFLAGS='-D_XOPEN_SOURCE=600' || (cat config.log && exit 42) - make @@ -50,7 +50,7 @@ debian-amd64: image: debian:bullseye script: - apt-get update - - apt-get install -y --no-install-recommends build-essential libcurl4-openssl-dev pkgconf autotools-dev bison flex make autoconf automake libtool libbsd-dev + - apt-get install -y --no-install-recommends build-essential libcurl4-openssl-dev pkgconf autotools-dev bison flex make autoconf automake libtool libbsd-dev libatf-dev kyua - ./autogen.sh - ./configure CFLAGS='-std=c99 -pedantic -Wall -Wextra -Werror -Wno-misleading-indentation' CPPFLAGS='-D_XOPEN_SOURCE=600' || (cat config.log && exit 42) - make diff --git a/Makefile.am b/Makefile.am index ea83fe14..6bec29a5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -205,40 +205,31 @@ EXTRA_DIST = \ ########################################### # Tests +if HAVE_TESTS check_PROGRAMS = \ tests/json-escape$(EXEEXT) \ tests/pgen-tests$(EXEEXT) \ tests/url-encode$(EXEEXT) \ tests/pretty_print_test$(EXEEXT) -SHELL_TESTS = \ - tests/01_pgen_simple_object.sh \ - tests/02_pgen_error_no_entries.sh \ - tests/03_pgen_error_trailing_comma.sh \ - tests/04_pgen_simple_issue.sh \ - tests/05_pgen_simple_pull.sh \ - tests/06_pgen_simple_label.sh \ - tests/07_pretty_print.sh - -EXTRA_DIST += \ - ${SHELL_TESTS} \ - tests/setup.sh \ - tests/samples/pgen_simple_object.dump \ - tests/samples/github_simple_issue.json tests/samples/parse_simple_issue.dump \ - tests/samples/github_simple_pull.json tests/samples/parse_simple_pull.dump \ - tests/samples/github_simple_label.json tests/samples/parse_simple_label.dump \ - tests/samples/pretty.dump - -TESTS = \ - tests/json-escape \ - tests/url-encode \ - ${SHELL_TESTS} +check: $(check_PROGRAMS) tests/Kyuafile libgcli.la gcli libsn.la libpdjson.la do_test + +do_test: + (cd tests; kyua test) tests_json_escape_LDADD = \ - libgcli.la libpdjson.la libsn.la + libgcli.la libpdjson.la libsn.la \ + $(LIBATFC_LDFLAGS) + tests_pgen_tests_LDADD = \ - libgcli.la libpdjson.la libsn.la + libgcli.la libpdjson.la libsn.la \ + $(LIBATFC_LDFLAGS) + tests_url_encode_LDADD = \ - libgcli.la libpdjson.la libsn.la + libgcli.la libpdjson.la libsn.la \ + $(LIBATFC_LDFLAGS) + tests_pretty_print_test_LDADD = \ - libsn.la + libsn.la \ + $(LIBATFC_LDFLAGS) +endif diff --git a/configure.ac b/configure.ac index 42bd0350..55af4f85 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([gcli],[2.0.0-devel],[nsonack@herrhotzenplotz.de],[gcli],[https://gitlab.com/herrhotzenplotz/gcli/]) +AC_INIT([gcli],[2.0.0-ALPHA1],[nsonack@herrhotzenplotz.de],[gcli],[https://gitlab.com/herrhotzenplotz/gcli/]) AM_INIT_AUTOMAKE([1.0 foreign subdir-objects dist-bzip2 dist-xz -Wall]) dnl Release Date. @@ -47,6 +47,42 @@ AS_IF([test "x$OPT_LIBCURL" = "xcheck" || test "x$OPT_LIBCURL" = "xyes"], AC_CHECK_HEADER([curl/curl.h],,[AC_MSG_ERROR([Cannot find libcurl headers])]) AC_CHECK_LIB([curl],[curl_easy_init],,[AC_MSG_ERROR([-lcurl doesn not contain curl_easy_init])]) +dnl For the test suite we require libatf-c and Kyua +OPT_LIBATFC=check +AC_ARG_WITH([libatf-c], +[AS_HELP_STRING([--with-libatf-c], + [Give an alternate path to libatf-c.])], +OPT_LIBATFC=$withval +) + +HAVE_ATFC=no +if test "x$OPT_LIBATFC" = "xcheck" || test "x$OPT_LIBATFC" = "xyes" +then + PKG_CHECK_MODULES([LIBATFC], [atf-c], [HAVE_ATFC=yes],[HAVE_ATFC=no]) + CFLAGS="$LIBATFC_CFLAGS $CFLAGS" + LDFLAGS="$LIBATFC_LIBS $LDFLAGS" +elif test "x$OPT_LIBATFC" = "xno" +then + HAVE_ATFC=no +else + CPPFLAGS="-I$OPT_LIBATFC/include $CPPFLAGS" + LDFLAGS="-L$OPT_LIBATFC/lib $LDFLAGS" + HAVE_ATFC=yes +fi + +AS_IF([test "x$HAVE_ATFC" = "xyes"], + [AC_CHECK_HEADER([atf-c.h],,[AC_MSG_ERROR([Cannot find libatf-c headers])]) + AC_CHECK_LIB([atf-c],[atf_no_error],,[AC_MSG_ERROR([-latf-c doesn not contain atf_no_error])]) + HAVE_ATFC=yes]) + +AC_CHECK_PROG([KYUA], [kyua], [kyua]) +HAVE_TESTS=0 +AS_IF([test -z "$KYUA" || test "x$HAVE_ATFC" = xno], + [HAVE_TESTS=no], + [HAVE_TESTS=yes]) +AC_SUBST([HAVE_TESTS]) +AM_CONDITIONAL([HAVE_TESTS], [test "x$HAVE_TESTS" = xyes]) + dnl Go looking for headers that may define getopt_long AC_CHECK_HEADERS([getopt.h unistd.h]) dnl Other headers that we require @@ -78,5 +114,8 @@ AC_CONFIG_FILES([Makefile docs/gcli-status.1 docs/gcli.1]) +dnl Technically only needed if tests are enabled but this doesn't +dnl hurt. +AC_CONFIG_FILES([tests/Kyuafile]) AC_OUTPUT diff --git a/tests/Kyuafile.in b/tests/Kyuafile.in new file mode 100644 index 00000000..fd68c94d --- /dev/null +++ b/tests/Kyuafile.in @@ -0,0 +1,5 @@ +syntax(2) + +test_suite('gcli') + +atf_test_program{name='json-escape'} \ No newline at end of file diff --git a/tests/json-escape.c b/tests/json-escape.c index 7d6b2e6c..cf26c92a 100644 --- a/tests/json-escape.c +++ b/tests/json-escape.c @@ -1,20 +1,49 @@ -#include -#include - #include -int -main(void) +#include + +ATF_TC_WITHOUT_HEAD(newlines); +ATF_TC_BODY(newlines, tc) { - if (!sn_sv_eq_to( - gcli_json_escape(SV("\n\r\n\n\n\t{}")), - "\\n\\r\\n\\n\\n\\t{}")) - return 1; + sn_sv const input = SV("\n\r"); + sn_sv const escaped = gcli_json_escape(input); - if (!sn_sv_eq_to( - gcli_json_escape(SV("\\")), - "\\\\")) - return 1; + ATF_CHECK(sn_sv_eq_to(escaped, "\\n\\r")); +} + +ATF_TC_WITHOUT_HEAD(tabs); +ATF_TC_BODY(tabs, tc) +{ + sn_sv const input = SV("\t\t\t"); + sn_sv const escaped = gcli_json_escape(input); + + ATF_CHECK(sn_sv_eq_to(escaped, "\\t\\t\\t")); +} + +ATF_TC_WITHOUT_HEAD(backslashes); +ATF_TC_BODY(backslashes, tc) +{ + sn_sv const input = SV("\\"); + sn_sv const escaped = gcli_json_escape(input); + + ATF_CHECK(sn_sv_eq_to(escaped, "\\\\")); +} + +ATF_TC_WITHOUT_HEAD(torture); +ATF_TC_BODY(torture, tc) +{ + sn_sv const input = SV("\n\r\n\n\n\t{}"); + sn_sv const escaped = gcli_json_escape(input); + + ATF_CHECK(sn_sv_eq_to(escaped, "\\n\\r\\n\\n\\n\\t{}")); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, newlines); + ATF_TP_ADD_TC(tp, tabs); + ATF_TP_ADD_TC(tp, backslashes); + ATF_TP_ADD_TC(tp, torture); - return 0; + return atf_no_error(); } From 6b1c25662b98f7b2ea7739d73e59a16e287f28e4 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 17:12:53 +0200 Subject: [PATCH 169/236] pgen-tests -> github-parse-tests Rename and move tests to kyua --- Makefile.am | 9 +- configure.ac | 4 + tests/04_pgen_simple_issue.sh | 15 - tests/05_pgen_simple_pull.sh | 15 - tests/06_pgen_simple_label.sh | 15 - tests/Kyuafile.in | 9 +- tests/github-parse-tests.c | 141 ++++++ tests/pgen-tests.c | 92 ---- tests/samples/github_simple_pull.json | 671 ++++++++++++++------------ 9 files changed, 510 insertions(+), 461 deletions(-) delete mode 100755 tests/04_pgen_simple_issue.sh delete mode 100755 tests/05_pgen_simple_pull.sh delete mode 100755 tests/06_pgen_simple_label.sh create mode 100644 tests/github-parse-tests.c delete mode 100644 tests/pgen-tests.c diff --git a/Makefile.am b/Makefile.am index 6bec29a5..bec6da23 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,6 +8,7 @@ AM_CPPFLAGS += -I$(srcdir) AM_CPPFLAGS += -DYY_NO_INPUT AM_CPPFLAGS += -DYY_NO_UNPUT AM_CPPFLAGS += -D_XOPEN_SOURCE=600 +AM_CFLAGS = -Wno-gnu-zero-variadic-macro-arguments noinst_PROGRAMS = pgen$(EXEEXT) pgen_SOURCES = \ @@ -208,20 +209,20 @@ EXTRA_DIST = \ if HAVE_TESTS check_PROGRAMS = \ tests/json-escape$(EXEEXT) \ - tests/pgen-tests$(EXEEXT) \ + tests/github-parse-tests$(EXEEXT) \ tests/url-encode$(EXEEXT) \ tests/pretty_print_test$(EXEEXT) -check: $(check_PROGRAMS) tests/Kyuafile libgcli.la gcli libsn.la libpdjson.la do_test +check: $(check_PROGRAMS) tests/Kyuafile libgcli.la libsn.la libpdjson.la do_test do_test: - (cd tests; kyua test) + kyua test -k tests/Kyuafile tests_json_escape_LDADD = \ libgcli.la libpdjson.la libsn.la \ $(LIBATFC_LDFLAGS) -tests_pgen_tests_LDADD = \ +tests_github_parse_tests_LDADD = \ libgcli.la libpdjson.la libsn.la \ $(LIBATFC_LDFLAGS) diff --git a/configure.ac b/configure.ac index 55af4f85..6926508f 100644 --- a/configure.ac +++ b/configure.ac @@ -116,6 +116,10 @@ AC_CONFIG_FILES([Makefile dnl Technically only needed if tests are enabled but this doesn't dnl hurt. +TESTSRCDIR="$(realpath ${srcdir}/tests)" +AC_SUBST([TESTSRCDIR]) +AC_DEFINE_UNQUOTED([TESTSRCDIR], ["$TESTSRCDIR"], [Directory to the test sources]) + AC_CONFIG_FILES([tests/Kyuafile]) AC_OUTPUT diff --git a/tests/04_pgen_simple_issue.sh b/tests/04_pgen_simple_issue.sh deleted file mode 100755 index a243a068..00000000 --- a/tests/04_pgen_simple_issue.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -xe - -. $(dirname $0)/setup.sh - -TMPFILE=$(mktemp) - -[ -x ./tests/pgen-tests ] || diehard "pgen-tests executable found" - -./tests/pgen-tests issues < $srcdir/tests/samples/github_simple_issue.json > $TMPFILE \ - || fail "Parse Step failed" - -diff -u $srcdir/tests/samples/parse_simple_issue.dump $TMPFILE \ - || fail "Unexpected output of parser" - -rm -f $TMPFILE diff --git a/tests/05_pgen_simple_pull.sh b/tests/05_pgen_simple_pull.sh deleted file mode 100755 index 06af0ef9..00000000 --- a/tests/05_pgen_simple_pull.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -xe - -. $(dirname $0)/setup.sh - -TMPFILE=$(mktemp) - -[ -x ./tests/pgen-tests ] || diehard "pgen-tests executable found" - -./tests/pgen-tests pulls < $srcdir/tests/samples/github_simple_pull.json > $TMPFILE \ - || fail "Parse Step failed" - -diff -u $srcdir/tests/samples/parse_simple_pull.dump $TMPFILE \ - || fail "Unexpected output of parser" - -rm -f $TMPFILE diff --git a/tests/06_pgen_simple_label.sh b/tests/06_pgen_simple_label.sh deleted file mode 100755 index 8c5271c7..00000000 --- a/tests/06_pgen_simple_label.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -xe - -. $(dirname $0)/setup.sh - -TMPFILE=$(mktemp) - -[ -x ./tests/pgen-tests ] || diehard "pgen-tests executable found" - -./tests/pgen-tests labels < $srcdir/tests/samples/github_simple_label.json > $TMPFILE \ - || fail "Parse Step failed" - -diff -u $srcdir/tests/samples/parse_simple_label.dump $TMPFILE \ - || fail "Unexpected output of parser" - -rm -f $TMPFILE diff --git a/tests/Kyuafile.in b/tests/Kyuafile.in index fd68c94d..638c1a16 100644 --- a/tests/Kyuafile.in +++ b/tests/Kyuafile.in @@ -2,4 +2,11 @@ syntax(2) test_suite('gcli') -atf_test_program{name='json-escape'} \ No newline at end of file +atf_test_program{ + name='json-escape' +} + +atf_test_program{ + name = 'github-parse-tests', + required_files = '@TESTSRCDIR@/samples/github_simple_issue.json @TESTSRCDIR@/samples/github_simple_pull.json @TESTSRCDIR@/samples/github_simple_label.json' +} diff --git a/tests/github-parse-tests.c b/tests/github-parse-tests.c new file mode 100644 index 00000000..d0d0e384 --- /dev/null +++ b/tests/github-parse-tests.c @@ -0,0 +1,141 @@ +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +static gcli_forge_type +get_github_forge_type(gcli_ctx *ctx) +{ + (void) ctx; + return GCLI_FORGE_GITHUB; +} + +static gcli_ctx * +test_context(void) +{ + gcli_ctx *ctx; + ATF_REQUIRE(gcli_init(&ctx, get_github_forge_type, NULL, NULL) == NULL); + return ctx; +} + +static FILE * +open_sample(char const *const name) +{ + FILE *r; + char p[4096] = {0}; + + snprintf(p, sizeof p, "%s/samples/%s", TESTSRCDIR, name); + + r = fopen(p, "r"); + return r; +} + +ATF_TC_WITHOUT_HEAD(simple_github_issue); +ATF_TC_BODY(simple_github_issue, tc) +{ + gcli_issue issue = {0}; + FILE *f; + json_stream stream; + gcli_ctx *ctx = test_context(); + + ATF_REQUIRE(f = open_sample("github_simple_issue.json")); + json_open_stream(&stream, f); + + ATF_REQUIRE(parse_github_issue(ctx, &stream, &issue) == 0); + + ATF_CHECK(issue.number = 115); + ATF_CHECK(sn_sv_eq_to(issue.title, "consider removing FILE *out from printing functions")); + ATF_CHECK(sn_sv_eq_to(issue.created_at, "2022-03-22T16:06:10Z")); + ATF_CHECK(sn_sv_eq_to(issue.author, "herrhotzenplotz")); + ATF_CHECK(sn_sv_eq_to(issue.state, "closed")); + ATF_CHECK(issue.comments == 0); + ATF_CHECK(issue.locked == false); + + ATF_CHECK(sn_sv_eq_to( + issue.body, + "We use these functions with ghcli only anyways. In " + "the GUI stuff we use the datastructures returned by " + "the api directly. And If we output, it is stdout " + "everywhere.\n")); + + ATF_CHECK(issue.labels_size == 0); + ATF_CHECK(issue.labels == NULL); + + ATF_CHECK(issue.assignees_size == 0); + ATF_CHECK(issue.assignees == NULL); + + ATF_CHECK(issue.is_pr == 0); + ATF_CHECK(sn_sv_null(issue.milestone)); +} + +ATF_TC_WITHOUT_HEAD(simple_github_pull); +ATF_TC_BODY(simple_github_pull, tc) +{ + gcli_pull pull = {0}; + FILE *f; + json_stream stream; + gcli_ctx *ctx = test_context(); + + ATF_REQUIRE(f = open_sample("github_simple_pull.json")); + json_open_stream(&stream, f); + + ATF_REQUIRE(parse_github_pull(ctx, &stream, &pull) == 0); + + ATF_CHECK_STREQ(pull.author, "herrhotzenplotz"); + ATF_CHECK_STREQ(pull.state, "closed"); + ATF_CHECK_STREQ(pull.title, "mark notifications as read/done"); + ATF_CHECK_STREQ(pull.body, "Fixes #99\n"); + ATF_CHECK_STREQ(pull.created_at, "2022-03-22T13:20:57Z"); + ATF_CHECK_STREQ(pull.head_label, "herrhotzenplotz:99"); + ATF_CHECK_STREQ(pull.base_label, "herrhotzenplotz:trunk"); + ATF_CHECK_STREQ(pull.head_sha, "a00f475af1e31d56c7a5839508a21e2b76a31e49"); + ATF_CHECK(pull.milestone == NULL); + ATF_CHECK(pull.id == 886044243); + ATF_CHECK(pull.comments == 0); + ATF_CHECK(pull.additions == 177); + ATF_CHECK(pull.deletions == 82); + ATF_CHECK(pull.commits == 6); + ATF_CHECK(pull.changed_files == 13); + + ATF_CHECK(pull.labels == NULL); + ATF_CHECK(pull.labels_size == 0); + ATF_CHECK(pull.merged == true); + ATF_CHECK(pull.mergeable == false); + ATF_CHECK(pull.draft == false); +} + +ATF_TC_WITHOUT_HEAD(simple_github_label); +ATF_TC_BODY(simple_github_label, tc) +{ + gcli_label label = {0}; + FILE *f; + json_stream stream; + gcli_ctx *ctx = test_context(); + + ATF_REQUIRE(f = open_sample("github_simple_label.json")); + json_open_stream(&stream, f); + + ATF_REQUIRE(parse_github_label(ctx, &stream, &label) == 0); + + ATF_CHECK(label.id == 208045946); + ATF_CHECK_STREQ(label.name, "bug"); + ATF_CHECK_STREQ(label.description, "Something isn't working"); + ATF_CHECK(label.colour == 0xf2951300); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, simple_github_issue); + ATF_TP_ADD_TC(tp, simple_github_pull); + ATF_TP_ADD_TC(tp, simple_github_label); + + return atf_no_error(); +} diff --git a/tests/pgen-tests.c b/tests/pgen-tests.c deleted file mode 100644 index b971a629..00000000 --- a/tests/pgen-tests.c +++ /dev/null @@ -1,92 +0,0 @@ -#include -#include -#include - -#include - -#ifdef NDEBUG -#undef NDEBUG -#endif -#include -#include -#include -#include - -static gcli_forge_type -get_github_forge_type(gcli_ctx *ctx) -{ - (void) ctx; - return GCLI_FORGE_GITHUB; -} - -static void -issues(struct json_stream *stream) -{ - gcli_issue issue = {0}; - gcli_ctx *ctx; - - assert(gcli_init(&ctx, get_github_forge_type, NULL, NULL) == NULL); - parse_github_issue(ctx, stream, &issue); - - printf("title\t"SV_FMT"\n", SV_ARGS(issue.title)); - printf("number\t%d\n", issue.number); - printf("author\t"SV_FMT"\n", SV_ARGS(issue.author)); - printf("locked\t%d\n", issue.locked); - printf("state\t"SV_FMT"\n", SV_ARGS(issue.state)); - printf("labels_size\t%zu\n", issue.labels_size); - printf("comments\t%d\n", issue.comments); -} - -static void -pulls(struct json_stream *stream) -{ - gcli_pull pull = {0}; - gcli_ctx *ctx; - - assert(gcli_init(&ctx, get_github_forge_type, NULL, NULL) == NULL); - parse_github_pull(ctx, stream, &pull); - - printf("title\t%s\n", pull.title); - printf("state\t%s\n", pull.state); - printf("author\t%s\n", pull.author); - printf("number\t%d\n", pull.number); - printf("id\t%d\n", pull.id); - printf("merged\t%d\n", pull.merged); -} - -static void -labels(struct json_stream *stream) -{ - gcli_label label = {0}; - gcli_ctx *ctx; - - assert(gcli_init(&ctx, get_github_forge_type, NULL, NULL) == NULL); - parse_github_label(ctx, stream, &label); - - printf("id\t%ld\n", label.id); - printf("name\t%s\n", label.name); - printf("description\t%s\n", label.description); - printf("colour\t%"PRIx32"\n", label.colour); -} - -int -main(int argc, char *argv[]) -{ - struct json_stream str = {0}; - - (void) argc; - - json_open_stream(&str, stdin); - json_set_streaming(&str, 1); - - if (strcmp(argv[1], "issues") == 0) - issues(&str); - else if (strcmp(argv[1], "pulls") == 0) - pulls(&str); - else if (strcmp(argv[1], "labels") == 0) - labels(&str); - else - fprintf(stderr, "error: unknown subcommand\n"); - - return 0; -} diff --git a/tests/samples/github_simple_pull.json b/tests/samples/github_simple_pull.json index baa60fa2..f2170ab3 100644 --- a/tests/samples/github_simple_pull.json +++ b/tests/samples/github_simple_pull.json @@ -11,24 +11,24 @@ "locked": false, "title": "mark notifications as read/done", "user": { - "login": "herrhotzenplotz", - "id": 34663024, - "node_id": "MDQ6VXNlcjM0NjYzMDI0", - "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/herrhotzenplotz", - "html_url": "https://github.com/herrhotzenplotz", - "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", - "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", - "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", - "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", - "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", - "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", - "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", - "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", - "type": "User", - "site_admin": false + "login": "herrhotzenplotz", + "id": 34663024, + "node_id": "MDQ6VXNlcjM0NjYzMDI0", + "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/herrhotzenplotz", + "html_url": "https://github.com/herrhotzenplotz", + "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", + "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", + "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", + "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", + "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", + "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", + "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", + "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", + "type": "User", + "site_admin": false }, "body": "Fixes #99\n", "created_at": "2022-03-22T13:20:57Z", @@ -57,312 +57,345 @@ "comments_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/113/comments", "statuses_url": "https://api.github.com/repos/herrhotzenplotz/gcli/statuses/a00f475af1e31d56c7a5839508a21e2b76a31e49", "head": { - "label": "herrhotzenplotz:99", - "ref": "99", - "sha": "a00f475af1e31d56c7a5839508a21e2b76a31e49", - "user": { - "login": "herrhotzenplotz", - "id": 34663024, - "node_id": "MDQ6VXNlcjM0NjYzMDI0", - "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/herrhotzenplotz", - "html_url": "https://github.com/herrhotzenplotz", - "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", - "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", - "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", - "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", - "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", - "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", - "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", - "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", - "type": "User", - "site_admin": false - }, - "repo": { - "id": 415015197, - "node_id": "R_kgDOGLyhHQ", - "name": "gcli", - "full_name": "herrhotzenplotz/gcli", - "private": false, - "owner": { - "login": "herrhotzenplotz", - "id": 34663024, - "node_id": "MDQ6VXNlcjM0NjYzMDI0", - "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/herrhotzenplotz", - "html_url": "https://github.com/herrhotzenplotz", - "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", - "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", - "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", - "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", - "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", - "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", - "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", - "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", - "type": "User", - "site_admin": false - }, - "html_url": "https://github.com/herrhotzenplotz/gcli", - "description": "Somewhat portable and secure CLI utility to interact with both GitHub and GitLab", - "fork": false, - "url": "https://api.github.com/repos/herrhotzenplotz/gcli", - "forks_url": "https://api.github.com/repos/herrhotzenplotz/gcli/forks", - "keys_url": "https://api.github.com/repos/herrhotzenplotz/gcli/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/herrhotzenplotz/gcli/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/herrhotzenplotz/gcli/teams", - "hooks_url": "https://api.github.com/repos/herrhotzenplotz/gcli/hooks", - "issue_events_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/events{/number}", - "events_url": "https://api.github.com/repos/herrhotzenplotz/gcli/events", - "assignees_url": "https://api.github.com/repos/herrhotzenplotz/gcli/assignees{/user}", - "branches_url": "https://api.github.com/repos/herrhotzenplotz/gcli/branches{/branch}", - "tags_url": "https://api.github.com/repos/herrhotzenplotz/gcli/tags", - "blobs_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/herrhotzenplotz/gcli/statuses/{sha}", - "languages_url": "https://api.github.com/repos/herrhotzenplotz/gcli/languages", - "stargazers_url": "https://api.github.com/repos/herrhotzenplotz/gcli/stargazers", - "contributors_url": "https://api.github.com/repos/herrhotzenplotz/gcli/contributors", - "subscribers_url": "https://api.github.com/repos/herrhotzenplotz/gcli/subscribers", - "subscription_url": "https://api.github.com/repos/herrhotzenplotz/gcli/subscription", - "commits_url": "https://api.github.com/repos/herrhotzenplotz/gcli/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/herrhotzenplotz/gcli/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/herrhotzenplotz/gcli/contents/{+path}", - "compare_url": "https://api.github.com/repos/herrhotzenplotz/gcli/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/herrhotzenplotz/gcli/merges", - "archive_url": "https://api.github.com/repos/herrhotzenplotz/gcli/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/herrhotzenplotz/gcli/downloads", - "issues_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues{/number}", - "pulls_url": "https://api.github.com/repos/herrhotzenplotz/gcli/pulls{/number}", - "milestones_url": "https://api.github.com/repos/herrhotzenplotz/gcli/milestones{/number}", - "notifications_url": "https://api.github.com/repos/herrhotzenplotz/gcli/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/herrhotzenplotz/gcli/labels{/name}", - "releases_url": "https://api.github.com/repos/herrhotzenplotz/gcli/releases{/id}", - "deployments_url": "https://api.github.com/repos/herrhotzenplotz/gcli/deployments", - "created_at": "2021-10-08T14:20:15Z", - "updated_at": "2022-08-31T16:32:13Z", - "pushed_at": "2022-09-25T19:53:40Z", - "git_url": "git://github.com/herrhotzenplotz/gcli.git", - "ssh_url": "git@github.com:herrhotzenplotz/gcli.git", - "clone_url": "https://github.com/herrhotzenplotz/gcli.git", - "svn_url": "https://github.com/herrhotzenplotz/gcli", - "homepage": "https://herrhotzenplotz.de/ghcli/releases/", - "size": 1227, - "stargazers_count": 2, - "watchers_count": 2, - "language": "C", - "has_issues": true, - "has_projects": false, - "has_downloads": true, - "has_wiki": false, - "has_pages": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": { - "key": "bsd-2-clause", - "name": "BSD 2-Clause \"Simplified\" License", - "spdx_id": "BSD-2-Clause", - "url": "https://api.github.com/licenses/bsd-2-clause", - "node_id": "MDc6TGljZW5zZTQ=" - }, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [ - "c", - "cli", - "freebsd", - "github-api", - "gitlab", - "gitlab-api", - "libcurl", - "linux", - "unix" - ], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 2, - "default_branch": "trunk" - } + "label": "herrhotzenplotz:99", + "ref": "99", + "sha": "a00f475af1e31d56c7a5839508a21e2b76a31e49", + "user": { + "login": "herrhotzenplotz", + "id": 34663024, + "node_id": "MDQ6VXNlcjM0NjYzMDI0", + "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/herrhotzenplotz", + "html_url": "https://github.com/herrhotzenplotz", + "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", + "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", + "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", + "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", + "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", + "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", + "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", + "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 415015197, + "node_id": "R_kgDOGLyhHQ", + "name": "gcli", + "full_name": "herrhotzenplotz/gcli", + "private": false, + "owner": { + "login": "herrhotzenplotz", + "id": 34663024, + "node_id": "MDQ6VXNlcjM0NjYzMDI0", + "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/herrhotzenplotz", + "html_url": "https://github.com/herrhotzenplotz", + "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", + "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", + "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", + "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", + "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", + "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", + "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", + "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/herrhotzenplotz/gcli", + "description": "Somewhat portable and secure CLI utility to interact with both GitHub and GitLab. Development is happening at https://gitlab.com/herrhotzenplotz/gcli but you can also submit issues/PRs here.", + "fork": false, + "url": "https://api.github.com/repos/herrhotzenplotz/gcli", + "forks_url": "https://api.github.com/repos/herrhotzenplotz/gcli/forks", + "keys_url": "https://api.github.com/repos/herrhotzenplotz/gcli/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/herrhotzenplotz/gcli/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/herrhotzenplotz/gcli/teams", + "hooks_url": "https://api.github.com/repos/herrhotzenplotz/gcli/hooks", + "issue_events_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/events{/number}", + "events_url": "https://api.github.com/repos/herrhotzenplotz/gcli/events", + "assignees_url": "https://api.github.com/repos/herrhotzenplotz/gcli/assignees{/user}", + "branches_url": "https://api.github.com/repos/herrhotzenplotz/gcli/branches{/branch}", + "tags_url": "https://api.github.com/repos/herrhotzenplotz/gcli/tags", + "blobs_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/herrhotzenplotz/gcli/statuses/{sha}", + "languages_url": "https://api.github.com/repos/herrhotzenplotz/gcli/languages", + "stargazers_url": "https://api.github.com/repos/herrhotzenplotz/gcli/stargazers", + "contributors_url": "https://api.github.com/repos/herrhotzenplotz/gcli/contributors", + "subscribers_url": "https://api.github.com/repos/herrhotzenplotz/gcli/subscribers", + "subscription_url": "https://api.github.com/repos/herrhotzenplotz/gcli/subscription", + "commits_url": "https://api.github.com/repos/herrhotzenplotz/gcli/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/herrhotzenplotz/gcli/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/herrhotzenplotz/gcli/contents/{+path}", + "compare_url": "https://api.github.com/repos/herrhotzenplotz/gcli/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/herrhotzenplotz/gcli/merges", + "archive_url": "https://api.github.com/repos/herrhotzenplotz/gcli/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/herrhotzenplotz/gcli/downloads", + "issues_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues{/number}", + "pulls_url": "https://api.github.com/repos/herrhotzenplotz/gcli/pulls{/number}", + "milestones_url": "https://api.github.com/repos/herrhotzenplotz/gcli/milestones{/number}", + "notifications_url": "https://api.github.com/repos/herrhotzenplotz/gcli/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/herrhotzenplotz/gcli/labels{/name}", + "releases_url": "https://api.github.com/repos/herrhotzenplotz/gcli/releases{/id}", + "deployments_url": "https://api.github.com/repos/herrhotzenplotz/gcli/deployments", + "created_at": "2021-10-08T14:20:15Z", + "updated_at": "2023-08-15T20:58:16Z", + "pushed_at": "2023-08-11T07:58:26Z", + "git_url": "git://github.com/herrhotzenplotz/gcli.git", + "ssh_url": "git@github.com:herrhotzenplotz/gcli.git", + "clone_url": "https://github.com/herrhotzenplotz/gcli.git", + "svn_url": "https://github.com/herrhotzenplotz/gcli", + "homepage": "https://herrhotzenplotz.de/gcli/", + "size": 2169, + "stargazers_count": 19, + "watchers_count": 19, + "language": "C", + "has_issues": true, + "has_projects": false, + "has_downloads": true, + "has_wiki": false, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 0, + "license": { + "key": "bsd-2-clause", + "name": "BSD 2-Clause \"Simplified\" License", + "spdx_id": "BSD-2-Clause", + "url": "https://api.github.com/licenses/bsd-2-clause", + "node_id": "MDc6TGljZW5zZTQ=" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [ + "c", + "cli", + "freebsd", + "github-api", + "gitlab", + "gitlab-api", + "libcurl", + "linux", + "unix" + ], + "visibility": "public", + "forks": 0, + "open_issues": 0, + "watchers": 19, + "default_branch": "trunk" + } }, "base": { - "label": "herrhotzenplotz:trunk", - "ref": "trunk", - "sha": "5970c6ec82cefe2f4815edf42b6e982595077b1f", - "user": { - "login": "herrhotzenplotz", - "id": 34663024, - "node_id": "MDQ6VXNlcjM0NjYzMDI0", - "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/herrhotzenplotz", - "html_url": "https://github.com/herrhotzenplotz", - "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", - "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", - "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", - "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", - "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", - "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", - "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", - "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", - "type": "User", - "site_admin": false - }, - "repo": { - "id": 415015197, - "node_id": "R_kgDOGLyhHQ", - "name": "gcli", - "full_name": "herrhotzenplotz/gcli", - "private": false, - "owner": { - "login": "herrhotzenplotz", - "id": 34663024, - "node_id": "MDQ6VXNlcjM0NjYzMDI0", - "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/herrhotzenplotz", - "html_url": "https://github.com/herrhotzenplotz", - "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", - "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", - "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", - "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", - "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", - "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", - "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", - "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", - "type": "User", - "site_admin": false - }, - "html_url": "https://github.com/herrhotzenplotz/gcli", - "description": "Somewhat portable and secure CLI utility to interact with both GitHub and GitLab", - "fork": false, - "url": "https://api.github.com/repos/herrhotzenplotz/gcli", - "forks_url": "https://api.github.com/repos/herrhotzenplotz/gcli/forks", - "keys_url": "https://api.github.com/repos/herrhotzenplotz/gcli/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/herrhotzenplotz/gcli/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/herrhotzenplotz/gcli/teams", - "hooks_url": "https://api.github.com/repos/herrhotzenplotz/gcli/hooks", - "issue_events_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/events{/number}", - "events_url": "https://api.github.com/repos/herrhotzenplotz/gcli/events", - "assignees_url": "https://api.github.com/repos/herrhotzenplotz/gcli/assignees{/user}", - "branches_url": "https://api.github.com/repos/herrhotzenplotz/gcli/branches{/branch}", - "tags_url": "https://api.github.com/repos/herrhotzenplotz/gcli/tags", - "blobs_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/herrhotzenplotz/gcli/statuses/{sha}", - "languages_url": "https://api.github.com/repos/herrhotzenplotz/gcli/languages", - "stargazers_url": "https://api.github.com/repos/herrhotzenplotz/gcli/stargazers", - "contributors_url": "https://api.github.com/repos/herrhotzenplotz/gcli/contributors", - "subscribers_url": "https://api.github.com/repos/herrhotzenplotz/gcli/subscribers", - "subscription_url": "https://api.github.com/repos/herrhotzenplotz/gcli/subscription", - "commits_url": "https://api.github.com/repos/herrhotzenplotz/gcli/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/herrhotzenplotz/gcli/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/herrhotzenplotz/gcli/contents/{+path}", - "compare_url": "https://api.github.com/repos/herrhotzenplotz/gcli/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/herrhotzenplotz/gcli/merges", - "archive_url": "https://api.github.com/repos/herrhotzenplotz/gcli/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/herrhotzenplotz/gcli/downloads", - "issues_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues{/number}", - "pulls_url": "https://api.github.com/repos/herrhotzenplotz/gcli/pulls{/number}", - "milestones_url": "https://api.github.com/repos/herrhotzenplotz/gcli/milestones{/number}", - "notifications_url": "https://api.github.com/repos/herrhotzenplotz/gcli/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/herrhotzenplotz/gcli/labels{/name}", - "releases_url": "https://api.github.com/repos/herrhotzenplotz/gcli/releases{/id}", - "deployments_url": "https://api.github.com/repos/herrhotzenplotz/gcli/deployments", - "created_at": "2021-10-08T14:20:15Z", - "updated_at": "2022-08-31T16:32:13Z", - "pushed_at": "2022-09-25T19:53:40Z", - "git_url": "git://github.com/herrhotzenplotz/gcli.git", - "ssh_url": "git@github.com:herrhotzenplotz/gcli.git", - "clone_url": "https://github.com/herrhotzenplotz/gcli.git", - "svn_url": "https://github.com/herrhotzenplotz/gcli", - "homepage": "https://herrhotzenplotz.de/ghcli/releases/", - "size": 1227, - "stargazers_count": 2, - "watchers_count": 2, - "language": "C", - "has_issues": true, - "has_projects": false, - "has_downloads": true, - "has_wiki": false, - "has_pages": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": { - "key": "bsd-2-clause", - "name": "BSD 2-Clause \"Simplified\" License", - "spdx_id": "BSD-2-Clause", - "url": "https://api.github.com/licenses/bsd-2-clause", - "node_id": "MDc6TGljZW5zZTQ=" - }, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [ - "c", - "cli", - "freebsd", - "github-api", - "gitlab", - "gitlab-api", - "libcurl", - "linux", - "unix" - ], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 2, - "default_branch": "trunk" - } + "label": "herrhotzenplotz:trunk", + "ref": "trunk", + "sha": "5970c6ec82cefe2f4815edf42b6e982595077b1f", + "user": { + "login": "herrhotzenplotz", + "id": 34663024, + "node_id": "MDQ6VXNlcjM0NjYzMDI0", + "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/herrhotzenplotz", + "html_url": "https://github.com/herrhotzenplotz", + "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", + "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", + "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", + "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", + "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", + "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", + "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", + "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 415015197, + "node_id": "R_kgDOGLyhHQ", + "name": "gcli", + "full_name": "herrhotzenplotz/gcli", + "private": false, + "owner": { + "login": "herrhotzenplotz", + "id": 34663024, + "node_id": "MDQ6VXNlcjM0NjYzMDI0", + "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/herrhotzenplotz", + "html_url": "https://github.com/herrhotzenplotz", + "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", + "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", + "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", + "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", + "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", + "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", + "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", + "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/herrhotzenplotz/gcli", + "description": "Somewhat portable and secure CLI utility to interact with both GitHub and GitLab. Development is happening at https://gitlab.com/herrhotzenplotz/gcli but you can also submit issues/PRs here.", + "fork": false, + "url": "https://api.github.com/repos/herrhotzenplotz/gcli", + "forks_url": "https://api.github.com/repos/herrhotzenplotz/gcli/forks", + "keys_url": "https://api.github.com/repos/herrhotzenplotz/gcli/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/herrhotzenplotz/gcli/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/herrhotzenplotz/gcli/teams", + "hooks_url": "https://api.github.com/repos/herrhotzenplotz/gcli/hooks", + "issue_events_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/events{/number}", + "events_url": "https://api.github.com/repos/herrhotzenplotz/gcli/events", + "assignees_url": "https://api.github.com/repos/herrhotzenplotz/gcli/assignees{/user}", + "branches_url": "https://api.github.com/repos/herrhotzenplotz/gcli/branches{/branch}", + "tags_url": "https://api.github.com/repos/herrhotzenplotz/gcli/tags", + "blobs_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/herrhotzenplotz/gcli/statuses/{sha}", + "languages_url": "https://api.github.com/repos/herrhotzenplotz/gcli/languages", + "stargazers_url": "https://api.github.com/repos/herrhotzenplotz/gcli/stargazers", + "contributors_url": "https://api.github.com/repos/herrhotzenplotz/gcli/contributors", + "subscribers_url": "https://api.github.com/repos/herrhotzenplotz/gcli/subscribers", + "subscription_url": "https://api.github.com/repos/herrhotzenplotz/gcli/subscription", + "commits_url": "https://api.github.com/repos/herrhotzenplotz/gcli/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/herrhotzenplotz/gcli/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/herrhotzenplotz/gcli/contents/{+path}", + "compare_url": "https://api.github.com/repos/herrhotzenplotz/gcli/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/herrhotzenplotz/gcli/merges", + "archive_url": "https://api.github.com/repos/herrhotzenplotz/gcli/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/herrhotzenplotz/gcli/downloads", + "issues_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues{/number}", + "pulls_url": "https://api.github.com/repos/herrhotzenplotz/gcli/pulls{/number}", + "milestones_url": "https://api.github.com/repos/herrhotzenplotz/gcli/milestones{/number}", + "notifications_url": "https://api.github.com/repos/herrhotzenplotz/gcli/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/herrhotzenplotz/gcli/labels{/name}", + "releases_url": "https://api.github.com/repos/herrhotzenplotz/gcli/releases{/id}", + "deployments_url": "https://api.github.com/repos/herrhotzenplotz/gcli/deployments", + "created_at": "2021-10-08T14:20:15Z", + "updated_at": "2023-08-15T20:58:16Z", + "pushed_at": "2023-08-11T07:58:26Z", + "git_url": "git://github.com/herrhotzenplotz/gcli.git", + "ssh_url": "git@github.com:herrhotzenplotz/gcli.git", + "clone_url": "https://github.com/herrhotzenplotz/gcli.git", + "svn_url": "https://github.com/herrhotzenplotz/gcli", + "homepage": "https://herrhotzenplotz.de/gcli/", + "size": 2169, + "stargazers_count": 19, + "watchers_count": 19, + "language": "C", + "has_issues": true, + "has_projects": false, + "has_downloads": true, + "has_wiki": false, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 0, + "license": { + "key": "bsd-2-clause", + "name": "BSD 2-Clause \"Simplified\" License", + "spdx_id": "BSD-2-Clause", + "url": "https://api.github.com/licenses/bsd-2-clause", + "node_id": "MDc6TGljZW5zZTQ=" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [ + "c", + "cli", + "freebsd", + "github-api", + "gitlab", + "gitlab-api", + "libcurl", + "linux", + "unix" + ], + "visibility": "public", + "forks": 0, + "open_issues": 0, + "watchers": 19, + "default_branch": "trunk" + } }, "_links": { - "self": { - "href": "https://api.github.com/repos/herrhotzenplotz/gcli/pulls/113" - }, - "html": { - "href": "https://github.com/herrhotzenplotz/gcli/pull/113" - }, - "issue": { - "href": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/113" - }, - "comments": { - "href": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/113/comments" - }, - "review_comments": { - "href": "https://api.github.com/repos/herrhotzenplotz/gcli/pulls/113/comments" - }, - "review_comment": { - "href": "https://api.github.com/repos/herrhotzenplotz/gcli/pulls/comments{/number}" - }, - "commits": { - "href": "https://api.github.com/repos/herrhotzenplotz/gcli/pulls/113/commits" - }, - "statuses": { - "href": "https://api.github.com/repos/herrhotzenplotz/gcli/statuses/a00f475af1e31d56c7a5839508a21e2b76a31e49" - } + "self": { + "href": "https://api.github.com/repos/herrhotzenplotz/gcli/pulls/113" + }, + "html": { + "href": "https://github.com/herrhotzenplotz/gcli/pull/113" + }, + "issue": { + "href": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/113" + }, + "comments": { + "href": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/113/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/herrhotzenplotz/gcli/pulls/113/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/herrhotzenplotz/gcli/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/herrhotzenplotz/gcli/pulls/113/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/herrhotzenplotz/gcli/statuses/a00f475af1e31d56c7a5839508a21e2b76a31e49" + } }, "author_association": "OWNER", "auto_merge": null, - "active_lock_reason": null + "active_lock_reason": null, + "merged": true, + "mergeable": null, + "rebaseable": null, + "mergeable_state": "unknown", + "merged_by": { + "login": "herrhotzenplotz", + "id": 34663024, + "node_id": "MDQ6VXNlcjM0NjYzMDI0", + "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/herrhotzenplotz", + "html_url": "https://github.com/herrhotzenplotz", + "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", + "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", + "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", + "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", + "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", + "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", + "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", + "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", + "type": "User", + "site_admin": false + }, + "comments": 0, + "review_comments": 0, + "maintainer_can_modify": false, + "commits": 6, + "additions": 177, + "deletions": 82, + "changed_files": 13 } From 539c6f8131b8d29cd243ae550b02e98d79b9f15f Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 17:16:47 +0200 Subject: [PATCH 170/236] Remove pgen simple test --- tests/01_pgen_simple_object.sh | 20 -------------------- tests/samples/pgen_simple_object.dump | 5 ----- 2 files changed, 25 deletions(-) delete mode 100755 tests/01_pgen_simple_object.sh delete mode 100644 tests/samples/pgen_simple_object.dump diff --git a/tests/01_pgen_simple_object.sh b/tests/01_pgen_simple_object.sh deleted file mode 100755 index adf1b878..00000000 --- a/tests/01_pgen_simple_object.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -ex - -. $(dirname $0)/setup.sh - -TMPFILE=$(mktemp) -cat < $TMPFILE || fail "parse failed" -parser github_issue -is object of gcli_issue -with - ("title" => title as sv, - "user" => user as sv use parse_user, - "id" => id as int, - "labels" => labels as array of github_label use parse_label); -EOF - -# Validate entries -diff -u $TMPFILE ${srcdir}/tests/samples/pgen_simple_object.dump \ - || fail "unexpected parser dump" - -rm -f $TMPFILE diff --git a/tests/samples/pgen_simple_object.dump b/tests/samples/pgen_simple_object.dump deleted file mode 100644 index ea6052a5..00000000 --- a/tests/samples/pgen_simple_object.dump +++ /dev/null @@ -1,5 +0,0 @@ -object parser: name = github_issue, type = gcli_issue - entry: kind = array, jsonname = labels, name = labels, type = github_label, parser = parse_label - entry: kind = simple, jsonname = id, name = id, type = int, parser = (null) - entry: kind = simple, jsonname = user, name = user, type = sv, parser = parse_user - entry: kind = simple, jsonname = title, name = title, type = sv, parser = (null) From 437a46e90d8545a80a9347e4ea0c178c860c4a2b Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 17:31:05 +0200 Subject: [PATCH 171/236] Move url-encode to kyua --- tests/Kyuafile.in | 4 +++ tests/url-encode.c | 68 ++++++++++++++++++++++++---------------------- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/tests/Kyuafile.in b/tests/Kyuafile.in index 638c1a16..85cc4fc2 100644 --- a/tests/Kyuafile.in +++ b/tests/Kyuafile.in @@ -10,3 +10,7 @@ atf_test_program{ name = 'github-parse-tests', required_files = '@TESTSRCDIR@/samples/github_simple_issue.json @TESTSRCDIR@/samples/github_simple_pull.json @TESTSRCDIR@/samples/github_simple_label.json' } + +atf_test_program{ + name = 'url-encode' +} diff --git a/tests/url-encode.c b/tests/url-encode.c index e7fbadef..5ef0f8c7 100644 --- a/tests/url-encode.c +++ b/tests/url-encode.c @@ -1,44 +1,46 @@ -#include -#include - #include -int -torture(void) -{ - char text[] = "some-random url// with %%%%%content" - "Rindfleischettikettierungsüberwachungsaufgabenübertragungsgesetz"; - char *escaped = gcli_urlencode(text); +#include - return strcmp( - escaped, - "some-random%20url%2F%2F%20with%20%25%25%25%25%25contentRindfleisch" - "ettikettierungs%C3%BCberwachungsaufgaben%C3%BCbertragungsgesetz"); +ATF_TC_WITHOUT_HEAD(simple_characters); +ATF_TC_BODY(simple_characters, tc) +{ + ATF_CHECK_STREQ(gcli_urlencode("%"), "%25"); + ATF_CHECK_STREQ(gcli_urlencode(" "), "%20"); + ATF_CHECK_STREQ(gcli_urlencode("-"), "-"); + ATF_CHECK_STREQ(gcli_urlencode("_"), "_"); } -int -main(void) +ATF_TC_WITHOUT_HEAD(umlaute); +ATF_TC_BODY(umlaute, tc) { - if (strcmp(gcli_urlencode("%"), "%25")) - return 1; - - if (strcmp(gcli_urlencode(" "), "%20")) - return 1; - - if (strcmp(gcli_urlencode("ä"), "%C3%A4")) - return 1; - - if (strcmp(gcli_urlencode("ẞ"), "%E1%BA%9E")) - return 1; + ATF_CHECK_STREQ(gcli_urlencode("Ä"), "%C3%84"); + ATF_CHECK_STREQ(gcli_urlencode("ä"), "%C3%A4"); + ATF_CHECK_STREQ(gcli_urlencode("Ö"), "%C3%96"); + ATF_CHECK_STREQ(gcli_urlencode("ö"), "%C3%B6"); + ATF_CHECK_STREQ(gcli_urlencode("Ü"), "%C3%9C"); + ATF_CHECK_STREQ(gcli_urlencode("ü"), "%C3%BC"); + ATF_CHECK_STREQ(gcli_urlencode("ẞ"), "%E1%BA%9E"); + ATF_CHECK_STREQ(gcli_urlencode("ß"), "%C3%9F"); +} - if (strcmp(gcli_urlencode("-"), "-")) - return 1; +ATF_TC_WITHOUT_HEAD(torture); +ATF_TC_BODY(torture, tc) +{ + char text[] = "some-random url// with %%%%%content" + "Rindfleischettikettierungsüberwachungsaufgabenübertragungsgesetz"; + char *escaped = gcli_urlencode(text); + char *expected = "some-random%20url%2F%2F%20with%20%25%25%25%25%25content" + "Rindfleischettikettierungs%C3%BCberwachungsaufgaben%C3%BCbertragungsgesetz"; - if (strcmp(gcli_urlencode("_"), "_")) - return 1; + ATF_CHECK_STREQ(escaped, expected); +} - if (torture()) - return 1; +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, simple_characters); + ATF_TP_ADD_TC(tp, umlaute); + ATF_TP_ADD_TC(tp, torture); - return 0; + return atf_no_error(); } From 624dd9d83fac49a4c248e565a5e41595daddbec5 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 18:55:55 +0200 Subject: [PATCH 172/236] Port pretty_print tests to Kyua and libatf --- tests/Kyuafile.in | 4 +++ tests/pretty_print_test.c | 75 ++++++++++++++++++++++++++++++++++----- 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/tests/Kyuafile.in b/tests/Kyuafile.in index 85cc4fc2..f2d4f887 100644 --- a/tests/Kyuafile.in +++ b/tests/Kyuafile.in @@ -14,3 +14,7 @@ atf_test_program{ atf_test_program{ name = 'url-encode' } + +atf_test_program{ + name = 'pretty_print_test' +} diff --git a/tests/pretty_print_test.c b/tests/pretty_print_test.c index 49249a72..c5379853 100644 --- a/tests/pretty_print_test.c +++ b/tests/pretty_print_test.c @@ -30,18 +30,77 @@ #include #include +#include +#include -static void +#include + +static char * test_string(char const *const input) { - pretty_print(input, 4, 80, stdout); + FILE *f; + long length; + char *buf; + static char const *const fname = "/tmp/gcli_pretty_print_test"; + + f = fopen(fname, "w"); + pretty_print(input, 4, 80, f); + + length = ftell(f); + fflush(f); + fclose(f); + + f = fopen(fname, "r"); + buf = malloc(length + 1); + fread(buf, 1, length, f); + buf[length] = '\0'; + + fclose(f); + unlink(fname); + + return buf; +} + +ATF_TC_WITHOUT_HEAD(simple_one_line); +ATF_TC_BODY(simple_one_line, tc) +{ + char *formatted = test_string(""); + ATF_CHECK_STREQ(formatted, " \n"); } -int -main(void) +ATF_TC_WITHOUT_HEAD(long_line_doesnt_break); +ATF_TC_BODY(long_line_doesnt_break, tc) { - test_string(""); - test_string("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - return 0; + char const *const input = + "0123456789012345678901234567890123456789012345678901234567890123456789" + "0123456789012345678901234567890123456789012345678901234567890123456789"; + char *formatted = test_string(input); + char const expected[] = + " 0123456789012345678901234567890123456789012345678901234567890123456789012345" + "6789012345678901234567890123456789012345678901234567890123456789\n"; + + ATF_CHECK_STREQ(formatted, expected); +} + +ATF_TC_WITHOUT_HEAD(line_overflow_break); +ATF_TC_BODY(line_overflow_break, tc) +{ + char const *const input = + "0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 " + "0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789"; + char *formatted = test_string(input); + char const expected[] = + " 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 \n" + " 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 \n" + " 0123456789 0123456789\n"; + ATF_CHECK_STREQ(formatted, expected); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, simple_one_line); + ATF_TP_ADD_TC(tp, long_line_doesnt_break); + ATF_TP_ADD_TC(tp, line_overflow_break); + + return atf_no_error(); } From 3eab596a6806434e4a34bb19de12307ab1217af3 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 18:58:54 +0200 Subject: [PATCH 173/236] Remove old Autotools test scripts --- tests/02_pgen_error_no_entries.sh | 13 ------------- tests/03_pgen_error_trailing_comma.sh | 15 --------------- tests/07_pretty_print.sh | 15 --------------- tests/samples/github_issue.t | 13 ------------- tests/samples/parse_simple_issue.dump | 7 ------- tests/samples/parse_simple_label.dump | 4 ---- tests/samples/parse_simple_pull.dump | 6 ------ tests/samples/pretty.dump | 2 -- tests/setup.sh | 17 ----------------- 9 files changed, 92 deletions(-) delete mode 100755 tests/02_pgen_error_no_entries.sh delete mode 100755 tests/03_pgen_error_trailing_comma.sh delete mode 100755 tests/07_pretty_print.sh delete mode 100644 tests/samples/github_issue.t delete mode 100644 tests/samples/parse_simple_issue.dump delete mode 100644 tests/samples/parse_simple_label.dump delete mode 100644 tests/samples/parse_simple_pull.dump delete mode 100644 tests/samples/pretty.dump delete mode 100644 tests/setup.sh diff --git a/tests/02_pgen_error_no_entries.sh b/tests/02_pgen_error_no_entries.sh deleted file mode 100755 index 40c32e20..00000000 --- a/tests/02_pgen_error_no_entries.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -xe - -. $(dirname $0)/setup.sh - -TMPFILE=$(mktemp) -cat < $TMPFILE ) || fail "parse suceeded" -parser github_issue -is object of gcli_issue -with - (); -EOF - -rm -f $TMPFILE diff --git a/tests/03_pgen_error_trailing_comma.sh b/tests/03_pgen_error_trailing_comma.sh deleted file mode 100755 index 56c8f83e..00000000 --- a/tests/03_pgen_error_trailing_comma.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -xe - -. $(dirname $0)/setup.sh - -TMPFILE=$(mktemp) - -cat < $TMPFILE ) || fail "parse succeeded" -parser github_issue -is object of gcli_issue -with - ("foo" => meh as string, - ); -EOF - -rm $TMPFILE diff --git a/tests/07_pretty_print.sh b/tests/07_pretty_print.sh deleted file mode 100755 index 6df87307..00000000 --- a/tests/07_pretty_print.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -xe - -. $(dirname $0)/setup.sh - -TMPFILE=$(mktemp) - -[ -x ./tests/pretty_print_test ] || diehard "pretty_print_test executable found" - -./tests/pretty_print_test > $TMPFILE \ - || fail "pretty_print failed" - -diff -u $srcdir/tests/samples/pretty.dump $TMPFILE \ - || fail "Unexpected test output" - -rm -f $TMPFILE diff --git a/tests/samples/github_issue.t b/tests/samples/github_issue.t deleted file mode 100644 index bba088e7..00000000 --- a/tests/samples/github_issue.t +++ /dev/null @@ -1,13 +0,0 @@ -include "gcli/issues.h"; -include "gcli/labels.h"; -include "gcli/json_util.h"; - -parser github_label is object of sn_sv select "name" as sv; - -parser github_issue -is object of gcli_issue -with - ("title" => title as sv, - "user" => author as user_sv, - "number" => number as int, - "labels" => labels as array of github_label use parse_github_label); diff --git a/tests/samples/parse_simple_issue.dump b/tests/samples/parse_simple_issue.dump deleted file mode 100644 index b6bb6f29..00000000 --- a/tests/samples/parse_simple_issue.dump +++ /dev/null @@ -1,7 +0,0 @@ -title consider removing FILE *out from printing functions -number 115 -author herrhotzenplotz -locked 0 -state closed -labels_size 0 -comments 0 diff --git a/tests/samples/parse_simple_label.dump b/tests/samples/parse_simple_label.dump deleted file mode 100644 index c438a50b..00000000 --- a/tests/samples/parse_simple_label.dump +++ /dev/null @@ -1,4 +0,0 @@ -id 208045946 -name bug -description Something isn't working -colour f2951300 diff --git a/tests/samples/parse_simple_pull.dump b/tests/samples/parse_simple_pull.dump deleted file mode 100644 index 7b934b89..00000000 --- a/tests/samples/parse_simple_pull.dump +++ /dev/null @@ -1,6 +0,0 @@ -title mark notifications as read/done -state closed -author herrhotzenplotz -number 113 -id 886044243 -merged 1 diff --git a/tests/samples/pretty.dump b/tests/samples/pretty.dump deleted file mode 100644 index c2620047..00000000 --- a/tests/samples/pretty.dump +++ /dev/null @@ -1,2 +0,0 @@ - - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/tests/setup.sh b/tests/setup.sh deleted file mode 100644 index 8b138ab9..00000000 --- a/tests/setup.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -xe - -fail() -{ - printf "fail: %s\n" "$*" >&2 - exit 1 -} - -diehard() -{ - printf "hard error: %s\n" "$*" >&2 - exit 99 -} - -PGEN=./pgen - -[ -x $PGEN ] || diehard "pgen not found or executable" From 11d8b893fe910ecb444c906d5bcf6aeb03b290d2 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 19:13:43 +0200 Subject: [PATCH 174/236] Add update script and account for changes to JSON files I needed to change the tests again because the Github folks decided to change a label in their example repository. --- tests/github-parse-tests.c | 4 ++-- tests/samples/github_simple_issue.json | 20 ++++++++++++++++++++ tests/samples/github_simple_label.json | 14 +++++++------- tests/update-samples.sh | 12 ++++++++++++ 4 files changed, 41 insertions(+), 9 deletions(-) create mode 100755 tests/update-samples.sh diff --git a/tests/github-parse-tests.c b/tests/github-parse-tests.c index d0d0e384..5a5939ba 100644 --- a/tests/github-parse-tests.c +++ b/tests/github-parse-tests.c @@ -125,10 +125,10 @@ ATF_TC_BODY(simple_github_label, tc) ATF_REQUIRE(parse_github_label(ctx, &stream, &label) == 0); - ATF_CHECK(label.id == 208045946); + ATF_CHECK(label.id == 3431203676); ATF_CHECK_STREQ(label.name, "bug"); ATF_CHECK_STREQ(label.description, "Something isn't working"); - ATF_CHECK(label.colour == 0xf2951300); + ATF_CHECK(label.colour == 0xd73a4a00); } ATF_TP_ADD_TCS(tp) diff --git a/tests/samples/github_simple_issue.json b/tests/samples/github_simple_issue.json index 6c41a57a..4124ad90 100644 --- a/tests/samples/github_simple_issue.json +++ b/tests/samples/github_simple_issue.json @@ -46,6 +46,26 @@ "author_association": "OWNER", "active_lock_reason": null, "body": "We use these functions with ghcli only anyways. In the GUI stuff we use the datastructures returned by the api directly. And If we output, it is stdout everywhere.\n", + "closed_by": { + "login": "herrhotzenplotz", + "id": 34663024, + "node_id": "MDQ6VXNlcjM0NjYzMDI0", + "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/herrhotzenplotz", + "html_url": "https://github.com/herrhotzenplotz", + "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", + "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", + "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", + "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", + "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", + "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", + "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", + "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", + "type": "User", + "site_admin": false + }, "reactions": { "url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/115/reactions", "total_count": 0, diff --git a/tests/samples/github_simple_label.json b/tests/samples/github_simple_label.json index 0adac940..685233e2 100644 --- a/tests/samples/github_simple_label.json +++ b/tests/samples/github_simple_label.json @@ -1,9 +1,9 @@ { - "id": 208045946, - "node_id": "MDU6TGFiZWwyMDgwNDU5NDY=", - "url": "https://api.github.com/repos/octocat/Hello-World/labels/bug", - "name": "bug", - "description": "Something isn't working", - "color": "f29513", - "default": true + "id": 3431203676, + "node_id": "LA_kwDOGLyhHc7MhANc", + "url": "https://api.github.com/repos/herrhotzenplotz/gcli/labels/bug", + "name": "bug", + "color": "d73a4a", + "default": true, + "description": "Something isn't working" } diff --git a/tests/update-samples.sh b/tests/update-samples.sh new file mode 100755 index 00000000..9522e0fb --- /dev/null +++ b/tests/update-samples.sh @@ -0,0 +1,12 @@ +#!/bin/sh -x + +die() { + printf -- "error: $@\n" >&2 + exit 1 +} + +which gcli > /dev/null 2>&1 || die "gcli is not in PATH" + +gcli -t github api /repos/herrhotzenplotz/gcli/issues/115 > samples/github_simple_issue.json +gcli -t github api /repos/herrhotzenplotz/gcli/labels/bug > samples/github_simple_label.json +gcli -t github api /repos/herrhotzenplotz/gcli/pulls/113 > samples/github_simple_pull.json From 807fac6a9137ade9e0a493e8da0f37d7e0d983f5 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 19:30:08 +0200 Subject: [PATCH 175/236] Add files and framework for testing gitlab parsers --- Makefile.am | 5 ++ tests/Kyuafile.in | 5 ++ tests/gitlab-parse-tests.c | 56 +++++++++++++++++++ .../samples/gitlab_simple_merge_request.json | 1 + tests/update-samples.sh | 2 + 5 files changed, 69 insertions(+) create mode 100644 tests/gitlab-parse-tests.c create mode 100644 tests/samples/gitlab_simple_merge_request.json diff --git a/Makefile.am b/Makefile.am index bec6da23..6e659691 100644 --- a/Makefile.am +++ b/Makefile.am @@ -210,6 +210,7 @@ if HAVE_TESTS check_PROGRAMS = \ tests/json-escape$(EXEEXT) \ tests/github-parse-tests$(EXEEXT) \ + tests/gitlab-parse-tests$(EXEEXT) \ tests/url-encode$(EXEEXT) \ tests/pretty_print_test$(EXEEXT) @@ -226,6 +227,10 @@ tests_github_parse_tests_LDADD = \ libgcli.la libpdjson.la libsn.la \ $(LIBATFC_LDFLAGS) +tests_gitlab_parse_tests_LDADD = \ + libgcli.la libpdjson.la libsn.la \ + $(LIBATFC_LDFLAGS) + tests_url_encode_LDADD = \ libgcli.la libpdjson.la libsn.la \ $(LIBATFC_LDFLAGS) diff --git a/tests/Kyuafile.in b/tests/Kyuafile.in index f2d4f887..4c40d37e 100644 --- a/tests/Kyuafile.in +++ b/tests/Kyuafile.in @@ -11,6 +11,11 @@ atf_test_program{ required_files = '@TESTSRCDIR@/samples/github_simple_issue.json @TESTSRCDIR@/samples/github_simple_pull.json @TESTSRCDIR@/samples/github_simple_label.json' } +atf_test_program{ + name = 'gitlab-parse-tests', + required_files = '@TESTSRCDIR@/samples/gitlab_simple_merge_request.json' +} + atf_test_program{ name = 'url-encode' } diff --git a/tests/gitlab-parse-tests.c b/tests/gitlab-parse-tests.c new file mode 100644 index 00000000..cd47ca8b --- /dev/null +++ b/tests/gitlab-parse-tests.c @@ -0,0 +1,56 @@ +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +static gcli_forge_type +get_gitlab_forge_type(gcli_ctx *ctx) +{ + (void) ctx; + return GCLI_FORGE_GITLAB; +} + +static gcli_ctx * +test_context(void) +{ + gcli_ctx *ctx; + ATF_REQUIRE(gcli_init(&ctx, get_gitlab_forge_type, NULL, NULL) == NULL); + return ctx; +} + +static FILE * +open_sample(char const *const name) +{ + FILE *r; + char p[4096] = {0}; + + snprintf(p, sizeof p, "%s/samples/%s", TESTSRCDIR, name); + + ATF_REQUIRE(r = fopen(p, "r")); + + return r; +} + +ATF_TC_WITHOUT_HEAD(gitlab_simple_merge_request); +ATF_TC_BODY(gitlab_simple_merge_request, tc) +{ + gcli_ctx *ctx = test_context(); + FILE *f = open_sample("gitlab_simple_merge_request.json"); + + (void) ctx; + (void) f; +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, gitlab_simple_merge_request); + return atf_no_error(); +} diff --git a/tests/samples/gitlab_simple_merge_request.json b/tests/samples/gitlab_simple_merge_request.json new file mode 100644 index 00000000..a6e22fee --- /dev/null +++ b/tests/samples/gitlab_simple_merge_request.json @@ -0,0 +1 @@ +{"id":246912053,"iid":216,"project_id":34707535,"title":"Fix test suite","description":"This finally fixes the broken test suite","state":"merged","created_at":"2023-08-31T23:37:50.848Z","updated_at":"2023-09-01T17:20:03.185Z","merged_by":{"id":5980462,"username":"herrhotzenplotz","name":"Nico Sonack","state":"active","avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/5980462/avatar.png","web_url":"https://gitlab.com/herrhotzenplotz"},"merge_user":{"id":5980462,"username":"herrhotzenplotz","name":"Nico Sonack","state":"active","avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/5980462/avatar.png","web_url":"https://gitlab.com/herrhotzenplotz"},"merged_at":"2023-09-01T17:20:02.486Z","closed_by":null,"closed_at":null,"target_branch":"trunk","source_branch":"fix-test-suite","user_notes_count":0,"upvotes":0,"downvotes":0,"author":{"id":5980462,"username":"herrhotzenplotz","name":"Nico Sonack","state":"active","avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/5980462/avatar.png","web_url":"https://gitlab.com/herrhotzenplotz"},"assignees":[],"assignee":null,"reviewers":[],"source_project_id":34707535,"target_project_id":34707535,"labels":[],"draft":false,"work_in_progress":false,"milestone":null,"merge_when_pipeline_succeeds":false,"merge_status":"can_be_merged","detailed_merge_status":"not_open","sha":"3eab596a6806434e4a34bb19de12307ab1217af3","merge_commit_sha":"767e01417ac36f0090ee6d5da737cfb5135e6fc6","squash_commit_sha":null,"discussion_locked":null,"should_remove_source_branch":false,"force_remove_source_branch":null,"prepared_at":"2023-08-31T23:37:58.547Z","reference":"!216","references":{"short":"!216","relative":"!216","full":"herrhotzenplotz/gcli!216"},"web_url":"https://gitlab.com/herrhotzenplotz/gcli/-/merge_requests/216","time_stats":{"time_estimate":0,"total_time_spent":0,"human_time_estimate":null,"human_total_time_spent":null},"squash":false,"squash_on_merge":false,"task_completion_status":{"count":0,"completed_count":0},"has_conflicts":false,"blocking_discussions_resolved":true,"approvals_before_merge":null,"subscribed":true,"changes_count":"98","latest_build_started_at":"2023-09-01T17:02:48.982Z","latest_build_finished_at":"2023-09-01T17:15:35.537Z","first_deployed_to_production_at":null,"pipeline":{"id":989409992,"iid":116,"project_id":34707535,"sha":"3eab596a6806434e4a34bb19de12307ab1217af3","ref":"refs/merge-requests/216/head","status":"success","source":"merge_request_event","created_at":"2023-09-01T17:02:48.091Z","updated_at":"2023-09-01T17:15:35.546Z","web_url":"https://gitlab.com/herrhotzenplotz/gcli/-/pipelines/989409992"},"head_pipeline":{"id":989409992,"iid":116,"project_id":34707535,"sha":"3eab596a6806434e4a34bb19de12307ab1217af3","ref":"refs/merge-requests/216/head","status":"success","source":"merge_request_event","created_at":"2023-09-01T17:02:48.091Z","updated_at":"2023-09-01T17:15:35.546Z","web_url":"https://gitlab.com/herrhotzenplotz/gcli/-/pipelines/989409992","before_sha":"0000000000000000000000000000000000000000","tag":false,"yaml_errors":null,"user":{"id":5980462,"username":"herrhotzenplotz","name":"Nico Sonack","state":"active","avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/5980462/avatar.png","web_url":"https://gitlab.com/herrhotzenplotz"},"started_at":"2023-09-01T17:02:48.982Z","finished_at":"2023-09-01T17:15:35.537Z","committed_at":null,"duration":450,"queued_duration":null,"coverage":null,"detailed_status":{"icon":"status_success","text":"passed","label":"passed","group":"success","tooltip":"passed","has_details":true,"details_path":"/herrhotzenplotz/gcli/-/pipelines/989409992","illustration":null,"favicon":"/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"}},"diff_refs":{"base_sha":"4295254675687c212df05a78f561566aea716780","head_sha":"3eab596a6806434e4a34bb19de12307ab1217af3","start_sha":"4295254675687c212df05a78f561566aea716780"},"merge_error":null,"first_contribution":false,"user":{"can_merge":true}} \ No newline at end of file diff --git a/tests/update-samples.sh b/tests/update-samples.sh index 9522e0fb..c65ca813 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -10,3 +10,5 @@ which gcli > /dev/null 2>&1 || die "gcli is not in PATH" gcli -t github api /repos/herrhotzenplotz/gcli/issues/115 > samples/github_simple_issue.json gcli -t github api /repos/herrhotzenplotz/gcli/labels/bug > samples/github_simple_label.json gcli -t github api /repos/herrhotzenplotz/gcli/pulls/113 > samples/github_simple_pull.json + +gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples/gitlab_simple_merge_request.json From fe3bf8494d7daf6da0ec86cb8998bc8beb5cafce Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 19:54:04 +0200 Subject: [PATCH 176/236] Add test for Gitlab Merge Request Parser While we're at it, fix the missing entry for the head_pipeline_id. --- templates/gitlab/merge_requests.t | 7 ++++++- tests/gitlab-parse-tests.c | 34 ++++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/templates/gitlab/merge_requests.t b/templates/gitlab/merge_requests.t index 3ef123e6..1a5811e9 100644 --- a/templates/gitlab/merge_requests.t +++ b/templates/gitlab/merge_requests.t @@ -4,6 +4,10 @@ parser gitlab_mr_milestone is object of gcli_pull with ("title" => milestone as string); +parser gitlab_mr_head_pipeline is +object of gcli_pull with + ("id" => head_pipeline_id as int); + parser gitlab_mr is object of gcli_pull with ("title" => title as string, @@ -20,7 +24,8 @@ object of gcli_pull with "source_branch" => head_label as string, "sha" => head_sha as string, "target_branch" => base_label as string, - "milestone" => use parse_gitlab_mr_milestone); + "milestone" => use parse_gitlab_mr_milestone, + "head_pipeline" => use parse_gitlab_mr_head_pipeline); parser gitlab_mrs is array of gcli_pull use parse_gitlab_mr; diff --git a/tests/gitlab-parse-tests.c b/tests/gitlab-parse-tests.c index cd47ca8b..18d43512 100644 --- a/tests/gitlab-parse-tests.c +++ b/tests/gitlab-parse-tests.c @@ -1,6 +1,4 @@ -#include -#include -#include +#include #include #include @@ -42,11 +40,37 @@ open_sample(char const *const name) ATF_TC_WITHOUT_HEAD(gitlab_simple_merge_request); ATF_TC_BODY(gitlab_simple_merge_request, tc) { + json_stream stream = {0}; gcli_ctx *ctx = test_context(); FILE *f = open_sample("gitlab_simple_merge_request.json"); + gcli_pull pull = {0}; - (void) ctx; - (void) f; + json_open_stream(&stream, f); + ATF_REQUIRE(parse_gitlab_mr(ctx, &stream, &pull) == 0); + + ATF_CHECK_STREQ(pull.author, "herrhotzenplotz"); + ATF_CHECK_STREQ(pull.state, "merged"); + ATF_CHECK_STREQ(pull.title, "Fix test suite"); + ATF_CHECK_STREQ(pull.body, "This finally fixes the broken test suite"); + ATF_CHECK_STREQ(pull.created_at, "2023-08-31T23:37:50.848Z"); + ATF_CHECK(pull.commits_link == NULL); + ATF_CHECK_STREQ(pull.head_label, "fix-test-suite"); + ATF_CHECK_STREQ(pull.base_label, "trunk"); + ATF_CHECK_STREQ(pull.head_sha, "3eab596a6806434e4a34bb19de12307ab1217af3"); + ATF_CHECK(pull.milestone == NULL); + ATF_CHECK(pull.id == 246912053); + ATF_CHECK(pull.number == 216); + ATF_CHECK(pull.comments == 0); // not supported + ATF_CHECK(pull.additions == 0); // not supported + ATF_CHECK(pull.deletions == 0); // not supported + ATF_CHECK(pull.commits == 0); // not supported + ATF_CHECK(pull.changed_files == 0); // not supported + ATF_CHECK(pull.head_pipeline_id == 989409992); + ATF_CHECK(pull.labels_size == 0); + ATF_CHECK(pull.labels == NULL); + ATF_CHECK(pull.merged == false); + ATF_CHECK(pull.mergeable == true); + ATF_CHECK(pull.draft == false); } ATF_TP_ADD_TCS(tp) From 9d54956e52d77efad7b5594c4a1882fb5b4bbab0 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 19:56:36 +0200 Subject: [PATCH 177/236] Add test for Gitlab Issue --- tests/gitlab-parse-tests.c | 29 ++++++++++++++++++++++++++ tests/samples/gitlab_simple_issue.json | 1 + tests/update-samples.sh | 1 + 3 files changed, 31 insertions(+) create mode 100644 tests/samples/gitlab_simple_issue.json diff --git a/tests/gitlab-parse-tests.c b/tests/gitlab-parse-tests.c index 18d43512..9a8fe02d 100644 --- a/tests/gitlab-parse-tests.c +++ b/tests/gitlab-parse-tests.c @@ -1,3 +1,4 @@ +#include #include #include @@ -73,8 +74,36 @@ ATF_TC_BODY(gitlab_simple_merge_request, tc) ATF_CHECK(pull.draft == false); } +ATF_TC_WITHOUT_HEAD(gitlab_simple_issue); +ATF_TC_BODY(gitlab_simple_issue, tc) +{ + json_stream stream = {0}; + gcli_ctx *ctx = test_context(); + FILE *f = open_sample("gitlab_simple_issue.json"); + gcli_issue issue = {0}; + + json_open_stream(&stream, f); + ATF_REQUIRE(parse_gitlab_issue(ctx, &stream, &issue) == 0); + + ATF_CHECK(issue.number == 193); + ATF_CHECK(sn_sv_eq_to(issue.title, "Make notifications API use a list struct containing both the ptr and size")); + ATF_CHECK(sn_sv_eq_to(issue.created_at, "2023-08-13T18:43:05.766Z")); + ATF_CHECK(sn_sv_eq_to(issue.author, "herrhotzenplotz")); + ATF_CHECK(sn_sv_eq_to(issue.state, "closed")); + ATF_CHECK(issue.comments == 2); + ATF_CHECK(issue.locked == false); + ATF_CHECK(sn_sv_eq_to(issue.body, "That would make some of the code much cleaner")); + ATF_CHECK(issue.labels_size == 1); + ATF_CHECK(sn_sv_eq_to(issue.labels[0], "good-first-issue")); + ATF_CHECK(issue.assignees == NULL); + ATF_CHECK(issue.assignees_size == 0); + ATF_CHECK(issue.is_pr == 0); + ATF_CHECK(sn_sv_null(issue.milestone)); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, gitlab_simple_merge_request); + ATF_TP_ADD_TC(tp, gitlab_simple_issue); return atf_no_error(); } diff --git a/tests/samples/gitlab_simple_issue.json b/tests/samples/gitlab_simple_issue.json new file mode 100644 index 00000000..372e0aca --- /dev/null +++ b/tests/samples/gitlab_simple_issue.json @@ -0,0 +1 @@ +{"id":132128913,"iid":193,"project_id":34707535,"title":"Make notifications API use a list struct containing both the ptr and size","description":"That would make some of the code much cleaner","state":"closed","created_at":"2023-08-13T18:43:05.766Z","updated_at":"2023-08-23T23:51:46.360Z","closed_at":"2023-08-23T23:51:46.350Z","closed_by":{"id":5980462,"username":"herrhotzenplotz","name":"Nico Sonack","state":"active","avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/5980462/avatar.png","web_url":"https://gitlab.com/herrhotzenplotz"},"labels":["good-first-issue"],"milestone":null,"assignees":[],"author":{"id":5980462,"username":"herrhotzenplotz","name":"Nico Sonack","state":"active","avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/5980462/avatar.png","web_url":"https://gitlab.com/herrhotzenplotz"},"type":"ISSUE","assignee":null,"user_notes_count":2,"merge_requests_count":0,"upvotes":0,"downvotes":0,"due_date":null,"confidential":false,"discussion_locked":null,"issue_type":"issue","web_url":"https://gitlab.com/herrhotzenplotz/gcli/-/issues/193","time_stats":{"time_estimate":0,"total_time_spent":0,"human_time_estimate":null,"human_total_time_spent":null},"task_completion_status":{"count":0,"completed_count":0},"blocking_issues_count":0,"has_tasks":true,"task_status":"0 of 0 checklist items completed","_links":{"self":"https://gitlab.com/api/v4/projects/34707535/issues/193","notes":"https://gitlab.com/api/v4/projects/34707535/issues/193/notes","award_emoji":"https://gitlab.com/api/v4/projects/34707535/issues/193/award_emoji","project":"https://gitlab.com/api/v4/projects/34707535","closed_as_duplicate_of":null},"references":{"short":"#193","relative":"#193","full":"herrhotzenplotz/gcli#193"},"severity":"UNKNOWN","subscribed":true,"moved_to_id":null,"service_desk_reply_to":null} \ No newline at end of file diff --git a/tests/update-samples.sh b/tests/update-samples.sh index c65ca813..3b5c79ae 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -12,3 +12,4 @@ gcli -t github api /repos/herrhotzenplotz/gcli/labels/bug > samples/github_simpl gcli -t github api /repos/herrhotzenplotz/gcli/pulls/113 > samples/github_simple_pull.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples/gitlab_simple_merge_request.json +gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/issues/152 > tests/samples/gitlab_simple_issue.json From 31f50e865bc31e4d4994813fcec6cdaca732d445 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 20:19:30 +0200 Subject: [PATCH 178/236] Add test for Gitlab Labels --- tests/gitlab-parse-tests.c | 19 +++++++++++++++++++ tests/samples/gitlab_simple_label.json | 1 + tests/update-samples.sh | 1 + 3 files changed, 21 insertions(+) create mode 100644 tests/samples/gitlab_simple_label.json diff --git a/tests/gitlab-parse-tests.c b/tests/gitlab-parse-tests.c index 9a8fe02d..739d24a2 100644 --- a/tests/gitlab-parse-tests.c +++ b/tests/gitlab-parse-tests.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -101,9 +102,27 @@ ATF_TC_BODY(gitlab_simple_issue, tc) ATF_CHECK(sn_sv_null(issue.milestone)); } +ATF_TC_WITHOUT_HEAD(gitlab_simple_label); +ATF_TC_BODY(gitlab_simple_label, tc) +{ + json_stream stream = {0}; + gcli_ctx *ctx = test_context(); + FILE *f = open_sample("gitlab_simple_label.json"); + gcli_label label = {0}; + + json_open_stream(&stream, f); + ATF_REQUIRE(parse_gitlab_label(ctx, &stream, &label) == 0); + + ATF_CHECK(label.id == 24376073); + ATF_CHECK_STREQ(label.name, "bug"); + ATF_CHECK_STREQ(label.description, "Something isn't working as expected"); + ATF_CHECK(label.colour == 0xD73A4A00); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, gitlab_simple_merge_request); ATF_TP_ADD_TC(tp, gitlab_simple_issue); + ATF_TP_ADD_TC(tp, gitlab_simple_label); return atf_no_error(); } diff --git a/tests/samples/gitlab_simple_label.json b/tests/samples/gitlab_simple_label.json new file mode 100644 index 00000000..7e8308d4 --- /dev/null +++ b/tests/samples/gitlab_simple_label.json @@ -0,0 +1 @@ +{"id":24376073,"name":"bug","description":"Something isn't working as expected","description_html":"Something isn't working as expected","text_color":"#FFFFFF","color":"#d73a4a","subscribed":false,"priority":null,"is_project_label":true} \ No newline at end of file diff --git a/tests/update-samples.sh b/tests/update-samples.sh index 3b5c79ae..115347fe 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -13,3 +13,4 @@ gcli -t github api /repos/herrhotzenplotz/gcli/pulls/113 > samples/github_simple gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples/gitlab_simple_merge_request.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/issues/152 > tests/samples/gitlab_simple_issue.json +gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/labels/24376073 > tests/samples/gitlab_simple_label.json From 2284d171afa2b751b1192f5788476cec2efae491 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 20:53:21 +0200 Subject: [PATCH 179/236] Fix distcheck --- Makefile.am | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Makefile.am b/Makefile.am index 6e659691..0c07b6d1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -238,4 +238,12 @@ tests_url_encode_LDADD = \ tests_pretty_print_test_LDADD = \ libsn.la \ $(LIBATFC_LDFLAGS) + +EXTRA_DIST += tests/samples/github_simple_issue.json \ + tests/samples/github_simple_label.json \ + tests/samples/github_simple_pull.json \ + tests/samples/gitlab_simple_issue.json \ + tests/samples/gitlab_simple_label.json \ + tests/samples/gitlab_simple_merge_request.json + endif From 095666a4003feafb0bbdd23858431dc07aae92cb Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 20:53:30 +0200 Subject: [PATCH 180/236] Fix installation path of headers --- Makefile.am | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Makefile.am b/Makefile.am index 0c07b6d1..d83fde97 100644 --- a/Makefile.am +++ b/Makefile.am @@ -118,12 +118,13 @@ TEMPLATES = \ templates/gitlab/snippets.t \ templates/gitea/milestones.t -include_HEADERS = include/gcli/gcli.h include/gcli/comments.h \ - include/gcli/curl.h include/gcli/forks.h \ - include/gcli/issues.h include/gcli/labels.h \ - include/gcli/milestones.h include/gcli/pulls.h \ - include/gcli/releases.h include/gcli/repos.h \ - include/gcli/review.h include/gcli/gitlab/snippets.h \ +headerdir = $(prefix) +nobase_header_HEADERS = include/gcli/gcli.h include/gcli/comments.h \ + include/gcli/curl.h include/gcli/forks.h \ + include/gcli/issues.h include/gcli/labels.h \ + include/gcli/milestones.h include/gcli/pulls.h \ + include/gcli/releases.h include/gcli/repos.h \ + include/gcli/review.h include/gcli/gitlab/snippets.h \ include/gcli/status.h include/gcli/sshkeys.h libgcli_la_SOURCES = \ From 8b16545ebcee12b5918bfeb835f9d90e03582f80 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Sep 2023 21:24:35 +0200 Subject: [PATCH 181/236] Update documentation and bump version I was missing the dependencies on Kyua and libatf in both the README and HACKING. Also, bump the version to a new alpha for people to test. --- HACKING.md | 3 +++ README.md | 9 ++++++++- configure.ac | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/HACKING.md b/HACKING.md index 43454dd2..75e3fdd5 100644 --- a/HACKING.md +++ b/HACKING.md @@ -99,6 +99,9 @@ to cram it into the LDFLAGS. ## Tests +The test suite depends on [Kyua](https://github.com/jmmv/kyua) and +[libatf-c](https://github.com/jmmv/atf). + Before submitting patches please make sure that your changes pass the test suite: diff --git a/README.md b/README.md index 248d8fe9..41ab42f5 100644 --- a/README.md +++ b/README.md @@ -44,16 +44,23 @@ Packages that are work-in-progress: Required dependencies: - libcurl -- pkg-config - yacc (System V yacc, Berkeley Yacc or Bison should suffice) - lex (flex is preferred) - C99 Compiler and linker - make +Optional dependencies: +- pkg-config + If you are building from Git you will also need: +- m4 - autoconf - automake +The test suite requires: +- [Kyua](https://github.com/jmmv/kyua) +- [ATF](https://github.com/jmmv/atf) + ### Compile In order to perform a build, do: ```console diff --git a/configure.ac b/configure.ac index 6926508f..a7239e34 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([gcli],[2.0.0-ALPHA1],[nsonack@herrhotzenplotz.de],[gcli],[https://gitlab.com/herrhotzenplotz/gcli/]) +AC_INIT([gcli],[2.0.0-ALPHA2],[nsonack@herrhotzenplotz.de],[gcli],[https://gitlab.com/herrhotzenplotz/gcli/]) AM_INIT_AUTOMAKE([1.0 foreign subdir-objects dist-bzip2 dist-xz -Wall]) dnl Release Date. From 1df0d0c56e0ab890ee062e92fcf704f3c70ca464 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 00:00:51 +0200 Subject: [PATCH 182/236] Fix gitea auth header generation --- src/gitea/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gitea/config.c b/src/gitea/config.c index 748ae1ea..5b22ec09 100644 --- a/src/gitea/config.c +++ b/src/gitea/config.c @@ -35,5 +35,5 @@ char * gitea_make_authheader(gcli_ctx *ctx, char const *token) { (void) ctx; - return sn_asprintf("Authorization: %s", token); + return sn_asprintf("Authorization: token %s", token); } From faa2e8ffad228f97b0ee13dc356dd2665877a69c Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 00:08:40 +0200 Subject: [PATCH 183/236] Update todo.org --- todo.org | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/todo.org b/todo.org index a898c0f8..30a49263 100644 --- a/todo.org +++ b/todo.org @@ -123,14 +123,14 @@ + https://api.github.com/repos/zorchenhimer/MovieNight/pulls/156/reviews/611653998/comments * Big refactor for libraryfication -** TODO Fix test suite - - [ ] Move config stuff to cmd and have callbacks that given the +** DONE Fix test suite + - [X] Move config stuff to cmd and have callbacks that given the context give you the account details etc. This would allow you to create a mock context that returns only values that make sense in test contexts. - - [ ] Add support for a testing gcli context + - [X] Add support for a testing gcli context ** DONE Check errx calls if they print "error: " ** DONE Check for calls to errx in submit routines ** TODO [[file:src/github/review.c::github_review_get_reviews(char const *owner)][github_review_get_reviews]] is garbage @@ -146,3 +146,33 @@ ** TODO Add a real changelog file ** DONE include [[file:docs/pgen.org][docs/pgen.org]] in the distribution tarball ** DONE remove gcli_print_html_url +** TODO Test suite +*** TODO Github [23%] + - [ ] Checks + - [ ] Comments + - [ ] Forks + - [ ] Gists + - [ ] Milestones + - [ ] Releases + - [ ] Repos + - [ ] Reviews + - [ ] SSH keys + - [ ] Status + - [X] Issues + - [X] Labels + - [X] Pulls +*** TODO Gitlab [25%] + - [ ] Comments + - [ ] Forks + - [ ] Milestones + - [ ] Pipelines + - [ ] Releases + - [ ] Repos + - [ ] Reviews + - [ ] SSH Keys + - [ ] Snippets + - [ ] Status + - [X] Issues + - [X] Labels + - [X] Merge Requests +*** TODO Gitea From b027f5a7ab2462bd95a06f297a21c22552dd27c2 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 13:36:13 +0200 Subject: [PATCH 184/236] tests: Fix buggy update script I dunno how I missed this. --- tests/update-samples.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/update-samples.sh b/tests/update-samples.sh index 115347fe..87eba44c 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -12,5 +12,5 @@ gcli -t github api /repos/herrhotzenplotz/gcli/labels/bug > samples/github_simpl gcli -t github api /repos/herrhotzenplotz/gcli/pulls/113 > samples/github_simple_pull.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples/gitlab_simple_merge_request.json -gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/issues/152 > tests/samples/gitlab_simple_issue.json -gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/labels/24376073 > tests/samples/gitlab_simple_label.json +gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/issues/193 > samples/gitlab_simple_issue.json +gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/labels/24376073 > samples/gitlab_simple_label.json From 1f444811fcd8734b78282bc623f61dbda990af49 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 16:37:43 +0200 Subject: [PATCH 185/236] Add test for Github milestone --- Makefile.am | 1 + tests/github-parse-tests.c | 29 ++++++++++++++++- tests/samples/github_simple_milestone.json | 37 ++++++++++++++++++++++ tests/update-samples.sh | 1 + todo.org | 4 +-- 5 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 tests/samples/github_simple_milestone.json diff --git a/Makefile.am b/Makefile.am index d83fde97..600f9d09 100644 --- a/Makefile.am +++ b/Makefile.am @@ -242,6 +242,7 @@ tests_pretty_print_test_LDADD = \ EXTRA_DIST += tests/samples/github_simple_issue.json \ tests/samples/github_simple_label.json \ + tests/samples/github_simple_milestone.json \ tests/samples/github_simple_pull.json \ tests/samples/gitlab_simple_issue.json \ tests/samples/gitlab_simple_label.json \ diff --git a/tests/github-parse-tests.c b/tests/github-parse-tests.c index 5a5939ba..0648599b 100644 --- a/tests/github-parse-tests.c +++ b/tests/github-parse-tests.c @@ -1,6 +1,7 @@ #include -#include #include +#include +#include #include #include @@ -131,11 +132,37 @@ ATF_TC_BODY(simple_github_label, tc) ATF_CHECK(label.colour == 0xd73a4a00); } +ATF_TC_WITHOUT_HEAD(simple_github_milestone); +ATF_TC_BODY(simple_github_milestone, tc) +{ + gcli_milestone milestone = {0}; + FILE *f; + json_stream stream; + gcli_ctx *ctx = test_context(); + + ATF_REQUIRE(f = open_sample("github_simple_milestone.json")); + json_open_stream(&stream, f); + + ATF_REQUIRE(parse_github_milestone(ctx, &stream, &milestone) == 0); + + ATF_CHECK(milestone.id == 1); + ATF_CHECK_STREQ(milestone.title, "Gitlab support"); + ATF_CHECK_STREQ(milestone.state, "open"); + ATF_CHECK_STREQ(milestone.created_at, "2021-12-14T07:02:05Z"); + ATF_CHECK_STREQ(milestone.description, ""); + ATF_CHECK_STREQ(milestone.updated_at, "2021-12-19T14:49:43Z"); + ATF_CHECK(milestone.due_date == NULL); + ATF_CHECK(milestone.expired == false); + ATF_CHECK(milestone.open_issues == 0); + ATF_CHECK(milestone.closed_issues == 8); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, simple_github_issue); ATF_TP_ADD_TC(tp, simple_github_pull); ATF_TP_ADD_TC(tp, simple_github_label); + ATF_TP_ADD_TC(tp, simple_github_milestone); return atf_no_error(); } diff --git a/tests/samples/github_simple_milestone.json b/tests/samples/github_simple_milestone.json new file mode 100644 index 00000000..f8f6747f --- /dev/null +++ b/tests/samples/github_simple_milestone.json @@ -0,0 +1,37 @@ +{ + "url": "https://api.github.com/repos/herrhotzenplotz/gcli/milestones/1", + "html_url": "https://github.com/herrhotzenplotz/gcli/milestone/1", + "labels_url": "https://api.github.com/repos/herrhotzenplotz/gcli/milestones/1/labels", + "id": 7485436, + "node_id": "MI_kwDOGLyhHc4Acjf8", + "number": 1, + "title": "Gitlab support", + "description": "", + "creator": { + "login": "herrhotzenplotz", + "id": 34663024, + "node_id": "MDQ6VXNlcjM0NjYzMDI0", + "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/herrhotzenplotz", + "html_url": "https://github.com/herrhotzenplotz", + "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", + "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", + "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", + "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", + "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", + "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", + "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", + "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", + "type": "User", + "site_admin": false + }, + "open_issues": 0, + "closed_issues": 8, + "state": "open", + "created_at": "2021-12-14T07:02:05Z", + "updated_at": "2021-12-19T14:49:43Z", + "due_on": null, + "closed_at": null +} diff --git a/tests/update-samples.sh b/tests/update-samples.sh index 87eba44c..c430c4ac 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -10,6 +10,7 @@ which gcli > /dev/null 2>&1 || die "gcli is not in PATH" gcli -t github api /repos/herrhotzenplotz/gcli/issues/115 > samples/github_simple_issue.json gcli -t github api /repos/herrhotzenplotz/gcli/labels/bug > samples/github_simple_label.json gcli -t github api /repos/herrhotzenplotz/gcli/pulls/113 > samples/github_simple_pull.json +gcli -t github api /repos/herrhotzenplotz/gcli/milestones/1 > samples/github_simple_milestone.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples/gitlab_simple_merge_request.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/issues/193 > samples/gitlab_simple_issue.json diff --git a/todo.org b/todo.org index 30a49263..c186041b 100644 --- a/todo.org +++ b/todo.org @@ -147,12 +147,12 @@ ** DONE include [[file:docs/pgen.org][docs/pgen.org]] in the distribution tarball ** DONE remove gcli_print_html_url ** TODO Test suite -*** TODO Github [23%] +*** TODO Github [30%] - [ ] Checks - [ ] Comments - [ ] Forks - [ ] Gists - - [ ] Milestones + - [X] Milestones - [ ] Releases - [ ] Repos - [ ] Reviews From 00bbd5e0f118883cd57a5e5c1b95951debc8da15 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 15:36:26 +0200 Subject: [PATCH 186/236] Update todo.org --- todo.org | 1 + 1 file changed, 1 insertion(+) diff --git a/todo.org b/todo.org index c186041b..0e75c3a1 100644 --- a/todo.org +++ b/todo.org @@ -176,3 +176,4 @@ - [X] Labels - [X] Merge Requests *** TODO Gitea +** TODO add an ATF macro for comparing string views From c06a4b2cfcf8b063c5d67c7d722bbfcbc8ff5d8a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 16:38:05 +0200 Subject: [PATCH 187/236] Add tests for Github releases --- Makefile.am | 2 ++ tests/github-parse-tests.c | 28 ++++++++++++++++ tests/samples/github_simple_release.json | 41 ++++++++++++++++++++++++ tests/update-samples.sh | 1 + todo.org | 4 +-- 5 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 tests/samples/github_simple_release.json diff --git a/Makefile.am b/Makefile.am index 600f9d09..dff0d9e6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -243,6 +243,8 @@ tests_pretty_print_test_LDADD = \ EXTRA_DIST += tests/samples/github_simple_issue.json \ tests/samples/github_simple_label.json \ tests/samples/github_simple_milestone.json \ + tests/samples/github_simple_fork.json \ + tests/samples/github_simple_release.json \ tests/samples/github_simple_pull.json \ tests/samples/gitlab_simple_issue.json \ tests/samples/gitlab_simple_label.json \ diff --git a/tests/github-parse-tests.c b/tests/github-parse-tests.c index 0648599b..f2d26367 100644 --- a/tests/github-parse-tests.c +++ b/tests/github-parse-tests.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -157,12 +158,39 @@ ATF_TC_BODY(simple_github_milestone, tc) ATF_CHECK(milestone.closed_issues == 8); } +ATF_TC_WITHOUT_HEAD(simple_github_release); +ATF_TC_BODY(simple_github_release, tc) +{ + gcli_release release = {0}; + FILE *f; + json_stream stream; + gcli_ctx *ctx = test_context(); + + ATF_REQUIRE(f = open_sample("github_simple_release.json")); + json_open_stream(&stream, f); + + ATF_REQUIRE(parse_github_release(ctx, &stream, &release) == 0); + + ATF_CHECK(sn_sv_eq_to(release.id, "116031718")); + ATF_CHECK(release.assets_size == 0); + ATF_CHECK(release.assets == NULL); + ATF_CHECK(sn_sv_eq_to(release.name, "1.2.0")); + ATF_CHECK(sn_sv_eq_to(release.body, "# Version 1.2.0\n\nThis is version 1.2.0 of gcli.\n\n## Notes\n\nPlease test and report bugs.\n\nYou can download autotoolized tarballs at: https://herrhotzenplotz.de/gcli/releases/gcli-1.2.0/\n\n## Bug Fixes\n\n- Fix compile error when providing --with-libcurl without any arguments\n- Fix memory leaks in string processing functions\n- Fix missing nul termination in read-file function\n- Fix segmentation fault when clearing the milestone of a PR on Gitea\n- Fix missing documentation for milestone action in issues and pulls\n- Set the 'merged' flag properly when showing Gitlab merge requests\n\n## New features\n\n- Add a config subcommand for managing ssh keys (see gcli-config(1))\n- Show number of comments/notes in list of issues and PRs\n- Add support for milestone management in pull requests\n")); + ATF_CHECK(sn_sv_eq_to(release.author, "herrhotzenplotz")); + ATF_CHECK(sn_sv_eq_to(release.date, "2023-08-11T07:42:37Z")); + ATF_CHECK(sn_sv_eq_to(release.upload_url, "https://uploads.github.com/repos/herrhotzenplotz/gcli/releases/116031718/assets{?name,label}")); + ATF_CHECK(sn_sv_eq_to(release.html_url, "https://github.com/herrhotzenplotz/gcli/releases/tag/1.2.0")); + ATF_CHECK(release.draft == false); + ATF_CHECK(release.prerelease == false); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, simple_github_issue); ATF_TP_ADD_TC(tp, simple_github_pull); ATF_TP_ADD_TC(tp, simple_github_label); ATF_TP_ADD_TC(tp, simple_github_milestone); + ATF_TP_ADD_TC(tp, simple_github_release); return atf_no_error(); } diff --git a/tests/samples/github_simple_release.json b/tests/samples/github_simple_release.json new file mode 100644 index 00000000..d6d3d6f2 --- /dev/null +++ b/tests/samples/github_simple_release.json @@ -0,0 +1,41 @@ +{ + "url": "https://api.github.com/repos/herrhotzenplotz/gcli/releases/116031718", + "assets_url": "https://api.github.com/repos/herrhotzenplotz/gcli/releases/116031718/assets", + "upload_url": "https://uploads.github.com/repos/herrhotzenplotz/gcli/releases/116031718/assets{?name,label}", + "html_url": "https://github.com/herrhotzenplotz/gcli/releases/tag/1.2.0", + "id": 116031718, + "author": { + "login": "herrhotzenplotz", + "id": 34663024, + "node_id": "MDQ6VXNlcjM0NjYzMDI0", + "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/herrhotzenplotz", + "html_url": "https://github.com/herrhotzenplotz", + "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", + "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", + "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", + "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", + "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", + "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", + "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", + "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", + "type": "User", + "site_admin": false + }, + "node_id": "RE_kwDOGLyhHc4G6oDm", + "tag_name": "1.2.0", + "target_commitish": "release", + "name": "1.2.0", + "draft": false, + "prerelease": false, + "created_at": "2023-08-11T07:42:37Z", + "published_at": "2023-08-11T07:58:26Z", + "assets": [ + + ], + "tarball_url": "https://api.github.com/repos/herrhotzenplotz/gcli/tarball/1.2.0", + "zipball_url": "https://api.github.com/repos/herrhotzenplotz/gcli/zipball/1.2.0", + "body": "# Version 1.2.0\n\nThis is version 1.2.0 of gcli.\n\n## Notes\n\nPlease test and report bugs.\n\nYou can download autotoolized tarballs at: https://herrhotzenplotz.de/gcli/releases/gcli-1.2.0/\n\n## Bug Fixes\n\n- Fix compile error when providing --with-libcurl without any arguments\n- Fix memory leaks in string processing functions\n- Fix missing nul termination in read-file function\n- Fix segmentation fault when clearing the milestone of a PR on Gitea\n- Fix missing documentation for milestone action in issues and pulls\n- Set the 'merged' flag properly when showing Gitlab merge requests\n\n## New features\n\n- Add a config subcommand for managing ssh keys (see gcli-config(1))\n- Show number of comments/notes in list of issues and PRs\n- Add support for milestone management in pull requests\n" +} diff --git a/tests/update-samples.sh b/tests/update-samples.sh index c430c4ac..7c2693a1 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -11,6 +11,7 @@ gcli -t github api /repos/herrhotzenplotz/gcli/issues/115 > samples/github_simpl gcli -t github api /repos/herrhotzenplotz/gcli/labels/bug > samples/github_simple_label.json gcli -t github api /repos/herrhotzenplotz/gcli/pulls/113 > samples/github_simple_pull.json gcli -t github api /repos/herrhotzenplotz/gcli/milestones/1 > samples/github_simple_milestone.json +gcli -t github api /repos/herrhotzenplotz/gcli/releases/116031718 > samples/github_simple_release.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples/gitlab_simple_merge_request.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/issues/193 > samples/gitlab_simple_issue.json diff --git a/todo.org b/todo.org index 0e75c3a1..e4c3d981 100644 --- a/todo.org +++ b/todo.org @@ -147,13 +147,13 @@ ** DONE include [[file:docs/pgen.org][docs/pgen.org]] in the distribution tarball ** DONE remove gcli_print_html_url ** TODO Test suite -*** TODO Github [30%] +*** TODO Github [38%] - [ ] Checks - [ ] Comments - [ ] Forks - [ ] Gists - [X] Milestones - - [ ] Releases + - [X] Releases - [ ] Repos - [ ] Reviews - [ ] SSH keys From b9dfdff237a33a7345813ab4e1fe9e5d927392d0 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 15:54:13 +0200 Subject: [PATCH 188/236] github repos: parse missing id Seen during a test failure --- templates/github/repos.t | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/github/repos.t b/templates/github/repos.t index 16cd4bec..03495c6d 100644 --- a/templates/github/repos.t +++ b/templates/github/repos.t @@ -3,7 +3,8 @@ include "gcli/gitea/repos.h"; parser github_repo is object of gcli_repo with - ("full_name" => full_name as sv, + ("id" => id as int, + "full_name" => full_name as sv, "name" => name as sv, "owner" => owner as user_sv, "created_at" => date as sv, From 56cdca49c3198f7152a4d11845f5ace1df4d9d16 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 16:38:12 +0200 Subject: [PATCH 189/236] Add test for Github Repositories --- Makefile.am | 1 + tests/github-parse-tests.c | 24 +++++ tests/samples/github_simple_repo.json | 148 ++++++++++++++++++++++++++ tests/update-samples.sh | 1 + todo.org | 4 +- 5 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 tests/samples/github_simple_repo.json diff --git a/Makefile.am b/Makefile.am index dff0d9e6..3c7207eb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -245,6 +245,7 @@ EXTRA_DIST += tests/samples/github_simple_issue.json \ tests/samples/github_simple_milestone.json \ tests/samples/github_simple_fork.json \ tests/samples/github_simple_release.json \ + tests/samples/github_simple_repo.json \ tests/samples/github_simple_pull.json \ tests/samples/gitlab_simple_issue.json \ tests/samples/gitlab_simple_label.json \ diff --git a/tests/github-parse-tests.c b/tests/github-parse-tests.c index f2d26367..13eca8e8 100644 --- a/tests/github-parse-tests.c +++ b/tests/github-parse-tests.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -184,6 +185,28 @@ ATF_TC_BODY(simple_github_release, tc) ATF_CHECK(release.prerelease == false); } +ATF_TC_WITHOUT_HEAD(simple_github_repo); +ATF_TC_BODY(simple_github_repo, tc) +{ + gcli_repo repo = {0}; + FILE *f; + json_stream stream; + gcli_ctx *ctx = test_context(); + + ATF_REQUIRE(f = open_sample("github_simple_repo.json")); + json_open_stream(&stream, f); + + ATF_REQUIRE(parse_github_repo(ctx, &stream, &repo) == 0); + + ATF_CHECK(repo.id == 415015197); + ATF_CHECK(sn_sv_eq_to(repo.full_name, "herrhotzenplotz/gcli")); + ATF_CHECK(sn_sv_eq_to(repo.name, "gcli")); + ATF_CHECK(sn_sv_eq_to(repo.owner, "herrhotzenplotz")); + ATF_CHECK(sn_sv_eq_to(repo.date, "2021-10-08T14:20:15Z")); + ATF_CHECK(sn_sv_eq_to(repo.visibility, "public")); + ATF_CHECK(repo.is_fork == false); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, simple_github_issue); @@ -191,6 +214,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, simple_github_label); ATF_TP_ADD_TC(tp, simple_github_milestone); ATF_TP_ADD_TC(tp, simple_github_release); + ATF_TP_ADD_TC(tp, simple_github_repo); return atf_no_error(); } diff --git a/tests/samples/github_simple_repo.json b/tests/samples/github_simple_repo.json new file mode 100644 index 00000000..9fca2ca8 --- /dev/null +++ b/tests/samples/github_simple_repo.json @@ -0,0 +1,148 @@ +{ + "id": 415015197, + "node_id": "R_kgDOGLyhHQ", + "name": "gcli", + "full_name": "herrhotzenplotz/gcli", + "private": false, + "owner": { + "login": "herrhotzenplotz", + "id": 34663024, + "node_id": "MDQ6VXNlcjM0NjYzMDI0", + "avatar_url": "https://avatars.githubusercontent.com/u/34663024?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/herrhotzenplotz", + "html_url": "https://github.com/herrhotzenplotz", + "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", + "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", + "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", + "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", + "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", + "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", + "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", + "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/herrhotzenplotz/gcli", + "description": "Somewhat portable and secure CLI utility to interact with both GitHub and GitLab. Development is happening at https://gitlab.com/herrhotzenplotz/gcli but you can also submit issues/PRs here.", + "fork": false, + "url": "https://api.github.com/repos/herrhotzenplotz/gcli", + "forks_url": "https://api.github.com/repos/herrhotzenplotz/gcli/forks", + "keys_url": "https://api.github.com/repos/herrhotzenplotz/gcli/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/herrhotzenplotz/gcli/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/herrhotzenplotz/gcli/teams", + "hooks_url": "https://api.github.com/repos/herrhotzenplotz/gcli/hooks", + "issue_events_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/events{/number}", + "events_url": "https://api.github.com/repos/herrhotzenplotz/gcli/events", + "assignees_url": "https://api.github.com/repos/herrhotzenplotz/gcli/assignees{/user}", + "branches_url": "https://api.github.com/repos/herrhotzenplotz/gcli/branches{/branch}", + "tags_url": "https://api.github.com/repos/herrhotzenplotz/gcli/tags", + "blobs_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/herrhotzenplotz/gcli/statuses/{sha}", + "languages_url": "https://api.github.com/repos/herrhotzenplotz/gcli/languages", + "stargazers_url": "https://api.github.com/repos/herrhotzenplotz/gcli/stargazers", + "contributors_url": "https://api.github.com/repos/herrhotzenplotz/gcli/contributors", + "subscribers_url": "https://api.github.com/repos/herrhotzenplotz/gcli/subscribers", + "subscription_url": "https://api.github.com/repos/herrhotzenplotz/gcli/subscription", + "commits_url": "https://api.github.com/repos/herrhotzenplotz/gcli/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/herrhotzenplotz/gcli/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/herrhotzenplotz/gcli/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/herrhotzenplotz/gcli/contents/{+path}", + "compare_url": "https://api.github.com/repos/herrhotzenplotz/gcli/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/herrhotzenplotz/gcli/merges", + "archive_url": "https://api.github.com/repos/herrhotzenplotz/gcli/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/herrhotzenplotz/gcli/downloads", + "issues_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues{/number}", + "pulls_url": "https://api.github.com/repos/herrhotzenplotz/gcli/pulls{/number}", + "milestones_url": "https://api.github.com/repos/herrhotzenplotz/gcli/milestones{/number}", + "notifications_url": "https://api.github.com/repos/herrhotzenplotz/gcli/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/herrhotzenplotz/gcli/labels{/name}", + "releases_url": "https://api.github.com/repos/herrhotzenplotz/gcli/releases{/id}", + "deployments_url": "https://api.github.com/repos/herrhotzenplotz/gcli/deployments", + "created_at": "2021-10-08T14:20:15Z", + "updated_at": "2023-08-15T20:58:16Z", + "pushed_at": "2023-09-01T22:01:34Z", + "git_url": "git://github.com/herrhotzenplotz/gcli.git", + "ssh_url": "git@github.com:herrhotzenplotz/gcli.git", + "clone_url": "https://github.com/herrhotzenplotz/gcli.git", + "svn_url": "https://github.com/herrhotzenplotz/gcli", + "homepage": "https://herrhotzenplotz.de/gcli/", + "size": 2531, + "stargazers_count": 19, + "watchers_count": 19, + "language": "C", + "has_issues": true, + "has_projects": false, + "has_downloads": true, + "has_wiki": false, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 0, + "license": { + "key": "bsd-2-clause", + "name": "BSD 2-Clause \"Simplified\" License", + "spdx_id": "BSD-2-Clause", + "url": "https://api.github.com/licenses/bsd-2-clause", + "node_id": "MDc6TGljZW5zZTQ=" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [ + "c", + "cli", + "freebsd", + "github-api", + "gitlab", + "gitlab-api", + "libcurl", + "linux", + "unix" + ], + "visibility": "public", + "forks": 0, + "open_issues": 0, + "watchers": 19, + "default_branch": "trunk", + "permissions": { + "admin": true, + "maintain": true, + "push": true, + "triage": true, + "pull": true + }, + "temp_clone_token": "", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE", + "security_and_analysis": { + "secret_scanning": { + "status": "disabled" + }, + "secret_scanning_push_protection": { + "status": "disabled" + }, + "dependabot_security_updates": { + "status": "disabled" + } + }, + "network_count": 0, + "subscribers_count": 4 +} diff --git a/tests/update-samples.sh b/tests/update-samples.sh index 7c2693a1..6ac651af 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -12,6 +12,7 @@ gcli -t github api /repos/herrhotzenplotz/gcli/labels/bug > samples/github_simpl gcli -t github api /repos/herrhotzenplotz/gcli/pulls/113 > samples/github_simple_pull.json gcli -t github api /repos/herrhotzenplotz/gcli/milestones/1 > samples/github_simple_milestone.json gcli -t github api /repos/herrhotzenplotz/gcli/releases/116031718 > samples/github_simple_release.json +gcli -t github api /repos/herrhotzenplotz/gcli > samples/github_simple_repo.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples/gitlab_simple_merge_request.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/issues/193 > samples/gitlab_simple_issue.json diff --git a/todo.org b/todo.org index e4c3d981..e253ad17 100644 --- a/todo.org +++ b/todo.org @@ -147,14 +147,14 @@ ** DONE include [[file:docs/pgen.org][docs/pgen.org]] in the distribution tarball ** DONE remove gcli_print_html_url ** TODO Test suite -*** TODO Github [38%] +*** TODO Github [46%] - [ ] Checks - [ ] Comments - [ ] Forks - [ ] Gists - [X] Milestones - [X] Releases - - [ ] Repos + - [X] Repos - [ ] Reviews - [ ] SSH keys - [ ] Status From 77762ceb57e869eb783bccc41e7bbb4b9e8dcabe Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 16:25:24 +0200 Subject: [PATCH 190/236] Add tests for github forks --- tests/github-parse-tests.c | 21 +++++ tests/samples/github_simple_fork.json | 113 ++++++++++++++++++++++++++ tests/update-samples.sh | 2 + todo.org | 4 +- 4 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 tests/samples/github_simple_fork.json diff --git a/tests/github-parse-tests.c b/tests/github-parse-tests.c index 13eca8e8..2ddf76f0 100644 --- a/tests/github-parse-tests.c +++ b/tests/github-parse-tests.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -207,6 +208,25 @@ ATF_TC_BODY(simple_github_repo, tc) ATF_CHECK(repo.is_fork == false); } +ATF_TC_WITHOUT_HEAD(simple_github_fork); +ATF_TC_BODY(simple_github_fork, tc) +{ + gcli_fork fork = {0}; + FILE *f; + json_stream stream; + gcli_ctx *ctx = test_context(); + + ATF_REQUIRE(f = open_sample("github_simple_fork.json")); + json_open_stream(&stream, f); + + ATF_REQUIRE(parse_github_fork(ctx, &stream, &fork) == 0); + + ATF_CHECK(sn_sv_eq_to(fork.full_name, "gjnoonan/quick-lint-js")); + ATF_CHECK(sn_sv_eq_to(fork.owner, "gjnoonan")); + ATF_CHECK(sn_sv_eq_to(fork.date, "2023-05-11T05:37:41Z")); + ATF_CHECK(fork.forks == 0); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, simple_github_issue); @@ -215,6 +235,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, simple_github_milestone); ATF_TP_ADD_TC(tp, simple_github_release); ATF_TP_ADD_TC(tp, simple_github_repo); + ATF_TP_ADD_TC(tp, simple_github_fork); return atf_no_error(); } diff --git a/tests/samples/github_simple_fork.json b/tests/samples/github_simple_fork.json new file mode 100644 index 00000000..b7d98469 --- /dev/null +++ b/tests/samples/github_simple_fork.json @@ -0,0 +1,113 @@ +{ + "id": 639263592, + "node_id": "R_kgDOJhpjaA", + "name": "quick-lint-js", + "full_name": "gjnoonan/quick-lint-js", + "private": false, + "owner": { + "login": "gjnoonan", + "id": 702, + "node_id": "MDQ6VXNlcjcwMg==", + "avatar_url": "https://avatars.githubusercontent.com/u/702?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/gjnoonan", + "html_url": "https://github.com/gjnoonan", + "followers_url": "https://api.github.com/users/gjnoonan/followers", + "following_url": "https://api.github.com/users/gjnoonan/following{/other_user}", + "gists_url": "https://api.github.com/users/gjnoonan/gists{/gist_id}", + "starred_url": "https://api.github.com/users/gjnoonan/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/gjnoonan/subscriptions", + "organizations_url": "https://api.github.com/users/gjnoonan/orgs", + "repos_url": "https://api.github.com/users/gjnoonan/repos", + "events_url": "https://api.github.com/users/gjnoonan/events{/privacy}", + "received_events_url": "https://api.github.com/users/gjnoonan/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/gjnoonan/quick-lint-js", + "description": "quick-lint-js finds bugs in JavaScript programs", + "fork": true, + "url": "https://api.github.com/repos/gjnoonan/quick-lint-js", + "forks_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/forks", + "keys_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/teams", + "hooks_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/hooks", + "issue_events_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/issues/events{/number}", + "events_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/events", + "assignees_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/assignees{/user}", + "branches_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/branches{/branch}", + "tags_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/tags", + "blobs_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/statuses/{sha}", + "languages_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/languages", + "stargazers_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/stargazers", + "contributors_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/contributors", + "subscribers_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/subscribers", + "subscription_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/subscription", + "commits_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/contents/{+path}", + "compare_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/merges", + "archive_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/downloads", + "issues_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/issues{/number}", + "pulls_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/pulls{/number}", + "milestones_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/milestones{/number}", + "notifications_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/labels{/name}", + "releases_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/releases{/id}", + "deployments_url": "https://api.github.com/repos/gjnoonan/quick-lint-js/deployments", + "created_at": "2023-05-11T05:37:41Z", + "updated_at": "2023-05-22T08:57:35Z", + "pushed_at": "2023-05-29T19:44:11Z", + "git_url": "git://github.com/gjnoonan/quick-lint-js.git", + "ssh_url": "git@github.com:gjnoonan/quick-lint-js.git", + "clone_url": "https://github.com/gjnoonan/quick-lint-js.git", + "svn_url": "https://github.com/gjnoonan/quick-lint-js", + "homepage": "https://quick-lint-js.com", + "size": 24816, + "stargazers_count": 0, + "watchers_count": 0, + "language": "C++", + "has_issues": false, + "has_projects": true, + "has_downloads": true, + "has_wiki": false, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 0, + "license": { + "key": "gpl-3.0", + "name": "GNU General Public License v3.0", + "spdx_id": "GPL-3.0", + "url": "https://api.github.com/licenses/gpl-3.0", + "node_id": "MDc6TGljZW5zZTk=" + }, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master", + "permissions": { + "admin": false, + "maintain": false, + "push": false, + "triage": false, + "pull": true + } +} diff --git a/tests/update-samples.sh b/tests/update-samples.sh index 6ac651af..854fce67 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -6,6 +6,7 @@ die() { } which gcli > /dev/null 2>&1 || die "gcli is not in PATH" +which jq > /dev/null 2>&1 || die "jq is not in PATH" gcli -t github api /repos/herrhotzenplotz/gcli/issues/115 > samples/github_simple_issue.json gcli -t github api /repos/herrhotzenplotz/gcli/labels/bug > samples/github_simple_label.json @@ -13,6 +14,7 @@ gcli -t github api /repos/herrhotzenplotz/gcli/pulls/113 > samples/github_simple gcli -t github api /repos/herrhotzenplotz/gcli/milestones/1 > samples/github_simple_milestone.json gcli -t github api /repos/herrhotzenplotz/gcli/releases/116031718 > samples/github_simple_release.json gcli -t github api /repos/herrhotzenplotz/gcli > samples/github_simple_repo.json +gcli -t github api /repos/quick-lint/quick-lint-js/forks | jq '.[] | select(.id == 639263592)' > samples/github_simple_fork.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples/gitlab_simple_merge_request.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/issues/193 > samples/gitlab_simple_issue.json diff --git a/todo.org b/todo.org index e253ad17..da1971eb 100644 --- a/todo.org +++ b/todo.org @@ -147,10 +147,10 @@ ** DONE include [[file:docs/pgen.org][docs/pgen.org]] in the distribution tarball ** DONE remove gcli_print_html_url ** TODO Test suite -*** TODO Github [46%] +*** TODO Github [53%] - [ ] Checks - [ ] Comments - - [ ] Forks + - [X] Forks - [ ] Gists - [X] Milestones - [X] Releases From 869a3da1243c09cd58241a0fda0a64db139eeff7 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 17:06:24 +0200 Subject: [PATCH 191/236] Parse comment id in Github comments --- templates/github/comments.t | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/github/comments.t b/templates/github/comments.t index 02c2db86..dcd09f15 100644 --- a/templates/github/comments.t +++ b/templates/github/comments.t @@ -2,7 +2,8 @@ include "gcli/github/comments.h"; parser github_comment is object of gcli_comment with - ("created_at" => date as string, + ("id" => id as int, + "created_at" => date as string, "body" => body as string, "user" => author as user); From d505e80e7f45a0d1a1d91f53ed47fee1d7b8e0f1 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 17:01:45 +0200 Subject: [PATCH 192/236] Add tests for github comments --- Makefile.am | 9 ++--- tests/github-parse-tests.c | 21 +++++++++++ tests/samples/github_simple_comment.json | 44 ++++++++++++++++++++++++ tests/update-samples.sh | 1 + 4 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 tests/samples/github_simple_comment.json diff --git a/Makefile.am b/Makefile.am index 3c7207eb..a7fe7721 100644 --- a/Makefile.am +++ b/Makefile.am @@ -240,15 +240,16 @@ tests_pretty_print_test_LDADD = \ libsn.la \ $(LIBATFC_LDFLAGS) -EXTRA_DIST += tests/samples/github_simple_issue.json \ +EXTRA_DIST += tests/samples/github_simple_comment.json \ + tests/samples/github_simple_fork.json \ tests/samples/github_simple_label.json \ tests/samples/github_simple_milestone.json \ - tests/samples/github_simple_fork.json \ + tests/samples/github_simple_pull.json \ tests/samples/github_simple_release.json \ tests/samples/github_simple_repo.json \ - tests/samples/github_simple_pull.json \ tests/samples/gitlab_simple_issue.json \ tests/samples/gitlab_simple_label.json \ - tests/samples/gitlab_simple_merge_request.json + tests/samples/gitlab_simple_merge_request.json \ + tests/samples/github_simple_issue.json endif diff --git a/tests/github-parse-tests.c b/tests/github-parse-tests.c index 2ddf76f0..175b8d35 100644 --- a/tests/github-parse-tests.c +++ b/tests/github-parse-tests.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -227,6 +228,25 @@ ATF_TC_BODY(simple_github_fork, tc) ATF_CHECK(fork.forks == 0); } +ATF_TC_WITHOUT_HEAD(simple_github_comment); +ATF_TC_BODY(simple_github_comment, tc) +{ + gcli_comment comment = {0}; + FILE *f; + json_stream stream; + gcli_ctx *ctx = test_context(); + + ATF_REQUIRE(f = open_sample("github_simple_comment.json")); + json_open_stream(&stream, f); + + ATF_REQUIRE(parse_github_comment(ctx, &stream, &comment) == 0); + + ATF_CHECK(comment.id == 1424392601); + ATF_CHECK_STREQ(comment.author, "herrhotzenplotz"); + ATF_CHECK_STREQ(comment.date, "2023-02-09T15:37:54Z"); + ATF_CHECK_STREQ(comment.body, "Hey,\n\nthe current trunk on Github might be a little outdated. I pushed the staging branch for version 1.0.0 from Gitlab to Github (cleanup-1.0). Could you try again with that branch and see if it still faults at the same place? If it does, please provide a full backtrace and if possible check with valgrind.\n"); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, simple_github_issue); @@ -236,6 +256,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, simple_github_release); ATF_TP_ADD_TC(tp, simple_github_repo); ATF_TP_ADD_TC(tp, simple_github_fork); + ATF_TP_ADD_TC(tp, simple_github_comment); return atf_no_error(); } diff --git a/tests/samples/github_simple_comment.json b/tests/samples/github_simple_comment.json new file mode 100644 index 00000000..a0b6a00b --- /dev/null +++ b/tests/samples/github_simple_comment.json @@ -0,0 +1,44 @@ +{ + "url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/comments/1424392601", + "html_url": "https://github.com/herrhotzenplotz/gcli/issues/116#issuecomment-1424392601", + "issue_url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/116", + "id": 1424392601, + "node_id": "IC_kwDOGLyhHc5U5oGZ", + "user": { + "login": "herrhotzenplotz", + "id": 34663024, + "node_id": "MDQ6VXNlcjM0NjYzMDI0", + "avatar_url": "https://avatars.githubusercontent.com/u/34663024?u=13531d0ed7a7eb54da4599c39ac3068c7d0d71ab&v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/herrhotzenplotz", + "html_url": "https://github.com/herrhotzenplotz", + "followers_url": "https://api.github.com/users/herrhotzenplotz/followers", + "following_url": "https://api.github.com/users/herrhotzenplotz/following{/other_user}", + "gists_url": "https://api.github.com/users/herrhotzenplotz/gists{/gist_id}", + "starred_url": "https://api.github.com/users/herrhotzenplotz/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/herrhotzenplotz/subscriptions", + "organizations_url": "https://api.github.com/users/herrhotzenplotz/orgs", + "repos_url": "https://api.github.com/users/herrhotzenplotz/repos", + "events_url": "https://api.github.com/users/herrhotzenplotz/events{/privacy}", + "received_events_url": "https://api.github.com/users/herrhotzenplotz/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2023-02-09T15:37:54Z", + "updated_at": "2023-02-09T15:37:54Z", + "author_association": "OWNER", + "body": "Hey,\n\nthe current trunk on Github might be a little outdated. I pushed the staging branch for version 1.0.0 from Gitlab to Github (cleanup-1.0). Could you try again with that branch and see if it still faults at the same place? If it does, please provide a full backtrace and if possible check with valgrind.\n", + "reactions": { + "url": "https://api.github.com/repos/herrhotzenplotz/gcli/issues/comments/1424392601/reactions", + "total_count": 0, + "+1": 0, + "-1": 0, + "laugh": 0, + "hooray": 0, + "confused": 0, + "heart": 0, + "rocket": 0, + "eyes": 0 + }, + "performed_via_github_app": null +} diff --git a/tests/update-samples.sh b/tests/update-samples.sh index 854fce67..7b1774cc 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -15,6 +15,7 @@ gcli -t github api /repos/herrhotzenplotz/gcli/milestones/1 > samples/github_sim gcli -t github api /repos/herrhotzenplotz/gcli/releases/116031718 > samples/github_simple_release.json gcli -t github api /repos/herrhotzenplotz/gcli > samples/github_simple_repo.json gcli -t github api /repos/quick-lint/quick-lint-js/forks | jq '.[] | select(.id == 639263592)' > samples/github_simple_fork.json +gcli -t github api /repos/herrhotzenplotz/gcli/issues/comments/1424392601 > samples/github_simple_comment.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples/gitlab_simple_merge_request.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/issues/193 > samples/gitlab_simple_issue.json From f23fa885fac562da82cb29b347ea3162e1c34890 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 17:39:57 +0200 Subject: [PATCH 193/236] Update todo.org --- todo.org | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/todo.org b/todo.org index da1971eb..6a69955b 100644 --- a/todo.org +++ b/todo.org @@ -149,7 +149,7 @@ ** TODO Test suite *** TODO Github [53%] - [ ] Checks - - [ ] Comments + - [X] Comments - [X] Forks - [ ] Gists - [X] Milestones @@ -177,3 +177,4 @@ - [X] Merge Requests *** TODO Gitea ** TODO add an ATF macro for comparing string views +** TODO Think about making IDs =unsigned long= From f2bc891fb82b5f76d4f8e225dd65d890d1b0deab Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 17:37:20 +0200 Subject: [PATCH 194/236] Fix type of check ids to be a long instead of an int These numbers tend to be very large and we got a compiler warning while working on it in the tests. --- include/gcli/github/checks.h | 2 +- templates/github/checks.t | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/gcli/github/checks.h b/include/gcli/github/checks.h index 65cc5773..b219c574 100644 --- a/include/gcli/github/checks.h +++ b/include/gcli/github/checks.h @@ -47,7 +47,7 @@ struct gcli_github_check { char *conclusion; char *started_at; char *completed_at; - int id; + long id; }; struct github_check_list { diff --git a/templates/github/checks.t b/templates/github/checks.t index e2448f3f..e667d3ed 100644 --- a/templates/github/checks.t +++ b/templates/github/checks.t @@ -7,7 +7,7 @@ object of gcli_github_check with "conclusion" => conclusion as string, "started_at" => started_at as string, "completed_at" => completed_at as string, - "id" => id as int); + "id" => id as long); parser github_checks is object of github_check_list with From 72a09e071d476b31e21e876b409c4839005817a1 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 17:24:40 +0200 Subject: [PATCH 195/236] Add tests for github ci checks --- Makefile.am | 1 + tests/github-parse-tests.c | 23 ++++++ tests/samples/github_simple_check.json | 110 +++++++++++++++++++++++++ tests/update-samples.sh | 1 + 4 files changed, 135 insertions(+) create mode 100644 tests/samples/github_simple_check.json diff --git a/Makefile.am b/Makefile.am index a7fe7721..c92a1d06 100644 --- a/Makefile.am +++ b/Makefile.am @@ -241,6 +241,7 @@ tests_pretty_print_test_LDADD = \ $(LIBATFC_LDFLAGS) EXTRA_DIST += tests/samples/github_simple_comment.json \ + tests/samples/github_simple_check.json \ tests/samples/github_simple_fork.json \ tests/samples/github_simple_label.json \ tests/samples/github_simple_milestone.json \ diff --git a/tests/github-parse-tests.c b/tests/github-parse-tests.c index 175b8d35..24fb0aca 100644 --- a/tests/github-parse-tests.c +++ b/tests/github-parse-tests.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -247,6 +248,27 @@ ATF_TC_BODY(simple_github_comment, tc) ATF_CHECK_STREQ(comment.body, "Hey,\n\nthe current trunk on Github might be a little outdated. I pushed the staging branch for version 1.0.0 from Gitlab to Github (cleanup-1.0). Could you try again with that branch and see if it still faults at the same place? If it does, please provide a full backtrace and if possible check with valgrind.\n"); } +ATF_TC_WITHOUT_HEAD(simple_github_check); +ATF_TC_BODY(simple_github_check, tc) +{ + gcli_github_check check = {0}; + FILE *f; + json_stream stream; + gcli_ctx *ctx = test_context(); + + ATF_REQUIRE(f = open_sample("github_simple_check.json")); + json_open_stream(&stream, f); + + ATF_REQUIRE(parse_github_check(ctx, &stream, &check) == 0); + + ATF_CHECK_STREQ(check.name, "test Windows x86"); + ATF_CHECK_STREQ(check.status, "completed"); + ATF_CHECK_STREQ(check.conclusion, "success"); + ATF_CHECK_STREQ(check.started_at, "2023-09-02T06:27:37Z"); + ATF_CHECK_STREQ(check.completed_at, "2023-09-02T06:29:11Z"); + ATF_CHECK(check.id == 16437184455); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, simple_github_issue); @@ -257,6 +279,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, simple_github_repo); ATF_TP_ADD_TC(tp, simple_github_fork); ATF_TP_ADD_TC(tp, simple_github_comment); + ATF_TP_ADD_TC(tp, simple_github_check); return atf_no_error(); } diff --git a/tests/samples/github_simple_check.json b/tests/samples/github_simple_check.json new file mode 100644 index 00000000..e2f79883 --- /dev/null +++ b/tests/samples/github_simple_check.json @@ -0,0 +1,110 @@ +{ + "id": 16437184455, + "name": "test Windows x86", + "node_id": "CR_kwDODwaEZM8AAAAD07uHxw", + "head_sha": "03a8af3dab144ea38910c1efdcce03fb708f3179", + "external_id": "85d15886-9467-5a76-a719-6058eec4b143", + "url": "https://api.github.com/repos/quick-lint/quick-lint-js/check-runs/16437184455", + "html_url": "https://github.com/quick-lint/quick-lint-js/actions/runs/6056687077/job/16437184455", + "details_url": "https://github.com/quick-lint/quick-lint-js/actions/runs/6056687077/job/16437184455", + "status": "completed", + "conclusion": "success", + "started_at": "2023-09-02T06:27:37Z", + "completed_at": "2023-09-02T06:29:11Z", + "output": { + "title": null, + "summary": null, + "text": null, + "annotations_count": 0, + "annotations_url": "https://api.github.com/repos/quick-lint/quick-lint-js/check-runs/16437184455/annotations" + }, + "check_suite": { + "id": 15750909232 + }, + "app": { + "id": 15368, + "slug": "github-actions", + "node_id": "MDM6QXBwMTUzNjg=", + "owner": { + "login": "github", + "id": 9919, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjk5MTk=", + "avatar_url": "https://avatars.githubusercontent.com/u/9919?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/github", + "html_url": "https://github.com/github", + "followers_url": "https://api.github.com/users/github/followers", + "following_url": "https://api.github.com/users/github/following{/other_user}", + "gists_url": "https://api.github.com/users/github/gists{/gist_id}", + "starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/github/subscriptions", + "organizations_url": "https://api.github.com/users/github/orgs", + "repos_url": "https://api.github.com/users/github/repos", + "events_url": "https://api.github.com/users/github/events{/privacy}", + "received_events_url": "https://api.github.com/users/github/received_events", + "type": "Organization", + "site_admin": false + }, + "name": "GitHub Actions", + "description": "Automate your workflow from idea to production", + "external_url": "https://help.github.com/en/actions", + "html_url": "https://github.com/apps/github-actions", + "created_at": "2018-07-30T09:30:17Z", + "updated_at": "2019-12-10T19:04:12Z", + "permissions": { + "actions": "write", + "administration": "read", + "checks": "write", + "contents": "write", + "deployments": "write", + "discussions": "write", + "issues": "write", + "merge_queues": "write", + "metadata": "read", + "packages": "write", + "pages": "write", + "pull_requests": "write", + "repository_hooks": "write", + "repository_projects": "write", + "security_events": "write", + "statuses": "write", + "vulnerability_alerts": "read" + }, + "events": [ + "branch_protection_rule", + "check_run", + "check_suite", + "create", + "delete", + "deployment", + "deployment_status", + "discussion", + "discussion_comment", + "fork", + "gollum", + "issues", + "issue_comment", + "label", + "merge_group", + "milestone", + "page_build", + "project", + "project_card", + "project_column", + "public", + "pull_request", + "pull_request_review", + "pull_request_review_comment", + "push", + "registry_package", + "release", + "repository", + "repository_dispatch", + "status", + "watch", + "workflow_dispatch", + "workflow_run" + ] + }, + "pull_requests": [] +} diff --git a/tests/update-samples.sh b/tests/update-samples.sh index 7b1774cc..2af5d959 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -16,6 +16,7 @@ gcli -t github api /repos/herrhotzenplotz/gcli/releases/116031718 > samples/gith gcli -t github api /repos/herrhotzenplotz/gcli > samples/github_simple_repo.json gcli -t github api /repos/quick-lint/quick-lint-js/forks | jq '.[] | select(.id == 639263592)' > samples/github_simple_fork.json gcli -t github api /repos/herrhotzenplotz/gcli/issues/comments/1424392601 > samples/github_simple_comment.json +gcli -t github api /repos/quick-lint/quick-lint-js/commits/03a8af3dab144ea38910c1efdcce03fb708f3179/check-runs | jq '.check_runs | .[] | select(.id == 16437184455)' > samples/github_simple_check.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples/gitlab_simple_merge_request.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/issues/193 > samples/gitlab_simple_issue.json From 0de028be673add560d6290e5ab288679dd1b0e3f Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 18:32:50 +0200 Subject: [PATCH 196/236] Add support for printing coverage in Gitlab MRs --- include/gcli/forges.h | 1 + include/gcli/pulls.h | 3 ++- src/cmd/pulls.c | 3 +++ src/forges.c | 5 +++-- templates/gitlab/merge_requests.t | 3 ++- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 4b10cc06..f6dcd2a0 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -320,6 +320,7 @@ struct gcli_forge_descriptor { GCLI_PRS_QUIRK_CHANGES = 0x04, GCLI_PRS_QUIRK_MERGED = 0x08, GCLI_PRS_QUIRK_DRAFT = 0x10, + GCLI_PRS_QUIRK_COVERAGE = 0x20, } pull_summary_quirks; /** diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index c42c656c..b81fb834 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -71,7 +71,8 @@ struct gcli_pull { int deletions; int commits; int changed_files; - int head_pipeline_id; /* This is GitLab specific */ + int head_pipeline_id; /* GitLab specific */ + char *coverage; /* Gitlab Specific */ sn_sv *labels; size_t labels_size; bool merged; diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 85a74604..341e95a0 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -202,6 +202,9 @@ gcli_pull_print(gcli_pull const *const it) if ((quirks & GCLI_PRS_QUIRK_DRAFT) == 0) gcli_dict_add_string(dict, "DRAFT", 0, 0, sn_bool_yesno(it->draft)); + if ((quirks & GCLI_PRS_QUIRK_COVERAGE) == 0 && it->coverage) + gcli_dict_add_string(dict, "COVERAGE", 0, 0, it->coverage); + if (it->labels_size) { gcli_dict_add_sv_list(dict, "LABELS", it->labels, it->labels_size); } else { diff --git a/src/forges.c b/src/forges.c index b24a6986..9c8f7b02 100644 --- a/src/forges.c +++ b/src/forges.c @@ -138,7 +138,7 @@ github_forge_descriptor = .get_api_error_string = github_api_error_string, .user_object_key = "login", .html_url_key = "html_url", - .pull_summary_quirks = 0, + .pull_summary_quirks = GCLI_PRS_QUIRK_COVERAGE, .milestone_quirks = GCLI_MILESTONE_QUIRKS_EXPIRED | GCLI_MILESTONE_QUIRKS_DUEDATE | GCLI_MILESTONE_QUIRKS_PULLS, @@ -266,7 +266,8 @@ gitea_forge_descriptor = .pull_summary_quirks = GCLI_PRS_QUIRK_COMMITS | GCLI_PRS_QUIRK_ADDDEL | GCLI_PRS_QUIRK_DRAFT - | GCLI_PRS_QUIRK_CHANGES, + | GCLI_PRS_QUIRK_CHANGES + | GCLI_PRS_QUIRK_COVERAGE, .milestone_quirks = GCLI_MILESTONE_QUIRKS_EXPIRED | GCLI_MILESTONE_QUIRKS_PULLS, }; diff --git a/templates/gitlab/merge_requests.t b/templates/gitlab/merge_requests.t index 1a5811e9..94d7a736 100644 --- a/templates/gitlab/merge_requests.t +++ b/templates/gitlab/merge_requests.t @@ -6,7 +6,8 @@ object of gcli_pull with parser gitlab_mr_head_pipeline is object of gcli_pull with - ("id" => head_pipeline_id as int); + ("id" => head_pipeline_id as int, + "coverage" => coverage as string); parser gitlab_mr is object of gcli_pull with From 867698d050e4548fe9cf677147b44a9f973a1645 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 18:47:07 +0200 Subject: [PATCH 197/236] Add coverage to gitlab jobs --- include/gcli/gitlab/pipelines.h | 1 + src/cmd/pipelines.c | 1 + templates/gitlab/pipelines.t | 5 +++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/gcli/gitlab/pipelines.h b/include/gcli/gitlab/pipelines.h index 1ca62cd9..12da361c 100644 --- a/include/gcli/gitlab/pipelines.h +++ b/include/gcli/gitlab/pipelines.h @@ -68,6 +68,7 @@ struct gitlab_job { double duration; char *runner_name; char *runner_description; + double coverage; }; struct gitlab_job_list { diff --git a/src/cmd/pipelines.c b/src/cmd/pipelines.c index 56359348..444f8aeb 100644 --- a/src/cmd/pipelines.c +++ b/src/cmd/pipelines.c @@ -203,6 +203,7 @@ gitlab_print_job_status(gitlab_job const *const job) gcli_dict_add_string(printer, "STARTED", 0, 0, job->started_at); gcli_dict_add_string(printer, "FINISHED", 0, 0, job->finished_at); gcli_dict_add(printer, "DURATION", 0, 0, "%-.2lfs", job->duration); + gcli_dict_add(printer, "COVERAGE", 0, 0, "%.1lf%%", job->coverage); gcli_dict_add_string(printer, "RUNNER NAME", 0, 0, job->runner_name); gcli_dict_add_string(printer, "RUNNER DESCR", 0, 0, job->runner_description); diff --git a/templates/gitlab/pipelines.t b/templates/gitlab/pipelines.t index 05e73283..b7543d4b 100644 --- a/templates/gitlab/pipelines.t +++ b/templates/gitlab/pipelines.t @@ -29,7 +29,8 @@ object of gitlab_job with "finished_at" => finished_at as string, "runner" => use parse_gitlab_job_runner, "duration" => duration as double, - "id" => id as long); + "id" => id as long, + "coverage" => coverage as double); parser gitlab_jobs is -array of gitlab_job use parse_gitlab_job; \ No newline at end of file +array of gitlab_job use parse_gitlab_job; From 873456b2c7d5d5eacccc4452c0836af2179ae5aa Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 19:27:30 +0200 Subject: [PATCH 198/236] Expose Gitlabs routine for release asset name fixup --- include/gcli/gitlab/releases.h | 2 ++ src/gitlab/releases.c | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/gcli/gitlab/releases.h b/include/gcli/gitlab/releases.h index cf497774..e586c7ec 100644 --- a/include/gcli/gitlab/releases.h +++ b/include/gcli/gitlab/releases.h @@ -44,4 +44,6 @@ int gitlab_create_release(gcli_ctx *ctx, gcli_new_release const *release); int gitlab_delete_release(gcli_ctx *ctx, char const *owner, char const *repo, char const *id); +void gitlab_fixup_release_assets(gcli_ctx *ctx, gcli_release *const release); + #endif /* GITLAB_RELEASES_H */ diff --git a/src/gitlab/releases.c b/src/gitlab/releases.c index 3c2a78e7..5f251e32 100644 --- a/src/gitlab/releases.c +++ b/src/gitlab/releases.c @@ -41,21 +41,23 @@ static void fixup_asset_name(gcli_ctx *ctx, gcli_release_asset *const asset) { - if (!asset->name) { + if (!asset->name) asset->name = gcli_urldecode(ctx, strrchr(asset->url, '/') + 1); - } +} + +void +gitlab_fixup_release_assets(gcli_ctx *ctx, gcli_release *const release) +{ + for (size_t i = 0; i < release->assets_size; ++i) + fixup_asset_name(ctx, &release->assets[i]); } static void fixup_release_asset_names(gcli_ctx *ctx, gcli_release_list *list) { /* Iterate over releases */ - for (size_t j = 0; j < list->releases_size; ++j) { - /* iterate over releases */ - for (size_t i = 0; i < list->releases[j].assets_size; ++i) { - fixup_asset_name(ctx, &list->releases[j].assets[i]); - } - } + for (size_t i = 0; i < list->releases_size; ++i) + gitlab_fixup_release_assets(ctx, &list->releases[i]); } int From bbd678a6c7c858604fc0c7b93d72e876a352485a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 19:26:00 +0200 Subject: [PATCH 199/236] Add missing prerelease field to parsers for Gitlab --- templates/gitlab/releases.t | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/templates/gitlab/releases.t b/templates/gitlab/releases.t index 85ff3b5d..1c4b83d9 100644 --- a/templates/gitlab/releases.t +++ b/templates/gitlab/releases.t @@ -11,12 +11,13 @@ object of gcli_release with parser gitlab_release is object of gcli_release with - ("name" => name as sv, - "tag_name" => id as sv, - "description" => body as sv, - "assets" => use parse_gitlab_release_assets, - "author" => author as user_sv, - "created_at" => date as sv); + ("name" => name as sv, + "tag_name" => id as sv, + "description" => body as sv, + "assets" => use parse_gitlab_release_assets, + "author" => author as user_sv, + "created_at" => date as sv, + "upcoming_release" => prerelease as bool); parser gitlab_releases is array of gcli_release use parse_gitlab_release; \ No newline at end of file From 0145acaba0800b078a864a710c69372177da77fb Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Sep 2023 19:28:06 +0200 Subject: [PATCH 200/236] Add tests for Gitlab releases --- Makefile.am | 7 +-- tests/gitlab-parse-tests.c | 54 +++++++++++++++++++++++- tests/samples/gitlab_simple_release.json | 1 + tests/update-samples.sh | 3 +- todo.org | 1 + 5 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 tests/samples/gitlab_simple_release.json diff --git a/Makefile.am b/Makefile.am index c92a1d06..e7693a3d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -240,9 +240,9 @@ tests_pretty_print_test_LDADD = \ libsn.la \ $(LIBATFC_LDFLAGS) -EXTRA_DIST += tests/samples/github_simple_comment.json \ - tests/samples/github_simple_check.json \ +EXTRA_DIST += tests/samples/github_simple_check.json \ tests/samples/github_simple_fork.json \ + tests/samples/github_simple_issue.json \ tests/samples/github_simple_label.json \ tests/samples/github_simple_milestone.json \ tests/samples/github_simple_pull.json \ @@ -251,6 +251,7 @@ EXTRA_DIST += tests/samples/github_simple_comment.json \ tests/samples/gitlab_simple_issue.json \ tests/samples/gitlab_simple_label.json \ tests/samples/gitlab_simple_merge_request.json \ - tests/samples/github_simple_issue.json + tests/samples/gitlab_simple_release.json \ + tests/samples/github_simple_comment.json endif diff --git a/tests/gitlab-parse-tests.c b/tests/gitlab-parse-tests.c index 739d24a2..eee877fd 100644 --- a/tests/gitlab-parse-tests.c +++ b/tests/gitlab-parse-tests.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -119,10 +120,61 @@ ATF_TC_BODY(gitlab_simple_label, tc) ATF_CHECK(label.colour == 0xD73A4A00); } +ATF_TC_WITHOUT_HEAD(gitlab_simple_release); +ATF_TC_BODY(gitlab_simple_release, tc) +{ + json_stream stream = {0}; + gcli_ctx *ctx = test_context(); + FILE *f = open_sample("gitlab_simple_release.json"); + gcli_release release = {0}; + + json_open_stream(&stream, f); + ATF_REQUIRE(parse_gitlab_release(ctx, &stream, &release) == 0); + + /* NOTE(Nico): this silly hack is needed as the fixup is only + * applied internally when you fetch the release list using the + * public library API. */ + gitlab_fixup_release_assets(ctx, &release); + + /* NOTE(Nico): on gitlab this is the tag name */ + ATF_CHECK(sn_sv_eq_to(release.id, "1.2.0")); + ATF_CHECK(release.assets_size == 4); + { + ATF_CHECK_STREQ(release.assets[0].name, "gcli-1.2.0.zip"); + ATF_CHECK_STREQ(release.assets[0].url, + "https://gitlab.com/herrhotzenplotz/gcli/-/archive/1.2.0/gcli-1.2.0.zip"); + } + { + ATF_CHECK_STREQ(release.assets[1].name, "gcli-1.2.0.tar.gz"); + ATF_CHECK_STREQ(release.assets[1].url, + "https://gitlab.com/herrhotzenplotz/gcli/-/archive/1.2.0/gcli-1.2.0.tar.gz"); + } + { + ATF_CHECK_STREQ(release.assets[2].name, "gcli-1.2.0.tar.bz2"); + ATF_CHECK_STREQ(release.assets[2].url, + "https://gitlab.com/herrhotzenplotz/gcli/-/archive/1.2.0/gcli-1.2.0.tar.bz2"); + } + { + ATF_CHECK_STREQ(release.assets[3].name, "gcli-1.2.0.tar"); + ATF_CHECK_STREQ(release.assets[3].url, + "https://gitlab.com/herrhotzenplotz/gcli/-/archive/1.2.0/gcli-1.2.0.tar"); + } + + ATF_CHECK(sn_sv_eq_to(release.name, "1.2.0")); + ATF_CHECK(sn_sv_eq_to(release.body, "# Version 1.2.0\n\nThis is version 1.2.0 of gcli.\n\n## Notes\n\nPlease test and report bugs.\n\nYou can download autotoolized tarballs at: https://herrhotzenplotz.de/gcli/releases/gcli-1.2.0/\n\n## Bug Fixes\n\n- Fix compile error when providing --with-libcurl without any arguments\n- Fix memory leaks in string processing functions\n- Fix missing nul termination in read-file function\n- Fix segmentation fault when clearing the milestone of a PR on Gitea\n- Fix missing documentation for milestone action in issues and pulls\n- Set the 'merged' flag properly when showing Gitlab merge requests\n\n## New features\n\n- Add a config subcommand for managing ssh keys (see gcli-config(1))\n- Show number of comments/notes in list of issues and PRs\n- Add support for milestone management in pull requests\n")); + ATF_CHECK(sn_sv_eq_to(release.author, "herrhotzenplotz")); + ATF_CHECK(sn_sv_eq_to(release.date, "2023-08-11T07:56:06.371Z")); + ATF_CHECK(sn_sv_null(release.upload_url)); + ATF_CHECK(release.draft == false); + ATF_CHECK(release.prerelease == false); +} + ATF_TP_ADD_TCS(tp) { - ATF_TP_ADD_TC(tp, gitlab_simple_merge_request); ATF_TP_ADD_TC(tp, gitlab_simple_issue); ATF_TP_ADD_TC(tp, gitlab_simple_label); + ATF_TP_ADD_TC(tp, gitlab_simple_merge_request); + ATF_TP_ADD_TC(tp, gitlab_simple_release); + return atf_no_error(); } diff --git a/tests/samples/gitlab_simple_release.json b/tests/samples/gitlab_simple_release.json new file mode 100644 index 00000000..5234406d --- /dev/null +++ b/tests/samples/gitlab_simple_release.json @@ -0,0 +1 @@ +{"name":"1.2.0","tag_name":"1.2.0","description":"# Version 1.2.0\n\nThis is version 1.2.0 of gcli.\n\n## Notes\n\nPlease test and report bugs.\n\nYou can download autotoolized tarballs at: https://herrhotzenplotz.de/gcli/releases/gcli-1.2.0/\n\n## Bug Fixes\n\n- Fix compile error when providing --with-libcurl without any arguments\n- Fix memory leaks in string processing functions\n- Fix missing nul termination in read-file function\n- Fix segmentation fault when clearing the milestone of a PR on Gitea\n- Fix missing documentation for milestone action in issues and pulls\n- Set the 'merged' flag properly when showing Gitlab merge requests\n\n## New features\n\n- Add a config subcommand for managing ssh keys (see gcli-config(1))\n- Show number of comments/notes in list of issues and PRs\n- Add support for milestone management in pull requests\n","created_at":"2023-08-11T07:56:06.371Z","released_at":"2023-08-11T07:56:06.371Z","upcoming_release":false,"author":{"id":5980462,"username":"herrhotzenplotz","name":"Nico Sonack","state":"active","avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/5980462/avatar.png","web_url":"https://gitlab.com/herrhotzenplotz"},"commit":{"id":"a6e295d088b4215ad52cb25d269e54b204acc471","short_id":"a6e295d0","created_at":"2023-08-11T09:42:37.000+02:00","parent_ids":["2503abe114b4701ccd42cf187349e5dc7d382a2b","f1b942e965a5d462a350faf0ff37fda86c25a931"],"title":"Merge branch 'trunk' into release","message":"Merge branch 'trunk' into release\n","author_name":"Nico Sonack","author_email":"nsonack@herrhotzenplotz.de","authored_date":"2023-08-11T09:42:37.000+02:00","committer_name":"Nico Sonack","committer_email":"nsonack@herrhotzenplotz.de","committed_date":"2023-08-11T09:42:37.000+02:00","trailers":{},"web_url":"https://gitlab.com/herrhotzenplotz/gcli/-/commit/a6e295d088b4215ad52cb25d269e54b204acc471"},"commit_path":"/herrhotzenplotz/gcli/-/commit/a6e295d088b4215ad52cb25d269e54b204acc471","tag_path":"/herrhotzenplotz/gcli/-/tags/1.2.0","assets":{"count":4,"sources":[{"format":"zip","url":"https://gitlab.com/herrhotzenplotz/gcli/-/archive/1.2.0/gcli-1.2.0.zip"},{"format":"tar.gz","url":"https://gitlab.com/herrhotzenplotz/gcli/-/archive/1.2.0/gcli-1.2.0.tar.gz"},{"format":"tar.bz2","url":"https://gitlab.com/herrhotzenplotz/gcli/-/archive/1.2.0/gcli-1.2.0.tar.bz2"},{"format":"tar","url":"https://gitlab.com/herrhotzenplotz/gcli/-/archive/1.2.0/gcli-1.2.0.tar"}],"links":[]},"evidences":[{"sha":"c4daff0bf736e2a5b4abe83f2811d01fe2d03ba287ed","filepath":"https://gitlab.com/herrhotzenplotz/gcli/-/releases/1.2.0/evidences/5392288.json","collected_at":"2023-08-11T07:56:06.694Z"}],"_links":{"closed_issues_url":"https://gitlab.com/herrhotzenplotz/gcli/-/issues?release_tag=1.2.0\u0026scope=all\u0026state=closed","closed_merge_requests_url":"https://gitlab.com/herrhotzenplotz/gcli/-/merge_requests?release_tag=1.2.0\u0026scope=all\u0026state=closed","edit_url":"https://gitlab.com/herrhotzenplotz/gcli/-/releases/1.2.0/edit","merged_merge_requests_url":"https://gitlab.com/herrhotzenplotz/gcli/-/merge_requests?release_tag=1.2.0\u0026scope=all\u0026state=merged","opened_issues_url":"https://gitlab.com/herrhotzenplotz/gcli/-/issues?release_tag=1.2.0\u0026scope=all\u0026state=opened","opened_merge_requests_url":"https://gitlab.com/herrhotzenplotz/gcli/-/merge_requests?release_tag=1.2.0\u0026scope=all\u0026state=opened","self":"https://gitlab.com/herrhotzenplotz/gcli/-/releases/1.2.0"}} \ No newline at end of file diff --git a/tests/update-samples.sh b/tests/update-samples.sh index 2af5d959..ca57aa8f 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -18,6 +18,7 @@ gcli -t github api /repos/quick-lint/quick-lint-js/forks | jq '.[] | select(.id gcli -t github api /repos/herrhotzenplotz/gcli/issues/comments/1424392601 > samples/github_simple_comment.json gcli -t github api /repos/quick-lint/quick-lint-js/commits/03a8af3dab144ea38910c1efdcce03fb708f3179/check-runs | jq '.check_runs | .[] | select(.id == 16437184455)' > samples/github_simple_check.json -gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples/gitlab_simple_merge_request.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/issues/193 > samples/gitlab_simple_issue.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/labels/24376073 > samples/gitlab_simple_label.json +gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples/gitlab_simple_merge_request.json +gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/releases/1.2.0 > samples/gitlab_simple_release.json diff --git a/todo.org b/todo.org index 6a69955b..001a14bf 100644 --- a/todo.org +++ b/todo.org @@ -178,3 +178,4 @@ *** TODO Gitea ** TODO add an ATF macro for comparing string views ** TODO Think about making IDs =unsigned long= +** TODO get rid of html_url everywhere From 4ccc19f3f28bbfcb5a43ec64f5657698efde6c8b Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 4 Sep 2023 01:09:27 +0200 Subject: [PATCH 201/236] Add tests for Gitlab Forks --- Makefile.am | 1 + tests/gitlab-parse-tests.c | 19 ++++ tests/samples/gitlab_simple_fork.json | 153 ++++++++++++++++++++++++++ tests/update-samples.sh | 1 + todo.org | 6 +- 5 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 tests/samples/gitlab_simple_fork.json diff --git a/Makefile.am b/Makefile.am index e7693a3d..aadf3ab9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -249,6 +249,7 @@ EXTRA_DIST += tests/samples/github_simple_check.json \ tests/samples/github_simple_release.json \ tests/samples/github_simple_repo.json \ tests/samples/gitlab_simple_issue.json \ + tests/samples/gitlab_simple_fork.json \ tests/samples/gitlab_simple_label.json \ tests/samples/gitlab_simple_merge_request.json \ tests/samples/gitlab_simple_release.json \ diff --git a/tests/gitlab-parse-tests.c b/tests/gitlab-parse-tests.c index eee877fd..d9c417e6 100644 --- a/tests/gitlab-parse-tests.c +++ b/tests/gitlab-parse-tests.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -169,12 +170,30 @@ ATF_TC_BODY(gitlab_simple_release, tc) ATF_CHECK(release.prerelease == false); } +ATF_TC_WITHOUT_HEAD(gitlab_simple_fork); +ATF_TC_BODY(gitlab_simple_fork, tc) +{ + json_stream stream = {0}; + gcli_ctx *ctx = test_context(); + FILE *f = open_sample("gitlab_simple_fork.json"); + gcli_fork fork = {0}; + + json_open_stream(&stream, f); + ATF_REQUIRE(parse_gitlab_fork(ctx, &stream, &fork) == 0); + + ATF_CHECK(sn_sv_eq_to(fork.full_name, "gjnoonan/gcli")); + ATF_CHECK(sn_sv_eq_to(fork.owner, "gjnoonan")); + ATF_CHECK(sn_sv_eq_to(fork.date, "2022-10-02T13:54:20.517Z")); + ATF_CHECK(fork.forks == 0); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, gitlab_simple_issue); ATF_TP_ADD_TC(tp, gitlab_simple_label); ATF_TP_ADD_TC(tp, gitlab_simple_merge_request); ATF_TP_ADD_TC(tp, gitlab_simple_release); + ATF_TP_ADD_TC(tp, gitlab_simple_fork); return atf_no_error(); } diff --git a/tests/samples/gitlab_simple_fork.json b/tests/samples/gitlab_simple_fork.json new file mode 100644 index 00000000..52ba6b86 --- /dev/null +++ b/tests/samples/gitlab_simple_fork.json @@ -0,0 +1,153 @@ +{ + "id": 39885442, + "description": "Somewhat portable and secure CLI utility to interact with various Git forges.", + "name": "gcli", + "name_with_namespace": "Gavin-John Noonan / gcli", + "path": "gcli", + "path_with_namespace": "gjnoonan/gcli", + "created_at": "2022-10-02T13:54:20.517Z", + "default_branch": "trunk", + "tag_list": [], + "topics": [], + "ssh_url_to_repo": "git@gitlab.com:gjnoonan/gcli.git", + "http_url_to_repo": "https://gitlab.com/gjnoonan/gcli.git", + "web_url": "https://gitlab.com/gjnoonan/gcli", + "readme_url": "https://gitlab.com/gjnoonan/gcli/-/blob/trunk/README.md", + "forks_count": 0, + "avatar_url": null, + "star_count": 0, + "last_activity_at": "2023-09-02T14:55:09.091Z", + "namespace": { + "id": 242706, + "name": "Gavin-John Noonan", + "path": "gjnoonan", + "kind": "user", + "full_path": "gjnoonan", + "parent_id": null, + "avatar_url": "https://secure.gravatar.com/avatar/89a6c7fbad7932af9cb579e240c9b4f6?s=80&d=identicon", + "web_url": "https://gitlab.com/gjnoonan" + }, + "container_registry_image_prefix": "registry.gitlab.com/gjnoonan/gcli", + "_links": { + "self": "https://gitlab.com/api/v4/projects/39885442", + "issues": "https://gitlab.com/api/v4/projects/39885442/issues", + "merge_requests": "https://gitlab.com/api/v4/projects/39885442/merge_requests", + "repo_branches": "https://gitlab.com/api/v4/projects/39885442/repository/branches", + "labels": "https://gitlab.com/api/v4/projects/39885442/labels", + "events": "https://gitlab.com/api/v4/projects/39885442/events", + "members": "https://gitlab.com/api/v4/projects/39885442/members", + "cluster_agents": "https://gitlab.com/api/v4/projects/39885442/cluster_agents" + }, + "packages_enabled": true, + "empty_repo": false, + "archived": false, + "visibility": "public", + "owner": { + "id": 205880, + "username": "gjnoonan", + "name": "Gavin-John Noonan", + "state": "active", + "avatar_url": "https://secure.gravatar.com/avatar/89a6c7fbad7932af9cb579e240c9b4f6?s=80&d=identicon", + "web_url": "https://gitlab.com/gjnoonan" + }, + "resolve_outdated_diff_discussions": false, + "container_expiration_policy": { + "cadence": "1d", + "enabled": false, + "keep_n": 10, + "older_than": "90d", + "name_regex": ".*", + "name_regex_keep": null, + "next_run_at": "2022-10-03T13:54:20.551Z" + }, + "issues_enabled": true, + "merge_requests_enabled": true, + "wiki_enabled": true, + "jobs_enabled": true, + "snippets_enabled": true, + "container_registry_enabled": true, + "service_desk_enabled": true, + "can_create_merge_request_in": true, + "issues_access_level": "enabled", + "repository_access_level": "enabled", + "merge_requests_access_level": "enabled", + "forking_access_level": "enabled", + "wiki_access_level": "enabled", + "builds_access_level": "enabled", + "snippets_access_level": "enabled", + "pages_access_level": "enabled", + "analytics_access_level": "enabled", + "container_registry_access_level": "enabled", + "security_and_compliance_access_level": "private", + "releases_access_level": "enabled", + "environments_access_level": "enabled", + "feature_flags_access_level": "enabled", + "infrastructure_access_level": "enabled", + "monitor_access_level": "enabled", + "emails_disabled": false, + "emails_enabled": true, + "shared_runners_enabled": true, + "lfs_enabled": true, + "creator_id": 205880, + "forked_from_project": { + "id": 34707535, + "description": "Somewhat portable and secure CLI utility to interact with various Git forges.", + "name": "gcli", + "name_with_namespace": "Nico Sonack / gcli", + "path": "gcli", + "path_with_namespace": "herrhotzenplotz/gcli", + "created_at": "2022-03-22T16:57:59.891Z", + "default_branch": "trunk", + "tag_list": [], + "topics": [], + "ssh_url_to_repo": "git@gitlab.com:herrhotzenplotz/gcli.git", + "http_url_to_repo": "https://gitlab.com/herrhotzenplotz/gcli.git", + "web_url": "https://gitlab.com/herrhotzenplotz/gcli", + "readme_url": "https://gitlab.com/herrhotzenplotz/gcli/-/blob/trunk/README.md", + "forks_count": 2, + "avatar_url": null, + "star_count": 2, + "last_activity_at": "2023-09-02T16:44:49.863Z", + "namespace": { + "id": 7926179, + "name": "Nico Sonack", + "path": "herrhotzenplotz", + "kind": "user", + "full_path": "herrhotzenplotz", + "parent_id": null, + "avatar_url": "/uploads/-/system/user/avatar/5980462/avatar.png", + "web_url": "https://gitlab.com/herrhotzenplotz" + } + }, + "mr_default_target_self": false, + "import_status": "finished", + "open_issues_count": 0, + "description_html": "

Somewhat portable and secure CLI utility to interact with various Git forges.

", + "updated_at": "2023-09-02T14:55:09.091Z", + "ci_config_path": "", + "public_jobs": true, + "shared_with_groups": [], + "only_allow_merge_if_pipeline_succeeds": false, + "allow_merge_on_skipped_pipeline": null, + "request_access_enabled": true, + "only_allow_merge_if_all_discussions_are_resolved": false, + "remove_source_branch_after_merge": true, + "printing_merge_request_link_enabled": true, + "merge_method": "merge", + "squash_option": "default_off", + "enforce_auth_checks_on_uploads": true, + "suggestion_commit_message": null, + "merge_commit_template": null, + "squash_commit_template": null, + "issue_branch_template": null, + "autoclose_referenced_issues": true, + "external_authorization_classification_label": "", + "requirements_enabled": false, + "requirements_access_level": "enabled", + "security_and_compliance_enabled": false, + "compliance_frameworks": [], + "permissions": { + "project_access": null, + "group_access": null + } +} diff --git a/tests/update-samples.sh b/tests/update-samples.sh index ca57aa8f..6f72098d 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -22,3 +22,4 @@ gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/issues/193 > samples/gitlab_ gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/labels/24376073 > samples/gitlab_simple_label.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples/gitlab_simple_merge_request.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/releases/1.2.0 > samples/gitlab_simple_release.json +gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/forks | jq '.[] | select(.id == 39885442)' > samples/gitlab_simple_fork.json diff --git a/todo.org b/todo.org index 001a14bf..516d4e00 100644 --- a/todo.org +++ b/todo.org @@ -161,12 +161,12 @@ - [X] Issues - [X] Labels - [X] Pulls -*** TODO Gitlab [25%] +*** TODO Gitlab [30%] - [ ] Comments - - [ ] Forks + - [X] Forks - [ ] Milestones - [ ] Pipelines - - [ ] Releases + - [X] Releases - [ ] Repos - [ ] Reviews - [ ] SSH Keys From e038546181a2193ce3e0539cab427128c37afa69 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 3 Sep 2023 23:29:04 +0200 Subject: [PATCH 202/236] Add tests for Gitlab milestones --- Makefile.am | 6 +++-- tests/gitlab-parse-tests.c | 29 +++++++++++++++++++++- tests/samples/gitlab_simple_milestone.json | 1 + tests/update-samples.sh | 1 + todo.org | 4 +-- 5 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 tests/samples/gitlab_simple_milestone.json diff --git a/Makefile.am b/Makefile.am index aadf3ab9..83168128 100644 --- a/Makefile.am +++ b/Makefile.am @@ -241,8 +241,10 @@ tests_pretty_print_test_LDADD = \ $(LIBATFC_LDFLAGS) EXTRA_DIST += tests/samples/github_simple_check.json \ + tests/samples/github_simple_comment.json \ tests/samples/github_simple_fork.json \ tests/samples/github_simple_issue.json \ + tests/samples/github_simple_issue.json \ tests/samples/github_simple_label.json \ tests/samples/github_simple_milestone.json \ tests/samples/github_simple_pull.json \ @@ -252,7 +254,7 @@ EXTRA_DIST += tests/samples/github_simple_check.json \ tests/samples/gitlab_simple_fork.json \ tests/samples/gitlab_simple_label.json \ tests/samples/gitlab_simple_merge_request.json \ - tests/samples/gitlab_simple_release.json \ - tests/samples/github_simple_comment.json + tests/samples/gitlab_simple_milestone.json \ + tests/samples/gitlab_simple_release.json endif diff --git a/tests/gitlab-parse-tests.c b/tests/gitlab-parse-tests.c index d9c417e6..3918d84a 100644 --- a/tests/gitlab-parse-tests.c +++ b/tests/gitlab-parse-tests.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -187,13 +188,39 @@ ATF_TC_BODY(gitlab_simple_fork, tc) ATF_CHECK(fork.forks == 0); } +ATF_TC_WITHOUT_HEAD(gitlab_simple_milestone); +ATF_TC_BODY(gitlab_simple_milestone, tc) +{ + json_stream stream = {0}; + gcli_ctx *ctx = test_context(); + FILE *f = open_sample("gitlab_simple_milestone.json"); + gcli_milestone milestone = {0}; + + json_open_stream(&stream, f); + ATF_REQUIRE(parse_gitlab_milestone(ctx, &stream, &milestone) == 0); + + ATF_CHECK(milestone.id == 2975318); + ATF_CHECK_STREQ(milestone.title, "Version 2"); + ATF_CHECK_STREQ(milestone.state, "active"); + ATF_CHECK_STREQ(milestone.description, + "Things that need to be done for version 2"); + ATF_CHECK_STREQ(milestone.created_at, "2023-02-05T19:08:20.379Z"); + ATF_CHECK_STREQ(milestone.due_date, ""); + ATF_CHECK_STREQ(milestone.updated_at, "2023-02-05T19:08:20.379Z"); + ATF_CHECK(milestone.expired == false); + + /* Ignore open issues and closed issues as they are + * github/gitea-specific */ +} + ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, gitlab_simple_fork); ATF_TP_ADD_TC(tp, gitlab_simple_issue); ATF_TP_ADD_TC(tp, gitlab_simple_label); ATF_TP_ADD_TC(tp, gitlab_simple_merge_request); + ATF_TP_ADD_TC(tp, gitlab_simple_milestone); ATF_TP_ADD_TC(tp, gitlab_simple_release); - ATF_TP_ADD_TC(tp, gitlab_simple_fork); return atf_no_error(); } diff --git a/tests/samples/gitlab_simple_milestone.json b/tests/samples/gitlab_simple_milestone.json new file mode 100644 index 00000000..48d0fea7 --- /dev/null +++ b/tests/samples/gitlab_simple_milestone.json @@ -0,0 +1 @@ +{"id":2975318,"iid":2,"project_id":34707535,"title":"Version 2","description":"Things that need to be done for version 2","state":"active","created_at":"2023-02-05T19:08:20.379Z","updated_at":"2023-02-05T19:08:20.379Z","due_date":null,"start_date":null,"expired":false,"web_url":"https://gitlab.com/herrhotzenplotz/gcli/-/milestones/2"} \ No newline at end of file diff --git a/tests/update-samples.sh b/tests/update-samples.sh index 6f72098d..04cb126a 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -23,3 +23,4 @@ gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/labels/24376073 > samples/gi gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples/gitlab_simple_merge_request.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/releases/1.2.0 > samples/gitlab_simple_release.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/forks | jq '.[] | select(.id == 39885442)' > samples/gitlab_simple_fork.json +gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/milestones/2975318 > samples/gitlab_simple_milestone.json diff --git a/todo.org b/todo.org index 516d4e00..4a892501 100644 --- a/todo.org +++ b/todo.org @@ -161,10 +161,10 @@ - [X] Issues - [X] Labels - [X] Pulls -*** TODO Gitlab [30%] +*** TODO Gitlab [46%] - [ ] Comments - [X] Forks - - [ ] Milestones + - [X] Milestones - [ ] Pipelines - [X] Releases - [ ] Repos From bac12e517035d433459cabc686a998539d57f416 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 3 Sep 2023 23:58:43 +0200 Subject: [PATCH 203/236] Add tests for Gitlab Pipelines --- Makefile.am | 7 ++++--- tests/gitlab-parse-tests.c | 22 ++++++++++++++++++++++ tests/samples/gitlab_simple_pipeline.json | 1 + tests/update-samples.sh | 1 + todo.org | 4 ++-- 5 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 tests/samples/gitlab_simple_pipeline.json diff --git a/Makefile.am b/Makefile.am index 83168128..1e5a2e4b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -240,8 +240,7 @@ tests_pretty_print_test_LDADD = \ libsn.la \ $(LIBATFC_LDFLAGS) -EXTRA_DIST += tests/samples/github_simple_check.json \ - tests/samples/github_simple_comment.json \ +EXTRA_DIST += tests/samples/github_simple_comment.json \ tests/samples/github_simple_fork.json \ tests/samples/github_simple_issue.json \ tests/samples/github_simple_issue.json \ @@ -255,6 +254,8 @@ EXTRA_DIST += tests/samples/github_simple_check.json \ tests/samples/gitlab_simple_label.json \ tests/samples/gitlab_simple_merge_request.json \ tests/samples/gitlab_simple_milestone.json \ - tests/samples/gitlab_simple_release.json + tests/samples/gitlab_simple_pipeline.json \ + tests/samples/gitlab_simple_release.json \ + tests/samples/github_simple_check.json endif diff --git a/tests/gitlab-parse-tests.c b/tests/gitlab-parse-tests.c index 3918d84a..786fa104 100644 --- a/tests/gitlab-parse-tests.c +++ b/tests/gitlab-parse-tests.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -213,6 +214,26 @@ ATF_TC_BODY(gitlab_simple_milestone, tc) * github/gitea-specific */ } +ATF_TC_WITHOUT_HEAD(gitlab_simple_pipeline); +ATF_TC_BODY(gitlab_simple_pipeline, tc) +{ + json_stream stream = {0}; + gcli_ctx *ctx = test_context(); + FILE *f = open_sample("gitlab_simple_pipeline.json"); + gitlab_pipeline pipeline = {0}; + + json_open_stream(&stream, f); + ATF_REQUIRE(parse_gitlab_pipeline(ctx, &stream, &pipeline) == 0); + + ATF_CHECK(pipeline.id == 989897020); + ATF_CHECK_STREQ(pipeline.status, "failed"); + ATF_CHECK_STREQ(pipeline.created_at, "2023-09-02T14:30:20.925Z"); + ATF_CHECK_STREQ(pipeline.updated_at, "2023-09-02T14:31:40.328Z"); + ATF_CHECK_STREQ(pipeline.ref, "refs/merge-requests/219/head"); + ATF_CHECK_STREQ(pipeline.sha, "742affb88a297a6b34201ad61c8b5b72ec6eb679"); + ATF_CHECK_STREQ(pipeline.source, "merge_request_event"); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, gitlab_simple_fork); @@ -220,6 +241,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, gitlab_simple_label); ATF_TP_ADD_TC(tp, gitlab_simple_merge_request); ATF_TP_ADD_TC(tp, gitlab_simple_milestone); + ATF_TP_ADD_TC(tp, gitlab_simple_pipeline); ATF_TP_ADD_TC(tp, gitlab_simple_release); return atf_no_error(); diff --git a/tests/samples/gitlab_simple_pipeline.json b/tests/samples/gitlab_simple_pipeline.json new file mode 100644 index 00000000..bc14764f --- /dev/null +++ b/tests/samples/gitlab_simple_pipeline.json @@ -0,0 +1 @@ +{"id":989897020,"iid":121,"project_id":34707535,"sha":"742affb88a297a6b34201ad61c8b5b72ec6eb679","ref":"refs/merge-requests/219/head","status":"failed","source":"merge_request_event","created_at":"2023-09-02T14:30:20.925Z","updated_at":"2023-09-02T14:31:40.328Z","web_url":"https://gitlab.com/herrhotzenplotz/gcli/-/pipelines/989897020","before_sha":"0000000000000000000000000000000000000000","tag":false,"yaml_errors":null,"user":{"id":5980462,"username":"herrhotzenplotz","name":"Nico Sonack","state":"active","avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/5980462/avatar.png","web_url":"https://gitlab.com/herrhotzenplotz"},"started_at":"2023-09-02T14:30:21.867Z","finished_at":"2023-09-02T14:31:40.317Z","committed_at":null,"duration":73,"queued_duration":null,"coverage":null,"detailed_status":{"icon":"status_failed","text":"failed","label":"failed","group":"failed","tooltip":"failed","has_details":true,"details_path":"/herrhotzenplotz/gcli/-/pipelines/989897020","illustration":null,"favicon":"/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png"},"name":null} \ No newline at end of file diff --git a/tests/update-samples.sh b/tests/update-samples.sh index 04cb126a..70e7931d 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -24,3 +24,4 @@ gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/releases/1.2.0 > samples/gitlab_simple_release.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/forks | jq '.[] | select(.id == 39885442)' > samples/gitlab_simple_fork.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/milestones/2975318 > samples/gitlab_simple_milestone.json +gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/pipelines/989897020 > samples/gitlab/simple_pipeline.json diff --git a/todo.org b/todo.org index 4a892501..8e777af6 100644 --- a/todo.org +++ b/todo.org @@ -161,11 +161,11 @@ - [X] Issues - [X] Labels - [X] Pulls -*** TODO Gitlab [46%] +*** TODO Gitlab [53%] - [ ] Comments - [X] Forks - [X] Milestones - - [ ] Pipelines + - [X] Pipelines - [X] Releases - [ ] Repos - [ ] Reviews From 3f2a500bbb5e6cbbc8f677eac7810cacbceea86d Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 4 Sep 2023 00:12:45 +0200 Subject: [PATCH 204/236] Fix wrong path --- tests/update-samples.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/update-samples.sh b/tests/update-samples.sh index 70e7931d..bf15e2d7 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -24,4 +24,4 @@ gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/merge_requests/216 > samples gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/releases/1.2.0 > samples/gitlab_simple_release.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/forks | jq '.[] | select(.id == 39885442)' > samples/gitlab_simple_fork.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/milestones/2975318 > samples/gitlab_simple_milestone.json -gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/pipelines/989897020 > samples/gitlab/simple_pipeline.json +gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/pipelines/989897020 > samples/gitlab_simple_pipeline.json From 103c30bb42d88b4e3a84f877067b02e7fe28b865 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 4 Sep 2023 00:13:01 +0200 Subject: [PATCH 205/236] Update todo.org --- todo.org | 1 + 1 file changed, 1 insertion(+) diff --git a/todo.org b/todo.org index 8e777af6..2ad2e2a0 100644 --- a/todo.org +++ b/todo.org @@ -179,3 +179,4 @@ ** TODO add an ATF macro for comparing string views ** TODO Think about making IDs =unsigned long= ** TODO get rid of html_url everywhere +** TODO Check the =Kyuafile.in= for requirements on test input From 25367f0e4d182c8dc56bf6bf02733886455e31c3 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 4 Sep 2023 00:13:08 +0200 Subject: [PATCH 206/236] Add tests for Gitlab repos --- Makefile.am | 1 + tests/gitlab-parse-tests.c | 22 ++++++++++++++++++++++ tests/samples/gitlab_simple_repo.json | 1 + tests/update-samples.sh | 1 + todo.org | 4 ++-- 5 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 tests/samples/gitlab_simple_repo.json diff --git a/Makefile.am b/Makefile.am index 1e5a2e4b..f0690d4a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -256,6 +256,7 @@ EXTRA_DIST += tests/samples/github_simple_comment.json \ tests/samples/gitlab_simple_milestone.json \ tests/samples/gitlab_simple_pipeline.json \ tests/samples/gitlab_simple_release.json \ + tests/samples/gitlab_simple_repo.json \ tests/samples/github_simple_check.json endif diff --git a/tests/gitlab-parse-tests.c b/tests/gitlab-parse-tests.c index 786fa104..c00dcaab 100644 --- a/tests/gitlab-parse-tests.c +++ b/tests/gitlab-parse-tests.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -234,6 +235,26 @@ ATF_TC_BODY(gitlab_simple_pipeline, tc) ATF_CHECK_STREQ(pipeline.source, "merge_request_event"); } +ATF_TC_WITHOUT_HEAD(gitlab_simple_repo); +ATF_TC_BODY(gitlab_simple_repo, tc) +{ + json_stream stream = {0}; + gcli_ctx *ctx = test_context(); + FILE *f = open_sample("gitlab_simple_repo.json"); + gcli_repo repo = {0}; + + json_open_stream(&stream, f); + ATF_REQUIRE(parse_gitlab_repo(ctx, &stream, &repo) == 0); + + ATF_CHECK(repo.id == 34707535); + ATF_CHECK(sn_sv_eq_to(repo.full_name, "herrhotzenplotz/gcli")); + ATF_CHECK(sn_sv_eq_to(repo.name, "gcli")); + ATF_CHECK(sn_sv_eq_to(repo.owner, "herrhotzenplotz")); + ATF_CHECK(sn_sv_eq_to(repo.date, "2022-03-22T16:57:59.891Z")); + ATF_CHECK(sn_sv_eq_to(repo.visibility, "public")); + ATF_CHECK(repo.is_fork == false); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, gitlab_simple_fork); @@ -243,6 +264,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, gitlab_simple_milestone); ATF_TP_ADD_TC(tp, gitlab_simple_pipeline); ATF_TP_ADD_TC(tp, gitlab_simple_release); + ATF_TP_ADD_TC(tp, gitlab_simple_repo); return atf_no_error(); } diff --git a/tests/samples/gitlab_simple_repo.json b/tests/samples/gitlab_simple_repo.json new file mode 100644 index 00000000..254e34f4 --- /dev/null +++ b/tests/samples/gitlab_simple_repo.json @@ -0,0 +1 @@ +{"id":34707535,"description":"Somewhat portable and secure CLI utility to interact with various Git forges.","name":"gcli","name_with_namespace":"Nico Sonack / gcli","path":"gcli","path_with_namespace":"herrhotzenplotz/gcli","created_at":"2022-03-22T16:57:59.891Z","default_branch":"trunk","tag_list":[],"topics":[],"ssh_url_to_repo":"git@gitlab.com:herrhotzenplotz/gcli.git","http_url_to_repo":"https://gitlab.com/herrhotzenplotz/gcli.git","web_url":"https://gitlab.com/herrhotzenplotz/gcli","readme_url":"https://gitlab.com/herrhotzenplotz/gcli/-/blob/trunk/README.md","forks_count":2,"avatar_url":null,"star_count":2,"last_activity_at":"2023-09-03T22:07:05.424Z","namespace":{"id":7926179,"name":"Nico Sonack","path":"herrhotzenplotz","kind":"user","full_path":"herrhotzenplotz","parent_id":null,"avatar_url":"/uploads/-/system/user/avatar/5980462/avatar.png","web_url":"https://gitlab.com/herrhotzenplotz"},"container_registry_image_prefix":"registry.gitlab.com/herrhotzenplotz/gcli","_links":{"self":"https://gitlab.com/api/v4/projects/34707535","issues":"https://gitlab.com/api/v4/projects/34707535/issues","merge_requests":"https://gitlab.com/api/v4/projects/34707535/merge_requests","repo_branches":"https://gitlab.com/api/v4/projects/34707535/repository/branches","labels":"https://gitlab.com/api/v4/projects/34707535/labels","events":"https://gitlab.com/api/v4/projects/34707535/events","members":"https://gitlab.com/api/v4/projects/34707535/members","cluster_agents":"https://gitlab.com/api/v4/projects/34707535/cluster_agents"},"packages_enabled":true,"empty_repo":false,"archived":false,"visibility":"public","owner":{"id":5980462,"username":"herrhotzenplotz","name":"Nico Sonack","state":"active","avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/5980462/avatar.png","web_url":"https://gitlab.com/herrhotzenplotz"},"resolve_outdated_diff_discussions":false,"container_expiration_policy":{"cadence":"1d","enabled":false,"keep_n":10,"older_than":"90d","name_regex":".*","name_regex_keep":null,"next_run_at":"2022-03-23T16:57:59.919Z"},"issues_enabled":true,"merge_requests_enabled":true,"wiki_enabled":true,"jobs_enabled":true,"snippets_enabled":true,"container_registry_enabled":true,"service_desk_enabled":true,"service_desk_address":"contact-project+herrhotzenplotz-gcli-34707535-issue-@incoming.gitlab.com","can_create_merge_request_in":true,"issues_access_level":"enabled","repository_access_level":"enabled","merge_requests_access_level":"enabled","forking_access_level":"enabled","wiki_access_level":"enabled","builds_access_level":"enabled","snippets_access_level":"enabled","pages_access_level":"enabled","analytics_access_level":"enabled","container_registry_access_level":"enabled","security_and_compliance_access_level":"private","releases_access_level":"enabled","environments_access_level":"enabled","feature_flags_access_level":"enabled","infrastructure_access_level":"enabled","monitor_access_level":"enabled","emails_disabled":false,"emails_enabled":true,"shared_runners_enabled":true,"lfs_enabled":true,"creator_id":5980462,"import_url":"https://github.com/herrhotzenplotz/ghcli.git","import_type":"github","import_status":"finished","import_error":null,"open_issues_count":20,"description_html":"\u003cp data-sourcepos=\"1:1-1:77\" dir=\"auto\"\u003eSomewhat portable and secure CLI utility to interact with various Git forges.\u003c/p\u003e","updated_at":"2023-09-03T22:07:05.424Z","ci_default_git_depth":20,"ci_forward_deployment_enabled":true,"ci_forward_deployment_rollback_allowed":true,"ci_job_token_scope_enabled":false,"ci_separated_caches":true,"ci_allow_fork_pipelines_to_run_in_parent_project":true,"build_git_strategy":"fetch","keep_latest_artifact":true,"restrict_user_defined_variables":false,"runners_token":"GR1348941v4uDTusyFqmfzCjiTcGb","runner_token_expiration_interval":null,"group_runners_enabled":true,"auto_cancel_pending_pipelines":"enabled","build_timeout":3600,"auto_devops_enabled":false,"auto_devops_deploy_strategy":"continuous","ci_config_path":"","public_jobs":true,"shared_with_groups":[],"only_allow_merge_if_pipeline_succeeds":false,"allow_merge_on_skipped_pipeline":false,"request_access_enabled":true,"only_allow_merge_if_all_discussions_are_resolved":true,"remove_source_branch_after_merge":true,"printing_merge_request_link_enabled":true,"merge_method":"merge","squash_option":"default_off","enforce_auth_checks_on_uploads":true,"suggestion_commit_message":"","merge_commit_template":null,"squash_commit_template":null,"issue_branch_template":null,"autoclose_referenced_issues":true,"external_authorization_classification_label":"","requirements_enabled":false,"requirements_access_level":"enabled","security_and_compliance_enabled":true,"compliance_frameworks":[],"permissions":{"project_access":{"access_level":50,"notification_level":3},"group_access":null}} \ No newline at end of file diff --git a/tests/update-samples.sh b/tests/update-samples.sh index bf15e2d7..0ce5985a 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -25,3 +25,4 @@ gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/releases/1.2.0 > samples/git gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/forks | jq '.[] | select(.id == 39885442)' > samples/gitlab_simple_fork.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/milestones/2975318 > samples/gitlab_simple_milestone.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/pipelines/989897020 > samples/gitlab_simple_pipeline.json +gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli > samples/gitlab_simple_repo.json diff --git a/todo.org b/todo.org index 2ad2e2a0..542ce387 100644 --- a/todo.org +++ b/todo.org @@ -161,13 +161,13 @@ - [X] Issues - [X] Labels - [X] Pulls -*** TODO Gitlab [53%] +*** TODO Gitlab [61%] - [ ] Comments - [X] Forks - [X] Milestones - [X] Pipelines - [X] Releases - - [ ] Repos + - [X] Repos - [ ] Reviews - [ ] SSH Keys - [ ] Snippets From e826edc1c6a429944e83023e69dba7bef5ad146a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 4 Sep 2023 00:55:07 +0200 Subject: [PATCH 207/236] gcli_snippet -> gcli_gitlab_snippet --- include/gcli/cmd/snippets.h | 4 +++- include/gcli/gitlab/snippets.h | 14 +++++++------- src/cmd/snippets.c | 11 ++++++----- src/gitlab/snippets.c | 6 +++--- templates/gitlab/snippets.t | 4 ++-- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/include/gcli/cmd/snippets.h b/include/gcli/cmd/snippets.h index 68fdc5da..a790867b 100644 --- a/include/gcli/cmd/snippets.h +++ b/include/gcli/cmd/snippets.h @@ -39,7 +39,9 @@ #include void gcli_snippets_print(enum gcli_output_flags const flags, - gcli_snippet_list const *const list, int const max); + gcli_gitlab_snippet_list const *const list, + int const max); + int subcommand_snippets(int argc, char *argv[]); #endif /* GCLI_CMD_SNIPPETS_H */ diff --git a/include/gcli/gitlab/snippets.h b/include/gcli/gitlab/snippets.h index f0403baf..72ae82d3 100644 --- a/include/gcli/gitlab/snippets.h +++ b/include/gcli/gitlab/snippets.h @@ -36,10 +36,10 @@ #include -typedef struct gcli_snippet gcli_snippet; -typedef struct gcli_snippet_list gcli_snippet_list; +typedef struct gcli_gitlab_snippet gcli_gitlab_snippet; +typedef struct gcli_gitlab_snippet_list gcli_gitlab_snippet_list; -struct gcli_snippet { +struct gcli_gitlab_snippet { int id; char *title; char *filename; @@ -49,14 +49,14 @@ struct gcli_snippet { char *raw_url; }; -struct gcli_snippet_list { - gcli_snippet *snippets; +struct gcli_gitlab_snippet_list { + gcli_gitlab_snippet *snippets; size_t snippets_size; }; -void gcli_snippets_free(gcli_snippet_list *list); +void gcli_snippets_free(gcli_gitlab_snippet_list *list); -int gcli_snippets_get(gcli_ctx *ctx, int max, gcli_snippet_list *out); +int gcli_snippets_get(gcli_ctx *ctx, int max, gcli_gitlab_snippet_list *out); int gcli_snippet_delete(gcli_ctx *ctx, char const *snippet_id); diff --git a/src/cmd/snippets.c b/src/cmd/snippets.c index 5195b3d5..ada815ba 100644 --- a/src/cmd/snippets.c +++ b/src/cmd/snippets.c @@ -58,7 +58,7 @@ usage(void) static void gcli_print_snippet(enum gcli_output_flags const flags, - gcli_snippet const *const it) + gcli_gitlab_snippet const *const it) { gcli_dict dict; @@ -79,7 +79,7 @@ gcli_print_snippet(enum gcli_output_flags const flags, static void gcli_print_snippets_long(enum gcli_output_flags const flags, - gcli_snippet_list const *const list, int const max) + gcli_gitlab_snippet_list const *const list, int const max) { int n; @@ -100,7 +100,8 @@ gcli_print_snippets_long(enum gcli_output_flags const flags, static void gcli_print_snippets_short(enum gcli_output_flags const flags, - gcli_snippet_list const *const list, int const max) + gcli_gitlab_snippet_list const *const list, + int const max) { int n; gcli_tbl table; @@ -146,7 +147,7 @@ gcli_print_snippets_short(enum gcli_output_flags const flags, void gcli_snippets_print(enum gcli_output_flags const flags, - gcli_snippet_list const *const list, int const max) + gcli_gitlab_snippet_list const *const list, int const max) { if (list->snippets_size == 0) { puts("No Snippets"); @@ -225,7 +226,7 @@ int subcommand_snippets(int argc, char *argv[]) { int ch; - gcli_snippet_list list = {0}; + gcli_gitlab_snippet_list list = {0}; int count = 30; enum gcli_output_flags flags = 0; diff --git a/src/gitlab/snippets.c b/src/gitlab/snippets.c index 3bb8064f..7883e0d3 100644 --- a/src/gitlab/snippets.c +++ b/src/gitlab/snippets.c @@ -41,7 +41,7 @@ #include void -gcli_snippets_free(gcli_snippet_list *const list) +gcli_snippets_free(gcli_gitlab_snippet_list *const list) { for (size_t i = 0; i < list->snippets_size; ++i) { free(list->snippets[i].title); @@ -59,7 +59,7 @@ gcli_snippets_free(gcli_snippet_list *const list) } int -gcli_snippets_get(gcli_ctx *ctx, int const max, gcli_snippet_list *const out) +gcli_snippets_get(gcli_ctx *ctx, int const max, gcli_gitlab_snippet_list *const out) { char *url = NULL; @@ -70,7 +70,7 @@ gcli_snippets_get(gcli_ctx *ctx, int const max, gcli_snippet_list *const out) .parse = (parsefn)(parse_gitlab_snippets), }; - *out = (gcli_snippet_list) {0}; + *out = (gcli_gitlab_snippet_list) {0}; url = sn_asprintf("%s/snippets", gcli_get_apibase(ctx)); return gcli_fetch_list(ctx, url, &fl); diff --git a/templates/gitlab/snippets.t b/templates/gitlab/snippets.t index 1233dfb8..ed250d2d 100644 --- a/templates/gitlab/snippets.t +++ b/templates/gitlab/snippets.t @@ -2,7 +2,7 @@ include "gcli/json_util.h"; include "gcli/gitlab/snippets.h"; parser gitlab_snippet is -object of gcli_snippet with +object of gcli_gitlab_snippet with ("title" => title as string, "id" => id as int, "raw_url" => raw_url as string, @@ -12,4 +12,4 @@ object of gcli_snippet with "visibility" => visibility as string); parser gitlab_snippets is -array of gcli_snippet use parse_gitlab_snippet; \ No newline at end of file +array of gcli_gitlab_snippet use parse_gitlab_snippet; From e06fcae55ef2b268bd5cd18f40deb2e3f4d9d63a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 4 Sep 2023 00:39:37 +0200 Subject: [PATCH 208/236] Add tests for Gitlab snippets --- Makefile.am | 1 + tests/gitlab-parse-tests.c | 22 ++++++++++++++++++++++ tests/samples/gitlab_simple_snippet.json | 1 + tests/update-samples.sh | 1 + todo.org | 2 +- 5 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 tests/samples/gitlab_simple_snippet.json diff --git a/Makefile.am b/Makefile.am index f0690d4a..c9541984 100644 --- a/Makefile.am +++ b/Makefile.am @@ -257,6 +257,7 @@ EXTRA_DIST += tests/samples/github_simple_comment.json \ tests/samples/gitlab_simple_pipeline.json \ tests/samples/gitlab_simple_release.json \ tests/samples/gitlab_simple_repo.json \ + tests/samples/gitlab_simple_snippet.json \ tests/samples/github_simple_check.json endif diff --git a/tests/gitlab-parse-tests.c b/tests/gitlab-parse-tests.c index c00dcaab..72a8064f 100644 --- a/tests/gitlab-parse-tests.c +++ b/tests/gitlab-parse-tests.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -255,6 +256,26 @@ ATF_TC_BODY(gitlab_simple_repo, tc) ATF_CHECK(repo.is_fork == false); } +ATF_TC_WITHOUT_HEAD(gitlab_simple_snippet); +ATF_TC_BODY(gitlab_simple_snippet, tc) +{ + json_stream stream = {0}; + gcli_ctx *ctx = test_context(); + FILE *f = open_sample("gitlab_simple_snippet.json"); + gcli_gitlab_snippet snippet = {0}; + + json_open_stream(&stream, f); + ATF_REQUIRE(parse_gitlab_snippet(ctx, &stream, &snippet) == 0); + + ATF_CHECK(snippet.id == 2141655); + ATF_CHECK_STREQ(snippet.title, "darcy-weisbach SPARC64"); + ATF_CHECK_STREQ(snippet.filename, "darcy-weisbach SPARC64"); + ATF_CHECK_STREQ(snippet.date, "2021-06-28T15:47:36.214Z"); + ATF_CHECK_STREQ(snippet.author, "herrhotzenplotz"); + ATF_CHECK_STREQ(snippet.visibility, "public"); + ATF_CHECK_STREQ(snippet.raw_url, "https://gitlab.com/-/snippets/2141655/raw"); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, gitlab_simple_fork); @@ -265,6 +286,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, gitlab_simple_pipeline); ATF_TP_ADD_TC(tp, gitlab_simple_release); ATF_TP_ADD_TC(tp, gitlab_simple_repo); + ATF_TP_ADD_TC(tp, gitlab_simple_snippet); return atf_no_error(); } diff --git a/tests/samples/gitlab_simple_snippet.json b/tests/samples/gitlab_simple_snippet.json new file mode 100644 index 00000000..8ed3a3a3 --- /dev/null +++ b/tests/samples/gitlab_simple_snippet.json @@ -0,0 +1 @@ +{"id":2141655,"title":"darcy-weisbach SPARC64","description":"Paste","visibility":"public","author":{"id":5980462,"username":"herrhotzenplotz","name":"Nico Sonack","state":"active","avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/5980462/avatar.png","web_url":"https://gitlab.com/herrhotzenplotz"},"created_at":"2021-06-28T15:47:36.214Z","updated_at":"2021-06-28T15:47:36.214Z","project_id":null,"web_url":"https://gitlab.com/-/snippets/2141655","raw_url":"https://gitlab.com/-/snippets/2141655/raw","ssh_url_to_repo":"git@gitlab.com:snippets/2141655.git","http_url_to_repo":"https://gitlab.com/snippets/2141655.git","file_name":"darcy-weisbach SPARC64","files":[{"path":"darcy-weisbach SPARC64","raw_url":"https://gitlab.com/-/snippets/2141655/raw/main/darcy-weisbach%20SPARC64"}]} \ No newline at end of file diff --git a/tests/update-samples.sh b/tests/update-samples.sh index 0ce5985a..b65e655c 100755 --- a/tests/update-samples.sh +++ b/tests/update-samples.sh @@ -26,3 +26,4 @@ gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/forks | jq '.[] | select(.id gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/milestones/2975318 > samples/gitlab_simple_milestone.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli/pipelines/989897020 > samples/gitlab_simple_pipeline.json gcli -t gitlab api /projects/herrhotzenplotz%2Fgcli > samples/gitlab_simple_repo.json +gcli -t gitlab api /snippets/2141655 > samples/gitlab_simple_snippet.json diff --git a/todo.org b/todo.org index 542ce387..2393d156 100644 --- a/todo.org +++ b/todo.org @@ -170,7 +170,7 @@ - [X] Repos - [ ] Reviews - [ ] SSH Keys - - [ ] Snippets + - [X] Snippets - [ ] Status - [X] Issues - [X] Labels From 6e8280d23cd5cd06d3070c0ea1def68a61db48c4 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 4 Sep 2023 11:13:42 +0200 Subject: [PATCH 209/236] Add test helper with macros for asserting on string views --- Makefile.am | 3 +++ tests/gcli_tests.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 tests/gcli_tests.h diff --git a/Makefile.am b/Makefile.am index c9541984..ebeb64a8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -215,6 +215,9 @@ check_PROGRAMS = \ tests/url-encode$(EXEEXT) \ tests/pretty_print_test$(EXEEXT) +$(check_PROGRAMS): tests/gcli_tests.h + +EXTRA_DIST += tests/gcli_tests.h check: $(check_PROGRAMS) tests/Kyuafile libgcli.la libsn.la libpdjson.la do_test do_test: diff --git a/tests/gcli_tests.h b/tests/gcli_tests.h new file mode 100644 index 00000000..34ca2e63 --- /dev/null +++ b/tests/gcli_tests.h @@ -0,0 +1,44 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GCLI_TESTS_H +#define GCLI_TESTS_H + +#if defined(HAVE_CONFIG_H) +#include +#endif /* HAVE_CONFIG_H */ + +#include + +/* Helper for making assertions on my custom string views. These + * should get removed at some point */ +#define ATF_CHECK_SV_EQTO(view, str) \ + ATF_CHECK(sn_sv_eq_to((view), str)) + +#endif /* GCLI_TESTS_H */ From 1378bbc5ef1c36071370ca39a93f3232c6c91c7e Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 4 Sep 2023 10:46:43 +0200 Subject: [PATCH 210/236] gitlab tests: use new string view assertion macro --- tests/gitlab-parse-tests.c | 42 ++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/tests/gitlab-parse-tests.c b/tests/gitlab-parse-tests.c index 72a8064f..c301011b 100644 --- a/tests/gitlab-parse-tests.c +++ b/tests/gitlab-parse-tests.c @@ -13,9 +13,7 @@ #include -#include - -#include +#include "gcli_tests.h" static gcli_forge_type get_gitlab_forge_type(gcli_ctx *ctx) @@ -93,15 +91,15 @@ ATF_TC_BODY(gitlab_simple_issue, tc) ATF_REQUIRE(parse_gitlab_issue(ctx, &stream, &issue) == 0); ATF_CHECK(issue.number == 193); - ATF_CHECK(sn_sv_eq_to(issue.title, "Make notifications API use a list struct containing both the ptr and size")); - ATF_CHECK(sn_sv_eq_to(issue.created_at, "2023-08-13T18:43:05.766Z")); - ATF_CHECK(sn_sv_eq_to(issue.author, "herrhotzenplotz")); - ATF_CHECK(sn_sv_eq_to(issue.state, "closed")); + ATF_CHECK_SV_EQTO(issue.title, "Make notifications API use a list struct containing both the ptr and size"); + ATF_CHECK_SV_EQTO(issue.created_at, "2023-08-13T18:43:05.766Z"); + ATF_CHECK_SV_EQTO(issue.author, "herrhotzenplotz"); + ATF_CHECK_SV_EQTO(issue.state, "closed"); ATF_CHECK(issue.comments == 2); ATF_CHECK(issue.locked == false); - ATF_CHECK(sn_sv_eq_to(issue.body, "That would make some of the code much cleaner")); + ATF_CHECK_SV_EQTO(issue.body, "That would make some of the code much cleaner"); ATF_CHECK(issue.labels_size == 1); - ATF_CHECK(sn_sv_eq_to(issue.labels[0], "good-first-issue")); + ATF_CHECK_SV_EQTO(issue.labels[0], "good-first-issue"); ATF_CHECK(issue.assignees == NULL); ATF_CHECK(issue.assignees_size == 0); ATF_CHECK(issue.is_pr == 0); @@ -142,7 +140,7 @@ ATF_TC_BODY(gitlab_simple_release, tc) gitlab_fixup_release_assets(ctx, &release); /* NOTE(Nico): on gitlab this is the tag name */ - ATF_CHECK(sn_sv_eq_to(release.id, "1.2.0")); + ATF_CHECK_SV_EQTO(release.id, "1.2.0"); ATF_CHECK(release.assets_size == 4); { ATF_CHECK_STREQ(release.assets[0].name, "gcli-1.2.0.zip"); @@ -165,10 +163,10 @@ ATF_TC_BODY(gitlab_simple_release, tc) "https://gitlab.com/herrhotzenplotz/gcli/-/archive/1.2.0/gcli-1.2.0.tar"); } - ATF_CHECK(sn_sv_eq_to(release.name, "1.2.0")); - ATF_CHECK(sn_sv_eq_to(release.body, "# Version 1.2.0\n\nThis is version 1.2.0 of gcli.\n\n## Notes\n\nPlease test and report bugs.\n\nYou can download autotoolized tarballs at: https://herrhotzenplotz.de/gcli/releases/gcli-1.2.0/\n\n## Bug Fixes\n\n- Fix compile error when providing --with-libcurl without any arguments\n- Fix memory leaks in string processing functions\n- Fix missing nul termination in read-file function\n- Fix segmentation fault when clearing the milestone of a PR on Gitea\n- Fix missing documentation for milestone action in issues and pulls\n- Set the 'merged' flag properly when showing Gitlab merge requests\n\n## New features\n\n- Add a config subcommand for managing ssh keys (see gcli-config(1))\n- Show number of comments/notes in list of issues and PRs\n- Add support for milestone management in pull requests\n")); - ATF_CHECK(sn_sv_eq_to(release.author, "herrhotzenplotz")); - ATF_CHECK(sn_sv_eq_to(release.date, "2023-08-11T07:56:06.371Z")); + ATF_CHECK_SV_EQTO(release.name, "1.2.0"); + ATF_CHECK_SV_EQTO(release.body, "# Version 1.2.0\n\nThis is version 1.2.0 of gcli.\n\n## Notes\n\nPlease test and report bugs.\n\nYou can download autotoolized tarballs at: https://herrhotzenplotz.de/gcli/releases/gcli-1.2.0/\n\n## Bug Fixes\n\n- Fix compile error when providing --with-libcurl without any arguments\n- Fix memory leaks in string processing functions\n- Fix missing nul termination in read-file function\n- Fix segmentation fault when clearing the milestone of a PR on Gitea\n- Fix missing documentation for milestone action in issues and pulls\n- Set the 'merged' flag properly when showing Gitlab merge requests\n\n## New features\n\n- Add a config subcommand for managing ssh keys (see gcli-config(1))\n- Show number of comments/notes in list of issues and PRs\n- Add support for milestone management in pull requests\n"); + ATF_CHECK_SV_EQTO(release.author, "herrhotzenplotz"); + ATF_CHECK_SV_EQTO(release.date, "2023-08-11T07:56:06.371Z"); ATF_CHECK(sn_sv_null(release.upload_url)); ATF_CHECK(release.draft == false); ATF_CHECK(release.prerelease == false); @@ -185,9 +183,9 @@ ATF_TC_BODY(gitlab_simple_fork, tc) json_open_stream(&stream, f); ATF_REQUIRE(parse_gitlab_fork(ctx, &stream, &fork) == 0); - ATF_CHECK(sn_sv_eq_to(fork.full_name, "gjnoonan/gcli")); - ATF_CHECK(sn_sv_eq_to(fork.owner, "gjnoonan")); - ATF_CHECK(sn_sv_eq_to(fork.date, "2022-10-02T13:54:20.517Z")); + ATF_CHECK_SV_EQTO(fork.full_name, "gjnoonan/gcli"); + ATF_CHECK_SV_EQTO(fork.owner, "gjnoonan"); + ATF_CHECK_SV_EQTO(fork.date, "2022-10-02T13:54:20.517Z"); ATF_CHECK(fork.forks == 0); } @@ -248,11 +246,11 @@ ATF_TC_BODY(gitlab_simple_repo, tc) ATF_REQUIRE(parse_gitlab_repo(ctx, &stream, &repo) == 0); ATF_CHECK(repo.id == 34707535); - ATF_CHECK(sn_sv_eq_to(repo.full_name, "herrhotzenplotz/gcli")); - ATF_CHECK(sn_sv_eq_to(repo.name, "gcli")); - ATF_CHECK(sn_sv_eq_to(repo.owner, "herrhotzenplotz")); - ATF_CHECK(sn_sv_eq_to(repo.date, "2022-03-22T16:57:59.891Z")); - ATF_CHECK(sn_sv_eq_to(repo.visibility, "public")); + ATF_CHECK_SV_EQTO(repo.full_name, "herrhotzenplotz/gcli"); + ATF_CHECK_SV_EQTO(repo.name, "gcli"); + ATF_CHECK_SV_EQTO(repo.owner, "herrhotzenplotz"); + ATF_CHECK_SV_EQTO(repo.date, "2022-03-22T16:57:59.891Z"); + ATF_CHECK_SV_EQTO(repo.visibility, "public"); ATF_CHECK(repo.is_fork == false); } From dd8a7b9bd3cac2b8ce95732f0fdbe4ddbfb09831 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 4 Sep 2023 10:52:32 +0200 Subject: [PATCH 211/236] Add license header --- tests/github-parse-tests.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/github-parse-tests.c b/tests/github-parse-tests.c index 24fb0aca..e638cef2 100644 --- a/tests/github-parse-tests.c +++ b/tests/github-parse-tests.c @@ -1,3 +1,32 @@ +/* + * Copyright 2023 Nico Sonack + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include #include #include From 519ab36238c15d21d7dececfc2694857f53d2c94 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 4 Sep 2023 11:07:04 +0200 Subject: [PATCH 212/236] Make Github tests use new string view macro --- tests/github-parse-tests.c | 47 ++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/tests/github-parse-tests.c b/tests/github-parse-tests.c index e638cef2..bab67126 100644 --- a/tests/github-parse-tests.c +++ b/tests/github-parse-tests.c @@ -42,9 +42,7 @@ #include -#include - -#include +#include "gcli_tests.h" static gcli_forge_type get_github_forge_type(gcli_ctx *ctx) @@ -87,19 +85,18 @@ ATF_TC_BODY(simple_github_issue, tc) ATF_REQUIRE(parse_github_issue(ctx, &stream, &issue) == 0); ATF_CHECK(issue.number = 115); - ATF_CHECK(sn_sv_eq_to(issue.title, "consider removing FILE *out from printing functions")); - ATF_CHECK(sn_sv_eq_to(issue.created_at, "2022-03-22T16:06:10Z")); - ATF_CHECK(sn_sv_eq_to(issue.author, "herrhotzenplotz")); - ATF_CHECK(sn_sv_eq_to(issue.state, "closed")); + ATF_CHECK_SV_EQTO(issue.title, "consider removing FILE *out from printing functions"); + ATF_CHECK_SV_EQTO(issue.created_at, "2022-03-22T16:06:10Z"); + ATF_CHECK_SV_EQTO(issue.author, "herrhotzenplotz"); + ATF_CHECK_SV_EQTO(issue.state, "closed"); ATF_CHECK(issue.comments == 0); ATF_CHECK(issue.locked == false); - ATF_CHECK(sn_sv_eq_to( - issue.body, + ATF_CHECK_SV_EQTO(issue.body, "We use these functions with ghcli only anyways. In " "the GUI stuff we use the datastructures returned by " "the api directly. And If we output, it is stdout " - "everywhere.\n")); + "everywhere.\n"); ATF_CHECK(issue.labels_size == 0); ATF_CHECK(issue.labels == NULL); @@ -204,15 +201,15 @@ ATF_TC_BODY(simple_github_release, tc) ATF_REQUIRE(parse_github_release(ctx, &stream, &release) == 0); - ATF_CHECK(sn_sv_eq_to(release.id, "116031718")); + ATF_CHECK_SV_EQTO(release.id, "116031718"); ATF_CHECK(release.assets_size == 0); ATF_CHECK(release.assets == NULL); - ATF_CHECK(sn_sv_eq_to(release.name, "1.2.0")); - ATF_CHECK(sn_sv_eq_to(release.body, "# Version 1.2.0\n\nThis is version 1.2.0 of gcli.\n\n## Notes\n\nPlease test and report bugs.\n\nYou can download autotoolized tarballs at: https://herrhotzenplotz.de/gcli/releases/gcli-1.2.0/\n\n## Bug Fixes\n\n- Fix compile error when providing --with-libcurl without any arguments\n- Fix memory leaks in string processing functions\n- Fix missing nul termination in read-file function\n- Fix segmentation fault when clearing the milestone of a PR on Gitea\n- Fix missing documentation for milestone action in issues and pulls\n- Set the 'merged' flag properly when showing Gitlab merge requests\n\n## New features\n\n- Add a config subcommand for managing ssh keys (see gcli-config(1))\n- Show number of comments/notes in list of issues and PRs\n- Add support for milestone management in pull requests\n")); - ATF_CHECK(sn_sv_eq_to(release.author, "herrhotzenplotz")); - ATF_CHECK(sn_sv_eq_to(release.date, "2023-08-11T07:42:37Z")); - ATF_CHECK(sn_sv_eq_to(release.upload_url, "https://uploads.github.com/repos/herrhotzenplotz/gcli/releases/116031718/assets{?name,label}")); - ATF_CHECK(sn_sv_eq_to(release.html_url, "https://github.com/herrhotzenplotz/gcli/releases/tag/1.2.0")); + ATF_CHECK_SV_EQTO(release.name, "1.2.0"); + ATF_CHECK_SV_EQTO(release.body, "# Version 1.2.0\n\nThis is version 1.2.0 of gcli.\n\n## Notes\n\nPlease test and report bugs.\n\nYou can download autotoolized tarballs at: https://herrhotzenplotz.de/gcli/releases/gcli-1.2.0/\n\n## Bug Fixes\n\n- Fix compile error when providing --with-libcurl without any arguments\n- Fix memory leaks in string processing functions\n- Fix missing nul termination in read-file function\n- Fix segmentation fault when clearing the milestone of a PR on Gitea\n- Fix missing documentation for milestone action in issues and pulls\n- Set the 'merged' flag properly when showing Gitlab merge requests\n\n## New features\n\n- Add a config subcommand for managing ssh keys (see gcli-config(1))\n- Show number of comments/notes in list of issues and PRs\n- Add support for milestone management in pull requests\n"); + ATF_CHECK_SV_EQTO(release.author, "herrhotzenplotz"); + ATF_CHECK_SV_EQTO(release.date, "2023-08-11T07:42:37Z"); + ATF_CHECK_SV_EQTO(release.upload_url, "https://uploads.github.com/repos/herrhotzenplotz/gcli/releases/116031718/assets{?name,label}"); + ATF_CHECK_SV_EQTO(release.html_url, "https://github.com/herrhotzenplotz/gcli/releases/tag/1.2.0"); ATF_CHECK(release.draft == false); ATF_CHECK(release.prerelease == false); } @@ -231,11 +228,11 @@ ATF_TC_BODY(simple_github_repo, tc) ATF_REQUIRE(parse_github_repo(ctx, &stream, &repo) == 0); ATF_CHECK(repo.id == 415015197); - ATF_CHECK(sn_sv_eq_to(repo.full_name, "herrhotzenplotz/gcli")); - ATF_CHECK(sn_sv_eq_to(repo.name, "gcli")); - ATF_CHECK(sn_sv_eq_to(repo.owner, "herrhotzenplotz")); - ATF_CHECK(sn_sv_eq_to(repo.date, "2021-10-08T14:20:15Z")); - ATF_CHECK(sn_sv_eq_to(repo.visibility, "public")); + ATF_CHECK_SV_EQTO(repo.full_name, "herrhotzenplotz/gcli"); + ATF_CHECK_SV_EQTO(repo.name, "gcli"); + ATF_CHECK_SV_EQTO(repo.owner, "herrhotzenplotz"); + ATF_CHECK_SV_EQTO(repo.date, "2021-10-08T14:20:15Z"); + ATF_CHECK_SV_EQTO(repo.visibility, "public"); ATF_CHECK(repo.is_fork == false); } @@ -252,9 +249,9 @@ ATF_TC_BODY(simple_github_fork, tc) ATF_REQUIRE(parse_github_fork(ctx, &stream, &fork) == 0); - ATF_CHECK(sn_sv_eq_to(fork.full_name, "gjnoonan/quick-lint-js")); - ATF_CHECK(sn_sv_eq_to(fork.owner, "gjnoonan")); - ATF_CHECK(sn_sv_eq_to(fork.date, "2023-05-11T05:37:41Z")); + ATF_CHECK_SV_EQTO(fork.full_name, "gjnoonan/quick-lint-js"); + ATF_CHECK_SV_EQTO(fork.owner, "gjnoonan"); + ATF_CHECK_SV_EQTO(fork.date, "2023-05-11T05:37:41Z"); ATF_CHECK(fork.forks == 0); } From 0a546fdbe9f3a832a7d3d2f751c379afac671247 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 4 Sep 2023 11:05:59 +0000 Subject: [PATCH 213/236] Remove gcli_release.html_url --- include/gcli/forges.h | 5 ----- include/gcli/releases.h | 1 - src/forges.c | 3 --- src/gitea/releases.c | 2 -- src/github/releases.c | 2 -- src/releases.c | 1 - templates/github/releases.t | 5 ++--- tests/github-parse-tests.c | 1 - 8 files changed, 2 insertions(+), 18 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index f6dcd2a0..4edfca95 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -492,11 +492,6 @@ struct gcli_forge_descriptor { * A key in the user json object sent by the API that represents * the user name */ char const *user_object_key; - - /** - * A key in responses by the API that represents the URL for the - * object being operated on */ - char const *html_url_key; }; gcli_forge_descriptor const *gcli_forge(gcli_ctx *ctx); diff --git a/include/gcli/releases.h b/include/gcli/releases.h index 160428c8..5992b9b6 100644 --- a/include/gcli/releases.h +++ b/include/gcli/releases.h @@ -57,7 +57,6 @@ struct gcli_release { sn_sv author; sn_sv date; sn_sv upload_url; - sn_sv html_url; bool draft; bool prerelease; }; diff --git a/src/forges.c b/src/forges.c index 9c8f7b02..cc8e002e 100644 --- a/src/forges.c +++ b/src/forges.c @@ -137,7 +137,6 @@ github_forge_descriptor = .make_authheader = github_make_authheader, .get_api_error_string = github_api_error_string, .user_object_key = "login", - .html_url_key = "html_url", .pull_summary_quirks = GCLI_PRS_QUIRK_COVERAGE, .milestone_quirks = GCLI_MILESTONE_QUIRKS_EXPIRED | GCLI_MILESTONE_QUIRKS_DUEDATE @@ -199,7 +198,6 @@ gitlab_forge_descriptor = .delete_sshkey = gitlab_delete_sshkey, .get_api_error_string = gitlab_api_error_string, .user_object_key = "username", - .html_url_key = "web_url", .pull_summary_quirks = GCLI_PRS_QUIRK_ADDDEL | GCLI_PRS_QUIRK_COMMITS | GCLI_PRS_QUIRK_CHANGES @@ -262,7 +260,6 @@ gitea_forge_descriptor = .make_authheader = gitea_make_authheader, .get_api_error_string = github_api_error_string, /* hack! */ .user_object_key = "username", - .html_url_key = "web_url", .pull_summary_quirks = GCLI_PRS_QUIRK_COMMITS | GCLI_PRS_QUIRK_ADDDEL | GCLI_PRS_QUIRK_DRAFT diff --git a/src/gitea/releases.c b/src/gitea/releases.c index 091b7970..6d78f79a 100644 --- a/src/gitea/releases.c +++ b/src/gitea/releases.c @@ -128,8 +128,6 @@ gitea_create_release(gcli_ctx *ctx, gcli_new_release const *release) gitea_parse_release(ctx, &buffer, &response); - printf("INFO : Release at "SV_FMT"\n", SV_ARGS(response.html_url)); - upload_url = sn_asprintf("%s/repos/%s/%s/releases/"SV_FMT"/assets", gcli_get_apibase(ctx), e_owner, e_repo, SV_ARGS(response.id)); diff --git a/src/github/releases.c b/src/github/releases.c index 9a0f5373..46df9cd2 100644 --- a/src/github/releases.c +++ b/src/github/releases.c @@ -182,8 +182,6 @@ github_create_release(gcli_ctx *ctx, gcli_new_release const *release) github_parse_single_release(ctx, buffer, &response); - printf("INFO : Release at "SV_FMT"\n", SV_ARGS(response.html_url)); - rc = github_get_upload_url(ctx, &response, &upload_url); if (rc < 0) goto out; diff --git a/src/releases.c b/src/releases.c index be1f0684..d844e5b0 100644 --- a/src/releases.c +++ b/src/releases.c @@ -51,7 +51,6 @@ gcli_free_releases(gcli_release_list *const list) free(list->releases[i].author.data); free(list->releases[i].date.data); free(list->releases[i].upload_url.data); - free(list->releases[i].html_url.data); for (size_t j = 0; j < list->releases[i].assets_size; ++j) { free(list->releases[i].assets[j].name); diff --git a/templates/github/releases.t b/templates/github/releases.t index f67ded36..d2748590 100644 --- a/templates/github/releases.t +++ b/templates/github/releases.t @@ -16,8 +16,7 @@ object of gcli_release with "prerelease" => prerelease as bool, "assets" => assets as array of gcli_release_asset use parse_github_release_asset, - "upload_url" => upload_url as sv, - "html_url" => html_url as sv); + "upload_url" => upload_url as sv); parser github_releases is array of gcli_release - use parse_github_release; \ No newline at end of file + use parse_github_release; diff --git a/tests/github-parse-tests.c b/tests/github-parse-tests.c index bab67126..9c611a41 100644 --- a/tests/github-parse-tests.c +++ b/tests/github-parse-tests.c @@ -209,7 +209,6 @@ ATF_TC_BODY(simple_github_release, tc) ATF_CHECK_SV_EQTO(release.author, "herrhotzenplotz"); ATF_CHECK_SV_EQTO(release.date, "2023-08-11T07:42:37Z"); ATF_CHECK_SV_EQTO(release.upload_url, "https://uploads.github.com/repos/herrhotzenplotz/gcli/releases/116031718/assets{?name,label}"); - ATF_CHECK_SV_EQTO(release.html_url, "https://github.com/herrhotzenplotz/gcli/releases/tag/1.2.0"); ATF_CHECK(release.draft == false); ATF_CHECK(release.prerelease == false); } From 994ea0e0e5f880d726307850f236c4ab60bad9c3 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Sep 2023 18:48:20 +0200 Subject: [PATCH 214/236] Fix incorrect mandoc syntax in gcli.1 .Bd does not take -width but -offset as an option --- docs/gcli.1.in | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/gcli.1.in b/docs/gcli.1.in index 54c10e80..1ca7fbde 100644 --- a/docs/gcli.1.in +++ b/docs/gcli.1.in @@ -249,23 +249,23 @@ to manually specify all the options like .El .Sh EXAMPLES List recently opened issues in the current upstream repository: -.Bd -literal -width indent +.Bd -literal -offset indent $ gcli issues .Ed .Pp Merge upstream PR #22: -.Bd -literal -width indent +.Bd -literal -offset indent $ gcli pulls -p 22 merge .Ed .Pp Get a summary and comments of upstream PR #22: -.Bd -literal -width indent +.Bd -literal -offset indent $ gcli pulls -p 22 summary comments .Ed .Pp Establish a connection to github and print the last 10 pull requests in contour-terminal/contour regardless of their state. -.Bd -literal -width indent +.Bd -literal -offset indent $ gcli -t github pulls -o contour-terminal -r contour -a -n10 .Ed .Pp @@ -318,7 +318,7 @@ Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ or on Github. .Pp You may also report an issue like so: -.Bd -literal -width indent +.Bd -literal -offset indent $ gcli -a some-gitlab-account \\ issues create \\ -o herrhotzenplotz -r gcli \\ From e16c74b1ab1b6b9403538e463bddfeaaee9bae4f Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Sep 2023 18:53:32 +0200 Subject: [PATCH 215/236] Unalign struct members --- include/gcli/issues.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/include/gcli/issues.h b/include/gcli/issues.h index 212cd55c..2ada6e61 100644 --- a/include/gcli/issues.h +++ b/include/gcli/issues.h @@ -45,28 +45,28 @@ typedef struct gcli_issue_list gcli_issue_list; typedef struct gcli_issue_fetch_details gcli_issue_fetch_details; struct gcli_issue { - int number; - sn_sv title; - sn_sv created_at; - sn_sv author; - sn_sv state; - int comments; - bool locked; - sn_sv body; - sn_sv *labels; - size_t labels_size; - sn_sv *assignees; - size_t assignees_size; + int number; + sn_sv title; + sn_sv created_at; + sn_sv author; + sn_sv state; + int comments; + bool locked; + sn_sv body; + sn_sv *labels; + size_t labels_size; + sn_sv *assignees; + size_t assignees_size; /* workaround for GitHub where PRs are also issues */ - int is_pr; - sn_sv milestone; + int is_pr; + sn_sv milestone; }; struct gcli_submit_issue_options { char const *owner; char const *repo; - sn_sv title; - sn_sv body; + sn_sv title; + sn_sv body; }; struct gcli_issue_list { From 258887ad90bd1f4d2f48e63aae5fbfa700027981 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Sep 2023 18:53:46 +0200 Subject: [PATCH 216/236] Add new gcli_id type --- include/gcli/gcli.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/gcli/gcli.h b/include/gcli/gcli.h index 767997f7..88cd88ed 100644 --- a/include/gcli/gcli.h +++ b/include/gcli/gcli.h @@ -45,6 +45,8 @@ typedef enum gcli_forge_type { GCLI_FORGE_GITEA, } gcli_forge_type; +typedef unsigned int gcli_id; + #ifdef IN_LIBGCLI #include #endif /* IN_LIBGCLI */ From e989bfff8272f1e1d14d02e01f888551bbb7fccd Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Sep 2023 19:05:30 +0200 Subject: [PATCH 217/236] Add parser support for gcli_id type --- include/gcli/json_util.h | 2 ++ src/json_util.c | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/include/gcli/json_util.h b/include/gcli/json_util.h index 22921dfc..632d8d62 100644 --- a/include/gcli/json_util.h +++ b/include/gcli/json_util.h @@ -43,6 +43,7 @@ #include #define get_int(ctx, input, out) get_int_(ctx, input, out, __func__) +#define get_id(ctx, input, out) get_id_(ctx, input, out, __func__) #define get_long(ctx, input, out) get_long_(ctx, input, out, __func__) #define get_size_t(ctx, input, out) get_size_t_(ctx, input, out, __func__) #define get_double(ctx, input, out) get_double_(ctx, input, out, __func__) @@ -57,6 +58,7 @@ #define get_int_to_string(ctx, input, out) get_int_to_string_(ctx, input, out, __func__) int get_int_(gcli_ctx *ctx, json_stream *input, int *out, char const *function); +int get_id_(gcli_ctx *ctx, json_stream *input, gcli_id *out, char const *function); int get_long_(gcli_ctx *ctx, json_stream *input, long *out, char const *function); int get_size_t_(gcli_ctx *ctx, json_stream *input, size_t *out, char const *function); int get_double_(gcli_ctx *ctx, json_stream *input, double *out, char const *function); diff --git a/src/json_util.c b/src/json_util.c index 2c14a643..e23e489f 100644 --- a/src/json_util.c +++ b/src/json_util.c @@ -47,6 +47,17 @@ get_int_(gcli_ctx *ctx, json_stream *const input, int *out, char const *where) return 0; } +int +get_id_(gcli_ctx *ctx, json_stream *const input, gcli_id *out, char const *where) +{ + if (json_next(input) != JSON_NUMBER) + return gcli_error(ctx, "unexpected non-integer ID field in %s", where); + + *out = json_get_number(input); + + return 0; +} + int get_long_(gcli_ctx *ctx, json_stream *const input, long *out, char const *where) { From b5cb2a3753afb1ef3488d6c3a60a43cead1c333f Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Sep 2023 19:06:38 +0200 Subject: [PATCH 218/236] Use gcli_id type in issues --- include/gcli/issues.h | 18 +++++++++--------- src/issues.c | 16 ++++++++-------- templates/github/issues.t | 2 +- templates/gitlab/issues.t | 4 ++-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/gcli/issues.h b/include/gcli/issues.h index 2ada6e61..ca2cdd7e 100644 --- a/include/gcli/issues.h +++ b/include/gcli/issues.h @@ -45,7 +45,7 @@ typedef struct gcli_issue_list gcli_issue_list; typedef struct gcli_issue_fetch_details gcli_issue_fetch_details; struct gcli_issue { - int number; + gcli_id number; sn_sv title; sn_sv created_at; sn_sv author; @@ -86,33 +86,33 @@ int gcli_get_issues(gcli_ctx *ctx, char const *owner, char const *reponame, void gcli_issues_free(gcli_issue_list *); int gcli_get_issue(gcli_ctx *ctx, char const *owner, char const *reponame, - int issue_number, gcli_issue *out); + gcli_id issue_number, gcli_issue *out); void gcli_issue_free(gcli_issue *it); int gcli_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number); + gcli_id issue_number); int gcli_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number); + gcli_id issue_number); int gcli_issue_submit(gcli_ctx *ctx, gcli_submit_issue_options); int gcli_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number, char const *assignee); + gcli_id issue_number, char const *assignee); int gcli_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number, char const *const labels[], + gcli_id issue_number, char const *const labels[], size_t labels_size); int gcli_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number, char const *const labels[], + gcli_id issue_number, char const *const labels[], size_t labels_size); int gcli_issue_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int issue, int milestone); + gcli_id issue, int milestone); int gcli_issue_clear_milestone(gcli_ctx *cxt, char const *owner, - char const *repo, int issue); + char const *repo, gcli_id issue); #endif /* ISSUES_H */ diff --git a/src/issues.c b/src/issues.c index 2169810e..9c9bba3c 100644 --- a/src/issues.c +++ b/src/issues.c @@ -71,7 +71,7 @@ gcli_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, int gcli_get_issue(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number, gcli_issue *const out) + gcli_id const issue_number, gcli_issue *const out) { return gcli_forge(ctx)->get_issue_summary( ctx, owner, repo, issue_number, out); @@ -79,14 +79,14 @@ gcli_get_issue(gcli_ctx *ctx, char const *owner, char const *repo, int gcli_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number) + gcli_id const issue_number) { return gcli_forge(ctx)->issue_close(ctx, owner, repo, issue_number); } int gcli_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number) + gcli_id const issue_number) { return gcli_forge(ctx)->issue_reopen(ctx, owner, repo, issue_number); } @@ -105,14 +105,14 @@ gcli_issue_submit(gcli_ctx *ctx, gcli_submit_issue_options opts) int gcli_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number, char const *assignee) + gcli_id const issue_number, char const *assignee) { return gcli_forge(ctx)->issue_assign(ctx, owner, repo, issue_number, assignee); } int gcli_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue, char const *const labels[], + gcli_id const issue, char const *const labels[], size_t const labels_size) { return gcli_forge(ctx)->issue_add_labels(ctx,owner, repo, issue, labels, @@ -121,7 +121,7 @@ gcli_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, int gcli_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue, char const *const labels[], + gcli_id const issue, char const *const labels[], size_t const labels_size) { return gcli_forge(ctx)->issue_remove_labels( @@ -130,7 +130,7 @@ gcli_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, int gcli_issue_set_milestone(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const issue, + char const *const repo, gcli_id const issue, int const milestone) { return gcli_forge(ctx)->issue_set_milestone( @@ -139,7 +139,7 @@ gcli_issue_set_milestone(gcli_ctx *ctx, char const *const owner, int gcli_issue_clear_milestone(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const issue) + char const *const repo, gcli_id const issue) { return gcli_forge(ctx)->issue_clear_milestone(ctx, owner, repo, issue); } diff --git a/templates/github/issues.t b/templates/github/issues.t index 7e5a897c..faee7f79 100644 --- a/templates/github/issues.t +++ b/templates/github/issues.t @@ -13,7 +13,7 @@ object of gcli_issue with "state" => state as sv, "body" => body as sv, "created_at" => created_at as sv, - "number" => number as int, + "number" => number as id, "comments" => comments as int, "user" => author as user_sv, "locked" => locked as bool, diff --git a/templates/gitlab/issues.t b/templates/gitlab/issues.t index 17a9cb2e..3c089348 100644 --- a/templates/gitlab/issues.t +++ b/templates/gitlab/issues.t @@ -12,7 +12,7 @@ object of gcli_issue with "state" => state as sv, "description" => body as sv, "created_at" => created_at as sv, - "iid" => number as int, + "iid" => number as id, "user_notes_count" => comments as int, "author" => author as user_sv, "discussion_locked" => locked as bool, @@ -21,4 +21,4 @@ object of gcli_issue with use parse_gitlab_user, "milestone" => use parse_gitlab_issue_milestone); -parser gitlab_issues is array of gcli_issue use parse_gitlab_issue; \ No newline at end of file +parser gitlab_issues is array of gcli_issue use parse_gitlab_issue; From c849749a35b3c284c47d67ed48b0fcd7e727e8a9 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Sep 2023 19:18:03 +0200 Subject: [PATCH 219/236] Make pulls use new gcli_id type --- include/gcli/pulls.h | 26 +++++++++++++------------- src/pulls.c | 22 +++++++++++----------- templates/github/pulls.t | 4 ++-- templates/gitlab/merge_requests.t | 4 ++-- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index b81fb834..59ca7d5e 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -64,8 +64,8 @@ struct gcli_pull { char *base_label; char *head_sha; char *milestone; - int id; - int number; + gcli_id id; + gcli_id number; int comments; int additions; int deletions; @@ -130,20 +130,20 @@ void gcli_pull_free(gcli_pull *it); void gcli_pulls_free(gcli_pull_list *list); int gcli_pull_get_diff(gcli_ctx *ctx, FILE *fout, char const *owner, - char const *repo, int pr_number); + char const *repo, gcli_id pr_number); int gcli_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, gcli_pull_checks_list *out); + gcli_id pr_number, gcli_pull_checks_list *out); void gcli_pull_checks_free(gcli_pull_checks_list *list); int gcli_pull_get_commits(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, gcli_commit_list *out); + gcli_id pr_number, gcli_commit_list *out); void gcli_commits_free(gcli_commit_list *list); int gcli_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, gcli_pull *out); + gcli_id pr_number, gcli_pull *out); int gcli_pull_submit(gcli_ctx *ctx, gcli_submit_pull_options); @@ -153,26 +153,26 @@ enum gcli_merge_flags { }; int gcli_pull_merge(gcli_ctx *ctx, char const *owner, char const *reponame, - int pr_number, enum gcli_merge_flags flags); + gcli_id pr_number, enum gcli_merge_flags flags); int gcli_pull_close(gcli_ctx *ctx, char const *owner, char const *reponame, - int pr_number); + gcli_id pr_number); int gcli_pull_reopen(gcli_ctx *ctx, char const *owner, char const *reponame, - int pr_number); + gcli_id pr_number); int gcli_pull_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, char const *const labels[], + gcli_id pr_number, char const *const labels[], size_t labels_size); int gcli_pull_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, char const *const labels[], + gcli_id pr_number, char const *const labels[], size_t labels_size); int gcli_pull_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, int milestone_id); + gcli_id pr_number, int milestone_id); int gcli_pull_clear_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number); + gcli_id pr_number); #endif /* PULLS_H */ diff --git a/src/pulls.c b/src/pulls.c index ef37e89c..dc2cc5c2 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -59,14 +59,14 @@ gcli_get_pulls(gcli_ctx *ctx, char const *owner, char const *repo, int gcli_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner, - char const *reponame, int const pr_number) + char const *reponame, gcli_id const pr_number) { return gcli_forge(ctx)->print_pull_diff(ctx, stream, owner, reponame, pr_number); } int gcli_pull_get_commits(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, gcli_commit_list *const out) + gcli_id const pr_number, gcli_commit_list *const out) { return gcli_forge(ctx)->get_pull_commits(ctx, owner, repo, pr_number, out); } @@ -108,14 +108,14 @@ gcli_pull_free(gcli_pull *const it) int gcli_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, gcli_pull *const out) + gcli_id const pr_number, gcli_pull *const out) { return gcli_forge(ctx)->get_pull(ctx, owner, repo, pr_number, out); } int gcli_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, gcli_pull_checks_list *out) + gcli_id const pr_number, gcli_pull_checks_list *out) { return gcli_forge(ctx)->get_pull_checks(ctx, owner, repo, pr_number, out); } @@ -143,28 +143,28 @@ gcli_pull_submit(gcli_ctx *ctx, gcli_submit_pull_options opts) int gcli_pull_merge(gcli_ctx *ctx, char const *owner, char const *reponame, - int const pr_number, enum gcli_merge_flags flags) + gcli_id const pr_number, enum gcli_merge_flags flags) { return gcli_forge(ctx)->pull_merge(ctx, owner, reponame, pr_number, flags); } int gcli_pull_close(gcli_ctx *ctx, char const *owner, char const *reponame, - int const pr_number) + gcli_id const pr_number) { return gcli_forge(ctx)->pull_close(ctx, owner, reponame, pr_number); } int gcli_pull_reopen(gcli_ctx *ctx, char const *owner, char const *reponame, - int const pr_number) + gcli_id const pr_number) { return gcli_forge(ctx)->pull_reopen(ctx, owner, reponame, pr_number); } int gcli_pull_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, char const *const labels[], + gcli_id const pr_number, char const *const labels[], size_t const labels_size) { return gcli_forge(ctx)->pull_add_labels( @@ -173,7 +173,7 @@ gcli_pull_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, int gcli_pull_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, char const *const labels[], + gcli_id const pr_number, char const *const labels[], size_t const labels_size) { return gcli_forge(ctx)->pull_remove_labels( @@ -182,7 +182,7 @@ gcli_pull_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, int gcli_pull_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, int milestone_id) + gcli_id const pr_number, int milestone_id) { return gcli_forge(ctx)->pull_set_milestone( ctx, owner, repo, pr_number, milestone_id); @@ -190,7 +190,7 @@ gcli_pull_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int gcli_pull_clear_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number) + gcli_id const pr_number) { return gcli_forge(ctx)->pull_clear_milestone(ctx, owner, repo, pr_number); } diff --git a/templates/github/pulls.t b/templates/github/pulls.t index fa4b9ec1..a5ae38ef 100644 --- a/templates/github/pulls.t +++ b/templates/github/pulls.t @@ -39,8 +39,8 @@ object of gcli_pull with "state" => state as string, "body" => body as string, "created_at" => created_at as string, - "number" => number as int, - "id" => id as int, + "number" => number as id, + "id" => id as id, "commits" => commits as int, "labels" => labels as array of github_label use parse_github_label_text, diff --git a/templates/gitlab/merge_requests.t b/templates/gitlab/merge_requests.t index 94d7a736..cf5439b4 100644 --- a/templates/gitlab/merge_requests.t +++ b/templates/gitlab/merge_requests.t @@ -15,8 +15,8 @@ object of gcli_pull with "state" => state as string, "description" => body as string, "created_at" => created_at as string, - "iid" => number as int, - "id" => id as int, + "iid" => number as id, + "id" => id as id, "labels" => labels as array of sn_sv use parse_sv, "user_notes_count" => comments as int, "merge_status" => mergeable as gitlab_can_be_merged, From e4f002b2cc487f05a7f42a899e19445e79bcd8cd Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Sep 2023 19:28:22 +0200 Subject: [PATCH 220/236] Make labels use new gcli_id type --- include/gcli/labels.h | 8 ++++---- src/gitea/issues.c | 2 +- templates/github/labels.t | 2 +- templates/gitlab/labels.t | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/gcli/labels.h b/include/gcli/labels.h index 0a5086e2..8b7a3935 100644 --- a/include/gcli/labels.h +++ b/include/gcli/labels.h @@ -44,10 +44,10 @@ typedef struct gcli_label gcli_label; typedef struct gcli_label_list gcli_label_list; struct gcli_label { - long id; - char *name; - char *description; - uint32_t colour; + gcli_id id; + char *name; + char *description; + uint32_t colour; }; struct gcli_label_list { diff --git a/src/gitea/issues.c b/src/gitea/issues.c index dd6f87a6..4e17a170 100644 --- a/src/gitea/issues.c +++ b/src/gitea/issues.c @@ -140,7 +140,7 @@ get_id_of_label(char const *label_name, { for (size_t i = 0; i < list->labels_size; ++i) if (strcmp(list->labels[i].name, label_name) == 0) - return sn_asprintf("%ld", list->labels[i].id); + return sn_asprintf("%ul", list->labels[i].id); return NULL; } diff --git a/templates/github/labels.t b/templates/github/labels.t index cb008e6b..9aaf5d51 100644 --- a/templates/github/labels.t +++ b/templates/github/labels.t @@ -4,7 +4,7 @@ parser github_label_text is object of sn_sv select "name" as sv; parser github_label is object of gcli_label with - ("id" => id as long, + ("id" => id as id, "name" => name as string, "description" => description as string, "color" => colour as github_style_colour); diff --git a/templates/gitlab/labels.t b/templates/gitlab/labels.t index 050808f8..c2a3ed84 100644 --- a/templates/gitlab/labels.t +++ b/templates/gitlab/labels.t @@ -5,6 +5,6 @@ object of gcli_label with ("name" => name as string, "description" => description as string, "color" => colour as gitlab_style_colour, - "id" => id as long); + "id" => id as id); parser gitlab_labels is array of gcli_label use parse_gitlab_label; From c2b78458c3e006099f068b925329fded8953c907 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Sep 2023 19:36:50 +0200 Subject: [PATCH 221/236] Make milestones use new gcli_id type --- include/gcli/milestones.h | 10 +++++----- src/milestones.c | 8 ++++---- templates/gitea/milestones.t | 2 +- templates/github/milestones.t | 4 ++-- templates/gitlab/milestones.t | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/gcli/milestones.h b/include/gcli/milestones.h index 298b95af..c7345ecc 100644 --- a/include/gcli/milestones.h +++ b/include/gcli/milestones.h @@ -44,7 +44,7 @@ typedef struct gcli_milestone gcli_milestone; typedef struct gcli_milestone_list gcli_milestone_list; struct gcli_milestone { - int id; + gcli_id id; char *title; char *state; char *created_at; @@ -79,23 +79,23 @@ int gcli_get_milestones(gcli_ctx *ctx, char const *owner, char const *repo, int max, gcli_milestone_list *out); int gcli_get_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int max, gcli_milestone *out); + gcli_id milestone, gcli_milestone *out); int gcli_create_milestone(gcli_ctx *ctx, struct gcli_milestone_create_args const *args); int gcli_delete_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int milestone); + gcli_id milestone); void gcli_free_milestone(gcli_milestone *it); void gcli_free_milestones(gcli_milestone_list *it); int gcli_milestone_get_issues(gcli_ctx *ctx, char const *owner, - char const *repo, int milestone, + char const *repo, gcli_id milestone, gcli_issue_list *out); int gcli_milestone_set_duedate(gcli_ctx *ctx, char const *owner, - char const *repo, int milestone, + char const *repo, gcli_id milestone, char const *date); #endif /* GCLI_MILESTONES_H */ diff --git a/src/milestones.c b/src/milestones.c index 2b09fb15..4af2bf2f 100644 --- a/src/milestones.c +++ b/src/milestones.c @@ -40,7 +40,7 @@ gcli_get_milestones(gcli_ctx *ctx, char const *const owner, int gcli_get_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int const milestone, gcli_milestone *const out) + gcli_id const milestone, gcli_milestone *const out) { return gcli_forge(ctx)->get_milestone(ctx, owner, repo, milestone, out); } @@ -54,7 +54,7 @@ gcli_create_milestone(gcli_ctx *ctx, int gcli_delete_milestone(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const milestone) + char const *const repo, gcli_id const milestone) { return gcli_forge(ctx)->delete_milestone(ctx, owner, repo, milestone); } @@ -90,7 +90,7 @@ gcli_free_milestones(gcli_milestone_list *const it) int gcli_milestone_get_issues(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const milestone, + char const *const repo, gcli_id const milestone, gcli_issue_list *const out) { return gcli_forge(ctx)->get_milestone_issues( @@ -99,7 +99,7 @@ gcli_milestone_get_issues(gcli_ctx *ctx, char const *const owner, int gcli_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const milestone, + char const *const repo, gcli_id const milestone, char const *const date) { return gcli_forge(ctx)->milestone_set_duedate( diff --git a/templates/gitea/milestones.t b/templates/gitea/milestones.t index c4842306..85b70c5e 100644 --- a/templates/gitea/milestones.t +++ b/templates/gitea/milestones.t @@ -2,7 +2,7 @@ include "gcli/milestones.h"; parser gitea_milestone is object of gcli_milestone with - ("id" => id as int, + ("id" => id as id, "title" => title as string, "created_at" => created_at as string, "description" => description as string, diff --git a/templates/github/milestones.t b/templates/github/milestones.t index 986bedba..e6cca23a 100644 --- a/templates/github/milestones.t +++ b/templates/github/milestones.t @@ -2,7 +2,7 @@ include "gcli/milestones.h"; parser github_milestone is object of gcli_milestone with - ("number" => id as int, + ("number" => id as id, "title" => title as string, "created_at" => created_at as string, "state" => state as string, @@ -12,4 +12,4 @@ object of gcli_milestone with "closed_issues" => closed_issues as int); parser github_milestones is -array of gcli_milestone use parse_github_milestone; \ No newline at end of file +array of gcli_milestone use parse_github_milestone; diff --git a/templates/gitlab/milestones.t b/templates/gitlab/milestones.t index 56152fa1..dd9f8b26 100644 --- a/templates/gitlab/milestones.t +++ b/templates/gitlab/milestones.t @@ -3,7 +3,7 @@ include "gcli/milestones.h"; parser gitlab_milestone is object of gcli_milestone with ("title" => title as string, - "id" => id as int, + "id" => id as id, "state" => state as string, "created_at" => created_at as string, "description" => description as string, From 2b1ab0aa14482e8c9b805e682741c7812180fee0 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Sep 2023 19:41:25 +0200 Subject: [PATCH 222/236] Make repos use new gcli_id type --- include/gcli/repos.h | 6 +++--- templates/github/repos.t | 4 ++-- templates/gitlab/repos.t | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/gcli/repos.h b/include/gcli/repos.h index 4d6134f2..65243712 100644 --- a/include/gcli/repos.h +++ b/include/gcli/repos.h @@ -42,13 +42,13 @@ typedef struct gcli_repo_list gcli_repo_list; typedef struct gcli_repo_create_options gcli_repo_create_options; struct gcli_repo { - int id; + gcli_id id; sn_sv full_name; sn_sv name; sn_sv owner; sn_sv date; sn_sv visibility; - bool is_fork; + bool is_fork; }; struct gcli_repo_list { @@ -59,7 +59,7 @@ struct gcli_repo_list { struct gcli_repo_create_options { sn_sv name; sn_sv description; - bool private; + bool private; }; int gcli_get_repos(gcli_ctx *ctx, char const *owner, int max, diff --git a/templates/github/repos.t b/templates/github/repos.t index 03495c6d..cd08aba4 100644 --- a/templates/github/repos.t +++ b/templates/github/repos.t @@ -3,7 +3,7 @@ include "gcli/gitea/repos.h"; parser github_repo is object of gcli_repo with - ("id" => id as int, + ("id" => id as id, "full_name" => full_name as sv, "name" => name as sv, "owner" => owner as user_sv, @@ -13,4 +13,4 @@ object of gcli_repo with "fork" => is_fork as bool); parser github_repos is array of gcli_repo - use parse_github_repo; \ No newline at end of file + use parse_github_repo; diff --git a/templates/gitlab/repos.t b/templates/gitlab/repos.t index 36e9b996..5c2c9913 100644 --- a/templates/gitlab/repos.t +++ b/templates/gitlab/repos.t @@ -8,7 +8,7 @@ object of gcli_repo with "created_at" => date as sv, "visibility" => visibility as sv, "fork" => is_fork as bool, - "id" => id as int); + "id" => id as id); parser gitlab_repos is array of gcli_repo use parse_gitlab_repo; From b12baaf517c931be47d0dfa506bc7bb1b2c25bac Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Sep 2023 19:59:01 +0200 Subject: [PATCH 223/236] Make sshkeys use the new gcli_id type --- include/gcli/forges.h | 2 +- include/gcli/gitea/sshkeys.h | 2 +- include/gcli/github/sshkeys.h | 2 +- include/gcli/gitlab/sshkeys.h | 2 +- include/gcli/sshkeys.h | 4 ++-- src/gitea/sshkeys.c | 2 +- src/github/sshkeys.c | 2 +- src/gitlab/sshkeys.c | 4 ++-- src/sshkeys.c | 2 +- templates/gitlab/sshkeys.t | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 4edfca95..3c08a033 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -480,7 +480,7 @@ struct gcli_forge_descriptor { /** * Delete an SSH public key by its ID */ - int (*delete_sshkey)(gcli_ctx *ctx, int id); + int (*delete_sshkey)(gcli_ctx *ctx, gcli_id id); /** * Get the error string from the API */ diff --git a/include/gcli/gitea/sshkeys.h b/include/gcli/gitea/sshkeys.h index 04e20f5c..46c8bc0f 100644 --- a/include/gcli/gitea/sshkeys.h +++ b/include/gcli/gitea/sshkeys.h @@ -37,6 +37,6 @@ int gitea_get_sshkeys(gcli_ctx *ctx, gcli_sshkey_list *out); int gitea_add_sshkey(gcli_ctx *ctx, char const *title, char const *public_key_data, gcli_sshkey *out); -int gitea_delete_sshkey(gcli_ctx *ctx, int id); +int gitea_delete_sshkey(gcli_ctx *ctx, gcli_id id); #endif /* GCLI_GITEA_SSHKEYS_H */ diff --git a/include/gcli/github/sshkeys.h b/include/gcli/github/sshkeys.h index 584ea43b..e1730a60 100644 --- a/include/gcli/github/sshkeys.h +++ b/include/gcli/github/sshkeys.h @@ -37,6 +37,6 @@ int github_get_sshkeys(gcli_ctx *ctx, gcli_sshkey_list *out); int github_add_sshkey(gcli_ctx *ctx, char const *const title, char const *const pubkey, gcli_sshkey *out); -int github_delete_sshkey(gcli_ctx *ctx, int id); +int github_delete_sshkey(gcli_ctx *ctx, gcli_id id); #endif /* GCLI_GITHUB_SSHKEYS_H */ diff --git a/include/gcli/gitlab/sshkeys.h b/include/gcli/gitlab/sshkeys.h index 5a5b7b6e..482fa645 100644 --- a/include/gcli/gitlab/sshkeys.h +++ b/include/gcli/gitlab/sshkeys.h @@ -41,6 +41,6 @@ int gitlab_get_sshkeys(gcli_ctx *ctx, gcli_sshkey_list *list); int gitlab_add_sshkey(gcli_ctx *ctx, char const *const title, char const *const pubkey, gcli_sshkey *const out); -int gitlab_delete_sshkey(gcli_ctx *ctx, int id); +int gitlab_delete_sshkey(gcli_ctx *ctx, gcli_id id); #endif /* GCLI_GITLAB_SSHKEYS_H */ diff --git a/include/gcli/sshkeys.h b/include/gcli/sshkeys.h index 9ebf2cce..fb91d788 100644 --- a/include/gcli/sshkeys.h +++ b/include/gcli/sshkeys.h @@ -39,7 +39,7 @@ #include struct gcli_sshkey { - int id; + gcli_id id; char *title; char *key; char *created_at; @@ -56,7 +56,7 @@ typedef struct gcli_sshkey_list gcli_sshkey_list; int gcli_sshkeys_get_keys(gcli_ctx *ctx, gcli_sshkey_list *out); int gcli_sshkeys_add_key(gcli_ctx *ctx, char const *title, char const *public_key_path, gcli_sshkey *out); -int gcli_sshkeys_delete_key(gcli_ctx *ctx, int id); +int gcli_sshkeys_delete_key(gcli_ctx *ctx, gcli_id id); void gcli_sshkeys_free_keys(gcli_sshkey_list *list); #endif /* GCLI_SSHKEYS_H */ diff --git a/src/gitea/sshkeys.c b/src/gitea/sshkeys.c index 3aa305e3..53715b46 100644 --- a/src/gitea/sshkeys.c +++ b/src/gitea/sshkeys.c @@ -50,7 +50,7 @@ gitea_add_sshkey(gcli_ctx *ctx, char const *const title, } int -gitea_delete_sshkey(gcli_ctx *ctx, int id) +gitea_delete_sshkey(gcli_ctx *ctx, gcli_id const id) { return gitlab_delete_sshkey(ctx, id); } diff --git a/src/github/sshkeys.c b/src/github/sshkeys.c index 99d40622..33bbc481 100644 --- a/src/github/sshkeys.c +++ b/src/github/sshkeys.c @@ -47,7 +47,7 @@ github_add_sshkey(gcli_ctx *ctx, char const *const title, } int -github_delete_sshkey(gcli_ctx *ctx, int id) +github_delete_sshkey(gcli_ctx *ctx, gcli_id const id) { return gitlab_delete_sshkey(ctx, id); } diff --git a/src/gitlab/sshkeys.c b/src/gitlab/sshkeys.c index 4cef2bf0..33387567 100644 --- a/src/gitlab/sshkeys.c +++ b/src/gitlab/sshkeys.c @@ -92,12 +92,12 @@ gitlab_add_sshkey(gcli_ctx *ctx, char const *const title, } int -gitlab_delete_sshkey(gcli_ctx *ctx, int id) +gitlab_delete_sshkey(gcli_ctx *ctx, gcli_id id) { char *url; int rc = 0; - url = sn_asprintf("%s/user/keys/%d", gcli_get_apibase(ctx), id); + url = sn_asprintf("%s/user/keys/%ul", gcli_get_apibase(ctx), id); rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); diff --git a/src/sshkeys.c b/src/sshkeys.c index 653d9021..5ff34707 100644 --- a/src/sshkeys.c +++ b/src/sshkeys.c @@ -74,7 +74,7 @@ gcli_sshkeys_add_key(gcli_ctx *ctx, char const *title, } int -gcli_sshkeys_delete_key(gcli_ctx *ctx, int id) +gcli_sshkeys_delete_key(gcli_ctx *ctx, gcli_id const id) { return gcli_forge(ctx)->delete_sshkey(ctx, id); } diff --git a/templates/gitlab/sshkeys.t b/templates/gitlab/sshkeys.t index 73bf9d76..d9c5d8a0 100644 --- a/templates/gitlab/sshkeys.t +++ b/templates/gitlab/sshkeys.t @@ -3,7 +3,7 @@ include "gcli/sshkeys.h"; parser gitlab_sshkey is object of gcli_sshkey with ("title" => title as string, - "id" => id as int, + "id" => id as id, "key" => key as string, "created_at" => created_at as string); From bf8e4a1abb28ea8810fdfb26440578c5f0d148d5 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Sep 2023 21:52:26 +0200 Subject: [PATCH 224/236] Change forge descriptor to use new gcli_id type instead of plain int The reasoning behind this is that if we decide to change the ID types or if we realise that it is wrong how we handle it at the moment we just have one typedef that affects all uses. Especially for GitLab this seems to be important as the IDs returned by it should be ulongs (learned from experience). Signed-off-by: Nico Sonack --- include/gcli/forges.h | 56 ++++++++++++++-------------- include/gcli/gcli.h | 2 +- include/gcli/gitea/comments.h | 2 +- include/gcli/gitea/issues.h | 16 ++++---- include/gcli/gitea/milestones.h | 8 ++-- include/gcli/gitea/pulls.h | 18 ++++----- include/gcli/github/comments.h | 2 +- include/gcli/github/issues.h | 16 ++++---- include/gcli/github/milestones.h | 8 ++-- include/gcli/github/pulls.h | 14 +++---- include/gcli/github/review.h | 2 +- include/gcli/gitlab/comments.h | 4 +- include/gcli/gitlab/issues.h | 16 ++++---- include/gcli/gitlab/merge_requests.h | 20 +++++----- include/gcli/gitlab/milestones.h | 8 ++-- include/gcli/gitlab/review.h | 2 +- src/gitea/comments.c | 2 +- src/gitea/issues.c | 26 ++++++------- src/gitea/milestones.c | 12 +++--- src/gitea/pulls.c | 22 +++++------ src/github/comments.c | 4 +- src/github/issues.c | 36 +++++++++--------- src/github/milestones.c | 16 ++++---- src/github/pulls.c | 30 +++++++-------- src/github/review.c | 2 +- src/gitlab/comments.c | 8 ++-- src/gitlab/issues.c | 34 ++++++++--------- src/gitlab/merge_requests.c | 44 +++++++++++----------- src/gitlab/milestones.c | 16 ++++---- src/gitlab/review.c | 4 +- src/gitlab/sshkeys.c | 2 +- 31 files changed, 225 insertions(+), 227 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 3c08a033..33915725 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -51,7 +51,7 @@ typedef struct gcli_forge_descriptor gcli_forge_descriptor; /* Hopefully temporary hack */ typedef int (*gcli_get_pull_checks_cb)( - gcli_ctx *, char const *, char const *, int, + gcli_ctx *, char const *, char const *, gcli_id, gcli_pull_checks_list *); /** @@ -71,7 +71,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int issue, + gcli_id issue, gcli_comment_list *out); /** @@ -80,7 +80,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int pr, + gcli_id pr, gcli_comment_list *out); /** @@ -116,7 +116,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number, + gcli_id issue_number, gcli_issue *out); /** @@ -125,7 +125,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number); + gcli_id issue_number); /** * Reopen the given issue */ @@ -133,7 +133,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number); + gcli_id issue_number); /** * Assign an issue to a user */ @@ -141,7 +141,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number, + gcli_id issue_number, char const *assignee); /** @@ -150,7 +150,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int issue, + gcli_id issue, char const *const labels[], size_t labels_size); @@ -160,7 +160,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int issue, + gcli_id issue, char const *const labels[], size_t labels_size); @@ -195,7 +195,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int milestone, + gcli_id milestone, gcli_milestone *out); /** @@ -210,7 +210,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int milestone); + gcli_id milestone); /** * delete a milestone */ @@ -218,7 +218,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int milestone, + gcli_id milestone, char const *date); /** @@ -227,7 +227,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int milestone, + gcli_id milestone, gcli_issue_list *out); /** Assign an issue to a milestone */ @@ -235,8 +235,8 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int issue, - int milestone); + gcli_id issue, + gcli_id milestone); /** * Clear the milestones of an issue */ @@ -244,7 +244,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int issue); + gcli_id issue); /** * Get a list of PRs/MRs on the given repo */ @@ -263,7 +263,7 @@ struct gcli_forge_descriptor { FILE *stream, char const *owner, char const *reponame, - int pr_number); + gcli_id pr_number); /** * Return a list of checks associated with the given pull. @@ -278,7 +278,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *reponame, - int pr_number, + gcli_id pr_number, enum gcli_merge_flags flags); /** @@ -287,7 +287,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *reponame, - int pr_number); + gcli_id pr_number); /** * Close the given PR/MR */ @@ -295,7 +295,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *reponame, - int pr_number); + gcli_id pr_number); /** * Submit PR/MR */ @@ -309,7 +309,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, + gcli_id pr_number, gcli_commit_list *out); /** Bitmask of unsupported fields in the pull summary for this @@ -329,7 +329,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, + gcli_id pr_number, gcli_pull *out); /** @@ -338,7 +338,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int pr, + gcli_id pr, char const *const labels[], size_t labels_size); @@ -348,7 +348,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int pr, + gcli_id pr, char const *const labels[], size_t labels_size); @@ -358,8 +358,8 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int pull, - int milestone_id); + gcli_id pull, + gcli_id milestone_id); /** * Clear a milestone on a PR */ @@ -367,7 +367,7 @@ struct gcli_forge_descriptor { gcli_ctx *ctx, char const *owner, char const *repo, - int pull); + gcli_id pull); /** * Get a list of releases in the given repo */ @@ -445,7 +445,7 @@ struct gcli_forge_descriptor { * Fetch MR/PR reviews including comments */ int (*get_reviews)( gcli_ctx *ctx, char const *owner, char const *repo, - int pr, gcli_pr_review_list *out); + gcli_id pr, gcli_pr_review_list *out); /** * Status summary for the account */ diff --git a/include/gcli/gcli.h b/include/gcli/gcli.h index 88cd88ed..833f0764 100644 --- a/include/gcli/gcli.h +++ b/include/gcli/gcli.h @@ -45,7 +45,7 @@ typedef enum gcli_forge_type { GCLI_FORGE_GITEA, } gcli_forge_type; -typedef unsigned int gcli_id; +typedef unsigned long gcli_id; #ifdef IN_LIBGCLI #include diff --git a/include/gcli/gitea/comments.h b/include/gcli/gitea/comments.h index a9491edc..cf72f7c8 100644 --- a/include/gcli/gitea/comments.h +++ b/include/gcli/gitea/comments.h @@ -38,7 +38,7 @@ #include int gitea_get_comments(gcli_ctx *ctx, char const *owner, char const *repo, - int issue, gcli_comment_list *out); + gcli_id issue, gcli_comment_list *out); int gitea_perform_submit_comment(gcli_ctx *ctx, gcli_submit_comment_opts opts, gcli_fetch_buffer *out); diff --git a/include/gcli/gitea/issues.h b/include/gcli/gitea/issues.h index 4774d950..ba2502f7 100644 --- a/include/gcli/gitea/issues.h +++ b/include/gcli/gitea/issues.h @@ -41,32 +41,32 @@ int gitea_get_issues(gcli_ctx *ctx, char const *owner, char const *reponame, gcli_issue_list *out); int gitea_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, - int issue, gcli_issue *out); + gcli_id issue_number, gcli_issue *out); int gitea_submit_issue(gcli_ctx *ctx, gcli_submit_issue_options opts, gcli_fetch_buffer *out); int gitea_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number); + gcli_id issue_number); int gitea_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number); + gcli_id issue_number); int gitea_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number, char const *assignee); + gcli_id issue_number, char const *assignee); int gitea_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int issue, char const *const labels[], + gcli_id issue_number, char const *const labels[], size_t labels_size); int gitea_issue_remove_labels(gcli_ctx *ctx, char const *owner, - char const *repo, int issue, + char const *repo, gcli_id issue, char const *const labels[], size_t labels_size); int gitea_issue_set_milestone(gcli_ctx *ctx, char const *owner, - char const *repo, int issue, int milestone); + char const *repo, gcli_id issue, gcli_id milestone); int gitea_issue_clear_milestone(gcli_ctx *ctx, char const *owner, - char const *repo, int issue); + char const *repo, gcli_id issue); #endif /* GITEA_ISSUES_H */ diff --git a/include/gcli/gitea/milestones.h b/include/gcli/gitea/milestones.h index 45bfec28..6a26456a 100644 --- a/include/gcli/gitea/milestones.h +++ b/include/gcli/gitea/milestones.h @@ -37,21 +37,21 @@ int gitea_get_milestones(gcli_ctx *ctx, char const *const owner, gcli_milestone_list *out); int gitea_get_milestone(gcli_ctx *ctx, char const *const owner, - char const *const repo, int milestone, + char const *const repo, gcli_id milestone, gcli_milestone *out); int gitea_create_milestone(gcli_ctx *ctx, struct gcli_milestone_create_args const *args); int gitea_delete_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int milestone); + gcli_id milestone); int gitea_milestone_set_duedate(gcli_ctx *ctx, char const *owner, - char const *repo, int milestone, + char const *repo, gcli_id milestone, char const *date); int gitea_milestone_get_issues(gcli_ctx *ctx, char const *owner, - char const *repo, int milestone, + char const *repo, gcli_id milestone, gcli_issue_list *out); #endif /* GCLI_GITEA_MILESTONES_H */ diff --git a/include/gcli/gitea/pulls.h b/include/gcli/gitea/pulls.h index b23e07b7..0ecc4ed5 100644 --- a/include/gcli/gitea/pulls.h +++ b/include/gcli/gitea/pulls.h @@ -42,32 +42,32 @@ int gitea_get_pulls(gcli_ctx *ctx, char const *owner, char const *reponame, gcli_pull_list *out); int gitea_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, gcli_pull *out); + gcli_id pr_number, gcli_pull *out); int gitea_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, gcli_commit_list *out); + gcli_id pr_number, gcli_commit_list *out); int gitea_pull_submit(gcli_ctx *ctx, gcli_submit_pull_options opts); int gitea_pull_merge(gcli_ctx *ctx, char const *owner, char const *reponame, - int pr_number, enum gcli_merge_flags flags); + gcli_id pr_number, enum gcli_merge_flags flags); int gitea_pull_close(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number); + gcli_id pr_number); int gitea_pull_reopen(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number); + gcli_id pr_number); int gitea_print_pr_diff(gcli_ctx *ctx, FILE *stream, char const *owner, - char const *repo, int pr_number); + char const *repo, gcli_id pr_number); int gitea_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, gcli_pull_checks_list *out); + gcli_id pr_number, gcli_pull_checks_list *out); int gitea_pull_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, int milestone_id); + gcli_id pr_number, gcli_id milestone_id); int gitea_pull_clear_milestone(gcli_ctx *ctx, char const *owner, - char const *repo, int pr_number); + char const *repo, gcli_id pr_number); #endif /* GITEA_PULLS_H */ diff --git a/include/gcli/github/comments.h b/include/gcli/github/comments.h index bbaf2ddb..6bd6e05b 100644 --- a/include/gcli/github/comments.h +++ b/include/gcli/github/comments.h @@ -41,6 +41,6 @@ int github_perform_submit_comment(gcli_ctx *ctx, gcli_submit_comment_opts opts, gcli_fetch_buffer *out); int github_get_comments(gcli_ctx *ctx, char const *owner, char const *repo, - int issue, gcli_comment_list *out); + gcli_id issue, gcli_comment_list *out); #endif /* GITHUB_COMMENTS_H */ diff --git a/include/gcli/github/issues.h b/include/gcli/github/issues.h index 19782f75..46246bd8 100644 --- a/include/gcli/github/issues.h +++ b/include/gcli/github/issues.h @@ -45,32 +45,32 @@ int github_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, gcli_issue_list *out); int github_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number, gcli_issue *out); + gcli_id issue_number, gcli_issue *out); int github_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number); + gcli_id issue_number); int github_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number); + gcli_id issue_number); int github_perform_submit_issue(gcli_ctx *ctx, gcli_submit_issue_options opts, gcli_fetch_buffer *out); int github_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number, char const *assignee); + gcli_id issue_number, char const *assignee); int github_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int issue, char const *const labels[], + gcli_id issue, char const *const labels[], size_t labels_size); int github_issue_remove_labels(gcli_ctx *ctx, char const *owner, - char const *repo, int issue, + char const *repo, gcli_id issue, char const *const labels[], size_t labels_size); int github_issue_set_milestone(gcli_ctx *ctx, char const *owner, - char const *repo, int issue, int milestone); + char const *repo, gcli_id issue, gcli_id milestone); int github_issue_clear_milestone(gcli_ctx *ctx, char const *owner, - char const *repo, int issue); + char const *repo, gcli_id issue); #endif /* GCLI_ISSUES_H */ diff --git a/include/gcli/github/milestones.h b/include/gcli/github/milestones.h index c17fb40b..ad3310b0 100644 --- a/include/gcli/github/milestones.h +++ b/include/gcli/github/milestones.h @@ -36,20 +36,20 @@ int github_get_milestones(gcli_ctx *ctx, char const *owner, char const *repo, int max, gcli_milestone_list *out); int github_get_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int milestone, gcli_milestone *out); + gcli_id milestone, gcli_milestone *out); int github_create_milestone(gcli_ctx *ctx, struct gcli_milestone_create_args const *args); int github_delete_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int milestone); + gcli_id milestone); int github_milestone_get_issues(gcli_ctx *ctx, char const *owner, - char const *repo, int milestone, + char const *repo, gcli_id milestone, gcli_issue_list *out); int github_milestone_set_duedate(gcli_ctx *ctx, char const *owner, - char const *repo, int milestone, + char const *repo, gcli_id milestone, char const *date); #endif /* GCLI_GITHUB_MILESTONES_H */ diff --git a/include/gcli/github/pulls.h b/include/gcli/github/pulls.h index 144c15a6..b65282a2 100644 --- a/include/gcli/github/pulls.h +++ b/include/gcli/github/pulls.h @@ -45,27 +45,27 @@ int github_get_pulls(gcli_ctx *ctx, char const *owner, char const *reponame, gcli_pull_list *out); int github_print_pull_diff(gcli_ctx *ctx, FILE *stream, char const *owner, - char const *reponame, int pr_number); + char const *reponame, gcli_id pr_number); int github_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, gcli_pull_checks_list *out); + gcli_id pr_number, gcli_pull_checks_list *out); int github_pull_merge(gcli_ctx *ctx, char const *owner, char const *reponame, - int pr_number, enum gcli_merge_flags flags); + gcli_id pr_number, enum gcli_merge_flags flags); int github_pull_reopen(gcli_ctx *ctx, char const *owner, char const *reponame, - int pr_number); + gcli_id pr_number); int github_pull_close(gcli_ctx *ctx, char const *owner, char const *reponame, - int pr_number); + gcli_id pr_number); int github_perform_submit_pull(gcli_ctx *ctx, gcli_submit_pull_options opts); int github_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, gcli_commit_list *out); + gcli_id pr_number, gcli_commit_list *out); int github_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, gcli_pull *out); + gcli_id pr_number, gcli_pull *out); sn_sv github_pull_try_derive_head(void); diff --git a/include/gcli/github/review.h b/include/gcli/github/review.h index e2ce0b5a..4a1b6008 100644 --- a/include/gcli/github/review.h +++ b/include/gcli/github/review.h @@ -37,7 +37,7 @@ #include int github_review_get_reviews(gcli_ctx *ctx, char const *owner, - char const *repo, int pr, + char const *repo, gcli_id pr, gcli_pr_review_list *out); #endif /* GITHUB_REVIEW_H */ diff --git a/include/gcli/gitlab/comments.h b/include/gcli/gitlab/comments.h index fcee4621..53318116 100644 --- a/include/gcli/gitlab/comments.h +++ b/include/gcli/gitlab/comments.h @@ -41,10 +41,10 @@ int gitlab_perform_submit_comment(gcli_ctx *ctx, gcli_submit_comment_opts opts, gcli_fetch_buffer *out); int gitlab_get_issue_comments(gcli_ctx *ctx, char const *owner, - char const *repo, int issue, + char const *repo, gcli_id issue, gcli_comment_list *out); int gitlab_get_mr_comments(gcli_ctx *ctx, char const *owner, char const *repo, - int issue, gcli_comment_list *out); + gcli_id issue, gcli_comment_list *out); #endif /* GITLAB_COMMENTS_H */ diff --git a/include/gcli/gitlab/issues.h b/include/gcli/gitlab/issues.h index 1c61e8d8..e0c8d5bd 100644 --- a/include/gcli/gitlab/issues.h +++ b/include/gcli/gitlab/issues.h @@ -45,32 +45,32 @@ int gitlab_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, gcli_issue_list *out); int gitlab_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number, gcli_issue *out); + gcli_id issue_number, gcli_issue *out); int gitlab_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number); + gcli_id issue_number); int gitlab_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number); + gcli_id issue_number); int gitlab_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, - int issue_number, char const *assignee); + gcli_id issue_number, char const *assignee); int gitlab_perform_submit_issue(gcli_ctx *ctx, gcli_submit_issue_options opts, gcli_fetch_buffer *out); int gitlab_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int issue, char const *const labels[], + gcli_id issue, char const *const labels[], size_t labels_size); int gitlab_issue_remove_labels(gcli_ctx *ctx, char const *owner, - char const *repo, int issue, + char const *repo, gcli_id issue, char const *const labels[], size_t labels_size); int gitlab_issue_set_milestone(gcli_ctx *ctx, char const *owner, - char const *repo, int issue, int milestone); + char const *repo, gcli_id issue, gcli_id milestone); int gitlab_issue_clear_milestone(gcli_ctx *ctx, char const *owner, - char const *repo, int issue); + char const *repo, gcli_id issue); #endif /* GITLAB_ISSUES_H */ diff --git a/include/gcli/gitlab/merge_requests.h b/include/gcli/gitlab/merge_requests.h index bc2a48e4..dc7f49f8 100644 --- a/include/gcli/gitlab/merge_requests.h +++ b/include/gcli/gitlab/merge_requests.h @@ -46,37 +46,37 @@ int gitlab_get_mrs(gcli_ctx *ctx, char const *owner, gcli_pull_list *out); int gitlab_print_pr_diff(gcli_ctx *ctx, FILE *stream, char const *owner, - char const *reponame, int pr_number); + char const *reponame, gcli_id mr_number); int gitlab_mr_merge(gcli_ctx *ctx, char const *owner, char const *reponame, - int mr_number, enum gcli_merge_flags flags); + gcli_id mr_number, enum gcli_merge_flags flags); int gitlab_mr_close(gcli_ctx *ctx, char const *owner, char const *reponame, - int pr_number); + gcli_id mr_number); int gitlab_mr_reopen(gcli_ctx *ctx, char const *owner, char const *reponame, - int pr_number); + gcli_id mr_number); int gitlab_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, gcli_pull *out); + gcli_id mr_number, gcli_pull *out); int gitlab_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, gcli_commit_list *out); + gcli_id mr_number, gcli_commit_list *out); int gitlab_perform_submit_mr(gcli_ctx *ctx, gcli_submit_pull_options opts); int gitlab_mr_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int mr, char const *const labels[], + gcli_id mr_number, char const *const labels[], size_t labels_size); int gitlab_mr_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int mr, char const *const labels[], + gcli_id mr_number, char const *const labels[], size_t labels_size); int gitlab_mr_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int mr, int milestone_id); + gcli_id mr_number, gcli_id milestone_id); int gitlab_mr_clear_milestone(gcli_ctx *ctx, char const *owner, - char const *repo, int mr); + char const *repo, gcli_id mr_number); #endif /* GITLAB_MERGE_REQUESTS_H */ diff --git a/include/gcli/gitlab/milestones.h b/include/gcli/gitlab/milestones.h index 597bea54..81d6dc93 100644 --- a/include/gcli/gitlab/milestones.h +++ b/include/gcli/gitlab/milestones.h @@ -43,17 +43,17 @@ int gitlab_create_milestone(gcli_ctx *ctx, struct gcli_milestone_create_args const *args); int gitlab_delete_milestone(gcli_ctx *ctx, char const *owner, - char const *repo, int milestone); + char const *repo, gcli_id milestone); int gitlab_get_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int milestone, gcli_milestone *out); + gcli_id milestone, gcli_milestone *out); int gitlab_milestone_get_issues(gcli_ctx *ctx, char const *owner, - char const *repo, int milestone, + char const *repo, gcli_id milestone, gcli_issue_list *out); int gitlab_milestone_set_duedate(gcli_ctx *ctx, char const *owner, - char const *repo, int milestone, + char const *repo, gcli_id milestone, char const *date); #endif /* GCLI_GITLAB_MILESTONES_H */ diff --git a/include/gcli/gitlab/review.h b/include/gcli/gitlab/review.h index 3d2a7bed..f4ae097d 100644 --- a/include/gcli/gitlab/review.h +++ b/include/gcli/gitlab/review.h @@ -37,7 +37,7 @@ #include int gitlab_review_get_reviews(gcli_ctx *cxt, char const *owner, - char const *repo, int pr, + char const *repo, gcli_id mr_number, gcli_pr_review_list *out); #endif /* GITLAB_REVIEW_H */ diff --git a/src/gitea/comments.c b/src/gitea/comments.c index c58b7efd..7be342e3 100644 --- a/src/gitea/comments.c +++ b/src/gitea/comments.c @@ -32,7 +32,7 @@ int gitea_get_comments(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue, gcli_comment_list *const out) + gcli_id const issue, gcli_comment_list *const out) { return github_get_comments(ctx, owner, repo, issue, out); } diff --git a/src/gitea/issues.c b/src/gitea/issues.c index 4e17a170..dbb89013 100644 --- a/src/gitea/issues.c +++ b/src/gitea/issues.c @@ -47,7 +47,7 @@ gitea_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, int gitea_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number, gcli_issue *const out) + gcli_id const issue_number, gcli_issue *const out) { return github_get_issue_summary(ctx, owner, repo, issue_number, out); } @@ -89,21 +89,21 @@ gitea_issue_patch_state(gcli_ctx *ctx, char const *owner, char const *repo, int gitea_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number) + gcli_id const issue_number) { return gitea_issue_patch_state(ctx, owner, repo, issue_number, "closed"); } int gitea_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number) + gcli_id const issue_number) { return gitea_issue_patch_state(ctx, owner, repo, issue_number, "open"); } int gitea_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number, char const *const assignee) + gcli_id const issue_number, char const *const assignee) { sn_sv escaped_assignee = SV_NULL; char *post_fields = NULL; @@ -119,7 +119,7 @@ gitea_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/repos/%s/%s/issues/%d", gcli_get_apibase(ctx), + url = sn_asprintf("%s/repos/%s/%s/issues/%lu", gcli_get_apibase(ctx), e_owner, e_repo, issue_number); rc = gcli_fetch_with_method(ctx, "PATCH", url, post_fields, NULL, NULL); @@ -140,7 +140,7 @@ get_id_of_label(char const *label_name, { for (size_t i = 0; i < list->labels_size; ++i) if (strcmp(list->labels[i].name, label_name) == 0) - return sn_asprintf("%ul", list->labels[i].id); + return sn_asprintf("%lu", list->labels[i].id); return NULL; } @@ -185,7 +185,7 @@ label_names_to_ids(gcli_ctx *ctx, char const *owner, char const *repo, int gitea_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue, char const *const labels[], + gcli_id const issue, char const *const labels[], size_t const labels_size) { char *list = NULL; @@ -204,7 +204,7 @@ gitea_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, list = sn_join_with((char const **)ids, labels_size, ","); data = sn_asprintf("{ \"labels\": [%s] }", list); - url = sn_asprintf("%s/repos/%s/%s/issues/%d/labels", gcli_get_apibase(ctx), + url = sn_asprintf("%s/repos/%s/%s/issues/%lu/labels", gcli_get_apibase(ctx), owner, repo, issue); rc = gcli_fetch_with_method(ctx, "POST", url, data, NULL, NULL); @@ -219,7 +219,7 @@ gitea_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, int gitea_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue, char const *const labels[], + gcli_id const issue, char const *const labels[], size_t const labels_size) { int rc = 0; @@ -233,7 +233,7 @@ gitea_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, for (size_t i = 0; i < labels_size; ++i) { char *url = NULL; - url = sn_asprintf("%s/repos/%s/%s/issues/%d/labels/%s", + url = sn_asprintf("%s/repos/%s/%s/issues/%lu/labels/%s", gcli_get_apibase(ctx), owner, repo, issue, ids[i]); rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); @@ -250,15 +250,15 @@ gitea_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, int gitea_issue_set_milestone(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const issue, - int const milestone) + char const *const repo, gcli_id const issue, + gcli_id const milestone) { return github_issue_set_milestone(ctx, owner, repo, issue, milestone); } int gitea_issue_clear_milestone(gcli_ctx *ctx, char const *owner, - char const *repo, int issue) + char const *repo, gcli_id issue) { return github_issue_set_milestone(ctx, owner, repo, issue, 0); } diff --git a/src/gitea/milestones.c b/src/gitea/milestones.c index cab50eec..29a14ceb 100644 --- a/src/gitea/milestones.c +++ b/src/gitea/milestones.c @@ -67,7 +67,7 @@ gitea_get_milestones(gcli_ctx *ctx, char const *const owner, int gitea_get_milestone(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const milestone, + char const *const repo, gcli_id const milestone, gcli_milestone *const out) { char *url, *e_owner, *e_repo; @@ -77,7 +77,7 @@ gitea_get_milestone(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/repos/%s/%s/milestones/%d", gcli_get_apibase(ctx), + url = sn_asprintf("%s/repos/%s/%s/milestones/%lu", gcli_get_apibase(ctx), e_owner, e_repo, milestone); free(e_owner); @@ -108,7 +108,7 @@ gitea_create_milestone(gcli_ctx *ctx, int gitea_milestone_get_issues(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const milestone, + char const *const repo, gcli_id const milestone, gcli_issue_list *const out) { char *url, *e_owner, *e_repo; @@ -116,7 +116,7 @@ gitea_milestone_get_issues(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/repos/%s/%s/issues?state=all&milestones=%d", + url = sn_asprintf("%s/repos/%s/%s/issues?state=all&milestones=%lu", gcli_get_apibase(ctx), e_owner, e_repo, milestone); free(e_repo); @@ -127,14 +127,14 @@ gitea_milestone_get_issues(gcli_ctx *ctx, char const *const owner, int gitea_delete_milestone(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const milestone) + char const *const repo, gcli_id const milestone) { return github_delete_milestone(ctx, owner, repo, milestone); } int gitea_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const milestone, + char const *const repo, gcli_id const milestone, char const *const date) { return github_milestone_set_duedate(ctx, owner, repo, milestone, date); diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index 17351865..bdf44748 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -41,14 +41,14 @@ gitea_get_pulls(gcli_ctx *ctx, char const *owner, char const *repo, int gitea_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, gcli_pull *const out) + gcli_id const pr_number, gcli_pull *const out) { return github_get_pull(ctx, owner, repo, pr_number, out); } int gitea_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, gcli_commit_list *const out) + gcli_id const pr_number, gcli_commit_list *const out) { return github_get_pull_commits(ctx, owner, repo, pr_number, out); } @@ -63,7 +63,7 @@ gitea_pull_submit(gcli_ctx *ctx, gcli_submit_pull_options opts) int gitea_pull_merge(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, enum gcli_merge_flags const flags) + gcli_id const pr_number, enum gcli_merge_flags const flags) { int rc = 0; char *url = NULL; @@ -75,7 +75,7 @@ gitea_pull_merge(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/repos/%s/%s/pulls/%d/merge", + url = sn_asprintf("%s/repos/%s/%s/pulls/%lu/merge", gcli_get_apibase(ctx), e_owner, e_repo, pr_number); data = sn_asprintf("{ \"Do\": \"%s\", \"delete_branch_after_merge\": %s }", squash ? "squash" : "merge", @@ -123,21 +123,21 @@ gitea_pulls_patch_state(gcli_ctx *ctx, char const *owner, char const *repo, int gitea_pull_close(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number) + gcli_id const pr_number) { return gitea_pulls_patch_state(ctx, owner, repo, pr_number, "closed"); } int gitea_pull_reopen(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number) + gcli_id const pr_number) { return gitea_pulls_patch_state(ctx, owner, repo, pr_number, "open"); } int gitea_print_pr_diff(gcli_ctx *ctx, FILE *const stream, char const *owner, - char const *repo, int const pr_number) + char const *repo, gcli_id const pr_number) { char *url = NULL; char *e_owner = NULL; @@ -148,7 +148,7 @@ gitea_print_pr_diff(gcli_ctx *ctx, FILE *const stream, char const *owner, e_repo = gcli_urlencode(repo); url = sn_asprintf( - "%s/repos/%s/%s/pulls/%d.patch", + "%s/repos/%s/%s/pulls/%lu.patch", gcli_get_apibase(ctx), e_owner, e_repo, pr_number); @@ -163,7 +163,7 @@ gitea_print_pr_diff(gcli_ctx *ctx, FILE *const stream, char const *owner, int gitea_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, gcli_pull_checks_list *out) + gcli_id const pr_number, gcli_pull_checks_list *out) { (void) ctx; (void) owner; @@ -176,7 +176,7 @@ gitea_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, int gitea_pull_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number, int milestone_id) + gcli_id pr_number, gcli_id milestone_id) { return github_issue_set_milestone(ctx, owner, repo, pr_number, milestone_id); @@ -184,7 +184,7 @@ gitea_pull_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int gitea_pull_clear_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int pr_number) + gcli_id pr_number) { /* NOTE: The github routine for clearing issues sets the milestone * to null (not the integer zero). However this does not work in diff --git a/src/github/comments.c b/src/github/comments.c index 90f7a09e..6606cc47 100644 --- a/src/github/comments.c +++ b/src/github/comments.c @@ -63,7 +63,7 @@ github_perform_submit_comment(gcli_ctx *ctx, gcli_submit_comment_opts opts, int github_get_comments(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue, gcli_comment_list *const out) + gcli_id const issue, gcli_comment_list *const out) { char *e_owner = NULL; char *e_repo = NULL; @@ -78,7 +78,7 @@ github_get_comments(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/repos/%s/%s/issues/%d/comments", + url = sn_asprintf("%s/repos/%s/%s/issues/%lu/comments", gcli_get_apibase(ctx), e_owner, e_repo, issue); free(e_owner); diff --git a/src/github/issues.c b/src/github/issues.c index 6d8b0d02..1c915f2a 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -114,7 +114,7 @@ github_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, int github_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number, gcli_issue *const out) + gcli_id const issue_number, gcli_issue *const out) { char *url = NULL; char *e_owner = NULL; @@ -127,7 +127,7 @@ github_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); url = sn_asprintf( - "%s/repos/%s/%s/issues/%d", + "%s/repos/%s/%s/issues/%lu", gcli_get_apibase(ctx), e_owner, e_repo, issue_number); @@ -151,7 +151,7 @@ github_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, int github_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number) + gcli_id const issue_number) { char *url = NULL; char *data = NULL; @@ -163,7 +163,7 @@ github_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); url = sn_asprintf( - "%s/repos/%s/%s/issues/%d", + "%s/repos/%s/%s/issues/%lu", gcli_get_apibase(ctx), e_owner, e_repo, issue_number); @@ -181,7 +181,7 @@ github_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, int github_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number) + gcli_id const issue_number) { char *url = NULL; char *data = NULL; @@ -193,7 +193,7 @@ github_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); url = sn_asprintf( - "%s/repos/%s/%s/issues/%d", + "%s/repos/%s/%s/issues/%lu", gcli_get_apibase(ctx), e_owner, e_repo, issue_number); @@ -240,7 +240,7 @@ github_perform_submit_issue(gcli_ctx *ctx, gcli_submit_issue_options opts, int github_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number, char const *assignee) + gcli_id const issue_number, char const *assignee) { sn_sv escaped_assignee = SV_NULL; char *post_fields = NULL; @@ -257,7 +257,7 @@ github_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); url = sn_asprintf( - "%s/repos/%s/%s/issues/%d/assignees", + "%s/repos/%s/%s/issues/%lu/assignees", gcli_get_apibase(ctx), e_owner, e_repo, issue_number); rc = gcli_fetch_with_method(ctx, "POST", url, post_fields, NULL, NULL); @@ -273,7 +273,7 @@ github_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, int github_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue, char const *const labels[], + gcli_id const issue, char const *const labels[], size_t const labels_size) { char *url = NULL; @@ -283,7 +283,7 @@ github_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, assert(labels_size > 0); - url = sn_asprintf("%s/repos/%s/%s/issues/%d/labels", + url = sn_asprintf("%s/repos/%s/%s/issues/%lu/labels", gcli_get_apibase(ctx), owner, repo, issue); list = sn_join_with(labels, labels_size, "\",\""); @@ -300,7 +300,7 @@ github_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, int github_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue, char const *const labels[], + gcli_id const issue, char const *const labels[], size_t const labels_size) { char *url = NULL; @@ -314,7 +314,7 @@ github_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, e_label = gcli_urlencode(labels[0]); - url = sn_asprintf("%s/repos/%s/%s/issues/%d/labels/%s", + url = sn_asprintf("%s/repos/%s/%s/issues/%lu/labels/%s", gcli_get_apibase(ctx), owner, repo, issue, e_label); rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); @@ -327,8 +327,8 @@ github_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, int github_issue_set_milestone(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const issue, - int const milestone) + char const *const repo, gcli_id const issue, + gcli_id const milestone) { char *url, *e_owner, *e_repo, *body; int rc; @@ -336,11 +336,11 @@ github_issue_set_milestone(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/repos/%s/%s/issues/%d", + url = sn_asprintf("%s/repos/%s/%s/issues/%lu", gcli_get_apibase(ctx), e_owner, e_repo, issue); - body = sn_asprintf("{ \"milestone\": %d }", milestone); + body = sn_asprintf("{ \"milestone\": %lu }", milestone); rc = gcli_fetch_with_method(ctx, "PATCH", url, body, NULL, NULL); @@ -354,7 +354,7 @@ github_issue_set_milestone(gcli_ctx *ctx, char const *const owner, int github_issue_clear_milestone(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const issue) + char const *const repo, gcli_id const issue) { char *url, *e_owner, *e_repo, *body; int rc; @@ -362,7 +362,7 @@ github_issue_clear_milestone(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/repos/%s/%s/issues/%d", + url = sn_asprintf("%s/repos/%s/%s/issues/%lu", gcli_get_apibase(ctx), e_owner, e_repo, issue); diff --git a/src/github/milestones.c b/src/github/milestones.c index 3d533eaa..b4571433 100644 --- a/src/github/milestones.c +++ b/src/github/milestones.c @@ -70,7 +70,7 @@ github_get_milestones(gcli_ctx *ctx, char const *const owner, int github_get_milestone(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const milestone, + char const *const repo, gcli_id const milestone, gcli_milestone *const out) { char *url, *e_owner, *e_repo; @@ -80,7 +80,7 @@ github_get_milestone(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/repos/%s/%s/milestones/%d", + url = sn_asprintf("%s/repos/%s/%s/milestones/%lu", gcli_get_apibase(ctx), e_owner, e_repo, milestone); free(e_repo); @@ -103,7 +103,7 @@ github_get_milestone(gcli_ctx *ctx, char const *const owner, int github_milestone_get_issues(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const milestone, + char const *const repo, gcli_id const milestone, gcli_issue_list *const out) { char *url, *e_owner, *e_repo; @@ -111,7 +111,7 @@ github_milestone_get_issues(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/repos/%s/%s/issues?milestone=%d&state=all", + url = sn_asprintf("%s/repos/%s/%s/issues?milestone=%lu&state=all", gcli_get_apibase(ctx), e_owner, e_repo, milestone); free(e_repo); @@ -163,7 +163,7 @@ github_create_milestone(gcli_ctx *ctx, int github_delete_milestone(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const milestone) + char const *const repo, gcli_id const milestone) { char *url, *e_owner, *e_repo; int rc = 0; @@ -171,7 +171,7 @@ github_delete_milestone(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/repos/%s/%s/milestones/%d", + url = sn_asprintf("%s/repos/%s/%s/milestones/%lu", gcli_get_apibase(ctx), e_owner, e_repo, milestone); @@ -187,7 +187,7 @@ github_delete_milestone(gcli_ctx *ctx, char const *const owner, int github_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const milestone, + char const *const repo, gcli_id const milestone, char const *const date) { char *url, *e_owner, *e_repo, *payload, norm_date[21] = {0}; @@ -201,7 +201,7 @@ github_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/repos/%s/%s/milestones/%d", + url = sn_asprintf("%s/repos/%s/%s/milestones/%lu", gcli_get_apibase(ctx), e_owner, e_repo, milestone); diff --git a/src/github/pulls.c b/src/github/pulls.c index e01f2401..67ceafcf 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -106,7 +106,7 @@ github_get_pulls(gcli_ctx *ctx, char const *owner, char const *repo, int github_print_pull_diff(gcli_ctx *ctx, FILE *stream, char const *owner, - char const *repo, int const pr_number) + char const *repo, gcli_id const pr_number) { char *url = NULL; char *e_owner = NULL; @@ -117,7 +117,7 @@ github_print_pull_diff(gcli_ctx *ctx, FILE *stream, char const *owner, e_repo = gcli_urlencode(repo); url = sn_asprintf( - "%s/repos/%s/%s/pulls/%d", + "%s/repos/%s/%s/pulls/%lu", gcli_get_apibase(ctx), e_owner, e_repo, pr_number); rc = gcli_curl(ctx, stream, url, "Accept: application/vnd.github.v3.diff"); @@ -133,7 +133,7 @@ github_print_pull_diff(gcli_ctx *ctx, FILE *stream, char const *owner, * calls */ static int github_pull_delete_head_branch(gcli_ctx *ctx, char const *owner, - char const *repo, int const pr_number) + char const *repo, gcli_id const pr_number) { gcli_pull pull = {0}; char *url, *e_owner, *e_repo; @@ -163,7 +163,7 @@ github_pull_delete_head_branch(gcli_ctx *ctx, char const *owner, int github_pull_merge(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, enum gcli_merge_flags const flags) + gcli_id const pr_number, enum gcli_merge_flags const flags) { char *url = NULL; char *e_owner = NULL; @@ -177,7 +177,7 @@ github_pull_merge(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); url = sn_asprintf( - "%s/repos/%s/%s/pulls/%d/merge?merge_method=%s", + "%s/repos/%s/%s/pulls/%lu/merge?merge_method=%s", gcli_get_apibase(ctx), e_owner, e_repo, pr_number, squash ? "squash" : "merge"); @@ -196,7 +196,7 @@ github_pull_merge(gcli_ctx *ctx, char const *owner, char const *repo, int github_pull_close(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number) + gcli_id const pr_number) { char *url = NULL; char *e_owner = NULL; @@ -208,7 +208,7 @@ github_pull_close(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); url = sn_asprintf( - "%s/repos/%s/%s/pulls/%d", + "%s/repos/%s/%s/pulls/%lu", gcli_get_apibase(ctx), e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state\": \"closed\"}"); @@ -225,7 +225,7 @@ github_pull_close(gcli_ctx *ctx, char const *owner, char const *repo, int github_pull_reopen(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number) + gcli_id const pr_number) { char *url = NULL; char *data = NULL; @@ -237,7 +237,7 @@ github_pull_reopen(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); url = sn_asprintf( - "%s/repos/%s/%s/pulls/%d", + "%s/repos/%s/%s/pulls/%lu", gcli_get_apibase(ctx), e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state\": \"open\"}"); @@ -307,7 +307,7 @@ github_perform_submit_pull(gcli_ctx *ctx, gcli_submit_pull_options opts) int github_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, gcli_commit_list *const out) + gcli_id const pr_number, gcli_commit_list *const out) { char *url = NULL; char *e_owner = NULL; @@ -324,7 +324,7 @@ github_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); url = sn_asprintf( - "%s/repos/%s/%s/pulls/%d/commits", + "%s/repos/%s/%s/pulls/%lu/commits", gcli_get_apibase(ctx), e_owner, e_repo, pr_number); @@ -336,7 +336,7 @@ github_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, int github_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, gcli_pull *const out) + gcli_id const pr_number, gcli_pull *const out) { int rc = 0; gcli_fetch_buffer json_buffer = {0}; @@ -348,7 +348,7 @@ github_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); url = sn_asprintf( - "%s/repos/%s/%s/pulls/%d", + "%s/repos/%s/%s/pulls/%lu", gcli_get_apibase(ctx), e_owner, e_repo, pr_number); free(e_owner); @@ -371,12 +371,12 @@ github_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, int github_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, gcli_pull_checks_list *out) + gcli_id const pr_number, gcli_pull_checks_list *out) { char refname[64] = {0}; /* This is kind of a hack, but it works! */ - snprintf(refname, sizeof refname, "refs%%2Fpull%%2F%d%%2Fhead", pr_number); + snprintf(refname, sizeof refname, "refs%%2Fpull%%2F%lu%%2Fhead", pr_number); return github_get_checks(ctx, owner, repo, refname, -1, (github_check_list *)out); diff --git a/src/github/review.c b/src/github/review.c index ba468ca1..674aca2d 100644 --- a/src/github/review.c +++ b/src/github/review.c @@ -181,7 +181,7 @@ static char const *get_reviews_fmt = int github_review_get_reviews(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr, gcli_pr_review_list *const out) + gcli_id const pr, gcli_pr_review_list *const out) { gcli_fetch_buffer buffer = {0}; char *url = NULL; diff --git a/src/gitlab/comments.c b/src/gitlab/comments.c index 6137e10c..a63dec5e 100644 --- a/src/gitlab/comments.c +++ b/src/gitlab/comments.c @@ -74,7 +74,7 @@ gitlab_perform_submit_comment(gcli_ctx *ctx, gcli_submit_comment_opts opts, int gitlab_get_mr_comments(gcli_ctx *ctx, char const *owner, char const *repo, - int const mr, gcli_comment_list *const out) + gcli_id const mr, gcli_comment_list *const out) { char *e_owner = gcli_urlencode(owner); char *e_repo = gcli_urlencode(repo); @@ -87,7 +87,7 @@ gitlab_get_mr_comments(gcli_ctx *ctx, char const *owner, char const *repo, }; char *url = sn_asprintf( - "%s/projects/%s%%2F%s/merge_requests/%d/notes", + "%s/projects/%s%%2F%s/merge_requests/%lu/notes", gcli_get_apibase(ctx), e_owner, e_repo, mr); @@ -99,7 +99,7 @@ gitlab_get_mr_comments(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_get_issue_comments(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue, gcli_comment_list *const out) + gcli_id const issue, gcli_comment_list *const out) { char *e_owner = gcli_urlencode(owner); char *e_repo = gcli_urlencode(repo); @@ -112,7 +112,7 @@ gitlab_get_issue_comments(gcli_ctx *ctx, char const *owner, char const *repo, }; char *url = sn_asprintf( - "%s/projects/%s%%2F%s/issues/%d/notes", + "%s/projects/%s%%2F%s/issues/%lu/notes", gcli_get_apibase(ctx), e_owner, e_repo, issue); free(e_owner); diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index b0e36b6f..12e6c952 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -85,7 +85,7 @@ gitlab_get_issues(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number, gcli_issue *const out) + gcli_id const issue_number, gcli_issue *const out) { char *url = NULL; char *e_owner = NULL; @@ -97,7 +97,7 @@ gitlab_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gcli_get_apibase(ctx), + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%lu", gcli_get_apibase(ctx), e_owner, e_repo, issue_number); rc = gcli_fetch(ctx, url, NULL, &buffer); @@ -118,7 +118,7 @@ gitlab_get_issue_summary(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number) + gcli_id const issue_number) { char *url = NULL; char *data = NULL; @@ -129,7 +129,7 @@ gitlab_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gcli_get_apibase(ctx), + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%lu", gcli_get_apibase(ctx), e_owner, e_repo, issue_number); data = sn_asprintf("{ \"state_event\": \"close\"}"); @@ -145,7 +145,7 @@ gitlab_issue_close(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number) + gcli_id const issue_number) { char *url = NULL; char *data = NULL; @@ -156,7 +156,7 @@ gitlab_issue_reopen(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gcli_get_apibase(ctx), + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%lu", gcli_get_apibase(ctx), e_owner, e_repo, issue_number); data = sn_asprintf("{ \"state_event\": \"reopen\"}"); @@ -235,7 +235,7 @@ gitlab_user_id(gcli_ctx *ctx, char const *user_name) int gitlab_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue_number, char const *assignee) + gcli_id const issue_number, char const *assignee) { int assignee_uid = -1; char *url = NULL; @@ -251,7 +251,7 @@ gitlab_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gcli_get_apibase(ctx), + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%lu", gcli_get_apibase(ctx), e_owner, e_repo, issue_number); post_data = sn_asprintf("{ \"assignee_ids\": [ %d ] }", assignee_uid); rc = gcli_fetch_with_method(ctx, "PUT", url, post_data, NULL, NULL); @@ -266,7 +266,7 @@ gitlab_issue_assign(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue, char const *const labels[], + gcli_id const issue, char const *const labels[], size_t const labels_size) { char *url = NULL; @@ -274,7 +274,7 @@ gitlab_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, char *list = NULL; int rc = 0; - url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gcli_get_apibase(ctx), + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%lu", gcli_get_apibase(ctx), owner, repo, issue); list = sn_join_with(labels, labels_size, ","); @@ -291,7 +291,7 @@ gitlab_issue_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int const issue, char const *const labels[], + gcli_id const issue, char const *const labels[], size_t const labels_size) { char *url = NULL; @@ -299,7 +299,7 @@ gitlab_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, char *list = NULL; int rc = 0; - url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gcli_get_apibase(ctx), + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%lu", gcli_get_apibase(ctx), owner, repo, issue); list = sn_join_with(labels, labels_size, ","); @@ -316,15 +316,15 @@ gitlab_issue_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_issue_set_milestone(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const issue, - int const milestone) + char const *const repo, gcli_id const issue, + gcli_id const milestone) { char *url, *e_owner, *e_repo; int rc = 0; e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d?milestone_id=%d", + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%lu?milestone_id=%lu", gcli_get_apibase(ctx), e_owner, e_repo, issue, milestone); rc = gcli_fetch_with_method(ctx, "PUT", url, NULL, NULL, NULL); @@ -338,7 +338,7 @@ gitlab_issue_set_milestone(gcli_ctx *ctx, char const *const owner, int gitlab_issue_clear_milestone(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const issue) + char const *const repo, gcli_id const issue) { char *url, *e_owner, *e_repo, *payload; int rc; @@ -357,7 +357,7 @@ gitlab_issue_clear_milestone(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/issues/%d", gcli_get_apibase(ctx), + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%lu", gcli_get_apibase(ctx), e_owner, e_repo, issue); payload = sn_asprintf("{ \"milestone_id\": null }"); diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index db32f163..f354a099 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -112,10 +112,8 @@ gitlab_get_mrs(gcli_ctx *ctx, char const *owner, char const *repo, } int -gitlab_print_pr_diff(gcli_ctx *ctx, FILE *stream, - char const *owner, - char const *repo, - int const pr_number) +gitlab_print_pr_diff(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *repo, gcli_id const pr_number) { (void)ctx; (void)owner; @@ -131,7 +129,7 @@ gitlab_print_pr_diff(gcli_ctx *ctx, FILE *stream, int gitlab_mr_merge(gcli_ctx *ctx, char const *owner, char const *repo, - int const mr_number, enum gcli_merge_flags const flags) + gcli_id const mr_number, enum gcli_merge_flags const flags) { gcli_fetch_buffer buffer = {0}; char *url = NULL; @@ -146,7 +144,7 @@ gitlab_mr_merge(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); /* PUT /projects/:id/merge_requests/:merge_request_iid/merge */ - url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d/merge" + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%lu/merge" "?squash=%s" "&should_remove_source_branch=%s", gcli_get_apibase(ctx), @@ -166,7 +164,7 @@ gitlab_mr_merge(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, gcli_pull *const out) + gcli_id const pr_number, gcli_pull *const out) { gcli_fetch_buffer json_buffer = {0}; char *url = NULL; @@ -178,7 +176,7 @@ gitlab_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); /* GET /projects/:id/merge_requests/:merge_request_iid */ - url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%lu", gcli_get_apibase(ctx), e_owner, e_repo, pr_number); free(e_owner); @@ -200,7 +198,7 @@ gitlab_get_pull(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number, gcli_commit_list *const out) + gcli_id const pr_number, gcli_commit_list *const out) { char *url = NULL; char *e_owner = NULL; @@ -217,7 +215,7 @@ gitlab_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, e_repo = gcli_urlencode(repo); /* GET /projects/:id/merge_requests/:merge_request_iid/commits */ - url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d/commits", + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%lu/commits", gcli_get_apibase(ctx), e_owner, e_repo, pr_number); free(e_owner); @@ -228,7 +226,7 @@ gitlab_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_mr_close(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number) + gcli_id const pr_number) { char *url = NULL; char *data = NULL; @@ -239,7 +237,7 @@ gitlab_mr_close(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%lu", gcli_get_apibase(ctx), e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state_event\": \"close\"}"); @@ -255,7 +253,7 @@ gitlab_mr_close(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_mr_reopen(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr_number) + gcli_id const pr_number) { char *url = NULL; char *data = NULL; @@ -266,7 +264,7 @@ gitlab_mr_reopen(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%lu", gcli_get_apibase(ctx), e_owner, e_repo, pr_number); data = sn_asprintf("{ \"state_event\": \"reopen\"}"); @@ -333,7 +331,7 @@ gitlab_perform_submit_mr(gcli_ctx *ctx, gcli_submit_pull_options opts) char *post_fields = sn_asprintf( "{\"source_branch\":\""SV_FMT"\",\"target_branch\":\""SV_FMT"\", " "\"title\": \""SV_FMT"\", \"description\": \""SV_FMT"\", " - "\"target_project_id\": %d %s }", + "\"target_project_id\": %lu %s }", SV_ARGS(e_source_branch), SV_ARGS(e_target_branch), SV_ARGS(e_title), @@ -369,7 +367,7 @@ gitlab_perform_submit_mr(gcli_ctx *ctx, gcli_submit_pull_options opts) int gitlab_mr_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int const mr, char const *const labels[], + gcli_id const mr, char const *const labels[], size_t const labels_size) { char *url = NULL; @@ -377,7 +375,7 @@ gitlab_mr_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, char *list = NULL; int rc = 0; - url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%lu", gcli_get_apibase(ctx), owner, repo, mr); list = sn_join_with(labels, labels_size, ","); @@ -394,7 +392,7 @@ gitlab_mr_add_labels(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_mr_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, - int const mr, char const *const labels[], + gcli_id const mr, char const *const labels[], size_t const labels_size) { char *url = NULL; @@ -402,7 +400,7 @@ gitlab_mr_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, char *list = NULL; int rc = 0; - url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%lu", gcli_get_apibase(ctx), owner, repo, mr); list = sn_join_with(labels, labels_size, ","); @@ -419,16 +417,16 @@ gitlab_mr_remove_labels(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_mr_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int mr, int milestone_id) + gcli_id mr, gcli_id milestone_id) { char *url = NULL; char *data = NULL; int rc = 0; - url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d", + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%lu", gcli_get_apibase(ctx), owner, repo, mr); - data = sn_asprintf("{ \"milestone_id\": \"%d\"}", milestone_id); + data = sn_asprintf("{ \"milestone_id\": \"%lu\"}", milestone_id); rc = gcli_fetch_with_method(ctx, "PUT", url, data, NULL, NULL); @@ -440,7 +438,7 @@ gitlab_mr_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_mr_clear_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int mr) + gcli_id const mr) { /* GitLab's REST API docs state: * diff --git a/src/gitlab/milestones.c b/src/gitlab/milestones.c index 54872222..f472c721 100644 --- a/src/gitlab/milestones.c +++ b/src/gitlab/milestones.c @@ -70,7 +70,7 @@ gitlab_get_milestones(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_get_milestone(gcli_ctx *ctx, char const *owner, char const *repo, - int const milestone, gcli_milestone *const out) + gcli_id const milestone, gcli_milestone *const out) { char *url, *e_owner, *e_repo; gcli_fetch_buffer buffer = {0}; @@ -80,7 +80,7 @@ gitlab_get_milestone(gcli_ctx *ctx, char const *owner, char const *repo, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d", gcli_get_apibase(ctx), + url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%lu", gcli_get_apibase(ctx), e_owner, e_repo, milestone); rc = gcli_fetch(ctx, url, NULL, &buffer); @@ -100,7 +100,7 @@ gitlab_get_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_milestone_get_issues(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const milestone, + char const *const repo, gcli_id const milestone, gcli_issue_list *const out) { char *url, *e_owner, *e_repo; @@ -108,7 +108,7 @@ gitlab_milestone_get_issues(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d/issues", + url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%lu/issues", gcli_get_apibase(ctx), e_owner, e_repo, milestone); free(e_repo); @@ -160,7 +160,7 @@ gitlab_create_milestone(gcli_ctx *ctx, int gitlab_delete_milestone(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const milestone) + char const *const repo, gcli_id const milestone) { char *url, *e_owner, *e_repo; int rc = 0; @@ -168,7 +168,7 @@ gitlab_delete_milestone(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d", gcli_get_apibase(ctx), + url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%lu", gcli_get_apibase(ctx), e_owner, e_repo, milestone); rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); @@ -182,7 +182,7 @@ gitlab_delete_milestone(gcli_ctx *ctx, char const *const owner, int gitlab_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, - char const *const repo, int const milestone, + char const *const repo, gcli_id const milestone, char const *const date) { char *url, *e_owner, *e_repo, norm_date[9] = {0}; @@ -196,7 +196,7 @@ gitlab_milestone_set_duedate(gcli_ctx *ctx, char const *const owner, e_owner = gcli_urlencode(owner); e_repo = gcli_urlencode(repo); - url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%d?due_date=%s", + url = sn_asprintf("%s/projects/%s%%2F%s/milestones/%lu?due_date=%s", gcli_get_apibase(ctx), e_owner, e_repo, milestone, norm_date); diff --git a/src/gitlab/review.c b/src/gitlab/review.c index 43af83b3..61a297cf 100644 --- a/src/gitlab/review.c +++ b/src/gitlab/review.c @@ -41,7 +41,7 @@ int gitlab_review_get_reviews(gcli_ctx *ctx, char const *owner, char const *repo, - int const pr, gcli_pr_review_list *const out) + gcli_id const pr, gcli_pr_review_list *const out) { char *url = NULL; @@ -52,7 +52,7 @@ gitlab_review_get_reviews(gcli_ctx *ctx, char const *owner, char const *repo, .parse = (parsefn)(parse_gitlab_reviews), }; - url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d/notes?sort=asc", + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%lu/notes?sort=asc", gcli_get_apibase(ctx), owner, repo, pr); return gcli_fetch_list(ctx, url, &fl); diff --git a/src/gitlab/sshkeys.c b/src/gitlab/sshkeys.c index 33387567..f77aa6f6 100644 --- a/src/gitlab/sshkeys.c +++ b/src/gitlab/sshkeys.c @@ -97,7 +97,7 @@ gitlab_delete_sshkey(gcli_ctx *ctx, gcli_id id) char *url; int rc = 0; - url = sn_asprintf("%s/user/keys/%ul", gcli_get_apibase(ctx), id); + url = sn_asprintf("%s/user/keys/%lu", gcli_get_apibase(ctx), id); rc = gcli_fetch_with_method(ctx, "DELETE", url, NULL, NULL, NULL); free(url); From 5b94d0783f9486fb052a7068591cb9f4ed85c4f8 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Sep 2023 22:21:21 +0200 Subject: [PATCH 225/236] Use new gcli_id type in Gitlab Pipelines --- include/gcli/gitlab/pipelines.h | 40 ++++++++++++++++----------------- src/gitlab/pipelines.c | 16 ++++++------- templates/gitlab/pipelines.t | 4 ++-- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/include/gcli/gitlab/pipelines.h b/include/gcli/gitlab/pipelines.h index 12da361c..a3385900 100644 --- a/include/gcli/gitlab/pipelines.h +++ b/include/gcli/gitlab/pipelines.h @@ -42,7 +42,7 @@ typedef struct gitlab_job gitlab_job; typedef struct gitlab_job_list gitlab_job_list; struct gitlab_pipeline { - long id; + gcli_id id; char *status; char *created_at; char *updated_at; @@ -57,18 +57,18 @@ struct gitlab_pipeline_list { }; struct gitlab_job { - long id; - char *status; - char *stage; - char *name; - char *ref; - char *created_at; - char *started_at; - char *finished_at; - double duration; - char *runner_name; - char *runner_description; - double coverage; + gcli_id id; + char *status; + char *stage; + char *name; + char *ref; + char *created_at; + char *started_at; + char *finished_at; + double duration; + char *runner_name; + char *runner_description; + double coverage; }; struct gitlab_job_list { @@ -82,29 +82,29 @@ int gitlab_get_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, void gitlab_free_pipelines(gitlab_pipeline_list *list); int gitlab_get_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, - long pipeline, int count, gitlab_job_list *out); + gcli_id pipeline, int count, gitlab_job_list *out); void gitlab_free_jobs(gitlab_job_list *jobs); void gitlab_free_job(gitlab_job *job); int gitlab_job_get_log(gcli_ctx *ctx, char const *owner, char const *repo, - long job_id, FILE *stream); + gcli_id job_id, FILE *stream); int gitlab_job_cancel(gcli_ctx *ctx, char const *owner, char const *repo, - long job_id); + gcli_id job_id); int gitlab_job_retry(gcli_ctx *ctx, char const *owner, char const *repo, - long job_id); + gcli_id job_id); int gitlab_job_download_artifacts(gcli_ctx *ctx, char const *owner, - char const *repo, long jid, + char const *repo, gcli_id jid, char const *outfile); int gitlab_get_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, - int mr_id, gitlab_pipeline_list *list); + gcli_id mr_id, gitlab_pipeline_list *list); int gitlab_get_job(gcli_ctx *ctx, char const *owner, char const *repo, - long const jid, gitlab_job *const out); + gcli_id const jid, gitlab_job *const out); #endif /* GITLAB_PIPELINES_H */ diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index 7842171e..56a317a2 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -71,11 +71,11 @@ gitlab_get_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_get_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, - int const mr_id, gitlab_pipeline_list *const list) + gcli_id const mr_id, gitlab_pipeline_list *const list) { char *url = NULL; - url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%d/pipelines", + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%lu/pipelines", gcli_get_apibase(ctx), owner, repo, mr_id); /* fetch everything */ @@ -101,7 +101,7 @@ gitlab_free_pipelines(gitlab_pipeline_list *const list) int gitlab_get_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, - long const pipeline, int const max, + gcli_id const pipeline, int const max, gitlab_job_list *const out) { char *url = NULL; @@ -146,7 +146,7 @@ gitlab_free_jobs(gitlab_job_list *list) int gitlab_job_get_log(gcli_ctx *ctx, char const *owner, char const *repo, - long const job_id, FILE *stream) + gcli_id const job_id, FILE *stream) { char *url = NULL; int rc = 0; @@ -163,7 +163,7 @@ gitlab_job_get_log(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_get_job(gcli_ctx *ctx, char const *owner, char const *repo, - long const jid, gitlab_job *const out) + gcli_id const jid, gitlab_job *const out) { gcli_fetch_buffer buffer = {0}; char *url = NULL; @@ -190,7 +190,7 @@ gitlab_get_job(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_job_cancel(gcli_ctx *ctx, char const *owner, char const *repo, - long const jid) + gcli_id const jid) { char *url = NULL; int rc = 0; @@ -206,7 +206,7 @@ gitlab_job_cancel(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_job_retry(gcli_ctx *ctx, char const *owner, char const *repo, - long const jid) + gcli_id const jid) { int rc = 0; char *url = NULL; @@ -222,7 +222,7 @@ gitlab_job_retry(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_job_download_artifacts(gcli_ctx *ctx, char const *owner, - char const *repo, long const jid, + char const *repo, gcli_id const jid, char const *const outfile) { char *url; diff --git a/templates/gitlab/pipelines.t b/templates/gitlab/pipelines.t index b7543d4b..569796cb 100644 --- a/templates/gitlab/pipelines.t +++ b/templates/gitlab/pipelines.t @@ -8,7 +8,7 @@ object of gitlab_pipeline with "ref" => ref as string, "sha" => sha as string, "source" => source as string, - "id" => id as long); + "id" => id as id); parser gitlab_pipelines is array of gitlab_pipeline use parse_gitlab_pipeline; @@ -29,7 +29,7 @@ object of gitlab_job with "finished_at" => finished_at as string, "runner" => use parse_gitlab_job_runner, "duration" => duration as double, - "id" => id as long, + "id" => id as id, "coverage" => coverage as double); parser gitlab_jobs is From 4d75ca9bd8a2843097a127880fb314aa3ed60551 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Sep 2023 21:47:41 +0200 Subject: [PATCH 226/236] Add local kakoune rc script --- .hotzrc | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .hotzrc diff --git a/.hotzrc b/.hotzrc new file mode 100644 index 00000000..965fdac2 --- /dev/null +++ b/.hotzrc @@ -0,0 +1,12 @@ +# local kakrc for gcli + +# We build inside the build directory +cd build + +set-option global ctagscmd "uctags -R --fields=+S" +set-option global ctagspaths "../include ../src ../thirdparty" + +hook global BufSetOption filetype=c %{ + add-highlighter buffer/ show-whitespaces -spc " " + smarttab +} From 54f2009f2158f19ee6ee7ea44c65b5e5393c6e33 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 10 Sep 2023 00:18:57 +0200 Subject: [PATCH 227/236] (#199) Add a pkgconf file This file allows automatic detection of CFLAGS and LDFLAGS required to link and compile against the new shared libgcli. --- Makefile.am | 3 +++ configure.ac | 1 + libgcli.pc.in | 14 ++++++++++++++ 3 files changed, 18 insertions(+) create mode 100644 libgcli.pc.in diff --git a/Makefile.am b/Makefile.am index ebeb64a8..2c834bf4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -127,6 +127,9 @@ nobase_header_HEADERS = include/gcli/gcli.h include/gcli/comments.h \ include/gcli/review.h include/gcli/gitlab/snippets.h \ include/gcli/status.h include/gcli/sshkeys.h +pkgconfdir = $(libdir)/pkgconfig +pkgconf_DATA = libgcli.pc + libgcli_la_SOURCES = \ include/gcli/ctx.h src/ctx.c \ include/gcli/gcli.h src/gcli.c \ diff --git a/configure.ac b/configure.ac index a7239e34..0d8f4913 100644 --- a/configure.ac +++ b/configure.ac @@ -98,6 +98,7 @@ AC_DEFINE_UNQUOTED([HOSTOS], ["$host"], [Define to the triplet of the host opera dnl Generate and substitute various files AC_CONFIG_FILES([Makefile + libgcli.pc docs/gcli-api.1 docs/gcli-comment.1 docs/gcli-config.1 diff --git a/libgcli.pc.in b/libgcli.pc.in new file mode 100644 index 00000000..c3174759 --- /dev/null +++ b/libgcli.pc.in @@ -0,0 +1,14 @@ +# libgcli package-config file +# +prefix=@prefix@ +exec_prefix=${prefix} +libdir=@libdir@ +includedir=@includedir@ + +Name: gcli +Description: Library to interact with various Git forges +Version: 2.0 +URL: https://herrhotzenplotz.de/gcli +Requires: libcurl >= 8.0 +Libs: -L${libdir} -lgcli +Cflags: -I${includedir} From f8b00f97177807805714dd88a3b90d2557a3a5b4 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 10 Sep 2023 00:37:41 +0200 Subject: [PATCH 228/236] (#196) Add option to filter issues by a label The new option added to the CLI is -L