summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/applet/applet_gtk.c4
-rw-r--r--src/gui-gtk/abrt-gtk.c11
-rw-r--r--src/gui-wizard-gtk/wizard.c192
-rw-r--r--src/include/abrtlib.h2
-rw-r--r--src/include/report/report.h29
-rw-r--r--src/lib/make_descr.c25
-rw-r--r--src/lib/report.c103
-rw-r--r--src/plugins/abrt-action-bugzilla.c28
-rw-r--r--src/report-python/Makefile.am1
-rw-r--r--src/report-python/README44
-rw-r--r--src/report-python/__init__.py4
-rw-r--r--src/report-python/common.h15
-rw-r--r--src/report-python/report.c59
-rw-r--r--src/report-python/reportmodule.c33
14 files changed, 318 insertions, 232 deletions
diff --git a/src/applet/applet_gtk.c b/src/applet/applet_gtk.c
index 74347963..9e3c68f7 100644
--- a/src/applet/applet_gtk.c
+++ b/src/applet/applet_gtk.c
@@ -86,7 +86,8 @@ static void action_report(NotifyNotification *notification, gchar *action, gpoin
struct applet *applet = (struct applet *)user_data;
if (applet->ap_daemon_running)
{
- analyze_and_report_dir(applet->ap_last_crash_id, LIBREPORT_NOWAIT);
+ report_problem_in_dir(applet->ap_last_crash_id, LIBREPORT_ANALYZE | LIBREPORT_NOWAIT);
+
GError *err = NULL;
notify_notification_close(notification, &err);
if (err != NULL)
@@ -94,6 +95,7 @@ static void action_report(NotifyNotification *notification, gchar *action, gpoin
error_msg("%s", err->message);
g_error_free(err);
}
+
hide_icon(applet);
stop_animate_icon(applet);
}
diff --git a/src/gui-gtk/abrt-gtk.c b/src/gui-gtk/abrt-gtk.c
index f6e9c5c2..a3bf1cab 100644
--- a/src/gui-gtk/abrt-gtk.c
+++ b/src/gui-gtk/abrt-gtk.c
@@ -108,8 +108,8 @@ static void on_row_activated_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTre
GValue d_dir = { 0 };
gtk_tree_model_get_value(store, &iter, COLUMN_DUMP_DIR, &d_dir);
- const char *dirname= g_value_get_string(&d_dir);
- analyze_and_report_dir(dirname, LIBREPORT_NOWAIT);
+ const char *dirname = g_value_get_string(&d_dir);
+ report_problem_in_dir(dirname, LIBREPORT_ANALYZE | LIBREPORT_NOWAIT);
}
}
}
@@ -203,8 +203,11 @@ static void on_button_send_cb(GtkWidget *button, gpointer data)
/* why it doesn't want to hide before report ends? */
gtk_widget_destroy(s_report_window);
- int status = report(pd);
- VERB1 log("Reporting finished with status: %i", status);
+//TODO: LIBREPORT_WAIT is used here only because we don't want to leave temp dir.
+//Change to LIBREPORT_NOWAIT when libreport is taught to
+//properly delete temp dir even with LIBREPORT_NOWAIT.
+ int status = report_problem_in_memory(pd, LIBREPORT_WAIT);
+ VERB1 log("Reporting finished with status %i", status);
free_problem_data(pd);
}
diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c
index 6d682233..12e6a81c 100644
--- a/src/gui-wizard-gtk/wizard.c
+++ b/src/gui-wizard-gtk/wizard.c
@@ -60,7 +60,6 @@ static GtkLabel *g_lbl_cd_reason;
static GtkTextView *g_tv_backtrace;
static GtkTextView *g_tv_comment;
static GtkEventBox *g_eb_comment;
-static GtkTreeView *g_tv_details;
static GtkWidget *g_widget_warnings_area;
static GtkBox *g_box_warning_labels;
static GtkToggleButton *g_tb_approve_bt;
@@ -69,10 +68,18 @@ static GtkButton *g_btn_refresh;
static GtkLabel *g_lbl_reporters;
static GtkLabel *g_lbl_size;
-static GtkCellRenderer *g_tv_details_col2;
+static GtkTreeView *g_tv_details;
+static GtkCellRenderer *g_tv_details_renderer_value;
+static GtkTreeViewColumn *g_tv_details_col_checkbox;
+//static GtkCellRenderer *g_tv_details_renderer_checkbox;
static GtkListStore *g_ls_details;
enum
{
+ /* Note: need to update types in
+ * gtk_list_store_new(DETAIL_NUM_COLUMNS, TYPE1, TYPE2...)
+ * if you change these:
+ */
+ DETAIL_COLUMN_CHECKBOX,
DETAIL_COLUMN_NAME,
DETAIL_COLUMN_VALUE,
DETAIL_NUM_COLUMNS,
@@ -351,37 +358,48 @@ static void free_event_gui_data_t(event_gui_data_t *evdata, void *unused)
/* tv_details handling */
-static void tv_details_row_activated(
- GtkTreeView *tree_view,
- GtkTreePath *path,
- GtkTreeViewColumn *column,
- gpointer user_data)
+static struct problem_item *get_current_problem_item_or_NULL(GtkTreeView *tree_view, gchar **pp_item_name)
{
GtkTreeModel *model;
GtkTreeIter iter;
GtkTreeSelection* selection = gtk_tree_view_get_selection(tree_view);
if (!gtk_tree_selection_get_selected(selection, &model, &iter))
- return;
+ return NULL;
+
+ *pp_item_name = NULL;
+ gtk_tree_model_get(model, &iter, DETAIL_COLUMN_NAME, pp_item_name, -1);
+ if (!*pp_item_name) /* paranoia, should never happen */
+ return NULL;
+ struct problem_item *item = get_problem_data_item_or_NULL(g_cd, *pp_item_name);
- gchar *column_name;
- gtk_tree_model_get(model, &iter, DETAIL_COLUMN_NAME, &column_name, -1);
- struct problem_item *item = get_problem_data_item_or_NULL(g_cd, column_name);
+ return item;
+}
+
+static void tv_details_row_activated(
+ GtkTreeView *tree_view,
+ GtkTreePath *tree_path_UNUSED,
+ GtkTreeViewColumn *column,
+ gpointer user_data)
+{
+ gchar *item_name;
+ struct problem_item *item = get_current_problem_item_or_NULL(tree_view, &item_name);
if (!item || !(item->flags & CD_FLAG_TXT))
- return;
+ goto ret;
if (!strchr(item->content, '\n')) /* one line? */
- return;
+ goto ret; /* yes */
gchar *arg[3];
arg[0] = (char *) "xdg-open";
- arg[1] = concat_path_file(g_dump_dir_name, column_name);
+ arg[1] = concat_path_file(g_dump_dir_name, item_name);
arg[2] = NULL;
- g_free(column_name);
g_spawn_sync(NULL, arg, NULL,
G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL,
NULL, NULL, NULL, NULL, NULL, NULL);
free(arg[1]);
+ ret:
+ g_free(item_name);
}
/* static gboolean tv_details_select_cursor_row(
@@ -391,17 +409,11 @@ static void tv_details_row_activated(
static void tv_details_cursor_changed(
GtkTreeView *tree_view,
- gpointer user_data)
+ gpointer user_data_UNUSED)
{
- GtkTreeModel *model;
- GtkTreeIter iter;
- GtkTreeSelection* selection = gtk_tree_view_get_selection(tree_view);
- if (!gtk_tree_selection_get_selected(selection, &model, &iter))
- return;
-
- gchar *column_name;
- gtk_tree_model_get(model, &iter, DETAIL_COLUMN_NAME, &column_name, -1);
- struct problem_item *item = get_problem_data_item_or_NULL(g_cd, column_name);
+ gchar *item_name;
+ struct problem_item *item = get_current_problem_item_or_NULL(tree_view, &item_name);
+ g_free(item_name);
gboolean editable = (item && (item->flags & CD_FLAG_TXT) && !strchr(item->content, '\n'));
@@ -410,11 +422,37 @@ static void tv_details_cursor_changed(
* but changes aren't saved (the old text reappears as soon as user
* leaves the field). Need to disable editing somehow.
*/
- g_object_set(G_OBJECT(g_tv_details_col2),
+ g_object_set(G_OBJECT(g_tv_details_renderer_value),
"editable", editable,
NULL);
}
+static void g_tv_details_checkbox_toggled(
+ GtkCellRendererToggle *cell_renderer_UNUSED,
+ gchar *tree_path,
+ gpointer user_data_UNUSED)
+{
+ //log("%s: path:'%s'", __func__, tree_path);
+ GtkTreeIter iter;
+ if (!gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(g_ls_details), &iter, tree_path))
+ return;
+
+ gchar *item_name = NULL;
+ gtk_tree_model_get(GTK_TREE_MODEL(g_ls_details), &iter, DETAIL_COLUMN_NAME, &item_name, -1);
+ if (!item_name) /* paranoia, should never happen */
+ return;
+ struct problem_item *item = get_problem_data_item_or_NULL(g_cd, item_name);
+ g_free(item_name);
+ if (!item) /* paranoia */
+ return;
+
+ item->flags ^= 0x8000000;
+ //log("%s: item->flags=%x", __func__, item->flags);
+ gtk_list_store_set(g_ls_details, &iter,
+ DETAIL_COLUMN_CHECKBOX, !!(item->flags & 0x8000000),
+ -1);
+}
+
/* update_gui_state_from_problem_data */
@@ -623,10 +661,10 @@ static void append_item_to_ls_details(gpointer name, gpointer value, gpointer da
stats->filecount++;
//FIXME: use the human-readable format_problem_item(item) instead of item->content.
- /* If text and not multiline... */
if (item->flags & CD_FLAG_TXT)
{
stats->filesize += strlen(item->content);
+ /* If not multiline... */
if (!strchr(item->content, '\n'))
{
gtk_list_store_set(g_ls_details, &iter,
@@ -1265,6 +1303,13 @@ static void on_page_prepare(GtkAssistant *assistant, GtkWidget *page, gpointer u
g_container_details1 : g_container_details2,
w
);
+ /* Make checkbox column visible only on the last page */
+ gtk_tree_view_column_set_visible(g_tv_details_col_checkbox,
+ (pages[PAGENO_REVIEW_DATA].page_widget == page)
+ );
+ //gtk_cell_renderer_set_visible(g_tv_details_renderer_checkbox,
+ // (pages[PAGENO_REVIEW_DATA].page_widget == page)
+ //);
}
if (pages[PAGENO_EDIT_COMMENT].page_widget == page)
@@ -1382,39 +1427,6 @@ static void search_timeout(GtkEntry *entry)
/* Initialization */
-static void create_details_treeview()
-{
- GtkCellRenderer *renderer;
- GtkTreeViewColumn *column;
-
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Name"),
- renderer,
- "text",
- DETAIL_COLUMN_NAME,
- NULL);
- gtk_tree_view_column_set_sort_column_id(column, DETAIL_COLUMN_NAME);
- gtk_tree_view_append_column(g_tv_details, column);
-
- g_tv_details_col2 = renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Value"),
- renderer,
- "text",
- DETAIL_COLUMN_VALUE,
- NULL);
- gtk_tree_view_append_column(g_tv_details, column);
-
- /*
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Path"),
- renderer,
- "text",
- DETAIL_COLUMN_PATH,
- NULL);
- gtk_tree_view_append_column(g_tv_details, column);
- */
-}
-
/* wizard.glade file as a string WIZARD_GLADE_CONTENTS: */
#include "wizard_glade.c"
@@ -1527,6 +1539,57 @@ static void add_pages()
gtk_widget_modify_bg(GTK_WIDGET(g_eb_comment), GTK_STATE_NORMAL, &color);
}
+static void create_details_treeview()
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ //g_tv_details_renderer_checkbox =
+ renderer = gtk_cell_renderer_toggle_new();
+ g_tv_details_col_checkbox = column = gtk_tree_view_column_new_with_attributes(
+ _("Include"), renderer,
+ /* which "attr" of renderer to set from which COLUMN? (can be repeated) */
+ "active", DETAIL_COLUMN_CHECKBOX,
+ NULL);
+ gtk_tree_view_append_column(g_tv_details, column);
+ /* This column has a handler */
+ g_signal_connect(renderer, "toggled", G_CALLBACK(g_tv_details_checkbox_toggled), NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(
+ _("Name"), renderer,
+ "text", DETAIL_COLUMN_NAME,
+ NULL);
+ gtk_tree_view_append_column(g_tv_details, column);
+
+ g_tv_details_renderer_value = renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(
+ _("Value"), renderer,
+ "text", DETAIL_COLUMN_VALUE,
+ NULL);
+ gtk_tree_view_append_column(g_tv_details, column);
+
+ /*
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(
+ _("Path"), renderer,
+ "text", DETAIL_COLUMN_PATH,
+ NULL);
+ gtk_tree_view_append_column(g_tv_details, column);
+ */
+
+ gtk_tree_view_column_set_sort_column_id(column, DETAIL_COLUMN_NAME);
+
+ g_ls_details = gtk_list_store_new(DETAIL_NUM_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING);
+ gtk_tree_view_set_model(g_tv_details, GTK_TREE_MODEL(g_ls_details));
+
+ g_signal_connect(g_tv_details, "row-activated", G_CALLBACK(tv_details_row_activated), NULL);
+ g_signal_connect(g_tv_details, "cursor-changed", G_CALLBACK(tv_details_cursor_changed), NULL);
+ /* [Enter] on a row:
+ * g_signal_connect(g_tv_details, "select-cursor-row", G_CALLBACK(tv_details_select_cursor_row), NULL);
+ */
+}
+
void create_assistant(void)
{
monospace_font = pango_font_description_from_string("monospace");
@@ -1541,8 +1604,8 @@ void create_assistant(void)
g_parent_window = wnd_assistant;
gtk_window_set_default_size(wnd_assistant, DEFAULT_WIDTH, DEFAULT_HEIGHT);
/* set_default sets icon for every windows used in this app, so we don't
- have to set the icon for those windows manually
- */
+ * have to set the icon for those windows manually
+ */
gtk_window_set_default_icon_name("abrt");
GObject *obj_assistant = G_OBJECT(g_assistant);
@@ -1554,15 +1617,10 @@ void create_assistant(void)
add_pages();
create_details_treeview();
- g_ls_details = gtk_list_store_new(DETAIL_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
- gtk_tree_view_set_model(g_tv_details, GTK_TREE_MODEL(g_ls_details));
g_signal_connect(g_tb_approve_bt, "toggled", G_CALLBACK(on_bt_approve_toggle), NULL);
g_signal_connect(g_btn_refresh, "clicked", G_CALLBACK(on_btn_refresh_clicked), NULL);
g_signal_connect(gtk_text_view_get_buffer(g_tv_comment), "changed", G_CALLBACK(on_comment_changed), NULL);
- g_signal_connect(g_tv_details, "row-activated", G_CALLBACK(tv_details_row_activated), NULL);
- /* [Enter] on a row: g_signal_connect(g_tv_details, "select-cursor-row", G_CALLBACK(tv_details_select_cursor_row), NULL); */
- g_signal_connect(g_tv_details, "cursor-changed", G_CALLBACK(tv_details_cursor_changed), NULL);
/* init searching */
GtkTextBuffer *backtrace_buf = gtk_text_view_get_buffer(g_tv_backtrace);
diff --git a/src/include/abrtlib.h b/src/include/abrtlib.h
index 5d03ee49..1e68a661 100644
--- a/src/include/abrtlib.h
+++ b/src/include/abrtlib.h
@@ -251,8 +251,6 @@ enum {
char *make_description(problem_data_t *problem_data, char **names_to_skip, unsigned max_text_size, unsigned desc_flags);
#define make_description_bz abrt_make_description_bz
char* make_description_bz(problem_data_t *problem_data);
-#define make_description_comment abrt_make_description_comment
-char* make_description_comment(problem_data_t *problem_data);
#define make_description_logger abrt_make_description_logger
char* make_description_logger(problem_data_t *problem_data);
#define make_description_mailx abrt_make_description_mailx
diff --git a/src/include/report/report.h b/src/include/report/report.h
index e441875b..269866b2 100644
--- a/src/include/report/report.h
+++ b/src/include/report/report.h
@@ -22,28 +22,21 @@
#include "problem_data.h"
enum {
- LIBREPORT_NOWAIT = 0,
- LIBREPORT_WAIT = (1 << 0), /* wait for report to finish and reload the problem data */
+ LIBREPORT_NOWAIT = 0,
+ LIBREPORT_WAIT = (1 << 0), /* wait for report to finish and reload the problem data */
+ LIBREPORT_ANALYZE = (1 << 1), /* run analyzers? */
+ /* ("run reporters" is always on, has no flag (for now?)) */
+ LIBREPORT_RELOAD_DATA = (1 << 3), /* reload problem data after run (needs WAIT) */
};
+int report_problem_in_dir(const char *dirname, int flags);
-/* analyzes AND reports a problem saved on disk
- * - takes user through all the steps in reporting wizard
+/* Reports a problem stored in problem_data_t.
+ * It's first saved to /tmp and then processed as a dump dir.
*/
-int analyze_and_report_dir(const char* dirname, int flags);
+int report_problem_in_memory(problem_data_t *pd, int flags);
-/* analyzes AND reports a problem stored in problem_data_t
- * it's first saved to /tmp and then processed as a dump_dir
- * - takes user through all the steps in reporting wizard
- */
-int analyze_and_report(problem_data_t *pd, int flags);
-
-/* reports a problem saved on disk
- * - shows only reporter selector and progress
-*/
-int report_dir(const char* dirname);
-
-/* to report a problem stored in memory */
-int report(problem_data_t *pd);
+/* Simple wrapper for trivial uses */
+int report_problem(problem_data_t *pd);
#endif /* REPORT_H_ */
diff --git a/src/lib/make_descr.c b/src/lib/make_descr.c
index 036d7770..d0afc8cb 100644
--- a/src/lib/make_descr.c
+++ b/src/lib/make_descr.c
@@ -260,28 +260,3 @@ char* make_description_logger(problem_data_t *problem_data)
MAKEDESC_SHOW_FILES | MAKEDESC_SHOW_MULTILINE
);
}
-
-char* make_description_comment(problem_data_t *problem_data)
-{
- char *comment = NULL;
- struct problem_item *value;
-
- value = get_problem_data_item_or_NULL(problem_data, FILENAME_COMMENT);
- if (value)
- {
- if (value->content[0])
- comment = xasprintf("\n\nComment\n-----\n%s", value->content);
- }
-
- if (!comment)
- return NULL;
-
- struct strbuf *buf_dsc = strbuf_new();
-
- if (comment)
- strbuf_append_str(buf_dsc, comment);
-
- free(comment);
-
- return strbuf_free_nobuf(buf_dsc);
-}
diff --git a/src/lib/report.c b/src/lib/report.c
index 99a3f919..07299e48 100644
--- a/src/lib/report.c
+++ b/src/lib/report.c
@@ -20,7 +20,7 @@
#include "abrtlib.h"
#include "report.h"
-static int run_reporter_ui(char **args, int flags)
+int report_problem_in_dir(const char *dirname, int flags)
{
const char *path;
/*
@@ -29,6 +29,15 @@ static int run_reporter_ui(char **args, int flags)
path = "cli"
*/
+ char *args[5], **pp;
+ pp = args;
+ *pp++ = (char *)"bug-reporting-wizard";
+ if (!(flags & LIBREPORT_ANALYZE))
+ *pp++ = (char *)"--report-only";
+ *pp++ = (char *)"--";
+ *pp++ = (char *)dirname;
+ *pp++ = NULL;
+
pid_t pid = vfork();
if (pid < 0) /* error */
{
@@ -79,22 +88,7 @@ static int run_reporter_ui(char **args, int flags)
return 0;
}
-int analyze_and_report_dir(const char* dirname, int flags)
-{
- char *args[4];
-
- args[0] = (char *)"bug-reporting-wizard";
- args[1] = (char *)"--";
- args[2] = (char *)dirname;
- args[3] = NULL;
-
- return run_reporter_ui(args, flags);
-}
-
-/* analyzes AND reports a problem saved on disk
- * - takes user through all the steps in reporting wizard
- */
-int analyze_and_report(problem_data_t *pd, int flags)
+int report_problem_in_memory(problem_data_t *pd, int flags)
{
int result = 0;
struct dump_dir *dd = create_dump_dir_from_problem_data(pd, "/tmp"/* /var/tmp ?? */);
@@ -103,78 +97,33 @@ int analyze_and_report(problem_data_t *pd, int flags)
char *dir_name = xstrdup(dd->dd_dirname);
dd_close(dd);
VERB2 log("Temp problem dir: '%s'", dir_name);
- result = analyze_and_report_dir(dir_name, flags);
- /* if we wait for reporter to finish, we can clean the tmp dir
- * and we should reload the problem data, so caller doesn't see the stalled
- * data
- */
+// TODO: if !LIBREPORT_WAIT pass LIBREPORT_DEL_DIR, and teach bug-reporting-wizard
+// an option to delete directory after reporting?
+// It will make !LIBREPORT_WAIT reporting possible
+ result = report_problem_in_dir(dir_name, flags);
+
+ /* If we wait for reporter to finish, we should clean the tmp dir.
+ * We can also reload the problem data if requested.
+ */
if (flags & LIBREPORT_WAIT)
{
- g_hash_table_remove_all(pd);
+ if (flags & LIBREPORT_RELOAD_DATA)
+ g_hash_table_remove_all(pd);
dd = dd_opendir(dir_name, 0);
if (dd)
{
- load_problem_data_from_dump_dir(pd, dd);
+ if (flags & LIBREPORT_RELOAD_DATA)
+ load_problem_data_from_dump_dir(pd, dd);
dd_delete(dd);
}
}
+
free(dir_name);
return result;
}
-/* report() and report_dir() don't take flags, because in all known use-cases
- * it doesn't make sense to not wait for the result
- *
-*/
-
-/* reports a problem saved on disk
- * - shows only reporter selector and progress
-*/
-int report_dir(const char* dirname)
+int report_problem(problem_data_t *pd)
{
- char *args[5];
-
- args[0] = (char *)"bug-reporting-wizard";
- args[1] = (char *)"--report-only";
- args[2] = (char *)"--";
- args[3] = (char *)dirname;
- args[4] = NULL;
-
- int flags = LIBREPORT_WAIT;
- int status = run_reporter_ui(args, flags);
- return status;
-}
-
-int report(problem_data_t *pd)
-{
- /* adds:
- * analyzer:libreport
- * executable:readlink(/proc/<pid>/exe)
- * tries to guess component
- */
- add_basics_to_problem_data(pd);
- struct dump_dir *dd = create_dump_dir_from_problem_data(pd, "/tmp"/* /var/tmp ?? */);
- if (!dd)
- return -1;
- dd_create_basic_files(dd, getuid());
- char *dir_name = xstrdup(dd->dd_dirname);
- dd_close(dd);
- VERB2 log("Temp problem dir: '%s'", dir_name);
- int result = report_dir(dir_name);
-
- /* here we always wait for reporter to finish, we can clean the tmp dir
- * and we should reload the problem data, so caller doesn't see the stalled
- * data
- */
- g_hash_table_remove_all(pd); //what if something fails? is it ok to return empty pd rather then stalled pd?
- dd = dd_opendir(dir_name, 0);
- if (dd)
- {
- load_problem_data_from_dump_dir(pd, dd);
- dd_delete(dd);
- }
- free(dir_name);
-
- return result;
+ return report_problem_in_memory(pd, LIBREPORT_WAIT);
}
diff --git a/src/plugins/abrt-action-bugzilla.c b/src/plugins/abrt-action-bugzilla.c
index d617d4bb..9290112a 100644
--- a/src/plugins/abrt-action-bugzilla.c
+++ b/src/plugins/abrt-action-bugzilla.c
@@ -170,26 +170,24 @@ static void report_to_bugzilla(const char *dump_dir_name, map_string_h *settings
rhbz_mail_to_cc(client, bz->bi_id, login, RHBZ_NOMAIL_NOTIFY);
}
- char *dsc = make_description_comment(problem_data);
- if (dsc)
+ const char *comment = get_problem_item_content_or_NULL(problem_data, FILENAME_COMMENT);
+ if (comment && comment[0])
{
- 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 *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);
+//COMPAT, remove in abrt-2.1 release
+ if (!release)release= get_problem_item_content_or_NULL(problem_data, "release");
+ const char *arch = get_problem_item_content_or_NULL(problem_data, FILENAME_ARCHITECTURE);
char *full_dsc = xasprintf("Package: %s\n"
"Architecture: %s\n"
"OS Release: %s\n"
- "%s", package, arch, release, dsc);
-
+ "\n"
+ "Comment\n"
+ "-----\n"
+ "%s\n",
+ package, arch, release, comment
+ );
log(_("Adding new comment to bug %d"), bz->bi_id);
- free(dsc);
-
/* unused code, enable it when gui/cli will be ready
int is_priv = is_private && string_to_bool(is_private);
const char *is_private = get_problem_item_content_or_NULL(problem_data,
diff --git a/src/report-python/Makefile.am b/src/report-python/Makefile.am
index c7b2dd67..c1b37596 100644
--- a/src/report-python/Makefile.am
+++ b/src/report-python/Makefile.am
@@ -11,6 +11,7 @@ _pyreport_la_SOURCES = \
problem_data.c \
dump_dir.c \
run_event.c \
+ report.c \
common.h
_pyreport_la_CPPFLAGS = \
-I$(srcdir)/../include/report -I$(srcdir)/../include \
diff --git a/src/report-python/README b/src/report-python/README
new file mode 100644
index 00000000..1c9c3a27
--- /dev/null
+++ b/src/report-python/README
@@ -0,0 +1,44 @@
+Currently (2011-05), include/report/*.h are:
+
+dump_dir.h
+event_config.h
+problem_data.h
+report.h
+run_event.h
+
+and we wrap all of them except event_config.h.
+
+Python wrappers for C types and functions declared in include/report/FOO.h
+should be implemented in corresponding FOO.c file in this directory.
+
+Their (C-level) declarations should go to common.h.
+
+Note that methods don't have to be declared in common.h:
+they can be static functions inside FOO.c, and exposed to the rest
+of the world via PyTypeObject instance. In FOO.c:
+
+static PyObject *p_method_name(PyObject *pself, PyObject *args)
+...
+static PyMethodDef p_FOO_methods[] = {
+{ "method_name", p_method_name, METH_VARARGS, NULL }
+...
+};
+PyTypeObject p_FOO_type = {
+ .tp_methods = p_FOO_methods,
+...
+};
+
+and only p_FOO_type needs to be declared in common.h.
+
+Similarly, (de)allocators, attr getters/setters also can be static functions
+and be hooked into p_FOO_type.
+
+However, non-method functions can't be static.
+
+
+File reportmodule.c contains the initialization function which should
+initialize types (p_FOO_type objects) and hook up finctions from every
+FOO.c so that they are usable from python code.
+
+Python wrappers for C constants (enums, defines) are created directly
+by reportmodule.c.
diff --git a/src/report-python/__init__.py b/src/report-python/__init__.py
index 2e875638..78beff6d 100644
--- a/src/report-python/__init__.py
+++ b/src/report-python/__init__.py
@@ -112,7 +112,7 @@ def createAlertSignature(component, hashmarkername, hashvalue, summary, alertSig
cd.add("component", component)
cd.add("hashmarkername", hashmarkername)
#cd.add("localhash", hashvalue)
- cd.add("global_uuid", hashvalue)
+ cd.add("duphash", hashvalue)
cd.add("reason", summary)
cd.add("description", alertSignature)
cd.add("product", getProduct())
@@ -127,4 +127,4 @@ def report(cd, io_unused):
"""
def report(pd, io_unused):
- result = report_problem_data(pd)
+ result = report_problem(pd)
diff --git a/src/report-python/common.h b/src/report-python/common.h
index ee56ad9a..713aa2f2 100644
--- a/src/report-python/common.h
+++ b/src/report-python/common.h
@@ -31,11 +31,6 @@ extern PyTypeObject p_problem_data_type;
extern PyTypeObject p_dump_dir_type;
extern PyTypeObject p_run_event_state_type;
-/* module-level functions */
-PyObject *p_dd_opendir(PyObject *module, PyObject *args);
-PyObject *p_dd_create(PyObject *module, PyObject *args);
-PyObject *p_delete_dump_dir(PyObject *pself, PyObject *args);
-
/* python objects' struct defs */
typedef struct {
PyObject_HEAD
@@ -46,3 +41,13 @@ typedef struct {
PyObject_HEAD
problem_data_t *cd;
} p_problem_data;
+
+/* module-level functions */
+/* for include/report/dump_dir.h */
+PyObject *p_dd_opendir(PyObject *module, PyObject *args);
+PyObject *p_dd_create(PyObject *module, PyObject *args);
+PyObject *p_delete_dump_dir(PyObject *pself, PyObject *args);
+/* for include/report/report.h */
+PyObject *p_report_problem_in_dir(PyObject *pself, PyObject *args);
+PyObject *p_report_problem_in_memory(PyObject *pself, PyObject *args);
+PyObject *p_report_problem(PyObject *pself, PyObject *args);
diff --git a/src/report-python/report.c b/src/report-python/report.c
new file mode 100644
index 00000000..0bdd4076
--- /dev/null
+++ b/src/report-python/report.c
@@ -0,0 +1,59 @@
+/*
+ Copyright (C) 2010 Abrt team.
+ Copyright (C) 2010 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include <Python.h>
+
+#include "common.h"
+
+/* C: int report_problem_in_dir(const char *dirname, int flags); */
+PyObject *p_report_problem_in_dir(PyObject *pself, PyObject *args)
+{
+ const char *dirname;
+ int flags;
+ if (!PyArg_ParseTuple(args, "si", &dirname, &flags))
+ {
+ return NULL;
+ }
+ int r = report_problem_in_dir(dirname, flags);
+ return Py_BuildValue("i", r);
+}
+
+/* C: int report_problem_in_memory(problem_data_t *pd, int flags); */
+PyObject *p_report_problem_in_memory(PyObject *pself, PyObject *args)
+{
+ p_problem_data *pd;
+ int flags;
+ if (!PyArg_ParseTuple(args, "O!i", &p_problem_data_type, &pd, &flags))
+ {
+ return NULL;
+ }
+ int r = report_problem_in_memory(pd->cd, flags);
+ return Py_BuildValue("i", r);
+}
+
+/* C: int report_problem(problem_data_t *pd); */
+PyObject *p_report_problem(PyObject *pself, PyObject *args)
+{
+ p_problem_data *pd;
+ if (!PyArg_ParseTuple(args, "O!", &p_problem_data_type, &pd))
+ {
+ return NULL;
+ }
+ int r = report_problem(pd->cd);
+ return Py_BuildValue("i", r);
+}
diff --git a/src/report-python/reportmodule.c b/src/report-python/reportmodule.c
index 1cae783f..539c66aa 100644
--- a/src/report-python/reportmodule.c
+++ b/src/report-python/reportmodule.c
@@ -22,21 +22,16 @@
PyObject *ReportError;
-
-static PyObject *p_report(PyObject *pself, PyObject *problem_data)
-{
- p_problem_data *p_pd = (p_problem_data*)problem_data;
- report(p_pd->cd);
- //FIXME return status as integer object
- Py_RETURN_NONE;
-}
-
static PyMethodDef module_methods[] = {
/* method_name, func, flags, doc_string */
- { "dd_opendir" , p_dd_opendir , METH_VARARGS },
- { "dd_create" , p_dd_create , METH_VARARGS },
- { "delete_dump_dir", p_delete_dump_dir, METH_VARARGS },
- { "report_problem_data" , p_report, METH_O},
+ /* for include/report/dump_dir.h */
+ { "dd_opendir" , p_dd_opendir , METH_VARARGS },
+ { "dd_create" , p_dd_create , METH_VARARGS },
+ { "delete_dump_dir" , p_delete_dump_dir , METH_VARARGS },
+ /* for include/report/report.h */
+ { "report_problem_in_dir" , p_report_problem_in_dir , METH_VARARGS },
+ { "report_problem_in_memory" , p_report_problem_in_memory, METH_VARARGS },
+ { "report_problem" , p_report_problem , METH_VARARGS },
{ NULL }
};
@@ -75,20 +70,26 @@ init_pyreport(void)
Py_INCREF(ReportError);
PyModule_AddObject(m, "error", ReportError);
- /* init type objects */
+ /* init type objects and constants */
+ /* for include/report/problem_data.h */
Py_INCREF(&p_problem_data_type);
PyModule_AddObject(m, "problem_data", (PyObject *)&p_problem_data_type);
PyModule_AddObject(m, "CD_FLAG_BIN" , Py_BuildValue("i", CD_FLAG_BIN ));
PyModule_AddObject(m, "CD_FLAG_TXT" , Py_BuildValue("i", CD_FLAG_TXT ));
PyModule_AddObject(m, "CD_FLAG_ISEDITABLE" , Py_BuildValue("i", CD_FLAG_ISEDITABLE ));
PyModule_AddObject(m, "CD_FLAG_ISNOTEDITABLE", Py_BuildValue("i", CD_FLAG_ISNOTEDITABLE));
-
+ /* for include/report/dump_dir.h */
Py_INCREF(&p_dump_dir_type);
PyModule_AddObject(m, "dump_dir", (PyObject *)&p_dump_dir_type);
PyModule_AddObject(m, "DD_FAIL_QUIETLY_ENOENT" , Py_BuildValue("i", DD_FAIL_QUIETLY_ENOENT ));
PyModule_AddObject(m, "DD_FAIL_QUIETLY_EACCES" , Py_BuildValue("i", DD_FAIL_QUIETLY_EACCES ));
PyModule_AddObject(m, "DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE", Py_BuildValue("i", DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE));
-
+ /* for include/report/run_event.h */
Py_INCREF(&p_run_event_state_type);
PyModule_AddObject(m, "run_event_state", (PyObject *)&p_run_event_state_type);
+ /* for include/report/report.h */
+ PyModule_AddObject(m, "LIBREPORT_NOWAIT" , Py_BuildValue("i", LIBREPORT_NOWAIT ));
+ PyModule_AddObject(m, "LIBREPORT_WAIT" , Py_BuildValue("i", LIBREPORT_WAIT ));
+ PyModule_AddObject(m, "LIBREPORT_ANALYZE" , Py_BuildValue("i", LIBREPORT_ANALYZE ));
+ PyModule_AddObject(m, "LIBREPORT_RELOAD_DATA", Py_BuildValue("i", LIBREPORT_RELOAD_DATA));
}