From 38605cad32f991493cfc2d895ab19364d76e12fc Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 17 Sep 2023 17:49:23 +0200 Subject: [PATCH 001/152] (#189) Add ground work for json generator --- Makefile.am | 9 ++++++- include/gcli/json_gen.h | 55 +++++++++++++++++++++++++++++++++++++++++ src/json_gen.c | 32 ++++++++++++++++++++++++ tests/Kyuafile.in | 4 +++ tests/test-jsongen.c | 41 ++++++++++++++++++++++++++++++ 5 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 include/gcli/json_gen.h create mode 100644 src/json_gen.c create mode 100644 tests/test-jsongen.c diff --git a/Makefile.am b/Makefile.am index eaede040..846a061b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -218,7 +218,8 @@ check_PROGRAMS = \ tests/github-parse-tests$(EXEEXT) \ tests/gitlab-parse-tests$(EXEEXT) \ tests/url-encode$(EXEEXT) \ - tests/pretty_print_test$(EXEEXT) + tests/pretty_print_test$(EXEEXT) \ + tests/test-jsongen$(EXEEXT) $(check_PROGRAMS): tests/gcli_tests.h @@ -258,6 +259,12 @@ tests_pretty_print_test_LDADD = \ libsn.la \ $(LIBATFC_LDFLAGS) +tests_test_jsongen_SOURCES = \ + tests/test-jsongen.c +tests_test_jsongen_LDADD = \ + libgcli.la \ + $(LIBATFC_LDFLAGS) + EXTRA_DIST += tests/samples/github_simple_comment.json \ tests/samples/github_simple_fork.json \ tests/samples/github_simple_issue.json \ diff --git a/include/gcli/json_gen.h b/include/gcli/json_gen.h new file mode 100644 index 00000000..13cffa81 --- /dev/null +++ b/include/gcli/json_gen.h @@ -0,0 +1,55 @@ +/* + * 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_JSON_GEN_H +#define GCLI_JSON_GEN_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +enum { + GCLI_JSONGEN_ARRAY, + GCLI_JSONGEN_OBJECT, +}; + +typedef struct gcli_jsongen gcli_jsongen; +struct gcli_jsongen { + char *buffer; + size_t buffer_size; + size_t buffer_capacity; + + int scopes[32]; /* scope stack */ + size_t scopes_size; /* scope stack pointer */ +}; + +int gcli_jsongen_init(gcli_jsongen *gen); +void gcli_jsongen_free(gcli_jsongen *gen); + +#endif /* GCLI_JSON_GEN_H */ diff --git a/src/json_gen.c b/src/json_gen.c new file mode 100644 index 00000000..592defd4 --- /dev/null +++ b/src/json_gen.c @@ -0,0 +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 diff --git a/tests/Kyuafile.in b/tests/Kyuafile.in index 4c40d37e..8d8e554f 100644 --- a/tests/Kyuafile.in +++ b/tests/Kyuafile.in @@ -23,3 +23,7 @@ atf_test_program{ atf_test_program{ name = 'pretty_print_test' } + +atf_test_program{ + name = 'test-jsongen' +} diff --git a/tests/test-jsongen.c b/tests/test-jsongen.c new file mode 100644 index 00000000..96840521 --- /dev/null +++ b/tests/test-jsongen.c @@ -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. + */ + +#include + +ATF_TC_WITHOUT_HEAD(empty_object); +ATF_TC_BODY(empty_object, tc) +{ +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, empty_object); + return atf_no_error(); +} From b7f3a6a8a42f3ee3f1ff6a476cccb30486f75d90 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 17 Sep 2023 19:56:22 +0200 Subject: [PATCH 002/152] (#189) Proper JSON Object generation --- Makefile.am | 1 + include/gcli/json_gen.h | 14 ++++- src/json_gen.c | 132 ++++++++++++++++++++++++++++++++++++++++ tests/test-jsongen.c | 11 ++++ 4 files changed, 156 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 846a061b..ca456aeb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -141,6 +141,7 @@ libgcli_la_SOURCES = \ src/forges.c include/gcli/forges.h \ src/forks.c include/gcli/forks.h \ src/issues.c include/gcli/issues.h \ + src/json_gen.c include/gcli/json_gen.h \ src/json_util.c include/gcli/json_util.h \ src/labels.c include/gcli/labels.h \ src/milestones.c include/gcli/milestones.h \ diff --git a/include/gcli/json_gen.h b/include/gcli/json_gen.h index 13cffa81..c67f6daa 100644 --- a/include/gcli/json_gen.h +++ b/include/gcli/json_gen.h @@ -34,9 +34,12 @@ #include #endif +#include +#include + enum { - GCLI_JSONGEN_ARRAY, - GCLI_JSONGEN_OBJECT, + GCLI_JSONGEN_ARRAY = 1, + GCLI_JSONGEN_OBJECT = 2, }; typedef struct gcli_jsongen gcli_jsongen; @@ -47,9 +50,16 @@ struct gcli_jsongen { int scopes[32]; /* scope stack */ size_t scopes_size; /* scope stack pointer */ + + bool await_object_value; /* when in an object scope set to true if + * we expect a value and not a key */ }; int gcli_jsongen_init(gcli_jsongen *gen); void gcli_jsongen_free(gcli_jsongen *gen); +char *gcli_jsongen_to_string(gcli_jsongen *gen); + +int gcli_jsongen_begin_object(gcli_jsongen *gen); +int gcli_jsongen_end_object(gcli_jsongen *gen); #endif /* GCLI_JSON_GEN_H */ diff --git a/src/json_gen.c b/src/json_gen.c index 592defd4..8fa0328e 100644 --- a/src/json_gen.c +++ b/src/json_gen.c @@ -30,3 +30,135 @@ #include #include + +#include +#include + +static void +grow_buffer(gcli_jsongen *gen) +{ + gen->buffer_capacity *= 2; + gen->buffer = realloc(gen->buffer, gen->buffer_capacity); +} + +int +gcli_jsongen_init(gcli_jsongen *gen) +{ + /* This will allocate a 32 byte buffer. We can optimise + * this for better allocation speed by analysing some statistics + * of how long usually the generated buffers are. */ + + memset(gen, 0, sizeof(*gen)); + gen->buffer_capacity = 16; + + grow_buffer(gen); + + return 0; +} + +void +gcli_jsongen_free(gcli_jsongen *gen) +{ + free(gen->buffer); + gen->buffer = NULL; + gen->buffer_size = 0; + gen->buffer_capacity = 0; + + gen->scopes_size = 0; +} + +char * +gcli_jsongen_to_string(gcli_jsongen *gen) +{ + char *buf = calloc(gen->buffer_size + 1, 1); + + return memcpy(buf, gen->buffer, gen->buffer_size); +} + +static void +fit(gcli_jsongen *gen, size_t const n_chars) +{ + while (gen->buffer_capacity - gen->buffer_size < n_chars) + grow_buffer(gen); +} + +static int +push_scope(gcli_jsongen *gen, int const scope) +{ + if (gen->scopes_size >= (sizeof(gen->scopes) / sizeof(*gen->scopes))) + return -1; + + gen->scopes[gen->scopes_size++] = scope; + + return 0; +} + +static int +pop_scope(gcli_jsongen *gen) +{ + if (gen->scopes_size == 0) + return -1; + + return gen->scopes[--gen->scopes_size]; +} + +static int +is_array_or_object_scope(gcli_jsongen *gen) +{ + return !!gen->scopes_size; +} + +static void +append_str(gcli_jsongen *gen, char const *str) +{ + size_t const len = strlen(str); + fit(gen, len); + memcpy(gen->buffer + gen->buffer_size, str, len); + gen->buffer_size += len; +} + +static void +put_comma_if_needed(gcli_jsongen *gen) +{ + if (is_array_or_object_scope(gen)) + append_str(gen, ", "); +} + +static bool +is_object_scope(gcli_jsongen *gen) +{ + if (gen->scopes_size == 0) + return false; + + return gen->scopes[gen->scopes_size - 1] == GCLI_JSONGEN_OBJECT; +} + +int +gcli_jsongen_begin_object(gcli_jsongen *gen) +{ + /* Cannot put a json object into a json object key */ + if (is_object_scope(gen) && !gen->await_object_value) + return -1; + + put_comma_if_needed(gen); + + if (push_scope(gen, GCLI_JSONGEN_OBJECT) < 0) + return -1; + + fit(gen, 1); + gen->buffer[gen->buffer_size++] = '{'; + + return 0; +} + +int +gcli_jsongen_end_object(gcli_jsongen *gen) +{ + if (pop_scope(gen) != GCLI_JSONGEN_OBJECT) + return -1; + + fit(gen, 1); + gen->buffer[gen->buffer_size++] = '}'; + + return 0; +} diff --git a/tests/test-jsongen.c b/tests/test-jsongen.c index 96840521..695dc218 100644 --- a/tests/test-jsongen.c +++ b/tests/test-jsongen.c @@ -29,9 +29,20 @@ #include +#include + ATF_TC_WITHOUT_HEAD(empty_object); ATF_TC_BODY(empty_object, tc) { + gcli_jsongen gen = {0}; + + ATF_REQUIRE(gcli_jsongen_init(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_begin_object(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); + + ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), "{}"); + + gcli_jsongen_free(&gen); } ATF_TP_ADD_TCS(tp) From 21ba1098ea4e3e649b3738c9f53e1a3879ba9b22 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 17 Sep 2023 22:02:27 +0200 Subject: [PATCH 003/152] (#189) Add support for JSON arrays to jsongen --- include/gcli/json_gen.h | 3 +++ src/json_gen.c | 48 ++++++++++++++++++++++++++++++++++++----- tests/test-jsongen.c | 19 ++++++++++++++++ 3 files changed, 65 insertions(+), 5 deletions(-) diff --git a/include/gcli/json_gen.h b/include/gcli/json_gen.h index c67f6daa..a3bcb5fe 100644 --- a/include/gcli/json_gen.h +++ b/include/gcli/json_gen.h @@ -53,6 +53,7 @@ struct gcli_jsongen { bool await_object_value; /* when in an object scope set to true if * we expect a value and not a key */ + bool first_elem; /* first element in object/array */ }; int gcli_jsongen_init(gcli_jsongen *gen); @@ -61,5 +62,7 @@ char *gcli_jsongen_to_string(gcli_jsongen *gen); int gcli_jsongen_begin_object(gcli_jsongen *gen); int gcli_jsongen_end_object(gcli_jsongen *gen); +int gcli_jsongen_begin_array(gcli_jsongen *gen); +int gcli_jsongen_end_array(gcli_jsongen *gen); #endif /* GCLI_JSON_GEN_H */ diff --git a/src/json_gen.c b/src/json_gen.c index 8fa0328e..a2120dba 100644 --- a/src/json_gen.c +++ b/src/json_gen.c @@ -53,6 +53,8 @@ gcli_jsongen_init(gcli_jsongen *gen) grow_buffer(gen); + gen->first_elem = true; + return 0; } @@ -120,8 +122,10 @@ append_str(gcli_jsongen *gen, char const *str) static void put_comma_if_needed(gcli_jsongen *gen) { - if (is_array_or_object_scope(gen)) + if (!gen->first_elem && is_array_or_object_scope(gen)) append_str(gen, ", "); + + gen->first_elem = false; } static bool @@ -145,8 +149,9 @@ gcli_jsongen_begin_object(gcli_jsongen *gen) if (push_scope(gen, GCLI_JSONGEN_OBJECT) < 0) return -1; - fit(gen, 1); - gen->buffer[gen->buffer_size++] = '{'; + append_str(gen, "{"); + + gen->first_elem = true; return 0; } @@ -157,8 +162,41 @@ gcli_jsongen_end_object(gcli_jsongen *gen) if (pop_scope(gen) != GCLI_JSONGEN_OBJECT) return -1; - fit(gen, 1); - gen->buffer[gen->buffer_size++] = '}'; + append_str(gen, "}"); + + gen->first_elem = false; + + return 0; +} + +int +gcli_jsongen_begin_array(gcli_jsongen *gen) +{ + /* Cannot put a json array into a json object key */ + if (is_object_scope(gen) && !gen->await_object_value) + return -1; + + put_comma_if_needed(gen); + + if (push_scope(gen, GCLI_JSONGEN_ARRAY) < 0) + return -1; + + append_str(gen, "["); + + gen->first_elem = true; + + return 0; +} + +int +gcli_jsongen_end_array(gcli_jsongen *gen) +{ + if (pop_scope(gen) != GCLI_JSONGEN_ARRAY) + return -1; + + append_str(gen, "]"); + + gen->first_elem = false; return 0; } diff --git a/tests/test-jsongen.c b/tests/test-jsongen.c index 695dc218..b2126954 100644 --- a/tests/test-jsongen.c +++ b/tests/test-jsongen.c @@ -45,8 +45,27 @@ ATF_TC_BODY(empty_object, tc) gcli_jsongen_free(&gen); } +ATF_TC_WITHOUT_HEAD(array_with_two_empty_objects); +ATF_TC_BODY(array_with_two_empty_objects, tc) +{ + gcli_jsongen gen = {0}; + + ATF_REQUIRE(gcli_jsongen_init(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_begin_array(&gen) == 0); + for (int i = 0; i < 2; ++i) { + ATF_REQUIRE(gcli_jsongen_begin_object(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); + } + ATF_REQUIRE(gcli_jsongen_end_array(&gen) == 0); + + ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), "[{}, {}]"); + + gcli_jsongen_free(&gen); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, empty_object); + ATF_TP_ADD_TC(tp, array_with_two_empty_objects); return atf_no_error(); } From abe7131877e492955c389009ebcc18ac2239de22 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 18 Sep 2023 15:30:08 +0200 Subject: [PATCH 004/152] (#189) Add test for empty json array --- src/json_gen.c | 2 +- tests/test-jsongen.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/json_gen.c b/src/json_gen.c index a2120dba..90c3829c 100644 --- a/src/json_gen.c +++ b/src/json_gen.c @@ -104,7 +104,7 @@ pop_scope(gcli_jsongen *gen) return gen->scopes[--gen->scopes_size]; } -static int +static bool is_array_or_object_scope(gcli_jsongen *gen) { return !!gen->scopes_size; diff --git a/tests/test-jsongen.c b/tests/test-jsongen.c index b2126954..c4150044 100644 --- a/tests/test-jsongen.c +++ b/tests/test-jsongen.c @@ -63,9 +63,25 @@ ATF_TC_BODY(array_with_two_empty_objects, tc) gcli_jsongen_free(&gen); } +ATF_TC_WITHOUT_HEAD(empty_array); +ATF_TC_BODY(empty_array, tc) +{ + gcli_jsongen gen = {0}; + + ATF_REQUIRE(gcli_jsongen_init(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_begin_array(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_end_array(&gen) == 0); + + ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), "[]"); + + gcli_jsongen_free(&gen); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, empty_object); ATF_TP_ADD_TC(tp, array_with_two_empty_objects); + ATF_TP_ADD_TC(tp, empty_array); + return atf_no_error(); } From befb0ea8115827dc449f0357c115cce14c00abdd Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 18 Sep 2023 16:22:36 +0200 Subject: [PATCH 005/152] (#189) jsongen: Add support for object members and numbers --- include/gcli/json_gen.h | 2 ++ src/json_gen.c | 60 ++++++++++++++++++++++++++++++++++++++++- src/json_util.c | 2 +- tests/test-jsongen.c | 18 +++++++++++++ 4 files changed, 80 insertions(+), 2 deletions(-) diff --git a/include/gcli/json_gen.h b/include/gcli/json_gen.h index a3bcb5fe..c4e09c69 100644 --- a/include/gcli/json_gen.h +++ b/include/gcli/json_gen.h @@ -64,5 +64,7 @@ int gcli_jsongen_begin_object(gcli_jsongen *gen); int gcli_jsongen_end_object(gcli_jsongen *gen); int gcli_jsongen_begin_array(gcli_jsongen *gen); int gcli_jsongen_end_array(gcli_jsongen *gen); +int gcli_jsongen_objmember(gcli_jsongen *gen, char const *key); +int gcli_jsongen_number(gcli_jsongen *gen, long long num); #endif /* GCLI_JSON_GEN_H */ diff --git a/src/json_gen.c b/src/json_gen.c index 90c3829c..cf2935b4 100644 --- a/src/json_gen.c +++ b/src/json_gen.c @@ -29,8 +29,12 @@ #include +#include + #include +#include +#include #include #include @@ -122,7 +126,7 @@ append_str(gcli_jsongen *gen, char const *str) static void put_comma_if_needed(gcli_jsongen *gen) { - if (!gen->first_elem && is_array_or_object_scope(gen)) + if (!gen->await_object_value && !gen->first_elem && is_array_or_object_scope(gen)) append_str(gen, ", "); gen->first_elem = false; @@ -200,3 +204,57 @@ gcli_jsongen_end_array(gcli_jsongen *gen) return 0; } + +static void +append_vstrf(gcli_jsongen *gen, char const *const fmt, va_list vp) +{ + va_list vp_copy; + size_t len; + + va_copy(vp_copy, vp); + len = vsnprintf(NULL, 0, fmt, vp_copy); + + fit(gen, len + 1); + vsnprintf(gen->buffer + gen->buffer_size, len + 1, fmt, vp); + + gen->buffer_size += len; +} + +static void +append_strf(gcli_jsongen *gen, char const *const fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + append_vstrf(gen, fmt, ap); + va_end(ap); +} + +int +gcli_jsongen_objmember(gcli_jsongen *gen, char const *const key) +{ + if (!is_object_scope(gen)) + return -1; + + put_comma_if_needed(gen); + char const *const e_key = gcli_json_escape_cstr(key); + + append_strf(gen, "\"%s\": ", e_key); + + gen->first_elem = false; + gen->await_object_value = true; + + return 0; +} + +int +gcli_jsongen_number(gcli_jsongen *gen, long long const number) +{ + put_comma_if_needed(gen); + append_strf(gen, "%lld", number); + + gen->await_object_value = false; + gen->first_elem = false; + + return 0; +} diff --git a/src/json_util.c b/src/json_util.c index e23e489f..8c3581ac 100644 --- a/src/json_util.c +++ b/src/json_util.c @@ -181,7 +181,7 @@ gcli_json_escape(sn_sv const it) { sn_sv result = {0}; - result.data = malloc(2 * it.length); + result.data = calloc(2 * it.length + 1, 1); if (!result.data) err(1, "malloc"); diff --git a/tests/test-jsongen.c b/tests/test-jsongen.c index c4150044..09e89518 100644 --- a/tests/test-jsongen.c +++ b/tests/test-jsongen.c @@ -77,11 +77,29 @@ ATF_TC_BODY(empty_array, tc) gcli_jsongen_free(&gen); } +ATF_TC_WITHOUT_HEAD(object_with_number); +ATF_TC_BODY(object_with_number, tc) +{ + gcli_jsongen gen = {0}; + + ATF_REQUIRE(gcli_jsongen_init(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_begin_object(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_objmember(&gen, "number") == 0); + ATF_REQUIRE(gcli_jsongen_number(&gen, 420) == 0); + ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); + + ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), + "{\"number\": 420}"); + + gcli_jsongen_free(&gen); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, empty_object); ATF_TP_ADD_TC(tp, array_with_two_empty_objects); ATF_TP_ADD_TC(tp, empty_array); + ATF_TP_ADD_TC(tp, object_with_number); return atf_no_error(); } From 0a02ba4c7fff4b33cc2c6c2e65950189dba4ed7f Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 18 Sep 2023 16:29:41 +0200 Subject: [PATCH 006/152] (#180) Moderately complex test for nested objects/arrays --- tests/test-jsongen.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/test-jsongen.c b/tests/test-jsongen.c index 09e89518..0e53613b 100644 --- a/tests/test-jsongen.c +++ b/tests/test-jsongen.c @@ -94,12 +94,36 @@ ATF_TC_BODY(object_with_number, tc) gcli_jsongen_free(&gen); } +ATF_TC_WITHOUT_HEAD(object_nested); +ATF_TC_BODY(object_nested, tc) +{ + gcli_jsongen gen = {0}; + + ATF_REQUIRE(gcli_jsongen_init(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_begin_object(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_objmember(&gen, "hiernenarray") == 0); + ATF_REQUIRE(gcli_jsongen_begin_array(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_number(&gen, 69) == 0); + ATF_REQUIRE(gcli_jsongen_number(&gen, 420) == 0); + ATF_REQUIRE(gcli_jsongen_end_array(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_objmember(&gen, "empty_object") == 0); + ATF_REQUIRE(gcli_jsongen_begin_object(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); + + ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), + "{\"hiernenarray\": [69, 420], \"empty_object\": {}}"); + + gcli_jsongen_free(&gen); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, empty_object); ATF_TP_ADD_TC(tp, array_with_two_empty_objects); ATF_TP_ADD_TC(tp, empty_array); ATF_TP_ADD_TC(tp, object_with_number); + ATF_TP_ADD_TC(tp, object_nested); return atf_no_error(); } From 2fae2e679cca4964d81a271c44b371ee365ec251 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 18 Sep 2023 16:41:15 +0200 Subject: [PATCH 007/152] (#189) jsongen: Add support for string literals --- include/gcli/json_gen.h | 1 + src/json_gen.c | 17 ++++++++++++++++- tests/test-jsongen.c | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/gcli/json_gen.h b/include/gcli/json_gen.h index c4e09c69..41a9a173 100644 --- a/include/gcli/json_gen.h +++ b/include/gcli/json_gen.h @@ -66,5 +66,6 @@ int gcli_jsongen_begin_array(gcli_jsongen *gen); int gcli_jsongen_end_array(gcli_jsongen *gen); int gcli_jsongen_objmember(gcli_jsongen *gen, char const *key); int gcli_jsongen_number(gcli_jsongen *gen, long long num); +int gcli_jsongen_string(gcli_jsongen *gen, char const *value); #endif /* GCLI_JSON_GEN_H */ diff --git a/src/json_gen.c b/src/json_gen.c index cf2935b4..05b40de9 100644 --- a/src/json_gen.c +++ b/src/json_gen.c @@ -237,13 +237,15 @@ gcli_jsongen_objmember(gcli_jsongen *gen, char const *const key) return -1; put_comma_if_needed(gen); - char const *const e_key = gcli_json_escape_cstr(key); + char *const e_key = gcli_json_escape_cstr(key); append_strf(gen, "\"%s\": ", e_key); gen->first_elem = false; gen->await_object_value = true; + free(e_key); + return 0; } @@ -258,3 +260,16 @@ gcli_jsongen_number(gcli_jsongen *gen, long long const number) return 0; } + +int +gcli_jsongen_string(gcli_jsongen *gen, char const *value) +{ + put_comma_if_needed(gen); + char *const e_value = gcli_json_escape_cstr(value); + + append_strf(gen, "\"%s\"", e_value); + + free(e_value); + + return 0; +} diff --git a/tests/test-jsongen.c b/tests/test-jsongen.c index 0e53613b..9453d4cd 100644 --- a/tests/test-jsongen.c +++ b/tests/test-jsongen.c @@ -117,6 +117,24 @@ ATF_TC_BODY(object_nested, tc) gcli_jsongen_free(&gen); } + +ATF_TC_WITHOUT_HEAD(object_with_strings); +ATF_TC_BODY(object_with_strings, tc) +{ + gcli_jsongen gen = {0}; + + ATF_REQUIRE(gcli_jsongen_init(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_begin_object(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_objmember(&gen, "key") == 0); + ATF_REQUIRE(gcli_jsongen_string(&gen, "value") == 0); + ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); + + ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), + "{\"key\": \"value\"}"); + + gcli_jsongen_free(&gen); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, empty_object); @@ -124,6 +142,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, empty_array); ATF_TP_ADD_TC(tp, object_with_number); ATF_TP_ADD_TC(tp, object_nested); + ATF_TP_ADD_TC(tp, object_with_strings); return atf_no_error(); } From b8ef887e4e7488904fc7b3361d62d4b2079ac1d8 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 18 Sep 2023 16:46:11 +0200 Subject: [PATCH 008/152] (#189) jsongen: Test for mixed values in array and objects --- tests/test-jsongen.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/test-jsongen.c b/tests/test-jsongen.c index 9453d4cd..3150978d 100644 --- a/tests/test-jsongen.c +++ b/tests/test-jsongen.c @@ -135,6 +135,30 @@ ATF_TC_BODY(object_with_strings, tc) gcli_jsongen_free(&gen); } +ATF_TC_WITHOUT_HEAD(object_with_mixed_values); +ATF_TC_BODY(object_with_mixed_values, tc) +{ + gcli_jsongen gen = {0}; + + ATF_REQUIRE(gcli_jsongen_init(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_begin_object(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_objmember(&gen, "array") == 0); + ATF_REQUIRE(gcli_jsongen_begin_array(&gen) == 0); + + ATF_REQUIRE(gcli_jsongen_number(&gen, 42) == 0); + ATF_REQUIRE(gcli_jsongen_string(&gen, "a string literal") == 0); + ATF_REQUIRE(gcli_jsongen_begin_object(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); + + ATF_REQUIRE(gcli_jsongen_end_array(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); + + ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), + "{\"array\": [42, \"a string literal\", {}]}"); + + gcli_jsongen_free(&gen); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, empty_object); @@ -143,6 +167,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, object_with_number); ATF_TP_ADD_TC(tp, object_nested); ATF_TP_ADD_TC(tp, object_with_strings); + ATF_TP_ADD_TC(tp, object_with_mixed_values); return atf_no_error(); } From 7bb4c38205d1e7b48b755a2f78a9e6168e4d61bf Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 18 Sep 2023 17:53:58 +0200 Subject: [PATCH 009/152] (#189) Add test for strings as object values This was bugged because we did not set await_object_value which caused the commas to be omitted. --- src/json_gen.c | 5 +++++ tests/test-jsongen.c | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/json_gen.c b/src/json_gen.c index 05b40de9..58f61a3f 100644 --- a/src/json_gen.c +++ b/src/json_gen.c @@ -168,6 +168,7 @@ gcli_jsongen_end_object(gcli_jsongen *gen) append_str(gen, "}"); + gen->await_object_value = false; gen->first_elem = false; return 0; @@ -200,6 +201,7 @@ gcli_jsongen_end_array(gcli_jsongen *gen) append_str(gen, "]"); + gen->await_object_value = false; gen->first_elem = false; return 0; @@ -269,6 +271,9 @@ gcli_jsongen_string(gcli_jsongen *gen, char const *value) append_strf(gen, "\"%s\"", e_value); + gen->await_object_value = false; + gen->first_elem = false; + free(e_value); return 0; diff --git a/tests/test-jsongen.c b/tests/test-jsongen.c index 3150978d..b510f39f 100644 --- a/tests/test-jsongen.c +++ b/tests/test-jsongen.c @@ -159,6 +159,26 @@ ATF_TC_BODY(object_with_mixed_values, tc) gcli_jsongen_free(&gen); } +ATF_TC_WITHOUT_HEAD(object_with_two_keys_and_values_that_are_string); +ATF_TC_BODY(object_with_two_keys_and_values_that_are_string, tc) +{ + gcli_jsongen gen = {0}; + + ATF_REQUIRE(gcli_jsongen_init(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_begin_object(&gen) == 0); + ATF_REQUIRE(gcli_jsongen_objmember(&gen, "key1") == 0); + ATF_REQUIRE(gcli_jsongen_string(&gen, "value1") == 0); + + ATF_REQUIRE(gcli_jsongen_objmember(&gen, "key2") == 0); + ATF_REQUIRE(gcli_jsongen_string(&gen, "value2") == 0); + ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); + + ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), + "{\"key1\": \"value1\", \"key2\": \"value2\"}"); + + gcli_jsongen_free(&gen); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, empty_object); @@ -168,6 +188,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, object_nested); ATF_TP_ADD_TC(tp, object_with_strings); ATF_TP_ADD_TC(tp, object_with_mixed_values); + ATF_TP_ADD_TC(tp, object_with_two_keys_and_values_that_are_string); return atf_no_error(); } From 6a5eeee72823da88ad3537b4d040d4ea2be0154c Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Wed, 20 Sep 2023 22:56:27 +0200 Subject: [PATCH 010/152] Add routine for getting a patch for a pull request/merge request --- include/gcli/forges.h | 9 +++++++++ include/gcli/pulls.h | 3 +++ src/pulls.c | 7 +++++++ 3 files changed, 19 insertions(+) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 9732567c..f117b937 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -265,6 +265,15 @@ struct gcli_forge_descriptor { char const *reponame, gcli_id pr_number); + /** + * Fetch the PR patch series into the file */ + int (*pull_get_patch)( + gcli_ctx *ctx, + FILE *stream, + char const *owner, + char const *repo, + gcli_id pull_id); + /** * Return a list of checks associated with the given pull. * diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index 200a99e6..8dfd2cb7 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -185,4 +185,7 @@ int gcli_pull_clear_milestone(gcli_ctx *ctx, char const *owner, char const *repo int gcli_pull_add_reviewer(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id pr_number, char const *username); +int gcli_pull_get_patch(gcli_ctx *ctx, FILE *out, char const *owner, + char const *repo, gcli_id pr_number); + #endif /* PULLS_H */ diff --git a/src/pulls.c b/src/pulls.c index 44317600..16534523 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -205,3 +205,10 @@ gcli_pull_add_reviewer(gcli_ctx *ctx, char const *owner, char const *repo, return gcli_forge(ctx)->pull_add_reviewer( ctx, owner, repo, pr_number, username); } + +int +gcli_pull_get_patch(gcli_ctx *ctx, FILE *out, char const *owner, char const *repo, + gcli_id pull_id) +{ + return gcli_forge(ctx)->pull_get_patch(ctx, out, owner, repo, pull_id); +} From 1981845c1f643f9452b0e365adbd9e706340eefc Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 26 Sep 2023 12:15:10 +0200 Subject: [PATCH 011/152] (#189) Split commit SHA into long and short hash fields This had to be calculated seperately in the case of Github. --- include/gcli/pulls.h | 2 +- src/github/pulls.c | 10 ++++++++++ src/pulls.c | 1 + templates/github/pulls.t | 2 +- templates/gitlab/merge_requests.t | 1 + 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index 8dfd2cb7..b4b58f49 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -86,7 +86,7 @@ struct gcli_pull { }; struct gcli_commit { - char *sha, *message, *date, *author, *email; + char *sha, *long_sha, *message, *date, *author, *email; }; struct gcli_commit_list { diff --git a/src/github/pulls.c b/src/github/pulls.c index ec32db83..6f089a0a 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -331,6 +331,15 @@ github_perform_submit_pull(gcli_ctx *ctx, gcli_submit_pull_options opts) return rc; } +static void +filter_commit_short_sha(gcli_commit **listp, size_t *sizep, void *_data) +{ + (void) _data; + + for (size_t i = 0; i < *sizep; ++i) + (*listp)[i].sha = sn_strndup((*listp)[i].long_sha, 8); +} + int github_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id const pr_number, gcli_commit_list *const out) @@ -344,6 +353,7 @@ github_get_pull_commits(gcli_ctx *ctx, char const *owner, char const *repo, .sizep = &out->commits_size, .max = -1, .parse = (parsefn)(parse_github_commits), + .filter = (filterfn)(filter_commit_short_sha), }; e_owner = gcli_urlencode(owner); diff --git a/src/pulls.c b/src/pulls.c index 16534523..ae616c2b 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -76,6 +76,7 @@ gcli_commits_free(gcli_commit_list *list) { for (size_t i = 0; i < list->commits_size; ++i) { free(list->commits[i].sha); + free(list->commits[i].long_sha); free(list->commits[i].message); free(list->commits[i].date); free(list->commits[i].author); diff --git a/templates/github/pulls.t b/templates/github/pulls.t index 8cc05701..a8437b5a 100644 --- a/templates/github/pulls.t +++ b/templates/github/pulls.t @@ -14,7 +14,7 @@ object of gcli_commit with parser github_commit is object of gcli_commit with - ("sha" => sha as string, + ("sha" => long_sha as string, "commit" => use parse_github_commit_commit_field); parser github_commits is array of gcli_commit diff --git a/templates/gitlab/merge_requests.t b/templates/gitlab/merge_requests.t index 9f43200a..dfe6be59 100644 --- a/templates/gitlab/merge_requests.t +++ b/templates/gitlab/merge_requests.t @@ -36,6 +36,7 @@ parser gitlab_mrs is array of gcli_pull use parse_gitlab_mr; parser gitlab_commit is object of gcli_commit with ("short_id" => sha as string, + "id" => long_sha as string, "title" => message as string, "created_at" => date as string, "author_name" => author as string, From d876c19205ff327d9144c23d52c812296a8b4ba4 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 21 Sep 2023 18:49:26 +0200 Subject: [PATCH 012/152] (#189) Generate patches for merge requests on Gitlab The Gitlab API does not expose an endpoint for grabbing a patch series for all the commits of a specific version of a merge request. Even though there is a link in the frontend rails application we cannot use it as it will redirect us to the login page when trying to access the patch of a private repository. Work around this issue by manually constructing a patch that can be used to review a MR. --- include/gcli/gitlab/merge_requests.h | 23 +++++ include/gcli/pulls.h | 1 + src/curl.c | 1 - src/forges.c | 1 + src/gitlab/merge_requests.c | 139 +++++++++++++++++++++++++-- templates/gitlab/merge_requests.t | 23 ++++- 6 files changed, 175 insertions(+), 13 deletions(-) diff --git a/include/gcli/gitlab/merge_requests.h b/include/gcli/gitlab/merge_requests.h index ac47322c..6666fba7 100644 --- a/include/gcli/gitlab/merge_requests.h +++ b/include/gcli/gitlab/merge_requests.h @@ -42,6 +42,26 @@ struct gitlab_reviewer_id_list { size_t reviewers_size; }; +/* Structs used for internal patch generator. Gitlab does not provide + * an endpoint for doing this properly. */ +typedef struct gitlab_diff gitlab_diff; +struct gitlab_diff { + char *diff; + char *old_path; + char *new_path; + char *a_mode; + char *b_mode; + bool new_file; + bool renamed_file; + bool deleted_file; +}; + +typedef struct gitlab_diff_list gitlab_diff_list; +struct gitlab_diff_list { + gitlab_diff *diffs; + size_t diffs_size; +}; + int gitlab_fetch_mrs(gcli_ctx *ctx, char *url, int max, gcli_pull_list *list); @@ -54,6 +74,9 @@ int gitlab_get_mrs(gcli_ctx *ctx, char const *owner, int gitlab_print_pr_diff(gcli_ctx *ctx, FILE *stream, char const *owner, char const *reponame, gcli_id mr_number); +int gitlab_print_pr_patch(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *reponame, gcli_id mr_number); + int gitlab_mr_merge(gcli_ctx *ctx, char const *owner, char const *reponame, gcli_id mr_number, enum gcli_merge_flags flags); diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index b4b58f49..f2fce835 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -63,6 +63,7 @@ struct gcli_pull { char *head_label; char *base_label; char *head_sha; + char *base_sha; char *milestone; gcli_id id; gcli_id number; diff --git a/src/curl.c b/src/curl.c index 3e245d71..06a4e9bf 100644 --- a/src/curl.c +++ b/src/curl.c @@ -171,7 +171,6 @@ gcli_curl_test_success(gcli_ctx *ctx, char const *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( diff --git a/src/forges.c b/src/forges.c index 08b5863e..79372861 100644 --- a/src/forges.c +++ b/src/forges.c @@ -171,6 +171,7 @@ gitlab_forge_descriptor = .issue_clear_milestone = gitlab_issue_clear_milestone, .get_pulls = gitlab_get_mrs, .print_pull_diff = gitlab_print_pr_diff, + .pull_get_patch = gitlab_print_pr_patch, .get_pull_checks = (gcli_get_pull_checks_cb)gitlab_get_mr_pipelines, .pull_merge = gitlab_mr_merge, .pull_reopen = gitlab_mr_reopen, diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index 8bbf7957..c0798697 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -124,20 +124,139 @@ gitlab_get_mrs(gcli_ctx *ctx, char const *owner, char const *repo, return gitlab_fetch_mrs(ctx, url, max, list); } +static void +gitlab_free_diff(gitlab_diff *diff) +{ + free(diff->diff); + free(diff->old_path); + free(diff->new_path); + free(diff->a_mode); + free(diff->b_mode); + + memset(diff, 0, sizeof(*diff)); +} + +static void +gitlab_free_diffs(gitlab_diff_list *list) +{ + for (size_t i = 0; i < list->diffs_size; ++i) { + gitlab_free_diff(&list->diffs[i]); + } + + free(list->diffs); + list->diffs = NULL; + list->diffs_size = 0; +} + +static int +gitlab_make_commit_patch(gcli_ctx *ctx, FILE *stream, + char const *const e_owner, char const *const e_repo, + char const *const prev_commit_sha, + gcli_commit const *const commit) +{ + char *url; + int rc; + gitlab_diff_list list = {0}; + + gcli_fetch_list_ctx fl = { + .listp = &list.diffs, + .sizep = &list.diffs_size, + .max = -1, + .parse = (parsefn)(parse_gitlab_diffs), + }; + + /* /projects/:id/repository/commits/:sha/diff */ + url = sn_asprintf("%s/projects/%s%%2F%s/repository/commits/%s/diff", + gcli_get_apibase(ctx), e_owner, e_repo, commit->sha); + + rc = gcli_fetch_list(ctx, url, &fl); + if (rc < 0) + goto err_fetch_diffs; + + fprintf(stream, "From %s Mon Sep 17 00:00:00 2001\n", commit->long_sha); + fprintf(stream, "From: %s <%s>\n", commit->author, commit->email); + fprintf(stream, "Date: %s\n", commit->date); + fprintf(stream, "Subject: %s\n\n", commit->message); + + for (size_t i = 0; i < list.diffs_size; ++i) { + gitlab_diff const *d = &list.diffs[i]; + fprintf(stream, + "diff --git a/%s b/%s\n" + "index %s..%s %s\n" + "--- a/%s\n" + "+++ b/%s\n" + "%s", + d->old_path, d->new_path, + prev_commit_sha, commit->sha, d->b_mode, + d->old_path, d->new_path, + d->diff); + } + + fprintf(stream, "--\n2.42.2\n\n"); + + gitlab_free_diffs(&list); + +err_fetch_diffs: + + return rc; +} + int -gitlab_print_pr_diff(gcli_ctx *ctx, FILE *stream, char const *owner, - char const *repo, gcli_id const pr_number) +gitlab_print_pr_patch(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *reponame, gcli_id mr_number) { - (void)ctx; - (void)owner; - (void)repo; - (void)pr_number; + int rc = 0; + char *e_owner, *e_repo; + gcli_pull pull = {0}; + gcli_commit_list commits = {0}; + char const *prev_commit_sha; + char *base_sha_short; + + rc = gitlab_get_pull(ctx, owner, reponame, mr_number, &pull); + if (rc < 0) + goto err_get_pull; - fprintf(stream, - "note : Getting the diff of a Merge Request is not " - "supported on GitLab. Blame the Gitlab people.\n"); + e_owner = gcli_urlencode(owner); + e_repo = gcli_urlencode(reponame); + + rc = gitlab_get_pull_commits(ctx, owner, reponame, mr_number, &commits); + if (rc < 0) + goto err_get_commit_list; + + base_sha_short = sn_strndup(pull.base_sha, 8); + prev_commit_sha = base_sha_short; + for (size_t i = 0; i < commits.commits_size; ++i) { + rc = gitlab_make_commit_patch(ctx, stream, e_owner, e_repo, + prev_commit_sha, + &commits.commits[i]); + if (rc < 0) + goto err_make_commit_patch; + + prev_commit_sha = commits.commits[i].sha; + } + +err_make_commit_patch: + free(base_sha_short); + gcli_commits_free(&commits); + +err_get_commit_list: + free(e_owner); + free(e_repo); + +err_get_pull: + return rc; +} + +int +gitlab_print_pr_diff(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *reponame, gcli_id mr_number) +{ + (void) stream; + (void) owner; + (void) reponame; + (void) mr_number; - return -1; + return gcli_error(ctx, "not yet implemented"); } int diff --git a/templates/gitlab/merge_requests.t b/templates/gitlab/merge_requests.t index dfe6be59..a8c4b09e 100644 --- a/templates/gitlab/merge_requests.t +++ b/templates/gitlab/merge_requests.t @@ -11,6 +11,11 @@ object of gcli_pull with parser gitlab_reviewer is object of char* select "username" as string; +parser gitlab_diff_refs is +object of gcli_pull with + ("base_sha" => base_sha as string, + "head_sha" => head_sha as string); + parser gitlab_mr is object of gcli_pull with ("title" => title as string, @@ -25,11 +30,11 @@ object of gcli_pull with "draft" => draft as bool, "author" => author as user, "source_branch" => head_label as string, - "sha" => head_sha as string, "target_branch" => base_label as string, "milestone" => use parse_gitlab_mr_milestone, "head_pipeline" => use parse_gitlab_mr_head_pipeline, - "reviewers" => reviewers as array of char* use parse_gitlab_reviewer); + "reviewers" => reviewers as array of char* use parse_gitlab_reviewer, + "diff_refs" => use parse_gitlab_diff_refs); parser gitlab_mrs is array of gcli_pull use parse_gitlab_mr; @@ -49,3 +54,17 @@ parser gitlab_reviewer_id is object of gcli_id select "id" as id; parser gitlab_reviewer_ids is object of gitlab_reviewer_id_list with ("reviewers" => reviewers as array of gcli_id use parse_gitlab_reviewer_id); + +parser gitlab_diff is +object of gitlab_diff with + ("diff" => diff as string, + "new_path" => new_path as string, + "old_path" => old_path as string, + "a_mode" => a_mode as string, + "b_mode" => b_mode as string, + "new_file" => new_file as bool, + "renamed_file" => renamed_file as bool, + "deleted_file" => deleted_file as bool); + +parser gitlab_diffs is +array of gitlab_diff use parse_gitlab_diff; From 915a1a1fa49a143294647ddb4ca22716cc190ee4 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 21 Sep 2023 22:49:19 +0200 Subject: [PATCH 013/152] Add missing html templates for tutorial --- docs/tutorial/footer.html | 2 ++ docs/tutorial/middle.html | 27 +++++++++++++++++++++++++++ docs/tutorial/top.html | 4 ++++ 3 files changed, 33 insertions(+) create mode 100644 docs/tutorial/footer.html create mode 100644 docs/tutorial/middle.html create mode 100644 docs/tutorial/top.html diff --git a/docs/tutorial/footer.html b/docs/tutorial/footer.html new file mode 100644 index 00000000..308b1d01 --- /dev/null +++ b/docs/tutorial/footer.html @@ -0,0 +1,2 @@ + + diff --git a/docs/tutorial/middle.html b/docs/tutorial/middle.html new file mode 100644 index 00000000..96684337 --- /dev/null +++ b/docs/tutorial/middle.html @@ -0,0 +1,27 @@ + + + + + + diff --git a/docs/tutorial/top.html b/docs/tutorial/top.html new file mode 100644 index 00000000..b0f93dbc --- /dev/null +++ b/docs/tutorial/top.html @@ -0,0 +1,4 @@ + + + + From fdbdce27c3d8b8c5f0a166e011ba61e70ac5bc1b Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 22 Sep 2023 12:29:06 +0200 Subject: [PATCH 014/152] (#206) Update HACKING.md for split into library and frontend tool --- HACKING.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/HACKING.md b/HACKING.md index 75e3fdd5..4fc4840f 100644 --- a/HACKING.md +++ b/HACKING.md @@ -202,9 +202,16 @@ The code generator is fully documented in [pgen.org](docs/pgen.org). # User Frontend Features -[src/gcli.c](src/gcli.c) is the entry point for the user-facing -tool. In this file you can find the dispatch table for all -subcommands. +The gcli command line tool links against libgcli. Through a context +structure it passes information like the forge type and user +credentials into the library. + +All code for the command line frontend tool is found in the +[src/cmd/](src/cmd/) directory. + +[src/cmd/gcli.c](src/cmd/gcli.c) is the entry point for the command +line tool. In this file you can find the dispatch table for all +subcommands of gcli. ## Subcommands @@ -220,7 +227,10 @@ to `getopt_long` so it needs to reset some internal state. Output is usually formatted as a dictionary or a table. For these cases gcli provides a few convenience functions and data structures. -The relevant header is [gcli/table.h](include/gcli/table.h). +The relevant header is [gcli/cmd/table.h](include/gcli/cmd/table.h). + +Do not use these functions in the library code. It's only supposed +to be used from the command line tool. ### Tables From b2b896f73f4d861987737a0e1a6e51f855581f5a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 22 Sep 2023 13:00:42 +0200 Subject: [PATCH 015/152] (#204) Use ccache if found --- configure.ac | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/configure.ac b/configure.ac index 0d8f4913..46b5c579 100644 --- a/configure.ac +++ b/configure.ac @@ -28,6 +28,13 @@ AC_PROG_LEX(noyywrap) PKG_PROG_PKG_CONFIG +dnl Use ccache if found +CCACHE="" +AC_CHECK_PROG([CCACHE], [ccache], [ccache]) +if ! test -z "${CCACHE}"; then + CC="${CCACHE} ${CC}" +fi + dnl Go looking for libcurl OPT_LIBCURL=check AC_ARG_WITH([libcurl], From 4f808b9e4e0f438c33ba643668247a4f7d7c97c8 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 22 Sep 2023 13:05:46 +0200 Subject: [PATCH 016/152] (#204) Use ccache on CI --- .gitlab-ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 46765190..6c6f5a86 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -15,8 +15,8 @@ alpine-amd64: - 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' --disable-silent-rules || (cat config.log && exit 42) - - make - - make distcheck + - make -j + - make -j distcheck freebsd-arm64: stage: testing @@ -26,8 +26,8 @@ freebsd-arm64: script: - ./autogen.sh - ./configure LEX=flex YACC=byacc CFLAGS='-std=c99 -pedantic -Wall -Wextra -Wno-misleading-indentation -Werror' CPPFLAGS='-D_XOPEN_SOURCE=600' --disable-silent-rules || (cat config.log && exit 42) - - make - - make distcheck + - make -j 4 + - make -j 4 distcheck dist: stage: dist @@ -53,5 +53,5 @@ debian-amd64: - 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' --disable-silent-rules || (cat config.log && exit 42) - - make - - make distcheck + - make -j + - make -j distcheck From 82a0d8b63dc7ec84b978138d9c76edcf652724e3 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 21 Sep 2023 21:17:27 +0200 Subject: [PATCH 017/152] Add new version entry for next release --- Changelog.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Changelog.md b/Changelog.md index c7d26152..c2222c13 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,6 +3,17 @@ This changelog does not follow semantic versioning. +## UNRELEASED + +### Added + +### Fixed + +### Changed + +### Removed + + ## 2.0.0 (2023-Sep-21) ### Added From 271d594be9a0a0a514190f3105bc11278877e869 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 26 Sep 2023 12:59:13 +0200 Subject: [PATCH 018/152] Add a little progress spinner thingy This is just a nice little thing for indicating network activity. --- Changelog.md | 2 ++ include/gcli/ctx.h | 2 ++ include/gcli/gcli.h | 1 + src/cmd/gcli.c | 23 ++++++++++++++++++++ src/ctx.c | 6 ++++++ src/curl.c | 51 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 85 insertions(+) diff --git a/Changelog.md b/Changelog.md index c2222c13..4258b1c9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,8 @@ This changelog does not follow semantic versioning. ### Added +- Added a little spinner to indicate network activity + ### Fixed ### Changed diff --git a/include/gcli/ctx.h b/include/gcli/ctx.h index 6cc2d20b..ce13c654 100644 --- a/include/gcli/ctx.h +++ b/include/gcli/ctx.h @@ -44,6 +44,8 @@ struct gcli_ctx { char *(*get_token)(struct gcli_ctx *); gcli_forge_type (*get_forge_type)(struct gcli_ctx *ctx); char *(*get_apibase)(struct gcli_ctx *); + + void (*report_progress)(void); }; /* Error routine */ diff --git a/include/gcli/gcli.h b/include/gcli/gcli.h index 833f0764..c6c54ea0 100644 --- a/include/gcli/gcli.h +++ b/include/gcli/gcli.h @@ -60,6 +60,7 @@ char const *gcli_init(gcli_ctx **, void *gcli_get_userdata(struct gcli_ctx const *); void gcli_set_userdata(struct gcli_ctx *, void *usrdata); +void gcli_set_progress_func(struct gcli_ctx *, void (*pfunc)(void)); void gcli_destroy(gcli_ctx **ctx); char const *gcli_get_error(gcli_ctx *ctx); diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index a5f803f5..b5b7fda2 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -153,6 +153,27 @@ usage(void) /** The CMD global gcli context */ gcli_ctx *g_clictx = NULL; +static void +gcli_progress_func(void) +{ + char spinner[] = "|/-\\"; + static size_t const spinner_elems = sizeof(spinner) / sizeof(*spinner); + static int spinner_idx = 0; + static int have_checked_stderr = 0, stderr_is_tty = 1; + + /* Check if stderr is a tty */ + if (!have_checked_stderr) { + stderr_is_tty = isatty(STDERR_FILENO); + have_checked_stderr = 1; + } + + if (!stderr_is_tty) + return; + + fprintf(stderr, "Wait... %c\r", spinner[spinner_idx]); + spinner_idx = (spinner_idx + 1) % (spinner_elems - 1); +} + int main(int argc, char *argv[]) { @@ -166,6 +187,8 @@ main(int argc, char *argv[]) if (gcli_config_init_ctx(g_clictx) < 0) errx(1, "error: failed to init context: %s", gcli_get_error(g_clictx)); + gcli_set_progress_func(g_clictx, gcli_progress_func); + /* Parse first arguments */ if (gcli_config_parse_args(g_clictx, &argc, &argv)) { usage(); diff --git a/src/ctx.c b/src/ctx.c index 638cb430..58b04180 100644 --- a/src/ctx.c +++ b/src/ctx.c @@ -71,6 +71,12 @@ gcli_set_userdata(struct gcli_ctx *ctx, void *usrdata) ctx->usrdata = usrdata; } +void +gcli_set_progress_func(struct gcli_ctx *ctx, void (*pfunc)(void)) +{ + ctx->report_progress = pfunc; +} + char * gcli_get_apibase(struct gcli_ctx *ctx) { diff --git a/src/curl.c b/src/curl.c index 9c2f7880..4b2c9c93 100644 --- a/src/curl.c +++ b/src/curl.c @@ -137,6 +137,22 @@ gcli_fetch(gcli_ctx *ctx, char const *url, char **const pagination_next, return gcli_fetch_with_method(ctx, "GET", url, NULL, pagination_next, out); } +static int +gcli_report_progress(void *_ctx, double dltotal, double dlnow, + double ultotal, double ulnow) +{ + gcli_ctx *ctx = _ctx; + + (void) dltotal; + (void) dlnow; + (void) ultotal; + (void) ulnow; + + ctx->report_progress(); + + return 0; +} + /* Check the given url for a successful query */ int gcli_curl_test_success(gcli_ctx *ctx, char const *url) @@ -166,6 +182,13 @@ gcli_curl_test_success(gcli_ctx *ctx, char const *url) curl_easy_setopt(ctx->curl, CURLOPT_FAILONERROR, 0L); curl_easy_setopt(ctx->curl, CURLOPT_FOLLOWLOCATION, 1L); + if (ctx->report_progress) { + curl_easy_setopt(ctx->curl, CURLOPT_XFERINFOFUNCTION, + gcli_report_progress); + curl_easy_setopt(ctx->curl, CURLOPT_XFERINFODATA, ctx); + curl_easy_setopt(ctx->curl, CURLOPT_NOPROGRESS, 0L); + } + ret = curl_easy_perform(ctx->curl); if (ret != CURLE_OK) { @@ -223,6 +246,13 @@ gcli_curl(gcli_ctx *ctx, FILE *stream, char const *url, char const *content_type curl_easy_setopt(ctx->curl, CURLOPT_FAILONERROR, 0L); curl_easy_setopt(ctx->curl, CURLOPT_FOLLOWLOCATION, 1L); + if (ctx->report_progress) { + curl_easy_setopt(ctx->curl, CURLOPT_XFERINFOFUNCTION, + gcli_report_progress); + curl_easy_setopt(ctx->curl, CURLOPT_XFERINFODATA, ctx); + curl_easy_setopt(ctx->curl, CURLOPT_NOPROGRESS, 0L); + } + ret = curl_easy_perform(ctx->curl); rc = gcli_curl_check_api_error(ctx, ret, url, &buffer); @@ -372,6 +402,13 @@ gcli_fetch_with_method( curl_easy_setopt(ctx->curl, CURLOPT_HEADERDATA, &link_header); curl_easy_setopt(ctx->curl, CURLOPT_FOLLOWLOCATION, 1L); + if (ctx->report_progress) { + curl_easy_setopt(ctx->curl, CURLOPT_XFERINFOFUNCTION, + gcli_report_progress); + curl_easy_setopt(ctx->curl, CURLOPT_XFERINFODATA, ctx); + curl_easy_setopt(ctx->curl, CURLOPT_NOPROGRESS, 0L); + } + ret = curl_easy_perform(ctx->curl); rc = gcli_curl_check_api_error(ctx, ret, url, buf); @@ -446,6 +483,13 @@ gcli_post_upload(gcli_ctx *ctx, char const *url, char const *content_type, curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, out); curl_easy_setopt(ctx->curl, CURLOPT_WRITEFUNCTION, fetch_write_callback); + if (ctx->report_progress) { + curl_easy_setopt(ctx->curl, CURLOPT_XFERINFOFUNCTION, + gcli_report_progress); + curl_easy_setopt(ctx->curl, CURLOPT_XFERINFODATA, ctx); + curl_easy_setopt(ctx->curl, CURLOPT_NOPROGRESS, 0L); + } + ret = curl_easy_perform(ctx->curl); rc = gcli_curl_check_api_error(ctx, ret, url, out); @@ -511,6 +555,13 @@ gcli_curl_gitea_upload_attachment(gcli_ctx *ctx, char const *url, curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, out); curl_easy_setopt(ctx->curl, CURLOPT_WRITEFUNCTION, fetch_write_callback); + if (ctx->report_progress) { + curl_easy_setopt(ctx->curl, CURLOPT_XFERINFOFUNCTION, + gcli_report_progress); + curl_easy_setopt(ctx->curl, CURLOPT_XFERINFODATA, ctx); + curl_easy_setopt(ctx->curl, CURLOPT_NOPROGRESS, 0L); + } + ret = curl_easy_perform(ctx->curl); rc = gcli_curl_check_api_error(ctx, ret, url, out); From d189bc9c7559b520beff0fdab0cd90b78b26ed02 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 26 Sep 2023 19:27:22 +0200 Subject: [PATCH 019/152] Clear out the line when done with a transfer --- include/gcli/ctx.h | 4 +++- include/gcli/gcli.h | 4 +++- src/cmd/gcli.c | 11 ++++++++--- src/ctx.c | 3 ++- src/curl.c | 18 +++++++++++++++++- 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/include/gcli/ctx.h b/include/gcli/ctx.h index ce13c654..c11ce213 100644 --- a/include/gcli/ctx.h +++ b/include/gcli/ctx.h @@ -30,6 +30,8 @@ #ifndef GCLI_CTX_H #define GCLI_CTX_H +#include + #include /* Strictly internal structure containing the gcli library context @@ -45,7 +47,7 @@ struct gcli_ctx { gcli_forge_type (*get_forge_type)(struct gcli_ctx *ctx); char *(*get_apibase)(struct gcli_ctx *); - void (*report_progress)(void); + void (*report_progress)(bool done); }; /* Error routine */ diff --git a/include/gcli/gcli.h b/include/gcli/gcli.h index c6c54ea0..c723b0ce 100644 --- a/include/gcli/gcli.h +++ b/include/gcli/gcli.h @@ -34,6 +34,8 @@ #include #endif +#include + enum gcli_output_flags { OUTPUT_SORTED = (1 << 0), OUTPUT_LONG = (1 << 1), @@ -60,7 +62,7 @@ char const *gcli_init(gcli_ctx **, void *gcli_get_userdata(struct gcli_ctx const *); void gcli_set_userdata(struct gcli_ctx *, void *usrdata); -void gcli_set_progress_func(struct gcli_ctx *, void (*pfunc)(void)); +void gcli_set_progress_func(struct gcli_ctx *, void (*pfunc)(bool done)); void gcli_destroy(gcli_ctx **ctx); char const *gcli_get_error(gcli_ctx *ctx); diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index b5b7fda2..b46e878b 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -154,7 +154,7 @@ usage(void) gcli_ctx *g_clictx = NULL; static void -gcli_progress_func(void) +gcli_progress_func(bool const done) { char spinner[] = "|/-\\"; static size_t const spinner_elems = sizeof(spinner) / sizeof(*spinner); @@ -170,8 +170,13 @@ gcli_progress_func(void) if (!stderr_is_tty) return; - fprintf(stderr, "Wait... %c\r", spinner[spinner_idx]); - spinner_idx = (spinner_idx + 1) % (spinner_elems - 1); + /* Clear out the line when done */ + if (done) { + fprintf(stderr, " \r"); + } else { + fprintf(stderr, "Wait... %c\r", spinner[spinner_idx]); + spinner_idx = (spinner_idx + 1) % (spinner_elems - 1); + } } int diff --git a/src/ctx.c b/src/ctx.c index 58b04180..82a04ca7 100644 --- a/src/ctx.c +++ b/src/ctx.c @@ -72,7 +72,8 @@ gcli_set_userdata(struct gcli_ctx *ctx, void *usrdata) } void -gcli_set_progress_func(struct gcli_ctx *ctx, void (*pfunc)(void)) +gcli_set_progress_func(struct gcli_ctx *ctx, + void (*pfunc)(bool done)) { ctx->report_progress = pfunc; } diff --git a/src/curl.c b/src/curl.c index 4b2c9c93..3e245d71 100644 --- a/src/curl.c +++ b/src/curl.c @@ -148,7 +148,8 @@ gcli_report_progress(void *_ctx, double dltotal, double dlnow, (void) ultotal; (void) ulnow; - ctx->report_progress(); + /* not done */ + ctx->report_progress(false); return 0; } @@ -200,6 +201,9 @@ gcli_curl_test_success(gcli_ctx *ctx, char const *url) is_success = false; } + if (ctx->report_progress) + ctx->report_progress(true); + free(buffer.data); return is_success; @@ -256,6 +260,9 @@ gcli_curl(gcli_ctx *ctx, FILE *stream, char const *url, char const *content_type ret = curl_easy_perform(ctx->curl); rc = gcli_curl_check_api_error(ctx, ret, url, &buffer); + if (ctx->report_progress) + ctx->report_progress(true); + if (rc == 0) fwrite(buffer.data, 1, buffer.length, stream); @@ -412,6 +419,9 @@ gcli_fetch_with_method( ret = curl_easy_perform(ctx->curl); rc = gcli_curl_check_api_error(ctx, ret, url, buf); + if (ctx->report_progress) + ctx->report_progress(true); + /* only parse these headers and continue if there was no error */ if (rc == 0) { if (link_header && pagination_next) @@ -493,6 +503,9 @@ gcli_post_upload(gcli_ctx *ctx, char const *url, char const *content_type, ret = curl_easy_perform(ctx->curl); rc = gcli_curl_check_api_error(ctx, ret, url, out); + if (ctx->report_progress) + ctx->report_progress(true); + curl_slist_free_all(headers); headers = NULL; @@ -565,6 +578,9 @@ gcli_curl_gitea_upload_attachment(gcli_ctx *ctx, char const *url, ret = curl_easy_perform(ctx->curl); rc = gcli_curl_check_api_error(ctx, ret, url, out); + if (ctx->report_progress) + ctx->report_progress(true); + /* Cleanup */ curl_slist_free_all(headers); headers = NULL; From 0fa674918090d5fdbfb6118d0c65d3c1b78b0492 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 26 Sep 2023 19:55:52 +0200 Subject: [PATCH 020/152] Fix version number --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 46b5c579..6f22d957 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-ALPHA2],[nsonack@herrhotzenplotz.de],[gcli],[https://gitlab.com/herrhotzenplotz/gcli/]) +AC_INIT([gcli],[2.1.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 8d42d7ba99fac01ecb4400371716c740bb8d240e Mon Sep 17 00:00:00 2001 From: Gavin-John Noonan Date: Wed, 27 Sep 2023 16:40:27 +0100 Subject: [PATCH 021/152] feat(docs/tutorial): set "safe" shell options for the generator script Set the following options: -e: Exit immediately if any command exits with a non-zero status (error). -u: Treat unset variables as errors, causing the script to exit. --- docs/tutorial/gen.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/tutorial/gen.sh b/docs/tutorial/gen.sh index 2f6caad3..f5e91b52 100755 --- a/docs/tutorial/gen.sh +++ b/docs/tutorial/gen.sh @@ -1,4 +1,8 @@ #!/bin/sh +# Set the following options: +# -e: Exit immediately if any command exits with a non-zero status (error). +# -u: Treat unset variables as errors, causing the script to exit. +set -eu # # Static Site generator for the tutorial. From f2a3e2ff15da5a16a09d2b9938a5bfb301cf367a Mon Sep 17 00:00:00 2001 From: Gavin-John Noonan Date: Wed, 27 Sep 2023 16:40:27 +0100 Subject: [PATCH 022/152] refactor(docs/tutorial): move the page title HTML into the template --- docs/tutorial/gen.sh | 8 ++++---- docs/tutorial/top.html | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/tutorial/gen.sh b/docs/tutorial/gen.sh index f5e91b52..54da8e4d 100755 --- a/docs/tutorial/gen.sh +++ b/docs/tutorial/gen.sh @@ -11,8 +11,8 @@ set -eu # header() { - cat top.html - printf "%s\n" "${1}" + title="${1}" + sed "s/{{TITLE_PLACEHOLDER}}/${title}/g" top.html cat middle.html } @@ -21,7 +21,7 @@ footer() { } genindex() { - header "GCLI Tutorial" + header "Index" cat <A GCLI Tutorial @@ -44,7 +44,7 @@ genpage() { PAGETITLE="${1}" PAGEMDFILE="${2}" - header "GCLI Tutorial | ${PAGETITLE}" + header "${PAGETITLE}" echo "

⇐ Back to table of contents

" echo "
" diff --git a/docs/tutorial/top.html b/docs/tutorial/top.html index b0f93dbc..29df8d52 100644 --- a/docs/tutorial/top.html +++ b/docs/tutorial/top.html @@ -2,3 +2,4 @@ + GCLI Tutorial | {{TITLE_PLACEHOLDER}} From e282960eb90aa0577c8781db932133647ac97859 Mon Sep 17 00:00:00 2001 From: Gavin-John Noonan Date: Wed, 27 Sep 2023 16:40:27 +0100 Subject: [PATCH 023/152] refactor(docs/tutorial): migrate middle.html code into top.html middle.html has become reduntant now that we hande the page titles within top.html. Move the code over and delete the file. --- docs/tutorial/gen.sh | 1 - docs/tutorial/middle.html | 27 --------------------------- docs/tutorial/top.html | 27 +++++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 28 deletions(-) delete mode 100644 docs/tutorial/middle.html diff --git a/docs/tutorial/gen.sh b/docs/tutorial/gen.sh index 54da8e4d..1b816b2b 100755 --- a/docs/tutorial/gen.sh +++ b/docs/tutorial/gen.sh @@ -13,7 +13,6 @@ set -eu header() { title="${1}" sed "s/{{TITLE_PLACEHOLDER}}/${title}/g" top.html - cat middle.html } footer() { diff --git a/docs/tutorial/middle.html b/docs/tutorial/middle.html deleted file mode 100644 index 96684337..00000000 --- a/docs/tutorial/middle.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - diff --git a/docs/tutorial/top.html b/docs/tutorial/top.html index 29df8d52..99ccce7d 100644 --- a/docs/tutorial/top.html +++ b/docs/tutorial/top.html @@ -3,3 +3,30 @@ GCLI Tutorial | {{TITLE_PLACEHOLDER}} + + + + + + From 750bfabe66ae3d80d14b0ce0e81d52da9b0894ff Mon Sep 17 00:00:00 2001 From: Gavin-John Noonan Date: Wed, 27 Sep 2023 16:40:27 +0100 Subject: [PATCH 024/152] fix(docs/tutorial): Extract Full Document Titles during Page Generation Previously, when generating HTML pages, only the first word of the page title was used, due to the use of `awk '{print $2}'` and how we read in the toc file. This led to incomplete titles for entries with multi-word titles. Update the script to use a tab character as the Internal Field Separator (IFS) whilst reading the file, ensuring full titles are accurately extracted. --- docs/tutorial/gen.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/tutorial/gen.sh b/docs/tutorial/gen.sh index 1b816b2b..83dce365 100755 --- a/docs/tutorial/gen.sh +++ b/docs/tutorial/gen.sh @@ -57,9 +57,7 @@ genpage() { genindex > index.html -while read record; do - title="$(echo ${record} | awk '{print $2}')" - htmldoc="$(echo ${record} | awk '{print $1}')" +while IFS="$(printf '\t')" read -r htmldoc title; do mddoc="${htmldoc%.html}.md" genpage "${title}" "${mddoc}" > "${htmldoc}" From f9fb54aa5195da20a26ac0be478e12b998fa925c Mon Sep 17 00:00:00 2001 From: Gavin-John Noonan Date: Wed, 27 Sep 2023 16:40:27 +0100 Subject: [PATCH 025/152] fix(docs/tutorial): prevent globing issues when passing files to cmark --- 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 83dce365..d56d3595 100755 --- a/docs/tutorial/gen.sh +++ b/docs/tutorial/gen.sh @@ -47,7 +47,7 @@ genpage() { echo "

⇐ Back to table of contents

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

⇐ Back to table of contents

" From 402c4ed3d8c0ed331be171cabfa4a9399a25954d Mon Sep 17 00:00:00 2001 From: Gavin-John Noonan Date: Wed, 27 Sep 2023 16:40:27 +0100 Subject: [PATCH 026/152] feat(docs/tutorial): generate next/previous links for navigation When generating a page, we now add next/previous links to both the header and the footer, to help with navigating between tutorial pages. I would have likes to stick with just using sh, however there was no clean solution so AWK has been used to keep track of the next/previous page as well as the page title. However the script remains POSIX compliant. --- docs/tutorial/gen.sh | 97 ++++++++++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 27 deletions(-) diff --git a/docs/tutorial/gen.sh b/docs/tutorial/gen.sh index d56d3595..08b610e1 100755 --- a/docs/tutorial/gen.sh +++ b/docs/tutorial/gen.sh @@ -11,54 +11,97 @@ set -eu # header() { - title="${1}" - sed "s/{{TITLE_PLACEHOLDER}}/${title}/g" top.html + TITLE="${1}" + sed "s/{{TITLE_PLACEHOLDER}}/${title}/g" top.html } footer() { - cat footer.html + cat footer.html +} + +pagination() { + PREVDOC="$1" + PREVTITLE="$2" + NEXTDOC="$3" + NEXTTITLE="$4" + + echo "" } genindex() { - header "Index" + header "Index" - cat <A GCLI Tutorial -

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

+ cat <A GCLI Tutorial +

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

-

Table of contents

+

Table of contents

EOF - echo "
    " + echo "
      " - awk -F\\t '{printf "
    1. %s
    2. \n", $1, $2}' < toc + awk -F\\t '{printf "
    3. %s
    4. \n", $1, $2}' < toc - echo "
    " + echo "
" - footer + footer } genpage() { - PAGETITLE="${1}" - PAGEMDFILE="${2}" + PAGETITLE="$1" + PAGEMDFILE="$2" + PREVDOC="$3" + PREVTITLE="$4" + NEXTDOC="$5" + NEXTTITLE="$6" - header "${PAGETITLE}" + header "${PAGETITLE}" - echo "

⇐ Back to table of contents

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

⇐ Back to table of contents

" + pagination "${PREVDOC}" "${PREVTITLE}" "${NEXTDOC}" "${NEXTTITLE}" + echo "
" - footer -} -genindex > index.html + cmark -t html < "${PAGEMDFILE}" + echo "
" + echo "
" + + pagination "${PREVDOC}" "${PREVTITLE}" "${NEXTDOC}" "${NEXTTITLE}" + + footer +} +prevhtmldoc="" +prevtitlename="" while IFS="$(printf '\t')" read -r htmldoc title; do - mddoc="${htmldoc%.html}.md" + mddoc="${htmldoc%.html}.md" + + + read -r nexthtmldoc nexttitle < "${htmldoc}" + # Generating the pages + genpage "${title}" "${mddoc}" "${prevhtmldoc}" "${prevtitlename}" "${nexthtmldoc}" "${nexttitle}" > "${htmldoc}" + + # Update the previous document filename and title for the next iteration + prevhtmldoc="$htmldoc" + prevtitlename="$title" done < toc + +genindex > index.html + From 3e9248da72af42b5ed8097dea4d749aa105474df Mon Sep 17 00:00:00 2001 From: Gavin-John Noonan Date: Wed, 27 Sep 2023 16:40:27 +0100 Subject: [PATCH 027/152] feat(docs/tutorial): Aid navigation by providing tags These tags used to be used by search engines and spiders when indexing a site, however with modern techniques they are not used as much. However certain browsers (EWW), screen readers, and browser extensions will read these and allow you to navigated between pages via the keyboard or voice commands. --- docs/tutorial/gen.sh | 8 ++++++-- docs/tutorial/top.html | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/gen.sh b/docs/tutorial/gen.sh index 08b610e1..043e42ad 100755 --- a/docs/tutorial/gen.sh +++ b/docs/tutorial/gen.sh @@ -12,7 +12,11 @@ set -eu header() { TITLE="${1}" - sed "s/{{TITLE_PLACEHOLDER}}/${title}/g" top.html + PREVURL="${2-}" + NEXTURL="${3-}" + sed -e "s/{{TITLE_PLACEHOLDER}}/${TITLE}/g" \ + -e "s/{{PREVURL}}/${PREVURL}/g" \ + -e "s/{{NEXURL}}/${NEXTURL}/g" top.html } footer() { @@ -66,7 +70,7 @@ genpage() { NEXTDOC="$5" NEXTTITLE="$6" - header "${PAGETITLE}" + header "${PAGETITLE}" "${PREVDOC}" "${NEXTDOC}" pagination "${PREVDOC}" "${PREVTITLE}" "${NEXTDOC}" "${NEXTTITLE}" echo "
" diff --git a/docs/tutorial/top.html b/docs/tutorial/top.html index 99ccce7d..daec21b4 100644 --- a/docs/tutorial/top.html +++ b/docs/tutorial/top.html @@ -4,6 +4,8 @@ GCLI Tutorial | {{TITLE_PLACEHOLDER}} + + + + + +

GCLI - A Git Forge CLI

+

+ GCLI is a tool that lets you interact with Git forges such as Gitlab, Gitea and + GitHub with a consistent command line interface. +
+ It allows you to create, inspect and interact with issues, pull- and merge requests, + inspect CI and pipelines and much more. +
+ Screenshot of gcli +

+

+

General

+ There is not much so far on this page. + However, you can go look at + +

+

+

Bug Reports and Development

+ Report bugs via GitLab, + GitHub or via E-mail. + I also happily accept patches and encourage sending them through all 3 above channels. +
+ For E-Mail please refer to git-send-email. If you have never done that, I can recommend + git-send-email.io +

+

+

GCLI is available or coming to various distributions

+ + If you want gcli to be available in your favourite operating system please submit + them to the respective packaging tree.
+ Please also tell me such that I can link to them here.
+

+

+ The CSS on this page is stolen and edited from + + the even better motherfucking website + . +

+ + diff --git a/docs/website/tutorial/01-Installation.html b/docs/website/tutorial/01-Installation.html new file mode 100644 index 00000000..e60433c9 --- /dev/null +++ b/docs/website/tutorial/01-Installation.html @@ -0,0 +1,113 @@ + + + + + GCLI Tutorial | Installation + + + + + + + + + +
+

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.

+

Windows NT Notes

+

It is entirely possible to build gcli on Windows using +MSYS2. Please follow their instructions on +how to set up a development environment.

+

Generic build instructions

+

For this purpose go to +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
+
+

or on MSYS2:

+
$ pacman -S libcurl-devel pkgconf
+
+

Extract the tarball:

+
$ tar xf gcli-1.1.0.tar.xz
+$ cd gcli-1.1.0
+
+

Configure, build and install gcli:

+
$ ./configure
+...
+$ make
+...
+$ make install
+
+

Check that the shell finds gcli:

+
$ which gcli
+/usr/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 <nsonack@herrhotzenplotz.de> and contributors.
+$
+
+

Advanced Windows Environment Setup

+

In case you want to use the installed gcli from outside MSYS2 (e.g. +in cmd.exe) you may wish to update the Path environment variable +and add the C:\msys2\usr\bin directory to it. Make sure you have +the library paths set up correctly.

+
+
+ + + diff --git a/docs/tutorial/01-Installation.md b/docs/website/tutorial/01-Installation.md similarity index 100% rename from docs/tutorial/01-Installation.md rename to docs/website/tutorial/01-Installation.md diff --git a/docs/website/tutorial/02-First-Steps.html b/docs/website/tutorial/02-First-Steps.html new file mode 100644 index 00000000..2f6318aa --- /dev/null +++ b/docs/website/tutorial/02-First-Steps.html @@ -0,0 +1,123 @@ + + + + + GCLI Tutorial | First Steps + + + + + + + + + +
+

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/02-First-Steps.md b/docs/website/tutorial/02-First-Steps.md similarity index 100% rename from docs/tutorial/02-First-Steps.md rename to docs/website/tutorial/02-First-Steps.md diff --git a/docs/website/tutorial/03-Find-Documentation.html b/docs/website/tutorial/03-Find-Documentation.html new file mode 100644 index 00000000..34265683 --- /dev/null +++ b/docs/website/tutorial/03-Find-Documentation.html @@ -0,0 +1,108 @@ + + + + + GCLI Tutorial | How to find documentation + + + + + + + + + +
+

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 <nsonack@herrhotzenplotz.de> 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/03-Find-Documentation.md b/docs/website/tutorial/03-Find-Documentation.md similarity index 100% rename from docs/tutorial/03-Find-Documentation.md rename to docs/website/tutorial/03-Find-Documentation.md diff --git a/docs/website/tutorial/04-Account-Setup.html b/docs/website/tutorial/04-Account-Setup.html new file mode 100644 index 00000000..abb51ad0 --- /dev/null +++ b/docs/website/tutorial/04-Account-Setup.html @@ -0,0 +1,92 @@ + + + + + GCLI Tutorial | Setting up an account + + + + + + + + + +
+

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 - on Windows you need to do this from +the MSYS2 Shell:

+
$ 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=<token-goes-here>
+    account=<account-name>
+    forge-type=github
+}
+
+

Replace the <token-goes-here> with the previously generated token +and the <account> 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/04-Account-Setup.md b/docs/website/tutorial/04-Account-Setup.md similarity index 100% rename from docs/tutorial/04-Account-Setup.md rename to docs/website/tutorial/04-Account-Setup.md diff --git a/docs/website/tutorial/05-Creating-an-issue.html b/docs/website/tutorial/05-Creating-an-issue.html new file mode 100644 index 00000000..8b171f8c --- /dev/null +++ b/docs/website/tutorial/05-Creating-an-issue.html @@ -0,0 +1,102 @@ + + + + + GCLI Tutorial | Creating an issue + + + + + + + + + +
+

Creating an issue

+

Note: This assumes you have configured gcli with an account 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/05-Creating-an-issue.md b/docs/website/tutorial/05-Creating-an-issue.md similarity index 100% rename from docs/tutorial/05-Creating-an-issue.md rename to docs/website/tutorial/05-Creating-an-issue.md diff --git a/docs/website/tutorial/06-Commenting.html b/docs/website/tutorial/06-Commenting.html new file mode 100644 index 00000000..c6c75b8a --- /dev/null +++ b/docs/website/tutorial/06-Commenting.html @@ -0,0 +1,70 @@ + + + + + GCLI Tutorial | Interacting and commenting + + + + + + + + + +
+

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/06-Commenting.md b/docs/website/tutorial/06-Commenting.md similarity index 100% rename from docs/tutorial/06-Commenting.md rename to docs/website/tutorial/06-Commenting.md diff --git a/docs/tutorial/footer.html b/docs/website/tutorial/footer.html similarity index 100% rename from docs/tutorial/footer.html rename to docs/website/tutorial/footer.html diff --git a/docs/tutorial/gen.sh b/docs/website/tutorial/gen.sh similarity index 100% rename from docs/tutorial/gen.sh rename to docs/website/tutorial/gen.sh diff --git a/docs/website/tutorial/index.html b/docs/website/tutorial/index.html new file mode 100644 index 00000000..d602e473 --- /dev/null +++ b/docs/website/tutorial/index.html @@ -0,0 +1,49 @@ + + + + + GCLI Tutorial | Index + + + + + + + + +

A GCLI Tutorial

+

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

+ +

Table of contents

+
    +
  1. Installation
  2. +
  3. First Steps
  4. +
  5. How to find documentation
  6. +
  7. Setting up an account
  8. +
  9. Creating an issue
  10. +
  11. Interacting and commenting
  12. +
+ + diff --git a/docs/tutorial/old_index.md b/docs/website/tutorial/old_index.md similarity index 100% rename from docs/tutorial/old_index.md rename to docs/website/tutorial/old_index.md diff --git a/docs/tutorial/toc b/docs/website/tutorial/toc similarity index 100% rename from docs/tutorial/toc rename to docs/website/tutorial/toc diff --git a/docs/tutorial/top.html b/docs/website/tutorial/top.html similarity index 100% rename from docs/tutorial/top.html rename to docs/website/tutorial/top.html From 07750eaabe21df6b983dc74a28722d874de70018 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 24 Nov 2023 19:35:06 +0100 Subject: [PATCH 103/152] Add a deploy script for the website --- docs/website/deploy.sh | 32 ++++++++++++++++++++++++++++++++ docs/website/index.html | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100755 docs/website/deploy.sh diff --git a/docs/website/deploy.sh b/docs/website/deploy.sh new file mode 100755 index 00000000..ae754bad --- /dev/null +++ b/docs/website/deploy.sh @@ -0,0 +1,32 @@ +#!/bin/sh -xe +# +# This script builds the tutorial and then creates a tarball that +# is pulled regularly from the server +# + +cd $(dirname $0) + +# Build the tutorial +( + cd tutorial + ./gen.sh +) + +# Make a dist directory and copy over files +DISTDIR=$(mktemp -d) +mkdir -p ${DISTDIR}/tutorial +mkdir -p ${DISTDIR}/assets + +cp -vp index.html ${DISTDIR}/ +cp -vp \ + tutorial/0*.html \ + tutorial/index.html \ + ${DISTDIR}/tutorial + +cp -vp \ + ../screenshot-04.png \ + ${DISTDIR}/assets/screenshot.png + +tar -c -f - -C ${DISTDIR} \. | xz > website_dist.tar.xz + +rm -fr ${DISTDIR} diff --git a/docs/website/index.html b/docs/website/index.html index 6629e971..14b67858 100644 --- a/docs/website/index.html +++ b/docs/website/index.html @@ -53,7 +53,7 @@

GCLI - A Git Forge CLI

It allows you to create, inspect and interact with issues, pull- and merge requests, inspect CI and pipelines and much more.
- Screenshot of gcli

From ffa8000cf716eac36f2dd6f535fcd030db116a49 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 24 Nov 2023 19:37:56 +0100 Subject: [PATCH 104/152] Build the website as part of the CI --- .gitlab-ci.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6c6f5a86..9ecdc021 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -32,16 +32,19 @@ freebsd-arm64: dist: stage: dist tags: - - freebsd - - arm64 + - linux + image: alpine:3.18 script: + - apk add libcurl gcc autoconf automake libtool make pkgconf musl-dev curl-dev flex bison xz gzip bzip2 libbsd-dev kyua atf-dev cmark - ./autogen.sh - - ./configure - - make dist + - ./configure CFLAGS='-std=c99 -pedantic -Wall -Wextra -Werror' CPPFLAGS='-D_XOPEN_SOURCE=600' --disable-silent-rules || (cat config.log && exit 42) + - make -j dist + - cd docs/website && ./deploy.sh artifacts: name: "Dist Tarballs" paths: - gcli-*.tar.* + - docs/website/website_dist.tar.xz debian-amd64: stage: testing From 39d268630f1cf7522a4f74a955fa7d8732f461b4 Mon Sep 17 00:00:00 2001 From: Jakub Wilk Date: Sat, 25 Nov 2023 10:35:17 +0100 Subject: [PATCH 105/152] Fix typos --- Changelog.md | 2 ++ HACKING.md | 4 ++-- README.md | 10 +++++++--- docs/gcli-config.1.in | 4 ++-- docs/gcli-gists.1.in | 2 +- docs/gcli-pipelines.1.in | 2 +- docs/gcli-repos.1.in | 2 +- 7 files changed, 16 insertions(+), 10 deletions(-) diff --git a/Changelog.md b/Changelog.md index 97ba9398..8b61ab17 100644 --- a/Changelog.md +++ b/Changelog.md @@ -31,6 +31,8 @@ This changelog does not follow semantic versioning. leaks were minor and gcli is not a long-running application where thease leaks would have had any serious impact on the memory footprint. +- Spelling fixes in manual pages (submitted by Jakub Wilk + https://github.com/herrhotzenplotz/gcli/pull/121) ### Changed diff --git a/HACKING.md b/HACKING.md index 9ec24554..db0e1d79 100644 --- a/HACKING.md +++ b/HACKING.md @@ -64,7 +64,7 @@ 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 +`libgcli.so`. Because of `build/gcli` now not being an ELF executable but a shell script debuggers can't load gcli properly. #### Sanitized Builds @@ -228,7 +228,7 @@ subcommands of gcli. ## Subcommands -Subcommand implementations are found in seperate C files in the +Subcommand implementations are found in separate C files in the `src/cmd` subdirectory. When parsing command line options please use `getopt_long`. Do not diff --git a/README.md b/README.md index 6dff6944..752493e8 100644 --- a/README.md +++ b/README.md @@ -116,9 +116,13 @@ Github and Gitlab or ask on IRC. ## Bugs and contributions -Please report bugs, issues and questions to nsonack@herrhotzenplotz.de -or on [GitLab](https://gitlab.com/herrhotzenplotz/gcli). You can also -submit patches this way using git-send-email. +Please report bugs, issues and questions to +[~herrhotzenplotz/gcli-discuss@lists.sr.ht](mailto:~herrhotzenplotz/gcli-discuss@lists.sr.ht) +or on [GitLab](https://gitlab.com/herrhotzenplotz/gcli). + +You can also submit patches using git-send-email or Mercurial +patchbomb to +[~herrhotzenplotz/gcli-devel@lists.sr.ht](mailto:~herrhotzenplotz/gcli-devl@lists.sr.ht). ## License diff --git a/docs/gcli-config.1.in b/docs/gcli-config.1.in index 2a61264f..bd1125ef 100644 --- a/docs/gcli-config.1.in +++ b/docs/gcli-config.1.in @@ -34,9 +34,9 @@ ID of the public key to delete. .It Cm ssh List SSH public keys for the current user. .It Cm ssh add -Add a SSH public key for the current user. +Add an SSH public key for the current user. .It Cm ssh delete -Delete a SSH public key for the current user. +Delete an SSH public key for the current user. .El .Sh EXAMPLES Print a list of registered SSH public keys: diff --git a/docs/gcli-gists.1.in b/docs/gcli-gists.1.in index df4a37e6..e611c0f3 100644 --- a/docs/gcli-gists.1.in +++ b/docs/gcli-gists.1.in @@ -55,7 +55,7 @@ Paste a new Gist. The following flags can be specified: .It Fl f , -file Pa file Read the content from the specified file instead of standard input. .It Fl d , -description Ar description -The descrition of the Gist to be created. +The description of the Gist to be created. .El .It Cm delete Delete a Gist. The following options can be specified: diff --git a/docs/gcli-pipelines.1.in b/docs/gcli-pipelines.1.in index 3bd40d6a..7c87d387 100644 --- a/docs/gcli-pipelines.1.in +++ b/docs/gcli-pipelines.1.in @@ -63,7 +63,7 @@ Retry the job. .It Cm artifacts Op Fl o Ar outfile Download the artifacts archive as a zip to disk. The default output file is .Pa artifacts.zip -but it can be overriden by using the +but it can be overridden by using the .Fl o flag. .El diff --git a/docs/gcli-repos.1.in b/docs/gcli-repos.1.in index 3972d38f..c8c90024 100644 --- a/docs/gcli-repos.1.in +++ b/docs/gcli-repos.1.in @@ -68,7 +68,7 @@ may be one or more of the following: .It Cm delete Op Fl y Delete the repository. You will be asked for confirmation unless you set .Fl y . -.It Cm set-visiblity Ar level +.It Cm set-visibility Ar level Change the visibility level of the repository. .Ar level may be one of: From c705c573d3dce9fa6794b66aae4b837c702f111a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 25 Nov 2023 11:36:22 +0100 Subject: [PATCH 106/152] Remove outdated links from readme Bug-Report: https://github.com/herrhotzenplotz/gcli/issues/119 Reported-By: Jakub Wilk (https://github.com/jwilk) --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 752493e8..62f161de 100644 --- a/README.md +++ b/README.md @@ -36,10 +36,6 @@ There are official packages available: - [FreeBSD](https://freshports.org/devel/gcli) -Packages that are work-in-progress: - -- [Debian and Devuan](https://herrhotzenplotz.de/gcli/pkg/Debian) - ### Dependencies Required dependencies: From b6bed6c0dff54e4354d57003ec466779b1763482 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 25 Nov 2023 11:42:42 +0100 Subject: [PATCH 107/152] Update reference to the IRC channel and mailing lists I created a new IRC channel for this purpose since the old one isn't really suitable for these kinds of discussions. Bug-Report: https://github.com/herrhotzenplotz/gcli/issues/120 Reported-By: Jakub Wilk (https://github.com/jwilk) --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 62f161de..59d555df 100644 --- a/README.md +++ b/README.md @@ -106,9 +106,12 @@ Tested Compilers so far: ## Support -Please refer to the manual pages that come with gcli. You may want to -start at `gcli(1)`. For further questions refer to the issues on -Github and Gitlab or ask on IRC. +Please refer to the manual pages that come with gcli. You may want +to start at `gcli(1)`. For further questions refer to the issues +on Github and Gitlab or ask on IRC at #gcli on +[Libera.Chat](https://libera.chat/). Alternatively you may also use +the mailing list at +[https://lists.sr.ht/~herrhotzenplotz/gcli-discuss](https://lists.sr.ht/~herrhotzenplotz/gcli-discuss). ## Bugs and contributions From 55dd6d626923240ffacacff9aada53dc84ea5c2e Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sun, 26 Nov 2023 00:44:06 +0100 Subject: [PATCH 108/152] Remove bad __unused decorator While compiling on IA-64 Debian Linux I discovered this silly thing. Doesn't work on Linux because it's a FreeBSD internal macro. --- src/github/issues.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/github/issues.c b/src/github/issues.c index 0f3fc65b..01920da7 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -107,9 +107,8 @@ get_milestone_id(gcli_ctx *ctx, char const *owner, char const *repo, } static int -parse_github_milestone(gcli_ctx *ctx, char const *owner __unused, - char const *repo __unused, char const *milestone, - gcli_id *out) +parse_github_milestone(gcli_ctx *ctx, char const *owner, char const *repo, + char const *milestone, gcli_id *out) { char *endptr = NULL; size_t const m_len = strlen(milestone); From 35a058dcb274aef9950d707bd2ba8e57da39fc47 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 25 Nov 2023 12:56:28 +0100 Subject: [PATCH 109/152] cmd/repos: Prevent segmentation fault without configured default account when listing repositories This bug occured because the default account name wasn't checked for NULL causing downstream dereference of that pointer. Bug-Report: https://github.com/herrhotzenplotz/gcli/issues/118 Reported-By: crpb (https://github.com/crpb) --- src/cmd/repos.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/cmd/repos.c b/src/cmd/repos.c index c7581b24..4ff42858 100644 --- a/src/cmd/repos.c +++ b/src/cmd/repos.c @@ -372,6 +372,15 @@ subcommand_repos(int argc, char *argv[]) if (!owner) owner = gcli_config_get_account_name(g_clictx); + /* whenever there is no default account we would be passing NULL to + * gcli_get_repos. This is bad since that causes segfaults down the + * line. (https://github.com/herrhotzenplotz/gcli/issues/118) */ + if (!owner) { + fprintf(stderr, "error: no account specified or no default account" + " configured. use -o to provide an explicit account name.\n"); + return EXIT_FAILURE; + } + 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)); From 210dbd6d379231ccd86c336ebd7686fbb9c373ec Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 27 Nov 2023 10:29:21 +0100 Subject: [PATCH 110/152] Prevent use-after-free when adding subcommand aliases The add_subcommand_alias routine contained a use-after-free bug which was discovered by valgrind. I actually used the AddressSanitizer to track down this bug - it is much more useful. The actual bug is that old_sc saved a reference to the old array that was realloc-ed and then the function pointer from out the now free'ed array was copied over. Fix this by storing the function pointer into a temporary, then realloc-ing the array and then copy the temporary value into the new array entry. Github-Issue: https://github.com/herrhotzenplotz/gcli/issues/122 Reported-By: Mikael Fangel (https://github.com/MikaelFangel) --- src/cmd/gcli.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cmd/gcli.c b/src/cmd/gcli.c index 0eb3a0c5..e542df28 100644 --- a/src/cmd/gcli.c +++ b/src/cmd/gcli.c @@ -269,6 +269,7 @@ add_subcommand_alias(char const *alias_name, char const *alias_for) char *docstring; struct subcommand const *old_sc; struct subcommand *new_sc; + int (*old_fn)(int, char **); old_sc = find_subcommand(alias_for, NULL); if (old_sc == NULL) { @@ -277,6 +278,7 @@ add_subcommand_alias(char const *alias_name, char const *alias_for) exit(EXIT_FAILURE); } + old_fn = old_sc->fn; docstring = sn_asprintf("Alias for %s", alias_for); subcommands = realloc(subcommands, (subcommands_size + 1) * sizeof(*subcommands)); @@ -284,7 +286,7 @@ add_subcommand_alias(char const *alias_name, char const *alias_for) new_sc = &subcommands[subcommands_size++]; new_sc->cmd_name = alias_name; - new_sc->fn = old_sc->fn; + new_sc->fn = old_fn; new_sc->docstring = docstring; } From 24df8738d5f2f3a445be056048fb6e4222567861 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Mon, 27 Nov 2023 21:12:23 +0100 Subject: [PATCH 111/152] website: Update Debian Link from ftp-master to tracker. The old link has expired because it's not in the NEW queue anymore. --- docs/website/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/website/index.html b/docs/website/index.html index 14b67858..414b2a26 100644 --- a/docs/website/index.html +++ b/docs/website/index.html @@ -84,7 +84,7 @@

Bug Reports and Development

GCLI is available or coming to various distributions

If you want gcli to be available in your favourite operating system please submit From 60d2d6320f24e7e93229acdd94fbb0d5d435fff2 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 25 Nov 2023 14:20:26 +0100 Subject: [PATCH 112/152] Add a new title action to the issues subcommand This action will allow changing the title of an issue. Also update documentation, both internal help and the manual page. Gitlab-Issue: https://gitlab.com/herrhotzenplotz/gcli/-/issues/215 --- docs/gcli-issues.1.in | 3 +++ src/cmd/issues.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/docs/gcli-issues.1.in b/docs/gcli-issues.1.in index 49055c9c..43ac8f38 100644 --- a/docs/gcli-issues.1.in +++ b/docs/gcli-issues.1.in @@ -116,6 +116,9 @@ Clear associated milestone of the given issue. Alias for the .Cm comments action that prints the list of comments associated with the issue. +.It Cm title Ar new-title +Change the title of the issue to +.Ar new-title . .El .Sh EXAMPLES Print a list of issues in the current project: diff --git a/src/cmd/issues.c b/src/cmd/issues.c index 5ffddeea..2f196cdd 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -76,6 +76,7 @@ usage(void) fprintf(stderr, " milestone Assign this issue to the given milestone\n"); fprintf(stderr, " milestone -d Clear the assigned milestone of the given issue\n"); fprintf(stderr, " notes Alias for comments\n"); + fprintf(stderr, " title Change the title of the issue\n"); fprintf(stderr, "\n"); version(); copyright(); @@ -628,6 +629,11 @@ handle_issues_actions(int argc, char *argv[], handle_issue_milestone_action( &argc, &argv, owner, repo, issue_id); + } else if (strcmp("title", operation) == 0) { + + char const __unused *new_title = shift(&argc, &argv); + errx(1, "error: changing titles is not yet implemented"); + } else { fprintf(stderr, "error: unknown operation %s\n", operation); usage(); From 1d2894dc98d0080e91aa1f4fbf3d58cad4dae2dc Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 25 Nov 2023 14:23:48 +0100 Subject: [PATCH 113/152] Add a new forge dispatch routine for setting the title of an issue This is the forge-agnostic library frontend function that is used in the gcli tool. Gitlab-Issue: https://gitlab.com/herrhotzenplotz/gcli/-/issues/215 --- include/gcli/forges.h | 6 ++++++ include/gcli/issues.h | 3 +++ src/issues.c | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index f117b937..83177537 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -171,6 +171,12 @@ struct gcli_forge_descriptor { gcli_submit_issue_options opts, gcli_fetch_buffer *out); + /** + * Change the title of an issue */ + int (*issue_set_title)( + gcli_ctx *ctx, char const *owner, char const *repo, gcli_id issue, + char const *new_title); + /** * Bitmask of exceptions/fields that the forge doesn't support */ enum { diff --git a/include/gcli/issues.h b/include/gcli/issues.h index 04b7a8ca..44d0bb84 100644 --- a/include/gcli/issues.h +++ b/include/gcli/issues.h @@ -117,4 +117,7 @@ int gcli_issue_set_milestone(gcli_ctx *ctx, char const *owner, char const *repo, int gcli_issue_clear_milestone(gcli_ctx *cxt, char const *owner, char const *repo, gcli_id issue); +int gcli_issue_set_title(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_id issue, char const *new_title); + #endif /* ISSUES_H */ diff --git a/src/issues.c b/src/issues.c index 06ca17cc..08114ed5 100644 --- a/src/issues.c +++ b/src/issues.c @@ -151,3 +151,10 @@ gcli_issue_clear_milestone(gcli_ctx *ctx, char const *const owner, { return gcli_forge(ctx)->issue_clear_milestone(ctx, owner, repo, issue); } + +int +gcli_issue_set_title(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_id issue, char const *new_title) +{ + return gcli_forge(ctx)->issue_set_title(ctx, owner, repo, issue, new_title); +} From f9e0724a2f216ebec3cd220088b84fc6e1fa456b Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 25 Nov 2023 14:46:50 +0100 Subject: [PATCH 114/152] cmd/issues: Forward calls to title action to forge dispatcher This wires up the new title action to the previously added library dispatch function. Gitlab-Issue: https://gitlab.com/herrhotzenplotz/gcli/-/issues/215 --- src/cmd/issues.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/cmd/issues.c b/src/cmd/issues.c index 2f196cdd..b4d4c0f2 100644 --- a/src/cmd/issues.c +++ b/src/cmd/issues.c @@ -631,8 +631,14 @@ handle_issues_actions(int argc, char *argv[], } else if (strcmp("title", operation) == 0) { - char const __unused *new_title = shift(&argc, &argv); - errx(1, "error: changing titles is not yet implemented"); + char const *new_title = shift(&argc, &argv); + int rc = gcli_issue_set_title(g_clictx, owner, repo, issue_id, + new_title); + + if (rc < 0) { + errx(1, "error: failed to set new issue title: %s", + gcli_get_error(g_clictx)); + } } else { fprintf(stderr, "error: unknown operation %s\n", operation); From a59630b0cba9cdf2844a66adbe367943a2f336d9 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 25 Nov 2023 15:04:21 +0100 Subject: [PATCH 115/152] Implement changing issue titles for Github Implements updating issues for Github forges. This is also the implementation for Gitea, the forwarding call to the Github implementation for Gitea will be a separate patch. Gitlab-Issue: https://gitlab.com/herrhotzenplotz/gcli/-/issues/215 --- include/gcli/github/issues.h | 4 ++++ src/forges.c | 1 + src/github/issues.c | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/include/gcli/github/issues.h b/include/gcli/github/issues.h index 46246bd8..6c4de0e4 100644 --- a/include/gcli/github/issues.h +++ b/include/gcli/github/issues.h @@ -73,4 +73,8 @@ int github_issue_set_milestone(gcli_ctx *ctx, char const *owner, int github_issue_clear_milestone(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id issue); +int github_issue_set_title(gcli_ctx *ctx, char const *const owner, + char const *const repo, gcli_id const issue, + char const *const new_title); + #endif /* GCLI_ISSUES_H */ diff --git a/src/forges.c b/src/forges.c index 79372861..8fc96abe 100644 --- a/src/forges.c +++ b/src/forges.c @@ -89,6 +89,7 @@ github_forge_descriptor = .perform_submit_issue = github_perform_submit_issue, .issue_set_milestone = github_issue_set_milestone, .issue_clear_milestone = github_issue_clear_milestone, + .issue_set_title = github_issue_set_title, .get_milestones = github_get_milestones, .get_milestone = github_get_milestone, .create_milestone = github_create_milestone, diff --git a/src/github/issues.c b/src/github/issues.c index 01920da7..f122001b 100644 --- a/src/github/issues.c +++ b/src/github/issues.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -441,3 +442,42 @@ github_issue_clear_milestone(gcli_ctx *ctx, char const *const owner, return rc; } + +int +github_issue_set_title(gcli_ctx *ctx, char const *const owner, + char const *const repo, gcli_id const issue, + char const *const new_title) +{ + char *url, *e_owner, *e_repo, *payload; + gcli_jsongen gen = {0}; + int rc; + + /* Generate url */ + e_owner = gcli_urlencode(owner); + e_repo = gcli_urlencode(repo); + + url = sn_asprintf("%s/repos/%s/%s/issues/%"PRIid, gcli_get_apibase(ctx), + e_owner, e_repo, issue); + + free(e_owner); + free(e_repo); + + /* Generate payload */ + gcli_jsongen_init(&gen); + gcli_jsongen_begin_object(&gen); + { + gcli_jsongen_objmember(&gen, "title"); + gcli_jsongen_string(&gen, new_title); + } + gcli_jsongen_end_object(&gen); + + payload = gcli_jsongen_to_string(&gen); + gcli_jsongen_free(&gen); + + rc = gcli_fetch_with_method(ctx, "PATCH", url, payload, NULL, NULL); + + free(payload); + free(url); + + return rc; +} From f592100621bc1a844446e63225dbe7a1caebad87 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 25 Nov 2023 15:29:27 +0100 Subject: [PATCH 116/152] Implement updating issue titles for Gitea Just the forward call to the Github implementation because the APIs are the same. Gitlab-Issue: https://gitlab.com/herrhotzenplotz/gcli/-/issues/215 --- include/gcli/gitea/issues.h | 4 ++++ src/forges.c | 1 + src/gitea/issues.c | 8 ++++++++ 3 files changed, 13 insertions(+) diff --git a/include/gcli/gitea/issues.h b/include/gcli/gitea/issues.h index ba2502f7..d50078a5 100644 --- a/include/gcli/gitea/issues.h +++ b/include/gcli/gitea/issues.h @@ -69,4 +69,8 @@ int gitea_issue_set_milestone(gcli_ctx *ctx, char const *owner, int gitea_issue_clear_milestone(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id issue); +int gitea_issue_set_title(gcli_ctx *ctx, char const *const owner, + char const *const repo, gcli_id const issue, + char const *const new_title); + #endif /* GITEA_ISSUES_H */ diff --git a/src/forges.c b/src/forges.c index 8fc96abe..af2cc19a 100644 --- a/src/forges.c +++ b/src/forges.c @@ -222,6 +222,7 @@ gitea_forge_descriptor = .issue_assign = gitea_issue_assign, .issue_set_milestone = gitea_issue_set_milestone, .issue_clear_milestone = gitea_issue_clear_milestone, + .issue_set_title = gitea_issue_set_title, .get_issue_comments = gitea_get_comments, .get_milestones = gitea_get_milestones, .get_milestone = gitea_get_milestone, diff --git a/src/gitea/issues.c b/src/gitea/issues.c index 5c43f169..010418df 100644 --- a/src/gitea/issues.c +++ b/src/gitea/issues.c @@ -262,3 +262,11 @@ gitea_issue_clear_milestone(gcli_ctx *ctx, char const *owner, { return github_issue_set_milestone(ctx, owner, repo, issue, 0); } + +int +gitea_issue_set_title(gcli_ctx *ctx, char const *const owner, + char const *const repo, gcli_id const issue, + char const *const new_title) +{ + return github_issue_set_title(ctx, owner, repo, issue, new_title); +} From 64a3f9d1d650c15dd3972bb59dd81e62188ef32a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 25 Nov 2023 15:17:09 +0100 Subject: [PATCH 117/152] Implement updating issue titles for Gitlab Gitlab-Issue: https://gitlab.com/herrhotzenplotz/gcli/-/issues/215 --- include/gcli/gitlab/issues.h | 3 +++ src/forges.c | 1 + src/gitlab/issues.c | 38 ++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/include/gcli/gitlab/issues.h b/include/gcli/gitlab/issues.h index e0c8d5bd..7f4264da 100644 --- a/include/gcli/gitlab/issues.h +++ b/include/gcli/gitlab/issues.h @@ -73,4 +73,7 @@ int gitlab_issue_set_milestone(gcli_ctx *ctx, char const *owner, int gitlab_issue_clear_milestone(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id issue); +int gitlab_issue_set_title(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_id issue, char const *new_title); + #endif /* GITLAB_ISSUES_H */ diff --git a/src/forges.c b/src/forges.c index af2cc19a..cf7d3ffa 100644 --- a/src/forges.c +++ b/src/forges.c @@ -162,6 +162,7 @@ gitlab_forge_descriptor = .issue_add_labels = gitlab_issue_add_labels, .issue_remove_labels = gitlab_issue_remove_labels, .perform_submit_issue = gitlab_perform_submit_issue, + .issue_set_title = gitlab_issue_set_title, .get_milestones = gitlab_get_milestones, .get_milestone = gitlab_get_milestone, .create_milestone = gitlab_create_milestone, diff --git a/src/gitlab/issues.c b/src/gitlab/issues.c index 5d47e066..386cfed0 100644 --- a/src/gitlab/issues.c +++ b/src/gitlab/issues.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -360,3 +361,40 @@ gitlab_issue_clear_milestone(gcli_ctx *ctx, char const *const owner, return rc; } + +int +gitlab_issue_set_title(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_id issue, char const *const new_title) +{ + char *url, *e_owner, *e_repo, *payload; + gcli_jsongen gen = {0}; + int rc; + + /* Generate url */ + e_owner = gcli_urlencode(owner); + e_repo = gcli_urlencode(repo); + + url = sn_asprintf("%s/projects/%s%%2F%s/issues/%"PRIid, + gcli_get_apibase(ctx), e_owner, e_repo, issue); + free(e_owner); + free(e_repo); + + /* Generate payload */ + gcli_jsongen_init(&gen); + gcli_jsongen_begin_object(&gen); + { + gcli_jsongen_objmember(&gen, "title"); + gcli_jsongen_string(&gen, new_title); + } + gcli_jsongen_end_object(&gen); + + payload = gcli_jsongen_to_string(&gen); + gcli_jsongen_free(&gen); + + rc = gcli_fetch_with_method(ctx, "PUT", url, payload, NULL, NULL); + + free(url); + free(payload); + + return rc; +} From 17cfeefc4cfe5531c14c5937f5d40256ede4e049 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 28 Nov 2023 20:14:03 +0100 Subject: [PATCH 118/152] Changelog: Add added entry for new title action in issues subcommand This option allows updating the title of an existing issue. Gitlab-Issue: https://gitlab.com/herrhotzenplotz/gcli/-/issues/215 --- Changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog.md b/Changelog.md index 8b51fd1c..12587665 100644 --- a/Changelog.md +++ b/Changelog.md @@ -21,6 +21,8 @@ This changelog does not follow semantic versioning. to allow filtering by milestones. - Add a new `patch` action to the pulls subcommand. This allows you to print the entire patch series for the given pull request. +- Add a new `title` action to the issues subcommand that allows + updating the title of an issue. ### Fixed From 0ce1b2e0a2c2aaad9eb131d006d4a5885972d13f Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 28 Nov 2023 20:33:05 +0100 Subject: [PATCH 119/152] cmd/pulls: Add new title action to pulls subcommand The action handler is stubbed out for now. Necessary documentation for this feature has been added to the internal help and the manual page as well. Issue: https://gitlab.com/herrhotzenplotz/gcli/-/issues/215 --- docs/gcli-pulls.1.in | 13 +++++++++++++ src/cmd/pulls.c | 17 +++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/docs/gcli-pulls.1.in b/docs/gcli-pulls.1.in index 13fff67d..f5c2302a 100644 --- a/docs/gcli-pulls.1.in +++ b/docs/gcli-pulls.1.in @@ -168,6 +168,9 @@ Add the given label to the pull request. .It remove Ar label Remove the given label from the pull request. .El +.It Cm title Ar new-title +Change the title of the pull request to +.Ar new-title . .El .Sh EXAMPLES Print a list of open PRs in the current project: @@ -216,6 +219,16 @@ List pull requests that are associated with the milestone $ gcli pulls -M version420 .Ed .Pp +Change the title of pull request #42 on Github to +.Dq "This is the new title" : +.Bd -literal -offset indent +$ gcli -t github pulls -i 42 title "This is the new title" +.Ed +.Pp +Same command as above, but with abbreviated pulls subcommand: +.Bd -literal -offset indent +$ gcli -t github pu -i 42 title "This is the new title" +.Ed .Sh SEE ALSO .Xr git 1 , .Xr git-merge 1 , diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 149996d0..9372f7b8 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -93,6 +93,7 @@ usage(void) fprintf(stderr, " remove \n"); fprintf(stderr, " diff Display changes as diff\n"); fprintf(stderr, " patch Display changes as patch series\n"); + fprintf(stderr, " title Change the title of the pull request\n"); fprintf(stderr, " request-review Add as a reviewer of the PR\n"); fprintf(stderr, "\n"); @@ -935,6 +936,21 @@ action_request_review(struct action_ctx *const ctx) ctx->argv += 1; } +static void +action_title(struct action_ctx *const ctx) +{ + if (ctx->argc < 2) { + fprintf(stderr, "error: missing title\n"); + usage(); + exit(EXIT_FAILURE); + } + + errx(1, "error: title action is not yet implemented"); + + ctx->argc -= 1; + ctx->argv += 1; +} + static struct action { char const *name; void (*fn)(struct action_ctx *ctx); @@ -954,6 +970,7 @@ static struct action { { .name = "labels", .fn = action_labels }, { .name = "milestone", .fn = action_milestone }, { .name = "request-review", .fn = action_request_review }, + { .name = "title", .fn = action_title }, }; static size_t const actions_size = ARRAY_SIZE(actions); From 126a0efbebbe8cd78e16c9cd0c687d5cb46107aa Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 28 Nov 2023 20:51:54 +0100 Subject: [PATCH 120/152] Add new dispatch routine for changing pull request titles and wire it into new action Issue: https://gitlab.com/herrhotzenplotz/gcli/-/issues/215 --- include/gcli/forges.h | 9 +++++++++ include/gcli/pulls.h | 3 +++ src/cmd/pulls.c | 9 ++++++++- src/pulls.c | 8 ++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 83177537..03e5c329 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -393,6 +393,15 @@ struct gcli_forge_descriptor { gcli_id pull, char const *username); + /** + * Change the title of a pull request */ + int (*pull_set_title)( + gcli_ctx *ctx, + char const *owner, + char const *repo, + gcli_id pull, + char const *new_title); + /** * Get a list of releases in the given repo */ int (*get_releases)( diff --git a/include/gcli/pulls.h b/include/gcli/pulls.h index f2fce835..b0b1d7eb 100644 --- a/include/gcli/pulls.h +++ b/include/gcli/pulls.h @@ -189,4 +189,7 @@ int gcli_pull_add_reviewer(gcli_ctx *ctx, char const *owner, char const *repo, int gcli_pull_get_patch(gcli_ctx *ctx, FILE *out, char const *owner, char const *repo, gcli_id pr_number); +int gcli_pull_set_title(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_id pull, char const *new_title); + #endif /* PULLS_H */ diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 9372f7b8..7f57594f 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -939,13 +939,20 @@ action_request_review(struct action_ctx *const ctx) static void action_title(struct action_ctx *const ctx) { + int rc = 0; + if (ctx->argc < 2) { fprintf(stderr, "error: missing title\n"); usage(); exit(EXIT_FAILURE); } - errx(1, "error: title action is not yet implemented"); + rc = gcli_pull_set_title(g_clictx, ctx->owner, ctx->repo, ctx->pr, + ctx->argv[1]); + if (rc < 0) { + errx(1, "error: failed to update review title: %s", + gcli_get_error(g_clictx)); + } ctx->argc -= 1; ctx->argv += 1; diff --git a/src/pulls.c b/src/pulls.c index ae616c2b..f9cf3935 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -213,3 +213,11 @@ gcli_pull_get_patch(gcli_ctx *ctx, FILE *out, char const *owner, char const *rep { return gcli_forge(ctx)->pull_get_patch(ctx, out, owner, repo, pull_id); } + +int +gcli_pull_set_title(gcli_ctx *ctx, char const *const owner, + char const *const repo, gcli_id const pull, + char const *new_title) +{ + return gcli_forge(ctx)->pull_set_title(ctx, owner, repo, pull, new_title); +} From 9b00f503ce5cce5191a0fb5094e18aae3674b1ec Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 28 Nov 2023 21:30:24 +0100 Subject: [PATCH 121/152] Implement updating pull request titles for Github Issue: https://gitlab.com/herrhotzenplotz/gcli/-/issues/215 --- include/gcli/github/pulls.h | 3 +++ src/forges.c | 1 + src/github/pulls.c | 39 +++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/include/gcli/github/pulls.h b/include/gcli/github/pulls.h index 2ff2cd7f..8fdb58c3 100644 --- a/include/gcli/github/pulls.h +++ b/include/gcli/github/pulls.h @@ -69,4 +69,7 @@ sn_sv github_pull_try_derive_head(void); int github_pull_add_reviewer(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id pr_number, char const *username); +int github_pull_set_title(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_id pull, char const *new_title); + #endif /* GITHUB_PULLS_H */ diff --git a/src/forges.c b/src/forges.c index cf7d3ffa..5bb637d7 100644 --- a/src/forges.c +++ b/src/forges.c @@ -118,6 +118,7 @@ github_forge_descriptor = * GitHub treats pull requests as issues */ .pull_set_milestone = github_issue_set_milestone, .pull_clear_milestone = github_issue_clear_milestone, + .pull_set_title = github_pull_set_title, .get_releases = github_get_releases, .create_release = github_create_release, diff --git a/src/github/pulls.c b/src/github/pulls.c index 6f089a0a..1acbbedc 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -460,3 +460,42 @@ github_pull_add_reviewer(gcli_ctx *ctx, char const *owner, char const *repo, return rc; } + +int +github_pull_set_title(gcli_ctx *ctx, char const *owner, char const *repo, + gcli_id pull, char const *new_title) +{ + char *url, *e_owner, *e_repo, *payload; + int rc; + gcli_jsongen gen = {0}; + + /* Generate the url */ + e_owner = gcli_urlencode(owner); + e_repo = gcli_urlencode(repo); + + url = sn_asprintf("%s/repos/%s/%s/pulls/%"PRIid, gcli_get_apibase(ctx), + e_owner, e_repo, pull); + free(e_owner); + free(e_repo); + + /* Generate the payload */ + gcli_jsongen_init(&gen); + gcli_jsongen_begin_object(&gen); + { + gcli_jsongen_objmember(&gen, "title"); + gcli_jsongen_string(&gen, new_title); + } + gcli_jsongen_end_object(&gen); + + payload = gcli_jsongen_to_string(&gen); + gcli_jsongen_free(&gen); + + /* perform request */ + rc = gcli_fetch_with_method(ctx, "PATCH", url, payload, NULL, NULL); + + /* Cleanup */ + free(payload); + free(url); + + return rc; +} From fffa5268fdabe94275070b687f06e95fcecc1abf Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 28 Nov 2023 22:02:22 +0100 Subject: [PATCH 122/152] Implement changing the title of Merge Requests for Gitlab Issue: https://gitlab.com/herrhotzenplotz/gcli/-/issues/215 --- include/gcli/gitlab/merge_requests.h | 4 +++ src/forges.c | 1 + src/gitlab/merge_requests.c | 42 ++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/include/gcli/gitlab/merge_requests.h b/include/gcli/gitlab/merge_requests.h index 6666fba7..35a8aa83 100644 --- a/include/gcli/gitlab/merge_requests.h +++ b/include/gcli/gitlab/merge_requests.h @@ -111,4 +111,8 @@ int gitlab_mr_clear_milestone(gcli_ctx *ctx, char const *owner, int gitlab_mr_add_reviewer(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id mr_number, char const *username); +int gitlab_mr_set_title(gcli_ctx *ctx, char const *const owner, + char const *const repo, gcli_id const id, + char const *const new_title); + #endif /* GITLAB_MERGE_REQUESTS_H */ diff --git a/src/forges.c b/src/forges.c index 5bb637d7..5cabe840 100644 --- a/src/forges.c +++ b/src/forges.c @@ -187,6 +187,7 @@ gitlab_forge_descriptor = .pull_set_milestone = gitlab_mr_set_milestone, .pull_clear_milestone = gitlab_mr_clear_milestone, .pull_add_reviewer = gitlab_mr_add_reviewer, + .pull_set_title = gitlab_mr_set_title, .get_releases = gitlab_get_releases, .create_release = gitlab_create_release, .delete_release = gitlab_delete_release, diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index c0798697..7b2a54a7 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -677,3 +677,45 @@ gitlab_mr_add_reviewer(gcli_ctx *ctx, char const *owner, char const *repo, return rc; } + +int +gitlab_mr_set_title(gcli_ctx *ctx, char const *const owner, + char const *const repo, gcli_id const id, + char const *const new_title) +{ + char *url, *e_owner, *e_repo, *payload; + gcli_jsongen gen = {0}; + int rc = 0; + + /* Generate url + * + * PUT /projects/:id/merge_requests/:merge_request_iid */ + e_owner = gcli_urlencode(owner); + e_repo = gcli_urlencode(repo); + + url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%"PRIid, + gcli_get_apibase(ctx), e_owner, e_repo, id); + free(e_owner); + free(e_repo); + + /* Generate payload */ + gcli_jsongen_init(&gen); + gcli_jsongen_begin_object(&gen); + { + gcli_jsongen_objmember(&gen, "title"); + gcli_jsongen_string(&gen, new_title); + } + gcli_jsongen_end_object(&gen); + + payload = gcli_jsongen_to_string(&gen); + gcli_jsongen_free(&gen); + + /* perform request */ + rc = gcli_fetch_with_method(ctx, "PUT", url, payload, NULL, NULL); + + /* clean up */ + free(url); + free(payload); + + return rc; +} From 7c1fd658ab38a868211734492e9e070f77232abc Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 28 Nov 2023 22:11:06 +0100 Subject: [PATCH 123/152] Implement updating pull request titles for Gitea Issue: https://gitlab.com/herrhotzenplotz/gcli/-/issues/215 --- include/gcli/gitea/pulls.h | 4 ++++ src/forges.c | 1 + src/gitea/pulls.c | 8 ++++++++ 3 files changed, 13 insertions(+) diff --git a/include/gcli/gitea/pulls.h b/include/gcli/gitea/pulls.h index a9a5aa63..b9cb063d 100644 --- a/include/gcli/gitea/pulls.h +++ b/include/gcli/gitea/pulls.h @@ -73,4 +73,8 @@ int gitea_pull_clear_milestone(gcli_ctx *ctx, char const *owner, int gitea_pull_add_reviewer(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id pr_number, char const *username); +int gitea_pull_set_title(gcli_ctx *ctx, char const *const owner, + char const *const repo, gcli_id pull, + char const *const title); + #endif /* GITEA_PULLS_H */ diff --git a/src/forges.c b/src/forges.c index 5cabe840..9e21bb4a 100644 --- a/src/forges.c +++ b/src/forges.c @@ -250,6 +250,7 @@ gitea_forge_descriptor = .pull_set_milestone = gitea_pull_set_milestone, .pull_clear_milestone = gitea_pull_clear_milestone, .pull_add_reviewer = gitea_pull_add_reviewer, + .pull_set_title = gitea_pull_set_title, .get_releases = gitea_get_releases, .create_release = gitea_create_release, .delete_release = gitea_delete_release, diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index b8bace7d..70cd1e47 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -199,3 +199,11 @@ gitea_pull_add_reviewer(gcli_ctx *ctx, char const *owner, char const *repo, { return github_pull_add_reviewer(ctx, owner, repo, pr_number, username); } + +int +gitea_pull_set_title(gcli_ctx *ctx, char const *const owner, + char const *const repo, gcli_id pull, + char const *const title) +{ + return github_pull_set_title(ctx, owner, repo, pull, title); +} From b129ec0157486c29b6260133f4e3417f376fcdec Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 28 Nov 2023 22:15:06 +0100 Subject: [PATCH 124/152] Update changelog for title action in pulls subcommand This feature implements changing the title of pull requests. Fixes: https://gitlab.com/herrhotzenplotz/gcli/-/issues/215 Issue: https://gitlab.com/herrhotzenplotz/gcli/-/issues/215 --- Changelog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index 12587665..f0463dbb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -21,8 +21,8 @@ This changelog does not follow semantic versioning. to allow filtering by milestones. - Add a new `patch` action to the pulls subcommand. This allows you to print the entire patch series for the given pull request. -- Add a new `title` action to the issues subcommand that allows - updating the title of an issue. +- Add a new `title` action to both the issues and the pulls + subcommand that allows updating their titles. ### Fixed From a802bdcedea589a79129fabf498496770819e9fb Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 30 Nov 2023 22:04:45 +0100 Subject: [PATCH 125/152] cmd/pulls: Fix internal documentation for merge options I incorrectly put a lower-case -d into the documentation that should inhibit deletion of the pull request source branch. However the option is actually -D (with a capital d). Fix the internal help message. --- src/cmd/pulls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/pulls.c b/src/cmd/pulls.c index 149996d0..f4afc385 100644 --- a/src/cmd/pulls.c +++ b/src/cmd/pulls.c @@ -83,7 +83,7 @@ usage(void) fprintf(stderr, " notes Alias for notes\n"); fprintf(stderr, " commits Display commits of the PR\n"); fprintf(stderr, " ci Display CI/Pipeline status information about the PR\n"); - fprintf(stderr, " merge [-s] [-D] Merge the PR (-s = squash commits, -d = inhibit deleting source branch)\n"); + fprintf(stderr, " merge [-s] [-D] Merge the PR (-s = squash commits, -D = inhibit deleting source branch)\n"); fprintf(stderr, " milestone Assign this PR to a milestone\n"); fprintf(stderr, " milestone -d Clear associated milestones from the PR\n"); fprintf(stderr, " close Close the PR\n"); From a9d058f88996b63de2b5bb2eb68d601aab5838e6 Mon Sep 17 00:00:00 2001 From: Markus Fischer Date: Fri, 1 Dec 2023 13:49:00 +0100 Subject: [PATCH 126/152] free memory leaks left by gcli_jsongen_to_string --- tests/test-jsongen.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/tests/test-jsongen.c b/tests/test-jsongen.c index b510f39f..fca41a1e 100644 --- a/tests/test-jsongen.c +++ b/tests/test-jsongen.c @@ -31,6 +31,8 @@ #include +#include + ATF_TC_WITHOUT_HEAD(empty_object); ATF_TC_BODY(empty_object, tc) { @@ -40,7 +42,9 @@ ATF_TC_BODY(empty_object, tc) ATF_REQUIRE(gcli_jsongen_begin_object(&gen) == 0); ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); - ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), "{}"); + char *str = gcli_jsongen_to_string(&gen); + ATF_CHECK_STREQ(str, "{}"); + free(str); gcli_jsongen_free(&gen); } @@ -58,7 +62,9 @@ ATF_TC_BODY(array_with_two_empty_objects, tc) } ATF_REQUIRE(gcli_jsongen_end_array(&gen) == 0); - ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), "[{}, {}]"); + char *str = gcli_jsongen_to_string(&gen); + ATF_CHECK_STREQ(str, "[{}, {}]"); + free(str); gcli_jsongen_free(&gen); } @@ -72,7 +78,9 @@ ATF_TC_BODY(empty_array, tc) ATF_REQUIRE(gcli_jsongen_begin_array(&gen) == 0); ATF_REQUIRE(gcli_jsongen_end_array(&gen) == 0); - ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), "[]"); + char *str = gcli_jsongen_to_string(&gen); + ATF_CHECK_STREQ(str, "[]"); + free(str); gcli_jsongen_free(&gen); } @@ -88,8 +96,9 @@ ATF_TC_BODY(object_with_number, tc) ATF_REQUIRE(gcli_jsongen_number(&gen, 420) == 0); ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); - ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), - "{\"number\": 420}"); + char *str = gcli_jsongen_to_string(&gen); + ATF_CHECK_STREQ(str, "{\"number\": 420}"); + free(str); gcli_jsongen_free(&gen); } @@ -111,8 +120,9 @@ ATF_TC_BODY(object_nested, tc) ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); - ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), - "{\"hiernenarray\": [69, 420], \"empty_object\": {}}"); + char *str = gcli_jsongen_to_string(&gen); + ATF_CHECK_STREQ(str, "{\"hiernenarray\": [69, 420], \"empty_object\": {}}"); + free(str); gcli_jsongen_free(&gen); } @@ -129,8 +139,9 @@ ATF_TC_BODY(object_with_strings, tc) ATF_REQUIRE(gcli_jsongen_string(&gen, "value") == 0); ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); - ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), - "{\"key\": \"value\"}"); + char *str = gcli_jsongen_to_string(&gen); + ATF_CHECK_STREQ(str, "{\"key\": \"value\"}"); + free(str); gcli_jsongen_free(&gen); } @@ -153,8 +164,9 @@ ATF_TC_BODY(object_with_mixed_values, tc) ATF_REQUIRE(gcli_jsongen_end_array(&gen) == 0); ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); - ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), - "{\"array\": [42, \"a string literal\", {}]}"); + char *str = gcli_jsongen_to_string(&gen); + ATF_CHECK_STREQ(str, "{\"array\": [42, \"a string literal\", {}]}"); + free(str); gcli_jsongen_free(&gen); } @@ -173,8 +185,9 @@ ATF_TC_BODY(object_with_two_keys_and_values_that_are_string, tc) ATF_REQUIRE(gcli_jsongen_string(&gen, "value2") == 0); ATF_REQUIRE(gcli_jsongen_end_object(&gen) == 0); - ATF_CHECK_STREQ(gcli_jsongen_to_string(&gen), - "{\"key1\": \"value1\", \"key2\": \"value2\"}"); + char *str = gcli_jsongen_to_string(&gen); + ATF_CHECK_STREQ(str, "{\"key1\": \"value1\", \"key2\": \"value2\"}"); + free(str); gcli_jsongen_free(&gen); } From 9eee5c43e8013d4bf50b5c309843b3ce0814c668 Mon Sep 17 00:00:00 2001 From: Markus Fischer Date: Fri, 1 Dec 2023 13:50:55 +0100 Subject: [PATCH 127/152] free memory leaks left by gcli_json_escape --- tests/json-escape.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/json-escape.c b/tests/json-escape.c index cf26c92a..89fd0424 100644 --- a/tests/json-escape.c +++ b/tests/json-escape.c @@ -9,6 +9,7 @@ ATF_TC_BODY(newlines, tc) sn_sv const escaped = gcli_json_escape(input); ATF_CHECK(sn_sv_eq_to(escaped, "\\n\\r")); + free(escaped.data); } ATF_TC_WITHOUT_HEAD(tabs); @@ -18,6 +19,7 @@ ATF_TC_BODY(tabs, tc) sn_sv const escaped = gcli_json_escape(input); ATF_CHECK(sn_sv_eq_to(escaped, "\\t\\t\\t")); + free(escaped.data); } ATF_TC_WITHOUT_HEAD(backslashes); @@ -27,6 +29,7 @@ ATF_TC_BODY(backslashes, tc) sn_sv const escaped = gcli_json_escape(input); ATF_CHECK(sn_sv_eq_to(escaped, "\\\\")); + free(escaped.data); } ATF_TC_WITHOUT_HEAD(torture); @@ -36,6 +39,7 @@ ATF_TC_BODY(torture, tc) sn_sv const escaped = gcli_json_escape(input); ATF_CHECK(sn_sv_eq_to(escaped, "\\n\\r\\n\\n\\n\\t{}")); + free(escaped.data); } ATF_TP_ADD_TCS(tp) From 67a2a3f9379d78e1b4a9469dbaa8f12380d9b8ee Mon Sep 17 00:00:00 2001 From: Markus Fischer Date: Fri, 1 Dec 2023 15:52:08 +0100 Subject: [PATCH 128/152] fix memory leaks in github- and gitlab-parse-tests --- include/gcli/comments.h | 1 + include/gcli/forks.h | 1 + include/gcli/github/checks.h | 2 ++ include/gcli/gitlab/pipelines.h | 1 + include/gcli/gitlab/snippets.h | 1 + include/gcli/releases.h | 2 ++ src/comments.c | 2 +- src/forks.c | 12 ++++++++--- src/github/checks.c | 16 ++++++++++----- src/gitlab/pipelines.c | 18 +++++++++++------ src/gitlab/snippets.c | 18 +++++++++++------ src/pulls.c | 1 + src/releases.c | 32 +++++++++++++++++------------ tests/github-parse-tests.c | 36 +++++++++++++++++++++++++++++++++ tests/gitlab-parse-tests.c | 36 +++++++++++++++++++++++++++++++++ 15 files changed, 145 insertions(+), 34 deletions(-) diff --git a/include/gcli/comments.h b/include/gcli/comments.h index c38850e9..73f3652e 100644 --- a/include/gcli/comments.h +++ b/include/gcli/comments.h @@ -74,4 +74,5 @@ int gcli_get_pull_comments(gcli_ctx *ctx, char const *owner, char const *repo, int gcli_comment_submit(gcli_ctx *ctx, gcli_submit_comment_opts opts); +void gcli_issue_comment_free(gcli_comment *const it); #endif /* COMMENTS_H */ diff --git a/include/gcli/forks.h b/include/gcli/forks.h index 927ff78f..902a137b 100644 --- a/include/gcli/forks.h +++ b/include/gcli/forks.h @@ -63,4 +63,5 @@ void gcli_fork_delete(char const *owner, void gcli_forks_free(gcli_fork_list *list); +void gcli_fork_free(gcli_fork *fork); #endif /* FORK_H */ diff --git a/include/gcli/github/checks.h b/include/gcli/github/checks.h index 3c06a072..b80a0a62 100644 --- a/include/gcli/github/checks.h +++ b/include/gcli/github/checks.h @@ -61,4 +61,6 @@ int github_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, void github_free_checks(github_check_list *checks); +void gcli_github_check_free(gcli_github_check *check); + #endif /* GITHUB_CHECKS_H */ diff --git a/include/gcli/gitlab/pipelines.h b/include/gcli/gitlab/pipelines.h index a3385900..0ea8c114 100644 --- a/include/gcli/gitlab/pipelines.h +++ b/include/gcli/gitlab/pipelines.h @@ -107,4 +107,5 @@ int gitlab_get_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_get_job(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id const jid, gitlab_job *const out); +void gitlab_pipeline_free(gitlab_pipeline *pipeline); #endif /* GITLAB_PIPELINES_H */ diff --git a/include/gcli/gitlab/snippets.h b/include/gcli/gitlab/snippets.h index 72ae82d3..fdedae4a 100644 --- a/include/gcli/gitlab/snippets.h +++ b/include/gcli/gitlab/snippets.h @@ -62,4 +62,5 @@ int gcli_snippet_delete(gcli_ctx *ctx, char const *snippet_id); int gcli_snippet_get(gcli_ctx *ctx, char const *snippet_id, FILE *stream); +void gcli_gitlab_snippet_free(gcli_gitlab_snippet *snippet); #endif /* GITLAB_SNIPPETS_H */ diff --git a/include/gcli/releases.h b/include/gcli/releases.h index 5992b9b6..d9b13624 100644 --- a/include/gcli/releases.h +++ b/include/gcli/releases.h @@ -99,4 +99,6 @@ int gcli_release_push_asset(gcli_ctx *, gcli_new_release *, int gcli_delete_release(gcli_ctx *ctx, char const *owner, char const *repo, char const *id); +void gcli_release_free(gcli_release *release); + #endif /* RELEASES_H */ diff --git a/src/comments.c b/src/comments.c index 5440632f..2531ef61 100644 --- a/src/comments.c +++ b/src/comments.c @@ -36,7 +36,7 @@ #include #include -static void +void gcli_issue_comment_free(gcli_comment *const it) { free((void *)it->author); diff --git a/src/forks.c b/src/forks.c index e8656064..3508b2d9 100644 --- a/src/forks.c +++ b/src/forks.c @@ -47,13 +47,19 @@ gcli_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, return gcli_forge(ctx)->fork_create(ctx, owner, repo, _in); } +void +gcli_fork_free(gcli_fork *fork) +{ + free(fork->full_name.data); + free(fork->owner.data); + free(fork->date.data); +} + void gcli_forks_free(gcli_fork_list *const list) { for (size_t i = 0; i < list->forks_size; ++i) { - free(list->forks[i].full_name.data); - free(list->forks[i].owner.data); - free(list->forks[i].date.data); + gcli_fork_free(&list->forks[i]); } free(list->forks); diff --git a/src/github/checks.c b/src/github/checks.c index 96ab3d07..d3378069 100644 --- a/src/github/checks.c +++ b/src/github/checks.c @@ -77,15 +77,21 @@ github_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, return rc; } +void +gcli_github_check_free(gcli_github_check *check) +{ + free(check->name); + free(check->status); + free(check->conclusion); + free(check->started_at); + free(check->completed_at); +} + void github_free_checks(github_check_list *const list) { for (size_t i = 0; i < list->checks_size; ++i) { - free(list->checks[i].name); - free(list->checks[i].status); - free(list->checks[i].conclusion); - free(list->checks[i].started_at); - free(list->checks[i].completed_at); + gcli_github_check_free(&list->checks[i]); } free(list->checks); diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index d725893f..5782c9cc 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -82,16 +82,22 @@ gitlab_get_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, return fetch_pipelines(ctx, url, -1, list); } +void +gitlab_pipeline_free(gitlab_pipeline *pipeline) +{ + free(pipeline->status); + free(pipeline->created_at); + free(pipeline->updated_at); + free(pipeline->ref); + free(pipeline->sha); + free(pipeline->source); +} + void gitlab_free_pipelines(gitlab_pipeline_list *const list) { for (size_t i = 0; i < list->pipelines_size; ++i) { - free(list->pipelines[i].status); - free(list->pipelines[i].created_at); - free(list->pipelines[i].updated_at); - free(list->pipelines[i].ref); - free(list->pipelines[i].sha); - free(list->pipelines[i].source); + gitlab_pipeline_free(&list->pipelines[i]); } free(list->pipelines); diff --git a/src/gitlab/snippets.c b/src/gitlab/snippets.c index 7883e0d3..c2703ab1 100644 --- a/src/gitlab/snippets.c +++ b/src/gitlab/snippets.c @@ -40,16 +40,22 @@ #include +void +gcli_gitlab_snippet_free(gcli_gitlab_snippet *snippet) +{ + free(snippet->title); + free(snippet->filename); + free(snippet->date); + free(snippet->author); + free(snippet->visibility); + free(snippet->raw_url); +} + void gcli_snippets_free(gcli_gitlab_snippet_list *const list) { for (size_t i = 0; i < list->snippets_size; ++i) { - free(list->snippets[i].title); - free(list->snippets[i].filename); - free(list->snippets[i].date); - free(list->snippets[i].author); - free(list->snippets[i].visibility); - free(list->snippets[i].raw_url); + gcli_gitlab_snippet_free(&list->snippets[i]); } free(list->snippets); diff --git a/src/pulls.c b/src/pulls.c index f9cf3935..56fda027 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -101,6 +101,7 @@ gcli_pull_free(gcli_pull *const it) free(it->head_label); free(it->base_label); free(it->head_sha); + free(it->base_sha); free(it->milestone); free(it->coverage); diff --git a/src/releases.c b/src/releases.c index d844e5b0..5beddfa6 100644 --- a/src/releases.c +++ b/src/releases.c @@ -42,22 +42,28 @@ gcli_get_releases(gcli_ctx *ctx, char const *owner, char const *repo, } void -gcli_free_releases(gcli_release_list *const list) +gcli_release_free(gcli_release *release) { - 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(release->id.data); + free(release->name.data); + free(release->body.data); + free(release->author.data); + free(release->date.data); + free(release->upload_url.data); - for (size_t j = 0; j < list->releases[i].assets_size; ++j) { - free(list->releases[i].assets[j].name); - free(list->releases[i].assets[j].url); - } + for (size_t i = 0; i < release->assets_size; ++i) { + free(release->assets[i].name); + free(release->assets[i].url); + } + + free(release->assets); +} - free(list->releases[i].assets); +void +gcli_free_releases(gcli_release_list *const list) +{ + for (size_t i = 0; i < list->releases_size; ++i) { + gcli_release_free(&list->releases[i]); } free(list->releases); diff --git a/tests/github-parse-tests.c b/tests/github-parse-tests.c index 9c611a41..b6d8f459 100644 --- a/tests/github-parse-tests.c +++ b/tests/github-parse-tests.c @@ -106,6 +106,10 @@ ATF_TC_BODY(simple_github_issue, tc) ATF_CHECK(issue.is_pr == 0); ATF_CHECK(sn_sv_null(issue.milestone)); + + json_close(&stream); + gcli_issue_free(&issue); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(simple_github_pull); @@ -142,6 +146,10 @@ ATF_TC_BODY(simple_github_pull, tc) ATF_CHECK(pull.merged == true); ATF_CHECK(pull.mergeable == false); ATF_CHECK(pull.draft == false); + + json_close(&stream); + gcli_pull_free(&pull); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(simple_github_label); @@ -161,6 +169,10 @@ ATF_TC_BODY(simple_github_label, tc) ATF_CHECK_STREQ(label.name, "bug"); ATF_CHECK_STREQ(label.description, "Something isn't working"); ATF_CHECK(label.colour == 0xd73a4a00); + + json_close(&stream); + gcli_free_label(&label); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(simple_github_milestone); @@ -186,6 +198,10 @@ ATF_TC_BODY(simple_github_milestone, tc) ATF_CHECK(milestone.expired == false); ATF_CHECK(milestone.open_issues == 0); ATF_CHECK(milestone.closed_issues == 8); + + json_close(&stream); + gcli_free_milestone(&milestone); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(simple_github_release); @@ -211,6 +227,10 @@ ATF_TC_BODY(simple_github_release, tc) ATF_CHECK_SV_EQTO(release.upload_url, "https://uploads.github.com/repos/herrhotzenplotz/gcli/releases/116031718/assets{?name,label}"); ATF_CHECK(release.draft == false); ATF_CHECK(release.prerelease == false); + + json_close(&stream); + gcli_release_free(&release); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(simple_github_repo); @@ -233,6 +253,10 @@ ATF_TC_BODY(simple_github_repo, tc) ATF_CHECK_SV_EQTO(repo.date, "2021-10-08T14:20:15Z"); ATF_CHECK_SV_EQTO(repo.visibility, "public"); ATF_CHECK(repo.is_fork == false); + + json_close(&stream); + gcli_repo_free(&repo); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(simple_github_fork); @@ -252,6 +276,10 @@ ATF_TC_BODY(simple_github_fork, tc) ATF_CHECK_SV_EQTO(fork.owner, "gjnoonan"); ATF_CHECK_SV_EQTO(fork.date, "2023-05-11T05:37:41Z"); ATF_CHECK(fork.forks == 0); + + json_close(&stream); + gcli_fork_free(&fork); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(simple_github_comment); @@ -271,6 +299,10 @@ ATF_TC_BODY(simple_github_comment, tc) 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"); + + json_close(&stream); + gcli_issue_comment_free(&comment); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(simple_github_check); @@ -292,6 +324,10 @@ ATF_TC_BODY(simple_github_check, tc) 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); + + json_close(&stream); + gcli_github_check_free(&check); + gcli_destroy(&ctx); } ATF_TP_ADD_TCS(tp) diff --git a/tests/gitlab-parse-tests.c b/tests/gitlab-parse-tests.c index c301011b..be9cf383 100644 --- a/tests/gitlab-parse-tests.c +++ b/tests/gitlab-parse-tests.c @@ -77,6 +77,10 @@ ATF_TC_BODY(gitlab_simple_merge_request, tc) ATF_CHECK(pull.merged == false); ATF_CHECK(pull.mergeable == true); ATF_CHECK(pull.draft == false); + + json_close(&stream); + gcli_pull_free(&pull); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(gitlab_simple_issue); @@ -104,6 +108,10 @@ ATF_TC_BODY(gitlab_simple_issue, tc) ATF_CHECK(issue.assignees_size == 0); ATF_CHECK(issue.is_pr == 0); ATF_CHECK(sn_sv_null(issue.milestone)); + + json_close(&stream); + gcli_issue_free(&issue); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(gitlab_simple_label); @@ -121,6 +129,10 @@ ATF_TC_BODY(gitlab_simple_label, tc) ATF_CHECK_STREQ(label.name, "bug"); ATF_CHECK_STREQ(label.description, "Something isn't working as expected"); ATF_CHECK(label.colour == 0xD73A4A00); + + json_close(&stream); + gcli_free_label(&label); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(gitlab_simple_release); @@ -170,6 +182,10 @@ ATF_TC_BODY(gitlab_simple_release, tc) ATF_CHECK(sn_sv_null(release.upload_url)); ATF_CHECK(release.draft == false); ATF_CHECK(release.prerelease == false); + + json_close(&stream); + gcli_release_free(&release); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(gitlab_simple_fork); @@ -187,6 +203,10 @@ ATF_TC_BODY(gitlab_simple_fork, tc) ATF_CHECK_SV_EQTO(fork.owner, "gjnoonan"); ATF_CHECK_SV_EQTO(fork.date, "2022-10-02T13:54:20.517Z"); ATF_CHECK(fork.forks == 0); + + json_close(&stream); + gcli_fork_free(&fork); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(gitlab_simple_milestone); @@ -210,6 +230,10 @@ ATF_TC_BODY(gitlab_simple_milestone, tc) ATF_CHECK_STREQ(milestone.updated_at, "2023-02-05T19:08:20.379Z"); ATF_CHECK(milestone.expired == false); + json_close(&stream); + gcli_free_milestone(&milestone); + gcli_destroy(&ctx); + /* Ignore open issues and closed issues as they are * github/gitea-specific */ } @@ -232,6 +256,10 @@ ATF_TC_BODY(gitlab_simple_pipeline, tc) ATF_CHECK_STREQ(pipeline.ref, "refs/merge-requests/219/head"); ATF_CHECK_STREQ(pipeline.sha, "742affb88a297a6b34201ad61c8b5b72ec6eb679"); ATF_CHECK_STREQ(pipeline.source, "merge_request_event"); + + json_close(&stream); + gitlab_pipeline_free(&pipeline); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(gitlab_simple_repo); @@ -252,6 +280,10 @@ ATF_TC_BODY(gitlab_simple_repo, tc) 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); + + json_close(&stream); + gcli_repo_free(&repo); + gcli_destroy(&ctx); } ATF_TC_WITHOUT_HEAD(gitlab_simple_snippet); @@ -272,6 +304,10 @@ ATF_TC_BODY(gitlab_simple_snippet, tc) ATF_CHECK_STREQ(snippet.author, "herrhotzenplotz"); ATF_CHECK_STREQ(snippet.visibility, "public"); ATF_CHECK_STREQ(snippet.raw_url, "https://gitlab.com/-/snippets/2141655/raw"); + + json_close(&stream); + gcli_gitlab_snippet_free(&snippet); + gcli_destroy(&ctx); } ATF_TP_ADD_TCS(tp) From 1c47228a22e815f74e54a3c08e93b71643026724 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Dec 2023 19:03:40 +0100 Subject: [PATCH 129/152] Trigger CI runs on every push --- .gitlab-ci.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9ecdc021..3115065e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,10 +2,6 @@ stages: - testing - dist -workflow: - rules: - - if: $CI_PIPELINE_SOURCE == 'merge_request_event' - alpine-amd64: stage: testing tags: From eb6a95dd3e30ec16b58e81709397e3bcd6b37bcf Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Thu, 30 Nov 2023 23:00:35 +0100 Subject: [PATCH 130/152] Update references to bug report URLs and website The main development platform is going to become Sourcehut. For this reason the references to mailing lists and other URLs have to be updated. While we're at it update the website to link to correct places for contributions and fix the link to the Debian package. --- configure.ac | 6 +++++- docs/gcli-api.1.in | 9 +++++++-- docs/gcli-comment.1.in | 9 +++++++-- docs/gcli-config.1.in | 9 +++++++-- docs/gcli-forks.1.in | 9 +++++++-- docs/gcli-gists.1.in | 9 +++++++-- docs/gcli-issues.1.in | 9 +++++++-- docs/gcli-labels.1.in | 9 +++++++-- docs/gcli-milestones.1.in | 9 +++++++-- docs/gcli-pipelines.1.in | 9 +++++++-- docs/gcli-pulls.1.in | 9 +++++++-- docs/gcli-releases.1.in | 9 +++++++-- docs/gcli-repos.1.in | 9 +++++++-- docs/gcli-snippets.1.in | 9 +++++++-- docs/gcli-status.1.in | 9 +++++++-- docs/gcli.1.in | 9 +++++++-- docs/website/index.html | 36 +++++++++++++++++++++++++----------- src/cmd/cmd.c | 4 +++- 18 files changed, 138 insertions(+), 43 deletions(-) diff --git a/configure.ac b/configure.ac index fbc3a14d..cbdee399 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,11 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([gcli],[2.1.0-devel],[nsonack@herrhotzenplotz.de],[gcli],[https://gitlab.com/herrhotzenplotz/gcli/]) +AC_INIT([gcli], + [2.1.0-devel], + [~herrhotzenplotz/gcli-discuss@lists.sr.ht], + [gcli], + [https://herrhotzenplotz.de/gcli]) AM_INIT_AUTOMAKE([1.0 foreign subdir-objects dist-bzip2 dist-xz -Wall]) dnl Release Date. diff --git a/docs/gcli-api.1.in b/docs/gcli-api.1.in index 49440b20..766fde84 100644 --- a/docs/gcli-api.1.in +++ b/docs/gcli-api.1.in @@ -34,5 +34,10 @@ $ gcli -v api -a /projects/herrhotzenplotz%2Fgcli/issues >/tmp/foo .An Nico Sonack aka. herrhotzenplotz Aq Mt nsonack@herrhotzenplotz.de and contributors. .Sh BUGS -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. diff --git a/docs/gcli-comment.1.in b/docs/gcli-comment.1.in index a1e4725c..58b34836 100644 --- a/docs/gcli-comment.1.in +++ b/docs/gcli-comment.1.in @@ -68,5 +68,10 @@ and contributors. There is no way to preview the markdown markup, however you can input markdown which will be rendered on the remote site. .Pp -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. diff --git a/docs/gcli-config.1.in b/docs/gcli-config.1.in index bd1125ef..5b186ab9 100644 --- a/docs/gcli-config.1.in +++ b/docs/gcli-config.1.in @@ -63,5 +63,10 @@ When using this feature to manage SSH keys on Github be aware that you need the scope enabled on your access token. You will receive HTTP 404 errors otherwise. .Pp -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. diff --git a/docs/gcli-forks.1.in b/docs/gcli-forks.1.in index 8458df87..698fbe55 100644 --- a/docs/gcli-forks.1.in +++ b/docs/gcli-forks.1.in @@ -96,5 +96,10 @@ $ gcli forks -y delete .An Nico Sonack aka. herrhotzenplotz Aq Mt nsonack@herrhotzenplotz.de and contributors. .Sh BUGS -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. diff --git a/docs/gcli-gists.1.in b/docs/gcli-gists.1.in index e611c0f3..4be11868 100644 --- a/docs/gcli-gists.1.in +++ b/docs/gcli-gists.1.in @@ -97,5 +97,10 @@ and contributors. This subcommand only works on GitHub. It is not implemented for GitLab, as GitLab snippets work differently. .Pp -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. diff --git a/docs/gcli-issues.1.in b/docs/gcli-issues.1.in index 43ac8f38..a0d2f158 100644 --- a/docs/gcli-issues.1.in +++ b/docs/gcli-issues.1.in @@ -176,5 +176,10 @@ $ gcli issues -i42 \\ labels remove foo .Ed .Pp -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. diff --git a/docs/gcli-labels.1.in b/docs/gcli-labels.1.in index 57e56057..085ee5e2 100644 --- a/docs/gcli-labels.1.in +++ b/docs/gcli-labels.1.in @@ -98,5 +98,10 @@ and contributors. The delete subcommand should ask for confirmation and have a flag to override this behaviour. .Pp -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. diff --git a/docs/gcli-milestones.1.in b/docs/gcli-milestones.1.in index 64cda75e..87a7c8fd 100644 --- a/docs/gcli-milestones.1.in +++ b/docs/gcli-milestones.1.in @@ -84,6 +84,11 @@ and contributors. The delete subcommand deletes the milestone without asking for confirmation. .Pp -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. diff --git a/docs/gcli-pipelines.1.in b/docs/gcli-pipelines.1.in index 7c87d387..9b585c4b 100644 --- a/docs/gcli-pipelines.1.in +++ b/docs/gcli-pipelines.1.in @@ -94,5 +94,10 @@ We are missing a .Fl a flag. This is the current implied behaviour. .Pp -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. diff --git a/docs/gcli-pulls.1.in b/docs/gcli-pulls.1.in index f5c2302a..7129c503 100644 --- a/docs/gcli-pulls.1.in +++ b/docs/gcli-pulls.1.in @@ -239,5 +239,10 @@ $ gcli -t github pu -i 42 title "This is the new title" .An Nico Sonack aka. herrhotzenplotz Aq Mt nsonack@herrhotzenplotz.de and contributors. .Sh BUGS -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. diff --git a/docs/gcli-releases.1.in b/docs/gcli-releases.1.in index 0360815d..5a07c69a 100644 --- a/docs/gcli-releases.1.in +++ b/docs/gcli-releases.1.in @@ -149,5 +149,10 @@ Prereleases and draft releases are unsupported by GitLab. Using those flags in a GitLab forge type remote will produce warnings but still create the release. .Pp -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. diff --git a/docs/gcli-repos.1.in b/docs/gcli-repos.1.in index c8c90024..c2d2bfc9 100644 --- a/docs/gcli-repos.1.in +++ b/docs/gcli-repos.1.in @@ -112,5 +112,10 @@ Currently it is only possible to create repositories for authenticated users thus it is impossible to create a repository in another organization. .Pp -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. diff --git a/docs/gcli-snippets.1.in b/docs/gcli-snippets.1.in index 586efb68..ce290b93 100644 --- a/docs/gcli-snippets.1.in +++ b/docs/gcli-snippets.1.in @@ -77,5 +77,10 @@ There is no flag to ask the user whether he is sure about deleting a snippet. .El .Pp -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. diff --git a/docs/gcli-status.1.in b/docs/gcli-status.1.in index c60b8ec6..a4bdd2ee 100644 --- a/docs/gcli-status.1.in +++ b/docs/gcli-status.1.in @@ -32,6 +32,11 @@ $ gcli -a my-account status .An Nico Sonack aka. herrhotzenplotz Aq Mt nsonack@herrhotzenplotz.de and contributors. .Sh BUGS -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. diff --git a/docs/gcli.1.in b/docs/gcli.1.in index 1ca7fbde..8535ecfa 100644 --- a/docs/gcli.1.in +++ b/docs/gcli.1.in @@ -314,8 +314,13 @@ There is an undocumented subcommand available for GitHub CI services. The subcommand is undocumented as it is not well tested and likely subject to changes. .Pp -Please report bugs at @PACKAGE_URL@, via E-Mail to @PACKAGE_BUGREPORT@ -or on Github. +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. .Pp You may also report an issue like so: .Bd -literal -offset indent diff --git a/docs/website/index.html b/docs/website/index.html index 414b2a26..267b9baa 100644 --- a/docs/website/index.html +++ b/docs/website/index.html @@ -65,32 +65,46 @@

General

  • Releases
  • Test tarballs
  • A work-in-progress tutorial
  • -
  • Gitlab +
  • Sourcehut, + Gitlab and Github
  • -

    -

    Bug Reports and Development

    - Report bugs via GitLab, - GitHub or via E-mail. - I also happily accept patches and encourage sending them through all 3 above channels. -
    - For E-Mail please refer to git-send-email. If you have never done that, I can recommend - git-send-email.io -

    GCLI is available or coming to various distributions

    If you want gcli to be available in your favourite operating system please submit them to the respective packaging tree.
    Please also tell me such that I can link to them here.

    +

    +

    Bug Reports and Development

    + Report bugs by sending an E-Mail to the mailing list. + You can view the archives on the web on Sourcehut. + We also accept bugs reportet via our mirrors on + GitLab and + GitHub, + however the mailing list is the preferred method. +
    + I also happily accept patches and encourage sending to our development mailing list. + Its archives can also be viewed on the web on Sourcehut. + Alternatively you can send patches to our mirrors on Gitlab and Github too, however the mailing list is the preferred method. +
    + For sending patches via E-Mail please refer to git-send-email. + If you have never done that, I can recommend git-send-email.io +
    + If you are using Mercurial, you can refer to + Sourcehut's documentation for patchbomb. +
    + For questions or general discussions about patches and bugs you can join the IRC channel + #gcli on Libera.Chat. +

    The CSS on this page is stolen and edited from diff --git a/src/cmd/cmd.c b/src/cmd/cmd.c index f2523e31..dd491c66 100644 --- a/src/cmd/cmd.c +++ b/src/cmd/cmd.c @@ -55,7 +55,9 @@ version(void) PACKAGE_STRING" ("HOSTOS")\n" "Using %s\n" "Using vendored pdjson library\n" - "Report bugs at "PACKAGE_URL".\n", + "\n" + "Project website: "PACKAGE_URL"\n" + "Bug reports: "PACKAGE_BUGREPORT"\n", curl_version()); } From 6444f97a0e655e0b1c9c33bc6949b9ad7f97034a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Dec 2023 19:49:17 +0100 Subject: [PATCH 131/152] Fix typo on website --- docs/website/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/website/index.html b/docs/website/index.html index 267b9baa..40b2641a 100644 --- a/docs/website/index.html +++ b/docs/website/index.html @@ -87,7 +87,7 @@

    GCLI is available or coming to various distributions

    Bug Reports and Development

    Report bugs by sending an E-Mail to
    the mailing list. You can view the archives on the web on Sourcehut. - We also accept bugs reportet via our mirrors on + We also accept bugs reported via our mirrors on GitLab and GitHub, however the mailing list is the preferred method. From 04dbfa7deb2cbb322e81536f0ce70cd39ccae82a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 14:55:50 +0100 Subject: [PATCH 132/152] Fix a couple of groff warnings in manual pages reported by Lintian Lintian was reporting a few issues with the manual pages on udd: https://udd.debian.org/lintian/?packages=gcli --- docs/gcli-forks.1.in | 1 - docs/gcli-gists.1.in | 1 + docs/gcli-milestones.1.in | 1 - docs/gcli-pipelines.1.in | 1 - docs/gcli-releases.1.in | 1 + docs/gcli-repos.1.in | 1 - docs/gcli-snippets.1.in | 1 + docs/gcli-status.1.in | 1 - 8 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/gcli-forks.1.in b/docs/gcli-forks.1.in index 698fbe55..ec4449b7 100644 --- a/docs/gcli-forks.1.in +++ b/docs/gcli-forks.1.in @@ -47,7 +47,6 @@ to -1 will fetch all forks. Default: 30. Note that on repositories with many forks fetching all forks can take a considerable amount of time and may result in rate limiting by the respective API. .El -.El .Sh ACTIONS .Ar actions... may be one or more of the following: diff --git a/docs/gcli-gists.1.in b/docs/gcli-gists.1.in index 4be11868..b75b9498 100644 --- a/docs/gcli-gists.1.in +++ b/docs/gcli-gists.1.in @@ -65,6 +65,7 @@ Do not ask for confirmation before deleting the Gist. Assume yes. .El .It Cm get Download a file from a Gist. There are no options to this subcommand. +.El .Sh EXAMPLES List neutaaaaan's Gists: .Bd -literal -offset indent diff --git a/docs/gcli-milestones.1.in b/docs/gcli-milestones.1.in index 87a7c8fd..949a7b1d 100644 --- a/docs/gcli-milestones.1.in +++ b/docs/gcli-milestones.1.in @@ -91,4 +91,3 @@ Alternatively you can report them on any of the forges linked at .Lk @PACKAGE_URL@ . However, the preferred and quickest method is to use the mailing list. - diff --git a/docs/gcli-pipelines.1.in b/docs/gcli-pipelines.1.in index 9b585c4b..4680d80f 100644 --- a/docs/gcli-pipelines.1.in +++ b/docs/gcli-pipelines.1.in @@ -82,7 +82,6 @@ Dump the log of Job #423141 in herrhotzenplotz/gcli: .Bd -literal -offset indent $ gcli pipelines -o herrhotzenplotz -r gcli -j 423141 log .Ed -.Ed .Sh SEE ALSO .Xr git 1 , .Xr gcli 1 diff --git a/docs/gcli-releases.1.in b/docs/gcli-releases.1.in index 5a07c69a..bd8fd56f 100644 --- a/docs/gcli-releases.1.in +++ b/docs/gcli-releases.1.in @@ -114,6 +114,7 @@ not your own account. Do not ask for confirmation before deleting the repository. Assume yes. .El +.El .Sh EXAMPLES Delete release with ID 54656866 in herrhotzenplotz/gcli-playground without asking for confirmation: diff --git a/docs/gcli-repos.1.in b/docs/gcli-repos.1.in index c2d2bfc9..95210edf 100644 --- a/docs/gcli-repos.1.in +++ b/docs/gcli-repos.1.in @@ -60,7 +60,6 @@ Set the description of a repo to be created. .It Fl p , -private Create a private repo. .El -.El .Sh ACTIONS .Ar actions... may be one or more of the following: diff --git a/docs/gcli-snippets.1.in b/docs/gcli-snippets.1.in index ce290b93..b4fd9ad7 100644 --- a/docs/gcli-snippets.1.in +++ b/docs/gcli-snippets.1.in @@ -43,6 +43,7 @@ time and may result in rate limiting by the GitLab API. Delete a snippet. .It Cm get Fetch the raw contents of the snippet. +.El .Sh EXAMPLES List all of your snippets: .Bd -literal -offset indent diff --git a/docs/gcli-status.1.in b/docs/gcli-status.1.in index a4bdd2ee..2ced9c66 100644 --- a/docs/gcli-status.1.in +++ b/docs/gcli-status.1.in @@ -39,4 +39,3 @@ Alternatively you can report them on any of the forges linked at .Lk @PACKAGE_URL@ . However, the preferred and quickest method is to use the mailing list. - From d507e8aed2e68e005e373d12d2b96269ccf6cd5a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Dec 2023 17:38:26 +0100 Subject: [PATCH 133/152] Rename gcli_comment* free routines This is done for consistency reasons, in general our API functions are called gcli__free for a single thing and for a list of things they are called gcli_s_free. Rename the routine and call sites appropriately. --- include/gcli/comments.h | 5 +++-- src/cmd/comment.c | 4 ++-- src/comments.c | 12 ++++++------ tests/github-parse-tests.c | 2 +- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/include/gcli/comments.h b/include/gcli/comments.h index 73f3652e..8ec2181a 100644 --- a/include/gcli/comments.h +++ b/include/gcli/comments.h @@ -64,7 +64,9 @@ struct gcli_submit_comment_opts { sn_sv message; }; -void gcli_comment_list_free(gcli_comment_list *list); +void gcli_comments_free(gcli_comment_list *list); + +void gcli_comment_free(gcli_comment *const it); int gcli_get_issue_comments(gcli_ctx *ctx, char const *owner, char const *repo, int issue, gcli_comment_list *out); @@ -74,5 +76,4 @@ int gcli_get_pull_comments(gcli_ctx *ctx, char const *owner, char const *repo, int gcli_comment_submit(gcli_ctx *ctx, gcli_submit_comment_opts opts); -void gcli_issue_comment_free(gcli_comment *const it); #endif /* COMMENTS_H */ diff --git a/src/cmd/comment.c b/src/cmd/comment.c index 20463444..244d3c46 100644 --- a/src/cmd/comment.c +++ b/src/cmd/comment.c @@ -130,7 +130,7 @@ gcli_issue_comments(char const *owner, char const *repo, int const issue) return rc; gcli_print_comment_list(&list); - gcli_comment_list_free(&list); + gcli_comments_free(&list); return rc; } @@ -146,7 +146,7 @@ gcli_pull_comments(char const *owner, char const *repo, int const pull) return rc; gcli_print_comment_list(&list); - gcli_comment_list_free(&list); + gcli_comments_free(&list); return rc; } diff --git a/src/comments.c b/src/comments.c index 2531ef61..45cd8827 100644 --- a/src/comments.c +++ b/src/comments.c @@ -37,18 +37,18 @@ #include void -gcli_issue_comment_free(gcli_comment *const it) +gcli_comment_free(gcli_comment *const it) { - free((void *)it->author); - free((void *)it->date); - free((void *)it->body); + free(it->author); + free(it->date); + free(it->body); } void -gcli_comment_list_free(gcli_comment_list *list) +gcli_comments_free(gcli_comment_list *const list) { for (size_t i = 0; i < list->comments_size; ++i) - gcli_issue_comment_free(&list->comments[i]); + gcli_comment_free(&list->comments[i]); free(list->comments); list->comments = NULL; diff --git a/tests/github-parse-tests.c b/tests/github-parse-tests.c index b6d8f459..ff3ba52a 100644 --- a/tests/github-parse-tests.c +++ b/tests/github-parse-tests.c @@ -301,7 +301,7 @@ 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"); json_close(&stream); - gcli_issue_comment_free(&comment); + gcli_comment_free(&comment); gcli_destroy(&ctx); } From 1bc7ebdf86c12a00dab78c73d4b1199ea7ede148 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 1 Dec 2023 18:13:26 +0100 Subject: [PATCH 134/152] Rename gitlab_pipeline*_free routines Rename them to be consistent with our naming scheme. In the future we might rename these to be prefixed with gcli_ as well. --- include/gcli/gitlab/pipelines.h | 5 ++--- src/cmd/pipelines.c | 4 ++-- src/gitlab/pipelines.c | 2 +- src/pulls.c | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/include/gcli/gitlab/pipelines.h b/include/gcli/gitlab/pipelines.h index 0ea8c114..05fe6cef 100644 --- a/include/gcli/gitlab/pipelines.h +++ b/include/gcli/gitlab/pipelines.h @@ -79,7 +79,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_free_pipelines(gitlab_pipeline_list *list); +void gitlab_pipeline_free(gitlab_pipeline *pipeline); +void gitlab_pipelines_free(gitlab_pipeline_list *list); int gitlab_get_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id pipeline, int count, gitlab_job_list *out); @@ -87,7 +88,6 @@ int gitlab_get_pipeline_jobs(gcli_ctx *ctx, char const *owner, char const *repo, 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, gcli_id job_id, FILE *stream); @@ -107,5 +107,4 @@ int gitlab_get_mr_pipelines(gcli_ctx *ctx, char const *owner, char const *repo, int gitlab_get_job(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id const jid, gitlab_job *const out); -void gitlab_pipeline_free(gitlab_pipeline *pipeline); #endif /* GITLAB_PIPELINES_H */ diff --git a/src/cmd/pipelines.c b/src/cmd/pipelines.c index 6d5649d6..92e2188a 100644 --- a/src/cmd/pipelines.c +++ b/src/cmd/pipelines.c @@ -79,7 +79,7 @@ gitlab_mr_pipelines(char const *owner, char const *repo, int const mr_id) if (rc == 0) gitlab_print_pipelines(&list); - gitlab_free_pipelines(&list); + gitlab_pipelines_free(&list); return rc; } @@ -128,7 +128,7 @@ gitlab_pipelines(char const *owner, char const *repo, int const count) return rc; gitlab_print_pipelines(&pipelines); - gitlab_free_pipelines(&pipelines); + gitlab_pipelines_free(&pipelines); return rc; } diff --git a/src/gitlab/pipelines.c b/src/gitlab/pipelines.c index 5782c9cc..a29df0ac 100644 --- a/src/gitlab/pipelines.c +++ b/src/gitlab/pipelines.c @@ -94,7 +94,7 @@ gitlab_pipeline_free(gitlab_pipeline *pipeline) } void -gitlab_free_pipelines(gitlab_pipeline_list *const list) +gitlab_pipelines_free(gitlab_pipeline_list *const list) { for (size_t i = 0; i < list->pipelines_size; ++i) { gitlab_pipeline_free(&list->pipelines[i]); diff --git a/src/pulls.c b/src/pulls.c index 56fda027..5655cde4 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -133,7 +133,7 @@ gcli_pull_checks_free(gcli_pull_checks_list *list) github_free_checks((github_check_list *)list); break; case GCLI_FORGE_GITLAB: - gitlab_free_pipelines((gitlab_pipeline_list *)list); + gitlab_pipelines_free((gitlab_pipeline_list *)list); break; default: assert(0 && "unreachable"); From f5d9ab97da5eb8b7f20ef1b42b2c5df49b3e54e0 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 17:02:34 +0100 Subject: [PATCH 135/152] Sort forge dispatch table First step in cleaning up this table: Order by groups and sort alphabetically. Issue: https://gitlab.com/herrhotzenplotz/gcli/-/issues/212 --- src/forges.c | 233 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 145 insertions(+), 88 deletions(-) diff --git a/src/forges.c b/src/forges.c index 9e21bb4a..5548f199 100644 --- a/src/forges.c +++ b/src/forges.c @@ -74,212 +74,269 @@ static gcli_forge_descriptor const github_forge_descriptor = { - .perform_submit_comment = github_perform_submit_comment, + /* Comments */ .get_issue_comments = github_get_comments, .get_pull_comments = github_get_comments, - .get_forks = github_get_forks, + .perform_submit_comment = github_perform_submit_comment, + + /* Forks */ .fork_create = github_fork_create, - .get_issues = github_get_issues, + .get_forks = github_get_forks, + + /* Issues */ .get_issue_summary = github_get_issue_summary, - .issue_close = github_issue_close, - .issue_reopen = github_issue_reopen, - .issue_assign = github_issue_assign, + .get_issues = github_get_issues, .issue_add_labels = github_issue_add_labels, + .issue_assign = github_issue_assign, + .issue_clear_milestone = github_issue_clear_milestone, + .issue_close = github_issue_close, .issue_remove_labels = github_issue_remove_labels, - .perform_submit_issue = github_perform_submit_issue, + .issue_reopen = github_issue_reopen, .issue_set_milestone = github_issue_set_milestone, - .issue_clear_milestone = github_issue_clear_milestone, .issue_set_title = github_issue_set_title, - .get_milestones = github_get_milestones, - .get_milestone = github_get_milestone, + .perform_submit_issue = github_perform_submit_issue, + + /* Milestones */ .create_milestone = github_create_milestone, .delete_milestone = github_delete_milestone, - .milestone_set_duedate = github_milestone_set_duedate, + .get_milestone = github_get_milestone, .get_milestone_issues = github_milestone_get_issues, + .get_milestones = github_get_milestones, + .milestone_set_duedate = github_milestone_set_duedate, + + /* Pull requests */ + .get_pull = github_get_pull, + .get_pull_checks = github_pull_get_checks, + .get_pull_commits = github_get_pull_commits, .get_pulls = github_get_pulls, + .perform_submit_pull = github_perform_submit_pull, .print_pull_diff = github_print_pull_diff, - .get_pull_checks = github_pull_get_checks, + .pull_add_reviewer = github_pull_add_reviewer, + .pull_close = github_pull_close, .pull_merge = github_pull_merge, .pull_reopen = github_pull_reopen, - .pull_close = github_pull_close, + .pull_set_title = github_pull_set_title, /* 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 */ .pull_add_labels = github_issue_add_labels, + .pull_clear_milestone = github_issue_clear_milestone, .pull_remove_labels = github_issue_remove_labels, - .pull_add_reviewer = github_pull_add_reviewer, - - .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 */ .pull_set_milestone = github_issue_set_milestone, - .pull_clear_milestone = github_issue_clear_milestone, - .pull_set_title = github_pull_set_title, - .get_releases = github_get_releases, + /* Releases */ .create_release = github_create_release, .delete_release = github_delete_release, - .get_labels = github_get_labels, + .get_releases = github_get_releases, + + /* Labels */ .create_label = github_create_label, .delete_label = github_delete_label, + .get_labels = github_get_labels, + + /* Repos */ .get_repos = github_get_repos, - .repo_set_visibility = github_repo_set_visibility, .get_reviews = github_review_get_reviews, .repo_create = github_repo_create, .repo_delete = github_repo_delete, + .repo_set_visibility = github_repo_set_visibility, - .get_sshkeys = github_get_sshkeys, + /* SSH Key management */ .add_sshkey = github_add_sshkey, .delete_sshkey = github_delete_sshkey, + .get_sshkeys = github_get_sshkeys, + /* Notifications */ .get_notifications = github_get_notifications, .notification_mark_as_read = github_notification_mark_as_read, - .make_authheader = github_make_authheader, + + /* Internal stuff */ .get_api_error_string = github_api_error_string, + .make_authheader = github_make_authheader, .user_object_key = "login", - .pull_summary_quirks = GCLI_PRS_QUIRK_COVERAGE, + + /* Quirks */ .milestone_quirks = GCLI_MILESTONE_QUIRKS_EXPIRED | GCLI_MILESTONE_QUIRKS_DUEDATE | GCLI_MILESTONE_QUIRKS_PULLS, + .pull_summary_quirks = GCLI_PRS_QUIRK_COVERAGE, }; static gcli_forge_descriptor const gitlab_forge_descriptor = { - .perform_submit_comment = gitlab_perform_submit_comment, + /* Comments */ .get_issue_comments = gitlab_get_issue_comments, .get_pull_comments = gitlab_get_mr_comments, - .get_forks = gitlab_get_forks, + .perform_submit_comment = gitlab_perform_submit_comment, + + /* Forks */ .fork_create = gitlab_fork_create, - .get_issues = gitlab_get_issues, + .get_forks = gitlab_get_forks, + + /* Issues */ .get_issue_summary = gitlab_get_issue_summary, - .issue_close = gitlab_issue_close, - .issue_reopen = gitlab_issue_reopen, - .issue_assign = gitlab_issue_assign, + .get_issues = gitlab_get_issues, .issue_add_labels = gitlab_issue_add_labels, + .issue_assign = gitlab_issue_assign, + .issue_clear_milestone = gitlab_issue_clear_milestone, + .issue_close = gitlab_issue_close, .issue_remove_labels = gitlab_issue_remove_labels, - .perform_submit_issue = gitlab_perform_submit_issue, + .issue_reopen = gitlab_issue_reopen, + .issue_set_milestone = gitlab_issue_set_milestone, .issue_set_title = gitlab_issue_set_title, - .get_milestones = gitlab_get_milestones, - .get_milestone = gitlab_get_milestone, + .perform_submit_issue = gitlab_perform_submit_issue, + + /* Milestones */ .create_milestone = gitlab_create_milestone, .delete_milestone = gitlab_delete_milestone, - .milestone_set_duedate = gitlab_milestone_set_duedate, + .get_milestone = gitlab_get_milestone, .get_milestone_issues = gitlab_milestone_get_issues, - .issue_set_milestone = gitlab_issue_set_milestone, - .issue_clear_milestone = gitlab_issue_clear_milestone, + .get_milestones = gitlab_get_milestones, + .milestone_set_duedate = gitlab_milestone_set_duedate, + + /* Pull requests */ + .get_pull = gitlab_get_pull, + .get_pull_checks = (gcli_get_pull_checks_cb)gitlab_get_mr_pipelines, + .get_pull_commits = gitlab_get_pull_commits, .get_pulls = gitlab_get_mrs, + .perform_submit_pull = gitlab_perform_submit_mr, .print_pull_diff = gitlab_print_pr_diff, + .pull_add_labels = gitlab_mr_add_labels, + .pull_add_reviewer = gitlab_mr_add_reviewer, + .pull_clear_milestone = gitlab_mr_clear_milestone, + .pull_close = gitlab_mr_close, .pull_get_patch = gitlab_print_pr_patch, - .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, - .perform_submit_pull = gitlab_perform_submit_mr, - .get_pull_commits = gitlab_get_pull_commits, - .get_pull = gitlab_get_pull, - .pull_add_labels = gitlab_mr_add_labels, .pull_remove_labels = gitlab_mr_remove_labels, + .pull_reopen = gitlab_mr_reopen, .pull_set_milestone = gitlab_mr_set_milestone, - .pull_clear_milestone = gitlab_mr_clear_milestone, - .pull_add_reviewer = gitlab_mr_add_reviewer, .pull_set_title = gitlab_mr_set_title, - .get_releases = gitlab_get_releases, + + /* Releases */ .create_release = gitlab_create_release, .delete_release = gitlab_delete_release, - .get_labels = gitlab_get_labels, + .get_releases = gitlab_get_releases, + + /* Labels */ .create_label = gitlab_create_label, .delete_label = gitlab_delete_label, + .get_labels = gitlab_get_labels, + + /* Repos */ .get_repos = gitlab_get_repos, .get_reviews = gitlab_review_get_reviews, .repo_create = gitlab_repo_create, .repo_delete = gitlab_repo_delete, .repo_set_visibility = gitlab_repo_set_visibility, - .get_notifications = gitlab_get_notifications, - .notification_mark_as_read = gitlab_notification_mark_as_read, - .make_authheader = gitlab_make_authheader, - .get_sshkeys = gitlab_get_sshkeys, + + /* SSH Key management */ .add_sshkey = gitlab_add_sshkey, .delete_sshkey = gitlab_delete_sshkey, + .get_sshkeys = gitlab_get_sshkeys, + + /* Notifications */ + .get_notifications = gitlab_get_notifications, + .notification_mark_as_read = gitlab_notification_mark_as_read, + + /* Internal stuff */ .get_api_error_string = gitlab_api_error_string, + .make_authheader = gitlab_make_authheader, .user_object_key = "username", + + /* Quirks */ + .milestone_quirks = GCLI_MILESTONE_QUIRKS_NISSUES, .pull_summary_quirks = GCLI_PRS_QUIRK_ADDDEL | GCLI_PRS_QUIRK_COMMITS | GCLI_PRS_QUIRK_CHANGES | GCLI_PRS_QUIRK_MERGED, - .milestone_quirks = GCLI_MILESTONE_QUIRKS_NISSUES, }; static gcli_forge_descriptor const gitea_forge_descriptor = { - .get_issues = gitea_get_issues, + /* Comments */ + .get_issue_comments = gitea_get_comments, + .get_pull_comments = gitea_get_comments, + .perform_submit_comment = gitea_perform_submit_comment, + + /* Forks */ + .get_forks = gitea_get_forks, + + /* Issues */ .get_issue_summary = gitea_get_issue_summary, - .perform_submit_issue = gitea_submit_issue, + .get_issues = gitea_get_issues, + .issue_add_labels = gitea_issue_add_labels, + .issue_assign = gitea_issue_assign, + .issue_clear_milestone = gitea_issue_clear_milestone, .issue_close = gitea_issue_close, + .issue_remove_labels = gitea_issue_remove_labels, .issue_reopen = gitea_issue_reopen, - .issue_assign = gitea_issue_assign, .issue_set_milestone = gitea_issue_set_milestone, - .issue_clear_milestone = gitea_issue_clear_milestone, .issue_set_title = gitea_issue_set_title, - .get_issue_comments = gitea_get_comments, - .get_milestones = gitea_get_milestones, - .get_milestone = gitea_get_milestone, + .perform_submit_issue = gitea_submit_issue, + + /* Milestones */ .create_milestone = gitea_create_milestone, .delete_milestone = gitea_delete_milestone, - .milestone_set_duedate = gitea_milestone_set_duedate, + .get_milestone = gitea_get_milestone, .get_milestone_issues = gitea_milestone_get_issues, - .perform_submit_comment = gitea_perform_submit_comment, - .issue_add_labels = gitea_issue_add_labels, - .issue_remove_labels = gitea_issue_remove_labels, - .get_labels = gitea_get_labels, - .create_label = gitea_create_label, - .delete_label = gitea_delete_label, - .get_pulls = gitea_get_pulls, + .get_milestones = gitea_get_milestones, + .milestone_set_duedate = gitea_milestone_set_duedate, + + /* Pull requests */ + .get_pull = gitea_get_pull, .get_pull_checks = gitea_pull_get_checks, /* stub, will always return an error */ + .get_pull_commits = gitea_get_pull_commits, + .get_pulls = gitea_get_pulls, + .perform_submit_pull = gitea_pull_submit, + .print_pull_diff = gitea_print_pr_diff, + .pull_add_labels = gitea_issue_add_labels, + .pull_add_reviewer = gitea_pull_add_reviewer, + .pull_clear_milestone = gitea_pull_clear_milestone, + .pull_close = gitea_pull_close, .pull_merge = gitea_pull_merge, + .pull_remove_labels = gitea_issue_remove_labels, .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, .pull_set_milestone = gitea_pull_set_milestone, - .pull_clear_milestone = gitea_pull_clear_milestone, - .pull_add_reviewer = gitea_pull_add_reviewer, .pull_set_title = gitea_pull_set_title, - .get_releases = gitea_get_releases, + + /* Releases */ .create_release = gitea_create_release, .delete_release = gitea_delete_release, - .perform_submit_pull = gitea_pull_submit, - .print_pull_diff = gitea_print_pr_diff, - .get_forks = gitea_get_forks, + .get_releases = gitea_get_releases, - /* Same procedure as with Github (see comment up there) */ - .pull_add_labels = gitea_issue_add_labels, - .pull_remove_labels = gitea_issue_remove_labels, + /* Labels */ + .create_label = gitea_create_label, + .delete_label = gitea_delete_label, + .get_labels = gitea_get_labels, + + /* Repos */ .get_repos = gitea_get_repos, .repo_create = gitea_repo_create, .repo_delete = gitea_repo_delete, .repo_set_visibility = gitea_repo_set_visibility, - .get_sshkeys = gitea_get_sshkeys, + /* SSH Key management */ .add_sshkey = gitea_add_sshkey, .delete_sshkey = gitea_delete_sshkey, + .get_sshkeys = gitea_get_sshkeys, + /* Notifications */ + /* Internal stuff */ .make_authheader = gitea_make_authheader, .get_api_error_string = github_api_error_string, /* hack! */ .user_object_key = "username", + + /* Quirks */ + .milestone_quirks = GCLI_MILESTONE_QUIRKS_EXPIRED + | GCLI_MILESTONE_QUIRKS_PULLS, .pull_summary_quirks = GCLI_PRS_QUIRK_COMMITS | GCLI_PRS_QUIRK_ADDDEL | GCLI_PRS_QUIRK_DRAFT | GCLI_PRS_QUIRK_CHANGES | GCLI_PRS_QUIRK_COVERAGE, - .milestone_quirks = GCLI_MILESTONE_QUIRKS_EXPIRED - | GCLI_MILESTONE_QUIRKS_PULLS, }; gcli_forge_descriptor const * From 82287fe7afa840b9494e3015bb1376adb8adb6aa Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 17:08:46 +0100 Subject: [PATCH 136/152] Remove unused review code These files should have originally been removed during the big refactor (passing the gcli_ctx * everywhere) but apparently I forgot about it. --- Makefile.am | 7 +- include/gcli/forges.h | 7 - include/gcli/github/review.h | 43 ------ include/gcli/gitlab/review.h | 43 ------ include/gcli/review.h | 83 ------------ src/forges.c | 4 - src/github/review.c | 253 ----------------------------------- src/gitlab/review.c | 59 -------- src/review.c | 83 ------------ templates/gitlab/review.t | 11 -- 10 files changed, 1 insertion(+), 592 deletions(-) delete mode 100644 include/gcli/github/review.h delete mode 100644 include/gcli/gitlab/review.h delete mode 100644 include/gcli/review.h delete mode 100644 src/github/review.c delete mode 100644 src/gitlab/review.c delete mode 100644 src/review.c delete mode 100644 templates/gitlab/review.t diff --git a/Makefile.am b/Makefile.am index ca456aeb..cb12a18f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -114,7 +114,6 @@ TEMPLATES = \ templates/gitlab/pipelines.t \ templates/gitlab/releases.t \ templates/gitlab/repos.t \ - templates/gitlab/review.t \ templates/gitlab/sshkeys.t \ templates/gitlab/status.t \ templates/gitlab/snippets.t \ @@ -125,8 +124,7 @@ 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/repos.h include/gcli/gitlab/snippets.h \ include/gcli/status.h include/gcli/sshkeys.h pkgconfdir = $(libdir)/pkgconfig @@ -148,7 +146,6 @@ libgcli_la_SOURCES = \ src/pulls.c include/gcli/pulls.h \ src/releases.c include/gcli/releases.h \ src/repos.c include/gcli/repos.h \ - src/review.c include/gcli/review.h \ src/gitlab/snippets.c include/gcli/gitlab/snippets.h \ src/status.c include/gcli/status.h \ src/sshkeys.c include/gcli/sshkeys.h \ @@ -163,7 +160,6 @@ libgcli_la_SOURCES = \ src/gitlab/pipelines.c include/gcli/gitlab/pipelines.h \ src/gitlab/releases.c include/gcli/gitlab/releases.h \ src/gitlab/repos.c include/gcli/gitlab/repos.h \ - src/gitlab/review.c include/gcli/gitlab/review.h \ src/gitlab/status.c include/gcli/gitlab/status.h \ src/gitlab/sshkeys.c include/gcli/gitlab/sshkeys.h \ src/github/releases.c include/gcli/github/releases.h \ @@ -177,7 +173,6 @@ libgcli_la_SOURCES = \ src/github/labels.c include/gcli/github/labels.h \ src/github/milestones.c include/gcli/github/milestones.h \ src/github/issues.c include/gcli/github/issues.h \ - src/github/review.c include/gcli/github/review.h \ src/github/checks.c include/gcli/github/checks.h \ src/github/gists.c include/gcli/github/gists.h \ src/github/sshkeys.c include/gcli/github/sshkeys.h \ diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 03e5c329..0209a242 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include @@ -482,12 +481,6 @@ struct gcli_forge_descriptor { char const *repo, gcli_repo_visibility vis); - /** - * Fetch MR/PR reviews including comments */ - int (*get_reviews)( - gcli_ctx *ctx, char const *owner, char const *repo, - gcli_id pr, gcli_pr_review_list *out); - /** * Status summary for the account */ int (*get_notifications)( diff --git a/include/gcli/github/review.h b/include/gcli/github/review.h deleted file mode 100644 index 4a1b6008..00000000 --- a/include/gcli/github/review.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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. - */ - -#ifndef GITHUB_REVIEW_H -#define GITHUB_REVIEW_H - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -int github_review_get_reviews(gcli_ctx *ctx, char const *owner, - char const *repo, gcli_id pr, - gcli_pr_review_list *out); - -#endif /* GITHUB_REVIEW_H */ diff --git a/include/gcli/gitlab/review.h b/include/gcli/gitlab/review.h deleted file mode 100644 index f4ae097d..00000000 --- a/include/gcli/gitlab/review.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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. - */ - -#ifndef GITLAB_REVIEW_H -#define GITLAB_REVIEW_H - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -int gitlab_review_get_reviews(gcli_ctx *cxt, char const *owner, - char const *repo, gcli_id mr_number, - gcli_pr_review_list *out); - -#endif /* GITLAB_REVIEW_H */ diff --git a/include/gcli/review.h b/include/gcli/review.h deleted file mode 100644 index 3669a4f9..00000000 --- a/include/gcli/review.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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. - */ - -#ifndef REVIEW_H -#define REVIEW_H - -#ifdef HAVE_CONFIG_H -#include -#endif - -#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; - -struct gcli_pr_review_comment { - char *id; - char *author; - char *date; - char *diff; - char *path; - char *body; - int original_position; -}; - -struct gcli_pr_review { - char *id; - char *author; - char *date; - char *state; - char *body; - gcli_pr_review_comment *comments; - size_t comments_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(gcli_ctx *ctx, char const *owner, char const *repo, - int pr, gcli_pr_review_list *out); - -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); - -#endif /* REVIEW_H */ diff --git a/src/forges.c b/src/forges.c index 5548f199..7051c57a 100644 --- a/src/forges.c +++ b/src/forges.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include @@ -56,7 +55,6 @@ #include #include #include -#include #include #include @@ -137,7 +135,6 @@ github_forge_descriptor = /* Repos */ .get_repos = github_get_repos, - .get_reviews = github_review_get_reviews, .repo_create = github_repo_create, .repo_delete = github_repo_delete, .repo_set_visibility = github_repo_set_visibility, @@ -226,7 +223,6 @@ gitlab_forge_descriptor = /* Repos */ .get_repos = gitlab_get_repos, - .get_reviews = gitlab_review_get_reviews, .repo_create = gitlab_repo_create, .repo_delete = gitlab_repo_delete, .repo_set_visibility = gitlab_repo_set_visibility, diff --git a/src/github/review.c b/src/github/review.c deleted file mode 100644 index 674aca2d..00000000 --- a/src/github/review.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * 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 -#include - -#include - -static int -github_parse_review_comment(gcli_ctx *ctx, json_stream *input, - gcli_pr_review_comment *it) -{ - if (json_next(input) != JSON_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; - char const *key = json_get_string(input, &len); - - 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 int -github_parse_review_comments(gcli_ctx *ctx, json_stream *input, - gcli_pr_review *it) -{ - 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}; - - if (github_parse_review_comment(ctx, input, comment) < 0) - return -1; - } - - if (gcli_json_advance(ctx, input, "]}") < 0) - return -1; - - return 0; -} - -static int -github_parse_review_header(gcli_ctx *ctx, json_stream *input, - gcli_pr_review *it) -{ - if (json_next(input) != JSON_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) { - 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 = - "query {" - " repository(owner: \"%s\", name: \"%s\") {" - " pullRequest(number: %d) {" - " reviews(first: 10) {" - " nodes {" - " author {" - " login" - " }" - " bodyText" - " id" - " createdAt" - " state" - " comments(first: 10) {" - " nodes {" - " bodyText" - " diffHunk" - " path" - " originalPosition" - " author {" - " login" - " }" - " state" - " createdAt" - " id" - " }" - " }" - " }" - " }" - " }" - " }" - "}"; - -int -github_review_get_reviews(gcli_ctx *ctx, char const *owner, char const *repo, - gcli_id const pr, gcli_pr_review_list *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; - int rc = 0; - - 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(ctx, "POST", url, post_data, NULL, &buffer); - free(url); - free(query); - free(query_escaped.data); - free(post_data); - - if (rc < 0) - goto error_fetch; - - json_open_buffer(&stream, buffer.data, buffer.length); - json_set_streaming(&stream, true); - - 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) { - 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, - sizeof(gcli_pr_review) * (out->reviews_size + 1)); - gcli_pr_review *it = &out->reviews[out->reviews_size]; - - *it = (gcli_pr_review) {0}; - - rc = github_parse_review_header(ctx, &stream, it); - if (rc < 0) - goto error_json; - - out->reviews_size++; - } - - if (json_next(&stream) != JSON_ARRAY_END) { - rc = gcli_error(ctx, "expected end of json array"); - goto error_json; - } - - rc = gcli_json_advance(ctx, &stream, "}}}}}"); - -error_json: - - json_close(&stream); -error_fetch: - free(buffer.data); - - return rc; -} diff --git a/src/gitlab/review.c b/src/gitlab/review.c deleted file mode 100644 index 9f6e1944..00000000 --- a/src/gitlab/review.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 -#include -#include -#include - -#include -#include - -#include - -#include - -int -gitlab_review_get_reviews(gcli_ctx *ctx, char const *owner, char const *repo, - gcli_id const pr, gcli_pr_review_list *const out) -{ - char *url = NULL; - - gcli_fetch_list_ctx fl = { - .listp = &out->reviews, - .sizep = &out->reviews_size, - .max = -1, - .parse = (parsefn)(parse_gitlab_reviews), - }; - - url = sn_asprintf("%s/projects/%s%%2F%s/merge_requests/%"PRIid"/notes?sort=asc", - gcli_get_apibase(ctx), owner, repo, pr); - - return gcli_fetch_list(ctx, url, &fl); -} diff --git a/src/review.c b/src/review.c deleted file mode 100644 index 1d388cf4..00000000 --- a/src/review.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 -#include -#include -#include -#include - -#include - -#include - -void -gcli_review_reviews_free(gcli_pr_review_list *list) -{ - if (!list) - return; - - 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); - } - - free(list->reviews); - - list->reviews = NULL; - list->reviews_size = 0; -} - -void -gcli_review_comments_free(gcli_pr_review_comment *it, size_t const size) -{ - if (!it) - return; - - for (size_t i = 0; i < size; ++i) { - free(it[i].id); - free(it[i].author); - free(it[i].date); - free(it[i].diff); - free(it[i].path); - free(it[i].body); - } - - free(it); -} - -int -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(ctx)->get_reviews(ctx, owner, repo, pr, out); -} diff --git a/templates/gitlab/review.t b/templates/gitlab/review.t deleted file mode 100644 index 037f6c92..00000000 --- a/templates/gitlab/review.t +++ /dev/null @@ -1,11 +0,0 @@ -include "gcli/gitlab/review.h"; - -parser gitlab_review_note is -object of gcli_pr_review with - ("created_at" => date as string, - "body" => body as string, - "author" => author as user, - "id" => id as int_to_string); - -parser gitlab_reviews is -array of gcli_pr_review use parse_gitlab_review_note; \ No newline at end of file From 6cdacb1457ca13057e4c338c5bae798536f1242e Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 17:23:06 +0100 Subject: [PATCH 137/152] Rename: print_pr_diff -> pull_get_diff For consistency reasons :-) --- include/gcli/forges.h | 18 +++++++++--------- src/forges.c | 6 +++--- src/pulls.c | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/gcli/forges.h b/include/gcli/forges.h index 0209a242..41538567 100644 --- a/include/gcli/forges.h +++ b/include/gcli/forges.h @@ -262,8 +262,8 @@ struct gcli_forge_descriptor { gcli_pull_list *out); /** - * Print a diff of the changes of a PR/MR to the stream */ - int (*print_pull_diff)( + * Fetch the PR diff into the file */ + int (*pull_get_diff)( gcli_ctx *ctx, FILE *stream, char const *owner, @@ -271,13 +271,13 @@ struct gcli_forge_descriptor { gcli_id pr_number); /** - * Fetch the PR patch series into the file */ - int (*pull_get_patch)( - gcli_ctx *ctx, - FILE *stream, - char const *owner, - char const *repo, - gcli_id pull_id); + * Fetch the PR patch series into the file */ + int (*pull_get_patch)( + gcli_ctx *ctx, + FILE *stream, + char const *owner, + char const *repo, + gcli_id pull_id); /** * Return a list of checks associated with the given pull. diff --git a/src/forges.c b/src/forges.c index 7051c57a..e8e14fee 100644 --- a/src/forges.c +++ b/src/forges.c @@ -108,9 +108,9 @@ github_forge_descriptor = .get_pull_commits = github_get_pull_commits, .get_pulls = github_get_pulls, .perform_submit_pull = github_perform_submit_pull, - .print_pull_diff = github_print_pull_diff, .pull_add_reviewer = github_pull_add_reviewer, .pull_close = github_pull_close, + .pull_get_diff = github_print_pull_diff, .pull_merge = github_pull_merge, .pull_reopen = github_pull_reopen, .pull_set_title = github_pull_set_title, @@ -199,11 +199,11 @@ gitlab_forge_descriptor = .get_pull_commits = gitlab_get_pull_commits, .get_pulls = gitlab_get_mrs, .perform_submit_pull = gitlab_perform_submit_mr, - .print_pull_diff = gitlab_print_pr_diff, .pull_add_labels = gitlab_mr_add_labels, .pull_add_reviewer = gitlab_mr_add_reviewer, .pull_clear_milestone = gitlab_mr_clear_milestone, .pull_close = gitlab_mr_close, + .pull_get_diff = gitlab_print_pr_diff, .pull_get_patch = gitlab_print_pr_patch, .pull_merge = gitlab_mr_merge, .pull_remove_labels = gitlab_mr_remove_labels, @@ -287,11 +287,11 @@ gitea_forge_descriptor = .get_pull_commits = gitea_get_pull_commits, .get_pulls = gitea_get_pulls, .perform_submit_pull = gitea_pull_submit, - .print_pull_diff = gitea_print_pr_diff, .pull_add_labels = gitea_issue_add_labels, .pull_add_reviewer = gitea_pull_add_reviewer, .pull_clear_milestone = gitea_pull_clear_milestone, .pull_close = gitea_pull_close, + .pull_get_diff = gitea_print_pr_diff, .pull_merge = gitea_pull_merge, .pull_remove_labels = gitea_issue_remove_labels, .pull_reopen = gitea_pull_reopen, diff --git a/src/pulls.c b/src/pulls.c index 5655cde4..a77f1b6e 100644 --- a/src/pulls.c +++ b/src/pulls.c @@ -61,7 +61,7 @@ int gcli_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner, char const *reponame, gcli_id const pr_number) { - return gcli_forge(ctx)->print_pull_diff(ctx, stream, owner, reponame, pr_number); + return gcli_forge(ctx)->pull_get_diff(ctx, stream, owner, reponame, pr_number); } int From de5b1859ed3487aebdeb9d3b7f70ded74a0de63f Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 17:32:32 +0100 Subject: [PATCH 138/152] Rename pr_print_* routines to pull_get_* For consistency reasons. --- include/gcli/gitea/pulls.h | 2 +- include/gcli/github/pulls.h | 4 ++-- include/gcli/gitlab/merge_requests.h | 8 ++++---- src/forges.c | 8 ++++---- src/gitea/pulls.c | 2 +- src/github/pulls.c | 4 ++-- src/gitlab/merge_requests.c | 8 ++++---- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/include/gcli/gitea/pulls.h b/include/gcli/gitea/pulls.h index b9cb063d..c3abd166 100644 --- a/include/gcli/gitea/pulls.h +++ b/include/gcli/gitea/pulls.h @@ -58,7 +58,7 @@ int gitea_pull_close(gcli_ctx *ctx, char const *owner, char const *repo, int gitea_pull_reopen(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id pr_number); -int gitea_print_pr_diff(gcli_ctx *ctx, FILE *stream, char const *owner, +int gitea_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner, char const *repo, gcli_id pr_number); int gitea_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, diff --git a/include/gcli/github/pulls.h b/include/gcli/github/pulls.h index 8fdb58c3..9fbfbf8f 100644 --- a/include/gcli/github/pulls.h +++ b/include/gcli/github/pulls.h @@ -41,8 +41,8 @@ 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(gcli_ctx *ctx, FILE *stream, char const *owner, - char const *reponame, gcli_id pr_number); +int github_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *reponame, gcli_id pr_number); int github_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id pr_number, gcli_pull_checks_list *out); diff --git a/include/gcli/gitlab/merge_requests.h b/include/gcli/gitlab/merge_requests.h index 35a8aa83..507c3542 100644 --- a/include/gcli/gitlab/merge_requests.h +++ b/include/gcli/gitlab/merge_requests.h @@ -71,11 +71,11 @@ int gitlab_get_mrs(gcli_ctx *ctx, char const *owner, int max, gcli_pull_list *out); -int gitlab_print_pr_diff(gcli_ctx *ctx, FILE *stream, char const *owner, - char const *reponame, gcli_id mr_number); +int gitlab_mr_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *reponame, gcli_id mr_number); -int gitlab_print_pr_patch(gcli_ctx *ctx, FILE *stream, char const *owner, - char const *reponame, gcli_id mr_number); +int gitlab_mr_get_patch(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *reponame, gcli_id mr_number); int gitlab_mr_merge(gcli_ctx *ctx, char const *owner, char const *reponame, gcli_id mr_number, enum gcli_merge_flags flags); diff --git a/src/forges.c b/src/forges.c index e8e14fee..f84e7303 100644 --- a/src/forges.c +++ b/src/forges.c @@ -110,7 +110,7 @@ github_forge_descriptor = .perform_submit_pull = github_perform_submit_pull, .pull_add_reviewer = github_pull_add_reviewer, .pull_close = github_pull_close, - .pull_get_diff = github_print_pull_diff, + .pull_get_diff = github_pull_get_diff, .pull_merge = github_pull_merge, .pull_reopen = github_pull_reopen, .pull_set_title = github_pull_set_title, @@ -203,8 +203,8 @@ gitlab_forge_descriptor = .pull_add_reviewer = gitlab_mr_add_reviewer, .pull_clear_milestone = gitlab_mr_clear_milestone, .pull_close = gitlab_mr_close, - .pull_get_diff = gitlab_print_pr_diff, - .pull_get_patch = gitlab_print_pr_patch, + .pull_get_diff = gitlab_mr_get_diff, + .pull_get_patch = gitlab_mr_get_patch, .pull_merge = gitlab_mr_merge, .pull_remove_labels = gitlab_mr_remove_labels, .pull_reopen = gitlab_mr_reopen, @@ -291,7 +291,7 @@ gitea_forge_descriptor = .pull_add_reviewer = gitea_pull_add_reviewer, .pull_clear_milestone = gitea_pull_clear_milestone, .pull_close = gitea_pull_close, - .pull_get_diff = gitea_print_pr_diff, + .pull_get_diff = gitea_pull_get_diff, .pull_merge = gitea_pull_merge, .pull_remove_labels = gitea_issue_remove_labels, .pull_reopen = gitea_pull_reopen, diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index 70cd1e47..de749e9b 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -136,7 +136,7 @@ gitea_pull_reopen(gcli_ctx *ctx, char const *owner, char const *repo, } int -gitea_print_pr_diff(gcli_ctx *ctx, FILE *const stream, char const *owner, +gitea_pull_get_diff(gcli_ctx *ctx, FILE *const stream, char const *owner, char const *repo, gcli_id const pr_number) { char *url = NULL; diff --git a/src/github/pulls.c b/src/github/pulls.c index 1acbbedc..7b7879a0 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -131,8 +131,8 @@ 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, gcli_id const pr_number) +github_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *repo, gcli_id const pr_number) { char *url = NULL; char *e_owner = NULL; diff --git a/src/gitlab/merge_requests.c b/src/gitlab/merge_requests.c index 7b2a54a7..65bfe744 100644 --- a/src/gitlab/merge_requests.c +++ b/src/gitlab/merge_requests.c @@ -202,8 +202,8 @@ gitlab_make_commit_patch(gcli_ctx *ctx, FILE *stream, } int -gitlab_print_pr_patch(gcli_ctx *ctx, FILE *stream, char const *owner, - char const *reponame, gcli_id mr_number) +gitlab_mr_get_patch(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *reponame, gcli_id mr_number) { int rc = 0; char *e_owner, *e_repo; @@ -248,8 +248,8 @@ gitlab_print_pr_patch(gcli_ctx *ctx, FILE *stream, char const *owner, } int -gitlab_print_pr_diff(gcli_ctx *ctx, FILE *stream, char const *owner, - char const *reponame, gcli_id mr_number) +gitlab_mr_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *reponame, gcli_id mr_number) { (void) stream; (void) owner; From 164caf949f10d22f88a4414020ad09439ab7379a Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 15:32:50 +0100 Subject: [PATCH 139/152] Add a manual page for the gcli configuration file format This manual page was long needed and contains the detailed documentation for the two config files that gcli will read if they exist. --- Makefile.am | 3 +- configure.ac | 3 +- docs/gcli.5.in | 136 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 docs/gcli.5.in diff --git a/Makefile.am b/Makefile.am index cb12a18f..939bc140 100644 --- a/Makefile.am +++ b/Makefile.am @@ -57,7 +57,8 @@ dist_man_MANS = \ docs/gcli-repos.1 \ docs/gcli-snippets.1 \ docs/gcli-status.1 \ - docs/gcli.1 + docs/gcli.1 \ + docs/gcli.5 gcli_SOURCES = \ include/gcli/cmd/ci.h src/cmd/ci.c \ diff --git a/configure.ac b/configure.ac index cbdee399..01944113 100644 --- a/configure.ac +++ b/configure.ac @@ -132,7 +132,8 @@ AC_CONFIG_FILES([Makefile docs/gcli-repos.1 docs/gcli-snippets.1 docs/gcli-status.1 - docs/gcli.1]) + docs/gcli.1 + docs/gcli.5]) dnl Technically only needed if tests are enabled but this doesn't dnl hurt. diff --git a/docs/gcli.5.in b/docs/gcli.5.in new file mode 100644 index 00000000..c698a050 --- /dev/null +++ b/docs/gcli.5.in @@ -0,0 +1,136 @@ +.Dd @PACKAGE_DATE@ +.Dt GCLI 5 +.Os @PACKAGE_STRING@ +.Sh NAME +.Nm gcli +.Nd gcli configuration file formats +.Sh DESCRIPTION +.Nm gcli +has two different configuration files. A user configuration file +that contains default values for +.Nm gcli +and a repository-local configuration that contains sensible default +values for a given repository. The latter is meant to be checked +into the repository and provide these default values to other users +as well. +.Ss User Configuration File +The user configuration file is located in +.Pa ${XDG_CONFIG_DIR}/gcli/config . +On most systems this equal to +.Pa ${HOME}/.config/gcli/config . +.Pp +The user configuration file contains definitions for accounts as +well as sensible default values for things like an editor. +.Pp +The file is structured in sections, each section has a name and +consists of a collection of key-value pairs. E.g.: +.Pp +.Bd -literal -offset indent +section-name { + key1 = value 1 + key2 = value 2 +} +.Ed +.Pp +There must be a section named +.Dq defaults +which may contain the following keys: +.Bl -tag +.It editor +Path to a default editor. This might be overridden by the environment +variable +.Ev EDITOR . +.It github-default-account +Section name of a default GitHub account to use whenever the account +is unspecified on the command line or in the environment. See +.Ev GCLI_ACCOUNT in +.Xr gcli 1 . +.It gitlab-default-account +Section name of a default GitLab account to use whenever the account +is unspecified on the command line or in the environment. See +.Ev GCLI_ACCOUNT in +.Xr gcli 1 . +.It gitea-default-account +Section name of a default Gitea account to use whenever the account +is unspecified on the command line or in the environment. See +.Ev GCLI_ACCOUNT in +.Xr gcli 1 . +.El +.Pp +All other sections define accounts for forges. Each of these account +definitions have the account name as their section name and may +have one or more of the following keys defined: +.Bl -tag -width forge-type +.It forge-type +The type of the forge. May be one of: +.Bl -bullet -compact +.It +github +.It +gitlab +.It +gitea +.El +.It api-base +(optional) Used to override the API base URL of the forge. This is +useful for self-hosted instances. Depending on the +.Dq forge-type +the default values are: +.Bl -column forge-type "default value" +.It Em forge-type Ta Em "default value" +.It github Ta Lk "https://api.github.com" +.It gitlab Ta Lk "https://gitlab.com/api/v4" +.It gitea Ta Lk "https://codeberg.org/api/v1" +.El +.It account +(optional) The username used to authenticate at the API. +.It token +(optional) A generated application token to use with this account. +TODO: Document for each forge how to generate these. +.El +.Ss Repository Local Configuration File +For repository-local configuration you can use a special configuration +file. It contains definitions for gcli that are specific to the +repository. +.Pp +The Repository-local configuration file is located in the root +directory of the repository and should be named +.Pa .gcli . +.Pp +It contains a list of key-value pairs. Allowed keys are: +.Bl -tag -width pr.upstream +.It pr.base +Name of a branch that the changes should be merged into by default. +Usually this is one of +.Em master , +.Em main or +.Em trunk . +.It pr.upstream +Name of the upstream repository to submit the pull request to by default. +This is a pair of the format +.Dq owner/repository . +.It pr.inhibit-delete-source-branch +If defined and set to +.Dq yes +this will prevent the pull request source branch to get deleted +when merging a pull request by default. +.It forge-type +When hosting on multiple forges this can be set to a type that will +be used as a default when other overrides are unspecified. For +possible values see the equivalent definition in +.Sx "User Configuration File" . +.El +.Sh SEE ALSO +.Xr git 1 , +.Xr gcli 1 +.Sh AUTHORS +.An Nico Sonack aka. herrhotzenplotz Aq Mt nsonack@herrhotzenplotz.de +and contributors. +.Sh BUGS +Please report bugs via E-Mail to +.Mt @PACKAGE_BUGREPORT@ . +.Pp +Alternatively you can report them on any of the forges linked at +.Lk @PACKAGE_URL@ . +However, the preferred and quickest method is to use the mailing +list. From 3e99fe5031731802203b885ed6632b6ecfe45a44 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 15:46:51 +0100 Subject: [PATCH 140/152] Move FILES examples from gcli(1) to gcli(5) and cross-reference them The documentation for this has been extended with a separate manual page for the configuration files (gcli(5)). The examples for these files have been moved appropriately as there is now a better place for them and it condenses the gcli(1) manual page a bit. --- docs/gcli.1.in | 63 ++++++-------------------------------------------- docs/gcli.5.in | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 56 deletions(-) diff --git a/docs/gcli.1.in b/docs/gcli.1.in index 8535ecfa..66acf37a 100644 --- a/docs/gcli.1.in +++ b/docs/gcli.1.in @@ -184,67 +184,18 @@ escape sequences. See .Sh FILES .Bl -tag -width ${XDG_CONFIG_DIR}/gcli/config -compact .It Pa ${XDG_CONFIG_DIR}/gcli/config -The config file for -.Nm . -It shall contain the following data: -.Pp -.Bd -literal -defaults { - editor=/path/to/ganoooo/emacs - github-default-account=herrhotzenplotz-gh - gitlab-default-account=herrhotzenplotz-gitlab -} - -herrhotzenplotz-gh { - account=herrhotzenplotz - token=foobar - apibase=https://api.github.com - forge-type=github -} - -herrhotzenplotz-gl { - account=herrhotzenplotz - token= - apibase=https://gitlab.com/api/v4 - forge-type=gitlab -} -.Ed -.Pp -In case -.Sq apibase -is not set, it defaults to the above values. -For the API token, you can set whatever scopes you want. However, I -recommend setting the following on GitHub: -.Sq admin:org, delete_repo, gist, repo, workflow . -On GitLab you only need the -.Sq api -scope. -.Pp -If editor is not set in the config file, -.Nm -will use -.Ev EDITOR -from the environment. -.Pp -Both -.Sq gitlab-default-account -and -.Sq github-default-account -must point at a config section with that exact name. +The user configuration file for gcli. It contains account definitions +as well as sensible default values. See +.Xr gcli 5 . .Pp .It Pa .gcli -A repo-specific config file that may contain the following data: -.Bd -literal -pr.upstream=herrhotzenplotz/gcli -pr.base=trunk -pr.inhibit-delete-source-branch=yes -.Ed -.Pp -It is intended to be committed into the repo so that users don't have -to manually specify all the options like +A repo-specific config file intended to be committed into the repo +so that users don't have to manually specify all the options like .Fl -in , .Fl -from , .Fl -base etc. +when creating pull requests. See +.Xr gcli 5 for details about this file. .Pp .El .Sh EXAMPLES diff --git a/docs/gcli.5.in b/docs/gcli.5.in index c698a050..d6ebdd77 100644 --- a/docs/gcli.5.in +++ b/docs/gcli.5.in @@ -120,6 +120,47 @@ be used as a default when other overrides are unspecified. For possible values see the equivalent definition in .Sx "User Configuration File" . .El +.Sh EXAMPLES +.Ss User Configuration File +An example for the user configuration file consisting of both a +Github and a Gitlab account: +.Bd -literal +defaults { + editor=/path/to/ganoooo/emacs + github-default-account=herrhotzenplotz-gh + gitlab-default-account=herrhotzenplotz-gitlab +} + +herrhotzenplotz-gh { + account=herrhotzenplotz + token=foobar + apibase=https://api.github.com + forge-type=github +} + +herrhotzenplotz-gl { + account=herrhotzenplotz + token= + apibase=https://gitlab.com/api/v4 + forge-type=gitlab +} +.Ed +.Pp +Notice that this allows you to run gcli and force it to use a +specific Gitlab account. E.g.: +.Bd -literal +$ gcli -a herrhotzenplotz-gl issues -a +.Ed +.Pp +.Ss Repository-Local Configuration file +The +.Pa .gcli +file for the gcli project itself looks like this: +.Bd -literal +pr.upstream=herrhotzenplotz/gcli +pr.base=trunk +pr.inhibit-delete-source-branch=yes +.Ed .Sh SEE ALSO .Xr git 1 , .Xr gcli 1 From 86cf37fc2f5e9935af6afb70ce2fc83a532023b7 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 17:16:02 +0100 Subject: [PATCH 141/152] Rename Gitea routine for getting PR diffs This routine was both incorrectly named and also didn't fetch the diff but the patch. Rename it to gitea_pull_get_diff and make it actually fetch the diff. --- src/gitea/pulls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index de749e9b..610c060f 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -148,7 +148,7 @@ gitea_pull_get_diff(gcli_ctx *ctx, FILE *const stream, char const *owner, e_repo = gcli_urlencode(repo); url = sn_asprintf( - "%s/repos/%s/%s/pulls/%"PRIid".patch", + "%s/repos/%s/%s/pulls/%"PRIid".diff", gcli_get_apibase(ctx), e_owner, e_repo, pr_number); From d2f20afde455dbdee18e37b3673afa05a70c5951 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 17:19:36 +0100 Subject: [PATCH 142/152] Implement fetching the pull request patch for gitea This was previously incorrectly implemented as getting the diff. Add the needed routine that fetches a patch. --- include/gcli/gitea/pulls.h | 3 +++ src/forges.c | 1 + src/gitea/pulls.c | 25 +++++++++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/include/gcli/gitea/pulls.h b/include/gcli/gitea/pulls.h index c3abd166..cb942f7a 100644 --- a/include/gcli/gitea/pulls.h +++ b/include/gcli/gitea/pulls.h @@ -61,6 +61,9 @@ int gitea_pull_reopen(gcli_ctx *ctx, char const *owner, char const *repo, int gitea_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner, char const *repo, gcli_id pr_number); +int gitea_pull_get_patch(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *repo, gcli_id pr_number); + int gitea_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id pr_number, gcli_pull_checks_list *out); diff --git a/src/forges.c b/src/forges.c index f84e7303..0ac5539d 100644 --- a/src/forges.c +++ b/src/forges.c @@ -292,6 +292,7 @@ gitea_forge_descriptor = .pull_clear_milestone = gitea_pull_clear_milestone, .pull_close = gitea_pull_close, .pull_get_diff = gitea_pull_get_diff, + .pull_get_patch = gitea_pull_get_patch, .pull_merge = gitea_pull_merge, .pull_remove_labels = gitea_issue_remove_labels, .pull_reopen = gitea_pull_reopen, diff --git a/src/gitea/pulls.c b/src/gitea/pulls.c index 610c060f..c4233d41 100644 --- a/src/gitea/pulls.c +++ b/src/gitea/pulls.c @@ -135,6 +135,31 @@ gitea_pull_reopen(gcli_ctx *ctx, char const *owner, char const *repo, return gitea_pulls_patch_state(ctx, owner, repo, pr_number, "open"); } +int +gitea_pull_get_patch(gcli_ctx *ctx, FILE *const stream, char const *owner, + char const *repo, gcli_id const pr_number) +{ + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; + + e_owner = gcli_urlencode(owner); + e_repo = gcli_urlencode(repo); + + url = sn_asprintf( + "%s/repos/%s/%s/pulls/%"PRIid".patch", + gcli_get_apibase(ctx), + e_owner, e_repo, pr_number); + + rc = gcli_curl(ctx, stream, url, NULL); + + free(e_owner); + free(e_repo); + free(url); + + return rc; +} int gitea_pull_get_diff(gcli_ctx *ctx, FILE *const stream, char const *owner, char const *repo, gcli_id const pr_number) From 985e3e76af7b84761a646fde58d0c8beff76ce22 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 17:45:17 +0100 Subject: [PATCH 143/152] Implement missing patch action for Github This routine was missing for some reason. Implement it for Github. --- include/gcli/github/pulls.h | 3 +++ src/forges.c | 1 + src/github/pulls.c | 25 +++++++++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/include/gcli/github/pulls.h b/include/gcli/github/pulls.h index 9fbfbf8f..30092036 100644 --- a/include/gcli/github/pulls.h +++ b/include/gcli/github/pulls.h @@ -44,6 +44,9 @@ int github_get_pulls(gcli_ctx *ctx, char const *owner, char const *reponame, int github_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner, char const *reponame, gcli_id pr_number); +int github_pull_get_patch(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *reponame, gcli_id pr_number); + int github_pull_get_checks(gcli_ctx *ctx, char const *owner, char const *repo, gcli_id pr_number, gcli_pull_checks_list *out); diff --git a/src/forges.c b/src/forges.c index 0ac5539d..02091068 100644 --- a/src/forges.c +++ b/src/forges.c @@ -111,6 +111,7 @@ github_forge_descriptor = .pull_add_reviewer = github_pull_add_reviewer, .pull_close = github_pull_close, .pull_get_diff = github_pull_get_diff, + .pull_get_patch = github_pull_get_patch, .pull_merge = github_pull_merge, .pull_reopen = github_pull_reopen, .pull_set_title = github_pull_set_title, diff --git a/src/github/pulls.c b/src/github/pulls.c index 7b7879a0..f2e8b0a8 100644 --- a/src/github/pulls.c +++ b/src/github/pulls.c @@ -130,6 +130,31 @@ github_get_pulls(gcli_ctx *ctx, char const *owner, char const *repo, return github_fetch_pulls(ctx, url, details, max, list); } +int +github_pull_get_patch(gcli_ctx *ctx, FILE *stream, char const *owner, + char const *repo, gcli_id const pr_number) +{ + char *url = NULL; + char *e_owner = NULL; + char *e_repo = NULL; + int rc = 0; + + e_owner = gcli_urlencode(owner); + e_repo = gcli_urlencode(repo); + + url = sn_asprintf( + "%s/repos/%s/%s/pulls/%"PRIid, + gcli_get_apibase(ctx), + e_owner, e_repo, pr_number); + rc = gcli_curl(ctx, stream, url, "Accept: application/vnd.github.v3.patch"); + + free(e_owner); + free(e_repo); + free(url); + + return rc; +} + int github_pull_get_diff(gcli_ctx *ctx, FILE *stream, char const *owner, char const *repo, gcli_id const pr_number) From 70cf677a5446d8af0c464cc0682a1d731f9f0e3d Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 17:48:07 +0100 Subject: [PATCH 144/152] Update changelog for new pull_get_patch routines Added implementations for Github and Gitea. --- Changelog.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index f0463dbb..62fe9c27 100644 --- a/Changelog.md +++ b/Changelog.md @@ -20,7 +20,8 @@ This changelog does not follow semantic versioning. - Add a new `-M` flag to both the pulls and the issues subcommand to allow filtering by milestones. - Add a new `patch` action to the pulls subcommand. This allows you - to print the entire patch series for the given pull request. + to print the entire patch series for the given pull request. Also, + add missing implementations for this feature for Github and Gitea. - Add a new `title` action to both the issues and the pulls subcommand that allows updating their titles. From 860a94a4a129a92771b6c66abcb96a261e1ff493 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 17:51:30 +0100 Subject: [PATCH 145/152] Wire up missing routine for creating forks on Gitea This routine previously had the wrong signature and also wasn't wired up in the forge dispatch table. Correct the signature and put it into the dispatch table. --- Changelog.md | 1 + include/gcli/gitea/forks.h | 4 ++-- src/forges.c | 1 + src/gitea/forks.c | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index 62fe9c27..7570044e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -36,6 +36,7 @@ This changelog does not follow semantic versioning. footprint. - Spelling fixes in manual pages (submitted by Jakub Wilk https://github.com/herrhotzenplotz/gcli/pull/121) +- Add existing implementation for forking on Gitea to gcli command ### Changed diff --git a/include/gcli/gitea/forks.h b/include/gcli/gitea/forks.h index e79ebffd..4e952975 100644 --- a/include/gcli/gitea/forks.h +++ b/include/gcli/gitea/forks.h @@ -39,7 +39,7 @@ int gitea_get_forks(gcli_ctx *ctx, char const *owner, char const *repo, int max, gcli_fork_list *out); -void gitea_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, - char const *_in); +int gitea_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, + char const *_in); #endif /* GITEA_FORKS_H */ diff --git a/src/forges.c b/src/forges.c index 02091068..b2ad23b7 100644 --- a/src/forges.c +++ b/src/forges.c @@ -259,6 +259,7 @@ gitea_forge_descriptor = .perform_submit_comment = gitea_perform_submit_comment, /* Forks */ + .fork_create = gitea_fork_create, .get_forks = gitea_get_forks, /* Issues */ diff --git a/src/gitea/forks.c b/src/gitea/forks.c index 6ddf9cf3..8c9b5017 100644 --- a/src/gitea/forks.c +++ b/src/gitea/forks.c @@ -39,9 +39,9 @@ gitea_get_forks(gcli_ctx *ctx, char const *owner, char const *repo, return github_get_forks(ctx, owner, repo, max, out); } -void +int gitea_fork_create(gcli_ctx *ctx, char const *owner, char const *repo, char const *_in) { - github_fork_create(ctx, owner, repo, _in); + return github_fork_create(ctx, owner, repo, _in); } From 1f162d343706142800a8c4d42e1eb439f887a1b1 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 18:51:37 +0100 Subject: [PATCH 146/152] Add a separate implementation for fetching Gitea notifications This is incompatible with Github because the IDs are integers not strings like in the Github API. Provide a separate implementation and also add tests for the parsers. --- Makefile.am | 14 ++- include/gcli/gitea/status.h | 40 ++++++++ include/gcli/status.h | 1 + src/forges.c | 4 + src/gitea/status.c | 59 ++++++++++++ src/status.c | 18 ++-- templates/gitea/status.t | 20 ++++ tests/Kyuafile.in | 5 + tests/gitea-parse-tests.c | 71 ++++++++++++++ tests/samples/gitea_simple_notification.json | 98 ++++++++++++++++++++ 10 files changed, 322 insertions(+), 8 deletions(-) create mode 100644 include/gcli/gitea/status.h create mode 100644 src/gitea/status.c create mode 100644 templates/gitea/status.t create mode 100644 tests/gitea-parse-tests.c create mode 100644 tests/samples/gitea_simple_notification.json diff --git a/Makefile.am b/Makefile.am index 939bc140..41ace0f5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -118,7 +118,8 @@ TEMPLATES = \ templates/gitlab/sshkeys.t \ templates/gitlab/status.t \ templates/gitlab/snippets.t \ - templates/gitea/milestones.t + templates/gitea/milestones.t \ + templates/gitea/status.t headerdir = $(prefix) nobase_header_HEADERS = include/gcli/gcli.h include/gcli/comments.h \ @@ -186,6 +187,7 @@ libgcli_la_SOURCES = \ src/gitea/releases.c include/gcli/gitea/releases.h \ src/gitea/repos.c include/gcli/gitea/repos.h \ src/gitea/sshkeys.c include/gcli/gitea/sshkeys.h \ + src/gitea/status.c include/gcli/gitea/status.h \ src/gitea/milestones.c include/gcli/gitea/milestones.h \ $(TEMPLATES) @@ -214,6 +216,7 @@ check_PROGRAMS = \ tests/json-escape$(EXEEXT) \ tests/github-parse-tests$(EXEEXT) \ tests/gitlab-parse-tests$(EXEEXT) \ + tests/gitea-parse-tests$(EXEEXT) \ tests/url-encode$(EXEEXT) \ tests/pretty_print_test$(EXEEXT) \ tests/test-jsongen$(EXEEXT) @@ -244,6 +247,12 @@ tests_gitlab_parse_tests_LDADD = \ libgcli.la libpdjson.la libsn.la \ $(LIBATFC_LDFLAGS) +tests_gitea_parse_tests_SOURCES = \ + tests/gitea-parse-tests.c +tests_gitea_parse_tests_LDADD = \ + libgcli.la libpdjson.la libsn.la \ + $(LIBATFC_LDFLAGS) + tests_url_encode_SOURCES = \ tests/url-encode.c tests_url_encode_LDADD = \ @@ -280,6 +289,7 @@ EXTRA_DIST += tests/samples/github_simple_comment.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 + tests/samples/github_simple_check.json \ + tests/samples/gitea_simple_notification.json endif diff --git a/include/gcli/gitea/status.h b/include/gcli/gitea/status.h new file mode 100644 index 00000000..88be8602 --- /dev/null +++ b/include/gcli/gitea/status.h @@ -0,0 +1,40 @@ +/* + * 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 GITEA_STATUS_H +#define GITEA_STATUS_H + +#include + +int gitea_get_notifications(gcli_ctx *ctx, int max, + gcli_notification_list *out); + +int gitea_notification_mark_as_read(gcli_ctx *ctx, char const *id); + +#endif /* GITEA_STATUS_H */ diff --git a/include/gcli/status.h b/include/gcli/status.h index 52601a58..c2c4bbe0 100644 --- a/include/gcli/status.h +++ b/include/gcli/status.h @@ -57,6 +57,7 @@ struct gcli_notification_list { 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_notification(gcli_notification *); void gcli_free_notifications(gcli_notification_list *); #endif /* STATUS_H */ diff --git a/src/forges.c b/src/forges.c index b2ad23b7..7461740a 100644 --- a/src/forges.c +++ b/src/forges.c @@ -68,6 +68,7 @@ #include #include #include +#include static gcli_forge_descriptor const github_forge_descriptor = @@ -323,6 +324,9 @@ gitea_forge_descriptor = .get_sshkeys = gitea_get_sshkeys, /* Notifications */ + .get_notifications = gitea_get_notifications, + .notification_mark_as_read = gitea_notification_mark_as_read, + /* Internal stuff */ .make_authheader = gitea_make_authheader, .get_api_error_string = github_api_error_string, /* hack! */ diff --git a/src/gitea/status.c b/src/gitea/status.c new file mode 100644 index 00000000..57cd87f2 --- /dev/null +++ b/src/gitea/status.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 +gitea_get_notifications(gcli_ctx *ctx, int const max, + gcli_notification_list *const out) +{ + char *url = NULL; + + gcli_fetch_list_ctx fl = { + .listp = &out->notifications, + .sizep = &out->notifications_size, + .parse = (parsefn)(parse_gitea_notifications), + .max = max, + }; + + url = sn_asprintf("%s/notifications", gcli_get_apibase(ctx)); + return gcli_fetch_list(ctx, url, &fl); +} + +int +gitea_notification_mark_as_read(gcli_ctx *ctx, char const *id) +{ + (void) id; + return gcli_error(ctx, "not implemented"); +} diff --git a/src/status.c b/src/status.c index 140f445e..aaf441c4 100644 --- a/src/status.c +++ b/src/status.c @@ -37,16 +37,22 @@ gcli_get_notifications(gcli_ctx *ctx, int const max, return gcli_forge(ctx)->get_notifications(ctx, max, out); } +void +gcli_free_notification(gcli_notification *const notification) +{ + free(notification->id); + free(notification->title); + free(notification->reason); + free(notification->date); + free(notification->type); + free(notification->repository); +} + void gcli_free_notifications(gcli_notification_list *list) { 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); + gcli_free_notification(&list->notifications[i]); } free(list->notifications); diff --git a/templates/gitea/status.t b/templates/gitea/status.t new file mode 100644 index 00000000..9196d240 --- /dev/null +++ b/templates/gitea/status.t @@ -0,0 +1,20 @@ +include "gcli/status.h"; + +parser gitea_notification_repository is +object of gcli_notification with + ("full_name" => repository as string); + +parser gitea_notification_status is +object of gcli_notification with + ("title" => title as string, + "type" => type as string); + +parser gitea_notification is +object of gcli_notification with + ("id" => id as int_to_string, + "repository" => use parse_gitea_notification_repository, + "subject" => use parse_gitea_notification_status, + "updated_at" => date as string); + +parser gitea_notifications is +array of gcli_notification use parse_gitea_notification; diff --git a/tests/Kyuafile.in b/tests/Kyuafile.in index 8d8e554f..483eab8b 100644 --- a/tests/Kyuafile.in +++ b/tests/Kyuafile.in @@ -16,6 +16,11 @@ atf_test_program{ required_files = '@TESTSRCDIR@/samples/gitlab_simple_merge_request.json' } +atf_test_program{ + name = 'gitea-parse-tests', + required_files = '@TESTSRCDIR@/samples/gitea_simple_notification.json' +} + atf_test_program{ name = 'url-encode' } diff --git a/tests/gitea-parse-tests.c b/tests/gitea-parse-tests.c new file mode 100644 index 00000000..f0a2badc --- /dev/null +++ b/tests/gitea-parse-tests.c @@ -0,0 +1,71 @@ +#include +#include + +#include +#include +#include + +#include + +#include "gcli_tests.h" + +#include + +static gcli_forge_type +get_gitea_forge_type(gcli_ctx *ctx) +{ + (void) ctx; + return GCLI_FORGE_GITEA; +} + +static gcli_ctx * +test_context(void) +{ + gcli_ctx *ctx; + ATF_REQUIRE(gcli_init(&ctx, get_gitea_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(gitea_simple_notification); +ATF_TC_BODY(gitea_simple_notification, tc) +{ + gcli_notification notification = {0}; + FILE *sample; + json_stream stream = {0}; + gcli_ctx *ctx; + + ctx = test_context(); + sample = open_sample("gitea_simple_notification.json"); + + json_open_stream(&stream, sample); + ATF_REQUIRE(parse_gitea_notification(ctx, &stream, ¬ification) == 0); + + ATF_CHECK_STREQ(notification.id, "511579"); + ATF_CHECK_STREQ(notification.title, "Remove register from C++ sources"); + ATF_CHECK(notification.reason == NULL); + ATF_CHECK_STREQ(notification.date, "2023-11-24T21:01:50Z"); + ATF_CHECK_STREQ(notification.repository, "schilytools/schilytools"); + + fclose(sample); + gcli_free_notification(¬ification); + gcli_destroy(&ctx); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, gitea_simple_notification); + return atf_no_error(); +} diff --git a/tests/samples/gitea_simple_notification.json b/tests/samples/gitea_simple_notification.json new file mode 100644 index 00000000..84913a86 --- /dev/null +++ b/tests/samples/gitea_simple_notification.json @@ -0,0 +1,98 @@ +{ + "id": 511579, + "repository": { + "id": 45938, + "owner": { + "id": 52534, + "login": "schilytools", + "login_name": "", + "full_name": "", + "email": "", + "avatar_url": "https://codeberg.org/avatars/f29c1b0621d441e37b83d4bf59bf2563", + "language": "", + "is_admin": false, + "last_login": "0001-01-01T00:00:00Z", + "created": "2022-05-24T12:20:59Z", + "restricted": false, + "active": false, + "prohibit_login": false, + "location": "", + "website": "http://schilytools.sourceforge.net/", + "description": "This project maintains the schilytools, a collection of tools written or formerly managed by Jörg Schilling.", + "visibility": "public", + "followers_count": 0, + "following_count": 0, + "starred_repos_count": 0, + "username": "schilytools" + }, + "name": "schilytools", + "full_name": "schilytools/schilytools", + "description": "A collection of tools written or formerly managed by Jörg Schilling.", + "empty": false, + "private": false, + "fork": false, + "template": false, + "parent": null, + "mirror": false, + "size": 16025, + "language": "", + "languages_url": "https://codeberg.org/api/v1/repos/schilytools/schilytools/languages", + "html_url": "https://codeberg.org/schilytools/schilytools", + "url": "https://codeberg.org/api/v1/repos/schilytools/schilytools", + "link": "", + "ssh_url": "git@codeberg.org:schilytools/schilytools.git", + "clone_url": "https://codeberg.org/schilytools/schilytools.git", + "original_url": "", + "website": "", + "stars_count": 20, + "forks_count": 10, + "watchers_count": 8, + "open_issues_count": 21, + "open_pr_counter": 1, + "release_counter": 7, + "default_branch": "master", + "archived": false, + "created_at": "2022-05-24T14:20:56Z", + "updated_at": "2023-11-24T21:01:16Z", + "archived_at": "1970-01-01T00:00:00Z", + "has_issues": true, + "internal_tracker": { + "enable_time_tracker": true, + "allow_only_contributors_to_track_time": true, + "enable_issue_dependencies": true + }, + "has_wiki": true, + "has_pull_requests": true, + "has_projects": true, + "has_releases": true, + "has_packages": false, + "has_actions": false, + "ignore_whitespace_conflicts": false, + "allow_merge_commits": true, + "allow_rebase": true, + "allow_rebase_explicit": true, + "allow_squash_merge": true, + "allow_rebase_update": true, + "default_delete_branch_after_merge": false, + "default_merge_style": "rebase", + "default_allow_maintainer_edit": false, + "avatar_url": "", + "internal": false, + "mirror_interval": "", + "mirror_updated": "0001-01-01T00:00:00Z", + "repo_transfer": null + }, + "subject": { + "title": "Remove register from C++ sources", + "url": "https://codeberg.org/api/v1/repos/schilytools/schilytools/issues/13", + "latest_comment_url": "https://codeberg.org/api/v1/repos/schilytools/schilytools/issues/comments/1349554", + "html_url": "https://codeberg.org/schilytools/schilytools/issues/13", + "latest_comment_html_url": "https://codeberg.org/schilytools/schilytools/issues/13#issuecomment-1349554", + "type": "Issue", + "state": "closed" + }, + "unread": true, + "pinned": false, + "updated_at": "2023-11-24T21:01:50Z", + "url": "https://codeberg.org/api/v1/notifications/threads/511579" +} From 0cad78c13333f4b5a33adec118b4ed25b6d71ddc Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 18:58:02 +0100 Subject: [PATCH 147/152] Add a workaround for the missing reason in Gitea notifications The reason pointer is NULL in the case of Gitea because it doesn't provide this value. Ignore it if is NULL. --- src/cmd/status.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/cmd/status.c b/src/cmd/status.c index 3fc7659e..268965ce 100644 --- a/src/cmd/status.c +++ b/src/cmd/status.c @@ -71,11 +71,16 @@ 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", + printf("%s - %s - %s - %s", list->notifications[i].id, list->notifications[i].repository, - list->notifications[i].type, list->notifications[i].date, - list->notifications[i].reason); + list->notifications[i].type, list->notifications[i].date); + + if (list->notifications[i].reason) { + printf(" - %s\n", list->notifications[i].reason); + } else { + printf("\n"); + } pretty_print(list->notifications[i].title, 4, 80, stdout); putchar('\n'); From 2c7dd24f16f6f6d0d6896d6180bc1f228c99cbb3 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 19:04:31 +0100 Subject: [PATCH 148/152] Forward "mark notification as done" implementation for Gitea to Github --- src/gitea/status.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gitea/status.c b/src/gitea/status.c index 57cd87f2..dd54263d 100644 --- a/src/gitea/status.c +++ b/src/gitea/status.c @@ -27,8 +27,9 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include +#include +#include #include @@ -54,6 +55,5 @@ gitea_get_notifications(gcli_ctx *ctx, int const max, int gitea_notification_mark_as_read(gcli_ctx *ctx, char const *id) { - (void) id; - return gcli_error(ctx, "not implemented"); + return github_notification_mark_as_read(ctx, id); } From 91c3ebda8d36553143ec591ebc2462674d929362 Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Sat, 2 Dec 2023 19:08:34 +0100 Subject: [PATCH 149/152] Update changelog for Gitea status fixes Provided working implementations for both fetching notifications and marking them as done. --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 7570044e..176e72f2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -37,6 +37,7 @@ This changelog does not follow semantic versioning. - Spelling fixes in manual pages (submitted by Jakub Wilk https://github.com/herrhotzenplotz/gcli/pull/121) - Add existing implementation for forking on Gitea to gcli command +- The `status` subcommand now works properly on Gitea. ### Changed From c940f58ede60c3a960aee2195cd646686823ecca Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Dec 2023 21:00:46 +0100 Subject: [PATCH 150/152] Clean up changelog - Fix mixed tenses - Remove verbose comment on memory leaks --- Changelog.md | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Changelog.md b/Changelog.md index 176e72f2..cb6fd647 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,18 +11,19 @@ This changelog does not follow semantic versioning. - Added Windows 10 MSYS2 to list of confirmed-to-work platforms - Added a new action `set-visibility` to the repos subcommand that allows updating the visibility level of a repository. -- Add a new action `request-review` to the pulls subcommand that +- Added a new action `request-review` to the pulls subcommand that allows requesting a review of a pull request from a given user. - One can now define custom aliases in the alias section of the config file. Aliases are very primitive as of now. This means they are just different names for subcommands. Aliases may reference other aliases. -- Add a new `-M` flag to both the pulls and the issues subcommand +- Added a new `-M` flag to both the pulls and the issues subcommand to allow filtering by milestones. -- Add a new `patch` action to the pulls subcommand. This allows you - to print the entire patch series for the given pull request. Also, - add missing implementations for this feature for Github and Gitea. -- Add a new `title` action to both the issues and the pulls +- Added a new `patch` action to the pulls subcommand. This allows + you to print the entire patch series for a given pull request. + Also added the missing implementations for this feature for Github + and Gitea. +- Added a new `title` action to both the issues and the pulls subcommand that allows updating their titles. ### Fixed @@ -30,13 +31,11 @@ This changelog does not follow semantic versioning. - Fixed incorrect internal help message of the `repos` subcommand. - Worked around ICE with xlC 16 on ppc64le Debian Linux, gcli now compiles using xlC and works too. -- Fixed various memory leaks. This was not a real issue as these - leaks were minor and gcli is not a long-running application where - thease leaks would have had any serious impact on the memory - footprint. +- Fixed various memory leaks. - Spelling fixes in manual pages (submitted by Jakub Wilk https://github.com/herrhotzenplotz/gcli/pull/121) -- Add existing implementation for forking on Gitea to gcli command +- Wired up alread existing implementation for forking on Gitea to + gcli command. - The `status` subcommand now works properly on Gitea. ### Changed From db5c39597ee0899ef712b957685d3903f583fc6f Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Tue, 5 Dec 2023 21:03:26 +0100 Subject: [PATCH 151/152] Bump version number for RC1 test release --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 01944113..caa2c2d6 100644 --- a/configure.ac +++ b/configure.ac @@ -3,14 +3,14 @@ AC_PREREQ([2.69]) AC_INIT([gcli], - [2.1.0-devel], + [2.1.0-rc1], [~herrhotzenplotz/gcli-discuss@lists.sr.ht], [gcli], [https://herrhotzenplotz.de/gcli]) AM_INIT_AUTOMAKE([1.0 foreign subdir-objects dist-bzip2 dist-xz -Wall]) dnl Release Date. -PACKAGE_DATE="UNRELEASED" +PACKAGE_DATE="05-Dec-2023" AC_SUBST([PACKAGE_DATE]) dnl Silent by default. From 9978c403531d1669b3ed04cba19fa740ad7104bf Mon Sep 17 00:00:00 2001 From: Nico Sonack Date: Fri, 8 Dec 2023 11:57:54 +0100 Subject: [PATCH 152/152] Include Changelog in dist tarball --- Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 41ace0f5..41b488bc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -207,7 +207,8 @@ EXTRA_DIST = \ HACKING.md \ autogen.sh \ m4/.gitkeep \ - docs/pgen.org + docs/pgen.org \ + Changelog.md ########################################### # Tests