diff options
Diffstat (limited to 'src/plugins/abrt-action-bugzilla.cpp')
-rw-r--r-- | src/plugins/abrt-action-bugzilla.cpp | 768 |
1 files changed, 75 insertions, 693 deletions
diff --git a/src/plugins/abrt-action-bugzilla.cpp b/src/plugins/abrt-action-bugzilla.cpp index e8a605f1..91bc26f8 100644 --- a/src/plugins/abrt-action-bugzilla.cpp +++ b/src/plugins/abrt-action-bugzilla.cpp @@ -17,350 +17,12 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "abrtlib.h" -#include "abrt_xmlrpc.h" #include "abrt_problem_data.h" #include "parse_options.h" +#include "abrt_xmlrpc.h" +#include "rhbz.h" #define XML_RPC_SUFFIX "/xmlrpc.cgi" -#define MAX_HOPS 5 - -/* - * TODO: npajkovs: better deallocation of xmlrpc value - * npajkovs: better gathering function which collects all information from bugzilla - * npajkovs: figure out how to deal with cloning bugs - * npajkovs: check if attachment was uploaded successul an if not try it again(max 3 times) - * and if it still fails. retrun successful, but mention that attaching failed - * npajkovs: add option to set comment privat - */ - -struct bug_info { - const char* bug_status; - const char* bug_resolution; - const char* bug_reporter; - const char* bug_product; - xmlrpc_int32 bug_dup_id; - GList* bug_cc; -}; - -/* xzalloc */ -static void bug_info_init(struct bug_info* bz) -{ - bz->bug_status = NULL; - bz->bug_resolution = NULL; - bz->bug_reporter = NULL; - bz->bug_product = NULL; - bz->bug_dup_id = -1; - bz->bug_cc = NULL; -} - -static void bug_info_destroy(struct bug_info* bz) -{ - free((void*)bz->bug_status); - free((void*)bz->bug_resolution); - free((void*)bz->bug_reporter); - free((void*)bz->bug_product); - - list_free_with_free(bz->bug_cc); -} - -/* - * Static namespace for xmlrpc stuff. - * Used mainly to ensure we always destroy xmlrpc client and server_info. - */ - -namespace { - -struct ctx: public abrt_xmlrpc_conn { - xmlrpc_env env; - - ctx(const char* url, bool ssl_verify): abrt_xmlrpc_conn(url, ssl_verify) - { xmlrpc_env_init(&env); } - ~ctx() { xmlrpc_env_clean(&env); } - - void login(const char* login, const char* passwd); - void logout(); - - const char* get_bug_status(xmlrpc_value* result_xml); - const char* get_bug_resolution(xmlrpc_value* result_xml); - const char* get_bug_reporter(xmlrpc_value* result_xml); - const char* get_bug_product(xmlrpc_value* relult_xml); - - xmlrpc_value* call_quicksearch_duphash(const char* component, const char* release, const char* duphash); - xmlrpc_value* get_cc_member(xmlrpc_value* result_xml); - xmlrpc_value* get_member(const char* member, xmlrpc_value* result_xml); - - int get_array_size(xmlrpc_value* result_xml); - xmlrpc_int32 get_bug_id(xmlrpc_value* result_xml); - xmlrpc_int32 get_bug_dup_id(xmlrpc_value* result_xml); - void get_bug_cc(xmlrpc_value* result_xml, struct bug_info* bz); - int add_plus_one_cc(xmlrpc_int32 bug_id, const char* login); - xmlrpc_int32 new_bug(problem_data_t *problem_data, int depend_on_bugno); - int add_attachments(const char* bug_id_str, problem_data_t *problem_data); - int get_bug_info(struct bug_info* bz, xmlrpc_int32 bug_id); - int add_comment(xmlrpc_int32 bug_id, const char* comment, bool is_private); - - xmlrpc_value* call(const char* method, const char* format, ...); -}; - -xmlrpc_value* ctx::call(const char* method, const char* format, ...) -{ - xmlrpc_value* result = NULL; - - if (!env.fault_occurred) - { - xmlrpc_value* param = NULL; - va_list args; - const char* suffix; - - va_start(args, format); - xmlrpc_build_value_va(&env, format, args, ¶m, &suffix); - va_end(args); - - if (*suffix != '\0') - { - xmlrpc_env_set_fault_formatted( - &env, XMLRPC_INTERNAL_ERROR, "Junk after the argument " - "specifier: '%s'. There must be exactly one arument.", - suffix); - } - else - { - xmlrpc_client_call2(&env, m_pClient, m_pServer_info, method, param, &result); - } - xmlrpc_DECREF(param); - if (env.fault_occurred) - return NULL; - } - - return result; -} - -xmlrpc_value* ctx::get_member(const char* member, xmlrpc_value* result_xml) -{ - xmlrpc_value* cc_member = NULL; - xmlrpc_struct_find_value(&env, result_xml, member, &cc_member); - if (env.fault_occurred) - return NULL; - - return cc_member; -} - -int ctx::get_array_size(xmlrpc_value* result_xml) -{ - int size = xmlrpc_array_size(&env, result_xml); - if (env.fault_occurred) - return -1; - - return size; -} - -xmlrpc_int32 ctx::get_bug_dup_id(xmlrpc_value* result_xml) -{ - xmlrpc_value* dup_id = get_member("dup_id", result_xml); - if (!dup_id) - return -1; - - xmlrpc_int32 dup_id_int = -1; - xmlrpc_read_int(&env, dup_id, &dup_id_int); - xmlrpc_DECREF(dup_id); - if (env.fault_occurred) - return -1; - - VERB3 log("got dup_id: %i", dup_id_int); - return dup_id_int; -} - -const char* ctx::get_bug_product(xmlrpc_value* result_xml) -{ - xmlrpc_value* product_member = get_member("product", result_xml); - if (!product_member) //should never happend. Each bug has to set up product - return NULL; - - const char* product = NULL; - xmlrpc_read_string(&env, product_member, &product); - xmlrpc_DECREF(product_member); - if (env.fault_occurred) - return NULL; - - if (*product != '\0') - { - VERB3 log("got bug product: %s", product); - return product; - } - - free((void*)product); - return NULL; -} - -const char* ctx::get_bug_reporter(xmlrpc_value* result_xml) -{ - xmlrpc_value* reporter_member = get_member("reporter", result_xml); - if (!reporter_member) - return NULL; - - const char* reporter = NULL; - xmlrpc_read_string(&env, reporter_member, &reporter); - xmlrpc_DECREF(reporter_member); - if (env.fault_occurred) - return NULL; - - if (*reporter != '\0') - { - VERB3 log("got bug reporter: %s", reporter); - return reporter; - } - free((void*)reporter); - return NULL; -} - -const char* ctx::get_bug_resolution(xmlrpc_value* result_xml) -{ - xmlrpc_value* bug_resolution = get_member("resolution", result_xml); - if (!bug_resolution) - return NULL; - - const char* resolution_str = NULL; - xmlrpc_read_string(&env, bug_resolution, &resolution_str); - xmlrpc_DECREF(bug_resolution); - if (env.fault_occurred) - return NULL; - - if (*resolution_str != '\0') - { - VERB3 log("got resolution: %s", resolution_str); - return resolution_str; - } - free((void*)resolution_str); - return NULL; -} - -const char* ctx::get_bug_status(xmlrpc_value* result_xml) -{ - xmlrpc_value* bug_status = get_member("bug_status", result_xml); - if (!bug_status) - return NULL; - - const char* status_str = NULL; - xmlrpc_read_string(&env, bug_status, &status_str); - xmlrpc_DECREF(bug_status); - if (env.fault_occurred) - return NULL; - - if (*status_str != '\0') - { - VERB3 log("got bug_status: %s", status_str); - return status_str; - } - free((void*)status_str); - return NULL; -} - -void ctx::get_bug_cc(xmlrpc_value* result_xml, struct bug_info* bz) -{ - xmlrpc_value* cc_member = get_member("cc", result_xml); - if (!cc_member) - return; - - int array_size = xmlrpc_array_size(&env, cc_member); - if (array_size == -1) - return; - - VERB3 log("count members on cc %i", array_size); - - for (int i = 0; i < array_size; i++) - { - xmlrpc_value* item = NULL; - xmlrpc_array_read_item(&env, cc_member, i, &item); - if (env.fault_occurred) - return; - - if (item) - { - const char* cc = NULL; - xmlrpc_read_string(&env, item, &cc); - xmlrpc_DECREF(item); - if (env.fault_occurred) - { - xmlrpc_DECREF(cc_member); - return; - } - - if (*cc != '\0') - { - bz->bug_cc = g_list_append(bz->bug_cc, (char*)cc); - VERB3 log("member on cc is %s", cc); - continue; - } - free((char*)cc); - } - } - xmlrpc_DECREF(cc_member); - return; -} - -xmlrpc_value* ctx::call_quicksearch_duphash(const char* component, - const char* release, const char* duphash) -{ - char *query = NULL; - if (!release) - query = xasprintf("ALL component:\"%s\" whiteboard:\"%s\"", component, duphash); - else - { - char *product = NULL; - char *version = NULL; - parse_release_for_bz(release, &product, &version); - query = xasprintf("ALL component:\"%s\" whiteboard:\"%s\" product:\"%s\"", - component, duphash, product - ); - free(product); - free(version); - } - - VERB3 log("quicksearch for `%s'", query); - xmlrpc_value *ret = call("Bug.search", "({s:s})", "quicksearch", query); - free(query); - return ret; -} - -xmlrpc_int32 ctx::get_bug_id(xmlrpc_value* result_xml) -{ - xmlrpc_value* item = NULL; - xmlrpc_array_read_item(&env, result_xml, 0, &item); - if (env.fault_occurred) - return -1; - - xmlrpc_value* bug = get_member("bug_id", item); - xmlrpc_DECREF(item); - if (!bug) - return -1; - - xmlrpc_int32 bug_id = -1; - xmlrpc_read_int(&env, bug, &bug_id); - xmlrpc_DECREF(bug); - if (env.fault_occurred) - return -1; - - VERB3 log("got bug_id %d", (int)bug_id); - return bug_id; -} - -int ctx::add_plus_one_cc(xmlrpc_int32 bug_id, const char* login) -{ - xmlrpc_value* result = call("Bug.update", "({s:i,s:{s:(s)}})", "ids", (int)bug_id, "updates", "add_cc", login); - if (result) - xmlrpc_DECREF(result); - return result ? 0 : -1; -} - -int ctx::add_comment(xmlrpc_int32 bug_id, const char* comment, bool is_private) -{ - xmlrpc_value* result = call("Bug.add_comment", "({s:i,s:s,s:b})", "id", (int)bug_id, - "comment", comment, - "private", is_private); - if (result) - xmlrpc_DECREF(result); - return result ? 0 : -1; -} /* From RHEL6 kernel/panic.c: * { TAINT_PROPRIETARY_MODULE, 'P', 'G' }, @@ -415,6 +77,7 @@ static const char * const taint_warnings[] = { NULL, }; +/* TODO: npajkovs: fix tainted string */ static const char *tainted_string(unsigned tainted) { unsigned idx = 0; @@ -424,207 +87,7 @@ static const char *tainted_string(unsigned tainted) return taint_warnings[idx]; } -xmlrpc_int32 ctx::new_bug(problem_data_t *problem_data, int depend_on_bugno) -{ - const char *package = get_problem_item_content_or_NULL(problem_data, FILENAME_PACKAGE); - const char *component = get_problem_item_content_or_NULL(problem_data, FILENAME_COMPONENT); - const char *release = get_problem_item_content_or_NULL(problem_data, FILENAME_OS_RELEASE); - if (!release) /* Old dump dir format compat. Remove in abrt-2.1 */ - release = get_problem_item_content_or_NULL(problem_data, "release"); - const char *arch = get_problem_item_content_or_NULL(problem_data, FILENAME_ARCHITECTURE); - const char *duphash = get_problem_item_content_or_NULL(problem_data, FILENAME_DUPHASH); - const char *reason = get_problem_item_content_or_NULL(problem_data, FILENAME_REASON); - const char *function = get_problem_item_content_or_NULL(problem_data, FILENAME_CRASH_FUNCTION); - const char *analyzer = get_problem_item_content_or_NULL(problem_data, FILENAME_ANALYZER); - const char *tainted_str = get_problem_item_content_or_NULL(problem_data, FILENAME_TAINTED); - - struct strbuf *buf_summary = strbuf_new(); - strbuf_append_strf(buf_summary, "[abrt] %s", package); - - if (function != NULL && strlen(function) < 30) - strbuf_append_strf(buf_summary, ": %s", function); - - if (reason != NULL) - strbuf_append_strf(buf_summary, ": %s", reason); - - if (tainted_str && analyzer - && (strcmp(analyzer, "Kerneloops") == 0) - ) { - unsigned long tainted = xatoi_positive(tainted_str); - const char *tainted_warning = tainted_string(tainted); - if (tainted_warning) - strbuf_append_strf(buf_summary, ": TAINTED %s", tainted_warning); - } - - char *status_whiteboard = xasprintf("abrt_hash:%s", duphash); - - char *bz_dsc = make_description_bz(problem_data); - char *full_dsc = xasprintf("abrt version: "VERSION"\n%s", bz_dsc); - free(bz_dsc); - - char *product = NULL; - char *version = NULL; - parse_release_for_bz(release, &product, &version); - - xmlrpc_value* result = NULL; - char *summary = strbuf_free_nobuf(buf_summary); - if (depend_on_bugno > -1) - { - result = call("Bug.create", "({s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:i})", - "product", product, - "component", component, - "version", version, - "summary", summary, - "description", full_dsc, - "status_whiteboard", status_whiteboard, - "platform", arch, - "dependson", depend_on_bugno - ); - } - else - { - result = call("Bug.create", "({s:s,s:s,s:s,s:s,s:s,s:s,s:s})", - "product", product, - "component", component, - "version", version, - "summary", summary, - "description", full_dsc, - "status_whiteboard", status_whiteboard, - "platform", arch - ); - } - free(status_whiteboard); - free(product); - free(version); - free(summary); - free(full_dsc); - - if (!result) - return -1; - - xmlrpc_value* id = get_member("id", result); - xmlrpc_DECREF(result); - if (!id) - return -1; - - xmlrpc_int32 bug_id = -1; - xmlrpc_read_int(&env, id, &bug_id); - xmlrpc_DECREF(id); - if (env.fault_occurred) - return -1; - - log(_("New bug id: %i"), (int)bug_id); - - return bug_id; -} - -int ctx::add_attachments(const char* bug_id_str, problem_data_t *problem_data) -{ - GHashTableIter iter; - char *name; - struct problem_item *value; - g_hash_table_iter_init(&iter, problem_data); - while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value)) - { - const char *content = value->content; - - // We were special-casing FILENAME_BACKTRACE here, but Karel says - // he can retrieve it in inlined form from comments too. - if ((value->flags & CD_FLAG_TXT) - && (strlen(content) > CD_TEXT_ATT_SIZE /*|| (strcmp(name, FILENAME_BACKTRACE) == 0)*/) - ) { - char *encoded64 = encode_base64(content, strlen(content)); - char *filename = xasprintf("File: %s", name); - xmlrpc_value* result = call("bugzilla.addAttachment", "(s{s:s,s:s,s:s,s:s})", bug_id_str, - "description", filename, - "filename", name, - "contenttype", "text/plain", - "data", encoded64 - ); - free(encoded64); - free(filename); - if (!result) - return -1; - - xmlrpc_DECREF(result); - } - } - return 0; -} - -int ctx::get_bug_info(struct bug_info* bz, xmlrpc_int32 bug_id) -{ - char bug_id_str[sizeof(long)*3 + 2]; - sprintf(bug_id_str, "%lu", (long)bug_id); - xmlrpc_value* result = call("bugzilla.getBug", "(s)", bug_id_str); - if (!result) - return -1; - - bz->bug_product = get_bug_product(result); - if (bz->bug_product == NULL) - return -1; - - bz->bug_status = get_bug_status(result); - if (bz->bug_status == NULL) - return -1; - - bz->bug_reporter = get_bug_reporter(result); - if (bz->bug_reporter == NULL) - return -1; - - // mandatory when bug status is CLOSED - if (strcmp(bz->bug_status, "CLOSED") == 0) - { - bz->bug_resolution = get_bug_resolution(result); - if ((env.fault_occurred) && (bz->bug_resolution == NULL)) - return -1; - } - - // mandatory when bug status is CLOSED and resolution is DUPLICATE - if ((strcmp(bz->bug_status, "CLOSED") == 0) - && (strcmp(bz->bug_resolution, "DUPLICATE") == 0) - ) { - bz->bug_dup_id = get_bug_dup_id(result); - if (env.fault_occurred) - return -1; - } - - get_bug_cc(result, bz); - if (env.fault_occurred) - return -1; - - xmlrpc_DECREF(result); - return 0; -} - -void ctx::login(const char* login, const char* passwd) -{ - xmlrpc_value* result = call("User.login", "({s:s,s:s})", "login", login, "password", passwd); -//TODO: with URL like http://bugzilla.redhat.com (that is, with http: instead of https:) -//we are getting this error: -//Logging into Bugzilla at http://bugzilla.redhat.com -//Can't login. Server said: HTTP response code is 301, not 200 -//But this is a 301 redirect! We _can_ follow it if we configure curl to understand that! - if (!result) - error_msg_and_die("Can't login. Server said: %s", env.fault_string); - xmlrpc_DECREF(result); -} - -void ctx::logout() -{ - xmlrpc_value* result = call("User.logout", "(s)", ""); - if (result) - xmlrpc_DECREF(result); - - throw_if_xml_fault_occurred(&env); -} - -} /* namespace */ - - -static void report_to_bugzilla( - const char *dump_dir_name, - map_string_h *settings) +static void report_to_bugzilla(const char *dump_dir_name, map_string_h *settings) { struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); if (!dd) @@ -669,13 +132,12 @@ static void report_to_bugzilla( if (!release) /* Old dump dir format compat. Remove in abrt-2.1 */ release = get_problem_item_content_or_NULL(problem_data, "release"); - ctx bz_server(bugzilla_xmlrpc, ssl_verify); + struct abrt_xmlrpc *client = abrt_xmlrpc_new_client(bugzilla_xmlrpc, ssl_verify); log(_("Logging into Bugzilla at %s"), bugzilla_url); - bz_server.login(login, password); + rhbz_login(client, login, password); log(_("Checking for duplicates")); - char *product = NULL; char *version = NULL; parse_release_for_bz(release, &product, &version); @@ -683,225 +145,145 @@ static void report_to_bugzilla( xmlrpc_value *result; if (strcmp(product, "Fedora") == 0) - result = bz_server.call_quicksearch_duphash(component, product, duphash); + result = rhbz_search_duphash(client, component, product, duphash); else - result = bz_server.call_quicksearch_duphash(component, NULL, duphash); + result = rhbz_search_duphash(client, component, NULL, duphash); - if (!result) - throw_if_xml_fault_occurred(&bz_server.env); - - xmlrpc_value *all_bugs = bz_server.get_member("bugs", result); + xmlrpc_value *all_bugs = rhbz_get_member("bugs", result); xmlrpc_DECREF(result); if (!all_bugs) - { - throw_if_xml_fault_occurred(&bz_server.env); error_msg_and_die(_("Missing mandatory member 'bugs'")); - } - xmlrpc_int32 bug_id = -1; - int all_bugs_size = bz_server.get_array_size(all_bugs); - struct bug_info bz; - int depend_on_bugno = -1; + int all_bugs_size = rhbz_array_size(all_bugs); + // When someone clones bug it has same duphash, so we can find more than 1. + // Need to be checked if component is same. + VERB3 log("Bugzilla has %i reports with same duphash '%s'", + all_bugs_size, duphash); + + int bug_id = -1, dependent_bug = -1; + struct bug_info *bz = NULL; if (all_bugs_size > 0) { - bug_id = bz_server.get_bug_id(all_bugs); + bug_id = rhbz_bug_id(all_bugs); xmlrpc_DECREF(all_bugs); - if (bug_id == -1) - throw_if_xml_fault_occurred(&bz_server.env); - - bug_info_init(&bz); - if (bz_server.get_bug_info(&bz, bug_id) == -1) - { - bug_info_destroy(&bz); - throw_if_xml_fault_occurred(&bz_server.env); - error_msg_and_die(_("get_bug_info() failed. Could not collect all mandatory information")); - } + bz = rhbz_bug_info(client, bug_id); - if (strcmp(bz.bug_product, product) != 0) + if (strcmp(bz->bi_product, product) != 0) { - depend_on_bugno = bug_id; - bug_info_destroy(&bz); - result = bz_server.call_quicksearch_duphash(component, release, duphash); - if (!result) - throw_if_xml_fault_occurred(&bz_server.env); + dependent_bug = bug_id; + /* found something, but its a different product */ + free_bug_info(bz); - all_bugs = bz_server.get_member("bugs", result); + xmlrpc_value *result = rhbz_search_duphash(client, component, + product, duphash); + xmlrpc_value *all_bugs = rhbz_get_member("bugs", result); xmlrpc_DECREF(result); - if (!all_bugs) - { - throw_if_xml_fault_occurred(&bz_server.env); - error_msg_and_die(_("Missing mandatory member 'bugs'")); - } - - all_bugs_size = bz_server.get_array_size(all_bugs); + all_bugs_size = rhbz_array_size(all_bugs); if (all_bugs_size > 0) { - bug_id = bz_server.get_bug_id(all_bugs); - xmlrpc_DECREF(all_bugs); - if (bug_id == -1) - throw_if_xml_fault_occurred(&bz_server.env); - - bug_info_init(&bz); - if (bz_server.get_bug_info(&bz, bug_id) == -1) - { - bug_info_destroy(&bz); - throw_if_xml_fault_occurred(&bz_server.env); - error_msg_and_die(_("get_bug_info() failed. Could not collect all mandatory information")); - } + bug_id = rhbz_bug_id(all_bugs); + bz = rhbz_bug_info(client, bug_id); } - else - xmlrpc_DECREF(all_bugs); + xmlrpc_DECREF(all_bugs); } + } free(product); - if (all_bugs_size < 0) - { - throw_if_xml_fault_occurred(&bz_server.env); - } - else if (all_bugs_size == 0) // Create new bug + if (all_bugs_size == 0) // Create new bug { log(_("Creating a new bug")); - bug_id = bz_server.new_bug(problem_data, depend_on_bugno); - if (bug_id < 0) - { - throw_if_xml_fault_occurred(&bz_server.env); - error_msg_and_die(_("Bugzilla entry creation failed")); - } + bug_id = rhbz_new_bug(client, problem_data, bug_id); - log("Adding attachments to bug %ld", (long)bug_id); - char bug_id_str[sizeof(long)*3 + 2]; - sprintf(bug_id_str, "%ld", (long) bug_id); - int ret = bz_server.add_attachments(bug_id_str, problem_data); - if (ret == -1) - { - throw_if_xml_fault_occurred(&bz_server.env); - } + log("Adding attachments to bug %i", bug_id); + char bug_id_str[sizeof(int)*3 + 2]; + sprintf(bug_id_str, "%i", bug_id); + + rhbz_attachments(client, bug_id_str, problem_data); log(_("Logging out")); - bz_server.logout(); + rhbz_logout(client); - log("Status: NEW %s/show_bug.cgi?id=%u", - bugzilla_url, - (int)bug_id - ); + log("Status: NEW %s/show_bug.cgi?id=%u", bugzilla_url, bug_id); + abrt_xmlrpc_free_client(client); return; } - if (all_bugs_size > 1) - { - // When someone clones bug it has same duphash, so we can find more than 1. - // Need to be checked if component is same. - VERB3 log("Bugzilla has %u reports with same duphash '%s'", all_bugs_size, duphash); - } - // decision based on state - log(_("Bug is already reported: %i"), bug_id); - - xmlrpc_int32 original_bug_id = bug_id; - if ((strcmp(bz.bug_status, "CLOSED") == 0) && (strcmp(bz.bug_resolution, "DUPLICATE") == 0)) + log(_("Bug is already reported: %i"), bz->bi_id); + if ((strcmp(bz->bi_status, "CLOSED") == 0) + && (strcmp(bz->bi_resolution, "DUPLICATE") == 0)) { - for (int ii = 0; ii <= MAX_HOPS; ii++) + struct bug_info *origin; + origin = rhbz_find_origin_bug_closed_duplicate(client, bz); + if (origin) { - if (ii == MAX_HOPS) - { - VERB3 log("Bugzilla could not find a parent of bug %d", (int)original_bug_id); - bug_info_destroy(&bz); - error_msg_and_die(_("Bugzilla couldn't find parent of bug %d"), (int)original_bug_id); - } - - log("Bug %d is a duplicate, using parent bug %d", bug_id, (int)bz.bug_dup_id); - bug_id = bz.bug_dup_id; - bug_info_destroy(&bz); - bug_info_init(&bz); - - if (bz_server.get_bug_info(&bz, bug_id) == -1) - { - bug_info_destroy(&bz); - if (bz_server.env.fault_occurred) - { - throw_if_xml_fault_occurred(&bz_server.env); - } - error_msg_and_die(_("get_bug_info() failed. Could not collect all mandatory information")); - } - - // found a bug which is not CLOSED as DUPLICATE - if (bz.bug_dup_id == -1) - break; + free_bug_info(bz); + bz = origin; } } - if (strcmp(bz.bug_status, "CLOSED") != 0) + if (strcmp(bz->bi_status, "CLOSED") != 0) { - int status = 0; - if ((strcmp(bz.bug_reporter, login) != 0) - && (g_list_find(bz.bug_cc, login))) + if ((strcmp(bz->bi_reporter, login) != 0) + && (!g_list_find_custom(bz->bi_cc_list, login, (GCompareFunc)g_strcmp0))) { log(_("Add %s to CC list"), login); - status = bz_server.add_plus_one_cc(bug_id, login); - } - - if (status == -1) - { - bug_info_destroy(&bz); - throw_if_xml_fault_occurred(&bz_server.env); + rhbz_mail_to_cc(client, bz->bi_id, login); } char *dsc = make_description_comment(problem_data); if (dsc) { - const char* package = get_problem_item_content_or_NULL(problem_data, FILENAME_PACKAGE); - const char* release = get_problem_item_content_or_NULL(problem_data, FILENAME_OS_RELEASE); + const char *package = get_problem_item_content_or_NULL(problem_data, + FILENAME_PACKAGE); + const char *release = get_problem_item_content_or_NULL(problem_data, + FILENAME_OS_RELEASE); if (!release) /* Old dump dir format compat. Remove in abrt-2.1 */ release = get_problem_item_content_or_NULL(problem_data, "release"); - const char* arch = get_problem_item_content_or_NULL(problem_data, FILENAME_ARCHITECTURE); - const char* is_private = get_problem_item_content_or_NULL(problem_data, "is_private"); + const char *arch = get_problem_item_content_or_NULL(problem_data, + FILENAME_ARCHITECTURE); + const char *is_private = get_problem_item_content_or_NULL(problem_data, + "is_private"); char *full_dsc = xasprintf("Package: %s\n" - "Architecture: %s\n" - "OS Release: %s\n" - "%s", package, arch, release, dsc - ); - - log(_("Adding new comment to bug %d"), (int)bug_id); + "Architecture: %s\n" + "OS Release: %s\n" + "%s", package, arch, release, dsc); + log(_("Adding new comment to bug %d"), bz->bi_id); free(dsc); - bool is_priv = is_private && string_to_bool(is_private); - if (bz_server.add_comment(bug_id, full_dsc, is_priv) == -1) - { - free(full_dsc); - bug_info_destroy(&bz); - throw_xml_fault(&bz_server.env); - } + int is_priv = is_private && string_to_bool(is_private); + rhbz_add_comment(client, bz->bi_id, full_dsc, is_priv); free(full_dsc); } } log(_("Logging out")); - bz_server.logout(); + rhbz_logout(client); log("Status: %s%s%s %s/show_bug.cgi?id=%u", - bz.bug_status, - bz.bug_resolution ? " " : "", - bz.bug_resolution ? bz.bug_resolution : "", + bz->bi_status, + bz->bi_resolution ? " " : "", + bz->bi_resolution ? bz->bi_resolution : "", bugzilla_url, - (int)bug_id - ); + bz->bi_id); dd = dd_opendir(dump_dir_name, /*flags:*/ 0); if (dd) { - char *msg = xasprintf("Bugzilla: URL=%s/show_bug.cgi?id=%u", bugzilla_url, (int)bug_id); + char *msg = xasprintf("Bugzilla: URL=%s/show_bug.cgi?id=%u", bugzilla_url, bz->bi_id); add_reported_to(dd, msg); free(msg); dd_close(dd); } free_problem_data(problem_data); - bug_info_destroy(&bz); + free_bug_info(bz); + abrt_xmlrpc_free_client(client); } int main(int argc, char **argv) |