/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-05-04 18:16:01 UTC
  • Revision ID: jelmer@samba.org-20080504181601-u5gh89q8l2we201l
Fix display of children in branchview.

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