blob: 75b5d348d7a4709e8413cb36dbecb4153ca7a756 [file] [log] [blame]
/*
* Copyright (c) 2009 Petri Lehtinen <petri@digip.org>
*
* Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <stdlib.h>
#include <string.h>
#include <jansson.h>
#include <curl/curl.h>
#define BUFFER_SIZE (256 * 1024) /* 256 KB */
#define URL_FORMAT "http://github.com/api/v2/json/commits/list/%s/%s/master"
#define URL_SIZE 256
/* Return the offset of the first newline in text or the length of
text if there's no newline */
static int newline_offset(const char *text)
{
const char *newline = strchr(text, '\n');
if(!newline)
return strlen(text);
else
return (int)(newline - text);
}
struct write_result
{
char *data;
int pos;
};
static size_t write_response(void *ptr, size_t size, size_t nmemb, void *stream)
{
struct write_result *result = (struct write_result *)stream;
if(result->pos + size * nmemb >= BUFFER_SIZE - 1)
{
fprintf(stderr, "error: too small buffer\n");
return 0;
}
memcpy(result->data + result->pos, ptr, size * nmemb);
result->pos += size * nmemb;
return size * nmemb;
}
static char *request(const char *url)
{
CURL *curl;
CURLcode status;
char *data;
long code;
curl = curl_easy_init();
data = malloc(BUFFER_SIZE);
if(!curl || !data)
return NULL;
struct write_result write_result = {
.data = data,
.pos = 0
};
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result);
status = curl_easy_perform(curl);
if(status != 0)
{
fprintf(stderr, "error: unable to request data from %s:\n", url);
fprintf(stderr, "%s\n", curl_easy_strerror(status));
return NULL;
}
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
if(code != 200)
{
fprintf(stderr, "error: server responded with code %ld\n", code);
return NULL;
}
curl_easy_cleanup(curl);
curl_global_cleanup();
/* zero-terminate the result */
data[write_result.pos] = '\0';
return data;
}
int main(int argc, char *argv[])
{
unsigned int i;
char *text;
char url[URL_SIZE];
json_t *root;
json_error_t error;
json_t *commits;
if(argc != 3)
{
fprintf(stderr, "usage: %s USER REPOSITORY\n\n", argv[0]);
fprintf(stderr, "List commits at USER's REPOSITORY.\n\n");
return 2;
}
snprintf(url, URL_SIZE, URL_FORMAT, argv[1], argv[2]);
text = request(url);
if(!text)
return 1;
root = json_loads(text, &error);
free(text);
if(!root)
{
fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
return 1;
}
commits = json_object_get(root, "commits");
if(!json_is_array(commits))
{
fprintf(stderr, "error: commits is not an array\n");
return 1;
}
for(i = 0; i < json_array_size(commits); i++)
{
json_t *commit, *id, *message;
const char *message_text;
commit = json_array_get(commits, i);
if(!json_is_object(commit))
{
fprintf(stderr, "error: commit %d is not an object\n", i + 1);
return 1;
}
id = json_object_get(commit, "id");
if(!json_is_string(id))
{
fprintf(stderr, "error: commit %d: id is not a string\n", i + 1);
return 1;
}
message = json_object_get(commit, "message");
if(!json_is_string(message))
{
fprintf(stderr, "error: commit %d: message is not a string\n", i + 1);
return 1;
}
message_text = json_string_value(message);
printf("%.8s %.*s\n",
json_string_value(id),
newline_offset(message_text),
message_text);
}
json_decref(root);
return 0;
}