WIP fetch command, very dirty
[gitlite/.git] / gitlite.c
index 8ffc3d6fa9d4d8d21b623f2d3fc01ee7eaff1f7b..5e26dbe8eb37aef1da5da2ee700ec0e6ab78cafb 100644 (file)
--- a/gitlite.c
+++ b/gitlite.c
+#include <getopt.h>
+#include <libgen.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sysexits.h>
+#include <unistd.h>
 
-#include <git2/global.h>
 #include <git2/clone.h>
 #include <git2/errors.h>
+#include <git2/global.h>
+
+#define PRIuZ "zu"
+
+#include "callbacks.h"
+
 
 // Compile with:
 // clang90 -o gitlite gitlite.c -lgit2 -I/usr/local/include -L/usr/local/lib -g
 
+extern char *__progname;
+
 void
-git_bail_error(int rc)
-{
-    const git_error *err = NULL;
+git_bail_error(int rc) {
+       const git_error *err = NULL;
 
        if (rc < 0) {
                err = git_error_last();
-               if (err) 
-            printf("ERROR %d: %s\n", err->klass, err->message);
-               else 
-            printf("ERROR %d: cannot fetch error info\n", rc);
+               if (err)
+                       printf("ERROR %d: %s\n", err->klass, err->message);
+               else
+                       printf("ERROR %d: cannot fetch error info\n", rc);
+       }
+
+//    exit(rc);
+}
+
+void
+util_stripext(char *path) {
+       char *end = path + strlen(path);
+
+       while (end > path && *end != '.') {
+               --end;
+       }
 
-    }
+       if (end > path) {
+               *end = '\0';
+       }
+}
+
+static
+void usage(void) {
+       fprintf(stderr, "usage: %s --<git-cmd> ...\n", __progname);
+       fprintf(stderr, "usage: %s --clone <git-url> [local-path]\n", __progname);
 }
 
 int
-main(int argc, char *argv[])
-{
+main(int argc, char *argv[]) {
        int rc;
-       const char *url = "https://github.com/freebsd/pkg.git";
-       //const char *url = "https://github.com/freebsd/freebsd.git";
-       const char *local_path = "/home/sbz/git/src";
-       git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
-       git_checkout_options co_opts = GIT_CHECKOUT_OPTIONS_INIT;
+       int ch = 0;
+       int opt_index = -1;
+       int do_clone, do_fetch, do_log = 0;
+       char buff[MAXPATHLEN];
+       char *url = NULL;
+       char *ext = NULL;
+       char *local_path = NULL;
        git_repository *cloned_repo = NULL;
 
-       co_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
-       co_opts.progress_cb = NULL;
-       co_opts.progress_payload = NULL;
-       clone_opts.checkout_opts = co_opts;
-       clone_opts.fetch_opts.callbacks.sideband_progress = NULL;
-       clone_opts.fetch_opts.callbacks.transfer_progress = NULL;
-       clone_opts.fetch_opts.callbacks.credentials = NULL;
-       clone_opts.fetch_opts.callbacks.payload = NULL;
+       static struct option longopts[] = {
+                       {"clone", required_argument, NULL, 'c'},
+                       {"fetch", no_argument, NULL, 'f'},
+                       {"log", no_argument, NULL, 'l'},
+                       {NULL, 0, NULL, 0}
+       };
 
-       rc = git_libgit2_init();
-       git_bail_error(rc);
+       if (argc == 1) {
+               usage();
+               return (EX_USAGE);
+       }
 
-       rc = git_clone(&cloned_repo, url, local_path, &clone_opts);
-       git_bail_error(rc);
+       while ((ch = getopt_long(argc, argv, "c:fl", longopts, &opt_index)) != -1) {
+               switch (ch) {
+               case 'c':
+                       do_clone = 1;
+                       url = optarg;
+                       break;
+               case 'f':
+                       do_fetch = 1;
+                       break;
+               case 'l':
+                       do_log = 1;
+                       break;
+               default:
+                       usage();
+                       return (EX_USAGE);
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       if (do_clone) {
+               printf("handle git clone command\n");
+
+               git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
+               git_checkout_options co_opts = GIT_CHECKOUT_OPTIONS_INIT;
+
+               co_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
+               co_opts.progress_cb = NULL;
+               co_opts.progress_payload = NULL;
+               clone_opts.checkout_opts = co_opts;
+               clone_opts.fetch_opts.callbacks.sideband_progress = NULL;
+               clone_opts.fetch_opts.callbacks.transfer_progress = NULL;
+               clone_opts.fetch_opts.callbacks.credentials = NULL;
+               clone_opts.fetch_opts.callbacks.payload = NULL;
+
+               rc = git_libgit2_init();
+               git_bail_error(rc);
+
+               local_path = argv[0];
+               if (local_path == NULL) {
+                       ext = strdup(basename(__DECONST(char *, url)));
+                       util_stripext(__DECONST(char *, ext));
+                       asprintf(&local_path, "%s/%s", getwd(buff), ext);
+               }
+
+               rc = git_clone(&cloned_repo, url, local_path, &clone_opts);
+               git_bail_error(rc);
+
+       } else if (do_fetch) {
+               fprintf(stderr, "handle git fetch command\n");
+
+               rc = git_libgit2_init();
+               git_bail_error(rc);
+
+        git_repository *repo = NULL;
+
+        rc = git_repository_open(&repo, argv[0]);
+        git_bail_error(rc);
+
+
+        git_remote *remote = NULL;
+        rc = git_remote_lookup(&remote, repo, "origin");
+        git_bail_error(rc);
+
+
+        const git_indexer_progress *stats;
+        git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
+        fetch_opts.callbacks.update_tips = &update_cb;
+        fetch_opts.callbacks.sideband_progress = &progress_cb;
+        fetch_opts.callbacks.transfer_progress = transfer_progress_cb;
+        fetch_opts.callbacks.credentials = NULL;
+
+        //rc = git_remote_add_fetch(repo, "origin", "master");
+        //git_bail_error(rc);
+        printf("Fetching %s for repo %p\n", argv[0], repo);
+        rc = git_remote_fetch(remote, NULL, &fetch_opts, "fetch");
+        git_bail_error(rc);
+
+        __asm("int $3");
+        stats = git_remote_stats(remote);
+
+        if (stats->local_objects > 0) {
+            printf("\rReceived %u/%u objects in %" PRIuZ " bytes (used %u local objects)\n", stats->indexed_objects, stats->total_objects, stats->received_bytes, stats->local_objects);
+        } else{
+            printf("\rReceived %u/%u objects in %" PRIuZ "bytes\n", stats->indexed_objects, stats->total_objects, stats->received_bytes);
+        }
+
+        git_remote_free(remote);
+
+       } else if (do_log) {
+               fprintf(stderr, "handle git log command\n");
+               return (-1);
+       }
 
        if (cloned_repo)
                git_repository_free(cloned_repo);
@@ -55,5 +180,8 @@ main(int argc, char *argv[])
        rc = git_libgit2_shutdown();
        git_bail_error(rc);
 
-    return (rc);
+       if (ext != NULL)
+               free(ext);
+
+       return (rc);
 }