Merge branch 'tr/describe-advice'
[git] / remote-curl.c
1 #include "cache.h"
2 #include "remote.h"
3 #include "strbuf.h"
4 #include "walker.h"
5 #include "http.h"
6 #include "exec_cmd.h"
7
8 static struct ref *get_refs(struct walker *walker, const char *url)
9 {
10         struct strbuf buffer = STRBUF_INIT;
11         char *data, *start, *mid;
12         char *ref_name;
13         char *refs_url;
14         int i = 0;
15         int http_ret;
16
17         struct ref *refs = NULL;
18         struct ref *ref = NULL;
19         struct ref *last_ref = NULL;
20
21         refs_url = xmalloc(strlen(url) + 11);
22         sprintf(refs_url, "%s/info/refs", url);
23
24         http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);
25         switch (http_ret) {
26         case HTTP_OK:
27                 break;
28         case HTTP_MISSING_TARGET:
29                 die("%s not found: did you run git update-server-info on the"
30                     " server?", refs_url);
31         default:
32                 http_error(refs_url, http_ret);
33                 die("HTTP request failed");
34         }
35
36         data = buffer.buf;
37         start = NULL;
38         mid = data;
39         while (i < buffer.len) {
40                 if (!start) {
41                         start = &data[i];
42                 }
43                 if (data[i] == '\t')
44                         mid = &data[i];
45                 if (data[i] == '\n') {
46                         data[i] = 0;
47                         ref_name = mid + 1;
48                         ref = xmalloc(sizeof(struct ref) +
49                                       strlen(ref_name) + 1);
50                         memset(ref, 0, sizeof(struct ref));
51                         strcpy(ref->name, ref_name);
52                         get_sha1_hex(start, ref->old_sha1);
53                         if (!refs)
54                                 refs = ref;
55                         if (last_ref)
56                                 last_ref->next = ref;
57                         last_ref = ref;
58                         start = NULL;
59                 }
60                 i++;
61         }
62
63         strbuf_release(&buffer);
64
65         ref = alloc_ref("HEAD");
66         if (!walker->fetch_ref(walker, ref) &&
67             !resolve_remote_symref(ref, refs)) {
68                 ref->next = refs;
69                 refs = ref;
70         } else {
71                 free(ref);
72         }
73
74         strbuf_release(&buffer);
75         free(refs_url);
76         return refs;
77 }
78
79 int main(int argc, const char **argv)
80 {
81         struct remote *remote;
82         struct strbuf buf = STRBUF_INIT;
83         const char *url;
84         struct walker *walker = NULL;
85         int nongit;
86
87         git_extract_argv0_path(argv[0]);
88         setup_git_directory_gently(&nongit);
89         if (argc < 2) {
90                 fprintf(stderr, "Remote needed\n");
91                 return 1;
92         }
93
94         remote = remote_get(argv[1]);
95
96         if (argc > 2) {
97                 url = argv[2];
98         } else {
99                 url = remote->url[0];
100         }
101
102         do {
103                 if (strbuf_getline(&buf, stdin, '\n') == EOF)
104                         break;
105                 if (!prefixcmp(buf.buf, "fetch ")) {
106                         char *obj = buf.buf + strlen("fetch ");
107                         if (nongit)
108                                 die("Fetch attempted without a local repo");
109                         if (!walker)
110                                 walker = get_http_walker(url, remote);
111                         walker->get_all = 1;
112                         walker->get_tree = 1;
113                         walker->get_history = 1;
114                         walker->get_verbosely = 0;
115                         walker->get_recover = 0;
116                         if (walker_fetch(walker, 1, &obj, NULL, NULL))
117                                 die("Fetch failed.");
118                         printf("\n");
119                         fflush(stdout);
120                 } else if (!strcmp(buf.buf, "list")) {
121                         struct ref *refs;
122                         struct ref *posn;
123                         if (!walker)
124                                 walker = get_http_walker(url, remote);
125                         refs = get_refs(walker, url);
126                         for (posn = refs; posn; posn = posn->next) {
127                                 if (posn->symref)
128                                         printf("@%s %s\n", posn->symref, posn->name);
129                                 else
130                                         printf("%s %s\n", sha1_to_hex(posn->old_sha1), posn->name);
131                         }
132                         printf("\n");
133                         fflush(stdout);
134                 } else if (!strcmp(buf.buf, "capabilities")) {
135                         printf("fetch\n");
136                         printf("\n");
137                         fflush(stdout);
138                 } else {
139                         return 1;
140                 }
141                 strbuf_reset(&buf);
142         } while (1);
143         return 0;
144 }