/b-gtk/fix-viz

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

« back to all changes in this revision

Viewing changes to __init__.py

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
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
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, 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)
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
    merge_directive,
 
81
    workingtree,
 
82
    )
 
83
""")
 
84
 
60
85
from bzrlib.commands import Command, register_command, display_command
61
86
from bzrlib.errors import NotVersionedError, BzrCommandError, NoSuchFile
62
 
from bzrlib.commands import Command, register_command
63
87
from bzrlib.option import Option
64
 
from bzrlib.branch import Branch
65
 
from bzrlib.workingtree import WorkingTree
66
 
from bzrlib.bzrdir import BzrDir
67
88
 
68
89
import os.path
69
90
 
77
98
 
78
99
 
79
100
def set_ui_factory():
80
 
    pygtk = import_pygtk()
 
101
    import_pygtk()
81
102
    from ui import GtkUIFactory
82
103
    import bzrlib.ui
83
104
    bzrlib.ui.ui_factory = GtkUIFactory()
84
105
 
85
106
 
86
 
class cmd_gbranch(Command):
 
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):
87
146
    """GTK+ branching.
88
147
    
89
148
    """
90
149
 
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
 
 
 
150
    def get_gtk_dialog(self, path):
99
151
        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):
 
152
        return BranchDialog(path)
 
153
 
 
154
 
 
155
class cmd_gcheckout(GTKCommand):
108
156
    """ GTK+ checkout.
109
157
    
110
158
    """
111
159
    
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
 
 
 
160
    def get_gtk_dialog(self, path):
120
161
        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):
 
162
        return CheckoutDialog(path)
 
163
 
 
164
 
 
165
 
 
166
class cmd_gpush(GTKCommand):
129
167
    """ GTK+ push.
130
168
    
131
169
    """
132
170
    takes_args = [ "location?" ]
133
 
    
 
171
 
134
172
    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
 
 
 
173
        (br, path) = branch.Branch.open_containing(location)
 
174
        open_display()
144
175
        from push import PushDialog
145
 
 
146
 
        set_ui_factory()
147
 
        dialog = PushDialog(branch)
 
176
        dialog = PushDialog(br.repository, br.last_revision(), br)
148
177
        dialog.run()
149
178
 
150
 
register_command(cmd_gpush)
151
 
 
152
 
class cmd_gdiff(Command):
 
179
 
 
180
 
 
181
class cmd_gdiff(GTKCommand):
153
182
    """Show differences in working tree in a GTK+ Window.
154
183
    
155
184
    Otherwise, all changes for the tree are listed.
160
189
    @display_command
161
190
    def run(self, revision=None, filename=None):
162
191
        set_ui_factory()
163
 
        wt = WorkingTree.open_containing(".")[0]
164
 
        branch = wt.branch
165
 
        if revision is not None:
166
 
            if len(revision) == 1:
 
192
        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:
167
207
                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)
 
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
 
199
240
 
200
241
class cmd_visualise(Command):
201
242
    """Graphically visualise this branch.
208
249
    """
209
250
    takes_options = [
210
251
        "revision",
211
 
        Option('limit', "maximum number of revisions to display",
 
252
        Option('limit', "Maximum number of revisions to display.",
212
253
               int, 'count')]
213
 
    takes_args = [ "location?" ]
 
254
    takes_args = [ "locations*" ]
214
255
    aliases = [ "visualize", "vis", "viz" ]
215
256
 
216
 
    def run(self, location=".", revision=None, limit=None):
 
257
    def run(self, locations_list, revision=None, limit=None):
217
258
        set_ui_factory()
218
 
        (branch, path) = Branch.open_containing(location)
219
 
        branch.lock_read()
220
 
        branch.repository.lock_read()
221
 
        try:
 
259
        if locations_list is None:
 
260
            locations_list = ["."]
 
261
        revids = []
 
262
        for location in locations_list:
 
263
            (br, path) = branch.Branch.open_containing(location)
222
264
            if revision is None:
223
 
                revid = branch.last_revision()
224
 
                if revid is None:
225
 
                    return
 
265
                revids.append(br.last_revision())
226
266
            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):
 
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):
242
276
    """GTK+ annotate.
243
277
    
244
278
    Browse changes to FILENAME line by line in a GTK+ window.
246
280
 
247
281
    takes_args = ["filename", "line?"]
248
282
    takes_options = [
249
 
        Option("all", help="show annotations on all lines"),
250
 
        Option("plain", help="don't highlight annotation lines"),
 
283
        Option("all", help="Show annotations on all lines."),
 
284
        Option("plain", help="Don't highlight annotation lines."),
251
285
        Option("line", type=int, argname="lineno",
252
 
               help="jump to specified line number"),
 
286
               help="Jump to specified line number."),
253
287
        "revision",
254
288
    ]
255
289
    aliases = ["gblame", "gpraise"]
256
290
    
257
291
    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()
 
292
        gtk = open_display()
266
293
 
267
294
        try:
268
295
            line = int(line)
272
299
 
273
300
        from annotate.gannotate import GAnnotateWindow
274
301
        from annotate.config import GAnnotateConfig
 
302
        from bzrlib.bzrdir import BzrDir
275
303
 
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()
 
304
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
 
305
        if wt is not None:
 
306
            tree = wt
 
307
        else:
 
308
            tree = br.basis_tree()
282
309
 
283
310
        file_id = tree.path2id(path)
284
311
 
287
314
        if revision is not None:
288
315
            if len(revision) != 1:
289
316
                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)
 
317
            revision_id = revision[0].as_revision_id(br)
 
318
            tree = br.repository.revision_tree(revision_id)
292
319
        else:
293
320
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
294
321
 
295
 
        window = GAnnotateWindow(all, plain)
 
322
        window = GAnnotateWindow(all, plain, branch=br)
296
323
        window.connect("destroy", lambda w: gtk.main_quit())
297
 
        window.set_title(path + " - gannotate")
298
324
        config = GAnnotateConfig(window)
299
325
        window.show()
300
 
        branch.lock_read()
 
326
        br.lock_read()
 
327
        if wt is not None:
 
328
            wt.lock_read()
301
329
        try:
302
 
            window.annotate(tree, branch, file_id)
 
330
            window.annotate(tree, br, file_id)
 
331
            window.jump_to_line(line)
 
332
            gtk.main()
303
333
        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):
 
334
            br.unlock()
 
335
            if wt is not None:
 
336
                wt.unlock()
 
337
 
 
338
 
 
339
 
 
340
class cmd_gcommit(GTKCommand):
312
341
    """GTK+ commit dialog
313
342
 
314
343
    Graphical user interface for committing revisions"""
315
 
    
 
344
 
316
345
    aliases = [ "gci" ]
317
346
    takes_args = []
318
347
    takes_options = []
319
348
 
320
349
    def run(self, filename=None):
321
350
        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()
 
351
        open_display()
331
352
        from commit import CommitDialog
332
 
        from bzrlib.commit import Commit
333
353
        from bzrlib.errors import (BzrCommandError,
334
354
                                   NotBranchError,
335
 
                                   NoWorkingTree,
336
 
                                   PointlessCommit,
337
 
                                   ConflictsInTree,
338
 
                                   StrictCommitFailed)
 
355
                                   NoWorkingTree)
339
356
 
340
357
        wt = None
341
 
        branch = None
 
358
        br = None
342
359
        try:
343
 
            (wt, path) = WorkingTree.open_containing(filename)
344
 
            branch = wt.branch
345
 
        except NotBranchError, e:
346
 
            path = e.path
 
360
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
 
361
            br = wt.branch
347
362
        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)
 
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):
 
381
    """GTK+ status dialog
 
382
 
 
383
    Graphical user interface for showing status 
 
384
    information."""
 
385
    
 
386
    aliases = [ "gst" ]
 
387
    takes_args = ['PATH?']
 
388
    takes_options = ['revision']
 
389
 
 
390
    def run(self, path='.', revision=None):
 
391
        import os
 
392
        gtk = open_display()
 
393
        from status import StatusDialog
 
394
        (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)
 
406
        status.connect("destroy", gtk.main_quit)
 
407
        status.run()
 
408
 
 
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.
 
432
    
 
433
    Select files from the list of conflicts and run an external utility to
 
434
    resolve them.
 
435
    """
 
436
    def run(self):
 
437
        (wt, path) = workingtree.WorkingTree.open_containing('.')
 
438
        open_display()
 
439
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
 
440
        dialog = ConflictsDialog(wt)
 
441
        dialog.run()
 
442
 
 
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
 
 
651
 
 
652
import gettext
 
653
gettext.install('olive-gtk')
 
654
 
 
655
# Let's create a specialized alias to protect '_' from being erased by other
 
656
# uses of '_' as an anonymous variable (think pdb for one).
 
657
_i18n = gettext.gettext
359
658
 
360
659
class NoDisplayError(BzrCommandError):
361
660
    """gtk could not find a proper display"""
363
662
    def __str__(self):
364
663
        return "No DISPLAY. Unable to run GTK+ application."
365
664
 
 
665
 
366
666
def test_suite():
367
667
    from unittest import TestSuite
368
668
    import tests
369
 
    result = TestSuite()
370
 
    result.addTest(tests.test_suite())
 
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)
371
682
    return result