/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: Daniel Schierbeck
  • Date: 2008-01-23 16:36:21 UTC
  • mto: (423.1.8 trunk)
  • mto: This revision was merged to the branch mainline in revision 429.
  • Revision ID: daniel.schierbeck@gmail.com-20080123163621-x8kublc38ojipnly
Made the revision popup menu correctly add tags.

Show diffs side-by-side

added added

removed removed

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