/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,
707 by Jelmer Vernooij
Move display opening, etc to commands.py.
19
    errors,
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
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 (
35
    set_ui_factory,
36
    )
729.1.1 by Jelmer Vernooij
Move i18n support to a separate file, so gettext files aren't loaded unless bzr-gtk is used.
37
from bzrlib.plugins.gtk.i18n import _i18n
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
38
707 by Jelmer Vernooij
Move display opening, etc to commands.py.
39
40
class NoDisplayError(errors.BzrCommandError):
41
    """gtk could not find a proper display"""
42
43
    def __str__(self):
44
        return "No DISPLAY. Unable to run GTK+ application."
45
46
47
def open_display():
48
    try:
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
49
        from gi.repository import Gtk
707 by Jelmer Vernooij
Move display opening, etc to commands.py.
50
    except RuntimeError, e:
51
        if str(e) == "could not open display":
52
            raise NoDisplayError
53
    set_ui_factory()
734.1.2 by Curtis Hovey
Removed import_pygtk because gi does not impicitly call Main(). Inlined checks for gtk availablility.
54
    return Gtk
707 by Jelmer Vernooij
Move display opening, etc to commands.py.
55
56
57
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
58
class GTKCommand(Command):
59
    """Abstract class providing GTK specific run commands."""
60
61
    def run(self):
62
        open_display()
63
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
64
        dialog.run()
65
66
67
class cmd_gbranch(GTKCommand):
68
    """GTK+ branching.
69
    
70
    """
71
72
    def get_gtk_dialog(self, path):
73
        from bzrlib.plugins.gtk.branch import BranchDialog
74
        return BranchDialog(path)
75
76
77
class cmd_gcheckout(GTKCommand):
78
    """ GTK+ checkout.
79
    
80
    """
81
    
82
    def get_gtk_dialog(self, path):
83
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
84
        return CheckoutDialog(path)
85
86
87
88
class cmd_gpush(GTKCommand):
89
    """ GTK+ push.
90
    
91
    """
92
    takes_args = [ "location?" ]
93
94
    def run(self, location="."):
95
        (br, path) = branch.Branch.open_containing(location)
96
        open_display()
97
        from bzrlib.plugins.gtk.push import PushDialog
98
        dialog = PushDialog(br.repository, br.last_revision(), br)
99
        dialog.run()
100
101
102
class cmd_gloom(GTKCommand):
103
    """ GTK+ loom.
104
    
105
    """
106
    takes_args = [ "location?" ]
107
108
    def run(self, location="."):
109
        try:
110
            (tree, path) = workingtree.WorkingTree.open_containing(location)
111
            br = tree.branch
112
        except NoWorkingTree, e:
113
            (br, path) = branch.Branch.open_containing(location)
114
            tree = None
115
        open_display()
116
        from bzrlib.plugins.gtk.loom import LoomDialog
117
        dialog = LoomDialog(br, tree)
118
        dialog.run()
119
120
121
class cmd_gdiff(GTKCommand):
122
    """Show differences in working tree in a GTK+ Window.
123
    
124
    Otherwise, all changes for the tree are listed.
125
    """
126
    takes_args = ['filename?']
127
    takes_options = ['revision']
128
129
    @display_command
130
    def run(self, revision=None, filename=None):
131
        set_ui_factory()
132
        wt = workingtree.WorkingTree.open_containing(".")[0]
133
        wt.lock_read()
134
        try:
135
            branch = wt.branch
136
            if revision is not None:
137
                if len(revision) == 1:
138
                    tree1 = wt
139
                    revision_id = revision[0].as_revision_id(tree1.branch)
140
                    tree2 = branch.repository.revision_tree(revision_id)
141
                elif len(revision) == 2:
142
                    revision_id_0 = revision[0].as_revision_id(branch)
143
                    tree2 = branch.repository.revision_tree(revision_id_0)
144
                    revision_id_1 = revision[1].as_revision_id(branch)
145
                    tree1 = branch.repository.revision_tree(revision_id_1)
146
            else:
147
                tree1 = wt
148
                tree2 = tree1.basis_tree()
149
150
            from diff import DiffWindow
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
151
            from gi.repository import Gtk
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
152
            window = DiffWindow()
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
153
            window.connect("destroy", Gtk.main_quit)
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
154
            window.set_diff("Working Tree", tree1, tree2)
155
            if filename is not None:
156
                tree_filename = wt.relpath(filename)
157
                try:
158
                    window.set_file(tree_filename)
159
                except NoSuchFile:
160
                    if (tree1.path2id(tree_filename) is None and 
161
                        tree2.path2id(tree_filename) is None):
162
                        raise NotVersionedError(filename)
163
                    raise BzrCommandError('No changes found for file "%s"' % 
164
                                          filename)
165
            window.show()
166
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
167
            Gtk.main()
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
168
        finally:
169
            wt.unlock()
170
171
172
def start_viz_window(branch, revisions, limit=None):
173
    """Start viz on branch with revision revision.
174
    
175
    :return: The viz window object.
176
    """
177
    from bzrlib.plugins.gtk.viz import BranchWindow
178
    return BranchWindow(branch, revisions, limit)
179
180
181
class cmd_visualise(Command):
700 by Vincent Ladeuil
Clarify viz help
182
    """Graphically visualise one or several branches.
183
184
    Opens a graphical window to allow you to see branches history and
185
    relationships between revisions in a visual manner,
186
187
    If no revision is specified, the branch last revision is taken as a
188
    starting point. When a revision is specified, the presented graph starts
189
    with it (as a side effect, when a shared repository is used, any revision
190
    can be used even if it's not part of the branch history).
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
191
    """
192
    takes_options = [
193
        "revision",
194
        Option('limit', "Maximum number of revisions to display.",
195
               int, 'count')]
196
    takes_args = [ "locations*" ]
197
    aliases = [ "visualize", "vis", "viz" ]
198
199
    def run(self, locations_list, revision=None, limit=None):
200
        set_ui_factory()
201
        if locations_list is None:
202
            locations_list = ["."]
203
        revids = []
204
        for location in locations_list:
205
            (br, path) = branch.Branch.open_containing(location)
206
            if revision is None:
207
                revids.append(br.last_revision())
208
            else:
209
                revids.append(revision[0].as_revision_id(br))
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
210
        from gi.repository import Gtk
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
211
        pp = start_viz_window(br, revids, limit)
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
212
        pp.connect("destroy", lambda w: Gtk.main_quit())
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
213
        pp.show()
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
214
        Gtk.main()
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
215
216
217
class cmd_gannotate(GTKCommand):
218
    """GTK+ annotate.
219
    
220
    Browse changes to FILENAME line by line in a GTK+ window.
688.1.1 by Martin Pool
Mention search commands in gannotate help
221
222
    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
223
    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.
224
    """
225
226
    takes_args = ["filename", "line?"]
227
    takes_options = [
228
        Option("all", help="Show annotations on all lines."),
229
        Option("plain", help="Don't highlight annotation lines."),
230
        Option("line", type=int, argname="lineno",
231
               help="Jump to specified line number."),
232
        "revision",
233
    ]
234
    aliases = ["gblame", "gpraise"]
235
    
236
    def run(self, filename, all=False, plain=False, line='1', revision=None):
734.1.2 by Curtis Hovey
Removed import_pygtk because gi does not impicitly call Main(). Inlined checks for gtk availablility.
237
        Gtk = open_display()
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
238
239
        try:
240
            line = int(line)
241
        except ValueError:
242
            raise BzrCommandError('Line argument ("%s") is not a number.' % 
243
                                  line)
244
245
        from annotate.gannotate import GAnnotateWindow
246
        from annotate.config import GAnnotateConfig
247
        from bzrlib.bzrdir import BzrDir
248
249
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
250
        if wt is not None:
251
            tree = wt
252
        else:
253
            tree = br.basis_tree()
254
255
        file_id = tree.path2id(path)
256
257
        if file_id is None:
258
            raise NotVersionedError(filename)
259
        if revision is not None:
260
            if len(revision) != 1:
261
                raise BzrCommandError("Only 1 revion may be specified.")
262
            revision_id = revision[0].as_revision_id(br)
263
            tree = br.repository.revision_tree(revision_id)
264
        else:
265
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
266
267
        window = GAnnotateWindow(all, plain, branch=br)
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
268
        window.connect("destroy", lambda w: Gtk.main_quit())
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
269
        config = GAnnotateConfig(window)
270
        window.show()
271
        br.lock_read()
272
        if wt is not None:
273
            wt.lock_read()
274
        try:
275
            window.annotate(tree, br, file_id)
276
            window.jump_to_line(line)
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
277
            Gtk.main()
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
278
        finally:
279
            br.unlock()
280
            if wt is not None:
281
                wt.unlock()
282
283
284
285
class cmd_gcommit(GTKCommand):
286
    """GTK+ commit dialog
287
288
    Graphical user interface for committing revisions"""
289
290
    aliases = [ "gci" ]
291
    takes_args = []
292
    takes_options = []
293
294
    def run(self, filename=None):
295
        open_display()
296
        from commit import CommitDialog
297
298
        wt = None
299
        br = None
300
        try:
301
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
302
            br = wt.branch
303
        except NoWorkingTree, e:
304
            from dialog import error_dialog
305
            error_dialog(_i18n('Directory does not have a working tree'),
306
                         _i18n('Operation aborted.'))
307
            return 1 # should this be retval=3?
308
309
        # It is a good habit to keep things locked for the duration, but it
310
        # could cause difficulties if someone wants to do things in another
311
        # window... We could lock_read() until we actually go to commit
312
        # changes... Just a thought.
313
        wt.lock_write()
314
        try:
315
            dlg = CommitDialog(wt)
316
            return dlg.run()
317
        finally:
318
            wt.unlock()
319
320
321
class cmd_gstatus(GTKCommand):
322
    """GTK+ status dialog
323
324
    Graphical user interface for showing status 
325
    information."""
326
327
    aliases = [ "gst" ]
328
    takes_args = ['PATH?']
329
    takes_options = ['revision']
330
331
    def run(self, path='.', revision=None):
734.1.2 by Curtis Hovey
Removed import_pygtk because gi does not impicitly call Main(). Inlined checks for gtk availablility.
332
        Gtk = open_display()
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
333
        from bzrlib.plugins.gtk.status import StatusWindow
334
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
335
336
        if revision is not None:
337
            try:
338
                revision_id = revision[0].as_revision_id(wt.branch)
339
            except:
340
                from bzrlib.errors import BzrError
341
                raise BzrError('Revision %r doesn\'t exist'
342
                               % revision[0].user_spec )
343
        else:
344
            revision_id = None
345
346
        status = StatusWindow(wt, wt_path, revision_id)
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
347
        status.connect("destroy", Gtk.main_quit)
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
348
        status.show()
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
349
        Gtk.main()
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
350
351
352
class cmd_gsend(GTKCommand):
353
    """GTK+ send merge directive.
354
355
    """
356
    def run(self):
357
        (br, path) = branch.Branch.open_containing(".")
734.1.2 by Curtis Hovey
Removed import_pygtk because gi does not impicitly call Main(). Inlined checks for gtk availablility.
358
        Gtk = open_display()
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
359
        from bzrlib.plugins.gtk.mergedirective import SendMergeDirectiveDialog
360
        from StringIO import StringIO
361
        dialog = SendMergeDirectiveDialog(br)
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
362
        if dialog.run() == Gtk.ResponseType.OK:
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
363
            outf = StringIO()
364
            outf.writelines(dialog.get_merge_directive().to_lines())
365
            mail_client = br.get_config().get_mail_client()
366
            mail_client.compose_merge_request(dialog.get_mail_to(), "[MERGE]", 
367
                outf.getvalue())
368
369
            
370
371
372
class cmd_gconflicts(GTKCommand):
373
    """GTK+ conflicts.
374
    
375
    Select files from the list of conflicts and run an external utility to
376
    resolve them.
377
    """
378
    def run(self):
379
        (wt, path) = workingtree.WorkingTree.open_containing('.')
380
        open_display()
381
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
382
        dialog = ConflictsDialog(wt)
383
        dialog.run()
384
385
386
class cmd_gpreferences(GTKCommand):
387
    """ GTK+ preferences dialog.
388
389
    """
390
    def run(self):
391
        open_display()
392
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
393
        dialog = PreferencesWindow()
394
        dialog.run()
395
396
397
class cmd_gmerge(Command):
398
    """ GTK+ merge dialog
399
    
400
    """
401
    takes_args = ["merge_from_path?"]
402
    def run(self, merge_from_path=None):
403
        from bzrlib.plugins.gtk.dialog import error_dialog
404
        from bzrlib.plugins.gtk.merge import MergeDialog
405
        
406
        (wt, path) = workingtree.WorkingTree.open_containing('.')
407
        old_tree = wt.branch.repository.revision_tree(wt.branch.last_revision())
408
        delta = wt.changes_from(old_tree)
409
        if len(delta.added) or len(delta.removed) or len(delta.renamed) or len(delta.modified):
410
            error_dialog(_i18n('There are local changes in the branch'),
411
                         _i18n('Please commit or revert the changes before merging.'))
412
        else:
413
            parent_branch_path = wt.branch.get_parent()
414
            merge = MergeDialog(wt, path, parent_branch_path)
415
            response = merge.run()
416
            merge.destroy()
417
418
419
class cmd_gmissing(Command):
420
    """ GTK+ missing revisions dialog.
421
422
    """
423
    takes_args = ["other_branch?"]
424
    def run(self, other_branch=None):
425
        try:
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
426
            from gi.repository import Gtk
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
427
        except RuntimeError, e:
428
            if str(e) == "could not open display":
429
                raise NoDisplayError
430
431
        from bzrlib.plugins.gtk.missing import MissingWindow
432
        from bzrlib.branch import Branch
433
434
        local_branch = Branch.open_containing(".")[0]
435
        if other_branch is None:
436
            other_branch = local_branch.get_parent()
437
            
438
            if other_branch is None:
656 by Jelmer Vernooij
Merge removal of unnecessary import from Mario and rmeove some more unnecessary imports.
439
                raise BzrCommandError("No peer location known or specified.")
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
440
        remote_branch = Branch.open_containing(other_branch)[0]
441
        set_ui_factory()
442
        local_branch.lock_read()
443
        try:
444
            remote_branch.lock_read()
445
            try:
446
                dialog = MissingWindow(local_branch, remote_branch)
447
                dialog.run()
448
            finally:
449
                remote_branch.unlock()
450
        finally:
451
            local_branch.unlock()
452
453
454
class cmd_ginit(GTKCommand):
673.1.1 by Andrew Starr-Bochicchio
Provide help for ginit and gtags.
455
    """ GTK+ init dialog
456
457
    Graphical user interface for initializing new branches.
458
459
    """
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
460
    def run(self):
461
        open_display()
462
        from initialize import InitDialog
463
        dialog = InitDialog(os.path.abspath(os.path.curdir))
464
        dialog.run()
465
466
467
class cmd_gtags(GTKCommand):
673.1.1 by Andrew Starr-Bochicchio
Provide help for ginit and gtags.
468
    """ GTK+ tags dialog 
469
470
    Graphical user interface to view, create, or remove tags.
471
472
    """
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
473
    def run(self):
474
        br = branch.Branch.open_containing('.')[0]
475
        
734.1.2 by Curtis Hovey
Removed import_pygtk because gi does not impicitly call Main(). Inlined checks for gtk availablility.
476
        Gtk = open_display()
625.2.1 by Jelmer Vernooij
Move commands to a separate module and register them lazily.
477
        from tags import TagsWindow
478
        window = TagsWindow(br)
479
        window.show()
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
480
        Gtk.main()