From f277f41d83d450a1f28d350bb7d6da075d1d2741 Mon Sep 17 00:00:00 2001 From: Anshul Gupta Date: Wed, 9 Apr 2025 13:24:53 -0700 Subject: Initial Commit Add cmake github workflow Install dependencies in gh action Fix missing directory Fix compiler errors Fix group name to gid conversion Force cjson to statically link Add header guards to query headers Add install and cpack to CMakeLists.txt Add config search and CLI arg parsing Improve docs for git.c Fix program continuing on -h flag --- src/main.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/main.c (limited to 'src/main.c') 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 +#include +#include + +#include + +#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 ] [--help]\n", + argv[0]); + return 0; + default: + fprintf(stderr, "Unknown option: %c\n", opt); + fprintf(stderr, + "Usage: %s [--config ] [--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; +} -- cgit v1.2.3