/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

Fix regressions in plugins tab.

Show diffs side-by-side

added added

removed removed

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