/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: 2007-03-09 17:47:28 UTC
  • Revision ID: jelmer@samba.org-20070309174728-gljlmt9b7fu0rrn9
Add simple test for tortoise_bzr

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
 
"""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
 
gstatus           GTK+ status dialog 
30
 
gtags             Manage branch tags.
31
 
visualise         Graphically visualise this branch. 
32
 
"""
 
15
"""GTK+ frontends to Bazaar commands """
33
16
 
34
17
import bzrlib
35
18
 
36
 
version_info = (0, 92, 0, 'dev', 0)
 
19
__version__ = '0.16.0'
 
20
version_info = tuple(int(n) for n in __version__.split('.'))
37
21
 
38
 
if version_info[3] == 'final':
39
 
    version_string = '%d.%d.%d' % version_info[:3]
40
 
else:
41
 
    version_string = '%d.%d.%d%s%d' % version_info
42
 
__version__ = version_string
43
22
 
44
23
def check_bzrlib_version(desired):
45
24
    """Check that bzrlib is compatible.
51
30
    """
52
31
    desired_plus = (desired[0], desired[1]+1)
53
32
    bzrlib_version = bzrlib.version_info[:2]
54
 
    if bzrlib_version == desired or (bzrlib_version == desired_plus and
55
 
                                     bzrlib.version_info[3] == 'dev'):
 
33
    if bzrlib_version == desired:
56
34
        return
57
35
    try:
58
36
        from bzrlib.trace import warning
60
38
        # get the message out any way we can
61
39
        from warnings import warn as warning
62
40
    if bzrlib_version < desired:
63
 
        from bzrlib.errors import BzrError
64
 
        warning('Installed Bazaar version %s is too old to be used with bzr-gtk'
 
41
        warning('Installed bzr version %s is too old to be used with bzr-gtk'
65
42
                ' %s.' % (bzrlib.__version__, __version__))
66
 
        raise BzrError('Version mismatch: %r, %r' % (version_info, bzrlib.version_info) )
 
43
        # Not using BzrNewError, because it may not exist.
 
44
        raise Exception, ('Version mismatch', version_info)
67
45
    else:
68
46
        warning('bzr-gtk is not up to date with installed bzr version %s.'
69
47
                ' \nThere should be a newer version available, e.g. %i.%i.' 
70
48
                % (bzrlib.__version__, bzrlib_version[0], bzrlib_version[1]))
71
 
 
72
 
 
73
 
if version_info[2] == "final":
74
 
    check_bzrlib_version(version_info[:2])
 
49
        if bzrlib_version != desired_plus:
 
50
            raise Exception, 'Version mismatch'
 
51
 
 
52
 
 
53
check_bzrlib_version(version_info[:2])
75
54
 
76
55
from bzrlib.trace import warning
77
56
if __name__ != 'bzrlib.plugins.gtk':
81
60
lazy_import(globals(), """
82
61
from bzrlib import (
83
62
    branch,
84
 
    builtins,
85
63
    errors,
86
64
    workingtree,
87
65
    )
89
67
 
90
68
from bzrlib.commands import Command, register_command, display_command
91
69
from bzrlib.errors import NotVersionedError, BzrCommandError, NoSuchFile
 
70
from bzrlib.commands import Command, register_command
92
71
from bzrlib.option import Option
 
72
from bzrlib.bzrdir import BzrDir
93
73
 
94
74
import os.path
95
75
 
103
83
 
104
84
 
105
85
def set_ui_factory():
106
 
    import_pygtk()
 
86
    pygtk = import_pygtk()
107
87
    from ui import GtkUIFactory
108
88
    import bzrlib.ui
109
89
    bzrlib.ui.ui_factory = GtkUIFactory()
110
90
 
111
91
 
112
 
def data_path():
113
 
    return os.path.dirname(__file__)
114
 
 
115
 
 
116
 
class GTKCommand(Command):
117
 
    """Abstract class providing GTK specific run commands."""
118
 
 
119
 
    def open_display(self):
120
 
        pygtk = import_pygtk()
121
 
        try:
122
 
            import gtk
123
 
        except RuntimeError, e:
124
 
            if str(e) == "could not open display":
125
 
                raise NoDisplayError
126
 
        set_ui_factory()
127
 
        return gtk
128
 
 
129
 
    def run(self):
130
 
        self.open_display()
131
 
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
132
 
        dialog.run()
133
 
 
134
 
 
135
 
class cmd_gbranch(GTKCommand):
 
92
class cmd_gbranch(Command):
136
93
    """GTK+ branching.
137
94
    
138
95
    """
139
96
 
140
 
    def get_gtk_dialog(self, path):
 
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
 
141
105
        from bzrlib.plugins.gtk.branch import BranchDialog
142
 
        return BranchDialog(path)
143
 
 
144
 
 
145
 
class cmd_gcheckout(GTKCommand):
 
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):
146
114
    """ GTK+ checkout.
147
115
    
148
116
    """
149
117
    
150
 
    def get_gtk_dialog(self, path):
 
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
 
151
126
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
152
 
        return CheckoutDialog(path)
153
 
 
154
 
 
155
 
 
156
 
class cmd_gpush(GTKCommand):
 
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):
157
135
    """ GTK+ push.
158
136
    
159
137
    """
161
139
 
162
140
    def run(self, location="."):
163
141
        (br, path) = branch.Branch.open_containing(location)
164
 
        self.open_display()
 
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
 
165
150
        from push import PushDialog
166
 
        dialog = PushDialog(br.repository, br.last_revision(), br)
 
151
 
 
152
        set_ui_factory()
 
153
        dialog = PushDialog(br)
167
154
        dialog.run()
168
155
 
169
 
 
170
 
 
171
 
class cmd_gdiff(GTKCommand):
 
156
register_command(cmd_gpush)
 
157
 
 
158
class cmd_gdiff(Command):
172
159
    """Show differences in working tree in a GTK+ Window.
173
160
    
174
161
    Otherwise, all changes for the tree are listed.
207
194
                try:
208
195
                    window.set_file(tree_filename)
209
196
                except NoSuchFile:
210
 
                    if (tree1.path2id(tree_filename) is None and 
211
 
                        tree2.path2id(tree_filename) is None):
 
197
                    if (tree1.inventory.path2id(tree_filename) is None and 
 
198
                        tree2.inventory.path2id(tree_filename) is None):
212
199
                        raise NotVersionedError(filename)
213
200
                    raise BzrCommandError('No changes found for file "%s"' % 
214
201
                                          filename)
218
205
        finally:
219
206
            wt.unlock()
220
207
 
221
 
 
222
 
def start_viz_window(branch, revision, limit=None):
223
 
    """Start viz on branch with revision revision.
224
 
    
225
 
    :return: The viz window object.
226
 
    """
227
 
    from viz.branchwin import BranchWindow
228
 
    return BranchWindow(branch, revision, limit)
229
 
 
 
208
register_command(cmd_gdiff)
230
209
 
231
210
class cmd_visualise(Command):
232
211
    """Graphically visualise this branch.
239
218
    """
240
219
    takes_options = [
241
220
        "revision",
242
 
        Option('limit', "Maximum number of revisions to display.",
 
221
        Option('limit', "maximum number of revisions to display",
243
222
               int, 'count')]
244
223
    takes_args = [ "location?" ]
245
224
    aliases = [ "visualize", "vis", "viz" ]
248
227
        set_ui_factory()
249
228
        (br, path) = branch.Branch.open_containing(location)
250
229
        br.lock_read()
 
230
        br.repository.lock_read()
251
231
        try:
252
232
            if revision is None:
253
233
                revid = br.last_revision()
256
236
            else:
257
237
                (revno, revid) = revision[0].in_history(br)
258
238
 
 
239
            from viz.branchwin import BranchWindow
259
240
            import gtk
260
 
            pp = start_viz_window(br, revid, limit)
 
241
                
 
242
            pp = BranchWindow()
 
243
            pp.set_branch(br, revid, limit)
261
244
            pp.connect("destroy", lambda w: gtk.main_quit())
262
245
            pp.show()
263
246
            gtk.main()
264
247
        finally:
 
248
            br.repository.unlock()
265
249
            br.unlock()
266
250
 
267
251
 
268
 
class cmd_gannotate(GTKCommand):
 
252
register_command(cmd_visualise)
 
253
 
 
254
class cmd_gannotate(Command):
269
255
    """GTK+ annotate.
270
256
    
271
257
    Browse changes to FILENAME line by line in a GTK+ window.
273
259
 
274
260
    takes_args = ["filename", "line?"]
275
261
    takes_options = [
276
 
        Option("all", help="Show annotations on all lines."),
277
 
        Option("plain", help="Don't highlight annotation lines."),
 
262
        Option("all", help="show annotations on all lines"),
 
263
        Option("plain", help="don't highlight annotation lines"),
278
264
        Option("line", type=int, argname="lineno",
279
 
               help="Jump to specified line number."),
 
265
               help="jump to specified line number"),
280
266
        "revision",
281
267
    ]
282
268
    aliases = ["gblame", "gpraise"]
283
269
    
284
270
    def run(self, filename, all=False, plain=False, line='1', revision=None):
285
 
        gtk = self.open_display()
 
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()
286
279
 
287
280
        try:
288
281
            line = int(line)
292
285
 
293
286
        from annotate.gannotate import GAnnotateWindow
294
287
        from annotate.config import GAnnotateConfig
295
 
        from bzrlib.bzrdir import BzrDir
296
288
 
297
289
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
298
290
        if wt is not None:
329
321
            if wt is not None:
330
322
                wt.unlock()
331
323
 
332
 
 
333
 
 
334
 
class cmd_gcommit(GTKCommand):
 
324
register_command(cmd_gannotate)
 
325
 
 
326
class cmd_gcommit(Command):
335
327
    """GTK+ commit dialog
336
328
 
337
329
    Graphical user interface for committing revisions"""
342
334
 
343
335
    def run(self, filename=None):
344
336
        import os
345
 
        self.open_display()
 
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()
346
346
        from commit import CommitDialog
 
347
        from bzrlib.commit import Commit
347
348
        from bzrlib.errors import (BzrCommandError,
348
349
                                   NotBranchError,
349
 
                                   NoWorkingTree)
 
350
                                   NoWorkingTree,
 
351
                                   PointlessCommit,
 
352
                                   ConflictsInTree,
 
353
                                   StrictCommitFailed)
350
354
 
351
355
        wt = None
352
356
        br = None
353
357
        try:
354
358
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
355
359
            br = wt.branch
 
360
        except NotBranchError, e:
 
361
            path = e.path
356
362
        except NoWorkingTree, e:
357
363
            path = e.base
358
 
            (br, path) = branch.Branch.open_containing(path)
 
364
            try:
 
365
                (br, path) = branch.Branch.open_containing(path)
 
366
            except NotBranchError, e:
 
367
                path = e.path
 
368
 
359
369
 
360
370
        commit = CommitDialog(wt, path, not br)
361
371
        commit.run()
362
372
 
363
 
 
364
 
 
365
 
class cmd_gstatus(GTKCommand):
 
373
register_command(cmd_gcommit)
 
374
 
 
375
class cmd_gstatus(Command):
366
376
    """GTK+ status dialog
367
377
 
368
378
    Graphical user interface for showing status 
374
384
 
375
385
    def run(self, path='.'):
376
386
        import os
377
 
        gtk = self.open_display()
 
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()
378
396
        from status import StatusDialog
379
397
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
380
398
        status = StatusDialog(wt, wt_path)
381
399
        status.connect("destroy", gtk.main_quit)
382
400
        status.run()
383
401
 
384
 
 
385
 
 
386
 
class cmd_gconflicts(GTKCommand):
387
 
    """ GTK+ conflicts.
 
402
register_command(cmd_gstatus)
 
403
 
 
404
class cmd_gconflicts(Command):
 
405
    """ GTK+ push.
388
406
    
389
 
    Select files from the list of conflicts and run an external utility to
390
 
    resolve them.
391
407
    """
392
408
    def run(self):
393
409
        (wt, path) = workingtree.WorkingTree.open_containing('.')
394
 
        self.open_display()
 
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
 
395
418
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
 
419
 
 
420
        set_ui_factory()
396
421
        dialog = ConflictsDialog(wt)
397
422
        dialog.run()
398
423
 
399
 
 
400
 
 
401
 
class cmd_gpreferences(GTKCommand):
402
 
    """ GTK+ preferences dialog.
403
 
 
404
 
    """
405
 
    def run(self):
406
 
        self.open_display()
407
 
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
408
 
        dialog = PreferencesWindow()
409
 
        dialog.run()
410
 
 
411
 
 
412
 
 
413
 
class cmd_gmissing(Command):
414
 
    """ GTK+ missing revisions dialog.
415
 
 
416
 
    """
417
 
    takes_args = ["other_branch?"]
418
 
    def run(self, other_branch=None):
419
 
        pygtk = import_pygtk()
420
 
        try:
421
 
            import gtk
422
 
        except RuntimeError, e:
423
 
            if str(e) == "could not open display":
424
 
                raise NoDisplayError
425
 
 
426
 
        from bzrlib.plugins.gtk.missing import MissingWindow
427
 
        from bzrlib.branch import Branch
428
 
 
429
 
        local_branch = Branch.open_containing(".")[0]
430
 
        if other_branch is None:
431
 
            other_branch = local_branch.get_parent()
432
 
            
433
 
            if other_branch is None:
434
 
                raise errors.BzrCommandError("No peer location known or specified.")
435
 
        remote_branch = Branch.open_containing(other_branch)[0]
436
 
        set_ui_factory()
437
 
        local_branch.lock_read()
438
 
        try:
439
 
            remote_branch.lock_read()
440
 
            try:
441
 
                dialog = MissingWindow(local_branch, remote_branch)
442
 
                dialog.run()
443
 
            finally:
444
 
                remote_branch.unlock()
445
 
        finally:
446
 
            local_branch.unlock()
447
 
 
448
 
 
449
 
class cmd_ginit(GTKCommand):
450
 
    def run(self):
451
 
        self.open_display()
452
 
        from initialize import InitDialog
453
 
        dialog = InitDialog(os.path.abspath(os.path.curdir))
454
 
        dialog.run()
455
 
 
456
 
 
457
 
class cmd_gtags(GTKCommand):
458
 
    def run(self):
459
 
        br = branch.Branch.open_containing('.')[0]
460
 
        
461
 
        gtk = self.open_display()
462
 
        from tags import TagsWindow
463
 
        window = TagsWindow(br)
464
 
        window.show()
465
 
        gtk.main()
466
 
 
467
 
 
468
 
commands = [
469
 
    cmd_gmissing, 
470
 
    cmd_gpreferences, 
471
 
    cmd_gconflicts, 
472
 
    cmd_gstatus,
473
 
    cmd_gcommit, 
474
 
    cmd_gannotate, 
475
 
    cmd_visualise, 
476
 
    cmd_gdiff,
477
 
    cmd_gpush, 
478
 
    cmd_gcheckout, 
479
 
    cmd_gbranch,
480
 
    cmd_ginit,
481
 
    cmd_gtags
482
 
    ]
483
 
 
484
 
for cmd in commands:
485
 
    register_command(cmd)
486
 
 
487
 
 
488
 
class cmd_commit_notify(GTKCommand):
489
 
    """Run the bzr commit notifier.
490
 
 
491
 
    This is a background program which will pop up a notification on the users
492
 
    screen when a commit occurs.
493
 
    """
494
 
 
495
 
    def run(self):
496
 
        from notify import NotifyPopupMenu
497
 
        gtk = self.open_display()
498
 
        menu = NotifyPopupMenu()
499
 
        icon = gtk.status_icon_new_from_file(os.path.join(data_path(), "bzr-icon-64.png"))
500
 
        icon.connect('popup-menu', menu.display)
501
 
 
502
 
        import cgi
503
 
        import dbus
504
 
        import dbus.service
505
 
        import pynotify
506
 
        from bzrlib.bzrdir import BzrDir
507
 
        from bzrlib import errors
508
 
        from bzrlib.osutils import format_date
509
 
        from bzrlib.transport import get_transport
510
 
        if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
511
 
            import dbus.glib
512
 
        from bzrlib.plugins.dbus import activity
513
 
        bus = dbus.SessionBus()
514
 
        # get the object so we can subscribe to callbacks from it.
515
 
        broadcast_service = bus.get_object(
516
 
            activity.Broadcast.DBUS_NAME,
517
 
            activity.Broadcast.DBUS_PATH)
518
 
 
519
 
        def catch_branch(revision_id, urls):
520
 
            # TODO: show all the urls, or perhaps choose the 'best'.
521
 
            url = urls[0]
522
 
            try:
523
 
                if isinstance(revision_id, unicode):
524
 
                    revision_id = revision_id.encode('utf8')
525
 
                transport = get_transport(url)
526
 
                a_dir = BzrDir.open_from_transport(transport)
527
 
                branch = a_dir.open_branch()
528
 
                revno = branch.revision_id_to_revno(revision_id)
529
 
                revision = branch.repository.get_revision(revision_id)
530
 
                summary = 'New revision %d in %s' % (revno, url)
531
 
                body  = 'Committer: %s\n' % revision.committer
532
 
                body += 'Date: %s\n' % format_date(revision.timestamp,
533
 
                    revision.timezone)
534
 
                body += '\n'
535
 
                body += revision.message
536
 
                body = cgi.escape(body)
537
 
                nw = pynotify.Notification(summary, body)
538
 
                def start_viz(notification=None, action=None, data=None):
539
 
                    """Start the viz program."""
540
 
                    pp = start_viz_window(branch, revision_id)
541
 
                    pp.show()
542
 
                def start_branch(notification=None, action=None, data=None):
543
 
                    """Start a Branch dialog"""
544
 
                    from bzrlib.plugins.gtk.branch import BranchDialog
545
 
                    bd = BranchDialog(remote_path=url)
546
 
                    bd.run()
547
 
                nw.add_action("inspect", "Inspect", start_viz, None)
548
 
                nw.add_action("branch", "Branch", start_branch, None)
549
 
                nw.set_timeout(5000)
550
 
                nw.show()
551
 
            except Exception, e:
552
 
                print e
553
 
                raise
554
 
        broadcast_service.connect_to_signal("Revision", catch_branch,
555
 
            dbus_interface=activity.Broadcast.DBUS_INTERFACE)
556
 
        pynotify.init("bzr commit-notify")
557
 
        gtk.main()
558
 
 
559
 
register_command(cmd_commit_notify)
560
 
 
561
 
 
562
 
class cmd_gselftest(GTKCommand):
563
 
    """Version of selftest that displays a notification at the end"""
564
 
 
565
 
    takes_args = builtins.cmd_selftest.takes_args
566
 
    takes_options = builtins.cmd_selftest.takes_options
567
 
    _see_also = ['selftest']
568
 
 
569
 
    def run(self, *args, **kwargs):
570
 
        import cgi
571
 
        import sys
572
 
        default_encoding = sys.getdefaultencoding()
573
 
        # prevent gtk from blowing up later
574
 
        gtk = import_pygtk()
575
 
        # prevent gtk from messing with default encoding
576
 
        import pynotify
577
 
        if sys.getdefaultencoding() != default_encoding:
578
 
            reload(sys)
579
 
            sys.setdefaultencoding(default_encoding)
580
 
        result = builtins.cmd_selftest().run(*args, **kwargs)
581
 
        if result == 0:
582
 
            summary = 'Success'
583
 
            body = 'Selftest succeeded in "%s"' % os.getcwd()
584
 
        if result == 1:
585
 
            summary = 'Failure'
586
 
            body = 'Selftest failed in "%s"' % os.getcwd()
587
 
        pynotify.init("bzr gselftest")
588
 
        note = pynotify.Notification(cgi.escape(summary), cgi.escape(body))
589
 
        note.set_timeout(pynotify.EXPIRES_NEVER)
590
 
        note.show()
591
 
 
592
 
 
593
 
register_command(cmd_gselftest)
594
 
 
 
424
register_command(cmd_gconflicts)
595
425
 
596
426
import gettext
597
427
gettext.install('olive-gtk')
598
428
 
599
 
 
600
429
class NoDisplayError(BzrCommandError):
601
430
    """gtk could not find a proper display"""
602
431
 
603
432
    def __str__(self):
604
433
        return "No DISPLAY. Unable to run GTK+ application."
605
434
 
606
 
 
607
435
def test_suite():
608
436
    from unittest import TestSuite
609
437
    import tests
613
441
        result = TestSuite()
614
442
        result.addTest(tests.test_suite())
615
443
    finally:
616
 
        if sys.getdefaultencoding() != default_encoding:
617
 
            reload(sys)
618
 
            sys.setdefaultencoding(default_encoding)
 
444
        reload(sys)
 
445
        sys.setdefaultencoding(default_encoding)
619
446
    return result