[SATYR PATCH 1/2] Build python api manpage conditionally
by Martin Milata
Related to #100.
Signed-off-by: Martin Milata <mmilata(a)redhat.com>
---
configure.ac | 7 +++++++
python/doc/Makefile.am | 4 +++-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index 2b16250..63769b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -38,6 +38,13 @@ PKG_CHECK_MODULES([PYTHON], [python2],,[
PYTHON_CFLAGS='-I/usr/include/python2.6'
])
+AC_ARG_ENABLE([python-manpage],
+ [AS_HELP_STRING([--disable-python-manpage],
+ [Disable python bindings manpage build])],
+ [enable_python_manpage=$enableval],
+ [enable_python_manpage=yes])
+AM_CONDITIONAL(ENABLE_PYTHON_MANPAGE, [test $enable_python_manpage = yes])
+
AC_CHECK_LIB([opcodes], [main], [have_libopcodes=yes], [have_libopcodes=no])
[if test "$have_libopcodes" = "no" -a "$target_cpu" = "x86_64"; then]
[echo "The libopcodes library was not found in the search path. The core stacktrace support "]
diff --git a/python/doc/Makefile.am b/python/doc/Makefile.am
index 4dc6221..a0350cf 100644
--- a/python/doc/Makefile.am
+++ b/python/doc/Makefile.am
@@ -133,6 +133,8 @@ EXTRA_DIST = \
stacktrace.rst \
clustering.rst
-man3_MANS = _build/man/satyr-python.3
+if ENABLE_PYTHON_MANPAGE
+ man3_MANS = _build/man/satyr-python.3
+endif
_build/man/satyr-python.3: conf.py man
--
1.8.3.1
10 years, 8 months
[BTPARSER PATCH] add dump_stack to kernel modules blacklist
by Richard Marko
Signed-off-by: Richard Marko <rmarko(a)fedoraproject.org>
---
lib/normalize_oops.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/normalize_oops.c b/lib/normalize_oops.c
index 5b2df56..36fd4d8 100644
--- a/lib/normalize_oops.c
+++ b/lib/normalize_oops.c
@@ -36,6 +36,7 @@ btp_normalize_oops_thread(struct btp_thread *thread)
const char *blacklist[] = {
"do_softirq",
"do_vfs_ioctl",
+ "dump_stack",
"flush_kthread_worker",
"gs_change",
"irq_exit",
--
1.8.3.1
10 years, 8 months
[LIBREPORT PATCH] make the build in the the build directory to not pollute the source tree
by Jiri Moskovcak
- it's easier andsafer to gitignore it if it's separated in directory
Signed-off-by: Jiri Moskovcak <jmoskovc(a)redhat.com>
---
.gitignore | 2 +-
Makefile.am | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/.gitignore b/.gitignore
index cc9ef53..bbcb18a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -95,7 +95,7 @@ libreport-version
apidoc/html/*
!apidoc/html/Makefile.am
-x86_64/*
+build/*
*.rpm
*.gz
*.patch
diff --git a/Makefile.am b/Makefile.am
index d108dbb..0a350e9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,10 +11,10 @@ pkgconfig_DATA = libreport.pc
pkgconfig_DATA += libreport-web.pc
RPM_DIRS = --define "_sourcedir `pwd`" \
- --define "_rpmdir `pwd`" \
+ --define "_rpmdir `pwd`/build" \
--define "_specdir `pwd`" \
- --define "_builddir `pwd`" \
- --define "_srcrpmdir `pwd`"
+ --define "_builddir `pwd`/build" \
+ --define "_srcrpmdir `pwd`/build"
rpm:
./gen-version
--
1.8.3.1
10 years, 8 months
[ABRT PATCH] make the build in the the build directory to not pollute the source tree
by Jiri Moskovcak
- it's easier andsafer to gitignore it if it's separated in directory
Signed-off-by: Jiri Moskovcak <jmoskovc(a)redhat.com>
---
.gitignore | 1 +
Makefile.am | 6 +++---
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/.gitignore b/.gitignore
index f3fb917..9fcbe04 100644
--- a/.gitignore
+++ b/.gitignore
@@ -143,3 +143,4 @@ tests/package.m4
# python API docs builddir
src/python-problem/doc/_build/
+build/*
diff --git a/Makefile.am b/Makefile.am
index f0b0e1b..182625b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -54,10 +54,10 @@ else
endif
RPM_DIRS = --define "_sourcedir `pwd`" \
- --define "_rpmdir `pwd`" \
+ --define "_rpmdir `pwd`/build" \
--define "_specdir `pwd`" \
- --define "_builddir `pwd`" \
- --define "_srcrpmdir `pwd`"
+ --define "_builddir `pwd`/build" \
+ --define "_srcrpmdir `pwd`/build"
rpm:
./gen-version
--
1.8.3.1
10 years, 8 months
[LIBREPORT PATCH] show warning if the network is not available - rhbz#876849
by Jiri Moskovcak
Signed-off-by: Jiri Moskovcak <jmoskovc(a)redhat.com>
---
src/gtk-helpers/Makefile.am | 3 ++-
src/gtk-helpers/internal_libreport_gtk.h | 3 +++
src/gtk-helpers/network_monitor.c | 32 ++++++++++++++++++++++++++++++++
src/gui-wizard-gtk/wizard.c | 24 +++++++++++++++++++++++-
4 files changed, 60 insertions(+), 2 deletions(-)
create mode 100644 src/gtk-helpers/network_monitor.c
diff --git a/src/gtk-helpers/Makefile.am b/src/gtk-helpers/Makefile.am
index b67186f..7c66d1f 100644
--- a/src/gtk-helpers/Makefile.am
+++ b/src/gtk-helpers/Makefile.am
@@ -15,7 +15,8 @@ libreport_gtk_la_SOURCES = \
autowrapped_label.c \
workflow_config_dialog.c \
config_dialog.c \
- ask_dialogs.c
+ ask_dialogs.c \
+ network_monitor.c
libreport_gtk_la_CPPFLAGS = \
-I$(srcdir)/../include \
diff --git a/src/gtk-helpers/internal_libreport_gtk.h b/src/gtk-helpers/internal_libreport_gtk.h
index dc1ef31..fbd49b0 100644
--- a/src/gtk-helpers/internal_libreport_gtk.h
+++ b/src/gtk-helpers/internal_libreport_gtk.h
@@ -136,6 +136,9 @@ int run_ask_yes_no_yesforever_dialog(const char *key, const char *message, GtkWi
#define run_ask_yes_no_save_result_dialog libreport_run_ask_yes_no_save_result_dialog
int run_ask_yes_no_save_result_dialog(const char *key, const char *message, GtkWindow *parent);
+#define is_network_available libreport_is_network_available
+bool is_network_available();
+
#ifdef __cplusplus
}
#endif
diff --git a/src/gtk-helpers/network_monitor.c b/src/gtk-helpers/network_monitor.c
new file mode 100644
index 0000000..193f7dc
--- /dev/null
+++ b/src/gtk-helpers/network_monitor.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 ABRT Team
+ * Copyright (C) 2012 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 <internal_libreport_gtk.h>
+
+static void on_network_change_wrap(GNetworkMonitor *g, gboolean available, void(*on_change_cb)(gboolean available))
+{
+ on_change_cb(available);
+}
+
+bool is_network_available(void(*on_change_cb)(gboolean available))
+{
+ GNetworkMonitor* net_monitor = g_network_monitor_get_default();
+ g_signal_connect(G_OBJECT(net_monitor), "network-changed", G_CALLBACK(on_network_change_wrap), on_change_cb);
+ return g_network_monitor_get_network_available(net_monitor);
+}
\ No newline at end of file
diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c
index 36ad3fa..b72dbcf 100644
--- a/src/gui-wizard-gtk/wizard.c
+++ b/src/gui-wizard-gtk/wizard.c
@@ -109,6 +109,7 @@ static GtkButton *g_btn_startcast;
static GtkExpander *g_exp_report_log;
static GtkWidget *g_top_most_window;
+static GtkWidget *g_statusbar;
static void add_workflow_buttons(GtkBox *box, GHashTable *workflows, GCallback func);
static void set_auto_event_chain(GtkButton *button, gpointer user_data);
@@ -2995,6 +2996,18 @@ static void on_next_btn_cb(GtkWidget *btn, gpointer user_data)
gtk_notebook_set_current_page(g_assistant, next_page_no);
}
+static void on_network_change(gboolean available)
+{
+ VERB1 log("The network is available: %i", available);
+ if (available)
+ {
+ gtk_statusbar_remove_all(GTK_STATUSBAR(g_statusbar), 0);
+ return;
+ }
+
+ gtk_statusbar_push(GTK_STATUSBAR(g_statusbar), 0, _("Network is not available, reporting to remote servers won't work!"));
+}
+
static void add_pages(void)
{
GError *error = NULL;
@@ -3083,6 +3096,8 @@ static void add_pages(void)
gtk_widget_override_color(GTK_WIDGET(g_eb_comment), GTK_STATE_FLAG_NORMAL, &color);
g_signal_connect(g_tv_details, "key-press-event", G_CALLBACK(on_key_press_event_in_item_list), NULL);
+ /* check the network state and hook up the callback to watch the changes */
+ on_network_change(is_network_available(&on_network_change));
}
static void create_details_treeview(void)
@@ -3299,8 +3314,15 @@ void create_assistant(bool expert_mode)
gtk_widget_hide(g_btn_onfail);
gtk_widget_show(g_btn_next);
+ /* the box which holds the main g_box_assistant and the status bar */
+ GtkWidget *main_hbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ g_statusbar = gtk_statusbar_new();
+
+ gtk_box_pack_start(GTK_BOX(main_hbox), GTK_WIDGET(g_box_assistant), true, true, 0);
+ gtk_box_pack_start(GTK_BOX(main_hbox), GTK_WIDGET(g_statusbar), false, false, 5);
+
g_wnd_assistant = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
- gtk_container_add(GTK_CONTAINER(g_wnd_assistant), GTK_WIDGET(g_box_assistant));
+ gtk_container_add(GTK_CONTAINER(g_wnd_assistant), GTK_WIDGET(main_hbox));
gtk_window_set_default_size(g_wnd_assistant, DEFAULT_WIDTH, DEFAULT_HEIGHT);
/* set_default sets icon for every windows used in this app, so we don't
--
1.8.3.1
10 years, 8 months
[SATYR PATCH] koops: "CPU:" is not a module name
by Martin Milata
I went through a few dozens of koopses in FAF and did not find anything
else that is not on the blacklist already.
Closes #102.
Signed-off-by: Martin Milata <mmilata(a)redhat.com>
---
lib/koops_stacktrace.c | 4 ++++
tests/kerneloopses/gh-102 | 25 +++++++++++++++++++++++++
tests/koops_stacktrace.at | 45 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 74 insertions(+)
create mode 100644 tests/kerneloopses/gh-102
diff --git a/lib/koops_stacktrace.c b/lib/koops_stacktrace.c
index 6aae938..559e1c7 100644
--- a/lib/koops_stacktrace.c
+++ b/lib/koops_stacktrace.c
@@ -345,6 +345,10 @@ module_list_continues(const char *input)
if (sr_skip_string(&input, "CPU ") && sr_skip_char_span(&input, "0123456789"))
return false;
+ /* See https://github.com/abrt/satyr/issues/102 */
+ if (sr_skip_string(&input, "CPU: "))
+ return false;
+
/* Other conditions may need to be added */
return true;
diff --git a/tests/kerneloopses/gh-102 b/tests/kerneloopses/gh-102
new file mode 100644
index 0000000..a26e6a5
--- /dev/null
+++ b/tests/kerneloopses/gh-102
@@ -0,0 +1,25 @@
+WARNING: at include/linux/mm.h:283 putback_inactive_pages+0x2cc/0x360()
+Modules linked in: vboxpci(OF) vboxnetadp(OF) vboxnetflt(OF) vboxdrv(OF) fuse ebtable_nat ipt_MASQUERADE nf_conntrack_netbios_ns nf_conntrack_broadcast bnep bluetooth rfkill ip6table_mangle ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 iptable_nat nf_nat_ipv4 nf_nat iptable_mangle nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ebtable_filter ebtables ip6table_filter ip6_tables be2iscsi iscsi_boot_sysfs bnx2i cnic uio cxgb4i cxgb4 cxgb3i cxgb3 mdio libcxgbi ib_iser rdma_cm ib_addr iw_cm ib_cm ib_sa ib_mad ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi snd_hda_codec_hdmi snd_usb_audio snd_hda_codec_realtek snd_usbmidi_lib snd_hda_intel snd_hda_codec uvcvideo snd_rawmidi snd_hwdep snd_seq snd_seq_device snd_pcm snd_page_alloc snd_timer iTCO_wdt videobuf2_vmalloc videobuf2_memops fglrx(POF) acpi_cpufreq mperf coretemp videobuf2_core videodev joydev iTCO_vendor_support snd ppdev hid_logitech_dj i2c_i801 media i2c_core lpc_ich mfd_core parport_pc parport !
amd_iommu_v2 microcode serio_raw soundcore vhost_net tun macvtap macvlan kvm_intel kvm binfmt_misc uinput ata_generic pata_acpi r8169 mii pata_jmicron sunrpc
+CPU: 1 PID: 42 Comm: kswapd0 Tainted: PF B WC O 3.10.4-100.fc18.x86_64 #1
+Hardware name: Gigabyte Technology Co., Ltd. EP45-UD3L/EP45-UD3L, BIOS F4 02/24/2009
+ 0000000000000009 ffff88022259da58 ffffffff816606a8 ffff88022259da98
+ ffffffff8105d660 ffff88022259dba0 ffff880227014410 ffff88022259dba8
+ 0000000000000000 ffffea0004018020 0000000000000200 ffff88022259daa8
+Call Trace:
+ [<ffffffff816606a8>] dump_stack+0x19/0x1b
+ [<ffffffff8105d660>] warn_slowpath_common+0x70/0xa0
+ [<ffffffff8105d6aa>] warn_slowpath_null+0x1a/0x20
+ [<ffffffff8114545c>] putback_inactive_pages+0x2cc/0x360
+ [<ffffffff8114567b>] shrink_inactive_list+0x18b/0x410
+ [<ffffffff81145e91>] shrink_lruvec+0x231/0x4f0
+ [<ffffffff8119fdc2>] ? drop_super+0x22/0x30
+ [<ffffffff811461b6>] shrink_zone+0x66/0x1a0
+ [<ffffffff811474fc>] balance_pgdat+0x48c/0x5c0
+ [<ffffffff811477a4>] kswapd+0x174/0x440
+ [<ffffffff81083260>] ? wake_up_bit+0x40/0x40
+ [<ffffffff81147630>] ? balance_pgdat+0x5c0/0x5c0
+ [<ffffffff81082a80>] kthread+0xc0/0xd0
+ [<ffffffff81010000>] ? perf_trace_xen_mmu_flush_tlb_others+0xa0/0x110
+ [<ffffffff810829c0>] ? kthread_create_on_node+0x120/0x120
+ [<ffffffff8166ec6c>] ret_from_fork+0x7c/0xb0
+ [<ffffffff810829c0>] ? kthread_create_on_node+0x120/0x120
diff --git a/tests/koops_stacktrace.at b/tests/koops_stacktrace.at
index c6e5b20..613a569 100644
--- a/tests/koops_stacktrace.at
+++ b/tests/koops_stacktrace.at
@@ -726,3 +726,48 @@ main(void)
return 0;
}
]])
+
+## --------------------------------------- ##
+## sr_koops_stacktrace_parse_modules_gh102 ##
+## --------------------------------------- ##
+AT_TESTFUN([sr_koops_stacktrace_parse_modules_gh102],
+[[
+#include "stacktrace.h"
+#include "koops/stacktrace.h"
+#include "location.h"
+#include "utils.h"
+#include <assert.h>
+#include <stdio.h>
+
+int
+main(void)
+{
+ char *error_message;
+ char *full_input = sr_file_to_string("../../kerneloopses/gh-102",
+ &error_message);
+
+ assert(full_input);
+ char *input = full_input;
+
+ struct sr_location location;
+ sr_location_init(&location);
+ struct sr_koops_stacktrace *stacktrace =
+ sr_koops_stacktrace_parse(&input, &location);
+
+ assert(stacktrace);
+ assert(*input == '\0');
+ free(full_input);
+
+ int module_count = 0;
+ char **mod = stacktrace->modules;
+ assert(*mod);
+
+ while (*mod++)
+ module_count++;
+
+ assert(module_count == 104);
+ assert(0 == sr_strcmp0(stacktrace->modules[module_count-1], "sunrpc"));
+
+ return 0;
+}
+]])
--
1.8.3.1
10 years, 8 months
[SATYR PATCH] fix module list parsing; closes #102
by Michal Toman
Signed-off-by: Michal Toman <mtoman(a)redhat.com>
---
lib/koops_stacktrace.c | 5 ++++-
tests/kerneloopses/github-102 | 26 ++++++++++++++++++++++++++
tests/koops_stacktrace.at | 2 ++
3 files changed, 32 insertions(+), 1 deletion(-)
create mode 100644 tests/kerneloopses/github-102
diff --git a/lib/koops_stacktrace.c b/lib/koops_stacktrace.c
index 6aae938..a4e19f2 100644
--- a/lib/koops_stacktrace.c
+++ b/lib/koops_stacktrace.c
@@ -342,7 +342,10 @@ module_list_continues(const char *input)
return false;
/* See tests/kerneloopses/rhbz-865695-2-notime */
- if (sr_skip_string(&input, "CPU ") && sr_skip_char_span(&input, "0123456789"))
+ /* and tests/kerneloopses/github-102 */
+ if (sr_skip_string(&input, "CPU") &&
+ sr_skip_char_span(&input, " :") &&
+ sr_skip_char_span(&input, "0123456789"))
return false;
/* Other conditions may need to be added */
diff --git a/tests/kerneloopses/github-102 b/tests/kerneloopses/github-102
new file mode 100644
index 0000000..667750d
--- /dev/null
+++ b/tests/kerneloopses/github-102
@@ -0,0 +1,26 @@
+WARNING: at include/linux/mm.h:283 putback_inactive_pages+0x2cc/0x360()
+Modules linked in: vboxpci(OF) vboxnetadp(OF) vboxnetflt(OF) vboxdrv(OF) fuse ebtable_nat ipt_MASQUERADE nf_conntrack_netbios_ns nf_conntrack_broadcast bnep bluetooth rfkill ip6table_mangle ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 iptable_nat nf_nat_ipv4 nf_nat iptable_mangle nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ebtable_filter ebtables ip6table_filter ip6_tables be2iscsi iscsi_boot_sysfs bnx2i cnic uio cxgb4i cxgb4 cxgb3i cxgb3 mdio libcxgbi ib_iser rdma_cm ib_addr iw_cm ib_cm ib_sa ib_mad ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi snd_hda_codec_hdmi snd_usb_audio snd_hda_codec_realtek snd_usbmidi_lib snd_hda_intel snd_hda_codec uvcvideo snd_rawmidi snd_hwdep snd_seq snd_seq_device snd_pcm snd_page_alloc snd_timer iTCO_wdt videobuf2_vmalloc videobuf2_memops fglrx(POF) acpi_cpufreq mperf coretemp videobuf2_core
+ videodev joydev iTCO_vendor_support snd ppdev hid_logitech_dj i2c_i801 media i2c_core lpc_ich mfd_core parport_pc parport amd_iommu_v2 microcode serio_raw soundcore vhost_net tun macvtap macvlan kvm_intel kvm binfmt_misc uinput ata_generic pata_acpi r8169 mii pata_jmicron sunrpc
+CPU: 1 PID: 42 Comm: kswapd0 Tainted: PF B WC O 3.10.4-100.fc18.x86_64 #1
+Hardware name: Gigabyte Technology Co., Ltd. EP45-UD3L/EP45-UD3L, BIOS F4 02/24/2009
+ 0000000000000009 ffff88022259da58 ffffffff816606a8 ffff88022259da98
+ ffffffff8105d660 ffff88022259dba0 ffff880227014410 ffff88022259dba8
+ 0000000000000000 ffffea0004018020 0000000000000200 ffff88022259daa8
+Call Trace:
+ [<ffffffff816606a8>] dump_stack+0x19/0x1b
+ [<ffffffff8105d660>] warn_slowpath_common+0x70/0xa0
+ [<ffffffff8105d6aa>] warn_slowpath_null+0x1a/0x20
+ [<ffffffff8114545c>] putback_inactive_pages+0x2cc/0x360
+ [<ffffffff8114567b>] shrink_inactive_list+0x18b/0x410
+ [<ffffffff81145e91>] shrink_lruvec+0x231/0x4f0
+ [<ffffffff8119fdc2>] ? drop_super+0x22/0x30
+ [<ffffffff811461b6>] shrink_zone+0x66/0x1a0
+ [<ffffffff811474fc>] balance_pgdat+0x48c/0x5c0
+ [<ffffffff811477a4>] kswapd+0x174/0x440
+ [<ffffffff81083260>] ? wake_up_bit+0x40/0x40
+ [<ffffffff81147630>] ? balance_pgdat+0x5c0/0x5c0
+ [<ffffffff81082a80>] kthread+0xc0/0xd0
+ [<ffffffff81010000>] ? perf_trace_xen_mmu_flush_tlb_others+0xa0/0x110
+ [<ffffffff810829c0>] ? kthread_create_on_node+0x120/0x120
+ [<ffffffff8166ec6c>] ret_from_fork+0x7c/0xb0
+ [<ffffffff810829c0>] ? kthread_create_on_node+0x120/0x120
diff --git a/tests/koops_stacktrace.at b/tests/koops_stacktrace.at
index c6e5b20..51092fe 100644
--- a/tests/koops_stacktrace.at
+++ b/tests/koops_stacktrace.at
@@ -242,6 +242,8 @@ main(void)
check("../../kerneloopses/rhbz-865695-2", "wdev_priv.part.8", "system_call_fastpath", 20, 2, 103);
check("../../kerneloopses/rhbz-865695-2-notime", "wdev_priv.part.8", "system_call_fastpath", 20, 2, 103);
+ check("../../kerneloopses/github-102", "dump_stack", "kthread_create_on_node", 17, 6, 104);
+
return 0;
}
]])
--
1.8.3.1
10 years, 8 months
[LIBREPORT PATCH] debuginfo code cleanup, closes #171
by Petr Kubat
Signed-off-by: Petr Kubat <pkubat(a)redhat.com>
---
src/client-python/debuginfo.py | 549 +++++++++++++++++++++++++++--------------
1 file changed, 361 insertions(+), 188 deletions(-)
diff --git a/src/client-python/debuginfo.py b/src/client-python/debuginfo.py
index 07e54c2..779c25c 100644
--- a/src/client-python/debuginfo.py
+++ b/src/client-python/debuginfo.py
@@ -1,29 +1,33 @@
-from subprocess import Popen, PIPE
-from yum import _, YumBase
-from yum.callbacks import DownloadBaseCallback
-from reportclient import *
-from reportclient import _
+"""
+ This module provides classes and functions used to download and manage
+ debuginfos.
+"""
+
import sys
import os
import time
import errno
import shutil
+from subprocess import Popen
+
+from yum import _, YumBase
+from yum.callbacks import DownloadBaseCallback
+from yum.Errors import YumBaseError
+
+from reportclient import (_, log1, log2, RETURN_OK, RETURN_FAILURE,
+ RETURN_CANCEL_BY_USER, verbose, ask_yes_no,
+ error_msg)
-old_stdout = -1
-def mute_stdout():
- if verbose < 2:
- global old_stdout
- old_stdout = sys.stdout
- sys.stdout = open("/dev/null", "w")
-
-def unmute_stdout():
- if verbose < 2:
- if old_stdout != -1:
- sys.stdout = old_stdout
- else:
- print "ERR: unmute called without mute?"
-def ensure_abrt_uid(fn):
+def ensure_abrt_uid(func):
+ """
+ Ensures that the function is called using abrt's uid and gid
+
+ Returns:
+ Either an unchanged function object or a wrapper function object for
+ the function.
+ """
+
import pwd
current_uid = os.getuid()
current_gid = os.getgid()
@@ -31,14 +35,24 @@ def ensure_abrt_uid(fn):
# if we're are already running as abrt, don't do anything
if abrt.pw_uid == current_uid and abrt.pw_gid == current_gid:
- return fn
+ return func
def wrapped(*args, **kwargs):
+ """
+ Wrapper function around the called function.
+
+ Sets up uid and gid to match abrt's and after the function finishes
+ rolls its uid and gid back.
+
+ Returns:
+ Return value of the wrapped function.
+ """
+
# switch to abrt
os.setegid(abrt.pw_gid)
os.seteuid(abrt.pw_uid)
# extract the files as abrt:abrt
- retval = fn(*args, **kwargs)
+ retval = func(*args, **kwargs)
# switch back to whatever we were
os.seteuid(current_uid)
os.setegid(current_gid)
@@ -46,11 +60,28 @@ def ensure_abrt_uid(fn):
return wrapped
+
# TODO: unpack just required debuginfo and not entire rpm?
# ..that can lead to: foo.c No such file and directory
# files is not used...
@ensure_abrt_uid
-def unpack_rpm(package_file_name, files, tmp_dir, destdir, keeprpm, exact_files=False):
+def unpack_rpm(package_file_name, files, tmp_dir, destdir, keeprpm,
+ exact_files=False):
+ """
+ Unpacks a single rpm located in tmp_dir into destdir.
+
+ Arguments:
+ package_file_name - name of the rpm file
+ files - files to extract from the rpm
+ tmp_dir - temporary directory where the rpm file is located
+ destdir - destination directory for the rpm package extraction
+ keeprpm - check if the user wants to delete rpms from the tmp directory
+ exact_files - extract only specified files
+
+ Returns:
+ RETURN_FAILURE in case of a serious problem
+ """
+
package_full_path = tmp_dir + "/" + package_file_name
log1("Extracting %s to %s", package_full_path, destdir)
log2("%s", files)
@@ -63,7 +94,7 @@ def unpack_rpm(package_file_name, files, tmp_dir, destdir, keeprpm, exact_files=
return RETURN_FAILURE
rpm2cpio = Popen(["rpm2cpio", package_full_path],
- stdout = unpacked_cpio, bufsize = -1)
+ stdout=unpacked_cpio, bufsize=-1)
retcode = rpm2cpio.wait()
if retcode == 0:
@@ -82,7 +113,8 @@ def unpack_rpm(package_file_name, files, tmp_dir, destdir, keeprpm, exact_files=
# and open it for reading
unpacked_cpio = open(unpacked_cpio_path, 'rb')
- print _("Caching files from {0} made from {1}").format("unpacked.cpio", package_file_name)
+ print _("Caching files from {0} made from {1}").format("unpacked.cpio",
+ package_file_name)
file_patterns = ""
cpio_args = ["cpio", "-idu"]
@@ -104,16 +136,20 @@ def unpack_rpm(package_file_name, files, tmp_dir, destdir, keeprpm, exact_files=
print _("Can't extract files from '{0}'").format(unpacked_cpio_path)
return RETURN_FAILURE
-def clean_up():
- if tmpdir:
- try:
- shutil.rmtree(tmpdir)
- except OSError, ex:
- if ex.errno != errno.ENOENT:
- error_msg(_("Can't remove '{0}': {1}").format(tmpdir, ex))
class MyDownloadCallback(DownloadBaseCallback):
+ """
+ This class serves as a download progress handler for yum's progress bar.
+ """
+
def __init__(self, total_pkgs):
+ """
+ Sets up instance variables
+
+ Arguments:
+ total_pkgs - number of packages to download
+ """
+
self.total_pkgs = total_pkgs
self.downloaded_pkgs = 0
self.last_pct = 0
@@ -121,6 +157,16 @@ class MyDownloadCallback(DownloadBaseCallback):
DownloadBaseCallback.__init__(self)
def updateProgress(self, name, frac, fread, ftime):
+ """
+ A method used to update the progress
+
+ Arguments:
+ name - filename
+ frac - progress fracment (0 -> 1)
+ fread - formated string containing BytesRead
+ ftime - formated string containing remaining or elapsed time
+ """
+
pct = int(frac * 100)
if pct == self.last_pct:
log2("percentage is the same, not updating progress")
@@ -130,50 +176,57 @@ class MyDownloadCallback(DownloadBaseCallback):
# if run from terminal we can have fancy output
if sys.stdout.isatty():
sys.stdout.write("\033[sDownloading (%i of %i) %s: %3u%%\033[u"
- % (self.downloaded_pkgs + 1, self.total_pkgs, name, pct)
- )
+ % (self.downloaded_pkgs + 1, self.total_pkgs,
+ name, pct))
if pct == 100:
#print (_("Downloading (%i of %i) %s: %3u%%")
- # % (self.downloaded_pkgs + 1, self.total_pkgs, name, pct)
+ # % (self.downloaded_pkgs + 1, self.total_pkgs, name, pct)
#)
print (_("Downloading ({0} of {1}) {2}: {3:3}%").format(
- self.downloaded_pkgs + 1, self.total_pkgs, name, pct
- )
- )
+ self.downloaded_pkgs + 1, self.total_pkgs, name, pct))
# but we want machine friendly output when spawned from abrt-server
else:
- t = time.time()
+ cur_time = time.time()
if self.last_time == 0:
- self.last_time = t
+ self.last_time = cur_time
# update only every 5 seconds
- if pct == 100 or self.last_time > t or t - self.last_time >= 5:
+ if pct == 100 or (self.last_time > cur_time or
+ cur_time - self.last_time >= 5):
print (_("Downloading ({0} of {1}) {2}: {3:3}%").format(
- self.downloaded_pkgs + 1, self.total_pkgs, name, pct
- )
- )
- self.last_time = t
+ self.downloaded_pkgs + 1, self.total_pkgs, name, pct))
+ self.last_time = cur_time
if pct == 100:
self.last_time = 0
sys.stdout.flush()
-def downloadErrorCallback(callBackObj):
- print _("Problem '{0!s}' occured while downloading from mirror: '{1!s}'. Trying next one").format(
- callBackObj.exception, callBackObj.mirror)
+
+def download_error_callback(callback_obj):
+ """
+ A callback function for mirror errors.
+ """
+
+ print _("Problem '{0!s}' occured while downloading from mirror: '{1!s}'."
+ "Trying next one").format(
+ callback_obj.exception, callback_obj.mirror)
# explanation of the return value can be found here:
# /usr/lib/python2.7/site-packages/urlgrabber/mirror.py
- return {'fail':0}
+ return {'fail': 0}
+
class DebugInfoDownload(YumBase):
+ """
+ This class is used to manage download of debuginfos.
+ """
+
def __init__(self, cache, tmp, keep_rpms=False, noninteractive=True):
+ self.old_stdout = -1
self.cachedir = cache
self.tmpdir = tmp
- global tmpdir
- tmpdir = tmp
self.keeprpms = keep_rpms
self.noninteractive = noninteractive
YumBase.__init__(self)
- mute_stdout()
+ self.mute_stdout()
#self.conf.cache = os.geteuid() != 0
# Setup yum (Ts, RPM db, Repo & Sack)
# doConfigSetup() takes some time, let user know what we are doing
@@ -181,17 +234,59 @@ class DebugInfoDownload(YumBase):
try:
# Saw this exception here:
# cannot open Packages index using db3 - Permission denied (13)
- # yum.Errors.YumBaseError: Error: rpmdb open failed
+ # YumBaseError: Error: rpmdb open failed
self.doConfigSetup()
- except Exception, e:
- unmute_stdout()
- print _("Error initializing yum (YumBase.doConfigSetup): '{0!s}'").format(e)
+ except YumBaseError, ex:
+ self.unmute_stdout()
+ print _("Error initializing yum (YumBase.doConfigSetup): "
+ "'{0!s}'").format(ex)
#return 1 - can't do this in constructor
exit(1)
- unmute_stdout()
+ self.unmute_stdout()
+
+ def mute_stdout(self):
+ """
+ Links sys.stdout with /dev/null and saves the old stdout
+ """
+
+ if verbose < 2:
+ self.old_stdout = sys.stdout
+ sys.stdout = open("/dev/null", "w")
+
+ def unmute_stdout(self):
+ """
+ Replaces sys.stdout by stdout saved using mute
+ """
+
+ if verbose < 2:
+ if self.old_stdout != -1:
+ sys.stdout = self.old_stdout
+ else:
+ print "ERR: unmute called without mute?"
+
+ def cleanup_tmp_dir(self):
+ """
+ Removes the temporary directory.
+ """
+
+ if self.tmpdir:
+ try:
+ shutil.rmtree(self.tmpdir)
+ except OSError, ex:
+ if ex.errno != errno.ENOENT:
+ error_msg(_("Can't remove '{0}': {1}").format(
+ self.tmpdir, ex))
@ensure_abrt_uid
def setup_tmp_dirs(self):
+ """
+ Sets up tmpdir and cache dir if they are not set up already.
+
+ Returns:
+ RETURN_OK if all goes well.
+ RETURN_FAILURE in case it cannot set up either of the directories.
+ """
+
if not os.path.exists(self.tmpdir):
try:
os.makedirs(self.tmpdir)
@@ -207,83 +302,219 @@ class DebugInfoDownload(YumBase):
return RETURN_OK
- # return value will be used as exitcode. So 0 = ok, !0 - error
- def download(self, files, download_exact_files=False):
- """ @files - """
- installed_size = 0
- total_pkgs = 0
- todownload_size = 0
+ def _download_rpms(self, package_files_dict, total_pkgs,
+ download_exact_files):
+ """
+ Downloads rpms into a temporary directory
+
+ Arguments:
+ package_files_dict - a dict containing {pkg: file list} entries
+ total_pkgs - total number of packages to download
+ download_exact_files - extract only specified files
+
+ Returns:
+ RETURN_OK if all goes well.
+ RETURN_FAILURE in case it cannot set up either of the directories.
+ """
+
+ # connect our progress update callback
+ dnlcb = MyDownloadCallback(total_pkgs)
+ self.repos.setProgressBar(dnlcb)
+ self.repos.setMirrorFailureCallback(download_error_callback)
downloaded_pkgs = 0
- # nothing to download?
- if not files:
- return RETURN_FAILURE
- #if verbose == 0:
- # # this suppress yum messages about setting up repositories
- # mute_stdout()
+ for pkg, files in package_files_dict.iteritems():
+ dnlcb.downloaded_pkgs = downloaded_pkgs
+ remote = pkg.returnSimple('relativepath')
+ local = os.path.basename(remote)
+ retval = self.setup_tmp_dirs()
+ # continue only if the tmp dirs are ok
+ if retval != RETURN_OK:
+ return retval
- # make yumdownloader work as non root user
- if not self.setCacheDir():
- print _("Error: can't make cachedir, exiting")
- return RETURN_FAILURE
+ remote = pkg.returnSimple('remote_url')
+ # check if the pkg is in a local repo and copy it if it is
+ err = None
+ if remote.startswith('file:///'):
+ log2("copying from local repo: %s", remote)
+ try:
+ shutil.copy(remote[7:], self.tmpdir)
+ except OSError, ex:
+ print _("Cannot copy file '{0}': {1}").format(
+ remote[7:], ex)
+ continue
+ else:
+ # pkg is in a remote repo, we need to download it to tmpdir
+ local = os.path.join(self.tmpdir, local)
+ pkg.localpath = local # Hack: to set the localpath we want
+ err = self.downloadPkgs(pkglist=[pkg])
+ # normalize the name
+ # just str(pkg) doesn't work because it can have epoch
+ package_file_name = (pkg.name + "-" + pkg.version + "-" +
+ pkg.release + "." + pkg.arch) + ".rpm"
+ if err:
+ # I observed a zero-length file left on error,
+ # which prevents cleanup later. Fix it:
+ try:
+ os.unlink(self.tmpdir + "/" + package_file_name)
+ except OSError:
+ pass
+ print (_("Downloading package {0} failed").format(pkg))
+ else:
+ unpack_result = unpack_rpm(package_file_name, files,
+ self.tmpdir, self.cachedir,
+ self.keeprpms,
+ exact_files=download_exact_files)
+ if unpack_result == RETURN_FAILURE:
+ # recursively delete the temp dir on failure
+ print _("Unpacking failed, aborting download...")
+ self.cleanup_tmp_dir()
+ return RETURN_FAILURE
+
+ downloaded_pkgs += 1
+ return RETURN_OK
+
+ def _setup_repos(self):
+ """
+ Disables repos and then sets up repos one-by-one so we can skip
+ broken ones.
+
+ this helps when users are using 3rd party repos like rpmfusion
+ in rawhide it results in: Can't find valid base url
+ """
# disable all not needed
for repo in self.repos.listEnabled():
try:
repo.close()
self.repos.disableRepo(repo.id)
- except Exception, ex:
- print _("Can't disable repository '{0!s}': {1!s}").format(repo.id, str(ex))
+ except YumBaseError, ex:
+ print _("Can't disable repository '{0!s}': {1!s}").format(
+ repo.id, str(ex))
# This takes some time, let user know what we are doing
print _("Setting up yum repositories")
- # setting-up repos one-by-one, so we can skip the broken ones...
- # this helps when users are using 3rd party repos like rpmfusion
- # in rawhide it results in: Can't find valid base url...
- for r in self.repos.findRepos(pattern="*debug*"):
+ for repo in self.repos.findRepos(pattern="*debug*"):
try:
- rid = self.repos.enableRepo(r.id)
- self.repos.doSetup(thisrepo=str(r.id))
+ rid = self.repos.enableRepo(repo.id)
+ self.repos.doSetup(thisrepo=str(repo.id))
log1("enabled repo %s", rid)
- setattr(r, "skip_if_unavailable", True)
+ setattr(repo, "skip_if_unavailable", True)
# yes, we want async download, otherwise our progressCallback
# is not called and the internal yum's one is used,
# which causes artifacts on output
try:
- setattr(r, "_async", False)
- except Exception, ex:
+ setattr(repo, "_async", False)
+ except (NameError, AttributeError), ex:
print ex
- print _("Can't disable async download, the output might contain artifacts!")
- except Exception, ex:
- print _("Can't setup {0}: {1}, disabling").format(r.id, ex)
- self.repos.disableRepo(r.id)
+ print _("Can't disable async download, the output might"
+ " contain artifacts!")
+ except (NameError, AttributeError, YumBaseError), ex:
+ print _("Can't setup {0}: {1}, disabling").format(repo.id, ex)
+ self.repos.disableRepo(repo.id)
+
+ def _check_space(self, total_pkgs, todownload_size, installed_size):
+ """
+ Checks free space in tmp and cache directories.
+
+ Returns:
+ RETURN_OK if all goes well.
+ RETURN_FAILURE in case it cannot set up either of the directories.
+ """
+
+ if verbose != 0 or total_pkgs != 0:
+ print _("Packages to download: {0}").format(total_pkgs)
+ question = _("Downloading {0:.2f}Mb, installed size: {1:.2f}Mb."
+ " Continue?").format(
+ todownload_size / (1024*1024), installed_size / (1024*1024))
+ if not self.noninteractive and not ask_yes_no(question):
+ print _("Download cancelled by user")
+ return RETURN_CANCEL_BY_USER
+
+ # set up tmp and cache dirs so that we can check free space in both
+ retval = self.setup_tmp_dirs()
+ if retval != RETURN_OK:
+ return retval
+ # check if there is enough free space in both tmp and cache
+ res = os.statvfs(self.tmpdir)
+ tmp_space = float(res.f_bsize * res.f_bavail) / (1024*1024)
+ if (todownload_size / (1024*1024)) > tmp_space:
+ question = _("Warning: Not enough free space in tmp dir '{0}'"
+ " ({1:.2f}Mb left). Continue?").format(
+ self.tmpdir, tmp_space)
+ if not self.noninteractive and not ask_yes_no(question):
+ print _("Download cancelled by user")
+ return RETURN_CANCEL_BY_USER
+ res = os.statvfs(self.cachedir)
+ cache_space = float(res.f_bsize * res.f_bavail) / (1024*1024)
+ if (installed_size / (1024*1024)) > cache_space:
+ question = _("Warning: Not enough free space in cache dir "
+ "'{0}' ({1:.2f}Mb left). Continue?").format(
+ self.cachedir, cache_space)
+ if not self.noninteractive and not ask_yes_no(question):
+ print _("Download cancelled by user")
+ return RETURN_CANCEL_BY_USER
+
+ return RETURN_OK
+
+ def _retrieve_repo_data(self):
+ """
+ Retrieves metadata and filelists from remote servers.
+ """
- # This is somewhat "magic", it unpacks the metadata making it usable.
- # Looks like this is the moment when yum talks to remote servers,
- # which takes time (sometimes minutes), let user know why
- # we have "paused":
- print _("Looking for needed packages in repositories")
try:
self.repos.populateSack(mdtype='metadata', cacheonly=1)
- except Exception, e:
- print _("Error retrieving metadata: '{0!s}'").format(e)
- #we don't want to die here, some metadata might be already retrieved
- # so there is a chance we already have what we need
- #return 1
+ except YumBaseError, ex:
+ print _("Error retrieving metadata: '{0!s}'").format(ex)
+ # we don't want to die here, some metadata might be already
+ # retrieved so there is a chance we already have what we need
+ # return 1
try:
# Saw this exception here:
# raise Errors.NoMoreMirrorsRepoError, errstr
# NoMoreMirrorsRepoError: failure:
- # repodata/7e6632b82c91a2e88a66ad848e231f14c48259cbf3a1c3e992a77b1fc0e9d2f6-filelists.sqlite.bz2
# from fedora-debuginfo: [Errno 256] No more mirrors to try.
self.repos.populateSack(mdtype='filelists', cacheonly=1)
- except Exception, ex:
+ except YumBaseError, ex:
print _("Error retrieving filelists: '{0!s}'").format(ex)
# we don't want to die here, some repos might be already processed
# so there is a chance we already have what we need
#return 1
+ # return value will be used as exitcode. So 0 = ok, !0 - error
+ def download(self, files, download_exact_files=False):
+ """
+ Finds debuginfo files in an rpm package and downloads it to
+ a temporary directory.
+ """
+
+ installed_size = 0
+ total_pkgs = 0
+ todownload_size = 0
+ # nothing to download?
+ if not files:
+ return RETURN_FAILURE
+
+ #if verbose == 0:
+ # # this suppress yum messages about setting up repositories
+ # mute_stdout()
+
+ # make yumdownloader work as non root user
+ if not self.setCacheDir():
+ print _("Error: can't make cachedir, exiting")
+ return RETURN_FAILURE
+
+ # set up yum repositories
+ self._setup_repos()
+
+ # This is somewhat "magic", it unpacks the metadata making it usable.
+ # Looks like this is the moment when yum talks to remote servers,
+ # which takes time (sometimes minutes), let user know why
+ # we have "paused":
+ print _("Looking for needed packages in repositories")
+ self._retrieve_repo_data()
+
#if verbose == 0:
# # re-enable the output to stdout
# unmute_stdout()
@@ -309,94 +540,18 @@ class DebugInfoDownload(YumBase):
log2("not found pkg for %s", debuginfo_path)
not_found.append(debuginfo_path)
- # connect our progress update callback
- dnlcb = MyDownloadCallback(total_pkgs)
- self.repos.setProgressBar(dnlcb)
- self.repos.setMirrorFailureCallback(downloadErrorCallback)
-
if verbose != 0 or len(not_found) != 0:
- print _("Can't find packages for {0} debuginfo files").format(len(not_found))
- if verbose != 0 or total_pkgs != 0:
- print _("Packages to download: {0}").format(total_pkgs)
- question = _("Downloading {0:.2f}Mb, installed size: {1:.2f}Mb. Continue?").format(
- todownload_size / (1024*1024),
- installed_size / (1024*1024)
- )
- if self.noninteractive == False and not ask_yes_no(question):
- print _("Download cancelled by user")
- return RETURN_CANCEL_BY_USER
- # set up tmp and cache dirs so that we can check free space in both
- retval = self.setup_tmp_dirs()
- if retval != RETURN_OK:
- return retval
- # check if there is enough free space in both tmp and cache
- res = os.statvfs(self.tmpdir)
- tmp_space = float(res.f_bsize * res.f_bavail) / (1024*1024)
- if (todownload_size / (1024*1024)) > tmp_space:
- question = _("Warning: Not enough free space in tmp dir '{0}'"
- " ({1:.2f}Mb left). Continue?").format(
- self.tmpdir, tmp_space)
- if not self.noninteractive and not ask_yes_no(question):
- print _("Download cancelled by user")
- return RETURN_CANCEL_BY_USER
- res = os.statvfs(self.cachedir)
- cache_space = float(res.f_bsize * res.f_bavail) / (1024*1024)
- if (installed_size / (1024*1024)) > cache_space:
- question = _("Warning: Not enough free space in cache dir "
- "'{0}' ({1:.2f}Mb left). Continue?").format(
- self.cachedir, cache_space)
- if not self.noninteractive and not ask_yes_no(question):
- print _("Download cancelled by user")
- return RETURN_CANCEL_BY_USER
+ print _("Can't find packages for {0} debuginfo files").format(
+ len(not_found))
- for pkg, files in package_files_dict.iteritems():
- dnlcb.downloaded_pkgs = downloaded_pkgs
- repo.cache = 0
- remote = pkg.returnSimple('relativepath')
- local = os.path.basename(remote)
- retval = self.setup_tmp_dirs()
- # continue only if the tmp dirs are ok
- if retval != RETURN_OK:
- return retval
+ retval = self._check_space(total_pkgs, todownload_size, installed_size)
+ if retval != RETURN_OK:
+ return retval
- remote_path = pkg.returnSimple('remote_url')
- # check if the pkg is in a local repo and copy it if it is
- err = None
- if remote_path.startswith('file:///'):
- pkg_path = remote_path[7:]
- log2("copying from local repo: %s", remote)
- try:
- shutil.copy(pkg_path, self.tmpdir)
- except OSError, ex:
- print _("Cannot copy file '{0}': {1}").format(pkg_path, ex)
- continue
- else:
- # pkg is in a remote repo, we need to download it to tmpdir
- local = os.path.join(self.tmpdir, local)
- pkg.localpath = local # Hack: to set the localpath we want
- err = self.downloadPkgs(pkglist=[pkg])
- # normalize the name
- # just str(pkg) doesn't work because it can have epoch
- pkg_nvra = pkg.name + "-" + pkg.version + "-" + pkg.release + "." + pkg.arch
- package_file_name = pkg_nvra + ".rpm"
- if err:
- # I observed a zero-length file left on error,
- # which prevents cleanup later. Fix it:
- try:
- os.unlink(self.tmpdir + "/" + package_file_name)
- except:
- pass
- print (_("Downloading package {0} failed").format(pkg))
- else:
- unpack_result = unpack_rpm(package_file_name, files, self.tmpdir,
- self.cachedir, self.keeprpms, exact_files=download_exact_files)
- if unpack_result == RETURN_FAILURE:
- # recursively delete the temp dir on failure
- print _("Unpacking failed, aborting download...")
- clean_up()
- return RETURN_FAILURE
-
- downloaded_pkgs += 1
+ retval = self._download_rpms(package_files_dict, total_pkgs,
+ download_exact_files)
+ if retval != RETURN_OK:
+ return retval
if not self.keeprpms and os.path.exists(self.tmpdir):
# Was: "All downloaded packages have been extracted, removing..."
@@ -406,21 +561,39 @@ class DebugInfoDownload(YumBase):
try:
os.rmdir(self.tmpdir)
except OSError:
- error_msg(_("Can't remove %s, probably contains an error log").format(self.tmpdir))
+ error_msg(_("Can't remove %s, probably contains an "
+ "error log").format(self.tmpdir))
return RETURN_OK
+
def build_ids_to_path(pfx, build_ids):
"""
+ Transforms build ids into a path.
+
build_id1=${build_id:0:2}
build_id2=${build_id:2}
file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug"
"""
- return ["%s/usr/lib/debug/.build-id/%s/%s.debug" % (pfx, b_id[:2], b_id[2:]) for b_id in build_ids]
+
+ return ["%s/usr/lib/debug/.build-id/%s/%s.debug" %
+ (pfx, b_id[:2], b_id[2:]) for b_id in build_ids]
# beware this finds only missing libraries, but not the executable itself ..
+
def filter_installed_debuginfos(build_ids, cache_dirs):
+ """
+ Checks for installed debuginfos.
+
+ Arguments:
+ build_ids - string containing build ids
+ cache_dirs - list of cache directories
+
+ Returns:
+ List of missing debuginfo files.
+ """
+
files = build_ids_to_path("", build_ids)
missing = []
@@ -436,7 +609,7 @@ def filter_installed_debuginfos(build_ids, cache_dirs):
if missing:
files = missing
missing = []
- else: # nothing is missing, we can stop looking
+ else: # nothing is missing, we can stop looking
return missing
for cache_dir in cache_dirs:
@@ -454,7 +627,7 @@ def filter_installed_debuginfos(build_ids, cache_dirs):
if missing:
files = missing
missing = []
- else: # nothing is missing, we can stop looking
+ else: # nothing is missing, we can stop looking
return missing
return files
--
1.8.3.1
10 years, 8 months
[LIBREPORT PATCH] fixed debugInfoDownload so that it can process local repos - closes #48
by Petr Kubat
Signed-off-by: Petr Kubat <pkubat(a)redhat.com>
---
src/client-python/debuginfo.py | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/client-python/debuginfo.py b/src/client-python/debuginfo.py
index 035d697..146d2b1 100644
--- a/src/client-python/debuginfo.py
+++ b/src/client-python/debuginfo.py
@@ -7,6 +7,7 @@ import sys
import os
import time
import errno
+import shutil
old_stdout = -1
def mute_stdout():
@@ -335,9 +336,22 @@ class DebugInfoDownload(YumBase):
if retval != RETURN_OK:
return retval
- local = os.path.join(self.tmpdir, local)
- pkg.localpath = local # Hack: to set the localpath we want
- err = self.downloadPkgs(pkglist=[pkg])
+ remote_path = pkg.returnSimple('remote_url')
+ # check if the pkg is in a local repo and copy it if it is
+ err = None
+ if remote_path.startswith('file:///'):
+ pkg_path = remote_path[7:]
+ log2("copying from local repo: %s", remote)
+ try:
+ shutil.copy(pkg_path, self.tmpdir)
+ except OSError, ex:
+ print _("Cannot copy file '{0}': {1}").format(pkg_path, ex)
+ continue
+ else:
+ # pkg is in a remote repo, we need to download it to tmpdir
+ local = os.path.join(self.tmpdir, local)
+ pkg.localpath = local # Hack: to set the localpath we want
+ err = self.downloadPkgs(pkglist=[pkg])
# normalize the name
# just str(pkg) doesn't work because it can have epoch
pkg_nvra = pkg.name + "-" + pkg.version + "-" + pkg.release + "." + pkg.arch
--
1.8.3.1
10 years, 8 months
[LIBREPORT PATCH] Increase text size limit from 1Mb to 8 MB. rhbz#887570.
by Denys Vlasenko
Signed-off-by: Denys Vlasenko <dvlasenk(a)redhat.com>
---
src/include/internal_libreport.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/include/internal_libreport.h b/src/include/internal_libreport.h
index da4e982..ae46ad4 100644
--- a/src/include/internal_libreport.h
+++ b/src/include/internal_libreport.h
@@ -749,8 +749,10 @@ struct dump_dir *open_directory_for_writing(
// Bumped up to 500k: saw 375252 byte anaconda traceback file
// Bumped up to 1M: bugzilla.redhat.com/show_bug.cgi?id=746727
// mentions 853646 byte anaconda-tb-* file.
+// Bumped up to 8M: bugzilla.redhat.com/show_bug.cgi?id=887570
+// (anaconda-tb file of 1.38 MBytes)
//
-#define CD_MAX_TEXT_SIZE (1024*1024)
+#define CD_MAX_TEXT_SIZE (8*1024*1024)
// Text bigger than this usually is attached, not added inline
// was 2k, 20kb is too much, let's try 4kb
--
1.8.1.4
10 years, 8 months