|
|
2032a8 |
From ff32b9ee7a7e396e33f1e9aeaa5bafd26ccbb273 Mon Sep 17 00:00:00 2001
|
|
|
2032a8 |
From: Jakub Filak <jfilak@redhat.com>
|
|
|
2032a8 |
Date: Thu, 4 Dec 2014 08:45:07 +0100
|
|
|
2032a8 |
Subject: [PATCH 1000/1015] bugzilla: port to Problem Format API
|
|
|
2032a8 |
|
|
|
2032a8 |
Related to #303
|
|
|
2032a8 |
|
|
|
2032a8 |
Signed-off-by: Jakub Filak <jfilak@redhat.com>
|
|
|
2032a8 |
---
|
|
|
2032a8 |
src/plugins/reporter-bugzilla.c | 691 ++++------------------------------------
|
|
|
2032a8 |
1 file changed, 59 insertions(+), 632 deletions(-)
|
|
|
2032a8 |
|
|
|
2032a8 |
diff --git a/src/plugins/reporter-bugzilla.c b/src/plugins/reporter-bugzilla.c
|
|
|
2032a8 |
index fbe7873..9ff3df3 100644
|
|
|
2032a8 |
--- a/src/plugins/reporter-bugzilla.c
|
|
|
2032a8 |
+++ b/src/plugins/reporter-bugzilla.c
|
|
|
2032a8 |
@@ -17,515 +17,11 @@
|
|
|
2032a8 |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
2032a8 |
*/
|
|
|
2032a8 |
#include "internal_libreport.h"
|
|
|
2032a8 |
+#include "problem_report.h"
|
|
|
2032a8 |
#include "client.h"
|
|
|
2032a8 |
#include "abrt_xmlrpc.h"
|
|
|
2032a8 |
#include "rhbz.h"
|
|
|
2032a8 |
|
|
|
2032a8 |
-#include <satyr/stacktrace.h>
|
|
|
2032a8 |
-#include <satyr/abrt.h>
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-struct section_t {
|
|
|
2032a8 |
- char *name;
|
|
|
2032a8 |
- GList *items;
|
|
|
2032a8 |
-};
|
|
|
2032a8 |
-typedef struct section_t section_t;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-/* Utility functions */
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-static
|
|
|
2032a8 |
-GList* split_string_on_char(const char *str, char ch)
|
|
|
2032a8 |
-{
|
|
|
2032a8 |
- GList *list = NULL;
|
|
|
2032a8 |
- for (;;)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- const char *delim = strchrnul(str, ch);
|
|
|
2032a8 |
- list = g_list_prepend(list, xstrndup(str, delim - str));
|
|
|
2032a8 |
- if (*delim == '\0')
|
|
|
2032a8 |
- break;
|
|
|
2032a8 |
- str = delim + 1;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- return g_list_reverse(list);
|
|
|
2032a8 |
-}
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-static
|
|
|
2032a8 |
-int compare_item_name(const char *lookup, const char *name)
|
|
|
2032a8 |
-{
|
|
|
2032a8 |
- if (lookup[0] == '-')
|
|
|
2032a8 |
- lookup++;
|
|
|
2032a8 |
- else if (strncmp(lookup, "%bare_", 6) == 0)
|
|
|
2032a8 |
- lookup += 6;
|
|
|
2032a8 |
- return strcmp(lookup, name);
|
|
|
2032a8 |
-}
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-static
|
|
|
2032a8 |
-int is_item_name_in_section(const section_t *lookup, const char *name)
|
|
|
2032a8 |
-{
|
|
|
2032a8 |
- if (g_list_find_custom(lookup->items, name, (GCompareFunc)compare_item_name))
|
|
|
2032a8 |
- return 0; /* "found it!" */
|
|
|
2032a8 |
- return 1;
|
|
|
2032a8 |
-}
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-static
|
|
|
2032a8 |
-bool is_explicit_or_forbidden(const char *name, GList *comment_fmt_spec)
|
|
|
2032a8 |
-{
|
|
|
2032a8 |
- return g_list_find_custom(comment_fmt_spec, name, (GCompareFunc)is_item_name_in_section);
|
|
|
2032a8 |
-}
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-static
|
|
|
2032a8 |
-GList* load_bzrep_conf_file(const char *path)
|
|
|
2032a8 |
-{
|
|
|
2032a8 |
- FILE *fp = stdin;
|
|
|
2032a8 |
- if (strcmp(path, "-") != 0)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- fp = fopen(path, "r");
|
|
|
2032a8 |
- if (!fp)
|
|
|
2032a8 |
- return NULL;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- GList *sections = NULL;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- char *line;
|
|
|
2032a8 |
- while ((line = xmalloc_fgetline(fp)) != NULL)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- /* Skip comments */
|
|
|
2032a8 |
- char first = *skip_whitespace(line);
|
|
|
2032a8 |
- if (first == '#')
|
|
|
2032a8 |
- goto free_line;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* Handle trailing backslash continuation */
|
|
|
2032a8 |
- check_continuation: ;
|
|
|
2032a8 |
- unsigned len = strlen(line);
|
|
|
2032a8 |
- if (len && line[len-1] == '\\')
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- line[len-1] = '\0';
|
|
|
2032a8 |
- char *next_line = xmalloc_fgetline(fp);
|
|
|
2032a8 |
- if (next_line)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- line = append_to_malloced_string(line, next_line);
|
|
|
2032a8 |
- free(next_line);
|
|
|
2032a8 |
- goto check_continuation;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* We are reusing line buffer to form temporary
|
|
|
2032a8 |
- * "key\0values\0..." in its beginning
|
|
|
2032a8 |
- */
|
|
|
2032a8 |
- bool summary_line = false;
|
|
|
2032a8 |
- char *value = NULL;
|
|
|
2032a8 |
- char *src;
|
|
|
2032a8 |
- char *dst;
|
|
|
2032a8 |
- for (src = dst = line; *src; src++)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- char c = *src;
|
|
|
2032a8 |
- /* did we reach the value list? */
|
|
|
2032a8 |
- if (!value && c == ':' && src[1] == ':')
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- *dst++ = '\0'; /* terminate key */
|
|
|
2032a8 |
- src += 2;
|
|
|
2032a8 |
- value = dst; /* remember where value starts */
|
|
|
2032a8 |
- summary_line = (strcmp(line, "%summary") == 0);
|
|
|
2032a8 |
- if (summary_line)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- value = src;
|
|
|
2032a8 |
- break;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- continue;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- /* skip whitespace in value list */
|
|
|
2032a8 |
- if (value && isspace(c))
|
|
|
2032a8 |
- continue;
|
|
|
2032a8 |
- *dst++ = c; /* store next key or value char */
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- GList *item_list = NULL;
|
|
|
2032a8 |
- if (summary_line)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- /* %summary is special */
|
|
|
2032a8 |
- item_list = g_list_append(NULL, xstrdup(skip_whitespace(value)));
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- else
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- *dst = '\0'; /* terminate value (or key) */
|
|
|
2032a8 |
- if (value)
|
|
|
2032a8 |
- item_list = split_string_on_char(value, ',');
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- section_t *sec = xzalloc(sizeof(*sec));
|
|
|
2032a8 |
- sec->name = xstrdup(line);
|
|
|
2032a8 |
- sec->items = item_list;
|
|
|
2032a8 |
- sections = g_list_prepend(sections, sec);
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- free_line:
|
|
|
2032a8 |
- free(line);
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- if (fp != stdin)
|
|
|
2032a8 |
- fclose(fp);
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- return g_list_reverse(sections);
|
|
|
2032a8 |
-}
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-/* Summary generation */
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-#define MAX_OPT_DEPTH 10
|
|
|
2032a8 |
-static
|
|
|
2032a8 |
-char *format_percented_string(const char *str, problem_data_t *pd)
|
|
|
2032a8 |
-{
|
|
|
2032a8 |
- size_t old_pos[MAX_OPT_DEPTH] = { 0 };
|
|
|
2032a8 |
- int okay[MAX_OPT_DEPTH] = { 1 };
|
|
|
2032a8 |
- int opt_depth = 1;
|
|
|
2032a8 |
- struct strbuf *result = strbuf_new();
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- while (*str) {
|
|
|
2032a8 |
- switch (*str) {
|
|
|
2032a8 |
- default:
|
|
|
2032a8 |
- strbuf_append_char(result, *str);
|
|
|
2032a8 |
- str++;
|
|
|
2032a8 |
- break;
|
|
|
2032a8 |
- case '\\':
|
|
|
2032a8 |
- if (str[1])
|
|
|
2032a8 |
- str++;
|
|
|
2032a8 |
- strbuf_append_char(result, *str);
|
|
|
2032a8 |
- str++;
|
|
|
2032a8 |
- break;
|
|
|
2032a8 |
- case '[':
|
|
|
2032a8 |
- if (str[1] == '[' && opt_depth < MAX_OPT_DEPTH)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- old_pos[opt_depth] = result->len;
|
|
|
2032a8 |
- okay[opt_depth] = 1;
|
|
|
2032a8 |
- opt_depth++;
|
|
|
2032a8 |
- str += 2;
|
|
|
2032a8 |
- } else {
|
|
|
2032a8 |
- strbuf_append_char(result, *str);
|
|
|
2032a8 |
- str++;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- break;
|
|
|
2032a8 |
- case ']':
|
|
|
2032a8 |
- if (str[1] == ']' && opt_depth > 1)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- opt_depth--;
|
|
|
2032a8 |
- if (!okay[opt_depth])
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- result->len = old_pos[opt_depth];
|
|
|
2032a8 |
- result->buf[result->len] = '\0';
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- str += 2;
|
|
|
2032a8 |
- } else {
|
|
|
2032a8 |
- strbuf_append_char(result, *str);
|
|
|
2032a8 |
- str++;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- break;
|
|
|
2032a8 |
- case '%': ;
|
|
|
2032a8 |
- char *nextpercent = strchr(++str, '%');
|
|
|
2032a8 |
- if (!nextpercent)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- error_msg_and_die("Unterminated %%element%%: '%s'", str - 1);
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- *nextpercent = '\0';
|
|
|
2032a8 |
- const problem_item *item = problem_data_get_item_or_NULL(pd, str);
|
|
|
2032a8 |
- *nextpercent = '%';
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- if (item && (item->flags & CD_FLAG_TXT))
|
|
|
2032a8 |
- strbuf_append_str(result, item->content);
|
|
|
2032a8 |
- else
|
|
|
2032a8 |
- okay[opt_depth - 1] = 0;
|
|
|
2032a8 |
- str = nextpercent + 1;
|
|
|
2032a8 |
- break;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- if (opt_depth > 1)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- error_msg_and_die("Unbalanced [[ ]] bracket");
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- if (!okay[0])
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- error_msg("Undefined variable outside of [[ ]] bracket");
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- return strbuf_free_nobuf(result);
|
|
|
2032a8 |
-}
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-static
|
|
|
2032a8 |
-char *create_summary_string(problem_data_t *pd, GList *comment_fmt_spec)
|
|
|
2032a8 |
-{
|
|
|
2032a8 |
- GList *l = comment_fmt_spec;
|
|
|
2032a8 |
- while (l)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- section_t *sec = l->data;
|
|
|
2032a8 |
- l = l->next;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* Find %summary" */
|
|
|
2032a8 |
- if (strcmp(sec->name, "%summary") != 0)
|
|
|
2032a8 |
- continue;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- GList *item = sec->items;
|
|
|
2032a8 |
- if (!item)
|
|
|
2032a8 |
- /* not supposed to happen, there will be at least "" */
|
|
|
2032a8 |
- error_msg_and_die("BUG in %%summary parser");
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- const char *str = item->data;
|
|
|
2032a8 |
- return format_percented_string(str, pd);
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- return format_percented_string("%reason%", pd);
|
|
|
2032a8 |
-}
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-/* BZ comment generation */
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-static
|
|
|
2032a8 |
-int append_text(struct strbuf *result, const char *item_name, const char *content, bool print_item_name)
|
|
|
2032a8 |
-{
|
|
|
2032a8 |
- char *eol = strchrnul(content, '\n');
|
|
|
2032a8 |
- if (eol[0] == '\0' || eol[1] == '\0')
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- /* one-liner */
|
|
|
2032a8 |
- int pad = 16 - (strlen(item_name) + 2);
|
|
|
2032a8 |
- if (pad < 0)
|
|
|
2032a8 |
- pad = 0;
|
|
|
2032a8 |
- if (print_item_name)
|
|
|
2032a8 |
- strbuf_append_strf(result,
|
|
|
2032a8 |
- eol[0] == '\0' ? "%s: %*s%s\n" : "%s: %*s%s",
|
|
|
2032a8 |
- item_name, pad, "", content
|
|
|
2032a8 |
- );
|
|
|
2032a8 |
- else
|
|
|
2032a8 |
- strbuf_append_strf(result,
|
|
|
2032a8 |
- eol[0] == '\0' ? "%s\n" : "%s",
|
|
|
2032a8 |
- content
|
|
|
2032a8 |
- );
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- else
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- /* multi-line item */
|
|
|
2032a8 |
- if (print_item_name)
|
|
|
2032a8 |
- strbuf_append_strf(result, "%s:\n", item_name);
|
|
|
2032a8 |
- for (;;)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- eol = strchrnul(content, '\n');
|
|
|
2032a8 |
- strbuf_append_strf(result,
|
|
|
2032a8 |
- /* For %bare_multiline_item, we don't want to print colons */
|
|
|
2032a8 |
- (print_item_name ? ":%.*s\n" : "%.*s\n"),
|
|
|
2032a8 |
- (int)(eol - content), content
|
|
|
2032a8 |
- );
|
|
|
2032a8 |
- if (eol[0] == '\0' || eol[1] == '\0')
|
|
|
2032a8 |
- break;
|
|
|
2032a8 |
- content = eol + 1;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- return 1;
|
|
|
2032a8 |
-}
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-static
|
|
|
2032a8 |
-int append_short_backtrace(struct strbuf *result, problem_data_t *problem_data, size_t max_text_size, bool print_item_name)
|
|
|
2032a8 |
-{
|
|
|
2032a8 |
- const problem_item *item = problem_data_get_item_or_NULL(problem_data,
|
|
|
2032a8 |
- FILENAME_BACKTRACE);
|
|
|
2032a8 |
- if (!item)
|
|
|
2032a8 |
- return 0; /* "I did not print anything" */
|
|
|
2032a8 |
- if (!(item->flags & CD_FLAG_TXT))
|
|
|
2032a8 |
- return 0; /* "I did not print anything" */
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- char *truncated = NULL;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- if (strlen(item->content) >= max_text_size)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- char *error_msg = NULL;
|
|
|
2032a8 |
- const char *analyzer = problem_data_get_content_or_NULL(problem_data, FILENAME_ANALYZER);
|
|
|
2032a8 |
- if (!analyzer)
|
|
|
2032a8 |
- return 0;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* For CCpp crashes, use the GDB-produced backtrace which should be
|
|
|
2032a8 |
- * available by now. sr_abrt_type_from_analyzer returns SR_REPORT_CORE
|
|
|
2032a8 |
- * by default for CCpp crashes.
|
|
|
2032a8 |
- */
|
|
|
2032a8 |
- enum sr_report_type report_type = sr_abrt_type_from_analyzer(analyzer);
|
|
|
2032a8 |
- if (strcmp(analyzer, "CCpp") == 0)
|
|
|
2032a8 |
- report_type = SR_REPORT_GDB;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- struct sr_stacktrace *backtrace = sr_stacktrace_parse(report_type,
|
|
|
2032a8 |
- item->content, &error_msg);
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- if (!backtrace)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- log(_("Can't parse backtrace: %s"), error_msg);
|
|
|
2032a8 |
- free(error_msg);
|
|
|
2032a8 |
- return 0;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* Get optimized thread stack trace for 10 top most frames */
|
|
|
2032a8 |
- truncated = sr_stacktrace_to_short_text(backtrace, 10);
|
|
|
2032a8 |
- sr_stacktrace_free(backtrace);
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- if (!truncated)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- log(_("Can't generate stacktrace description (no crash thread?)"));
|
|
|
2032a8 |
- return 0;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- append_text(result,
|
|
|
2032a8 |
- /*item_name:*/ truncated ? "truncated_backtrace" : FILENAME_BACKTRACE,
|
|
|
2032a8 |
- /*content:*/ truncated ? truncated : item->content,
|
|
|
2032a8 |
- print_item_name
|
|
|
2032a8 |
- );
|
|
|
2032a8 |
- free(truncated);
|
|
|
2032a8 |
- return 1;
|
|
|
2032a8 |
-}
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-static
|
|
|
2032a8 |
-int append_item(struct strbuf *result, const char *item_name, problem_data_t *pd, GList *comment_fmt_spec)
|
|
|
2032a8 |
-{
|
|
|
2032a8 |
- bool print_item_name = (strncmp(item_name, "%bare_", strlen("%bare_")) != 0);
|
|
|
2032a8 |
- if (!print_item_name)
|
|
|
2032a8 |
- item_name += strlen("%bare_");
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- if (item_name[0] != '%')
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- struct problem_item *item = problem_data_get_item_or_NULL(pd, item_name);
|
|
|
2032a8 |
- if (!item)
|
|
|
2032a8 |
- return 0; /* "I did not print anything" */
|
|
|
2032a8 |
- if (!(item->flags & CD_FLAG_TXT))
|
|
|
2032a8 |
- return 0; /* "I did not print anything" */
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- char *formatted = problem_item_format(item);
|
|
|
2032a8 |
- char *content = formatted ? formatted : item->content;
|
|
|
2032a8 |
- append_text(result, item_name, content, print_item_name);
|
|
|
2032a8 |
- free(formatted);
|
|
|
2032a8 |
- return 1; /* "I printed something" */
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* Special item name */
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* Compat with previously-existed ad-hockery: %short_backtrace */
|
|
|
2032a8 |
- if (strcmp(item_name, "%short_backtrace") == 0)
|
|
|
2032a8 |
- return append_short_backtrace(result, pd, CD_TEXT_ATT_SIZE_BZ, print_item_name);
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* Compat with previously-existed ad-hockery: %reporter */
|
|
|
2032a8 |
- if (strcmp(item_name, "%reporter") == 0)
|
|
|
2032a8 |
- return append_text(result, "reporter", PACKAGE"-"VERSION, print_item_name);
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* %oneline,%multiline,%text */
|
|
|
2032a8 |
- bool oneline = (strcmp(item_name+1, "oneline" ) == 0);
|
|
|
2032a8 |
- bool multiline = (strcmp(item_name+1, "multiline") == 0);
|
|
|
2032a8 |
- bool text = (strcmp(item_name+1, "text" ) == 0);
|
|
|
2032a8 |
- if (!oneline && !multiline && !text)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- log("Unknown or unsupported element specifier '%s'", item_name);
|
|
|
2032a8 |
- return 0; /* "I did not print anything" */
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- int printed = 0;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* Iterate over _sorted_ items */
|
|
|
2032a8 |
- GList *sorted_names = g_hash_table_get_keys(pd);
|
|
|
2032a8 |
- sorted_names = g_list_sort(sorted_names, (GCompareFunc)strcmp);
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* %text => do as if %oneline, then repeat as if %multiline */
|
|
|
2032a8 |
- if (text)
|
|
|
2032a8 |
- oneline = 1;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- again: ;
|
|
|
2032a8 |
- GList *l = sorted_names;
|
|
|
2032a8 |
- while (l)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- const char *name = l->data;
|
|
|
2032a8 |
- l = l->next;
|
|
|
2032a8 |
- struct problem_item *item = g_hash_table_lookup(pd, name);
|
|
|
2032a8 |
- if (!item)
|
|
|
2032a8 |
- continue; /* paranoia, won't happen */
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- if (!(item->flags & CD_FLAG_TXT))
|
|
|
2032a8 |
- continue;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- if (is_explicit_or_forbidden(name, comment_fmt_spec))
|
|
|
2032a8 |
- continue;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- char *formatted = problem_item_format(item);
|
|
|
2032a8 |
- char *content = formatted ? formatted : item->content;
|
|
|
2032a8 |
- char *eol = strchrnul(content, '\n');
|
|
|
2032a8 |
- bool is_oneline = (eol[0] == '\0' || eol[1] == '\0');
|
|
|
2032a8 |
- if (oneline == is_oneline)
|
|
|
2032a8 |
- printed |= append_text(result, name, content, print_item_name);
|
|
|
2032a8 |
- free(formatted);
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- if (text && oneline)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- /* %text, and we just did %oneline. Repeat as if %multiline */
|
|
|
2032a8 |
- oneline = 0;
|
|
|
2032a8 |
- /*multiline = 1; - not checked in fact, so why bother setting? */
|
|
|
2032a8 |
- goto again;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- g_list_free(sorted_names); /* names themselves are not freed */
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- return printed;
|
|
|
2032a8 |
-}
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-static
|
|
|
2032a8 |
-void generate_bz_comment(struct strbuf *result, problem_data_t *pd, GList *comment_fmt_spec)
|
|
|
2032a8 |
-{
|
|
|
2032a8 |
- bool last_line_is_empty = true;
|
|
|
2032a8 |
- GList *l = comment_fmt_spec;
|
|
|
2032a8 |
- while (l)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- section_t *sec = l->data;
|
|
|
2032a8 |
- l = l->next;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* Skip special sections such as "%attach" */
|
|
|
2032a8 |
- if (sec->name[0] == '%')
|
|
|
2032a8 |
- continue;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- if (sec->items)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- /* "Text: item[,item]..." */
|
|
|
2032a8 |
- struct strbuf *output = strbuf_new();
|
|
|
2032a8 |
- GList *item = sec->items;
|
|
|
2032a8 |
- while (item)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- const char *str = item->data;
|
|
|
2032a8 |
- item = item->next;
|
|
|
2032a8 |
- if (str[0] == '-') /* "-name", ignore it */
|
|
|
2032a8 |
- continue;
|
|
|
2032a8 |
- append_item(output, str, pd, comment_fmt_spec);
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- if (output->len != 0)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- strbuf_append_strf(result,
|
|
|
2032a8 |
- sec->name[0] ? "%s:\n%s" : "%s%s",
|
|
|
2032a8 |
- sec->name,
|
|
|
2032a8 |
- output->buf
|
|
|
2032a8 |
- );
|
|
|
2032a8 |
- last_line_is_empty = false;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- strbuf_free(output);
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- else
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- /* Just "Text" (can be "") */
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* Filter out consecutive empty lines */
|
|
|
2032a8 |
- if (sec->name[0] != '\0' || !last_line_is_empty)
|
|
|
2032a8 |
- strbuf_append_strf(result, "%s\n", sec->name);
|
|
|
2032a8 |
- last_line_is_empty = (sec->name[0] == '\0');
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* Nuke any trailing empty lines */
|
|
|
2032a8 |
- while (result->len >= 1
|
|
|
2032a8 |
- && result->buf[result->len-1] == '\n'
|
|
|
2032a8 |
- && (result->len == 1 || result->buf[result->len-2] == '\n')
|
|
|
2032a8 |
- ) {
|
|
|
2032a8 |
- result->buf[--result->len] = '\0';
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-}
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-
|
|
|
2032a8 |
/* BZ attachments */
|
|
|
2032a8 |
|
|
|
2032a8 |
static
|
|
|
2032a8 |
@@ -573,104 +69,6 @@ int attach_file_item(struct abrt_xmlrpc *ax, const char *bug_id,
|
|
|
2032a8 |
return (r == 0);
|
|
|
2032a8 |
}
|
|
|
2032a8 |
|
|
|
2032a8 |
-static
|
|
|
2032a8 |
-int attach_item(struct abrt_xmlrpc *ax, const char *bug_id,
|
|
|
2032a8 |
- const char *item_name, problem_data_t *pd, GList *comment_fmt_spec)
|
|
|
2032a8 |
-{
|
|
|
2032a8 |
- if (item_name[0] != '%')
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- struct problem_item *item = problem_data_get_item_or_NULL(pd, item_name);
|
|
|
2032a8 |
- if (!item)
|
|
|
2032a8 |
- return 0;
|
|
|
2032a8 |
- if (item->flags & CD_FLAG_TXT)
|
|
|
2032a8 |
- return attach_text_item(ax, bug_id, item_name, item);
|
|
|
2032a8 |
- if (item->flags & CD_FLAG_BIN)
|
|
|
2032a8 |
- return attach_file_item(ax, bug_id, item_name, item);
|
|
|
2032a8 |
- return 0;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* Special item name */
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* %oneline,%multiline,%text,%binary */
|
|
|
2032a8 |
- bool oneline = (strcmp(item_name+1, "oneline" ) == 0);
|
|
|
2032a8 |
- bool multiline = (strcmp(item_name+1, "multiline") == 0);
|
|
|
2032a8 |
- bool text = (strcmp(item_name+1, "text" ) == 0);
|
|
|
2032a8 |
- bool binary = (strcmp(item_name+1, "binary" ) == 0);
|
|
|
2032a8 |
- if (!oneline && !multiline && !text && !binary)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- log("Unknown or unsupported element specifier '%s'", item_name);
|
|
|
2032a8 |
- return 0;
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- log_debug("Special item_name '%s', iterating for attach...", item_name);
|
|
|
2032a8 |
- int done = 0;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* Iterate over _sorted_ items */
|
|
|
2032a8 |
- GList *sorted_names = g_hash_table_get_keys(pd);
|
|
|
2032a8 |
- sorted_names = g_list_sort(sorted_names, (GCompareFunc)strcmp);
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- GList *l = sorted_names;
|
|
|
2032a8 |
- while (l)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- const char *name = l->data;
|
|
|
2032a8 |
- l = l->next;
|
|
|
2032a8 |
- struct problem_item *item = g_hash_table_lookup(pd, name);
|
|
|
2032a8 |
- if (!item)
|
|
|
2032a8 |
- continue; /* paranoia, won't happen */
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- if (is_explicit_or_forbidden(name, comment_fmt_spec))
|
|
|
2032a8 |
- continue;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- if ((item->flags & CD_FLAG_TXT) && !binary)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- char *content = item->content;
|
|
|
2032a8 |
- char *eol = strchrnul(content, '\n');
|
|
|
2032a8 |
- bool is_oneline = (eol[0] == '\0' || eol[1] == '\0');
|
|
|
2032a8 |
- if (text || oneline == is_oneline)
|
|
|
2032a8 |
- done |= attach_text_item(ax, bug_id, name, item);
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- if ((item->flags & CD_FLAG_BIN) && binary)
|
|
|
2032a8 |
- done |= attach_file_item(ax, bug_id, name, item);
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- g_list_free(sorted_names); /* names themselves are not freed */
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- log_debug("...Done iterating over '%s' for attach", item_name);
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- return done;
|
|
|
2032a8 |
-}
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-static
|
|
|
2032a8 |
-int attach_files(struct abrt_xmlrpc *ax, const char *bug_id,
|
|
|
2032a8 |
- problem_data_t *pd, GList *comment_fmt_spec)
|
|
|
2032a8 |
-{
|
|
|
2032a8 |
- int done = 0;
|
|
|
2032a8 |
- GList *l = comment_fmt_spec;
|
|
|
2032a8 |
- while (l)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- section_t *sec = l->data;
|
|
|
2032a8 |
- l = l->next;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- /* Find %attach" */
|
|
|
2032a8 |
- if (strcmp(sec->name, "%attach") != 0)
|
|
|
2032a8 |
- continue;
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- GList *item = sec->items;
|
|
|
2032a8 |
- while (item)
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- const char *str = item->data;
|
|
|
2032a8 |
- item = item->next;
|
|
|
2032a8 |
- if (str[0] == '-') /* "-name", ignore it */
|
|
|
2032a8 |
- continue;
|
|
|
2032a8 |
- done |= attach_item(ax, bug_id, str, pd, comment_fmt_spec);
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
-
|
|
|
2032a8 |
- return done;
|
|
|
2032a8 |
-}
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-
|
|
|
2032a8 |
/* Main */
|
|
|
2032a8 |
|
|
|
2032a8 |
struct bugzilla_struct {
|
|
|
2032a8 |
@@ -1103,18 +501,29 @@ int main(int argc, char **argv)
|
|
|
2032a8 |
|
|
|
2032a8 |
if (opts & OPT_D)
|
|
|
2032a8 |
{
|
|
|
2032a8 |
- GList *comment_fmt_spec = load_bzrep_conf_file(fmt_file);
|
|
|
2032a8 |
- struct strbuf *bzcomment_buf = strbuf_new();
|
|
|
2032a8 |
- generate_bz_comment(bzcomment_buf, problem_data, comment_fmt_spec);
|
|
|
2032a8 |
- char *bzcomment = strbuf_free_nobuf(bzcomment_buf);
|
|
|
2032a8 |
- char *summary = create_summary_string(problem_data, comment_fmt_spec);
|
|
|
2032a8 |
+ problem_formatter_t *pf = problem_formatter_new();
|
|
|
2032a8 |
+
|
|
|
2032a8 |
+ if (problem_formatter_load_file(pf, fmt_file))
|
|
|
2032a8 |
+ error_msg_and_die("Invalid format file: %s", fmt_file);
|
|
|
2032a8 |
+
|
|
|
2032a8 |
+ problem_report_t *pr = NULL;
|
|
|
2032a8 |
+ if (problem_formatter_generate_report(pf, problem_data, &pr))
|
|
|
2032a8 |
+ error_msg_and_die("Failed to format bug report from problem data");
|
|
|
2032a8 |
+
|
|
|
2032a8 |
printf("summary: %s\n"
|
|
|
2032a8 |
"\n"
|
|
|
2032a8 |
"%s"
|
|
|
2032a8 |
- , summary, bzcomment
|
|
|
2032a8 |
+ "\n"
|
|
|
2032a8 |
+ , problem_report_get_summary(pr)
|
|
|
2032a8 |
+ , problem_report_get_description(pr)
|
|
|
2032a8 |
);
|
|
|
2032a8 |
- free(bzcomment);
|
|
|
2032a8 |
- free(summary);
|
|
|
2032a8 |
+
|
|
|
2032a8 |
+ puts("attachments:");
|
|
|
2032a8 |
+ for (GList *a = problem_report_get_attachments(pr); a != NULL; a = g_list_next(a))
|
|
|
2032a8 |
+ printf(" %s\n", (const char *)a->data);
|
|
|
2032a8 |
+
|
|
|
2032a8 |
+ problem_report_free(pr);
|
|
|
2032a8 |
+ problem_formatter_free(pf);
|
|
|
2032a8 |
exit(0);
|
|
|
2032a8 |
}
|
|
|
2032a8 |
|
|
|
2032a8 |
@@ -1227,22 +636,29 @@ int main(int argc, char **argv)
|
|
|
2032a8 |
/* Create new bug */
|
|
|
2032a8 |
log(_("Creating a new bug"));
|
|
|
2032a8 |
|
|
|
2032a8 |
- GList *comment_fmt_spec = load_bzrep_conf_file(fmt_file);
|
|
|
2032a8 |
+ problem_formatter_t *pf = problem_formatter_new();
|
|
|
2032a8 |
+
|
|
|
2032a8 |
+ if (problem_formatter_load_file(pf, fmt_file))
|
|
|
2032a8 |
+ error_msg_and_die("Invalid format file: %s", fmt_file);
|
|
|
2032a8 |
+
|
|
|
2032a8 |
+ problem_report_t *pr = NULL;
|
|
|
2032a8 |
+ if (problem_formatter_generate_report(pf, problem_data, &pr))
|
|
|
2032a8 |
+ error_msg_and_die("Failed to format problem data");
|
|
|
2032a8 |
|
|
|
2032a8 |
- struct strbuf *bzcomment_buf = strbuf_new();
|
|
|
2032a8 |
- generate_bz_comment(bzcomment_buf, problem_data, comment_fmt_spec);
|
|
|
2032a8 |
if (crossver_id >= 0)
|
|
|
2032a8 |
- strbuf_append_strf(bzcomment_buf, "\nPotential duplicate: bug %u\n", crossver_id);
|
|
|
2032a8 |
- char *bzcomment = strbuf_free_nobuf(bzcomment_buf);
|
|
|
2032a8 |
- char *summary = create_summary_string(problem_data, comment_fmt_spec);
|
|
|
2032a8 |
+ problem_report_buffer_printf(
|
|
|
2032a8 |
+ problem_report_get_buffer(pr, PR_SEC_DESCRIPTION),
|
|
|
2032a8 |
+ "\nPotential duplicate: bug %u\n", crossver_id);
|
|
|
2032a8 |
+
|
|
|
2032a8 |
+ problem_formatter_free(pf);
|
|
|
2032a8 |
+
|
|
|
2032a8 |
int new_id = rhbz_new_bug(client,
|
|
|
2032a8 |
problem_data, rhbz.b_product, rhbz.b_product_version,
|
|
|
2032a8 |
- summary, bzcomment,
|
|
|
2032a8 |
+ problem_report_get_summary(pr),
|
|
|
2032a8 |
+ problem_report_get_description(pr),
|
|
|
2032a8 |
rhbz.b_create_private,
|
|
|
2032a8 |
rhbz.b_private_groups
|
|
|
2032a8 |
);
|
|
|
2032a8 |
- free(bzcomment);
|
|
|
2032a8 |
- free(summary);
|
|
|
2032a8 |
|
|
|
2032a8 |
if (new_id == -1)
|
|
|
2032a8 |
{
|
|
|
2032a8 |
@@ -1267,9 +683,17 @@ int main(int argc, char **argv)
|
|
|
2032a8 |
char new_id_str[sizeof(int)*3 + 2];
|
|
|
2032a8 |
sprintf(new_id_str, "%i", new_id);
|
|
|
2032a8 |
|
|
|
2032a8 |
- attach_files(client, new_id_str, problem_data, comment_fmt_spec);
|
|
|
2032a8 |
-
|
|
|
2032a8 |
-//TODO: free_comment_fmt_spec(comment_fmt_spec);
|
|
|
2032a8 |
+ for (GList *a = problem_report_get_attachments(pr); a != NULL; a = g_list_next(a))
|
|
|
2032a8 |
+ {
|
|
|
2032a8 |
+ const char *item_name = (const char *)a->data;
|
|
|
2032a8 |
+ struct problem_item *item = problem_data_get_item_or_NULL(problem_data, item_name);
|
|
|
2032a8 |
+ if (!item)
|
|
|
2032a8 |
+ continue;
|
|
|
2032a8 |
+ else if (item->flags & CD_FLAG_TXT)
|
|
|
2032a8 |
+ attach_text_item(client, new_id_str, item_name, item);
|
|
|
2032a8 |
+ else if (item->flags & CD_FLAG_BIN)
|
|
|
2032a8 |
+ attach_file_item(client, new_id_str, item_name, item);
|
|
|
2032a8 |
+ }
|
|
|
2032a8 |
|
|
|
2032a8 |
bz = new_bug_info();
|
|
|
2032a8 |
bz->bi_status = xstrdup("NEW");
|
|
|
2032a8 |
@@ -1340,18 +764,21 @@ int main(int argc, char **argv)
|
|
|
2032a8 |
const char *comment = problem_data_get_content_or_NULL(problem_data, FILENAME_COMMENT);
|
|
|
2032a8 |
if (comment && comment[0])
|
|
|
2032a8 |
{
|
|
|
2032a8 |
- GList *comment_fmt_spec = load_bzrep_conf_file(fmt_file2);
|
|
|
2032a8 |
- struct strbuf *bzcomment_buf = strbuf_new();
|
|
|
2032a8 |
- generate_bz_comment(bzcomment_buf, problem_data, comment_fmt_spec);
|
|
|
2032a8 |
- char *bzcomment = strbuf_free_nobuf(bzcomment_buf);
|
|
|
2032a8 |
-//TODO: free_comment_fmt_spec(comment_fmt_spec);
|
|
|
2032a8 |
+ problem_formatter_t *pf = problem_formatter_new();
|
|
|
2032a8 |
+ if (problem_formatter_load_file(pf, fmt_file2))
|
|
|
2032a8 |
+ error_msg_and_die("Invalid duplicate format file: '%s", fmt_file2);
|
|
|
2032a8 |
+
|
|
|
2032a8 |
+ problem_report_t *pr;
|
|
|
2032a8 |
+ if (problem_formatter_generate_report(pf, problem_data, &pr))
|
|
|
2032a8 |
+ error_msg_and_die("Failed to format duplicate comment from problem data");
|
|
|
2032a8 |
+
|
|
|
2032a8 |
+ const char *bzcomment = problem_report_get_description(pr);
|
|
|
2032a8 |
|
|
|
2032a8 |
int dup_comment = is_comment_dup(bz->bi_comments, bzcomment);
|
|
|
2032a8 |
if (!dup_comment)
|
|
|
2032a8 |
{
|
|
|
2032a8 |
log(_("Adding new comment to bug %d"), bz->bi_id);
|
|
|
2032a8 |
rhbz_add_comment(client, bz->bi_id, bzcomment, 0);
|
|
|
2032a8 |
- free(bzcomment);
|
|
|
2032a8 |
|
|
|
2032a8 |
const char *bt = problem_data_get_content_or_NULL(problem_data, FILENAME_BACKTRACE);
|
|
|
2032a8 |
unsigned rating = 0;
|
|
|
2032a8 |
@@ -1369,10 +796,10 @@ int main(int argc, char **argv)
|
|
|
2032a8 |
}
|
|
|
2032a8 |
}
|
|
|
2032a8 |
else
|
|
|
2032a8 |
- {
|
|
|
2032a8 |
- free(bzcomment);
|
|
|
2032a8 |
log(_("Found the same comment in the bug history, not adding a new one"));
|
|
|
2032a8 |
- }
|
|
|
2032a8 |
+
|
|
|
2032a8 |
+ problem_report_free(pr);
|
|
|
2032a8 |
+ problem_formatter_free(pf);
|
|
|
2032a8 |
}
|
|
|
2032a8 |
|
|
|
2032a8 |
log_out:
|
|
|
2032a8 |
--
|
|
|
2032a8 |
1.8.3.1
|
|
|
2032a8 |
|