/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: 2009-04-21 22:00:10 UTC
  • mfrom: (625.1.6 trunk)
  • Revision ID: jelmer@samba.org-20090421220010-9ix3gjr3g68kwwlv
merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
visualise         Graphically visualise this branch. 
35
35
"""
36
36
 
37
 
import sys
38
 
 
39
37
import bzrlib
 
38
import bzrlib.api
 
39
from bzrlib import errors
 
40
from bzrlib.commands import plugin_cmds
 
41
 
 
42
import os.path
40
43
 
41
44
version_info = (0, 96, 0, 'dev', 1)
42
45
 
46
49
    version_string = '%d.%d.%d%s%d' % version_info
47
50
__version__ = version_string
48
51
 
49
 
required_bzrlib = (1, 6)
50
 
 
51
 
def check_bzrlib_version(desired):
52
 
    """Check that bzrlib is compatible.
53
 
 
54
 
    If version is < bzr-gtk version, assume incompatible.
55
 
    """
56
 
    bzrlib_version = bzrlib.version_info[:2]
57
 
    try:
58
 
        from bzrlib.trace import warning
59
 
    except ImportError:
60
 
        # get the message out any way we can
61
 
        from warnings import warn as warning
62
 
    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'
65
 
                ' %s.' % (bzrlib.__version__, __version__))
66
 
        raise BzrError('Version mismatch: %r, %r' % (version_info, bzrlib.version_info) )
67
 
 
68
 
 
69
 
if version_info[2] == "final":
70
 
    check_bzrlib_version(required_bzrlib)
71
 
 
72
 
from bzrlib.trace import warning
 
52
COMPATIBLE_BZR_VERSIONS = [(1, 6, 0), (1, 7, 0), (1, 8, 0), (1, 9, 0),
 
53
                           (1, 10, 0), (1, 11, 0), (1, 12, 0), (1, 13, 0)]
 
54
 
 
55
bzrlib.api.require_any_api(bzrlib, COMPATIBLE_BZR_VERSIONS)
 
56
 
73
57
if __name__ != 'bzrlib.plugins.gtk':
 
58
    from bzrlib.trace import warning
74
59
    warning("Not running as bzrlib.plugins.gtk, things may break.")
75
60
 
76
 
from bzrlib.lazy_import import lazy_import
77
 
lazy_import(globals(), """
78
 
from bzrlib import (
79
 
    branch,
80
 
    builtins,
81
 
    errors,
82
 
    merge_directive,
83
 
    workingtree,
84
 
    )
85
 
""")
86
 
 
87
 
from bzrlib.commands import Command, register_command, display_command
88
 
from bzrlib.errors import NotVersionedError, BzrCommandError, NoSuchFile
89
 
from bzrlib.option import Option
90
 
 
91
 
import os.path
92
 
 
93
61
def import_pygtk():
94
62
    try:
95
63
        import pygtk
135
103
    return gtk
136
104
 
137
105
 
138
 
class GTKCommand(Command):
139
 
    """Abstract class providing GTK specific run commands."""
140
 
 
141
 
    def run(self):
142
 
        open_display()
143
 
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
144
 
        dialog.run()
145
 
 
146
 
 
147
 
class cmd_gbranch(GTKCommand):
148
 
    """GTK+ branching.
149
 
    
150
 
    """
151
 
 
152
 
    def get_gtk_dialog(self, path):
153
 
        from bzrlib.plugins.gtk.branch import BranchDialog
154
 
        return BranchDialog(path)
155
 
 
156
 
 
157
 
class cmd_gcheckout(GTKCommand):
158
 
    """ GTK+ checkout.
159
 
    
160
 
    """
161
 
    
162
 
    def get_gtk_dialog(self, path):
163
 
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
164
 
        return CheckoutDialog(path)
165
 
 
166
 
 
167
 
 
168
 
class cmd_gpush(GTKCommand):
169
 
    """ GTK+ push.
170
 
    
171
 
    """
172
 
    takes_args = [ "location?" ]
173
 
 
174
 
    def run(self, location="."):
175
 
        (br, path) = branch.Branch.open_containing(location)
176
 
        open_display()
177
 
        from bzrlib.plugins.gtk.push import PushDialog
178
 
        dialog = PushDialog(br.repository, br.last_revision(), br)
179
 
        dialog.run()
180
 
 
181
 
 
182
 
class cmd_gloom(GTKCommand):
183
 
    """ GTK+ loom.
184
 
    
185
 
    """
186
 
    takes_args = [ "location?" ]
187
 
 
188
 
    def run(self, location="."):
189
 
        try:
190
 
            (tree, path) = workingtree.WorkingTree.open_containing(location)
191
 
            br = tree.branch
192
 
        except NoWorkingTree, e:
193
 
            (br, path) = branch.Branch.open_containing(location)
194
 
            tree = None
195
 
        open_display()
196
 
        from bzrlib.plugins.gtk.loom import LoomDialog
197
 
        dialog = LoomDialog(br, tree)
198
 
        dialog.run()
199
 
 
200
 
 
201
 
class cmd_gdiff(GTKCommand):
202
 
    """Show differences in working tree in a GTK+ Window.
203
 
    
204
 
    Otherwise, all changes for the tree are listed.
205
 
    """
206
 
    takes_args = ['filename?']
207
 
    takes_options = ['revision']
208
 
 
209
 
    @display_command
210
 
    def run(self, revision=None, filename=None):
211
 
        set_ui_factory()
212
 
        wt = workingtree.WorkingTree.open_containing(".")[0]
213
 
        wt.lock_read()
214
 
        try:
215
 
            branch = wt.branch
216
 
            if revision is not None:
217
 
                if len(revision) == 1:
218
 
                    tree1 = wt
219
 
                    revision_id = revision[0].as_revision_id(tree1.branch)
220
 
                    tree2 = branch.repository.revision_tree(revision_id)
221
 
                elif len(revision) == 2:
222
 
                    revision_id_0 = revision[0].as_revision_id(branch)
223
 
                    tree2 = branch.repository.revision_tree(revision_id_0)
224
 
                    revision_id_1 = revision[1].as_revision_id(branch)
225
 
                    tree1 = branch.repository.revision_tree(revision_id_1)
226
 
            else:
227
 
                tree1 = wt
228
 
                tree2 = tree1.basis_tree()
229
 
 
230
 
            from diff import DiffWindow
231
 
            import gtk
232
 
            window = DiffWindow()
233
 
            window.connect("destroy", gtk.main_quit)
234
 
            window.set_diff("Working Tree", tree1, tree2)
235
 
            if filename is not None:
236
 
                tree_filename = wt.relpath(filename)
237
 
                try:
238
 
                    window.set_file(tree_filename)
239
 
                except NoSuchFile:
240
 
                    if (tree1.path2id(tree_filename) is None and 
241
 
                        tree2.path2id(tree_filename) is None):
242
 
                        raise NotVersionedError(filename)
243
 
                    raise BzrCommandError('No changes found for file "%s"' % 
244
 
                                          filename)
245
 
            window.show()
246
 
 
247
 
            gtk.main()
248
 
        finally:
249
 
            wt.unlock()
250
 
 
251
 
 
252
 
def start_viz_window(branch, revisions, limit=None):
253
 
    """Start viz on branch with revision revision.
254
 
    
255
 
    :return: The viz window object.
256
 
    """
257
 
    from bzrlib.plugins.gtk.viz import BranchWindow
258
 
    return BranchWindow(branch, revisions, limit)
259
 
 
260
 
 
261
 
class cmd_visualise(Command):
262
 
    """Graphically visualise this branch.
263
 
 
264
 
    Opens a graphical window to allow you to see the history of the branch
265
 
    and relationships between revisions in a visual manner,
266
 
 
267
 
    The default starting point is latest revision on the branch, you can
268
 
    specify a starting point with -r revision.
269
 
    """
270
 
    takes_options = [
271
 
        "revision",
272
 
        Option('limit', "Maximum number of revisions to display.",
273
 
               int, 'count')]
274
 
    takes_args = [ "locations*" ]
275
 
    aliases = [ "visualize", "vis", "viz" ]
276
 
 
277
 
    def run(self, locations_list, revision=None, limit=None):
278
 
        set_ui_factory()
279
 
        if locations_list is None:
280
 
            locations_list = ["."]
281
 
        revids = []
282
 
        for location in locations_list:
283
 
            (br, path) = branch.Branch.open_containing(location)
284
 
            if revision is None:
285
 
                revids.append(br.last_revision())
286
 
            else:
287
 
                revids.append(revision[0].as_revision_id(br))
288
 
        import gtk
289
 
        pp = start_viz_window(br, revids, limit)
290
 
        pp.connect("destroy", lambda w: gtk.main_quit())
291
 
        pp.show()
292
 
        gtk.main()
293
 
 
294
 
 
295
 
class cmd_gannotate(GTKCommand):
296
 
    """GTK+ annotate.
297
 
    
298
 
    Browse changes to FILENAME line by line in a GTK+ window.
299
 
    """
300
 
 
301
 
    takes_args = ["filename", "line?"]
302
 
    takes_options = [
303
 
        Option("all", help="Show annotations on all lines."),
304
 
        Option("plain", help="Don't highlight annotation lines."),
305
 
        Option("line", type=int, argname="lineno",
306
 
               help="Jump to specified line number."),
307
 
        "revision",
308
 
    ]
309
 
    aliases = ["gblame", "gpraise"]
310
 
    
311
 
    def run(self, filename, all=False, plain=False, line='1', revision=None):
312
 
        gtk = open_display()
313
 
 
314
 
        try:
315
 
            line = int(line)
316
 
        except ValueError:
317
 
            raise BzrCommandError('Line argument ("%s") is not a number.' % 
318
 
                                  line)
319
 
 
320
 
        from annotate.gannotate import GAnnotateWindow
321
 
        from annotate.config import GAnnotateConfig
322
 
        from bzrlib.bzrdir import BzrDir
323
 
 
324
 
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
325
 
        if wt is not None:
326
 
            tree = wt
327
 
        else:
328
 
            tree = br.basis_tree()
329
 
 
330
 
        file_id = tree.path2id(path)
331
 
 
332
 
        if file_id is None:
333
 
            raise NotVersionedError(filename)
334
 
        if revision is not None:
335
 
            if len(revision) != 1:
336
 
                raise BzrCommandError("Only 1 revion may be specified.")
337
 
            revision_id = revision[0].as_revision_id(br)
338
 
            tree = br.repository.revision_tree(revision_id)
339
 
        else:
340
 
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
341
 
 
342
 
        window = GAnnotateWindow(all, plain, branch=br)
343
 
        window.connect("destroy", lambda w: gtk.main_quit())
344
 
        config = GAnnotateConfig(window)
345
 
        window.show()
346
 
        br.lock_read()
347
 
        if wt is not None:
348
 
            wt.lock_read()
349
 
        try:
350
 
            window.annotate(tree, br, file_id)
351
 
            window.jump_to_line(line)
352
 
            gtk.main()
353
 
        finally:
354
 
            br.unlock()
355
 
            if wt is not None:
356
 
                wt.unlock()
357
 
 
358
 
 
359
 
 
360
 
class cmd_gcommit(GTKCommand):
361
 
    """GTK+ commit dialog
362
 
 
363
 
    Graphical user interface for committing revisions"""
364
 
 
365
 
    aliases = [ "gci" ]
366
 
    takes_args = []
367
 
    takes_options = []
368
 
 
369
 
    def run(self, filename=None):
370
 
        import os
371
 
        open_display()
372
 
        from commit import CommitDialog
373
 
        from bzrlib.errors import (BzrCommandError,
374
 
                                   NotBranchError,
375
 
                                   NoWorkingTree)
376
 
 
377
 
        wt = None
378
 
        br = None
379
 
        try:
380
 
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
381
 
            br = wt.branch
382
 
        except NoWorkingTree, e:
383
 
            from dialog import error_dialog
384
 
            error_dialog(_i18n('Directory does not have a working tree'),
385
 
                         _i18n('Operation aborted.'))
386
 
            return 1 # should this be retval=3?
387
 
 
388
 
        # It is a good habit to keep things locked for the duration, but it
389
 
        # could cause difficulties if someone wants to do things in another
390
 
        # window... We could lock_read() until we actually go to commit
391
 
        # changes... Just a thought.
392
 
        wt.lock_write()
393
 
        try:
394
 
            dlg = CommitDialog(wt)
395
 
            return dlg.run()
396
 
        finally:
397
 
            wt.unlock()
398
 
 
399
 
 
400
 
class cmd_gstatus(GTKCommand):
401
 
    """GTK+ status dialog
402
 
 
403
 
    Graphical user interface for showing status 
404
 
    information."""
405
 
 
406
 
    aliases = [ "gst" ]
407
 
    takes_args = ['PATH?']
408
 
    takes_options = ['revision']
409
 
 
410
 
    def run(self, path='.', revision=None):
411
 
        import os
412
 
        gtk = open_display()
413
 
        from bzrlib.plugins.gtk.status import StatusWindow
414
 
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
415
 
 
416
 
        if revision is not None:
417
 
            try:
418
 
                revision_id = revision[0].as_revision_id(wt.branch)
419
 
            except:
420
 
                from bzrlib.errors import BzrError
421
 
                raise BzrError('Revision %r doesn\'t exist'
422
 
                               % revision[0].user_spec )
423
 
        else:
424
 
            revision_id = None
425
 
 
426
 
        status = StatusWindow(wt, wt_path, revision_id)
427
 
        status.connect("destroy", gtk.main_quit)
428
 
        status.show()
429
 
        gtk.main()
430
 
 
431
 
 
432
 
class cmd_gsend(GTKCommand):
433
 
    """GTK+ send merge directive.
434
 
 
435
 
    """
436
 
    def run(self):
437
 
        (br, path) = branch.Branch.open_containing(".")
438
 
        gtk = open_display()
439
 
        from bzrlib.plugins.gtk.mergedirective import SendMergeDirectiveDialog
440
 
        from StringIO import StringIO
441
 
        dialog = SendMergeDirectiveDialog(br)
442
 
        if dialog.run() == gtk.RESPONSE_OK:
443
 
            outf = StringIO()
444
 
            outf.writelines(dialog.get_merge_directive().to_lines())
445
 
            mail_client = br.get_config().get_mail_client()
446
 
            mail_client.compose_merge_request(dialog.get_mail_to(), "[MERGE]", 
447
 
                outf.getvalue())
448
 
 
449
 
            
450
 
 
451
 
 
452
 
class cmd_gconflicts(GTKCommand):
453
 
    """GTK+ conflicts.
454
 
    
455
 
    Select files from the list of conflicts and run an external utility to
456
 
    resolve them.
457
 
    """
458
 
    def run(self):
459
 
        (wt, path) = workingtree.WorkingTree.open_containing('.')
460
 
        open_display()
461
 
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
462
 
        dialog = ConflictsDialog(wt)
463
 
        dialog.run()
464
 
 
465
 
 
466
 
class cmd_gpreferences(GTKCommand):
467
 
    """ GTK+ preferences dialog.
468
 
 
469
 
    """
470
 
    def run(self):
471
 
        open_display()
472
 
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
473
 
        dialog = PreferencesWindow()
474
 
        dialog.run()
475
 
 
476
 
 
477
 
class cmd_ginfo(Command):
478
 
    """ GTK+ info dialog
479
 
    
480
 
    """
481
 
    def run(self):
482
 
        from bzrlib import workingtree
483
 
        from bzrlib.plugins.gtk.olive.info import InfoDialog
484
 
        wt = workingtree.WorkingTree.open_containing('.')[0]
485
 
        info = InfoDialog(wt.branch)
486
 
        info.display()
487
 
        info.window.run()
488
 
 
489
 
 
490
 
class cmd_gmerge(Command):
491
 
    """ GTK+ merge dialog
492
 
    
493
 
    """
494
 
    takes_args = ["merge_from_path?"]
495
 
    def run(self, merge_from_path=None):
496
 
        from bzrlib import workingtree
497
 
        from bzrlib.plugins.gtk.dialog import error_dialog
498
 
        from bzrlib.plugins.gtk.merge import MergeDialog
499
 
        
500
 
        (wt, path) = workingtree.WorkingTree.open_containing('.')
501
 
        old_tree = wt.branch.repository.revision_tree(wt.branch.last_revision())
502
 
        delta = wt.changes_from(old_tree)
503
 
        if len(delta.added) or len(delta.removed) or len(delta.renamed) or len(delta.modified):
504
 
            error_dialog(_i18n('There are local changes in the branch'),
505
 
                         _i18n('Please commit or revert the changes before merging.'))
506
 
        else:
507
 
            parent_branch_path = wt.branch.get_parent()
508
 
            merge = MergeDialog(wt, path, parent_branch_path)
509
 
            response = merge.run()
510
 
            merge.destroy()
511
 
 
512
 
 
513
 
class cmd_gmissing(Command):
514
 
    """ GTK+ missing revisions dialog.
515
 
 
516
 
    """
517
 
    takes_args = ["other_branch?"]
518
 
    def run(self, other_branch=None):
519
 
        pygtk = import_pygtk()
520
 
        try:
521
 
            import gtk
522
 
        except RuntimeError, e:
523
 
            if str(e) == "could not open display":
524
 
                raise NoDisplayError
525
 
 
526
 
        from bzrlib.plugins.gtk.missing import MissingWindow
527
 
        from bzrlib.branch import Branch
528
 
 
529
 
        local_branch = Branch.open_containing(".")[0]
530
 
        if other_branch is None:
531
 
            other_branch = local_branch.get_parent()
532
 
            
533
 
            if other_branch is None:
534
 
                raise errors.BzrCommandError("No peer location known or specified.")
535
 
        remote_branch = Branch.open_containing(other_branch)[0]
536
 
        set_ui_factory()
537
 
        local_branch.lock_read()
538
 
        try:
539
 
            remote_branch.lock_read()
540
 
            try:
541
 
                dialog = MissingWindow(local_branch, remote_branch)
542
 
                dialog.run()
543
 
            finally:
544
 
                remote_branch.unlock()
545
 
        finally:
546
 
            local_branch.unlock()
547
 
 
548
 
 
549
 
class cmd_ginit(GTKCommand):
550
 
    def run(self):
551
 
        open_display()
552
 
        from initialize import InitDialog
553
 
        dialog = InitDialog(os.path.abspath(os.path.curdir))
554
 
        dialog.run()
555
 
 
556
 
 
557
 
class cmd_gtags(GTKCommand):
558
 
    def run(self):
559
 
        br = branch.Branch.open_containing('.')[0]
560
 
        
561
 
        gtk = open_display()
562
 
        from tags import TagsWindow
563
 
        window = TagsWindow(br)
564
 
        window.show()
565
 
        gtk.main()
566
 
 
567
 
 
568
 
commands = [
569
 
    cmd_gannotate, 
570
 
    cmd_gbranch,
571
 
    cmd_gcheckout, 
572
 
    cmd_gcommit, 
573
 
    cmd_gconflicts, 
574
 
    cmd_gdiff,
575
 
    cmd_ginit,
576
 
    cmd_ginfo,
577
 
    cmd_gmerge,
578
 
    cmd_gmissing, 
579
 
    cmd_gpreferences, 
580
 
    cmd_gpush, 
581
 
    cmd_gsend,
582
 
    cmd_gstatus,
583
 
    cmd_gtags,
584
 
    cmd_visualise
585
 
    ]
 
106
commands = {
 
107
    "gannotate": ["gblame", "gpraise"],
 
108
    "gbranch": [],
 
109
    "gcheckout": [], 
 
110
    "gcommit": ["gci"], 
 
111
    "gconflicts": [], 
 
112
    "gdiff": [],
 
113
    "ginit": [],
 
114
    "ginfo": [],
 
115
    "gmerge": [],
 
116
    "gmissing": [], 
 
117
    "gpreferences": [], 
 
118
    "gpush": [], 
 
119
    "gselftest": [],
 
120
    "gsend": [],
 
121
    "gstatus": ["gst"],
 
122
    "gtags": [],
 
123
    "visualise": ["visualize", "vis", "viz"],
 
124
    }
586
125
 
587
126
try:
588
127
    from bzrlib.plugins import loom
589
128
except ImportError:
590
129
    pass # Loom plugin doesn't appear to be present
591
130
else:
592
 
    commands.append(cmd_gloom)
593
 
 
594
 
for cmd in commands:
595
 
    register_command(cmd)
596
 
 
597
 
 
598
 
class cmd_gselftest(GTKCommand):
599
 
    """Version of selftest that displays a notification at the end"""
600
 
 
601
 
    takes_args = builtins.cmd_selftest.takes_args
602
 
    takes_options = builtins.cmd_selftest.takes_options
603
 
    _see_also = ['selftest']
604
 
 
605
 
    def run(self, *args, **kwargs):
606
 
        import cgi
607
 
        import sys
608
 
        default_encoding = sys.getdefaultencoding()
609
 
        # prevent gtk from blowing up later
610
 
        gtk = import_pygtk()
611
 
        # prevent gtk from messing with default encoding
612
 
        import pynotify
613
 
        if sys.getdefaultencoding() != default_encoding:
614
 
            reload(sys)
615
 
            sys.setdefaultencoding(default_encoding)
616
 
        result = builtins.cmd_selftest().run(*args, **kwargs)
617
 
        if result == 0:
618
 
            summary = 'Success'
619
 
            body = 'Selftest succeeded in "%s"' % os.getcwd()
620
 
        if result == 1:
621
 
            summary = 'Failure'
622
 
            body = 'Selftest failed in "%s"' % os.getcwd()
623
 
        pynotify.init("bzr gselftest")
624
 
        note = pynotify.Notification(cgi.escape(summary), cgi.escape(body))
625
 
        note.set_timeout(pynotify.EXPIRES_NEVER)
626
 
        note.show()
627
 
 
628
 
 
629
 
register_command(cmd_gselftest)
 
131
    commands["gloom"] = []
 
132
 
 
133
for cmd, aliases in commands.iteritems():
 
134
    plugin_cmds.register_lazy("cmd_%s" % cmd, aliases, "bzrlib.plugins.gtk.commands")
630
135
 
631
136
 
632
137
import gettext
636
141
# uses of '_' as an anonymous variable (think pdb for one).
637
142
_i18n = gettext.gettext
638
143
 
639
 
class NoDisplayError(BzrCommandError):
 
144
class NoDisplayError(errors.BzrCommandError):
640
145
    """gtk could not find a proper display"""
641
146
 
642
147
    def __str__(self):