/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
1
# This program is free software; you can redistribute it and/or modify
2
# it under the terms of the GNU General Public License as published by
3
# the Free Software Foundation; either version 2 of the License, or
4
# (at your option) any later version.
5
6
# This program is distributed in the hope that it will be useful,
7
# but WITHOUT ANY WARRANTY; without even the implied warranty of
8
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9
# GNU General Public License for more details.
10
11
# You should have received a copy of the GNU General Public License
12
# along with this program; if not, write to the Free Software
13
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
14
644 by Jelmer Vernooij
Fix import.
15
import os
16
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
17
from bzrlib import (
18
    branch,
19
    builtins,
20
    workingtree,
21
    )
22
from bzrlib.commands import (
23
    Command,
24
    display_command,
25
    )
26
from bzrlib.errors import (
27
    BzrCommandError,
656 by Jelmer Vernooij
Merge removal of unnecessary import from Mario and rmeove some more unnecessary imports.
28
    NoWorkingTree,
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
29
    NotVersionedError,
30
    NoSuchFile,
31
    )
32
from bzrlib.option import Option
33
34
from bzrlib.plugins.gtk import (
656 by Jelmer Vernooij
Merge removal of unnecessary import from Mario and rmeove some more unnecessary imports.
35
    _i18n,
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
36
    open_display,
37
    import_pygtk,
38
    set_ui_factory,
39
    )
40
41
class GTKCommand(Command):
42
    """Abstract class providing GTK specific run commands."""
43
44
    def run(self):
45
        open_display()
46
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
47
        dialog.run()
48
49
50
class cmd_gbranch(GTKCommand):
51
    """GTK+ branching.
52
    
53
    """
54
55
    def get_gtk_dialog(self, path):
56
        from bzrlib.plugins.gtk.branch import BranchDialog
57
        return BranchDialog(path)
58
59
60
class cmd_gcheckout(GTKCommand):
61
    """ GTK+ checkout.
62
    
63
    """
64
    
65
    def get_gtk_dialog(self, path):
66
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
67
        return CheckoutDialog(path)
68
69
70
71
class cmd_gpush(GTKCommand):
72
    """ GTK+ push.
73
    
74
    """
75
    takes_args = [ "location?" ]
76
77
    def run(self, location="."):
78
        (br, path) = branch.Branch.open_containing(location)
79
        open_display()
80
        from bzrlib.plugins.gtk.push import PushDialog
81
        dialog = PushDialog(br.repository, br.last_revision(), br)
82
        dialog.run()
83
84
85
class cmd_gloom(GTKCommand):
86
    """ GTK+ loom.
87
    
88
    """
89
    takes_args = [ "location?" ]
90
91
    def run(self, location="."):
92
        try:
93
            (tree, path) = workingtree.WorkingTree.open_containing(location)
94
            br = tree.branch
95
        except NoWorkingTree, e:
96
            (br, path) = branch.Branch.open_containing(location)
97
            tree = None
98
        open_display()
99
        from bzrlib.plugins.gtk.loom import LoomDialog
100
        dialog = LoomDialog(br, tree)
101
        dialog.run()
102
103
104
class cmd_gdiff(GTKCommand):
105
    """Show differences in working tree in a GTK+ Window.
106
    
107
    Otherwise, all changes for the tree are listed.
108
    """
109
    takes_args = ['filename?']
110
    takes_options = ['revision']
111
112
    @display_command
113
    def run(self, revision=None, filename=None):
114
        set_ui_factory()
115
        wt = workingtree.WorkingTree.open_containing(".")[0]
116
        wt.lock_read()
117
        try:
118
            branch = wt.branch
119
            if revision is not None:
120
                if len(revision) == 1:
121
                    tree1 = wt
122
                    revision_id = revision[0].as_revision_id(tree1.branch)
123
                    tree2 = branch.repository.revision_tree(revision_id)
124
                elif len(revision) == 2:
125
                    revision_id_0 = revision[0].as_revision_id(branch)
126
                    tree2 = branch.repository.revision_tree(revision_id_0)
127
                    revision_id_1 = revision[1].as_revision_id(branch)
128
                    tree1 = branch.repository.revision_tree(revision_id_1)
129
            else:
130
                tree1 = wt
131
                tree2 = tree1.basis_tree()
132
133
            from diff import DiffWindow
134
            import gtk
135
            window = DiffWindow()
136
            window.connect("destroy", gtk.main_quit)
137
            window.set_diff("Working Tree", tree1, tree2)
138
            if filename is not None:
139
                tree_filename = wt.relpath(filename)
140
                try:
141
                    window.set_file(tree_filename)
142
                except NoSuchFile:
143
                    if (tree1.path2id(tree_filename) is None and 
144
                        tree2.path2id(tree_filename) is None):
145
                        raise NotVersionedError(filename)
146
                    raise BzrCommandError('No changes found for file "%s"' % 
147
                                          filename)
148
            window.show()
149
150
            gtk.main()
151
        finally:
152
            wt.unlock()
153
154
155
def start_viz_window(branch, revisions, limit=None):
156
    """Start viz on branch with revision revision.
157
    
158
    :return: The viz window object.
159
    """
160
    from bzrlib.plugins.gtk.viz import BranchWindow
161
    return BranchWindow(branch, revisions, limit)
162
163
164
class cmd_visualise(Command):
165
    """Graphically visualise this branch.
166
167
    Opens a graphical window to allow you to see the history of the branch
168
    and relationships between revisions in a visual manner,
169
170
    The default starting point is latest revision on the branch, you can
171
    specify a starting point with -r revision.
172
    """
173
    takes_options = [
174
        "revision",
175
        Option('limit', "Maximum number of revisions to display.",
176
               int, 'count')]
177
    takes_args = [ "locations*" ]
178
    aliases = [ "visualize", "vis", "viz" ]
179
180
    def run(self, locations_list, revision=None, limit=None):
181
        set_ui_factory()
182
        if locations_list is None:
183
            locations_list = ["."]
184
        revids = []
185
        for location in locations_list:
186
            (br, path) = branch.Branch.open_containing(location)
187
            if revision is None:
188
                revids.append(br.last_revision())
189
            else:
190
                revids.append(revision[0].as_revision_id(br))
191
        import gtk
192
        pp = start_viz_window(br, revids, limit)
193
        pp.connect("destroy", lambda w: gtk.main_quit())
194
        pp.show()
195
        gtk.main()
196
197
198
class cmd_gannotate(GTKCommand):
199
    """GTK+ annotate.
200
    
201
    Browse changes to FILENAME line by line in a GTK+ window.
202
    """
203
204
    takes_args = ["filename", "line?"]
205
    takes_options = [
206
        Option("all", help="Show annotations on all lines."),
207
        Option("plain", help="Don't highlight annotation lines."),
208
        Option("line", type=int, argname="lineno",
209
               help="Jump to specified line number."),
210
        "revision",
211
    ]
212
    aliases = ["gblame", "gpraise"]
213
    
214
    def run(self, filename, all=False, plain=False, line='1', revision=None):
215
        gtk = open_display()
216
217
        try:
218
            line = int(line)
219
        except ValueError:
220
            raise BzrCommandError('Line argument ("%s") is not a number.' % 
221
                                  line)
222
223
        from annotate.gannotate import GAnnotateWindow
224
        from annotate.config import GAnnotateConfig
225
        from bzrlib.bzrdir import BzrDir
226
227
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
228
        if wt is not None:
229
            tree = wt
230
        else:
231
            tree = br.basis_tree()
232
233
        file_id = tree.path2id(path)
234
235
        if file_id is None:
236
            raise NotVersionedError(filename)
237
        if revision is not None:
238
            if len(revision) != 1:
239
                raise BzrCommandError("Only 1 revion may be specified.")
240
            revision_id = revision[0].as_revision_id(br)
241
            tree = br.repository.revision_tree(revision_id)
242
        else:
243
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
244
245
        window = GAnnotateWindow(all, plain, branch=br)
246
        window.connect("destroy", lambda w: gtk.main_quit())
247
        config = GAnnotateConfig(window)
248
        window.show()
249
        br.lock_read()
250
        if wt is not None:
251
            wt.lock_read()
252
        try:
253
            window.annotate(tree, br, file_id)
254
            window.jump_to_line(line)
255
            gtk.main()
256
        finally:
257
            br.unlock()
258
            if wt is not None:
259
                wt.unlock()
260
261
262
263
class cmd_gcommit(GTKCommand):
264
    """GTK+ commit dialog
265
266
    Graphical user interface for committing revisions"""
267
268
    aliases = [ "gci" ]
269
    takes_args = []
270
    takes_options = []
271
272
    def run(self, filename=None):
273
        open_display()
274
        from commit import CommitDialog
275
276
        wt = None
277
        br = None
278
        try:
279
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
280
            br = wt.branch
281
        except NoWorkingTree, e:
282
            from dialog import error_dialog
283
            error_dialog(_i18n('Directory does not have a working tree'),
284
                         _i18n('Operation aborted.'))
285
            return 1 # should this be retval=3?
286
287
        # It is a good habit to keep things locked for the duration, but it
288
        # could cause difficulties if someone wants to do things in another
289
        # window... We could lock_read() until we actually go to commit
290
        # changes... Just a thought.
291
        wt.lock_write()
292
        try:
293
            dlg = CommitDialog(wt)
294
            return dlg.run()
295
        finally:
296
            wt.unlock()
297
298
299
class cmd_gstatus(GTKCommand):
300
    """GTK+ status dialog
301
302
    Graphical user interface for showing status 
303
    information."""
304
305
    aliases = [ "gst" ]
306
    takes_args = ['PATH?']
307
    takes_options = ['revision']
308
309
    def run(self, path='.', revision=None):
310
        gtk = open_display()
311
        from bzrlib.plugins.gtk.status import StatusWindow
312
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
313
314
        if revision is not None:
315
            try:
316
                revision_id = revision[0].as_revision_id(wt.branch)
317
            except:
318
                from bzrlib.errors import BzrError
319
                raise BzrError('Revision %r doesn\'t exist'
320
                               % revision[0].user_spec )
321
        else:
322
            revision_id = None
323
324
        status = StatusWindow(wt, wt_path, revision_id)
325
        status.connect("destroy", gtk.main_quit)
326
        status.show()
327
        gtk.main()
328
329
330
class cmd_gsend(GTKCommand):
331
    """GTK+ send merge directive.
332
333
    """
334
    def run(self):
335
        (br, path) = branch.Branch.open_containing(".")
336
        gtk = open_display()
337
        from bzrlib.plugins.gtk.mergedirective import SendMergeDirectiveDialog
338
        from StringIO import StringIO
339
        dialog = SendMergeDirectiveDialog(br)
340
        if dialog.run() == gtk.RESPONSE_OK:
341
            outf = StringIO()
342
            outf.writelines(dialog.get_merge_directive().to_lines())
343
            mail_client = br.get_config().get_mail_client()
344
            mail_client.compose_merge_request(dialog.get_mail_to(), "[MERGE]", 
345
                outf.getvalue())
346
347
            
348
349
350
class cmd_gconflicts(GTKCommand):
351
    """GTK+ conflicts.
352
    
353
    Select files from the list of conflicts and run an external utility to
354
    resolve them.
355
    """
356
    def run(self):
357
        (wt, path) = workingtree.WorkingTree.open_containing('.')
358
        open_display()
359
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
360
        dialog = ConflictsDialog(wt)
361
        dialog.run()
362
363
364
class cmd_gpreferences(GTKCommand):
365
    """ GTK+ preferences dialog.
366
367
    """
368
    def run(self):
369
        open_display()
370
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
371
        dialog = PreferencesWindow()
372
        dialog.run()
373
374
375
class cmd_ginfo(Command):
376
    """ GTK+ info dialog
377
    
378
    """
379
    def run(self):
380
        from bzrlib import workingtree
381
        from bzrlib.plugins.gtk.olive.info import InfoDialog
382
        wt = workingtree.WorkingTree.open_containing('.')[0]
383
        info = InfoDialog(wt.branch)
384
        info.display()
385
        info.window.run()
386
387
388
class cmd_gmerge(Command):
389
    """ GTK+ merge dialog
390
    
391
    """
392
    takes_args = ["merge_from_path?"]
393
    def run(self, merge_from_path=None):
394
        from bzrlib.plugins.gtk.dialog import error_dialog
395
        from bzrlib.plugins.gtk.merge import MergeDialog
396
        
397
        (wt, path) = workingtree.WorkingTree.open_containing('.')
398
        old_tree = wt.branch.repository.revision_tree(wt.branch.last_revision())
399
        delta = wt.changes_from(old_tree)
400
        if len(delta.added) or len(delta.removed) or len(delta.renamed) or len(delta.modified):
401
            error_dialog(_i18n('There are local changes in the branch'),
402
                         _i18n('Please commit or revert the changes before merging.'))
403
        else:
404
            parent_branch_path = wt.branch.get_parent()
405
            merge = MergeDialog(wt, path, parent_branch_path)
406
            response = merge.run()
407
            merge.destroy()
408
409
410
class cmd_gmissing(Command):
411
    """ GTK+ missing revisions dialog.
412
413
    """
414
    takes_args = ["other_branch?"]
415
    def run(self, other_branch=None):
416
        pygtk = import_pygtk()
417
        try:
418
            import gtk
419
        except RuntimeError, e:
420
            if str(e) == "could not open display":
421
                raise NoDisplayError
422
423
        from bzrlib.plugins.gtk.missing import MissingWindow
424
        from bzrlib.branch import Branch
425
426
        local_branch = Branch.open_containing(".")[0]
427
        if other_branch is None:
428
            other_branch = local_branch.get_parent()
429
            
430
            if other_branch is None:
656 by Jelmer Vernooij
Merge removal of unnecessary import from Mario and rmeove some more unnecessary imports.
431
                raise BzrCommandError("No peer location known or specified.")
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
432
        remote_branch = Branch.open_containing(other_branch)[0]
433
        set_ui_factory()
434
        local_branch.lock_read()
435
        try:
436
            remote_branch.lock_read()
437
            try:
438
                dialog = MissingWindow(local_branch, remote_branch)
439
                dialog.run()
440
            finally:
441
                remote_branch.unlock()
442
        finally:
443
            local_branch.unlock()
444
445
446
class cmd_ginit(GTKCommand):
447
    def run(self):
448
        open_display()
449
        from initialize import InitDialog
450
        dialog = InitDialog(os.path.abspath(os.path.curdir))
451
        dialog.run()
452
453
454
class cmd_gtags(GTKCommand):
455
    def run(self):
456
        br = branch.Branch.open_containing('.')[0]
457
        
458
        gtk = open_display()
459
        from tags import TagsWindow
460
        window = TagsWindow(br)
461
        window.show()
462
        gtk.main()
463
464
465
class cmd_gselftest(GTKCommand):
466
    """Version of selftest that displays a notification at the end"""
467
468
    takes_args = builtins.cmd_selftest.takes_args
469
    takes_options = builtins.cmd_selftest.takes_options
470
    _see_also = ['selftest']
471
472
    def run(self, *args, **kwargs):
473
        import cgi
474
        import sys
475
        default_encoding = sys.getdefaultencoding()
476
        # prevent gtk from blowing up later
477
        gtk = import_pygtk()
478
        # prevent gtk from messing with default encoding
479
        import pynotify
480
        if sys.getdefaultencoding() != default_encoding:
481
            reload(sys)
482
            sys.setdefaultencoding(default_encoding)
483
        result = builtins.cmd_selftest().run(*args, **kwargs)
484
        if result == 0:
485
            summary = 'Success'
486
            body = 'Selftest succeeded in "%s"' % os.getcwd()
487
        if result == 1:
488
            summary = 'Failure'
489
            body = 'Selftest failed in "%s"' % os.getcwd()
490
        pynotify.init("bzr gselftest")
491
        note = pynotify.Notification(cgi.escape(summary), cgi.escape(body))
492
        note.set_timeout(pynotify.EXPIRES_NEVER)
493
        note.show()