/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz

« back to all changes in this revision

Viewing changes to __init__.py

  • Committer: Jelmer Vernooij
  • Date: 2008-06-29 19:34:29 UTC
  • mto: This revision was merged to the branch mainline in revision 520.
  • Revision ID: jelmer@samba.org-20080629193429-ir2ilmbko6qkubg5
Add Branch/Index option if bzr-search is available.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
# along with this program; if not, write to the Free Software
13
13
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
14
14
 
15
 
"""GTK+ frontends to Bazaar commands """
 
15
"""Graphical support for Bazaar using GTK.
 
16
 
 
17
This plugin includes:
 
18
commit-notify     Start the graphical notifier of commits.
 
19
gannotate         GTK+ annotate. 
 
20
gbranch           GTK+ branching. 
 
21
gcheckout         GTK+ checkout. 
 
22
gcommit           GTK+ commit dialog.
 
23
gconflicts        GTK+ conflicts. 
 
24
gdiff             Show differences in working tree in a GTK+ Window. 
 
25
ginit             Initialise a new branch.
 
26
gmissing          GTK+ missing revisions dialog. 
 
27
gpreferences      GTK+ preferences dialog. 
 
28
gpush             GTK+ push.
 
29
gsend             GTK+ send merge directive.
 
30
gstatus           GTK+ status dialog.
 
31
gtags             Manage branch tags.
 
32
visualise         Graphically visualise this branch. 
 
33
"""
 
34
 
 
35
import sys
16
36
 
17
37
import bzrlib
18
38
 
19
 
__version__ = '0.16.0'
20
 
version_info = tuple(int(n) for n in __version__.split('.'))
21
 
 
 
39
version_info = (0, 95, 0, 'dev', 1)
 
40
 
 
41
if version_info[3] == 'final':
 
42
    version_string = '%d.%d.%d' % version_info[:3]
 
43
else:
 
44
    version_string = '%d.%d.%d%s%d' % version_info
 
45
__version__ = version_string
 
46
 
 
47
required_bzrlib = (1, 3)
22
48
 
23
49
def check_bzrlib_version(desired):
24
50
    """Check that bzrlib is compatible.
25
51
 
26
52
    If version is < bzr-gtk version, assume incompatible.
27
 
    If version == bzr-gtk version, assume completely compatible
28
 
    If version == bzr-gtk version + 1, assume compatible, with deprecations
29
 
    Otherwise, assume incompatible.
30
53
    """
31
 
    desired_plus = (desired[0], desired[1]+1)
32
54
    bzrlib_version = bzrlib.version_info[:2]
33
 
    if bzrlib_version == desired:
34
 
        return
35
55
    try:
36
56
        from bzrlib.trace import warning
37
57
    except ImportError:
38
58
        # get the message out any way we can
39
59
        from warnings import warn as warning
40
60
    if bzrlib_version < desired:
41
 
        warning('Installed bzr version %s is too old to be used with bzr-gtk'
 
61
        from bzrlib.errors import BzrError
 
62
        warning('Installed Bazaar version %s is too old to be used with bzr-gtk'
42
63
                ' %s.' % (bzrlib.__version__, __version__))
43
 
        # Not using BzrNewError, because it may not exist.
44
 
        raise Exception, ('Version mismatch', version_info)
45
 
    else:
46
 
        warning('bzr-gtk is not up to date with installed bzr version %s.'
47
 
                ' \nThere should be a newer version available, e.g. %i.%i.' 
48
 
                % (bzrlib.__version__, bzrlib_version[0], bzrlib_version[1]))
49
 
        if bzrlib_version != desired_plus:
50
 
            raise Exception, 'Version mismatch'
51
 
 
52
 
 
53
 
check_bzrlib_version(version_info[:2])
 
64
        raise BzrError('Version mismatch: %r, %r' % (version_info, bzrlib.version_info) )
 
65
 
 
66
 
 
67
if version_info[2] == "final":
 
68
    check_bzrlib_version(required_bzrlib)
54
69
 
55
70
from bzrlib.trace import warning
56
71
if __name__ != 'bzrlib.plugins.gtk':
60
75
lazy_import(globals(), """
61
76
from bzrlib import (
62
77
    branch,
 
78
    builtins,
63
79
    errors,
 
80
    merge_directive,
64
81
    workingtree,
65
82
    )
66
83
""")
67
84
 
68
85
from bzrlib.commands import Command, register_command, display_command
69
86
from bzrlib.errors import NotVersionedError, BzrCommandError, NoSuchFile
70
 
from bzrlib.commands import Command, register_command
71
87
from bzrlib.option import Option
72
 
from bzrlib.bzrdir import BzrDir
73
88
 
74
89
import os.path
75
90
 
83
98
 
84
99
 
85
100
def set_ui_factory():
86
 
    pygtk = import_pygtk()
 
101
    import_pygtk()
87
102
    from ui import GtkUIFactory
88
103
    import bzrlib.ui
89
104
    bzrlib.ui.ui_factory = GtkUIFactory()
90
105
 
91
106
 
 
107
def data_path():
 
108
    return os.path.dirname(__file__)
 
109
 
 
110
 
 
111
def icon_path(*args):
 
112
    basedirs = [os.path.join(data_path()),
 
113
             "/usr/share/bzr-gtk", 
 
114
             "/usr/local/share/bzr-gtk"]
 
115
    for basedir in basedirs:
 
116
        path = os.path.join(basedir, 'icons', *args)
 
117
        if os.path.exists(path):
 
118
            return path
 
119
    return None
 
120
 
 
121
 
 
122
def open_display():
 
123
    pygtk = import_pygtk()
 
124
    try:
 
125
        import gtk
 
126
    except RuntimeError, e:
 
127
        if str(e) == "could not open display":
 
128
            raise NoDisplayError
 
129
    set_ui_factory()
 
130
    return gtk
 
131
 
 
132
 
92
133
class GTKCommand(Command):
93
134
    """Abstract class providing GTK specific run commands."""
94
135
 
95
 
    def open_display(self):
96
 
        pygtk = import_pygtk()
97
 
        try:
98
 
            import gtk
99
 
        except RuntimeError, e:
100
 
            if str(e) == "could not open display":
101
 
                raise NoDisplayError
102
 
        set_ui_factory()
103
 
        return gtk
104
 
 
105
136
    def run(self):
106
 
        self.open_display()
 
137
        open_display()
107
138
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
108
139
        dialog.run()
109
140
 
118
149
        return BranchDialog(path)
119
150
 
120
151
 
121
 
register_command(cmd_gbranch)
122
 
 
123
152
class cmd_gcheckout(GTKCommand):
124
153
    """ GTK+ checkout.
125
154
    
129
158
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
130
159
        return CheckoutDialog(path)
131
160
 
132
 
register_command(cmd_gcheckout)
133
161
 
134
162
 
135
163
class cmd_gpush(GTKCommand):
140
168
 
141
169
    def run(self, location="."):
142
170
        (br, path) = branch.Branch.open_containing(location)
143
 
        self.open_display()
 
171
        open_display()
144
172
        from push import PushDialog
145
 
        dialog = PushDialog(br)
 
173
        dialog = PushDialog(br.repository, br.last_revision(), br)
146
174
        dialog.run()
147
175
 
148
 
register_command(cmd_gpush)
149
176
 
150
177
 
151
178
class cmd_gdiff(GTKCommand):
166
193
            if revision is not None:
167
194
                if len(revision) == 1:
168
195
                    tree1 = wt
169
 
                    revision_id = revision[0].in_history(branch).rev_id
 
196
                    revision_id = revision[0].as_revision_id(tree1.branch)
170
197
                    tree2 = branch.repository.revision_tree(revision_id)
171
198
                elif len(revision) == 2:
172
 
                    revision_id_0 = revision[0].in_history(branch).rev_id
 
199
                    revision_id_0 = revision[0].as_revision_id(branch)
173
200
                    tree2 = branch.repository.revision_tree(revision_id_0)
174
 
                    revision_id_1 = revision[1].in_history(branch).rev_id
 
201
                    revision_id_1 = revision[1].as_revision_id(branch)
175
202
                    tree1 = branch.repository.revision_tree(revision_id_1)
176
203
            else:
177
204
                tree1 = wt
187
214
                try:
188
215
                    window.set_file(tree_filename)
189
216
                except NoSuchFile:
190
 
                    if (tree1.inventory.path2id(tree_filename) is None and 
191
 
                        tree2.inventory.path2id(tree_filename) is None):
 
217
                    if (tree1.path2id(tree_filename) is None and 
 
218
                        tree2.path2id(tree_filename) is None):
192
219
                        raise NotVersionedError(filename)
193
220
                    raise BzrCommandError('No changes found for file "%s"' % 
194
221
                                          filename)
198
225
        finally:
199
226
            wt.unlock()
200
227
 
201
 
register_command(cmd_gdiff)
 
228
 
 
229
def start_viz_window(branch, revisions, limit=None):
 
230
    """Start viz on branch with revision revision.
 
231
    
 
232
    :return: The viz window object.
 
233
    """
 
234
    from viz import BranchWindow
 
235
    return BranchWindow(branch, revisions, limit)
 
236
 
202
237
 
203
238
class cmd_visualise(Command):
204
239
    """Graphically visualise this branch.
211
246
    """
212
247
    takes_options = [
213
248
        "revision",
214
 
        Option('limit', "maximum number of revisions to display",
 
249
        Option('limit', "Maximum number of revisions to display.",
215
250
               int, 'count')]
216
 
    takes_args = [ "location?" ]
 
251
    takes_args = [ "locations*" ]
217
252
    aliases = [ "visualize", "vis", "viz" ]
218
253
 
219
 
    def run(self, location=".", revision=None, limit=None):
 
254
    def run(self, locations_list, revision=None, limit=None):
220
255
        set_ui_factory()
221
 
        (br, path) = branch.Branch.open_containing(location)
222
 
        br.lock_read()
223
 
        br.repository.lock_read()
224
 
        try:
 
256
        if locations_list is None:
 
257
            locations_list = ["."]
 
258
        revids = []
 
259
        for location in locations_list:
 
260
            (br, path) = branch.Branch.open_containing(location)
225
261
            if revision is None:
226
 
                revid = br.last_revision()
227
 
                if revid is None:
228
 
                    return
 
262
                revids.append(br.last_revision())
229
263
            else:
230
 
                (revno, revid) = revision[0].in_history(br)
231
 
 
232
 
            from viz.branchwin import BranchWindow
233
 
            import gtk
234
 
                
235
 
            pp = BranchWindow()
236
 
            pp.set_branch(br, revid, limit)
237
 
            pp.connect("destroy", lambda w: gtk.main_quit())
238
 
            pp.show()
239
 
            gtk.main()
240
 
        finally:
241
 
            br.repository.unlock()
242
 
            br.unlock()
243
 
 
244
 
 
245
 
register_command(cmd_visualise)
 
264
                revids.append(revision[0].as_revision_id(br))
 
265
        import gtk
 
266
        pp = start_viz_window(br, revids, limit)
 
267
        pp.connect("destroy", lambda w: gtk.main_quit())
 
268
        pp.show()
 
269
        gtk.main()
246
270
 
247
271
 
248
272
class cmd_gannotate(GTKCommand):
253
277
 
254
278
    takes_args = ["filename", "line?"]
255
279
    takes_options = [
256
 
        Option("all", help="show annotations on all lines"),
257
 
        Option("plain", help="don't highlight annotation lines"),
 
280
        Option("all", help="Show annotations on all lines."),
 
281
        Option("plain", help="Don't highlight annotation lines."),
258
282
        Option("line", type=int, argname="lineno",
259
 
               help="jump to specified line number"),
 
283
               help="Jump to specified line number."),
260
284
        "revision",
261
285
    ]
262
286
    aliases = ["gblame", "gpraise"]
263
287
    
264
288
    def run(self, filename, all=False, plain=False, line='1', revision=None):
265
 
        self.open_display()
 
289
        gtk = open_display()
266
290
 
267
291
        try:
268
292
            line = int(line)
272
296
 
273
297
        from annotate.gannotate import GAnnotateWindow
274
298
        from annotate.config import GAnnotateConfig
 
299
        from bzrlib.bzrdir import BzrDir
275
300
 
276
301
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
277
302
        if wt is not None:
286
311
        if revision is not None:
287
312
            if len(revision) != 1:
288
313
                raise BzrCommandError("Only 1 revion may be specified.")
289
 
            revision_id = revision[0].in_history(br).rev_id
 
314
            revision_id = revision[0].as_revision_id(br)
290
315
            tree = br.repository.revision_tree(revision_id)
291
316
        else:
292
317
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
293
318
 
294
 
        window = GAnnotateWindow(all, plain)
 
319
        window = GAnnotateWindow(all, plain, branch=br)
295
320
        window.connect("destroy", lambda w: gtk.main_quit())
296
 
        window.set_title(path + " - gannotate")
297
321
        config = GAnnotateConfig(window)
298
322
        window.show()
299
323
        br.lock_read()
308
332
            if wt is not None:
309
333
                wt.unlock()
310
334
 
311
 
register_command(cmd_gannotate)
312
335
 
313
336
 
314
337
class cmd_gcommit(GTKCommand):
315
338
    """GTK+ commit dialog
316
339
 
317
340
    Graphical user interface for committing revisions"""
318
 
    
 
341
 
319
342
    aliases = [ "gci" ]
320
343
    takes_args = []
321
344
    takes_options = []
322
345
 
323
346
    def run(self, filename=None):
324
347
        import os
325
 
        self.open_display()
 
348
        open_display()
326
349
        from commit import CommitDialog
327
 
        from bzrlib.commit import Commit
328
350
        from bzrlib.errors import (BzrCommandError,
329
351
                                   NotBranchError,
330
 
                                   NoWorkingTree,
331
 
                                   PointlessCommit,
332
 
                                   ConflictsInTree,
333
 
                                   StrictCommitFailed)
 
352
                                   NoWorkingTree)
334
353
 
335
354
        wt = None
336
355
        br = None
337
356
        try:
338
357
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
339
358
            br = wt.branch
340
 
        except NotBranchError, e:
341
 
            path = e.path
342
359
        except NoWorkingTree, e:
343
 
            path = e.base
344
 
            try:
345
 
                (br, path) = branch.Branch.open_containing(path)
346
 
            except NotBranchError, e:
347
 
                path = e.path
348
 
 
349
 
 
350
 
        commit = CommitDialog(wt, path, not br)
351
 
        commit.run()
352
 
 
353
 
register_command(cmd_gcommit)
 
360
            from dialog import error_dialog
 
361
            error_dialog(_i18n('Directory does not have a working tree'),
 
362
                         _i18n('Operation aborted.'))
 
363
            return 1 # should this be retval=3?
 
364
 
 
365
        # It is a good habit to keep things locked for the duration, but it
 
366
        # could cause difficulties if someone wants to do things in another
 
367
        # window... We could lock_read() until we actually go to commit
 
368
        # changes... Just a thought.
 
369
        wt.lock_write()
 
370
        try:
 
371
            dlg = CommitDialog(wt)
 
372
            return dlg.run()
 
373
        finally:
 
374
            wt.unlock()
354
375
 
355
376
 
356
377
class cmd_gstatus(GTKCommand):
361
382
    
362
383
    aliases = [ "gst" ]
363
384
    takes_args = ['PATH?']
364
 
    takes_options = []
 
385
    takes_options = ['revision']
365
386
 
366
 
    def run(self, path='.'):
 
387
    def run(self, path='.', revision=None):
367
388
        import os
368
 
        self.open_display()
 
389
        gtk = open_display()
369
390
        from status import StatusDialog
370
391
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
371
 
        status = StatusDialog(wt, wt_path)
 
392
        
 
393
        if revision is not None:
 
394
            try:
 
395
                revision_id = revision[0].as_revision_id(wt.branch)
 
396
            except:
 
397
                from bzrlib.errors import BzrError
 
398
                raise BzrError('Revision %r doesn\'t exist' % revision[0].user_spec )
 
399
        else:
 
400
            revision_id = None
 
401
 
 
402
        status = StatusDialog(wt, wt_path, revision_id)
372
403
        status.connect("destroy", gtk.main_quit)
373
404
        status.run()
374
405
 
375
 
register_command(cmd_gstatus)
 
406
 
 
407
class cmd_gsend(GTKCommand):
 
408
    """GTK+ send merge directive.
 
409
 
 
410
    """
 
411
    def run(self):
 
412
        (br, path) = branch.Branch.open_containing(".")
 
413
        gtk = open_display()
 
414
        from bzrlib.plugins.gtk.mergedirective import SendMergeDirectiveDialog
 
415
        from StringIO import StringIO
 
416
        dialog = SendMergeDirectiveDialog(br)
 
417
        if dialog.run() == gtk.RESPONSE_OK:
 
418
            outf = StringIO()
 
419
            outf.writelines(dialog.get_merge_directive().to_lines())
 
420
            mail_client = br.get_config().get_mail_client()
 
421
            mail_client.compose_merge_request(dialog.get_mail_to(), "[MERGE]", 
 
422
                outf.getvalue())
 
423
 
 
424
            
376
425
 
377
426
 
378
427
class cmd_gconflicts(GTKCommand):
379
 
    """ GTK+ push.
 
428
    """GTK+ conflicts.
380
429
    
 
430
    Select files from the list of conflicts and run an external utility to
 
431
    resolve them.
381
432
    """
382
433
    def run(self):
383
434
        (wt, path) = workingtree.WorkingTree.open_containing('.')
384
 
        self.open_display()
 
435
        open_display()
385
436
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
386
437
        dialog = ConflictsDialog(wt)
387
438
        dialog.run()
388
439
 
389
 
register_command(cmd_gconflicts)
390
 
 
391
440
 
392
441
class cmd_gpreferences(GTKCommand):
393
442
    """ GTK+ preferences dialog.
394
443
 
395
444
    """
396
445
    def run(self):
397
 
        self.open_display()
 
446
        open_display()
398
447
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
399
448
        dialog = PreferencesWindow()
400
449
        dialog.run()
401
450
 
402
 
register_command(cmd_gpreferences)
 
451
 
 
452
class cmd_gmissing(Command):
 
453
    """ GTK+ missing revisions dialog.
 
454
 
 
455
    """
 
456
    takes_args = ["other_branch?"]
 
457
    def run(self, other_branch=None):
 
458
        pygtk = import_pygtk()
 
459
        try:
 
460
            import gtk
 
461
        except RuntimeError, e:
 
462
            if str(e) == "could not open display":
 
463
                raise NoDisplayError
 
464
 
 
465
        from bzrlib.plugins.gtk.missing import MissingWindow
 
466
        from bzrlib.branch import Branch
 
467
 
 
468
        local_branch = Branch.open_containing(".")[0]
 
469
        if other_branch is None:
 
470
            other_branch = local_branch.get_parent()
 
471
            
 
472
            if other_branch is None:
 
473
                raise errors.BzrCommandError("No peer location known or specified.")
 
474
        remote_branch = Branch.open_containing(other_branch)[0]
 
475
        set_ui_factory()
 
476
        local_branch.lock_read()
 
477
        try:
 
478
            remote_branch.lock_read()
 
479
            try:
 
480
                dialog = MissingWindow(local_branch, remote_branch)
 
481
                dialog.run()
 
482
            finally:
 
483
                remote_branch.unlock()
 
484
        finally:
 
485
            local_branch.unlock()
 
486
 
 
487
 
 
488
class cmd_ginit(GTKCommand):
 
489
    def run(self):
 
490
        open_display()
 
491
        from initialize import InitDialog
 
492
        dialog = InitDialog(os.path.abspath(os.path.curdir))
 
493
        dialog.run()
 
494
 
 
495
 
 
496
class cmd_gtags(GTKCommand):
 
497
    def run(self):
 
498
        br = branch.Branch.open_containing('.')[0]
 
499
        
 
500
        gtk = open_display()
 
501
        from tags import TagsWindow
 
502
        window = TagsWindow(br)
 
503
        window.show()
 
504
        gtk.main()
 
505
 
 
506
 
 
507
commands = [
 
508
    cmd_gannotate, 
 
509
    cmd_gbranch,
 
510
    cmd_gcheckout, 
 
511
    cmd_gcommit, 
 
512
    cmd_gconflicts, 
 
513
    cmd_gdiff,
 
514
    cmd_ginit,
 
515
    cmd_gmissing, 
 
516
    cmd_gpreferences, 
 
517
    cmd_gpush, 
 
518
    cmd_gsend,
 
519
    cmd_gstatus,
 
520
    cmd_gtags,
 
521
    cmd_visualise
 
522
    ]
 
523
 
 
524
for cmd in commands:
 
525
    register_command(cmd)
403
526
 
404
527
 
405
528
class cmd_commit_notify(GTKCommand):
410
533
    """
411
534
 
412
535
    def run(self):
413
 
        gtk = self.open_display()
 
536
        from notify import NotifyPopupMenu
 
537
        gtk = open_display()
 
538
        menu = NotifyPopupMenu()
 
539
        icon = gtk.status_icon_new_from_file(icon_path("bzr-icon-64.png"))
 
540
        icon.connect('popup-menu', menu.display)
 
541
 
414
542
        import cgi
415
543
        import dbus
416
544
        import dbus.service
421
549
        from bzrlib.transport import get_transport
422
550
        if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
423
551
            import dbus.glib
424
 
        from bzrlib.plugins.dbus import activity
 
552
        BROADCAST_INTERFACE = "org.bazaarvcs.plugins.dbus.Broadcast"
425
553
        bus = dbus.SessionBus()
426
 
        # get the object so we can subscribe to callbacks from it.
427
 
        broadcast_service = bus.get_object(
428
 
            activity.Broadcast.DBUS_NAME,
429
 
            activity.Broadcast.DBUS_PATH)
430
 
        def catch_branch(revision_id, url):
 
554
 
 
555
        def catch_branch(revision_id, urls):
 
556
            # TODO: show all the urls, or perhaps choose the 'best'.
 
557
            url = urls[0]
431
558
            try:
432
559
                if isinstance(revision_id, unicode):
433
560
                    revision_id = revision_id.encode('utf8')
434
561
                transport = get_transport(url)
435
 
                try:
436
 
                    transport.local_abspath('.')
437
 
                except errors.TransportNotPossible:
438
 
                    # dont show remote urls for now.
439
 
                    return
440
 
                # here we should:
441
562
                a_dir = BzrDir.open_from_transport(transport)
442
563
                branch = a_dir.open_branch()
443
564
                revno = branch.revision_id_to_revno(revision_id)
449
570
                body += '\n'
450
571
                body += revision.message
451
572
                body = cgi.escape(body)
452
 
                #print repr(body)
453
573
                nw = pynotify.Notification(summary, body)
 
574
                def start_viz(notification=None, action=None, data=None):
 
575
                    """Start the viz program."""
 
576
                    pp = start_viz_window(branch, revision_id)
 
577
                    pp.show()
 
578
                def start_branch(notification=None, action=None, data=None):
 
579
                    """Start a Branch dialog"""
 
580
                    from bzrlib.plugins.gtk.branch import BranchDialog
 
581
                    bd = BranchDialog(remote_path=url)
 
582
                    bd.run()
 
583
                nw.add_action("inspect", "Inspect", start_viz, None)
 
584
                nw.add_action("branch", "Branch", start_branch, None)
454
585
                nw.set_timeout(5000)
455
586
                nw.show()
456
587
            except Exception, e:
457
588
                print e
458
589
                raise
459
 
        broadcast_service.connect_to_signal("Revision", catch_branch,
460
 
            dbus_interface=activity.Broadcast.DBUS_INTERFACE)
 
590
        bus.add_signal_receiver(catch_branch,
 
591
                                dbus_interface=BROADCAST_INTERFACE,
 
592
                                signal_name="Revision")
461
593
        pynotify.init("bzr commit-notify")
462
594
        gtk.main()
463
595
 
464
596
register_command(cmd_commit_notify)
465
597
 
466
598
 
 
599
class cmd_gselftest(GTKCommand):
 
600
    """Version of selftest that displays a notification at the end"""
 
601
 
 
602
    takes_args = builtins.cmd_selftest.takes_args
 
603
    takes_options = builtins.cmd_selftest.takes_options
 
604
    _see_also = ['selftest']
 
605
 
 
606
    def run(self, *args, **kwargs):
 
607
        import cgi
 
608
        import sys
 
609
        default_encoding = sys.getdefaultencoding()
 
610
        # prevent gtk from blowing up later
 
611
        gtk = import_pygtk()
 
612
        # prevent gtk from messing with default encoding
 
613
        import pynotify
 
614
        if sys.getdefaultencoding() != default_encoding:
 
615
            reload(sys)
 
616
            sys.setdefaultencoding(default_encoding)
 
617
        result = builtins.cmd_selftest().run(*args, **kwargs)
 
618
        if result == 0:
 
619
            summary = 'Success'
 
620
            body = 'Selftest succeeded in "%s"' % os.getcwd()
 
621
        if result == 1:
 
622
            summary = 'Failure'
 
623
            body = 'Selftest failed in "%s"' % os.getcwd()
 
624
        pynotify.init("bzr gselftest")
 
625
        note = pynotify.Notification(cgi.escape(summary), cgi.escape(body))
 
626
        note.set_timeout(pynotify.EXPIRES_NEVER)
 
627
        note.show()
 
628
 
 
629
 
 
630
register_command(cmd_gselftest)
 
631
 
 
632
 
 
633
class cmd_test_gtk(GTKCommand):
 
634
    """Version of selftest that just runs the gtk test suite."""
 
635
 
 
636
    takes_options = ['verbose',
 
637
                     Option('one', short_name='1',
 
638
                            help='Stop when one test fails.'),
 
639
                     Option('benchmark', help='Run the benchmarks.'),
 
640
                     Option('lsprof-timed',
 
641
                     help='Generate lsprof output for benchmarked'
 
642
                          ' sections of code.'),
 
643
                     Option('list-only',
 
644
                     help='List the tests instead of running them.'),
 
645
                     Option('randomize', type=str, argname="SEED",
 
646
                     help='Randomize the order of tests using the given'
 
647
                          ' seed or "now" for the current time.'),
 
648
                    ]
 
649
    takes_args = ['testspecs*']
 
650
 
 
651
    def run(self, verbose=None, one=False, benchmark=None,
 
652
            lsprof_timed=None, list_only=False, randomize=None,
 
653
            testspecs_list=None):
 
654
        from bzrlib import __path__ as bzrlib_path
 
655
        from bzrlib.tests import selftest
 
656
 
 
657
        print '%10s: %s' % ('bzrlib', bzrlib_path[0])
 
658
        if benchmark:
 
659
            print 'No benchmarks yet'
 
660
            return 3
 
661
 
 
662
            test_suite_factory = bench_suite
 
663
            if verbose is None:
 
664
                verbose = True
 
665
            # TODO: should possibly lock the history file...
 
666
            benchfile = open(".perf_history", "at", buffering=1)
 
667
        else:
 
668
            test_suite_factory = test_suite
 
669
            if verbose is None:
 
670
                verbose = False
 
671
            benchfile = None
 
672
 
 
673
        if testspecs_list is not None:
 
674
            pattern = '|'.join(testspecs_list)
 
675
        else:
 
676
            pattern = ".*"
 
677
 
 
678
        try:
 
679
            result = selftest(verbose=verbose,
 
680
                              pattern=pattern,
 
681
                              stop_on_failure=one,
 
682
                              test_suite_factory=test_suite_factory,
 
683
                              lsprof_timed=lsprof_timed,
 
684
                              bench_history=benchfile,
 
685
                              list_only=list_only,
 
686
                              random_seed=randomize,
 
687
                             )
 
688
        finally:
 
689
            if benchfile is not None:
 
690
                benchfile.close()
 
691
 
 
692
register_command(cmd_test_gtk)
 
693
 
 
694
 
 
695
 
467
696
import gettext
468
697
gettext.install('olive-gtk')
469
698
 
 
699
# Let's create a specialized alias to protect '_' from being erased by other
 
700
# uses of '_' as an anonymous variable (think pdb for one).
 
701
_i18n = gettext.gettext
470
702
 
471
703
class NoDisplayError(BzrCommandError):
472
704
    """gtk could not find a proper display"""
482
714
    default_encoding = sys.getdefaultencoding()
483
715
    try:
484
716
        result = TestSuite()
 
717
        try:
 
718
            import_pygtk()
 
719
        except errors.BzrCommandError:
 
720
            return result
485
721
        result.addTest(tests.test_suite())
486
722
    finally:
487
723
        if sys.getdefaultencoding() != default_encoding: