static GHashTable *bodhi_query_list(const char *query, const char *release) { char *bodhi_url_bugs = xasprintf("%s/?%s", bodhi_url, query); post_state_t *post_state = new_post_state(POST_WANT_BODY | POST_WANT_SSL_VERIFY | POST_WANT_ERROR_MSG); const char *headers[] = { "Accept: application/json", NULL }; get(post_state, bodhi_url_bugs, "application/x-www-form-urlencoded", headers); if (post_state->http_resp_code != 200 && post_state->http_resp_code != 400) { char *errmsg = post_state->curl_error_msg; if (errmsg && errmsg[0]) error_msg_and_die("%s '%s'", errmsg, bodhi_url_bugs); } free(bodhi_url_bugs); // log_warning("%s", post_state->body); json_object *json = json_tokener_parse(post_state->body); if (is_error(json)) error_msg_and_die("fatal: unable parse response from bodhi server"); /* we must check the http_resp_code because only error responses contain * 'status' item. 'bodhi_read_value' function prints an error message in * the case it did not found the item */ if (post_state->http_resp_code != 200) { char *status_item = NULL; bodhi_read_value(json, "status", &status_item, BODHI_READ_STR); if (status_item != NULL && strcmp(status_item, "error") == 0) { free(status_item); bodhi_print_errors_from_json(json); json_object_put(json); xfunc_die(); // error_msg are printed in bodhi_print_errors_from_json } } GHashTable *bodhi_table = bodhi_parse_json(json, release); json_object_put(json); free_post_state(post_state); return bodhi_table; }
/* bodhi returns following json structure in case of error { "status": "error", "errors": [ { "location": "querystring", "name": "releases", "description": "Invalid releases specified: Rawhide" } ] } */ static void bodhi_print_errors_from_json(json_object *json) { json_object *errors_array = NULL; bodhi_read_value(json, "errors", &errors_array, BODHI_READ_JSON_OBJ); if (!errors_array) { error_msg("Error: unable to read 'errors' array from json"); return; } int errors_len = json_object_array_length(errors_array); for (int i = 0; i < errors_len; ++i) { json_object *error = json_object_array_get_idx(errors_array, i); if (!error) { error_msg("Error: unable to get 'error[%d]'", i); json_object_put(errors_array); return; } char *desc_item = NULL; bodhi_read_value(error, "description", &desc_item, BODHI_READ_STR); if (!desc_item) { error_msg("Error: unable to get 'description' from 'error[%d]'", i); continue; } error_msg("Error: %s", desc_item); json_object_put(error); free(desc_item); } json_object_put(errors_array); return; }
static GHashTable *bodhi_parse_json(json_object *json, const char *release) { int num_items = 0; bodhi_read_value(json, "num_items", &num_items, BODHI_READ_INT); if (num_items <= 0) return NULL; json_object *updates = NULL; bodhi_read_value(json, "updates", &updates, BODHI_READ_JSON_OBJ); if (!updates) return NULL; int updates_len = json_object_array_length(updates); GHashTable *bodhi_table = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify) free_bodhi_item); for (int i = 0; i < updates_len; ++i) { json_object *updates_item = json_object_array_get_idx(updates, i); /* some of item are null */ if (!updates_item) continue; json_object *builds_item = NULL; bodhi_read_value(updates_item, "builds", &builds_item, BODHI_READ_JSON_OBJ); if (!builds_item) /* broken json */ continue; int karma, unstable_karma; bodhi_read_value(updates_item, "karma", &karma, BODHI_READ_INT); bodhi_read_value(updates_item, "unstable_karma", &unstable_karma, BODHI_READ_INT); if (karma <= unstable_karma) continue; struct bodhi *b = NULL; int builds_len = json_object_array_length(builds_item); for (int k = 0; k < builds_len; ++k) { b = xzalloc(sizeof(struct bodhi)); char *name = NULL; json_object *build = json_object_array_get_idx(builds_item, k); bodhi_read_value(build, "nvr", &b->nvr, BODHI_READ_STR); json_object *package = NULL; bodhi_read_value(build, "package", &package, BODHI_READ_JSON_OBJ); bodhi_read_value(package, "name", &name, BODHI_READ_STR); struct bodhi *bodhi_tbl_item = g_hash_table_lookup(bodhi_table, name); if (bodhi_tbl_item && rpmvercmp(bodhi_tbl_item->nvr, b->nvr) > 0) { free_bodhi_item(b); continue; } g_hash_table_replace(bodhi_table, name, b); } #if 0 bodhi_read_value(updates_item, "date_pushed", &b->date_pushed, BODHI_READ_STR); bodhi_read_value(updates_item, "status", &b->status, BODHI_READ_STR); json_object *release_item = NULL; bodhi_read_value(updates_item, "release", &release_item, BODHI_READ_JSON_OBJ); if (release_item) bodhi_read_value(release_item, "dist_tag", &b->dist_tag, BODHI_READ_STR); json_object *bugs = NULL; bodhi_read_value(updates_item, "bugs", &release_item, BODHI_READ_JSON_OBJ); if (bugs) { for (int j = 0; j < json_object_array_length(bugs); ++j) { int *bz_id = xmalloc(sizeof(int)); json_object *bug_item = json_object_array_get_idx(bugs, j); bodhi_read_value(bug_item, "bz_id", bz_id, BODHI_READ_INT); b->bz_ids = g_list_append(b->bz_ids, bz_id); } } #endif } return bodhi_table; }