~herrhotzenplotz/gcli-devel

gcli: Bugfixes: segfaults and github API error 422 v1 APPLIED

This is the local branch I've been running, and tweaking as I encounter
bugs. Sent in one thread to avoid spamming the mailing list.
Also, thanks for the cool program!

remph (2):
  Misc. small patches:
  Fix github API error 422 on `gcli forks create'

 configure                   |  2 ++
 docs/gcli-forks.1.in        |  2 +-
 include/gcli/github/repos.h |  2 ++
 src/cmd/cmdconfig.c         |  8 +++++---
 src/cmd/repos.c             |  2 +-
 src/github/forks.c          | 11 ++++++++++-
 src/github/repos.c          | 38 ++++++++++++++++++++-----------------
 7 files changed, 42 insertions(+), 23 deletions(-)

-- 
2.47.1
build pending: alpine.yml
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~herrhotzenplotz/gcli-devel/patches/56710/mbox | git am -3
Learn more about email & git

[PATCH gcli 1/2] Misc. small patches: Export this patch

* Document existing --{en,dis}able-liblowdown ./configure options
* Fix segfault caused by type mismatch in gcli_print_repos()
* Fix null dereference in gcli_config_get_account_name() when no account is
  is given
---
 configure           | 2 ++
 src/cmd/cmdconfig.c | 8 +++++---
 src/cmd/repos.c     | 2 +-
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/configure b/configure
index 560b097d..1a8e6ea7 100755
--- a/configure
+++ b/configure
@@ -132,6 +132,8 @@ OPTIONS:
    --disable-libedit       Do not use libedit
    --enable-libreadline    Search and use libreadline for interactive editing [DEFAULT: yes]
    --disable-libreadline   Disable use of libreadline
    --enable-liblowdown     Search and use liblowdown for markdown rendering [DEFAULT: yes]
    --disable-liblowdown    Disable use of liblowdown
    --debug                 Compile without optimisations, generate code with
                            debug information and enable additional compiler-specific
                            warnings and portability checks.
diff --git a/src/cmd/cmdconfig.c b/src/cmd/cmdconfig.c
index efb1696b..aa5b2807 100644
--- a/src/cmd/cmdconfig.c
+++ b/src/cmd/cmdconfig.c
@@ -791,11 +791,13 @@ char *
gcli_config_get_account_name(struct gcli_ctx *ctx)
{
	char *account = gcli_config_get_account(ctx);
	sn_sv actname = gcli_config_find_by_key(
		ctx, account, "account");
	sn_sv actname;

	free(account);
	if (!account)
		return NULL;

	actname = gcli_config_find_by_key(ctx, account, "account");
	free(account);
	return sn_sv_to_cstr(actname);
}

diff --git a/src/cmd/repos.c b/src/cmd/repos.c
index 7b66cd2e..3e9504dc 100644
--- a/src/cmd/repos.c
+++ b/src/cmd/repos.c
@@ -74,7 +74,7 @@ gcli_print_repos(enum gcli_output_flags const flags,
	struct gcli_tblcoldef cols[] = {
		{ .name = "FORK",     .type = GCLI_TBLCOLTYPE_BOOL,   .flags = 0 },
		{ .name = "VISBLTY",  .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 },
		{ .name = "DATE",     .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 },
		{ .name = "DATE",     .type = GCLI_TBLCOLTYPE_TIME_T, .flags = 0 },
		{ .name = "FULLNAME", .type = GCLI_TBLCOLTYPE_STRING, .flags = 0 },
	};

-- 
2.47.1

[PATCH gcli 2/2] Fix github API error 422 on `gcli forks create' Export this patch

The github distinction between user and organisation, noted in
github_get_repos(), is relevant also for gcli forks. This separates into
github_user_is_org() the code from github_get_repos() used to determine if
the user is an organisation, and uses that in github_fork_create().

Also match manpage treatment of -i option with --help output
---
 docs/gcli-forks.1.in        |  2 +-
 include/gcli/github/repos.h |  2 ++
 src/github/forks.c          | 11 ++++++++++-
 src/github/repos.c          | 38 ++++++++++++++++++++-----------------
 4 files changed, 34 insertions(+), 19 deletions(-)

diff --git a/docs/gcli-forks.1.in b/docs/gcli-forks.1.in
index 4f68de54..3b2a3c59 100644
--- a/docs/gcli-forks.1.in
+++ b/docs/gcli-forks.1.in
@@ -14,7 +14,7 @@
.Nm
.Cm create
.Op Fl o Ar owner Fl r Ar repo
.Fl i Ar target-owner
.Op Fl i Ar target-owner
.Sh DESCRIPTION
Use
.Nm
diff --git a/include/gcli/github/repos.h b/include/gcli/github/repos.h
index 4acd7798..f6b192d4 100644
--- a/include/gcli/github/repos.h
+++ b/include/gcli/github/repos.h
@@ -39,6 +39,8 @@
int github_repo_make_url(struct gcli_ctx *ctx, struct gcli_path const *path,
                         char **url, char const *suffix_fmt, ...);

int github_user_is_org(struct gcli_ctx *ctx, char const *e_owner);

int github_get_repos(struct gcli_ctx *ctx, char const *owner, int max,
                     struct gcli_repo_list *out);

diff --git a/src/github/forks.c b/src/github/forks.c
index c84cc1ca..2fedd154 100644
--- a/src/github/forks.c
+++ b/src/github/forks.c
@@ -67,13 +67,22 @@ github_fork_create(struct gcli_ctx *ctx,
	char *url = NULL;
	char *post_data = NULL;
	int rc = 0;
	bool is_org = false;

	if (in) {
		char *const e_in = gcli_urlencode(in);
		rc = github_user_is_org(ctx, e_in);
		free(e_in);
		if (rc < 0)
			return rc;
		is_org = rc;
	}

	rc = github_repo_make_url(ctx, repo_path, &url, "/forks");
	if (rc < 0)
		return rc;

	if (in) {
	if (is_org) {
		struct gcli_jsongen gen = {0};

		gcli_jsongen_init(&gen);
diff --git a/src/github/repos.c b/src/github/repos.c
index 17d0b9f5..b63548a4 100644
--- a/src/github/repos.c
+++ b/src/github/repos.c
@@ -75,13 +75,28 @@ github_repo_make_url(struct gcli_ctx *ctx, struct gcli_path const *const path,
	return rc;
}

int
github_user_is_org(struct gcli_ctx *ctx, char const *e_owner)
{
	/* Github is a little stupid in that it distinguishes
	 * organizations and users. Thus, we have to find out, whether the
	 * <org> param is a user or an actual organization. */
	char *url = sn_asprintf("%s/users/%s", gcli_get_apibase(ctx), e_owner);
	int const rc = gcli_curl_test_success(ctx, url);
	free(url);

	/* 0 = failed, 1 = success, -1 = error (just like a BOOL in Win32
	 * /sarc). But to make the name of the function make sense, reverse
	 * non-negative return values (failure means user *is* an org);
	 * negative return to indiciate error is preserved */
	return rc < 0 ? rc : !rc;
}

int
github_get_repos(struct gcli_ctx *ctx, char const *owner, int const max,
                 struct gcli_repo_list *const list)
{
	char *url = NULL;
	char *e_owner = NULL;
	int rc = 0;

	struct gcli_fetch_list_ctx lf = {
		.listp = &list->repos,
@@ -90,30 +105,19 @@ github_get_repos(struct gcli_ctx *ctx, char const *owner, int const max,
		.parse = (parsefn)(parse_github_repos),
	};

	e_owner = gcli_urlencode(owner);
	char *e_owner = gcli_urlencode(owner);
	int rc = github_user_is_org(ctx, e_owner);

	/* Github is a little stupid in that it distinguishes
	 * organizations and users. Thus, we have to find out, whether the
	 * <org> param is a user or an actual organization. */
	url = sn_asprintf("%s/users/%s", gcli_get_apibase(ctx), e_owner);

	/* 0 = failed, 1 = success, -1 = error (just like a BOOL in Win32
	 * /sarc) */
	rc = gcli_curl_test_success(ctx, url);
	if (rc < 0) {
		free(url);
	if (rc < 0)
		return rc;
	}

	if (rc) {
	if (!rc) {
		/* it is a user */
		free(url);
		url = sn_asprintf("%s/users/%s/repos",
		                  gcli_get_apibase(ctx),
		                  e_owner);
	} else {
		/* this is an actual organization */
		free(url);
		url = sn_asprintf("%s/orgs/%s/repos",
		                  gcli_get_apibase(ctx),
		                  e_owner);
-- 
2.47.1