github_commits.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
  3. *
  4. * Jansson is free software; you can redistribute it and/or modify
  5. * it under the terms of the MIT license. See LICENSE for details.
  6. */
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <jansson.h>
  10. #include <curl/curl.h>
  11. #define BUFFER_SIZE (256 * 1024) /* 256 KB */
  12. #define URL_FORMAT "https://api.github.com/repos/%s/%s/commits"
  13. #define URL_SIZE 256
  14. /* Return the offset of the first newline in text or the length of
  15. text if there's no newline */
  16. static int newline_offset(const char *text)
  17. {
  18. const char *newline = strchr(text, '\n');
  19. if(!newline)
  20. return strlen(text);
  21. else
  22. return (int)(newline - text);
  23. }
  24. struct write_result
  25. {
  26. char *data;
  27. int pos;
  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. if(result->pos + size * nmemb >= BUFFER_SIZE - 1)
  33. {
  34. fprintf(stderr, "error: too small buffer\n");
  35. return 0;
  36. }
  37. memcpy(result->data + result->pos, ptr, size * nmemb);
  38. result->pos += size * nmemb;
  39. return size * nmemb;
  40. }
  41. static char *request(const char *url)
  42. {
  43. CURL *curl;
  44. CURLcode status;
  45. char *data;
  46. long code;
  47. curl = curl_easy_init();
  48. data = malloc(BUFFER_SIZE);
  49. if(!curl || !data)
  50. return NULL;
  51. struct write_result write_result = {
  52. .data = data,
  53. .pos = 0
  54. };
  55. curl_easy_setopt(curl, CURLOPT_URL, url);
  56. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response);
  57. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result);
  58. status = curl_easy_perform(curl);
  59. if(status != 0)
  60. {
  61. fprintf(stderr, "error: unable to request data from %s:\n", url);
  62. fprintf(stderr, "%s\n", curl_easy_strerror(status));
  63. return NULL;
  64. }
  65. curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
  66. if(code != 200)
  67. {
  68. fprintf(stderr, "error: server responded with code %ld\n", code);
  69. return NULL;
  70. }
  71. curl_easy_cleanup(curl);
  72. curl_global_cleanup();
  73. /* zero-terminate the result */
  74. data[write_result.pos] = '\0';
  75. return data;
  76. }
  77. int main(int argc, char *argv[])
  78. {
  79. size_t i;
  80. char *text;
  81. char url[URL_SIZE];
  82. json_t *root;
  83. json_error_t error;
  84. if(argc != 3)
  85. {
  86. fprintf(stderr, "usage: %s USER REPOSITORY\n\n", argv[0]);
  87. fprintf(stderr, "List commits at USER's REPOSITORY.\n\n");
  88. return 2;
  89. }
  90. snprintf(url, URL_SIZE, URL_FORMAT, argv[1], argv[2]);
  91. text = request(url);
  92. if(!text)
  93. return 1;
  94. root = json_loads(text, 0, &error);
  95. free(text);
  96. if(!root)
  97. {
  98. fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
  99. return 1;
  100. }
  101. if(!json_is_array(root))
  102. {
  103. fprintf(stderr, "error: root is not an array\n");
  104. return 1;
  105. }
  106. for(i = 0; i < json_array_size(root); i++)
  107. {
  108. json_t *data, *sha, *commit, *message;
  109. const char *message_text;
  110. data = json_array_get(root, i);
  111. if(!json_is_object(data))
  112. {
  113. fprintf(stderr, "error: commit data %d is not an object\n", i + 1);
  114. return 1;
  115. }
  116. sha = json_object_get(data, "sha");
  117. if(!json_is_string(sha))
  118. {
  119. fprintf(stderr, "error: commit %d: sha is not a string\n", i + 1);
  120. return 1;
  121. }
  122. commit = json_object_get(data, "commit");
  123. if(!json_is_object(commit))
  124. {
  125. fprintf(stderr, "error: commit %d: commit is not an object\n", i + 1);
  126. return 1;
  127. }
  128. message = json_object_get(commit, "message");
  129. if(!json_is_string(message))
  130. {
  131. fprintf(stderr, "error: commit %d: message is not a string\n", i + 1);
  132. return 1;
  133. }
  134. message_text = json_string_value(message);
  135. printf("%.8s %.*s\n",
  136. json_string_value(sha),
  137. newline_offset(message_text),
  138. message_text);
  139. }
  140. json_decref(root);
  141. return 0;
  142. }
粤ICP备19079148号