/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz

« back to all changes in this revision

Viewing changes to __init__.py

  • Committer: Jelmer Vernooij
  • Date: 2007-03-06 13:48:35 UTC
  • mfrom: (157.1.9 trunk)
  • Revision ID: jelmer@samba.org-20070306134835-4e3gg9sq0ovvzwad
Merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
# along with this program; if not, write to the Free Software
13
13
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
14
14
 
15
 
"""Graphical support for Bazaar using GTK.
16
 
 
17
 
This plugin includes:
18
 
gannotate         GTK+ annotate. 
19
 
gbranch           GTK+ branching. 
20
 
gcheckout         GTK+ checkout. 
21
 
gcommit           GTK+ commit dialog.
22
 
gconflicts        GTK+ conflicts. 
23
 
gdiff             Show differences in working tree in a GTK+ Window. 
24
 
ginit             Initialise a new branch.
25
 
gmerge            GTK+ merge dialog
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
 
15
"""GTK+ frontends to Bazaar commands """
36
16
 
37
17
import bzrlib
38
18
 
39
 
version_info = (0, 95, 0, 'dev', 1)
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, 3)
 
19
__version__ = '0.15.0'
 
20
version_info = tuple(int(n) for n in __version__.split('.'))
 
21
 
48
22
 
49
23
def check_bzrlib_version(desired):
50
24
    """Check that bzrlib is compatible.
51
25
 
52
26
    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.
53
30
    """
 
31
    desired_plus = (desired[0], desired[1]+1)
54
32
    bzrlib_version = bzrlib.version_info[:2]
 
33
    if bzrlib_version == desired:
 
34
        return
55
35
    try:
56
36
        from bzrlib.trace import warning
57
37
    except ImportError:
58
38
        # get the message out any way we can
59
39
        from warnings import warn as warning
60
40
    if bzrlib_version < desired:
61
 
        from bzrlib.errors import BzrError
62
 
        warning('Installed Bazaar version %s is too old to be used with bzr-gtk'
 
41
        warning('Installed bzr version %s is too old to be used with bzr-gtk'
63
42
                ' %s.' % (bzrlib.__version__, __version__))
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)
 
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])
69
54
 
70
55
from bzrlib.trace import warning
71
56
if __name__ != 'bzrlib.plugins.gtk':
75
60
lazy_import(globals(), """
76
61
from bzrlib import (
77
62
    branch,
78
 
    builtins,
79
63
    errors,
80
 
    merge_directive,
81
64
    workingtree,
82
65
    )
83
66
""")
84
67
 
85
68
from bzrlib.commands import Command, register_command, display_command
86
69
from bzrlib.errors import NotVersionedError, BzrCommandError, NoSuchFile
 
70
from bzrlib.commands import Command, register_command
87
71
from bzrlib.option import Option
 
72
from bzrlib.bzrdir import BzrDir
88
73
 
89
74
import os.path
90
75
 
98
83
 
99
84
 
100
85
def set_ui_factory():
101
 
    import_pygtk()
 
86
    pygtk = import_pygtk()
102
87
    from ui import GtkUIFactory
103
88
    import bzrlib.ui
104
89
    bzrlib.ui.ui_factory = GtkUIFactory()
105
90
 
106
91
 
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
 
 
135
 
 
136
 
class GTKCommand(Command):
137
 
    """Abstract class providing GTK specific run commands."""
138
 
 
139
 
    def run(self):
140
 
        open_display()
141
 
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
142
 
        dialog.run()
143
 
 
144
 
 
145
 
class cmd_gbranch(GTKCommand):
 
92
class cmd_gbranch(Command):
146
93
    """GTK+ branching.
147
94
    
148
95
    """
149
96
 
150
 
    def get_gtk_dialog(self, path):
 
97
    def run(self):
 
98
        pygtk = import_pygtk()
 
99
        try:
 
100
            import gtk
 
101
        except RuntimeError, e:
 
102
            if str(e) == "could not open display":
 
103
                raise NoDisplayError
 
104
 
151
105
        from bzrlib.plugins.gtk.branch import BranchDialog
152
 
        return BranchDialog(path)
153
 
 
154
 
 
155
 
class cmd_gcheckout(GTKCommand):
 
106
 
 
107
        set_ui_factory()
 
108
        dialog = BranchDialog(os.path.abspath('.'))
 
109
        dialog.run()
 
110
 
 
111
register_command(cmd_gbranch)
 
112
 
 
113
class cmd_gcheckout(Command):
156
114
    """ GTK+ checkout.
157
115
    
158
116
    """
159
117
    
160
 
    def get_gtk_dialog(self, path):
 
118
    def run(self):
 
119
        pygtk = import_pygtk()
 
120
        try:
 
121
            import gtk
 
122
        except RuntimeError, e:
 
123
            if str(e) == "could not open display":
 
124
                raise NoDisplayError
 
125
 
161
126
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
162
 
        return CheckoutDialog(path)
163
 
 
164
 
 
165
 
 
166
 
class cmd_gpush(GTKCommand):
 
127
 
 
128
        set_ui_factory()
 
129
        dialog = CheckoutDialog(os.path.abspath('.'))
 
130
        dialog.run()
 
131
 
 
132
register_command(cmd_gcheckout)
 
133
 
 
134
class cmd_gpush(Command):
167
135
    """ GTK+ push.
168
136
    
169
137
    """
171
139
 
172
140
    def run(self, location="."):
173
141
        (br, path) = branch.Branch.open_containing(location)
174
 
        open_display()
 
142
 
 
143
        pygtk = import_pygtk()
 
144
        try:
 
145
            import gtk
 
146
        except RuntimeError, e:
 
147
            if str(e) == "could not open display":
 
148
                raise NoDisplayError
 
149
 
175
150
        from push import PushDialog
176
 
        dialog = PushDialog(br.repository, br.last_revision(), br)
 
151
 
 
152
        set_ui_factory()
 
153
        dialog = PushDialog(br)
177
154
        dialog.run()
178
155
 
179
 
 
180
 
 
181
 
class cmd_gdiff(GTKCommand):
 
156
register_command(cmd_gpush)
 
157
 
 
158
class cmd_gdiff(Command):
182
159
    """Show differences in working tree in a GTK+ Window.
183
160
    
184
161
    Otherwise, all changes for the tree are listed.
190
167
    def run(self, revision=None, filename=None):
191
168
        set_ui_factory()
192
169
        wt = workingtree.WorkingTree.open_containing(".")[0]
193
 
        wt.lock_read()
194
 
        try:
195
 
            branch = wt.branch
196
 
            if revision is not None:
197
 
                if len(revision) == 1:
198
 
                    tree1 = wt
199
 
                    revision_id = revision[0].as_revision_id(tree1.branch)
200
 
                    tree2 = branch.repository.revision_tree(revision_id)
201
 
                elif len(revision) == 2:
202
 
                    revision_id_0 = revision[0].as_revision_id(branch)
203
 
                    tree2 = branch.repository.revision_tree(revision_id_0)
204
 
                    revision_id_1 = revision[1].as_revision_id(branch)
205
 
                    tree1 = branch.repository.revision_tree(revision_id_1)
206
 
            else:
 
170
        branch = wt.branch
 
171
        if revision is not None:
 
172
            if len(revision) == 1:
207
173
                tree1 = wt
208
 
                tree2 = tree1.basis_tree()
209
 
 
210
 
            from diff import DiffWindow
211
 
            import gtk
212
 
            window = DiffWindow()
213
 
            window.connect("destroy", gtk.main_quit)
214
 
            window.set_diff("Working Tree", tree1, tree2)
215
 
            if filename is not None:
216
 
                tree_filename = wt.relpath(filename)
217
 
                try:
218
 
                    window.set_file(tree_filename)
219
 
                except NoSuchFile:
220
 
                    if (tree1.path2id(tree_filename) is None and 
221
 
                        tree2.path2id(tree_filename) is None):
222
 
                        raise NotVersionedError(filename)
223
 
                    raise BzrCommandError('No changes found for file "%s"' % 
224
 
                                          filename)
225
 
            window.show()
226
 
 
227
 
            gtk.main()
228
 
        finally:
229
 
            wt.unlock()
230
 
 
231
 
 
232
 
def start_viz_window(branch, revisions, limit=None):
233
 
    """Start viz on branch with revision revision.
234
 
    
235
 
    :return: The viz window object.
236
 
    """
237
 
    from viz import BranchWindow
238
 
    return BranchWindow(branch, revisions, limit)
239
 
 
 
174
                revision_id = revision[0].in_history(branch).rev_id
 
175
                tree2 = branch.repository.revision_tree(revision_id)
 
176
            elif len(revision) == 2:
 
177
                revision_id_0 = revision[0].in_history(branch).rev_id
 
178
                tree2 = branch.repository.revision_tree(revision_id_0)
 
179
                revision_id_1 = revision[1].in_history(branch).rev_id
 
180
                tree1 = branch.repository.revision_tree(revision_id_1)
 
181
        else:
 
182
            tree1 = wt
 
183
            tree2 = tree1.basis_tree()
 
184
 
 
185
        from diff import DiffWindow
 
186
        import gtk
 
187
        window = DiffWindow()
 
188
        window.connect("destroy", gtk.main_quit)
 
189
        window.set_diff("Working Tree", tree1, tree2)
 
190
        if filename is not None:
 
191
            tree_filename = wt.relpath(filename)
 
192
            try:
 
193
                window.set_file(tree_filename)
 
194
            except NoSuchFile:
 
195
                if (tree1.inventory.path2id(tree_filename) is None and 
 
196
                    tree2.inventory.path2id(tree_filename) is None):
 
197
                    raise NotVersionedError(filename)
 
198
                raise BzrCommandError('No changes found for file "%s"' % 
 
199
                                      filename)
 
200
        window.show()
 
201
 
 
202
        gtk.main()
 
203
 
 
204
register_command(cmd_gdiff)
240
205
 
241
206
class cmd_visualise(Command):
242
207
    """Graphically visualise this branch.
249
214
    """
250
215
    takes_options = [
251
216
        "revision",
252
 
        Option('limit', "Maximum number of revisions to display.",
 
217
        Option('limit', "maximum number of revisions to display",
253
218
               int, 'count')]
254
 
    takes_args = [ "locations*" ]
 
219
    takes_args = [ "location?" ]
255
220
    aliases = [ "visualize", "vis", "viz" ]
256
221
 
257
 
    def run(self, locations_list, revision=None, limit=None):
 
222
    def run(self, location=".", revision=None, limit=None):
258
223
        set_ui_factory()
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)
 
224
        (br, path) = branch.Branch.open_containing(location)
 
225
        br.lock_read()
 
226
        br.repository.lock_read()
 
227
        try:
264
228
            if revision is None:
265
 
                revids.append(br.last_revision())
 
229
                revid = br.last_revision()
 
230
                if revid is None:
 
231
                    return
266
232
            else:
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()
273
 
 
274
 
 
275
 
class cmd_gannotate(GTKCommand):
 
233
                (revno, revid) = revision[0].in_history(br)
 
234
 
 
235
            from viz.branchwin import BranchWindow
 
236
            import gtk
 
237
                
 
238
            pp = BranchWindow()
 
239
            pp.set_branch(br, revid, limit)
 
240
            pp.connect("destroy", lambda w: gtk.main_quit())
 
241
            pp.show()
 
242
            gtk.main()
 
243
        finally:
 
244
            br.repository.unlock()
 
245
            br.unlock()
 
246
 
 
247
 
 
248
register_command(cmd_visualise)
 
249
 
 
250
class cmd_gannotate(Command):
276
251
    """GTK+ annotate.
277
252
    
278
253
    Browse changes to FILENAME line by line in a GTK+ window.
280
255
 
281
256
    takes_args = ["filename", "line?"]
282
257
    takes_options = [
283
 
        Option("all", help="Show annotations on all lines."),
284
 
        Option("plain", help="Don't highlight annotation lines."),
 
258
        Option("all", help="show annotations on all lines"),
 
259
        Option("plain", help="don't highlight annotation lines"),
285
260
        Option("line", type=int, argname="lineno",
286
 
               help="Jump to specified line number."),
 
261
               help="jump to specified line number"),
287
262
        "revision",
288
263
    ]
289
264
    aliases = ["gblame", "gpraise"]
290
265
    
291
266
    def run(self, filename, all=False, plain=False, line='1', revision=None):
292
 
        gtk = open_display()
 
267
        pygtk = import_pygtk()
 
268
 
 
269
        try:
 
270
            import gtk
 
271
        except RuntimeError, e:
 
272
            if str(e) == "could not open display":
 
273
                raise NoDisplayError
 
274
        set_ui_factory()
293
275
 
294
276
        try:
295
277
            line = int(line)
299
281
 
300
282
        from annotate.gannotate import GAnnotateWindow
301
283
        from annotate.config import GAnnotateConfig
302
 
        from bzrlib.bzrdir import BzrDir
303
284
 
304
 
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
305
 
        if wt is not None:
306
 
            tree = wt
307
 
        else:
 
285
        try:
 
286
            (tree, path) = workingtree.WorkingTree.open_containing(filename)
 
287
            br = tree.branch
 
288
        except errors.NoWorkingTree:
 
289
            (br, path) = branch.Branch.open_containing(filename)
308
290
            tree = br.basis_tree()
309
291
 
310
292
        file_id = tree.path2id(path)
314
296
        if revision is not None:
315
297
            if len(revision) != 1:
316
298
                raise BzrCommandError("Only 1 revion may be specified.")
317
 
            revision_id = revision[0].as_revision_id(br)
 
299
            revision_id = revision[0].in_history(br).rev_id
318
300
            tree = br.repository.revision_tree(revision_id)
319
301
        else:
320
302
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
321
303
 
322
 
        window = GAnnotateWindow(all, plain, branch=br)
 
304
        window = GAnnotateWindow(all, plain)
323
305
        window.connect("destroy", lambda w: gtk.main_quit())
 
306
        window.set_title(path + " - gannotate")
324
307
        config = GAnnotateConfig(window)
325
308
        window.show()
326
309
        br.lock_read()
327
 
        if wt is not None:
328
 
            wt.lock_read()
329
310
        try:
330
311
            window.annotate(tree, br, file_id)
331
 
            window.jump_to_line(line)
332
 
            gtk.main()
333
312
        finally:
334
313
            br.unlock()
335
 
            if wt is not None:
336
 
                wt.unlock()
337
 
 
338
 
 
339
 
 
340
 
class cmd_gcommit(GTKCommand):
 
314
        window.jump_to_line(line)
 
315
        
 
316
        gtk.main()
 
317
 
 
318
register_command(cmd_gannotate)
 
319
 
 
320
class cmd_gcommit(Command):
341
321
    """GTK+ commit dialog
342
322
 
343
323
    Graphical user interface for committing revisions"""
344
 
 
 
324
    
345
325
    aliases = [ "gci" ]
346
326
    takes_args = []
347
327
    takes_options = []
348
328
 
349
329
    def run(self, filename=None):
350
330
        import os
351
 
        open_display()
 
331
        pygtk = import_pygtk()
 
332
 
 
333
        try:
 
334
            import gtk
 
335
        except RuntimeError, e:
 
336
            if str(e) == "could not open display":
 
337
                raise NoDisplayError
 
338
 
 
339
        set_ui_factory()
352
340
        from commit import CommitDialog
 
341
        from bzrlib.commit import Commit
353
342
        from bzrlib.errors import (BzrCommandError,
354
343
                                   NotBranchError,
355
 
                                   NoWorkingTree)
 
344
                                   NoWorkingTree,
 
345
                                   PointlessCommit,
 
346
                                   ConflictsInTree,
 
347
                                   StrictCommitFailed)
356
348
 
357
349
        wt = None
358
350
        br = None
359
351
        try:
360
352
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
361
353
            br = wt.branch
 
354
        except NotBranchError, e:
 
355
            path = e.path
362
356
        except NoWorkingTree, e:
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()
378
 
 
379
 
 
380
 
class cmd_gstatus(GTKCommand):
 
357
            path = e.base
 
358
            try:
 
359
                (br, path) = branch.Branch.open_containing(path)
 
360
            except NotBranchError, e:
 
361
                path = e.path
 
362
 
 
363
 
 
364
        commit = CommitDialog(wt, path, not br)
 
365
        commit.run()
 
366
 
 
367
register_command(cmd_gcommit)
 
368
 
 
369
class cmd_gstatus(Command):
381
370
    """GTK+ status dialog
382
371
 
383
372
    Graphical user interface for showing status 
385
374
    
386
375
    aliases = [ "gst" ]
387
376
    takes_args = ['PATH?']
388
 
    takes_options = ['revision']
 
377
    takes_options = []
389
378
 
390
 
    def run(self, path='.', revision=None):
 
379
    def run(self, path='.'):
391
380
        import os
392
 
        gtk = open_display()
 
381
        pygtk = import_pygtk()
 
382
 
 
383
        try:
 
384
            import gtk
 
385
        except RuntimeError, e:
 
386
            if str(e) == "could not open display":
 
387
                raise NoDisplayError
 
388
 
 
389
        set_ui_factory()
393
390
        from status import StatusDialog
394
391
        (wt, wt_path) = workingtree.WorkingTree.open_containing(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)
 
392
        status = StatusDialog(wt, wt_path)
406
393
        status.connect("destroy", gtk.main_quit)
407
394
        status.run()
408
395
 
409
 
 
410
 
class cmd_gsend(GTKCommand):
411
 
    """GTK+ send merge directive.
412
 
 
413
 
    """
414
 
    def run(self):
415
 
        (br, path) = branch.Branch.open_containing(".")
416
 
        gtk = open_display()
417
 
        from bzrlib.plugins.gtk.mergedirective import SendMergeDirectiveDialog
418
 
        from StringIO import StringIO
419
 
        dialog = SendMergeDirectiveDialog(br)
420
 
        if dialog.run() == gtk.RESPONSE_OK:
421
 
            outf = StringIO()
422
 
            outf.writelines(dialog.get_merge_directive().to_lines())
423
 
            mail_client = br.get_config().get_mail_client()
424
 
            mail_client.compose_merge_request(dialog.get_mail_to(), "[MERGE]", 
425
 
                outf.getvalue())
426
 
 
427
 
            
428
 
 
429
 
 
430
 
class cmd_gconflicts(GTKCommand):
431
 
    """GTK+ conflicts.
 
396
register_command(cmd_gstatus)
 
397
 
 
398
class cmd_gconflicts(Command):
 
399
    """ GTK+ push.
432
400
    
433
 
    Select files from the list of conflicts and run an external utility to
434
 
    resolve them.
435
401
    """
436
402
    def run(self):
437
403
        (wt, path) = workingtree.WorkingTree.open_containing('.')
438
 
        open_display()
 
404
        
 
405
        pygtk = import_pygtk()
 
406
        try:
 
407
            import gtk
 
408
        except RuntimeError, e:
 
409
            if str(e) == "could not open display":
 
410
                raise NoDisplayError
 
411
 
439
412
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
 
413
 
 
414
        set_ui_factory()
440
415
        dialog = ConflictsDialog(wt)
441
416
        dialog.run()
442
417
 
443
 
 
444
 
class cmd_gpreferences(GTKCommand):
445
 
    """ GTK+ preferences dialog.
446
 
 
447
 
    """
448
 
    def run(self):
449
 
        open_display()
450
 
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
451
 
        dialog = PreferencesWindow()
452
 
        dialog.run()
453
 
 
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
 
 
478
 
class cmd_gmissing(Command):
479
 
    """ GTK+ missing revisions dialog.
480
 
 
481
 
    """
482
 
    takes_args = ["other_branch?"]
483
 
    def run(self, other_branch=None):
484
 
        pygtk = import_pygtk()
485
 
        try:
486
 
            import gtk
487
 
        except RuntimeError, e:
488
 
            if str(e) == "could not open display":
489
 
                raise NoDisplayError
490
 
 
491
 
        from bzrlib.plugins.gtk.missing import MissingWindow
492
 
        from bzrlib.branch import Branch
493
 
 
494
 
        local_branch = Branch.open_containing(".")[0]
495
 
        if other_branch is None:
496
 
            other_branch = local_branch.get_parent()
497
 
            
498
 
            if other_branch is None:
499
 
                raise errors.BzrCommandError("No peer location known or specified.")
500
 
        remote_branch = Branch.open_containing(other_branch)[0]
501
 
        set_ui_factory()
502
 
        local_branch.lock_read()
503
 
        try:
504
 
            remote_branch.lock_read()
505
 
            try:
506
 
                dialog = MissingWindow(local_branch, remote_branch)
507
 
                dialog.run()
508
 
            finally:
509
 
                remote_branch.unlock()
510
 
        finally:
511
 
            local_branch.unlock()
512
 
 
513
 
 
514
 
class cmd_ginit(GTKCommand):
515
 
    def run(self):
516
 
        open_display()
517
 
        from initialize import InitDialog
518
 
        dialog = InitDialog(os.path.abspath(os.path.curdir))
519
 
        dialog.run()
520
 
 
521
 
 
522
 
class cmd_gtags(GTKCommand):
523
 
    def run(self):
524
 
        br = branch.Branch.open_containing('.')[0]
525
 
        
526
 
        gtk = open_display()
527
 
        from tags import TagsWindow
528
 
        window = TagsWindow(br)
529
 
        window.show()
530
 
        gtk.main()
531
 
 
532
 
 
533
 
commands = [
534
 
    cmd_gannotate, 
535
 
    cmd_gbranch,
536
 
    cmd_gcheckout, 
537
 
    cmd_gcommit, 
538
 
    cmd_gconflicts, 
539
 
    cmd_gdiff,
540
 
    cmd_ginit,
541
 
    cmd_gmerge,
542
 
    cmd_gmissing, 
543
 
    cmd_gpreferences, 
544
 
    cmd_gpush, 
545
 
    cmd_gsend,
546
 
    cmd_gstatus,
547
 
    cmd_gtags,
548
 
    cmd_visualise
549
 
    ]
550
 
 
551
 
for cmd in commands:
552
 
    register_command(cmd)
553
 
 
554
 
 
555
 
class cmd_gselftest(GTKCommand):
556
 
    """Version of selftest that displays a notification at the end"""
557
 
 
558
 
    takes_args = builtins.cmd_selftest.takes_args
559
 
    takes_options = builtins.cmd_selftest.takes_options
560
 
    _see_also = ['selftest']
561
 
 
562
 
    def run(self, *args, **kwargs):
563
 
        import cgi
564
 
        import sys
565
 
        default_encoding = sys.getdefaultencoding()
566
 
        # prevent gtk from blowing up later
567
 
        gtk = import_pygtk()
568
 
        # prevent gtk from messing with default encoding
569
 
        import pynotify
570
 
        if sys.getdefaultencoding() != default_encoding:
571
 
            reload(sys)
572
 
            sys.setdefaultencoding(default_encoding)
573
 
        result = builtins.cmd_selftest().run(*args, **kwargs)
574
 
        if result == 0:
575
 
            summary = 'Success'
576
 
            body = 'Selftest succeeded in "%s"' % os.getcwd()
577
 
        if result == 1:
578
 
            summary = 'Failure'
579
 
            body = 'Selftest failed in "%s"' % os.getcwd()
580
 
        pynotify.init("bzr gselftest")
581
 
        note = pynotify.Notification(cgi.escape(summary), cgi.escape(body))
582
 
        note.set_timeout(pynotify.EXPIRES_NEVER)
583
 
        note.show()
584
 
 
585
 
 
586
 
register_command(cmd_gselftest)
587
 
 
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
 
 
 
418
register_command(cmd_gconflicts)
651
419
 
652
420
import gettext
653
421
gettext.install('olive-gtk')
654
422
 
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
658
 
 
659
423
class NoDisplayError(BzrCommandError):
660
424
    """gtk could not find a proper display"""
661
425
 
662
426
    def __str__(self):
663
427
        return "No DISPLAY. Unable to run GTK+ application."
664
428
 
665
 
 
666
429
def test_suite():
667
430
    from unittest import TestSuite
668
431
    import tests
669
 
    import sys
670
 
    default_encoding = sys.getdefaultencoding()
671
 
    try:
672
 
        result = TestSuite()
673
 
        try:
674
 
            import_pygtk()
675
 
        except errors.BzrCommandError:
676
 
            return result
677
 
        result.addTest(tests.test_suite())
678
 
    finally:
679
 
        if sys.getdefaultencoding() != default_encoding:
680
 
            reload(sys)
681
 
            sys.setdefaultencoding(default_encoding)
 
432
    result = TestSuite()
 
433
    result.addTest(tests.test_suite())
682
434
    return result