/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: Jasper Groenewegen
  • Date: 2008-07-27 12:01:40 UTC
  • mfrom: (576.3.2 improve-merge)
  • mto: This revision was merged to the branch mainline in revision 579.
  • Revision ID: colbrac@xs4all.nl-20080727120140-1agdlzkc9fumjk5f
Merge merge dialog improvements

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
"""Graphical support for Bazaar using GTK.
16
16
 
17
17
This plugin includes:
18
 
commit-notify     Start the graphical notifier of commits.
19
18
gannotate         GTK+ annotate. 
20
19
gbranch           GTK+ branching. 
21
20
gcheckout         GTK+ checkout. 
23
22
gconflicts        GTK+ conflicts. 
24
23
gdiff             Show differences in working tree in a GTK+ Window. 
25
24
ginit             Initialise a new branch.
 
25
gmerge            GTK+ merge dialog
26
26
gmissing          GTK+ missing revisions dialog. 
27
27
gpreferences      GTK+ preferences dialog. 
28
28
gpush             GTK+ push.
32
32
visualise         Graphically visualise this branch. 
33
33
"""
34
34
 
 
35
import sys
 
36
 
35
37
import bzrlib
36
38
 
37
 
version_info = (0, 92, 0, 'dev', 0)
 
39
version_info = (0, 95, 0, 'dev', 1)
38
40
 
39
41
if version_info[3] == 'final':
40
42
    version_string = '%d.%d.%d' % version_info[:3]
42
44
    version_string = '%d.%d.%d%s%d' % version_info
43
45
__version__ = version_string
44
46
 
 
47
required_bzrlib = (1, 3)
 
48
 
45
49
def check_bzrlib_version(desired):
46
50
    """Check that bzrlib is compatible.
47
51
 
48
52
    If version is < bzr-gtk version, assume incompatible.
49
 
    If version == bzr-gtk version, assume completely compatible
50
 
    If version == bzr-gtk version + 1, assume compatible, with deprecations
51
 
    Otherwise, assume incompatible.
52
53
    """
53
 
    desired_plus = (desired[0], desired[1]+1)
54
54
    bzrlib_version = bzrlib.version_info[:2]
55
 
    if bzrlib_version == desired or (bzrlib_version == desired_plus and
56
 
                                     bzrlib.version_info[3] == 'dev'):
57
 
        return
58
55
    try:
59
56
        from bzrlib.trace import warning
60
57
    except ImportError:
65
62
        warning('Installed Bazaar version %s is too old to be used with bzr-gtk'
66
63
                ' %s.' % (bzrlib.__version__, __version__))
67
64
        raise BzrError('Version mismatch: %r, %r' % (version_info, bzrlib.version_info) )
68
 
    else:
69
 
        warning('bzr-gtk is not up to date with installed bzr version %s.'
70
 
                ' \nThere should be a newer version available, e.g. %i.%i.' 
71
 
                % (bzrlib.__version__, bzrlib_version[0], bzrlib_version[1]))
72
65
 
73
66
 
74
67
if version_info[2] == "final":
75
 
    check_bzrlib_version(version_info[:2])
 
68
    check_bzrlib_version(required_bzrlib)
76
69
 
77
70
from bzrlib.trace import warning
78
71
if __name__ != 'bzrlib.plugins.gtk':
84
77
    branch,
85
78
    builtins,
86
79
    errors,
 
80
    merge_directive,
87
81
    workingtree,
88
82
    )
89
83
""")
110
104
    bzrlib.ui.ui_factory = GtkUIFactory()
111
105
 
112
106
 
113
 
def data_path():
114
 
    return os.path.dirname(__file__)
115
 
 
 
107
def data_basedirs():
 
108
    return [os.path.dirname(__file__),
 
109
             "/usr/share/bzr-gtk", 
 
110
             "/usr/local/share/bzr-gtk"]
 
111
 
 
112
 
 
113
def data_path(*args):
 
114
    for basedir in data_basedirs():
 
115
        path = os.path.join(basedir, *args)
 
116
        if os.path.exists(path):
 
117
            return path
 
118
    return None
 
119
 
 
120
 
 
121
def icon_path(*args):
 
122
    return data_path(os.path.join('icons', *args))
 
123
 
 
124
 
 
125
def open_display():
 
126
    pygtk = import_pygtk()
 
127
    try:
 
128
        import gtk
 
129
    except RuntimeError, e:
 
130
        if str(e) == "could not open display":
 
131
            raise NoDisplayError
 
132
    set_ui_factory()
 
133
    return gtk
 
134
 
116
135
 
117
136
class GTKCommand(Command):
118
137
    """Abstract class providing GTK specific run commands."""
119
138
 
120
 
    def open_display(self):
121
 
        pygtk = import_pygtk()
122
 
        try:
123
 
            import gtk
124
 
        except RuntimeError, e:
125
 
            if str(e) == "could not open display":
126
 
                raise NoDisplayError
127
 
        set_ui_factory()
128
 
        return gtk
129
 
 
130
139
    def run(self):
131
 
        self.open_display()
 
140
        open_display()
132
141
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
133
142
        dialog.run()
134
143
 
162
171
 
163
172
    def run(self, location="."):
164
173
        (br, path) = branch.Branch.open_containing(location)
165
 
        self.open_display()
 
174
        open_display()
166
175
        from push import PushDialog
167
176
        dialog = PushDialog(br.repository, br.last_revision(), br)
168
177
        dialog.run()
187
196
            if revision is not None:
188
197
                if len(revision) == 1:
189
198
                    tree1 = wt
190
 
                    revision_id = revision[0].in_history(branch).rev_id
 
199
                    revision_id = revision[0].as_revision_id(tree1.branch)
191
200
                    tree2 = branch.repository.revision_tree(revision_id)
192
201
                elif len(revision) == 2:
193
 
                    revision_id_0 = revision[0].in_history(branch).rev_id
 
202
                    revision_id_0 = revision[0].as_revision_id(branch)
194
203
                    tree2 = branch.repository.revision_tree(revision_id_0)
195
 
                    revision_id_1 = revision[1].in_history(branch).rev_id
 
204
                    revision_id_1 = revision[1].as_revision_id(branch)
196
205
                    tree1 = branch.repository.revision_tree(revision_id_1)
197
206
            else:
198
207
                tree1 = wt
220
229
            wt.unlock()
221
230
 
222
231
 
223
 
def start_viz_window(branch, revision, limit=None):
 
232
def start_viz_window(branch, revisions, limit=None):
224
233
    """Start viz on branch with revision revision.
225
234
    
226
235
    :return: The viz window object.
227
236
    """
228
 
    from viz.branchwin import BranchWindow
229
 
    return BranchWindow(branch, revision, limit)
 
237
    from viz import BranchWindow
 
238
    return BranchWindow(branch, revisions, limit)
230
239
 
231
240
 
232
241
class cmd_visualise(Command):
242
251
        "revision",
243
252
        Option('limit', "Maximum number of revisions to display.",
244
253
               int, 'count')]
245
 
    takes_args = [ "location?" ]
 
254
    takes_args = [ "locations*" ]
246
255
    aliases = [ "visualize", "vis", "viz" ]
247
256
 
248
 
    def run(self, location=".", revision=None, limit=None):
 
257
    def run(self, locations_list, revision=None, limit=None):
249
258
        set_ui_factory()
250
 
        (br, path) = branch.Branch.open_containing(location)
251
 
        br.lock_read()
252
 
        try:
 
259
        if locations_list is None:
 
260
            locations_list = ["."]
 
261
        revids = []
 
262
        for location in locations_list:
 
263
            (br, path) = branch.Branch.open_containing(location)
253
264
            if revision is None:
254
 
                revid = br.last_revision()
255
 
                if revid is None:
256
 
                    return
 
265
                revids.append(br.last_revision())
257
266
            else:
258
 
                (revno, revid) = revision[0].in_history(br)
259
 
 
260
 
            import gtk
261
 
            pp = start_viz_window(br, revid, limit)
262
 
            pp.connect("destroy", lambda w: gtk.main_quit())
263
 
            pp.show()
264
 
            gtk.main()
265
 
        finally:
266
 
            br.unlock()
 
267
                revids.append(revision[0].as_revision_id(br))
 
268
        import gtk
 
269
        pp = start_viz_window(br, revids, limit)
 
270
        pp.connect("destroy", lambda w: gtk.main_quit())
 
271
        pp.show()
 
272
        gtk.main()
267
273
 
268
274
 
269
275
class cmd_gannotate(GTKCommand):
283
289
    aliases = ["gblame", "gpraise"]
284
290
    
285
291
    def run(self, filename, all=False, plain=False, line='1', revision=None):
286
 
        gtk = self.open_display()
 
292
        gtk = open_display()
287
293
 
288
294
        try:
289
295
            line = int(line)
308
314
        if revision is not None:
309
315
            if len(revision) != 1:
310
316
                raise BzrCommandError("Only 1 revion may be specified.")
311
 
            revision_id = revision[0].in_history(br).rev_id
 
317
            revision_id = revision[0].as_revision_id(br)
312
318
            tree = br.repository.revision_tree(revision_id)
313
319
        else:
314
320
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
315
321
 
316
 
        window = GAnnotateWindow(all, plain)
 
322
        window = GAnnotateWindow(all, plain, branch=br)
317
323
        window.connect("destroy", lambda w: gtk.main_quit())
318
 
        window.set_title(path + " - gannotate")
319
324
        config = GAnnotateConfig(window)
320
325
        window.show()
321
326
        br.lock_read()
336
341
    """GTK+ commit dialog
337
342
 
338
343
    Graphical user interface for committing revisions"""
339
 
    
 
344
 
340
345
    aliases = [ "gci" ]
341
346
    takes_args = []
342
347
    takes_options = []
343
348
 
344
349
    def run(self, filename=None):
345
350
        import os
346
 
        self.open_display()
 
351
        open_display()
347
352
        from commit import CommitDialog
348
353
        from bzrlib.errors import (BzrCommandError,
349
354
                                   NotBranchError,
355
360
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
356
361
            br = wt.branch
357
362
        except NoWorkingTree, e:
358
 
            path = e.base
359
 
            (br, path) = branch.Branch.open_containing(path)
360
 
 
361
 
        commit = CommitDialog(wt, path, not br)
362
 
        commit.run()
363
 
 
 
363
            from dialog import error_dialog
 
364
            error_dialog(_i18n('Directory does not have a working tree'),
 
365
                         _i18n('Operation aborted.'))
 
366
            return 1 # should this be retval=3?
 
367
 
 
368
        # It is a good habit to keep things locked for the duration, but it
 
369
        # could cause difficulties if someone wants to do things in another
 
370
        # window... We could lock_read() until we actually go to commit
 
371
        # changes... Just a thought.
 
372
        wt.lock_write()
 
373
        try:
 
374
            dlg = CommitDialog(wt)
 
375
            return dlg.run()
 
376
        finally:
 
377
            wt.unlock()
364
378
 
365
379
 
366
380
class cmd_gstatus(GTKCommand):
371
385
    
372
386
    aliases = [ "gst" ]
373
387
    takes_args = ['PATH?']
374
 
    takes_options = []
 
388
    takes_options = ['revision']
375
389
 
376
 
    def run(self, path='.'):
 
390
    def run(self, path='.', revision=None):
377
391
        import os
378
 
        gtk = self.open_display()
 
392
        gtk = open_display()
379
393
        from status import StatusDialog
380
394
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
381
 
        status = StatusDialog(wt, wt_path)
 
395
        
 
396
        if revision is not None:
 
397
            try:
 
398
                revision_id = revision[0].as_revision_id(wt.branch)
 
399
            except:
 
400
                from bzrlib.errors import BzrError
 
401
                raise BzrError('Revision %r doesn\'t exist' % revision[0].user_spec )
 
402
        else:
 
403
            revision_id = None
 
404
 
 
405
        status = StatusDialog(wt, wt_path, revision_id)
382
406
        status.connect("destroy", gtk.main_quit)
383
407
        status.run()
384
408
 
389
413
    """
390
414
    def run(self):
391
415
        (br, path) = branch.Branch.open_containing(".")
392
 
        gtk = self.open_display()
 
416
        gtk = open_display()
393
417
        from bzrlib.plugins.gtk.mergedirective import SendMergeDirectiveDialog
394
418
        from StringIO import StringIO
395
419
        dialog = SendMergeDirectiveDialog(br)
411
435
    """
412
436
    def run(self):
413
437
        (wt, path) = workingtree.WorkingTree.open_containing('.')
414
 
        self.open_display()
 
438
        open_display()
415
439
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
416
440
        dialog = ConflictsDialog(wt)
417
441
        dialog.run()
422
446
 
423
447
    """
424
448
    def run(self):
425
 
        self.open_display()
 
449
        open_display()
426
450
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
427
451
        dialog = PreferencesWindow()
428
452
        dialog.run()
429
453
 
430
454
 
 
455
class cmd_gmerge(Command):
 
456
    """ GTK+ merge dialog
 
457
    
 
458
    """
 
459
    takes_args = ["merge_from_path?"]
 
460
    def run(self, merge_from_path=None):
 
461
        from bzrlib import workingtree
 
462
        from bzrlib.plugins.gtk.dialog import error_dialog
 
463
        from bzrlib.plugins.gtk.merge import MergeDialog
 
464
        
 
465
        (wt, path) = workingtree.WorkingTree.open_containing('.')
 
466
        old_tree = wt.branch.repository.revision_tree(wt.branch.last_revision())
 
467
        delta = wt.changes_from(old_tree)
 
468
        if len(delta.added) or len(delta.removed) or len(delta.renamed) or len(delta.modified):
 
469
            error_dialog(_i18n('There are local changes in the branch'),
 
470
                         _i18n('Please commit or revert the changes before merging.'))
 
471
        else:
 
472
            parent_branch_path = wt.branch.get_parent()
 
473
            merge = MergeDialog(wt, path, parent_branch_path)
 
474
            response = merge.run()
 
475
            merge.destroy()
 
476
 
 
477
 
431
478
class cmd_gmissing(Command):
432
479
    """ GTK+ missing revisions dialog.
433
480
 
466
513
 
467
514
class cmd_ginit(GTKCommand):
468
515
    def run(self):
469
 
        self.open_display()
 
516
        open_display()
470
517
        from initialize import InitDialog
471
518
        dialog = InitDialog(os.path.abspath(os.path.curdir))
472
519
        dialog.run()
476
523
    def run(self):
477
524
        br = branch.Branch.open_containing('.')[0]
478
525
        
479
 
        gtk = self.open_display()
 
526
        gtk = open_display()
480
527
        from tags import TagsWindow
481
528
        window = TagsWindow(br)
482
529
        window.show()
491
538
    cmd_gconflicts, 
492
539
    cmd_gdiff,
493
540
    cmd_ginit,
 
541
    cmd_gmerge,
494
542
    cmd_gmissing, 
495
543
    cmd_gpreferences, 
496
544
    cmd_gpush, 
504
552
    register_command(cmd)
505
553
 
506
554
 
507
 
class cmd_commit_notify(GTKCommand):
508
 
    """Run the bzr commit notifier.
509
 
 
510
 
    This is a background program which will pop up a notification on the users
511
 
    screen when a commit occurs.
512
 
    """
513
 
 
514
 
    def run(self):
515
 
        from notify import NotifyPopupMenu
516
 
        gtk = self.open_display()
517
 
        menu = NotifyPopupMenu()
518
 
        icon = gtk.status_icon_new_from_file(os.path.join(data_path(), "bzr-icon-64.png"))
519
 
        icon.connect('popup-menu', menu.display)
520
 
 
521
 
        import cgi
522
 
        import dbus
523
 
        import dbus.service
524
 
        import pynotify
525
 
        from bzrlib.bzrdir import BzrDir
526
 
        from bzrlib import errors
527
 
        from bzrlib.osutils import format_date
528
 
        from bzrlib.transport import get_transport
529
 
        if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
530
 
            import dbus.glib
531
 
        from bzrlib.plugins.dbus import activity
532
 
        bus = dbus.SessionBus()
533
 
        # get the object so we can subscribe to callbacks from it.
534
 
        broadcast_service = bus.get_object(
535
 
            activity.Broadcast.DBUS_NAME,
536
 
            activity.Broadcast.DBUS_PATH)
537
 
 
538
 
        def catch_branch(revision_id, urls):
539
 
            # TODO: show all the urls, or perhaps choose the 'best'.
540
 
            url = urls[0]
541
 
            try:
542
 
                if isinstance(revision_id, unicode):
543
 
                    revision_id = revision_id.encode('utf8')
544
 
                transport = get_transport(url)
545
 
                a_dir = BzrDir.open_from_transport(transport)
546
 
                branch = a_dir.open_branch()
547
 
                revno = branch.revision_id_to_revno(revision_id)
548
 
                revision = branch.repository.get_revision(revision_id)
549
 
                summary = 'New revision %d in %s' % (revno, url)
550
 
                body  = 'Committer: %s\n' % revision.committer
551
 
                body += 'Date: %s\n' % format_date(revision.timestamp,
552
 
                    revision.timezone)
553
 
                body += '\n'
554
 
                body += revision.message
555
 
                body = cgi.escape(body)
556
 
                nw = pynotify.Notification(summary, body)
557
 
                def start_viz(notification=None, action=None, data=None):
558
 
                    """Start the viz program."""
559
 
                    pp = start_viz_window(branch, revision_id)
560
 
                    pp.show()
561
 
                def start_branch(notification=None, action=None, data=None):
562
 
                    """Start a Branch dialog"""
563
 
                    from bzrlib.plugins.gtk.branch import BranchDialog
564
 
                    bd = BranchDialog(remote_path=url)
565
 
                    bd.run()
566
 
                nw.add_action("inspect", "Inspect", start_viz, None)
567
 
                nw.add_action("branch", "Branch", start_branch, None)
568
 
                nw.set_timeout(5000)
569
 
                nw.show()
570
 
            except Exception, e:
571
 
                print e
572
 
                raise
573
 
        broadcast_service.connect_to_signal("Revision", catch_branch,
574
 
            dbus_interface=activity.Broadcast.DBUS_INTERFACE)
575
 
        pynotify.init("bzr commit-notify")
576
 
        gtk.main()
577
 
 
578
 
register_command(cmd_commit_notify)
579
 
 
580
 
 
581
555
class cmd_gselftest(GTKCommand):
582
556
    """Version of selftest that displays a notification at the end"""
583
557
 
612
586
register_command(cmd_gselftest)
613
587
 
614
588
 
 
589
class cmd_test_gtk(GTKCommand):
 
590
    """Version of selftest that just runs the gtk test suite."""
 
591
 
 
592
    takes_options = ['verbose',
 
593
                     Option('one', short_name='1',
 
594
                            help='Stop when one test fails.'),
 
595
                     Option('benchmark', help='Run the benchmarks.'),
 
596
                     Option('lsprof-timed',
 
597
                     help='Generate lsprof output for benchmarked'
 
598
                          ' sections of code.'),
 
599
                     Option('list-only',
 
600
                     help='List the tests instead of running them.'),
 
601
                     Option('randomize', type=str, argname="SEED",
 
602
                     help='Randomize the order of tests using the given'
 
603
                          ' seed or "now" for the current time.'),
 
604
                    ]
 
605
    takes_args = ['testspecs*']
 
606
 
 
607
    def run(self, verbose=None, one=False, benchmark=None,
 
608
            lsprof_timed=None, list_only=False, randomize=None,
 
609
            testspecs_list=None):
 
610
        from bzrlib import __path__ as bzrlib_path
 
611
        from bzrlib.tests import selftest
 
612
 
 
613
        print '%10s: %s' % ('bzrlib', bzrlib_path[0])
 
614
        if benchmark:
 
615
            print 'No benchmarks yet'
 
616
            return 3
 
617
 
 
618
            test_suite_factory = bench_suite
 
619
            if verbose is None:
 
620
                verbose = True
 
621
            # TODO: should possibly lock the history file...
 
622
            benchfile = open(".perf_history", "at", buffering=1)
 
623
        else:
 
624
            test_suite_factory = test_suite
 
625
            if verbose is None:
 
626
                verbose = False
 
627
            benchfile = None
 
628
 
 
629
        if testspecs_list is not None:
 
630
            pattern = '|'.join(testspecs_list)
 
631
        else:
 
632
            pattern = ".*"
 
633
 
 
634
        try:
 
635
            result = selftest(verbose=verbose,
 
636
                              pattern=pattern,
 
637
                              stop_on_failure=one,
 
638
                              test_suite_factory=test_suite_factory,
 
639
                              lsprof_timed=lsprof_timed,
 
640
                              bench_history=benchfile,
 
641
                              list_only=list_only,
 
642
                              random_seed=randomize,
 
643
                             )
 
644
        finally:
 
645
            if benchfile is not None:
 
646
                benchfile.close()
 
647
 
 
648
register_command(cmd_test_gtk)
 
649
 
 
650
 
 
651
 
615
652
import gettext
616
653
gettext.install('olive-gtk')
617
654
 
 
655
# Let's create a specialized alias to protect '_' from being erased by other
 
656
# uses of '_' as an anonymous variable (think pdb for one).
 
657
_i18n = gettext.gettext
618
658
 
619
659
class NoDisplayError(BzrCommandError):
620
660
    """gtk could not find a proper display"""
630
670
    default_encoding = sys.getdefaultencoding()
631
671
    try:
632
672
        result = TestSuite()
 
673
        try:
 
674
            import_pygtk()
 
675
        except errors.BzrCommandError:
 
676
            return result
633
677
        result.addTest(tests.test_suite())
634
678
    finally:
635
679
        if sys.getdefaultencoding() != default_encoding: