Merge lp:~brian-murray/apport/sandbox-gdb into lp:~apport-hackers/apport/trunk

Proposed by Brian Murray
Status: Merged
Merged at revision: 3124
Proposed branch: lp:~brian-murray/apport/sandbox-gdb
Merge into: lp:~apport-hackers/apport/trunk
Diff against target: 1510 lines (+516/-342)
8 files modified
apport/packaging.py (+4/-1)
apport/report.py (+55/-18)
apport/sandboxutils.py (+15/-2)
backends/packaging-apt-dpkg.py (+51/-9)
bin/apport-retrace (+54/-6)
po/apport.pot (+306/-306)
test/test_backend_apt_dpkg.py (+17/-0)
test/test_report.py (+14/-0)
To merge this branch: bzr merge lp:~brian-murray/apport/sandbox-gdb
Reviewer Review Type Date Requested Status
Steve Langasek Needs Fixing
Barry Warsaw Pending
Apport upstream developers Pending
Review via email: mp+315619@code.launchpad.net

Description of the change

This adds an option, --gdb-sandbox, to apport-retrace that will install gdb in the report's sandbox (if it is the same architecture as the host) or create another sandbox using the distribution from the report and the host's architecture. This makes it so that users of apport-retrace do not need to have gdb or gdb-multiarch installed on their system and ensures that a modern version of gdb is being used to retrace the crash.

Some of the changes, choosing which gdb to use, are from work Martin did in revision r3076 of apport.

One thing I don't feel great about is the way os.environ is modified and restored for LD_LIBRARY_PATH etc as the code is duplicated in apport-retrace and apport/report.py so suggestions welcome there!

To post a comment you must log in.
lp:~brian-murray/apport/sandbox-gdb updated
3141. By Brian Murray

pep8, pyflakes fixes

Revision history for this message
Brian Murray (brian-murray) wrote :

Oh, I've tested this using the _bin_cat crash from apport test crashes for arches amd64, i386, armhf, and arm64. Additionally, I've used the following combinations of switches "--gdb-sandbox, -C", "--gdb --gdb-sandbox -C", "--gdb-sandbox -C --sandbox-dir", and "-C".

Revision history for this message
Steve Langasek (vorlon) wrote :

> One thing I don't feel great about is the way os.environ is modified
> and restored for LD_LIBRARY_PATH etc as the code is duplicated in
> apport-retrace and apport/report.py so suggestions welcome there!

Most of the subprocess family of calls can take an env= argument pointing to an environment to use for the subprocess. You could factor out a helper function to populate a copy environment, then pass this in to subprocess.call().

From what I see, the code in apport-retrace isn't ever setting an environment at all, it's saving an environment and then restoring that same environment without ever modifying it in between. So, +1 indeed for factoring this out!

review: Needs Fixing
lp:~brian-murray/apport/sandbox-gdb updated
3142. By Brian Murray

Changed how environmental variables are set for the gdb call.

Revision history for this message
Brian Murray (brian-murray) wrote :

On Wed, Jan 25, 2017 at 10:52:12PM -0000, Steve Langasek wrote:
> Review: Needs Fixing
>
> > One thing I don't feel great about is the way os.environ is modified
> > and restored for LD_LIBRARY_PATH etc as the code is duplicated in
> > apport-retrace and apport/report.py so suggestions welcome there!
>
> Most of the subprocess family of calls can take an env= argument
> pointing to an environment to use for the subprocess. You could factor
> out a helper function to populate a copy environment, then pass this
> in to subprocess.call().

Cool, fixed.

> >From what I see, the code in apport-retrace isn't ever setting an
> >environment at all, it's saving an environment and then restoring
> >that same environment without ever modifying it in between. So, +1
> >indeed for factoring this out!

It was getting set in report.py's gdb_command, but by using subprocess's
env= argument I think things are clearer and cleaner now.

--
Brian Murray

lp:~brian-murray/apport/sandbox-gdb updated
3143. By Brian Murray

update generic packaging.py documentation

3144. By Brian Murray

add a test for report._command_output passing env arguments

3145. By Brian Murray

add in a test for _which_extrapath

3146. By Brian Murray

add a test for install_packages install_deps argument

3147. By Brian Murray

bin/apport-retrace: exit if the system architecture is not amd64

Revision history for this message
Barry Warsaw (barry) wrote :

Just a few comments, but nothing that must be changed.

lp:~brian-murray/apport/sandbox-gdb updated
3148. By Brian Murray

modifications based off barry's feedback

Revision history for this message
Brian Murray (brian-murray) wrote :

Thanks Barry, I've made some of the changes you suggested.

lp:~brian-murray/apport/sandbox-gdb updated
3149. By Brian Murray

Merge with upstream.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'apport/packaging.py'
2--- apport/packaging.py 2016-05-03 19:00:37 +0000
3+++ apport/packaging.py 2017-01-31 23:14:32 +0000
4@@ -193,7 +193,7 @@
5 def install_packages(self, rootdir, configdir, release, packages,
6 verbose=False, cache_dir=None,
7 permanent_rootdir=False, architecture=None,
8- origins=None, install_dbg=True):
9+ origins=None, install_dbg=True, install_deps=False):
10 '''Install packages into a sandbox (for apport-retrace).
11
12 In order to work without any special permissions and without touching
13@@ -225,6 +225,9 @@
14 If origins is given, the sandbox will be created with apt data sources
15 for foreign origins.
16
17+ If install_deps is True, then the dependencies of packages will also
18+ be installed.
19+
20 Return a string with outdated packages, or None if all packages were
21 installed.
22
23
24=== modified file 'apport/report.py'
25--- apport/report.py 2016-12-18 12:50:20 +0000
26+++ apport/report.py 2017-01-31 23:14:32 +0000
27@@ -91,14 +91,14 @@
28 return maps
29
30
31-def _command_output(command, input=None):
32+def _command_output(command, input=None, env=None):
33 '''Run command and capture its output.
34
35 Try to execute given command (argv list) and return its stdout, or return
36 a textual error if it failed.
37 '''
38 sp = subprocess.Popen(command, stdout=subprocess.PIPE,
39- stderr=subprocess.STDOUT)
40+ stderr=subprocess.STDOUT, env=env)
41
42 out = sp.communicate(input)[0]
43 if sp.returncode == 0:
44@@ -213,6 +213,23 @@
45
46 return False
47
48+
49+def _which_extrapath(command, extra_path):
50+ '''Return path of command, preferring extra_path'''
51+
52+ if extra_path:
53+ env = os.environ.copy()
54+ parts = env.get('PATH', '').split(os.pathsep)
55+ parts[0:0] = extra_path
56+ env['PATH'] = os.pathsep.join(parts)
57+ else:
58+ env = None
59+ try:
60+ return subprocess.check_output(['which', command], env=env).decode().strip()
61+ except subprocess.CalledProcessError:
62+ return None
63+
64+
65 #
66 # Report class
67 #
68@@ -661,7 +678,7 @@
69 os.unlink(core)
70 return ret
71
72- def add_gdb_info(self, rootdir=None):
73+ def add_gdb_info(self, rootdir=None, gdb_sandbox=None):
74 '''Add information from gdb.
75
76 This requires that the report has a CoreDump and an
77@@ -693,8 +710,7 @@
78 'AssertionMessage': 'print __abort_msg->msg',
79 'GLibAssertionMessage': 'print __glib_assert_msg',
80 'NihAssertionMessage': 'print (char*) __nih_abort_msg'}
81-
82- gdb_cmd = self.gdb_command(rootdir)
83+ gdb_cmd, environ = self.gdb_command(rootdir, gdb_sandbox)
84
85 # limit maximum backtrace depth (to avoid looped stacks)
86 gdb_cmd += ['--batch', '--ex', 'set backtrace limit 2000']
87@@ -705,8 +721,7 @@
88 value_keys.append(name)
89 gdb_cmd += ['--ex', 'p -99', '--ex', cmd]
90
91- # call gdb (might raise OSError)
92- out = _command_output(gdb_cmd).decode('UTF-8', errors='replace')
93+ out = _command_output(gdb_cmd, env=environ).decode('UTF-8', errors='replace')
94
95 # check for truncated stack trace
96 if 'is truncated: expected core file size' in out:
97@@ -1490,7 +1505,7 @@
98 else:
99 self[k] = pattern.sub(repl, self[k])
100
101- def gdb_command(self, sandbox):
102+ def gdb_command(self, sandbox, gdb_sandbox=None):
103 '''Build gdb command for this report.
104
105 This builds a gdb command for processing the given report, by setting
106@@ -1501,20 +1516,28 @@
107 When available, this calls "gdb-multiarch" instead of "gdb", for
108 processing crash reports from foreign architectures.
109
110- Return argv list.
111+ Return argv list for gdb and any environment variables.
112 '''
113 assert 'ExecutablePath' in self
114 executable = self.get('InterpreterPath', self['ExecutablePath'])
115
116- command = ['gdb']
117-
118- if 'Architecture' in self and self['Architecture'] != packaging.get_system_architecture():
119+ same_arch = False
120+ if 'Architecture' in self and self['Architecture'] == packaging.get_system_architecture():
121+ same_arch = True
122+
123+ gdb_sandbox_bin = (os.path.join(gdb_sandbox, 'usr', 'bin') if gdb_sandbox else None)
124+ gdb_path = _which_extrapath('gdb', gdb_sandbox_bin)
125+ if not gdb_path:
126+ apport.fatal('gdb does not exist in the %ssandbox nor on the host'
127+ % ('gdb ' if not same_arch else ''))
128+ command = [gdb_path]
129+ environ = None
130+
131+ if not same_arch:
132 # check if we have gdb-multiarch
133- which = subprocess.Popen(['which', 'gdb-multiarch'],
134- stdout=subprocess.PIPE)
135- which.communicate()
136- if which.returncode == 0:
137- command = ['gdb-multiarch']
138+ ma = _which_extrapath('gdb-multiarch', gdb_sandbox_bin)
139+ if ma:
140+ command = [ma]
141 else:
142 sys.stderr.write(
143 'WARNING: Please install gdb-multiarch for processing '
144@@ -1522,8 +1545,22 @@
145 'will be very poor.\n')
146
147 if sandbox:
148+ # N.B. set solib-absolute-prefix is an alias for set sysroot
149 command += ['--ex', 'set debug-file-directory %s/usr/lib/debug' % sandbox,
150 '--ex', 'set solib-absolute-prefix ' + sandbox]
151+ if gdb_sandbox:
152+ native_multiarch = "x86_64-linux-gnu"
153+ ld_lib_path = '%s/lib:%s/lib/%s:%s/usr/lib/%s:%s/usr/lib' % \
154+ (gdb_sandbox, gdb_sandbox, native_multiarch,
155+ gdb_sandbox, native_multiarch, gdb_sandbox)
156+ pyhome = '%s/usr' % gdb_sandbox
157+ # env settings need to be modified for gdb in a sandbox
158+ environ = {'LD_LIBRARY_PATH': ld_lib_path,
159+ 'PYTHONHOME': pyhome,
160+ 'GCONV_PATH': '%s/usr/lib/%s/gconv' % (gdb_sandbox, native_multiarch)}
161+ command.insert(0, '%s/lib/%s/ld-linux-x86-64.so.2' % (gdb_sandbox, native_multiarch))
162+ command += ['--ex', 'set data-directory %s/usr/share/gdb' % gdb_sandbox,
163+ '--ex', 'set auto-load safe-path ' + sandbox]
164 executable = sandbox + '/' + executable
165
166 assert os.path.exists(executable)
167@@ -1547,7 +1584,7 @@
168
169 command += ['--ex', 'core-file ' + core]
170
171- return command
172+ return command, environ
173
174 def _address_to_offset(self, addr):
175 '''Resolve a memory address to an ELF name and offset.
176
177=== modified file 'apport/sandboxutils.py'
178--- apport/sandboxutils.py 2016-05-11 10:43:40 +0000
179+++ apport/sandboxutils.py 2017-01-31 23:14:32 +0000
180@@ -138,7 +138,8 @@
181 deleted at program exit.
182
183 extra_packages can specify a list of additional packages to install which
184- are not derived from the report.
185+ are not derived from the report and will be installed along with their
186+ dependencies.
187
188 If verbose is True (False by default), this will write some additional
189 logging to stdout.
190@@ -181,8 +182,10 @@
191 pkgs = needed_packages(report)
192
193 # add user-specified extra packages, if any
194+ extra_pkgs = []
195 for p in extra_packages:
196- pkgs.append((p, None))
197+ extra_pkgs.append((p, None))
198+
199 if config_dir == 'system':
200 config_dir = None
201
202@@ -202,6 +205,16 @@
203 architecture=report.get('Architecture'), origins=origins)
204 except SystemError as e:
205 apport.fatal(str(e))
206+ # install the extra packages and their deps
207+ if extra_pkgs:
208+ try:
209+ outdated_msg += apport.packaging.install_packages(
210+ sandbox_dir, config_dir, report['DistroRelease'], extra_pkgs,
211+ verbose, cache_dir, permanent_rootdir,
212+ architecture=report.get('Architecture'), origins=origins,
213+ install_deps=True)
214+ except SystemError as e:
215+ apport.fatal(str(e))
216
217 pkg_versions = report_package_versions(report)
218 pkgs = needed_runtime_packages(report, sandbox_dir, pkgmap_cache_dir, pkg_versions, verbose)
219
220=== modified file 'backends/packaging-apt-dpkg.py'
221--- backends/packaging-apt-dpkg.py 2016-12-10 11:28:27 +0000
222+++ backends/packaging-apt-dpkg.py 2017-01-31 23:14:32 +0000
223@@ -46,6 +46,7 @@
224 def __init__(self):
225 self._apt_cache = None
226 self._sandbox_apt_cache = None
227+ self._sandbox_apt_cache_arch = None
228 self._contents_dir = None
229 self._mirror = None
230 self._virtual_mapping_obj = None
231@@ -93,17 +94,19 @@
232 self._apt_cache = apt.Cache(rootdir='/')
233 return self._apt_cache
234
235- def _sandbox_cache(self, aptroot, apt_sources, fetchProgress, distro_name, release_codename, origins):
236+ def _sandbox_cache(self, aptroot, apt_sources, fetchProgress, distro_name,
237+ release_codename, origins, arch):
238 '''Build apt sandbox and return apt.Cache(rootdir=) (initialized lazily).
239
240 Clear the package selection on subsequent calls.
241 '''
242 self._apt_cache = None
243- if not self._sandbox_apt_cache:
244+ if not self._sandbox_apt_cache or arch != self._sandbox_apt_cache_arch:
245 self._build_apt_sandbox(aptroot, apt_sources, distro_name,
246 release_codename, origins)
247 rootdir = os.path.abspath(aptroot)
248 self._sandbox_apt_cache = apt.Cache(rootdir=rootdir)
249+ self._sandbox_apt_cache_arch = arch
250 try:
251 # We don't need to update this multiple times.
252 self._sandbox_apt_cache.update(fetchProgress)
253@@ -669,7 +672,7 @@
254 def install_packages(self, rootdir, configdir, release, packages,
255 verbose=False, cache_dir=None,
256 permanent_rootdir=False, architecture=None,
257- origins=None, install_dbg=True):
258+ origins=None, install_dbg=True, install_deps=False):
259 '''Install packages into a sandbox (for apport-retrace).
260
261 In order to work without any special permissions and without touching
262@@ -701,6 +704,9 @@
263 If origins is given, the sandbox will be created with apt data sources
264 for foreign origins.
265
266+ If install_deps is True, then the dependencies of packages will also
267+ be installed.
268+
269 Return a string with outdated packages, or None if all packages were
270 installed.
271
272@@ -738,10 +744,14 @@
273 # create apt sandbox
274 if cache_dir:
275 tmp_aptroot = False
276+ if architecture != self.get_system_architecture():
277+ aptroot_arch = architecture
278+ else:
279+ aptroot_arch = ''
280 if configdir:
281- aptroot = os.path.join(cache_dir, release, 'apt')
282+ aptroot = os.path.join(cache_dir, release, aptroot_arch, 'apt')
283 else:
284- aptroot = os.path.join(cache_dir, 'system', 'apt')
285+ aptroot = os.path.join(cache_dir, 'system', aptroot_arch, 'apt')
286 if not os.path.isdir(aptroot):
287 os.makedirs(aptroot)
288 else:
289@@ -762,7 +772,7 @@
290 cache = self._sandbox_cache(aptroot, apt_sources, fetchProgress,
291 self.get_distro_name(),
292 self.current_release_codename,
293- origins)
294+ origins, architecture)
295 else:
296 self._build_apt_sandbox(aptroot, apt_sources,
297 self.get_distro_name(),
298@@ -798,6 +808,38 @@
299 fetcher = apt.apt_pkg.Acquire(fetchProgress)
300 # need to keep AcquireFile references
301 acquire_queue = []
302+ # add any dependencies to the packages list
303+ if install_deps:
304+ deps = []
305+ for (pkg, ver) in packages:
306+ try:
307+ cache_pkg = cache[pkg]
308+ except KeyError:
309+ m = 'package %s does not exist, ignoring' % pkg.replace('%', '%%')
310+ obsolete += m + '\n'
311+ apport.warning(m)
312+ continue
313+ for dep in cache_pkg.candidate.dependencies:
314+ # if the dependency is in the list of packages we don't
315+ # need to look up its dependencies again
316+ if dep[0].name in [pkg[0] for pkg in packages]:
317+ continue
318+ # if the package is already extracted in the sandbox
319+ # because the report need that package we don't want to
320+ # install a newer version which may cause a CRC mismatch
321+ # with the installed dbg symbols
322+ if dep[0].name in pkg_versions:
323+ inst_version = pkg_versions[dep[0].name]
324+ if self.compare_versions(inst_version, dep[0].version) > -1:
325+ deps.append((dep[0].name, inst_version))
326+ else:
327+ deps.append((dep[0].name, dep[0].version))
328+ else:
329+ deps.append((dep[0].name, dep[0].version))
330+ if dep[0].name not in [pkg[0] for pkg in packages]:
331+ packages.append((dep[0].name, None))
332+ packages.extend(deps)
333+
334 for (pkg, ver) in packages:
335 try:
336 cache_pkg = cache[pkg]
337@@ -1012,9 +1054,9 @@
338 if verbose:
339 print('Extracting downloaded debs...')
340 for i in fetcher.items:
341- if not permanent_rootdir or os.path.getctime(i.destfile) > last_written:
342- out = subprocess.check_output(['dpkg-deb', '--show', i.destfile]).decode()
343- (p, v) = out.strip().split()
344+ out = subprocess.check_output(['dpkg-deb', '--show', i.destfile]).decode()
345+ (p, v) = out.strip().split()
346+ if not permanent_rootdir or p not in pkg_versions or os.path.getctime(i.destfile) > last_written:
347 # don't extract the same version of the package if it is
348 # already extracted
349 if pkg_versions.get(p) == v:
350
351=== modified file 'bin/apport-retrace'
352--- bin/apport-retrace 2016-12-18 12:53:35 +0000
353+++ bin/apport-retrace 2017-01-31 23:14:32 +0000
354@@ -49,6 +49,8 @@
355 help=_('Rebuild report\'s Package information'))
356 argparser.add_argument('-S', '--sandbox', metavar='CONFIG_DIR',
357 help=_('Build a temporary sandbox and download/install the necessary packages and debug symbols in there; without this option it assumes that the necessary packages and debug symbols are already installed in the system. The argument points to the packaging system configuration base directory; if you specify "system", it will use the system configuration files, but will then only be able to retrace crashes that happened on the currently running release.'))
358+ argparser.add_argument('--gdb-sandbox', action='store_true',
359+ help=_('Build another temporary sandbox for installing gdb and its dependencies using the same release as the report rather than whatever version of gdb you have installed.'))
360 argparser.add_argument('-v', '--verbose', action='store_true',
361 help=_('Report download/install progress when installing packages into sandbox'))
362 argparser.add_argument('--timestamps', action='store_true',
363@@ -280,7 +282,8 @@
364
365
366 # sanity checks
367-required_fields = set(['CoreDump', 'ExecutablePath', 'Package', 'DistroRelease'])
368+required_fields = set(['CoreDump', 'ExecutablePath', 'Package',
369+ 'DistroRelease', 'Architecture'])
370 if report['ProblemType'] == 'KernelCrash':
371 if not set(['Package', 'VmCore']).issubset(set(report.keys())):
372 apport.error('report file does not contain the required fields')
373@@ -294,18 +297,63 @@
374
375 apport.memdbg('sanity checks passed')
376
377+if options.gdb_sandbox:
378+ system_arch = apport.packaging.get_system_architecture()
379+ if system_arch != 'amd64':
380+ apport.error('gdb sandboxes are only implemented for amd64 hosts')
381+ sys.exit(0)
382+
383 if options.sandbox:
384+ if options.sandbox_dir:
385+ sandbox_dir = '%s/%s/%s/report-sandbox/' % \
386+ (options.sandbox_dir, report['DistroRelease'],
387+ report['Architecture'])
388+ else:
389+ sandbox_dir = None
390+ if options.gdb_sandbox:
391+ if report['Architecture'] == system_arch:
392+ options.extra_package.append('gdb')
393 sandbox, cache, outdated_msg = apport.sandboxutils.make_sandbox(
394- report, options.sandbox, options.cache, options.sandbox_dir,
395+ report, options.sandbox, options.cache, sandbox_dir,
396 options.extra_package, options.verbose, log_timestamps,
397 options.dynamic_origins)
398 else:
399 sandbox = None
400+ cache = None
401 outdated_msg = None
402
403+if options.gdb_sandbox:
404+ if report['Architecture'] == system_arch:
405+ if sandbox:
406+ # gdb was installed in the sandbox
407+ gdb_sandbox = sandbox
408+ gdb_cache = cache
409+ else:
410+ gdb_packages = ['gdb', 'gdb-multiarch']
411+ fake_report = apport.Report()
412+ # if the report has no Architecture the host one will be used
413+ fake_report['DistroRelease'] = report['DistroRelease']
414+ # use a empty ProcMaps so needed_runtimes packages won't want ExecPath
415+ fake_report['ProcMaps'] = '\n\n'
416+ if options.sandbox_dir:
417+ gdb_sandbox_dir = '%s/%s/%s/gdb-sandbox/' % \
418+ (options.sandbox_dir, report['DistroRelease'], system_arch)
419+ else:
420+ gdb_sandbox_dir = None
421+ gdb_sandbox, gdb_cache, gdb_outdated_msg = \
422+ apport.sandboxutils.make_sandbox(fake_report,
423+ options.sandbox, options.cache,
424+ gdb_sandbox_dir, gdb_packages,
425+ options.verbose, log_timestamps,
426+ options.dynamic_origins)
427+else:
428+ gdb_sandbox = None
429+ gdb_cache = None
430+ gdb_outdated_msg = None
431+
432 # interactive gdb session
433 if options.gdb:
434- gdb_cmd = report.gdb_command(sandbox)
435+ gdb_cmd, environ = report.gdb_command(sandbox, gdb_sandbox)
436 if options.verbose:
437 # build a shell-style command
438 cmd = ''
439@@ -318,12 +366,12 @@
440 cmd += w
441 apport.log('Calling gdb command: ' + cmd, log_timestamps)
442 apport.memdbg('before calling gdb')
443- subprocess.call(gdb_cmd)
444+ subprocess.call(gdb_cmd, env=environ)
445 else:
446 # regenerate gdb info
447 apport.memdbg('before collecting gdb info')
448 try:
449- report.add_gdb_info(sandbox)
450+ report.add_gdb_info(sandbox, gdb_sandbox)
451 except IOError as e:
452 if not options.auth:
453 apport.fatal(str(e))
454@@ -337,7 +385,7 @@
455
456 Thank you for your understanding, and sorry for the inconvenience!
457 '''
458- crashdb.mark_retrace_failed(crashid, corruptcore_msg)
459+ crashdb.mark_retrace_failed(crashid, invalid_msg)
460 apport.fatal(str(e))
461 if options.sandbox == 'system':
462 apt_root = os.path.join(cache, 'system', 'apt')
463
464=== modified file 'po/apport.pot'
465--- po/apport.pot 2015-09-10 09:17:19 +0000
466+++ po/apport.pot 2017-01-31 23:14:32 +0000
467@@ -8,7 +8,7 @@
468 msgstr ""
469 "Project-Id-Version: PACKAGE VERSION\n"
470 "Report-Msgid-Bugs-To: \n"
471-"POT-Creation-Date: 2015-09-10 11:16+0200\n"
472+"POT-Creation-Date: 2016-12-19 10:06-0800\n"
473 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
474 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
475 "Language-Team: LANGUAGE <LL@li.org>\n"
476@@ -17,8 +17,8 @@
477 "Content-Type: text/plain; charset=CHARSET\n"
478 "Content-Transfer-Encoding: 8bit\n"
479
480-#: ../gtk/apport-gtk.ui.h:1 ../kde/apport-kde.py:468 ../kde/apport-kde.py:503
481-#: ../kde/apport-kde.py:522
482+#: ../gtk/apport-gtk.ui.h:1 ../kde/apport-kde.py:469 ../kde/apport-kde.py:504
483+#: ../kde/apport-kde.py:524
484 msgid "Apport"
485 msgstr ""
486
487@@ -38,7 +38,7 @@
488 msgid "<big><b>Sorry, an internal error happened.</b></big>"
489 msgstr ""
490
491-#: ../gtk/apport-gtk.ui.h:6 ../gtk/apport-gtk.py:300 ../kde/apport-kde.py:240
492+#: ../gtk/apport-gtk.ui.h:6 ../gtk/apport-gtk.py:303 ../kde/apport-kde.py:241
493 msgid "If you notice further problems, try restarting the computer."
494 msgstr ""
495
496@@ -50,8 +50,8 @@
497 msgid "Ignore future problems of this program version"
498 msgstr ""
499
500-#: ../gtk/apport-gtk.ui.h:9 ../gtk/apport-gtk.py:204 ../gtk/apport-gtk.py:573
501-#: ../kde/apport-kde.py:291
502+#: ../gtk/apport-gtk.ui.h:9 ../gtk/apport-gtk.py:207 ../gtk/apport-gtk.py:576
503+#: ../kde/apport-kde.py:292
504 msgid "Show Details"
505 msgstr ""
506
507@@ -59,12 +59,12 @@
508 msgid "_Examine locally"
509 msgstr ""
510
511-#: ../gtk/apport-gtk.ui.h:11 ../gtk/apport-gtk.py:287 ../kde/apport-kde.py:233
512+#: ../gtk/apport-gtk.ui.h:11 ../gtk/apport-gtk.py:290 ../kde/apport-kde.py:234
513 msgid "Leave Closed"
514 msgstr ""
515
516-#: ../gtk/apport-gtk.ui.h:12 ../gtk/apport-gtk.py:216 ../gtk/apport-gtk.py:284
517-#: ../gtk/apport-gtk.py:303 ../kde/apport-kde.py:230 ../kde/apport-kde.py:243
518+#: ../gtk/apport-gtk.ui.h:12 ../gtk/apport-gtk.py:219 ../gtk/apport-gtk.py:287
519+#: ../gtk/apport-gtk.py:306 ../kde/apport-kde.py:231 ../kde/apport-kde.py:244
520 msgid "Continue"
521 msgstr ""
522
523@@ -78,7 +78,7 @@
524 "you report."
525 msgstr ""
526
527-#: ../gtk/apport-gtk.ui.h:15 ../kde/apport-kde.py:434 ../bin/apport-cli.py:251
528+#: ../gtk/apport-gtk.ui.h:15 ../kde/apport-kde.py:435 ../bin/apport-cli.py:251
529 msgid "Uploading problem information"
530 msgstr ""
531
532@@ -86,308 +86,97 @@
533 msgid "<big><b>Uploading problem information</b></big>"
534 msgstr ""
535
536-#: ../gtk/apport-gtk.ui.h:17 ../kde/apport-kde.py:435
537+#: ../gtk/apport-gtk.ui.h:17 ../kde/apport-kde.py:436
538 msgid ""
539 "The collected information is being sent to the bug tracking system. This "
540 "might take a few minutes."
541 msgstr ""
542
543-#: ../kde/apport-kde-mimelnk.desktop.in.h:1
544-msgid "Apport crash file"
545-msgstr ""
546-
547-#: ../gtk/apport-gtk.py:142 ../kde/apport-kde.py:362 ../bin/apport-cli.py:150
548+#: ../gtk/apport-gtk.py:145 ../kde/apport-kde.py:363 ../bin/apport-cli.py:150
549 msgid "(binary data)"
550 msgstr ""
551
552-#: ../gtk/apport-gtk.py:157
553+#: ../gtk/apport-gtk.py:160
554 #, python-format
555 msgid "Sorry, the application %s has stopped unexpectedly."
556 msgstr ""
557
558-#: ../gtk/apport-gtk.py:160
559+#: ../gtk/apport-gtk.py:163
560 #, python-format
561 msgid "Sorry, %s has closed unexpectedly."
562 msgstr ""
563
564-#: ../gtk/apport-gtk.py:165 ../kde/apport-kde.py:199 ../kde/apport-kde.py:237
565+#: ../gtk/apport-gtk.py:168 ../kde/apport-kde.py:200 ../kde/apport-kde.py:238
566 #, python-format
567 msgid "Sorry, %s has experienced an internal error."
568 msgstr ""
569
570-#: ../gtk/apport-gtk.py:177 ../kde/apport-kde.py:185 ../bin/apport-cli.py:178
571+#: ../gtk/apport-gtk.py:180 ../kde/apport-kde.py:186 ../bin/apport-cli.py:178
572 msgid "Send problem report to the developers?"
573 msgstr ""
574
575-#: ../gtk/apport-gtk.py:186 ../kde/apport-kde.py:193
576+#: ../gtk/apport-gtk.py:189 ../kde/apport-kde.py:194
577 msgid "Send"
578 msgstr ""
579
580-#: ../gtk/apport-gtk.py:228
581+#: ../gtk/apport-gtk.py:231
582 msgid "Force Closed"
583 msgstr ""
584
585-#: ../gtk/apport-gtk.py:229 ../gtk/apport-gtk.py:288 ../kde/apport-kde.py:234
586-#: ../kde/apport-kde.py:380
587+#: ../gtk/apport-gtk.py:232 ../gtk/apport-gtk.py:291 ../kde/apport-kde.py:235
588+#: ../kde/apport-kde.py:381
589 msgid "Relaunch"
590 msgstr ""
591
592-#: ../gtk/apport-gtk.py:238
593+#: ../gtk/apport-gtk.py:241
594 #, python-format
595 msgid "The application %s has stopped responding."
596 msgstr ""
597
598-#: ../gtk/apport-gtk.py:242
599+#: ../gtk/apport-gtk.py:245
600 #, python-format
601 msgid "The program \"%s\" has stopped responding."
602 msgstr ""
603
604-#: ../gtk/apport-gtk.py:257 ../kde/apport-kde.py:207
605+#: ../gtk/apport-gtk.py:260 ../kde/apport-kde.py:208
606 #, python-format
607 msgid "Package: %s"
608 msgstr ""
609
610-#: ../gtk/apport-gtk.py:264 ../kde/apport-kde.py:213
611+#: ../gtk/apport-gtk.py:267 ../kde/apport-kde.py:214
612 msgid "Sorry, a problem occurred while installing software."
613 msgstr ""
614
615-#: ../gtk/apport-gtk.py:273 ../gtk/apport-gtk.py:292 ../kde/apport-kde.py:219
616+#: ../gtk/apport-gtk.py:276 ../gtk/apport-gtk.py:295 ../kde/apport-kde.py:220
617 #, python-format
618 msgid "The application %s has experienced an internal error."
619 msgstr ""
620
621-#: ../gtk/apport-gtk.py:276 ../kde/apport-kde.py:222
622+#: ../gtk/apport-gtk.py:279 ../kde/apport-kde.py:223
623 #, python-format
624 msgid "The application %s has closed unexpectedly."
625 msgstr ""
626
627-#: ../gtk/apport-gtk.py:304 ../kde/apport-kde.py:244
628+#: ../gtk/apport-gtk.py:307 ../kde/apport-kde.py:245
629 msgid "Ignore future problems of this type"
630 msgstr ""
631
632-#: ../gtk/apport-gtk.py:577 ../kde/apport-kde.py:288
633+#: ../gtk/apport-gtk.py:580 ../kde/apport-kde.py:289
634 msgid "Hide Details"
635 msgstr ""
636
637-#: ../bin/apport-unpack.py:22
638-#, python-format
639-msgid "Usage: %s <report> <target directory>"
640-msgstr ""
641-
642-#: ../bin/apport-unpack.py:46
643-msgid "Destination directory exists and is not empty."
644-msgstr ""
645-
646-#: ../kde/apport-kde.py:314
647-msgid "Username:"
648-msgstr ""
649-
650-#: ../kde/apport-kde.py:315
651-msgid "Password:"
652-msgstr ""
653-
654-#: ../kde/apport-kde.py:405
655-msgid "Collecting Problem Information"
656-msgstr ""
657-
658-#: ../kde/apport-kde.py:406 ../bin/apport-cli.py:238
659-msgid "Collecting problem information"
660-msgstr ""
661-
662-#: ../kde/apport-kde.py:407
663-msgid ""
664-"The collected information can be sent to the developers to improve the "
665-"application. This might take a few minutes."
666-msgstr ""
667-
668-#: ../kde/apport-kde.py:433
669-msgid "Uploading Problem Information"
670-msgstr ""
671-
672-#: ../apport/com.ubuntu.apport.policy.in.h:1
673-msgid "Collect system information"
674-msgstr ""
675-
676-#: ../apport/com.ubuntu.apport.policy.in.h:2
677-msgid ""
678-"Authentication is required to collect system information for this problem "
679-"report"
680-msgstr ""
681-
682-#: ../apport/com.ubuntu.apport.policy.in.h:3
683-msgid "System problem reports"
684-msgstr ""
685-
686-#: ../apport/com.ubuntu.apport.policy.in.h:4
687-msgid "Please enter your password to access problem reports of system programs"
688-msgstr ""
689-
690-#: ../kde/apport-kde.desktop.in.h:1 ../gtk/apport-gtk.desktop.in.h:1
691-#: ../kde/apport-kde-mime.desktop.in.h:1
692-msgid "Report a problem..."
693-msgstr ""
694-
695-#: ../kde/apport-kde.desktop.in.h:2 ../gtk/apport-gtk.desktop.in.h:2
696-#: ../kde/apport-kde-mime.desktop.in.h:2
697-msgid "Report a malfunction to the developers"
698-msgstr ""
699-
700-#: ../bin/apport-valgrind.py:37
701-msgid "See man page for details."
702-msgstr ""
703-
704-#: ../bin/apport-valgrind.py:43
705-msgid "specify the log file name produced by valgrind"
706-msgstr ""
707-
708-#: ../bin/apport-valgrind.py:46
709-msgid ""
710-"reuse a previously created sandbox dir (SDIR) or, if it does not exist, "
711-"create it"
712-msgstr ""
713-
714-#: ../bin/apport-valgrind.py:50
715-msgid ""
716-"do not create or reuse a sandbox directory for additional debug symbols "
717-"but rely only on installed debug symbols."
718-msgstr ""
719-
720-#: ../bin/apport-valgrind.py:54
721-msgid ""
722-"reuse a previously created cache dir (CDIR) or, if it does not exist, create "
723-"it"
724-msgstr ""
725-
726-#: ../bin/apport-valgrind.py:58
727-msgid "report download/install progress when installing packages into sandbox"
728-msgstr ""
729-
730-#: ../bin/apport-valgrind.py:62
731-msgid ""
732-"the executable that is run under valgrind's memcheck tool for memory leak "
733-"detection"
734-msgstr ""
735-
736-#: ../bin/apport-valgrind.py:66 ../bin/apport-retrace.py:63
737-msgid ""
738-"Install an extra package into the sandbox (can be specified multiple times)"
739-msgstr ""
740-
741-#: ../bin/apport-valgrind.py:97
742-#, python-format
743-msgid "Error: %s is not an executable. Stopping."
744-msgstr ""
745-
746-#: ../data/kernel_oops.py:29
747-msgid "Your system might become unstable now and might need to be restarted."
748-msgstr ""
749-
750-#: ../bin/apport-retrace.py:34
751-msgid "Do not put the new traces into the report, but write them to stdout."
752-msgstr ""
753-
754-#: ../bin/apport-retrace.py:36
755-msgid ""
756-"Start an interactive gdb session with the report's core dump (-o ignored; "
757-"does not rewrite report)"
758-msgstr ""
759-
760-#: ../bin/apport-retrace.py:38
761-msgid ""
762-"Write modified report to given file instead of changing the original report"
763-msgstr ""
764-
765-#: ../bin/apport-retrace.py:41
766-msgid "Remove the core dump from the report after stack trace regeneration"
767-msgstr ""
768-
769-#: ../bin/apport-retrace.py:43
770-msgid "Override report's CoreFile"
771-msgstr ""
772-
773-#: ../bin/apport-retrace.py:45
774-msgid "Override report's ExecutablePath"
775-msgstr ""
776-
777-#: ../bin/apport-retrace.py:47
778-msgid "Override report's ProcMaps"
779-msgstr ""
780-
781-#: ../bin/apport-retrace.py:49
782-msgid "Rebuild report's Package information"
783-msgstr ""
784-
785-#: ../bin/apport-retrace.py:51
786-msgid ""
787-"Build a temporary sandbox and download/install the necessary packages and "
788-"debug symbols in there; without this option it assumes that the necessary "
789-"packages and debug symbols are already installed in the system. The argument "
790-"points to the packaging system configuration base directory; if you specify "
791-"\"system\", it will use the system configuration files, but will then only "
792-"be able to retrace crashes that happened on the currently running release."
793-msgstr ""
794-
795-#: ../bin/apport-retrace.py:53
796-msgid "Report download/install progress when installing packages into sandbox"
797-msgstr ""
798-
799-#: ../bin/apport-retrace.py:55
800-msgid "Prepend timestamps to log messages, for batch operation"
801-msgstr ""
802-
803-#: ../bin/apport-retrace.py:57
804-msgid ""
805-"Create and use third-party repositories from origins specified in reports"
806-msgstr ""
807-
808-#: ../bin/apport-retrace.py:59
809-msgid "Cache directory for packages downloaded in the sandbox"
810-msgstr ""
811-
812-#: ../bin/apport-retrace.py:61
813-msgid ""
814-"Directory for unpacked packages. Future runs will assume that any already "
815-"downloaded package is also extracted to this sandbox."
816-msgstr ""
817-
818-#: ../bin/apport-retrace.py:65
819-msgid ""
820-"Path to a file with the crash database authentication information. This is "
821-"used when specifying a crash ID to upload the retraced stack traces (only if "
822-"neither -g, -o, nor -s are specified)"
823-msgstr ""
824-
825-#: ../bin/apport-retrace.py:67
826-msgid ""
827-"Display retraced stack traces and ask for confirmation before sending them "
828-"to the crash database."
829-msgstr ""
830-
831-#: ../bin/apport-retrace.py:69
832-msgid "Path to the duplicate sqlite database (default: no duplicate checking)"
833-msgstr ""
834-
835-#: ../bin/apport-retrace.py:78
836-msgid "You cannot use -C without -S. Stopping."
837-msgstr ""
838-
839-#. translators: don't translate y/n, apport currently only checks for "y"
840-#: ../bin/apport-retrace.py:111
841-msgid "OK to send these as attachments? [y/n]"
842-msgstr ""
843-
844-#: ../apport/ui.py:124
845+#: ../apport/ui.py:131
846 msgid "This package does not seem to be installed correctly"
847 msgstr ""
848
849-#: ../apport/ui.py:129
850+#: ../apport/ui.py:136
851 #, python-format
852 msgid ""
853 "This is not an official %s package. Please remove any third party package "
854 "and try again."
855 msgstr ""
856
857-#: ../apport/ui.py:146
858+#: ../apport/ui.py:153
859 #, python-format
860 msgid ""
861 "You have some obsolete package versions installed. Please upgrade the "
862@@ -396,90 +185,90 @@
863 "%s"
864 msgstr ""
865
866-#: ../apport/ui.py:270
867+#: ../apport/ui.py:281
868 msgid "unknown program"
869 msgstr ""
870
871-#: ../apport/ui.py:271
872+#: ../apport/ui.py:282
873 #, python-format
874 msgid "Sorry, the program \"%s\" closed unexpectedly"
875 msgstr ""
876
877-#: ../apport/ui.py:273 ../apport/ui.py:1301
878+#: ../apport/ui.py:284 ../apport/ui.py:1312
879 #, python-format
880 msgid "Problem in %s"
881 msgstr ""
882
883-#: ../apport/ui.py:274
884+#: ../apport/ui.py:285
885 msgid ""
886 "Your computer does not have enough free memory to automatically analyze the "
887 "problem and send a report to the developers."
888 msgstr ""
889
890-#: ../apport/ui.py:317 ../apport/ui.py:325 ../apport/ui.py:452
891-#: ../apport/ui.py:455 ../apport/ui.py:656 ../apport/ui.py:1107
892-#: ../apport/ui.py:1273 ../apport/ui.py:1277
893+#: ../apport/ui.py:328 ../apport/ui.py:336 ../apport/ui.py:463
894+#: ../apport/ui.py:466 ../apport/ui.py:667 ../apport/ui.py:1118
895+#: ../apport/ui.py:1284 ../apport/ui.py:1288
896 msgid "Invalid problem report"
897 msgstr ""
898
899-#: ../apport/ui.py:318
900+#: ../apport/ui.py:329
901 msgid "You are not allowed to access this problem report."
902 msgstr ""
903
904-#: ../apport/ui.py:321
905+#: ../apport/ui.py:332
906 msgid "Error"
907 msgstr ""
908
909-#: ../apport/ui.py:322
910+#: ../apport/ui.py:333
911 msgid "There is not enough disk space available to process this report."
912 msgstr ""
913
914-#: ../apport/ui.py:406
915+#: ../apport/ui.py:417
916 msgid "No package specified"
917 msgstr ""
918
919-#: ../apport/ui.py:407
920+#: ../apport/ui.py:418
921 msgid ""
922 "You need to specify a package or a PID. See --help for more information."
923 msgstr ""
924
925-#: ../apport/ui.py:430
926+#: ../apport/ui.py:441
927 msgid "Permission denied"
928 msgstr ""
929
930-#: ../apport/ui.py:431
931+#: ../apport/ui.py:442
932 msgid ""
933 "The specified process does not belong to you. Please run this program as the "
934 "process owner or as root."
935 msgstr ""
936
937-#: ../apport/ui.py:433
938+#: ../apport/ui.py:444
939 msgid "Invalid PID"
940 msgstr ""
941
942-#: ../apport/ui.py:434
943+#: ../apport/ui.py:445
944 msgid "The specified process ID does not belong to a program."
945 msgstr ""
946
947-#: ../apport/ui.py:453
948+#: ../apport/ui.py:464
949 #, python-format
950 msgid "Symptom script %s did not determine an affected package"
951 msgstr ""
952
953-#: ../apport/ui.py:456
954+#: ../apport/ui.py:467
955 #, python-format
956 msgid "Package %s does not exist"
957 msgstr ""
958
959-#: ../apport/ui.py:480 ../apport/ui.py:668 ../apport/ui.py:673
960+#: ../apport/ui.py:491 ../apport/ui.py:679 ../apport/ui.py:684
961 msgid "Cannot create report"
962 msgstr ""
963
964-#: ../apport/ui.py:495 ../apport/ui.py:541 ../apport/ui.py:558
965+#: ../apport/ui.py:506 ../apport/ui.py:552 ../apport/ui.py:569
966 msgid "Updating problem report"
967 msgstr ""
968
969-#: ../apport/ui.py:496
970+#: ../apport/ui.py:507
971 msgid ""
972 "You are not the reporter or subscriber of this problem report, or the report "
973 "is a duplicate or already closed.\n"
974@@ -487,7 +276,7 @@
975 "Please create a new report using \"apport-bug\"."
976 msgstr ""
977
978-#: ../apport/ui.py:505
979+#: ../apport/ui.py:516
980 msgid ""
981 "You are not the reporter of this problem report. It is much easier to mark a "
982 "bug as a duplicate of another than to move your comments and attachments to "
983@@ -499,185 +288,185 @@
984 "Do you really want to proceed?"
985 msgstr ""
986
987-#: ../apport/ui.py:542 ../apport/ui.py:559
988+#: ../apport/ui.py:553 ../apport/ui.py:570
989 msgid "No additional information collected."
990 msgstr ""
991
992-#: ../apport/ui.py:610
993+#: ../apport/ui.py:621
994 msgid "What kind of problem do you want to report?"
995 msgstr ""
996
997-#: ../apport/ui.py:627
998+#: ../apport/ui.py:638
999 msgid "Unknown symptom"
1000 msgstr ""
1001
1002-#: ../apport/ui.py:628
1003+#: ../apport/ui.py:639
1004 #, python-format
1005 msgid "The symptom \"%s\" is not known."
1006 msgstr ""
1007
1008-#: ../apport/ui.py:659
1009+#: ../apport/ui.py:670
1010 msgid ""
1011 "After closing this message please click on an application window to report a "
1012 "problem about it."
1013 msgstr ""
1014
1015-#: ../apport/ui.py:669 ../apport/ui.py:674
1016+#: ../apport/ui.py:680 ../apport/ui.py:685
1017 msgid "xprop failed to determine process ID of the window"
1018 msgstr ""
1019
1020-#: ../apport/ui.py:688
1021+#: ../apport/ui.py:699
1022 msgid "%prog <report number>"
1023 msgstr ""
1024
1025-#: ../apport/ui.py:690
1026+#: ../apport/ui.py:701
1027 msgid "Specify package name."
1028 msgstr ""
1029
1030-#: ../apport/ui.py:692 ../apport/ui.py:743
1031+#: ../apport/ui.py:703 ../apport/ui.py:754
1032 msgid "Add an extra tag to the report. Can be specified multiple times."
1033 msgstr ""
1034
1035-#: ../apport/ui.py:722
1036+#: ../apport/ui.py:733
1037 msgid "%prog [options] [symptom|pid|package|program path|.apport/.crash file]"
1038 msgstr ""
1039
1040-#: ../apport/ui.py:725
1041+#: ../apport/ui.py:736
1042 msgid ""
1043 "Start in bug filing mode. Requires --package and an optional --pid, or just "
1044 "a --pid. If neither is given, display a list of known symptoms. (Implied if "
1045 "a single argument is given.)"
1046 msgstr ""
1047
1048-#: ../apport/ui.py:727
1049+#: ../apport/ui.py:738
1050 msgid "Click a window as a target for filing a problem report."
1051 msgstr ""
1052
1053-#: ../apport/ui.py:729
1054+#: ../apport/ui.py:740
1055 msgid "Start in bug updating mode. Can take an optional --package."
1056 msgstr ""
1057
1058-#: ../apport/ui.py:731
1059+#: ../apport/ui.py:742
1060 msgid ""
1061 "File a bug report about a symptom. (Implied if symptom name is given as only "
1062 "argument.)"
1063 msgstr ""
1064
1065-#: ../apport/ui.py:733
1066+#: ../apport/ui.py:744
1067 msgid ""
1068 "Specify package name in --file-bug mode. This is optional if a --pid is "
1069 "specified. (Implied if package name is given as only argument.)"
1070 msgstr ""
1071
1072-#: ../apport/ui.py:735
1073+#: ../apport/ui.py:746
1074 msgid ""
1075 "Specify a running program in --file-bug mode. If this is specified, the bug "
1076 "report will contain more information. (Implied if pid is given as only "
1077 "argument.)"
1078 msgstr ""
1079
1080-#: ../apport/ui.py:737
1081+#: ../apport/ui.py:748
1082 msgid "The provided pid is a hanging application."
1083 msgstr ""
1084
1085-#: ../apport/ui.py:739
1086+#: ../apport/ui.py:750
1087 #, python-format
1088 msgid ""
1089 "Report the crash from given .apport or .crash file instead of the pending "
1090 "ones in %s. (Implied if file is given as only argument.)"
1091 msgstr ""
1092
1093-#: ../apport/ui.py:741
1094+#: ../apport/ui.py:752
1095 msgid ""
1096 "In bug filing mode, save the collected information into a file instead of "
1097 "reporting it. This file can then be reported later on from a different "
1098 "machine."
1099 msgstr ""
1100
1101-#: ../apport/ui.py:745
1102+#: ../apport/ui.py:756
1103 msgid "Print the Apport version number."
1104 msgstr ""
1105
1106-#: ../apport/ui.py:884
1107+#: ../apport/ui.py:895
1108 msgid ""
1109 "This will launch apport-retrace in a terminal window to examine the crash."
1110 msgstr ""
1111
1112-#: ../apport/ui.py:885
1113+#: ../apport/ui.py:896
1114 msgid "Run gdb session"
1115 msgstr ""
1116
1117-#: ../apport/ui.py:886
1118+#: ../apport/ui.py:897
1119 msgid "Run gdb session without downloading debug symbols"
1120 msgstr ""
1121
1122 #. TRANSLATORS: %s contains the crash report file name
1123-#: ../apport/ui.py:888
1124+#: ../apport/ui.py:899
1125 #, python-format
1126 msgid "Update %s with fully symbolic stack trace"
1127 msgstr ""
1128
1129-#: ../apport/ui.py:962 ../apport/ui.py:972
1130+#: ../apport/ui.py:973 ../apport/ui.py:983
1131 msgid ""
1132 "This problem report applies to a program which is not installed any more."
1133 msgstr ""
1134
1135-#: ../apport/ui.py:986
1136+#: ../apport/ui.py:997
1137 #, python-format
1138 msgid ""
1139 "The problem happened with the program %s which changed since the crash "
1140 "occurred."
1141 msgstr ""
1142
1143-#: ../apport/ui.py:1033 ../apport/ui.py:1064 ../apport/ui.py:1279
1144+#: ../apport/ui.py:1044 ../apport/ui.py:1075 ../apport/ui.py:1290
1145 msgid "This problem report is damaged and cannot be processed."
1146 msgstr ""
1147
1148 #. package does not exist
1149-#: ../apport/ui.py:1036
1150+#: ../apport/ui.py:1047
1151 msgid "The report belongs to a package that is not installed."
1152 msgstr ""
1153
1154-#: ../apport/ui.py:1039
1155+#: ../apport/ui.py:1050
1156 msgid "An error occurred while attempting to process this problem report:"
1157 msgstr ""
1158
1159-#: ../apport/ui.py:1108
1160+#: ../apport/ui.py:1119
1161 msgid "Could not determine the package or source package name."
1162 msgstr ""
1163
1164-#: ../apport/ui.py:1126
1165+#: ../apport/ui.py:1137
1166 msgid "Unable to start web browser"
1167 msgstr ""
1168
1169-#: ../apport/ui.py:1127
1170+#: ../apport/ui.py:1138
1171 #, python-format
1172 msgid "Unable to start web browser to open %s."
1173 msgstr ""
1174
1175-#: ../apport/ui.py:1227
1176+#: ../apport/ui.py:1238
1177 #, python-format
1178 msgid "Please enter your account information for the %s bug tracking system"
1179 msgstr ""
1180
1181-#: ../apport/ui.py:1239
1182+#: ../apport/ui.py:1250
1183 msgid "Network problem"
1184 msgstr ""
1185
1186-#: ../apport/ui.py:1241
1187+#: ../apport/ui.py:1252
1188 msgid ""
1189 "Cannot connect to crash database, please check your Internet connection."
1190 msgstr ""
1191
1192-#: ../apport/ui.py:1268
1193+#: ../apport/ui.py:1279
1194 msgid "Memory exhaustion"
1195 msgstr ""
1196
1197-#: ../apport/ui.py:1269
1198+#: ../apport/ui.py:1280
1199 msgid "Your system does not have enough memory to process this crash report."
1200 msgstr ""
1201
1202-#: ../apport/ui.py:1304
1203+#: ../apport/ui.py:1315
1204 #, python-format
1205 msgid ""
1206 "The problem cannot be reported:\n"
1207@@ -685,21 +474,201 @@
1208 "%s"
1209 msgstr ""
1210
1211-#: ../apport/ui.py:1360 ../apport/ui.py:1367
1212+#: ../apport/ui.py:1371 ../apport/ui.py:1378
1213 msgid "Problem already known"
1214 msgstr ""
1215
1216-#: ../apport/ui.py:1361
1217+#: ../apport/ui.py:1372
1218 msgid ""
1219 "This problem was already reported in the bug report displayed in the web "
1220 "browser. Please check if you can add any further information that might be "
1221 "helpful for the developers."
1222 msgstr ""
1223
1224-#: ../apport/ui.py:1368
1225+#: ../apport/ui.py:1379
1226 msgid "This problem was already reported to developers. Thank you!"
1227 msgstr ""
1228
1229+#: ../kde/apport-kde.desktop.in.h:1 ../kde/apport-kde-mime.desktop.in.h:1
1230+#: ../gtk/apport-gtk.desktop.in.h:1
1231+msgid "Report a problem..."
1232+msgstr ""
1233+
1234+#: ../kde/apport-kde.desktop.in.h:2 ../kde/apport-kde-mime.desktop.in.h:2
1235+#: ../gtk/apport-gtk.desktop.in.h:2
1236+msgid "Report a malfunction to the developers"
1237+msgstr ""
1238+
1239+#: ../bin/apport-retrace.py:34
1240+msgid "Do not put the new traces into the report, but write them to stdout."
1241+msgstr ""
1242+
1243+#: ../bin/apport-retrace.py:36
1244+msgid ""
1245+"Start an interactive gdb session with the report's core dump (-o ignored; "
1246+"does not rewrite report)"
1247+msgstr ""
1248+
1249+#: ../bin/apport-retrace.py:38
1250+msgid ""
1251+"Write modified report to given file instead of changing the original report"
1252+msgstr ""
1253+
1254+#: ../bin/apport-retrace.py:41
1255+msgid "Remove the core dump from the report after stack trace regeneration"
1256+msgstr ""
1257+
1258+#: ../bin/apport-retrace.py:43
1259+msgid "Override report's CoreFile"
1260+msgstr ""
1261+
1262+#: ../bin/apport-retrace.py:45
1263+msgid "Override report's ExecutablePath"
1264+msgstr ""
1265+
1266+#: ../bin/apport-retrace.py:47
1267+msgid "Override report's ProcMaps"
1268+msgstr ""
1269+
1270+#: ../bin/apport-retrace.py:49
1271+msgid "Rebuild report's Package information"
1272+msgstr ""
1273+
1274+#: ../bin/apport-retrace.py:51
1275+msgid ""
1276+"Build a temporary sandbox and download/install the necessary packages and "
1277+"debug symbols in there; without this option it assumes that the necessary "
1278+"packages and debug symbols are already installed in the system. The argument "
1279+"points to the packaging system configuration base directory; if you specify "
1280+"\"system\", it will use the system configuration files, but will then only "
1281+"be able to retrace crashes that happened on the currently running release."
1282+msgstr ""
1283+
1284+#: ../bin/apport-retrace.py:53
1285+msgid "Report download/install progress when installing packages into sandbox"
1286+msgstr ""
1287+
1288+#: ../bin/apport-retrace.py:55
1289+msgid "Prepend timestamps to log messages, for batch operation"
1290+msgstr ""
1291+
1292+#: ../bin/apport-retrace.py:57
1293+msgid ""
1294+"Create and use third-party repositories from origins specified in reports"
1295+msgstr ""
1296+
1297+#: ../bin/apport-retrace.py:59
1298+msgid "Cache directory for packages downloaded in the sandbox"
1299+msgstr ""
1300+
1301+#: ../bin/apport-retrace.py:61
1302+msgid ""
1303+"Directory for unpacked packages. Future runs will assume that any already "
1304+"downloaded package is also extracted to this sandbox."
1305+msgstr ""
1306+
1307+#: ../bin/apport-retrace.py:63 ../bin/apport-valgrind.py:66
1308+msgid ""
1309+"Install an extra package into the sandbox (can be specified multiple times)"
1310+msgstr ""
1311+
1312+#: ../bin/apport-retrace.py:65
1313+msgid ""
1314+"Path to a file with the crash database authentication information. This is "
1315+"used when specifying a crash ID to upload the retraced stack traces (only if "
1316+"neither -g, -o, nor -s are specified)"
1317+msgstr ""
1318+
1319+#: ../bin/apport-retrace.py:67
1320+msgid ""
1321+"Display retraced stack traces and ask for confirmation before sending them "
1322+"to the crash database."
1323+msgstr ""
1324+
1325+#: ../bin/apport-retrace.py:69
1326+msgid "Path to the duplicate sqlite database (default: no duplicate checking)"
1327+msgstr ""
1328+
1329+#: ../bin/apport-retrace.py:78
1330+msgid "You cannot use -C without -S. Stopping."
1331+msgstr ""
1332+
1333+#. translators: don't translate y/n, apport currently only checks for "y"
1334+#: ../bin/apport-retrace.py:111
1335+msgid "OK to send these as attachments? [y/n]"
1336+msgstr ""
1337+
1338+#: ../data/kernel_oops.py:29
1339+msgid "Your system might become unstable now and might need to be restarted."
1340+msgstr ""
1341+
1342+#: ../kde/apport-kde.py:315
1343+msgid "Username:"
1344+msgstr ""
1345+
1346+#: ../kde/apport-kde.py:316
1347+msgid "Password:"
1348+msgstr ""
1349+
1350+#: ../kde/apport-kde.py:406
1351+msgid "Collecting Problem Information"
1352+msgstr ""
1353+
1354+#: ../kde/apport-kde.py:407 ../bin/apport-cli.py:238
1355+msgid "Collecting problem information"
1356+msgstr ""
1357+
1358+#: ../kde/apport-kde.py:408
1359+msgid ""
1360+"The collected information can be sent to the developers to improve the "
1361+"application. This might take a few minutes."
1362+msgstr ""
1363+
1364+#: ../kde/apport-kde.py:434
1365+msgid "Uploading Problem Information"
1366+msgstr ""
1367+
1368+#: ../bin/apport-valgrind.py:37
1369+msgid "See man page for details."
1370+msgstr ""
1371+
1372+#: ../bin/apport-valgrind.py:43
1373+msgid "specify the log file name produced by valgrind"
1374+msgstr ""
1375+
1376+#: ../bin/apport-valgrind.py:46
1377+msgid ""
1378+"reuse a previously created sandbox dir (SDIR) or, if it does not exist, "
1379+"create it"
1380+msgstr ""
1381+
1382+#: ../bin/apport-valgrind.py:50
1383+msgid ""
1384+"do not create or reuse a sandbox directory for additional debug symbols "
1385+"but rely only on installed debug symbols."
1386+msgstr ""
1387+
1388+#: ../bin/apport-valgrind.py:54
1389+msgid ""
1390+"reuse a previously created cache dir (CDIR) or, if it does not exist, create "
1391+"it"
1392+msgstr ""
1393+
1394+#: ../bin/apport-valgrind.py:58
1395+msgid "report download/install progress when installing packages into sandbox"
1396+msgstr ""
1397+
1398+#: ../bin/apport-valgrind.py:62
1399+msgid ""
1400+"the executable that is run under valgrind's memcheck tool for memory leak "
1401+"detection"
1402+msgstr ""
1403+
1404+#: ../bin/apport-valgrind.py:97
1405+#, python-format
1406+msgid "Error: %s is not an executable. Stopping."
1407+msgstr ""
1408+
1409 #: ../data/apportcheckresume.py:67
1410 msgid ""
1411 "This occurred during a previous suspend, and prevented the system from "
1412@@ -718,6 +687,33 @@
1413 "completed normally."
1414 msgstr ""
1415
1416+#: ../apport/com.ubuntu.apport.policy.in.h:1
1417+msgid "Collect system information"
1418+msgstr ""
1419+
1420+#: ../apport/com.ubuntu.apport.policy.in.h:2
1421+msgid ""
1422+"Authentication is required to collect system information for this problem "
1423+"report"
1424+msgstr ""
1425+
1426+#: ../apport/com.ubuntu.apport.policy.in.h:3
1427+msgid "System problem reports"
1428+msgstr ""
1429+
1430+#: ../apport/com.ubuntu.apport.policy.in.h:4
1431+msgid "Please enter your password to access problem reports of system programs"
1432+msgstr ""
1433+
1434+#: ../bin/apport-unpack.py:22
1435+#, python-format
1436+msgid "Usage: %s <report> <target directory>"
1437+msgstr ""
1438+
1439+#: ../bin/apport-unpack.py:47
1440+msgid "Destination directory exists and is not empty."
1441+msgstr ""
1442+
1443 #: ../bin/apport-cli.py:74
1444 msgid "Press any key to continue..."
1445 msgstr ""
1446@@ -836,6 +832,10 @@
1447 msgid "Launch a browser now"
1448 msgstr ""
1449
1450-#: ../bin/apport-cli.py:371
1451+#: ../bin/apport-cli.py:372
1452 msgid "No pending crash reports. Try --help for more information."
1453 msgstr ""
1454+
1455+#: ../kde/apport-kde-mimelnk.desktop.in.h:1
1456+msgid "Apport crash file"
1457+msgstr ""
1458
1459=== modified file 'test/test_backend_apt_dpkg.py'
1460--- test/test_backend_apt_dpkg.py 2016-12-10 11:28:27 +0000
1461+++ test/test_backend_apt_dpkg.py 2017-01-31 23:14:32 +0000
1462@@ -644,6 +644,23 @@
1463 self.assertEqual(len(pkglist), 3, str(pkglist))
1464
1465 @unittest.skipUnless(_has_internet(), 'online test')
1466+ def test_install_packages_dependencies(self):
1467+ '''install packages's dependencies'''
1468+
1469+ self._setup_foonux_config(release='xenial')
1470+ # coreutils should always depend on libc6
1471+ impl.install_packages(self.rootdir, self.configdir,
1472+ 'Foonux 1.2',
1473+ [('coreutils', None)],
1474+ False, None, install_deps=True)
1475+
1476+ # check packages.txt for a dependency
1477+ with open(os.path.join(self.rootdir, 'packages.txt')) as f:
1478+ pkglist = f.read().splitlines()
1479+ self.assertIn('coreutils 8.25-2ubuntu2', pkglist)
1480+ self.assertIn('libc6 2.23-0ubuntu3', pkglist)
1481+
1482+ @unittest.skipUnless(_has_internet(), 'online test')
1483 def test_install_packages_system(self):
1484 '''install_packages() with system configuration'''
1485
1486
1487=== modified file 'test/test_report.py'
1488--- test/test_report.py 2016-12-10 11:28:27 +0000
1489+++ test/test_report.py 2017-01-31 23:14:32 +0000
1490@@ -2246,6 +2246,20 @@
1491 del r['Date']
1492 self.assertEqual(r.get_timestamp(), None)
1493
1494+ def test_command_output_passes_env(self):
1495+ fake_env = {'GCONV_PATH': '/tmp'}
1496+ out = apport.report._command_output(['env'], env=fake_env)
1497+ self.assertTrue(b'GCONV_PATH' in out)
1498+
1499+ def test_extrapath_preferred(self):
1500+ '''if extrapath is passed it is preferred'''
1501+ bin_true = apport.report._which_extrapath('true', None)
1502+ # need something to be preferred
1503+ os.symlink('/bin/true', '/tmp/true')
1504+ tmp_true = apport.report._which_extrapath('true', '/tmp')
1505+ os.unlink('/tmp/true')
1506+ self.assertEqual(tmp_true, '/tmp/true')
1507+ self.assertEqual(bin_true, '/bin/true')
1508
1509 if __name__ == '__main__':
1510 unittest.main()

Subscribers

People subscribed via source and target branches