diff options
author | 2025-04-09 13:24:53 -0700 | |
---|---|---|
committer | 2025-04-11 00:15:18 -0700 | |
commit | f277f41d83d450a1f28d350bb7d6da075d1d2741 (patch) | |
tree | e197a7de7e26b47cec57a46acdde4b6c74889ad5 /src/main.c | |
download | github-mirror-f277f41d83d450a1f28d350bb7d6da075d1d2741.tar.gz github-mirror-f277f41d83d450a1f28d350bb7d6da075d1d2741.tar.zst github-mirror-f277f41d83d450a1f28d350bb7d6da075d1d2741.zip |
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
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; +} |