/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_gmerge(Command):
376
    """ GTK+ merge dialog
377
    
378
    """
379
    takes_args = ["merge_from_path?"]
380
    def run(self, merge_from_path=None):
381
        from bzrlib.plugins.gtk.dialog import error_dialog
382
        from bzrlib.plugins.gtk.merge import MergeDialog
383
        
384
        (wt, path) = workingtree.WorkingTree.open_containing('.')
385
        old_tree = wt.branch.repository.revision_tree(wt.branch.last_revision())
386
        delta = wt.changes_from(old_tree)
387
        if len(delta.added) or len(delta.removed) or len(delta.renamed) or len(delta.modified):
388
            error_dialog(_i18n('There are local changes in the branch'),
389
                         _i18n('Please commit or revert the changes before merging.'))
390
        else:
391
            parent_branch_path = wt.branch.get_parent()
392
            merge = MergeDialog(wt, path, parent_branch_path)
393
            response = merge.run()
394
            merge.destroy()
395
396
397
class cmd_gmissing(Command):
398
    """ GTK+ missing revisions dialog.
399
400
    """
401
    takes_args = ["other_branch?"]
402
    def run(self, other_branch=None):
403
        pygtk = import_pygtk()
404
        try:
405
            import gtk
406
        except RuntimeError, e:
407
            if str(e) == "could not open display":
408
                raise NoDisplayError
409
410
        from bzrlib.plugins.gtk.missing import MissingWindow
411
        from bzrlib.branch import Branch
412
413
        local_branch = Branch.open_containing(".")[0]
414
        if other_branch is None:
415
            other_branch = local_branch.get_parent()
416
            
417
            if other_branch is None:
656 by Jelmer Vernooij
Merge removal of unnecessary import from Mario and rmeove some more unnecessary imports.
418
                raise BzrCommandError("No peer location known or specified.")
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
419
        remote_branch = Branch.open_containing(other_branch)[0]
420
        set_ui_factory()
421
        local_branch.lock_read()
422
        try:
423
            remote_branch.lock_read()
424
            try:
425
                dialog = MissingWindow(local_branch, remote_branch)
426
                dialog.run()
427
            finally:
428
                remote_branch.unlock()
429
        finally:
430
            local_branch.unlock()
431
432
433
class cmd_ginit(GTKCommand):
673.1.1 by Andrew Starr-Bochicchio
Provide help for ginit and gtags.
434
    """ GTK+ init dialog
435
436
    Graphical user interface for initializing new branches.
437
438
    """
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
439
    def run(self):
440
        open_display()
441
        from initialize import InitDialog
442
        dialog = InitDialog(os.path.abspath(os.path.curdir))
443
        dialog.run()
444
445
446
class cmd_gtags(GTKCommand):
673.1.1 by Andrew Starr-Bochicchio
Provide help for ginit and gtags.
447
    """ GTK+ tags dialog 
448
449
    Graphical user interface to view, create, or remove tags.
450
451
    """
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
452
    def run(self):
453
        br = branch.Branch.open_containing('.')[0]
454
        
455
        gtk = open_display()
456
        from tags import TagsWindow
457
        window = TagsWindow(br)
458
        window.show()
459
        gtk.main()
460
461
462
class cmd_gselftest(GTKCommand):
463
    """Version of selftest that displays a notification at the end"""
464
465
    takes_args = builtins.cmd_selftest.takes_args
466
    takes_options = builtins.cmd_selftest.takes_options
467
    _see_also = ['selftest']
468
469
    def run(self, *args, **kwargs):
470
        import cgi
471
        import sys
472
        default_encoding = sys.getdefaultencoding()
473
        # prevent gtk from blowing up later
474
        gtk = import_pygtk()
475
        # prevent gtk from messing with default encoding
476
        import pynotify
477
        if sys.getdefaultencoding() != default_encoding:
478
            reload(sys)
479
            sys.setdefaultencoding(default_encoding)
480
        result = builtins.cmd_selftest().run(*args, **kwargs)
481
        if result == 0:
482
            summary = 'Success'
483
            body = 'Selftest succeeded in "%s"' % os.getcwd()
484
        if result == 1:
485
            summary = 'Failure'
486
            body = 'Selftest failed in "%s"' % os.getcwd()
487
        pynotify.init("bzr gselftest")
488
        note = pynotify.Notification(cgi.escape(summary), cgi.escape(body))
489
        note.set_timeout(pynotify.EXPIRES_NEVER)
490
        note.show()