diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..db11d5a --- /dev/null +++ b/src/main.c @@ -0,0 +1,132 @@ +#include <getopt.h> +#include <string.h> +#include <unistd.h> + +#include <curl/curl.h> + +#include "config.h" +#include "git.h" +#include "github.h" +#include "github_types.h" +#include "precheck.h" + +static int load_config(int argc, char **argv, struct config **cfg_out) +{ + int opt, opt_idx = 0; + size_t i; + char *cfg_path = NULL; + + static struct option long_options[] = { + {"config", required_argument, 0, 'c'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0}}; + + while ((opt = getopt_long(argc, argv, "C:c:h", long_options, + &opt_idx)) != -1) { + switch (opt) { + case 'C': + case 'c': + cfg_path = optarg; + break; + case 'h': + fprintf(stderr, + "Usage: %s [--config <file>] [--help]\n", + argv[0]); + return 0; + default: + fprintf(stderr, "Unknown option: %c\n", opt); + fprintf(stderr, + "Usage: %s [--config <file>] [--help]\n", + argv[0]); + return 1; + } + } + + // Config file given, use it + if (cfg_path) { + *cfg_out = config_read(cfg_path); + return *cfg_out == NULL; + } + + // No config file given, try the default locations + for (i = 0; config_locations[i]; i++) { + fprintf(stderr, "Trying config file: %s\n", + config_locations[i]); + *cfg_out = config_read(config_locations[i]); + if (*cfg_out) { + fprintf(stderr, "Using config file: %s\n", + config_locations[i]); + return 0; + } + } + fprintf(stderr, "Failed to read config file\n"); + return 1; +} + +int main(int argc, char **argv) +{ + curl_global_init(CURL_GLOBAL_DEFAULT); + + struct config *cfg = NULL; + const int ret = load_config(argc, argv, &cfg); + if (ret != 0 || !cfg) + return ret; + + if (precheck_self(cfg)) { + fprintf(stderr, "Precheck failed\n"); + config_free(cfg); + return 1; + } + + const struct github_ctx ctx = { + .endpoint = cfg->endpoint, + .token = cfg->token, + .user_agent = cfg->user_agent, + }; + github_client *client = github_client_new(ctx); + if (!client) { + fprintf(stderr, "Failed to create GitHub client\n"); + return 1; + } + + // Get identity + char *login = github_client_identity(client); + + struct list_repos_res res; + char *end_cursor = NULL; + int status = 0; + do { + if (github_client_list_user_repos(client, cfg->owner, + end_cursor, &res)) + return 1; + + for (size_t i = 0; i < res.repos_len; i++) { + printf("Repo: %s\t%s\n", res.repos[i].name, + res.repos[i].url); + + const struct repo_ctx repo = { + .cfg = cfg, + .name = res.repos[i].name, + .url = res.repos[i].url, + .username = login, + }; + if (git_mirror_repo(&repo) != 0) { + fprintf(stderr, "Failed to mirror repo\n"); + status = 1; + break; + } + } + + free(end_cursor); + end_cursor = strdup(res.end_cursor); + + list_repos_res_free(res); + } while (res.has_next_page); + + free(end_cursor); + github_client_free(client); + free(login); + config_free(cfg); + curl_global_cleanup(); + return status; +} |