summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Anshul Gupta <ansg191@anshulg.com> 2025-04-11 16:18:31 -0700
committerGravatar Anshul Gupta <ansg191@anshulg.com> 2025-04-11 16:18:31 -0700
commit9f46ca93b86e5bcf43e11d6f533f82c68794e0b1 (patch)
treeb1845c78bb8efa71e1a3b34fd93bee47b6da4d9b /src
parentf199bc5c0b4ed3219eedf61757e66dee2f328712 (diff)
downloadgithub-mirror-9f46ca93b86e5bcf43e11d6f533f82c68794e0b1.tar.gz
github-mirror-9f46ca93b86e5bcf43e11d6f533f82c68794e0b1.tar.zst
github-mirror-9f46ca93b86e5bcf43e11d6f533f82c68794e0b1.zip
Add quiet mode
Diffstat (limited to 'src')
-rw-r--r--src/config.c6
-rw-r--r--src/config.h3
-rw-r--r--src/git.c51
-rw-r--r--src/git.h2
-rw-r--r--src/main.c49
-rw-r--r--src/precheck.c15
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;
diff --git a/src/git.c b/src/git.c
index 8d5673f..b8156ce 100644
--- a/src/git.c
+++ b/src/git.c
@@ -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;
}
diff --git a/src/git.h b/src/git.h
index ad3902d..06d3e92 100644
--- a/src/git.h
+++ b/src/git.h
@@ -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
diff --git a/src/main.c b/src/main.c
index f17bc99..24db79a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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