WIP fetch command, very dirty
[gitlite/.git] / gitlite.c
1 #include <getopt.h>
2 #include <libgen.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <sys/param.h>
7 #include <sys/types.h>
8 #include <sysexits.h>
9 #include <unistd.h>
10
11 #include <git2/clone.h>
12 #include <git2/errors.h>
13 #include <git2/global.h>
14
15 #define PRIuZ "zu"
16
17 #include "callbacks.h"
18
19
20 // Compile with:
21 // clang90 -o gitlite gitlite.c -lgit2 -I/usr/local/include -L/usr/local/lib -g
22
23 extern char *__progname;
24
25 void
26 git_bail_error(int rc) {
27         const git_error *err = NULL;
28
29         if (rc < 0) {
30                 err = git_error_last();
31                 if (err)
32                         printf("ERROR %d: %s\n", err->klass, err->message);
33                 else
34                         printf("ERROR %d: cannot fetch error info\n", rc);
35         }
36
37 //    exit(rc);
38 }
39
40 void
41 util_stripext(char *path) {
42         char *end = path + strlen(path);
43
44         while (end > path && *end != '.') {
45                 --end;
46         }
47
48         if (end > path) {
49                 *end = '\0';
50         }
51 }
52
53 static
54 void usage(void) {
55         fprintf(stderr, "usage: %s --<git-cmd> ...\n", __progname);
56         fprintf(stderr, "usage: %s --clone <git-url> [local-path]\n", __progname);
57 }
58
59 int
60 main(int argc, char *argv[]) {
61         int rc;
62         int ch = 0;
63         int opt_index = -1;
64         int do_clone, do_fetch, do_log = 0;
65         char buff[MAXPATHLEN];
66         char *url = NULL;
67         char *ext = NULL;
68         char *local_path = NULL;
69         git_repository *cloned_repo = NULL;
70
71         static struct option longopts[] = {
72                         {"clone", required_argument, NULL, 'c'},
73                         {"fetch", no_argument, NULL, 'f'},
74                         {"log", no_argument, NULL, 'l'},
75                         {NULL, 0, NULL, 0}
76         };
77
78         if (argc == 1) {
79                 usage();
80                 return (EX_USAGE);
81         }
82
83         while ((ch = getopt_long(argc, argv, "c:fl", longopts, &opt_index)) != -1) {
84                 switch (ch) {
85                 case 'c':
86                         do_clone = 1;
87                         url = optarg;
88                         break;
89                 case 'f':
90                         do_fetch = 1;
91                         break;
92                 case 'l':
93                         do_log = 1;
94                         break;
95                 default:
96                         usage();
97                         return (EX_USAGE);
98                 }
99         }
100         argc -= optind;
101         argv += optind;
102
103         if (do_clone) {
104                 printf("handle git clone command\n");
105
106                 git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
107                 git_checkout_options co_opts = GIT_CHECKOUT_OPTIONS_INIT;
108
109                 co_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
110                 co_opts.progress_cb = NULL;
111                 co_opts.progress_payload = NULL;
112                 clone_opts.checkout_opts = co_opts;
113                 clone_opts.fetch_opts.callbacks.sideband_progress = NULL;
114                 clone_opts.fetch_opts.callbacks.transfer_progress = NULL;
115                 clone_opts.fetch_opts.callbacks.credentials = NULL;
116                 clone_opts.fetch_opts.callbacks.payload = NULL;
117
118                 rc = git_libgit2_init();
119                 git_bail_error(rc);
120
121                 local_path = argv[0];
122                 if (local_path == NULL) {
123                         ext = strdup(basename(__DECONST(char *, url)));
124                         util_stripext(__DECONST(char *, ext));
125                         asprintf(&local_path, "%s/%s", getwd(buff), ext);
126                 }
127
128                 rc = git_clone(&cloned_repo, url, local_path, &clone_opts);
129                 git_bail_error(rc);
130
131         } else if (do_fetch) {
132                 fprintf(stderr, "handle git fetch command\n");
133
134                 rc = git_libgit2_init();
135                 git_bail_error(rc);
136
137         git_repository *repo = NULL;
138
139         rc = git_repository_open(&repo, argv[0]);
140         git_bail_error(rc);
141
142
143         git_remote *remote = NULL;
144         rc = git_remote_lookup(&remote, repo, "origin");
145         git_bail_error(rc);
146
147
148         const git_indexer_progress *stats;
149         git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
150         fetch_opts.callbacks.update_tips = &update_cb;
151         fetch_opts.callbacks.sideband_progress = &progress_cb;
152         fetch_opts.callbacks.transfer_progress = transfer_progress_cb;
153         fetch_opts.callbacks.credentials = NULL;
154
155         //rc = git_remote_add_fetch(repo, "origin", "master");
156         //git_bail_error(rc);
157         printf("Fetching %s for repo %p\n", argv[0], repo);
158         rc = git_remote_fetch(remote, NULL, &fetch_opts, "fetch");
159         git_bail_error(rc);
160
161         __asm("int $3");
162         stats = git_remote_stats(remote);
163
164         if (stats->local_objects > 0) {
165             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);
166         } else{
167             printf("\rReceived %u/%u objects in %" PRIuZ "bytes\n", stats->indexed_objects, stats->total_objects, stats->received_bytes);
168         }
169
170         git_remote_free(remote);
171
172         } else if (do_log) {
173                 fprintf(stderr, "handle git log command\n");
174                 return (-1);
175         }
176
177         if (cloned_repo)
178                 git_repository_free(cloned_repo);
179
180         rc = git_libgit2_shutdown();
181         git_bail_error(rc);
182
183         if (ext != NULL)
184                 free(ext);
185
186         return (rc);
187 }