diff options
-rw-r--r-- | src/config.c | 6 | ||||
-rw-r--r-- | src/config.h | 3 | ||||
-rw-r--r-- | src/git.c | 51 | ||||
-rw-r--r-- | src/git.h | 2 | ||||
-rw-r--r-- | src/main.c | 49 | ||||
-rw-r--r-- | src/precheck.c | 15 |
6 files changed, 93 insertions, 33 deletions
diff --git a/src/config.c b/src/config.c index a80aefb..56aac11 100644 --- a/src/config.c +++ b/src/config.c @@ -300,7 +300,11 @@ static int config_parse(struct config *cfg) return 0; } -static void config_defaults(struct config *cfg) { cfg->git_base = "/srv/git"; } +static void config_defaults(struct config *cfg) +{ + cfg->quiet = 0; + cfg->git_base = "/srv/git"; +} static int config_validate(const struct config *cfg) { diff --git a/src/config.h b/src/config.h index 0f4709f..f5dfe2d 100644 --- a/src/config.h +++ b/src/config.h @@ -36,6 +36,9 @@ struct config { char *contents; size_t contents_len; + /// Quiet mode + int quiet; + /// Repo owners to mirror struct github_cfg *head; @@ -157,9 +157,11 @@ static int contains_mirror(const char *path) * Creates a mirror of the git repository at the specified path. * @param path Full path to the git repository * @param ctx Context containing the repository information + * @param quiet Suppress output if non-zero * @return 0 on success, -1 on error */ -static int create_mirror(const char *path, const struct repo_ctx *ctx) +static int create_mirror(const char *path, const struct repo_ctx *ctx, + const int quiet) { const pid_t pid = fork(); if (pid < 0) { @@ -174,10 +176,17 @@ static int create_mirror(const char *path, const struct repo_ctx *ctx) ctx->cfg->token); // Run git - char *args[] = { - "git", "clone", "--mirror", - url, (char *) path, NULL, - }; + char *args[7]; + int i = 0; + args[i++] = "git"; + args[i++] = "clone"; + args[i++] = "--mirror"; + if (quiet) + args[i++] = "--quiet"; + args[i++] = url; + args[i++] = (char *) path; + args[i] = NULL; + execvp("git", args); perror("execvp"); _exit(127); // execvp only returns on error @@ -234,9 +243,10 @@ static int create_git_path(const struct repo_ctx *ctx) /** * Updates the git repository at the specified path from the remote. * @param path Full path to the git repository + * @param quiet Suppress output if non-zero * @return 0 on success, -1 on error */ -static int update_mirror(const char *path) +static int update_mirror(const char *path, int quiet) { const pid_t pid = fork(); if (pid < 0) { @@ -246,10 +256,19 @@ static int update_mirror(const char *path) if (pid == 0) { // Child process - char *args[] = { - "git", "--git-dir", (char *) path, "remote", - "update", "--prune", NULL, - }; + char *args[9]; + int i = 0; + args[i++] = "git"; + args[i++] = "--git-dir"; + args[i++] = (char *) path; + args[i++] = "fetch"; + args[i++] = "--prune"; + if (quiet) + args[i++] = "--quiet"; + args[i++] = "--all"; + args[i++] = "--tags"; + args[i] = NULL; + execvp("git", args); perror("execvp"); _exit(127); // execvp only returns on error @@ -271,7 +290,7 @@ static int update_mirror(const char *path) return -1; // Error occurred } -int git_mirror_repo(const struct repo_ctx *ctx) +int git_mirror_repo(const struct repo_ctx *ctx, int quiet) { int ret = 0; char *path = get_git_path(ctx->git_base, ctx->cfg->owner, ctx->name); @@ -283,8 +302,9 @@ int git_mirror_repo(const struct repo_ctx *ctx) // Check whether repo exists if (contains_mirror(path)) { // Repo exists, so we can just update it - printf("Repo already exists, updating...\n"); - if (update_mirror(path) == -1) { + if (!quiet) + printf("Repo already exists, updating...\n"); + if (update_mirror(path, quiet) == -1) { perror("update_mirror"); ret = -1; goto end; @@ -293,13 +313,14 @@ int git_mirror_repo(const struct repo_ctx *ctx) } // Repo does not exist, so we need to clone it - printf("Repo does not exist, cloning...\n"); + if (!quiet) + printf("Repo does not exist, cloning...\n"); if (create_git_path(ctx) == -1) { perror("create_git_path"); ret = -1; goto end; } - if (create_mirror(path, ctx) == -1) { + if (create_mirror(path, ctx, quiet) == -1) { perror("create_mirror"); ret = -1; } @@ -19,7 +19,7 @@ struct repo_ctx { const char *username; }; -int git_mirror_repo(const struct repo_ctx *ctx); +int git_mirror_repo(const struct repo_ctx *ctx, int quiet); #endif // GIT_H @@ -14,14 +14,16 @@ static int load_config(int argc, char **argv, struct config **cfg_out) { int opt, opt_idx = 0; size_t i; + int quiet = 0; char *cfg_path = NULL; static struct option long_options[] = { {"config", required_argument, 0, 'c'}, {"help", no_argument, 0, 'h'}, + {"quiet", no_argument, 0, 'q'}, {0, 0, 0, 0}}; - while ((opt = getopt_long(argc, argv, "C:c:h", long_options, + while ((opt = getopt_long(argc, argv, "C:c:h:q", long_options, &opt_idx)) != -1) { switch (opt) { case 'C': @@ -33,10 +35,14 @@ static int load_config(int argc, char **argv, struct config **cfg_out) "Usage: %s [--config <file>] [--help]\n", argv[0]); return 0; + case 'q': + quiet = 1; + break; default: fprintf(stderr, "Unknown option: %c\n", opt); fprintf(stderr, - "Usage: %s [--config <file>] [--help]\n", + "Usage: %s [--config <file>] [--quiet] " + "[--help]\n", argv[0]); return 1; } @@ -45,17 +51,24 @@ static int load_config(int argc, char **argv, struct config **cfg_out) // Config file given, use it if (cfg_path) { *cfg_out = config_read(cfg_path); - return *cfg_out == NULL; + if (*cfg_out) { + (*cfg_out)->quiet = quiet; + return 0; + } + return 1; } // 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]); + if (!quiet) + 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]); + if (!quiet) + fprintf(stderr, "Using config file: %s\n", + config_locations[i]); + (*cfg_out)->quiet = quiet; return 0; } } @@ -63,7 +76,8 @@ static int load_config(int argc, char **argv, struct config **cfg_out) return 1; } -static int mirror_owner(const char *git_base, const struct github_cfg *cfg) +static int mirror_owner(const char *git_base, const struct github_cfg *cfg, + int quiet) { const struct github_ctx ctx = { .endpoint = cfg->endpoint, @@ -89,13 +103,15 @@ static int mirror_owner(const char *git_base, const struct github_cfg *cfg) for (size_t i = 0; i < res.repos_len; i++) { if (cfg->skip_forks && res.repos[i].is_fork) { - fprintf(stderr, "Skipping forked repo: %s\n", - res.repos[i].name); + if (!quiet) + printf("Skipping forked repo: %s\n", + res.repos[i].name); continue; } - printf("Repo: %s\t%s\n", res.repos[i].name, - res.repos[i].url); + if (!quiet) + printf("Repo: %s\t%s\n", res.repos[i].name, + res.repos[i].url); const struct repo_ctx repo = { .git_base = git_base, @@ -104,7 +120,7 @@ static int mirror_owner(const char *git_base, const struct github_cfg *cfg) .url = res.repos[i].url, .username = login, }; - if (git_mirror_repo(&repo) != 0) { + if (git_mirror_repo(&repo, quiet) != 0) { fprintf(stderr, "Failed to mirror repo\n"); status = -1; break; @@ -140,10 +156,11 @@ int main(int argc, char **argv) } int status = 0; - struct github_cfg *owner = cfg->head; + const struct github_cfg *owner = cfg->head; while (owner) { - printf("Mirroring owner: %s\n", owner->owner); - if (mirror_owner(cfg->git_base, owner)) { + if (!cfg->quiet) + printf("Mirroring owner: %s\n", owner->owner); + if (mirror_owner(cfg->git_base, owner, cfg->quiet)) { fprintf(stderr, "Failed to mirror owner: %s\n", owner->owner); status = 1; diff --git a/src/precheck.c b/src/precheck.c index cbabd2c..78501ba 100644 --- a/src/precheck.c +++ b/src/precheck.c @@ -6,6 +6,7 @@ #include <stdio.h> #include <sys/errno.h> +#include <sys/fcntl.h> #include <sys/stat.h> #include <sys/wait.h> #include <unistd.h> @@ -24,6 +25,20 @@ static int has_git(void) if (pid == 0) { // Child process + + // Redirect stdout to /dev/null + const int devnull = open("/dev/null", O_WRONLY); + if (devnull == -1) { + perror("open"); + _exit(127); + } + if (dup2(devnull, STDOUT_FILENO) == -1) { + perror("dup2"); + close(devnull); + _exit(127); + } + close(devnull); + char *args[] = {"git", "--version", NULL}; execvp("git", args); _exit(127); // execvp only returns on error |