Skip to content

Commit

Permalink
Allow for missing config files
Browse files Browse the repository at this point in the history
Squashed commit of the following:

commit 49dd378ab14107eedd405a41e91ac3672808f9d3
Author: Nico Sonack <[email protected]>
Date:   Wed May 25 14:07:38 2022 +0200

    Bump version

commit 7eec9481353c3bd0c165694888344138fa938c9a
Author: Nico Sonack <[email protected]>
Date:   Wed May 25 14:04:33 2022 +0200

    reintroduce forge type override

commit 2364391686ccc05918cfd468f541542b77070287
Author: Nico Sonack <[email protected]>
Date:   Wed May 25 13:17:39 2022 +0200

    add -q option to suppress warning messages

commit 7a31915da235d56642ac3732d1e2c7e8646c10b0
Author: Nico Sonack <[email protected]>
Date:   Wed May 25 13:17:26 2022 +0200

    allow for missing config in github

commit f778fcebe5c5dbb66deb40f19813327d2ee7ac1a
Author: Nico Sonack <[email protected]>
Date:   Wed May 25 13:01:41 2022 +0200

    gitlab: allow missing config files with default values

commit 4bda340b70196550245b5e05dbdda89f2c50677e
Author: Nico Sonack <[email protected]>
Date:   Wed May 25 13:00:55 2022 +0200

    Add warn and warnx functions

Thanks to moshe for reporting.
  • Loading branch information
herrhotzenplotz committed May 25, 2022
1 parent f821f0a commit 5fc197a
Show file tree
Hide file tree
Showing 10 changed files with 372 additions and 238 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
PROGS = ghcli
LIBS = libghcli.a

GHCLI_VERSION = 0.7.2-alpha
GHCLI_VERSION = 0.7.3-alpha
# These and LDFLAGS can be overwritten
CFLAGS = -std=iso9899:1999 \
-Ithirdparty/pdjson/ \
Expand Down
19 changes: 19 additions & 0 deletions docs/ghcli.1
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ Do not output ANSI escape sequences for changing text
formatting. Default is to output colors unless stdout is not a
tty. See
.Xr isatty 3 .
.It Fl q , -quiet
Suppress warning messages about missing config files and various other
things.
.It Fl t , -type Ar forge-type
Forcefully override the forge type if it can't be inferred
correctly. Set
.Ar forge-type
to
.Sq github
or
.Sq gitlab
to connect to the corresponding services.
.El

Common options across almost all of the subcommands are:
Expand Down Expand Up @@ -237,6 +249,13 @@ Get a summary and comments of upstream PR #22:
.Bd -literal -width indent
$ ghcli pulls -p 22 summary comments
.Ed

List the last 10 issues in contour-terminal/contour ignoring all
warnings and forcing a connection to GitHub.
.Bd -literal -width indent
ghcli -t github -q issues -o contour-terminal -r contour -a -n10
.Ed
This works when you don't have a config file in place.
.Sh SEE ALSO
.Xr git 1 ,
.Xr ghcli-issues 1 ,
Expand Down
74 changes: 60 additions & 14 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ static struct ghcli_config {

const char *override_default_account;
const char *override_remote;
int override_forgetype;
int colors_disabled;

sn_sv buffer;
Expand Down Expand Up @@ -182,7 +183,7 @@ init_local_config(void)

if (line.length == 0)
errx(1, "%s:%d: Unexpected end of line",
path, curr_line);
path, curr_line);

// Comments
if (line.data[0] == '#') {
Expand Down Expand Up @@ -272,7 +273,7 @@ parse_section_title(struct config_parser *input)
size_t len = 0;
if (input->buffer.length == 0)
errx(1, "%s:%d: unexpected end of input in section title",
input->filename, input->line);
input->filename, input->line);


while (!isspace(input->buffer.data[len]) && input->buffer.data[len] != '{')
Expand Down Expand Up @@ -314,15 +315,15 @@ parse_config_section(struct config_parser *input)

if (section->entries_size == CONFIG_MAX_ENTRIES)
errx(1, "error: too many config entries in section "SV_FMT,
SV_ARGS(section->title));
SV_ARGS(section->title));

parse_keyvaluepair(input, &section->entries[section->entries_size++]);
skip_ws_and_comments(input);
}

if (input->buffer.length == 0)
errx(1, "%s:%d: missing '}' before end of file",
input->filename, input->line);
input->filename, input->line);

input->buffer.length -= 1;
input->buffer.data += 1;
Expand All @@ -339,22 +340,28 @@ parse_config_file(struct config_parser *input)
}
}

static void
/**
* Try to load up the local config file if it exists. If we succeed,
* return 0. Otherwise return -1.
*/
static int
ensure_config(void)
{
char *file_path = NULL;
struct config_parser parser = {0};

if (config.inited)
return;
return 0;

config.inited = true;

file_path = getenv("XDG_CONFIG_PATH");
if (!file_path) {
file_path = getenv("HOME");
if (!file_path)
errx(1, "Neither XDG_CONFIG_PATH nor HOME set in env");
if (!file_path) {
warnx("Neither XDG_CONFIG_PATH nor HOME set in env");
return -1;
}

/*
* Code duplication to avoid leaking pointers */
Expand All @@ -363,8 +370,10 @@ ensure_config(void)
file_path = sn_asprintf("%s/ghcli/config", file_path);
}

if (access(file_path, R_OK) < 0)
err(1, "Cannot access config file at %s", file_path);
if (access(file_path, R_OK) < 0) {
warn("Cannot access config file at %s", file_path);
return -1;
}

int len = sn_mmap_file(file_path, &config.mmap_pointer);
if (len < 0)
Expand All @@ -380,6 +389,8 @@ ensure_config(void)
parse_config_file(&parser);

free((void *)file_path);

return 0;
}

void
Expand All @@ -404,10 +415,22 @@ ghcli_config_init(int *argc, char ***argv)
.has_arg = no_argument,
.flag = &config.colors_disabled,
.val = 1 },
{ .name = "type",
.has_arg = required_argument,
.flag = NULL,
.val = 't' },
{ .name = "quiet",
.has_arg = no_argument,
.flag = NULL,
.val = 'q' },
{0},
};

while ((ch = getopt_long(*argc, *argv, "+a:r:c", options, NULL)) != -1) {
/* Before we parse options, invalidate the override type so it
* doesn't get confused later */
config.override_forgetype = -1;

while ((ch = getopt_long(*argc, *argv, "+a:r:cqt:", options, NULL)) != -1) {
switch (ch) {
case 'a': {
config.override_default_account = optarg;
Expand All @@ -418,6 +441,18 @@ ghcli_config_init(int *argc, char ***argv)
case 'c': {
config.colors_disabled = 1;
} break;
case 'q': {
sn_setquiet(1);
} break;
case 't': {
if (strcmp(optarg, "github") == 0)
config.override_forgetype = GHCLI_FORGE_GITHUB;
else if (strcmp(optarg, "gitlab") == 0)
config.override_forgetype = GHCLI_FORGE_GITLAB;
else
errx(1, "error: unknown forge type '%s'. "
"Have either github or gitlab.", optarg);
} break;
case 0: break;
case '?':
default:
Expand Down Expand Up @@ -544,6 +579,10 @@ ghcli_config_get_override_default_account(void)
ghcli_forge_type
ghcli_config_get_forge_type(void)
{
/* Hard override */
if (config.override_forgetype >= 0)
return config.override_forgetype;

ensure_config();
init_local_config();

Expand All @@ -554,8 +593,8 @@ ghcli_config_get_forge_type(void)
entry = ghcli_config_find_by_key(section, "forge-type");
if (sn_sv_null(entry))
errx(1,
"error: given default override account not found or "
"missing forge-type");
"error: given default override account not found or "
"missing forge-type");
} else {
entry = ghcli_local_config_find_by_key("forge-type");
}
Expand All @@ -569,7 +608,14 @@ ghcli_config_get_forge_type(void)
errx(1, "Unknown forge type "SV_FMT, SV_ARGS(entry));
}

return ghcli_gitconfig_get_forgetype(config.override_remote);
/* As a last resort, try to infer from the git remote */
int type = ghcli_gitconfig_get_forgetype(config.override_remote);
if (type < 0)
errx(1, "error: cannot infer forge type. "
"use -t <forge-type> to overrride manually.");

return type;

}

void
Expand Down
19 changes: 10 additions & 9 deletions src/curl.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,19 @@ ghcli_curl_check_api_error(

if (code != CURLE_OK)
errx(1,
"error: request to %s failed\n"
" : curl error: %s",
url,
curl_easy_strerror(code));
"error: request to %s failed\n"
" : curl error: %s",
url,
curl_easy_strerror(code));

curl_easy_getinfo(ghcli_curl_session, CURLINFO_RESPONSE_CODE, &status_code);

if (status_code >= 300L) {
errx(1,
"error: request to %s failed with code %ld\n"
" : API error: %s",
url, status_code,
ghcli_forge()->get_api_error_string(result));
"error: request to %s failed with code %ld\n"
" : API error: %s",
url, status_code,
ghcli_forge()->get_api_error_string(result));
}
}

Expand Down Expand Up @@ -304,7 +304,8 @@ ghcli_fetch_with_method(
headers = curl_slist_append(
headers,
"Content-Type: application/json");
headers = curl_slist_append(headers, auth_header);
if (auth_header)
headers = curl_slist_append(headers, auth_header);

*out = (ghcli_fetch_buffer) {0};

Expand Down
4 changes: 2 additions & 2 deletions src/forges.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ ghcli_forge(void)
return &gitlab_forge_descriptor;
default:
errx(1,
"error: cannot determine forge type. try forcing an account "
"with -a or create a .ghcli file.");
"error: cannot determine forge type. try forcing an account "
"with -a, specifying -t or create a .ghcli file.");
}
return NULL;
}
18 changes: 12 additions & 6 deletions src/gitconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ find_file_in_dotgit(const char *fname)
if (strcmp("/", curr_dir_path) == 0) {
free(curr_dir_path);
closedir(curr_dir);
errx(1, "error: not a git repository");
warn("not a git repository");
return NULL;
}
}

Expand Down Expand Up @@ -192,7 +193,7 @@ http_extractor(ghcli_gitremote *remote, const char *prefix)
remote->forge_type = GHCLI_FORGE_GITLAB;
} else {
warnx("non-github or non-gitlab https remotes are not supported "
"and will likely cause bugs");
"and will likely cause bugs");
}

pair.length -= prefix_size;
Expand Down Expand Up @@ -310,7 +311,10 @@ ghcli_gitconfig_read_gitconfig(void)
const char *path = NULL;
sn_sv buffer = {0};

path = ghcli_find_gitconfig();
path = ghcli_find_gitconfig();
if (!path)
return;

buffer.length = sn_mmap_file(path, (void **)&buffer.data);

while (buffer.length > 0) {
Expand Down Expand Up @@ -359,7 +363,7 @@ ghcli_gitconfig_add_fork_remote(const char *org, const char *repo)
if ((pid = fork()) == 0) {
printf("[INFO] git remote rename origin upstream\n");
execlp("git", "git", "remote",
"rename", "origin", "upstream", NULL);
"rename", "origin", "upstream", NULL);
} else if (pid > 0) {
int status = 0;
waitpid(pid, &status, 0);
Expand Down Expand Up @@ -412,8 +416,10 @@ ghcli_gitconfig_get_forgetype(const char *remote_name)
}
}

if (!remotes_size)
errx(1, "error: no remotes to auto-detect forge");
if (!remotes_size) {
warn("no remotes to auto-detect forge");
return -1;
}

return remotes[0].forge_type;
}
Expand Down
16 changes: 14 additions & 2 deletions src/github/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ github_default_account_name(void)
"github-default-account");

if (sn_sv_null(section_name))
errx(1, "Config file does not name a default GitHub account name.");
warnx("Config file does not name a default GitHub account name.");
}

return section_name;
Expand All @@ -54,18 +54,27 @@ char *
github_get_apibase(void)
{
sn_sv account_name = github_default_account_name();
if (sn_sv_null(account_name))
goto default_val;

sn_sv api_base = ghcli_config_find_by_key(account_name, "apibase");

if (sn_sv_null(api_base))
return "https://api.github.com";
goto default_val;

return sn_sv_to_cstr(api_base);

default_val:
return "https://api.github.com";
}

char *
github_get_authheader(void)
{
sn_sv account = github_default_account_name();
if (sn_sv_null(account))
return NULL;

sn_sv token = ghcli_config_find_by_key(account, "token");;
if (sn_sv_null(token))
errx(1, "Missing Github token");
Expand All @@ -76,6 +85,9 @@ sn_sv
github_get_account(void)
{
sn_sv section = github_default_account_name();
if (sn_sv_null(section))
return SV_NULL;

sn_sv account = ghcli_config_find_by_key(section, "account");;
if (!account.length)
errx(1, "Missing Github account name");
Expand Down
Loading

0 comments on commit 5fc197a

Please sign in to comment.