/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.
688.1.1 by Martin Pool
Mention search commands in gannotate help
202
203
    Within the annotate window, you can use Ctrl-F to search for text, and 
688.1.2 by Martin Pool
Describe what Ctrl-G actually does
204
    Ctrl-G to jump to a line by number.
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
205
    """
206
207
    takes_args = ["filename", "line?"]
208
    takes_options = [
209
        Option("all", help="Show annotations on all lines."),
210
        Option("plain", help="Don't highlight annotation lines."),
211
        Option("line", type=int, argname="lineno",
212
               help="Jump to specified line number."),
213
        "revision",
214
    ]
215
    aliases = ["gblame", "gpraise"]
216
    
217
    def run(self, filename, all=False, plain=False, line='1', revision=None):
218
        gtk = open_display()
219
220
        try:
221
            line = int(line)
222
        except ValueError:
223
            raise BzrCommandError('Line argument ("%s") is not a number.' % 
224
                                  line)
225
226
        from annotate.gannotate import GAnnotateWindow
227
        from annotate.config import GAnnotateConfig
228
        from bzrlib.bzrdir import BzrDir
229
230
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
231
        if wt is not None:
232
            tree = wt
233
        else:
234
            tree = br.basis_tree()
235
236
        file_id = tree.path2id(path)
237
238
        if file_id is None:
239
            raise NotVersionedError(filename)
240
        if revision is not None:
241
            if len(revision) != 1:
242
                raise BzrCommandError("Only 1 revion may be specified.")
243
            revision_id = revision[0].as_revision_id(br)
244
            tree = br.repository.revision_tree(revision_id)
245
        else:
246
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
247
248
        window = GAnnotateWindow(all, plain, branch=br)
249
        window.connect("destroy", lambda w: gtk.main_quit())
250
        config = GAnnotateConfig(window)
251
        window.show()
252
        br.lock_read()
253
        if wt is not None:
254
            wt.lock_read()
255
        try:
256
            window.annotate(tree, br, file_id)
257
            window.jump_to_line(line)
258
            gtk.main()
259
        finally:
260
            br.unlock()
261
            if wt is not None:
262
                wt.unlock()
263
264
265
266
class cmd_gcommit(GTKCommand):
267
    """GTK+ commit dialog
268
269
    Graphical user interface for committing revisions"""
270
271
    aliases = [ "gci" ]
272
    takes_args = []
273
    takes_options = []
274
275
    def run(self, filename=None):
276
        open_display()
277
        from commit import CommitDialog
278
279
        wt = None
280
        br = None
281
        try:
282
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
283
            br = wt.branch
284
        except NoWorkingTree, e:
285
            from dialog import error_dialog
286
            error_dialog(_i18n('Directory does not have a working tree'),
287
                         _i18n('Operation aborted.'))
288
            return 1 # should this be retval=3?
289
290
        # It is a good habit to keep things locked for the duration, but it
291
        # could cause difficulties if someone wants to do things in another
292
        # window... We could lock_read() until we actually go to commit
293
        # changes... Just a thought.
294
        wt.lock_write()
295
        try:
296
            dlg = CommitDialog(wt)
297
            return dlg.run()
298
        finally:
299
            wt.unlock()
300
301
302
class cmd_gstatus(GTKCommand):
303
    """GTK+ status dialog
304
305
    Graphical user interface for showing status 
306
    information."""
307
308
    aliases = [ "gst" ]
309
    takes_args = ['PATH?']
310
    takes_options = ['revision']
311
312
    def run(self, path='.', revision=None):
313
        gtk = open_display()
314
        from bzrlib.plugins.gtk.status import StatusWindow
315
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
316
317
        if revision is not None:
318
            try:
319
                revision_id = revision[0].as_revision_id(wt.branch)
320
            except:
321
                from bzrlib.errors import BzrError
322
                raise BzrError('Revision %r doesn\'t exist'
323
                               % revision[0].user_spec )
324
        else:
325
            revision_id = None
326
327
        status = StatusWindow(wt, wt_path, revision_id)
328
        status.connect("destroy", gtk.main_quit)
329
        status.show()
330
        gtk.main()
331
332
333
class cmd_gsend(GTKCommand):
334
    """GTK+ send merge directive.
335
336
    """
337
    def run(self):
338
        (br, path) = branch.Branch.open_containing(".")
339
        gtk = open_display()
340
        from bzrlib.plugins.gtk.mergedirective import SendMergeDirectiveDialog
341
        from StringIO import StringIO
342
        dialog = SendMergeDirectiveDialog(br)
343
        if dialog.run() == gtk.RESPONSE_OK:
344
            outf = StringIO()
345
            outf.writelines(dialog.get_merge_directive().to_lines())
346
            mail_client = br.get_config().get_mail_client()
347
            mail_client.compose_merge_request(dialog.get_mail_to(), "[MERGE]", 
348
                outf.getvalue())
349
350
            
351
352
353
class cmd_gconflicts(GTKCommand):
354
    """GTK+ conflicts.
355
    
356
    Select files from the list of conflicts and run an external utility to
357
    resolve them.
358
    """
359
    def run(self):
360
        (wt, path) = workingtree.WorkingTree.open_containing('.')
361
        open_display()
362
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
363
        dialog = ConflictsDialog(wt)
364
        dialog.run()
365
366
367
class cmd_gpreferences(GTKCommand):
368
    """ GTK+ preferences dialog.
369
370
    """
371
    def run(self):
372
        open_display()
373
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
374
        dialog = PreferencesWindow()
375
        dialog.run()
376
377
378
class cmd_gmerge(Command):
379
    """ GTK+ merge dialog
380
    
381
    """
382
    takes_args = ["merge_from_path?"]
383
    def run(self, merge_from_path=None):
384
        from bzrlib.plugins.gtk.dialog import error_dialog
385
        from bzrlib.plugins.gtk.merge import MergeDialog
386
        
387
        (wt, path) = workingtree.WorkingTree.open_containing('.')
388
        old_tree = wt.branch.repository.revision_tree(wt.branch.last_revision())
389
        delta = wt.changes_from(old_tree)
390
        if len(delta.added) or len(delta.removed) or len(delta.renamed) or len(delta.modified):
391
            error_dialog(_i18n('There are local changes in the branch'),
392
                         _i18n('Please commit or revert the changes before merging.'))
393
        else:
394
            parent_branch_path = wt.branch.get_parent()
395
            merge = MergeDialog(wt, path, parent_branch_path)
396
            response = merge.run()
397
            merge.destroy()
398
399
400
class cmd_gmissing(Command):
401
    """ GTK+ missing revisions dialog.
402
403
    """
404
    takes_args = ["other_branch?"]
405
    def run(self, other_branch=None):
406
        pygtk = import_pygtk()
407
        try:
408
            import gtk
409
        except RuntimeError, e:
410
            if str(e) == "could not open display":
411
                raise NoDisplayError
412
413
        from bzrlib.plugins.gtk.missing import MissingWindow
414
        from bzrlib.branch import Branch
415
416
        local_branch = Branch.open_containing(".")[0]
417
        if other_branch is None:
418
            other_branch = local_branch.get_parent()
419
            
420
            if other_branch is None:
656 by Jelmer Vernooij
Merge removal of unnecessary import from Mario and rmeove some more unnecessary imports.
421
                raise BzrCommandError("No peer location known or specified.")
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
422
        remote_branch = Branch.open_containing(other_branch)[0]
423
        set_ui_factory()
424
        local_branch.lock_read()
425
        try:
426
            remote_branch.lock_read()
427
            try:
428
                dialog = MissingWindow(local_branch, remote_branch)
429
                dialog.run()
430
            finally:
431
                remote_branch.unlock()
432
        finally:
433
            local_branch.unlock()
434
435
436
class cmd_ginit(GTKCommand):
673.1.1 by Andrew Starr-Bochicchio
Provide help for ginit and gtags.
437
    """ GTK+ init dialog
438
439
    Graphical user interface for initializing new branches.
440
441
    """
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
442
    def run(self):
443
        open_display()
444
        from initialize import InitDialog
445
        dialog = InitDialog(os.path.abspath(os.path.curdir))
446
        dialog.run()
447
448
449
class cmd_gtags(GTKCommand):
673.1.1 by Andrew Starr-Bochicchio
Provide help for ginit and gtags.
450
    """ GTK+ tags dialog 
451
452
    Graphical user interface to view, create, or remove tags.
453
454
    """
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
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()