3d8e2cb9f27054cfc164da7f092f37e227d2ec22
[jansson.git] / doc / github_commits.c
1 #include <stdlib.h>
2 #include <string.h>
3
4 #include <jansson.h>
5 #include <curl/curl.h>
6
7 #define BUFFER_SIZE  (256 * 1024)  /* 256 KB */
8
9 #define URL_FORMAT   "http://github.com/api/v2/json/commits/list/%s/%s/master"
10 #define URL_SIZE     256
11
12 /* Return the offset of the first newline in text or the length of
13    text if there's no newline */
14 static int newline_offset(const char *text)
15 {
16     const char *newline = strchr(text, '\n');
17     if(!newline)
18         return strlen(text);
19     else
20         return (int)(newline - text);
21 }
22
23 struct write_result
24 {
25     char *data;
26     int pos;
27 };
28
29 static size_t write_response(void *ptr, size_t size, size_t nmemb, void *stream)
30 {
31     struct write_result *result = (struct write_result *)stream;
32
33     if(result->pos + size * nmemb >= BUFFER_SIZE - 1)
34     {
35         fprintf(stderr, "error: too small buffer\n");
36         return 0;
37     }
38
39     memcpy(result->data + result->pos, ptr, size * nmemb);
40     result->pos += size * nmemb;
41
42     return size * nmemb;
43 }
44
45 static char *request(const char *url)
46 {
47     CURL *curl;
48     CURLcode status;
49     char *data;
50     long code;
51
52     curl = curl_easy_init();
53     data = malloc(BUFFER_SIZE);
54     if(!curl || !data)
55         return NULL;
56
57     struct write_result write_result = {
58         .data = data,
59         .pos = 0
60     };
61
62     curl_easy_setopt(curl, CURLOPT_URL, url);
63     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response);
64     curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result);
65
66     status = curl_easy_perform(curl);
67     if(status != 0)
68     {
69         fprintf(stderr, "error: unable to request data from %s:\n", url);
70         fprintf(stderr, "%s\n", curl_easy_strerror(status));
71         return NULL;
72     }
73
74     curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
75     if(code != 200)
76     {
77         fprintf(stderr, "error: server responded with code %ld\n", code);
78         return NULL;
79     }
80
81     curl_easy_cleanup(curl);
82     curl_global_cleanup();
83
84     /* zero-terminate the result */
85     data[write_result.pos] = '\0';
86
87     return data;
88 }
89
90 int main(int argc, char *argv[])
91 {
92     unsigned int i;
93     char *text;
94     char url[URL_SIZE];
95
96     json_t *root;
97     json_error_t error;
98     json_t *commits;
99
100     if(argc != 3)
101     {
102         fprintf(stderr, "usage: %s USER REPOSITORY\n\n", argv[0]);
103         fprintf(stderr, "List commits at USER's REPOSITORY.\n\n");
104         return 2;
105     }
106
107     snprintf(url, URL_SIZE, URL_FORMAT, argv[1], argv[2]);
108
109     text = request(url);
110     if(!text)
111         return 1;
112
113     root = json_loads(text, &error);
114     free(text);
115
116     if(!root)
117     {
118         fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
119         return 1;
120     }
121
122     commits = json_object_get(root, "commits");
123     if(!json_is_array(commits))
124     {
125         fprintf(stderr, "error: commits is not an array\n");
126         return 1;
127     }
128
129     for(i = 0; i < json_array_size(commits); i++)
130     {
131         json_t *commit, *id, *message;
132         const char *message_text;
133
134         commit = json_array_get(commits, i);
135         if(!json_is_object(commit))
136         {
137             fprintf(stderr, "error: commit %d is not an object\n", i + 1);
138             return 1;
139         }
140
141         id = json_object_get(commit, "id");
142         if(!json_is_string(id))
143         {
144             fprintf(stderr, "error: commit %d: id is not a string\n", i + 1);
145             return 1;
146         }
147
148         message = json_object_get(commit, "message");
149         if(!json_is_string(message))
150         {
151             fprintf(stderr, "error: commit %d: message is not a string\n", i + 1);
152             return 1;
153         }
154
155         message_text = json_string_value(message);
156         printf("%.8s %.*s\n",
157                json_string_value(id),
158                newline_offset(message_text),
159                message_text);
160     }
161
162     json_decref(root);
163     return 0;
164 }