/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
49 by Jelmer Vernooij
Merge in Dan Loda's gannotate plugin and put it in annotate/
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
15
"""GTK+ frontends to Bazaar commands """
73 by Jelmer Vernooij
Release 0.9, list myself as maintainer.
16
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
17
import bzrlib
18
139 by Jelmer Vernooij
Update for use with current bzr.dev
19
__version__ = '0.15.0'
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
20
version_info = tuple(int(n) for n in __version__.split('.'))
21
22
23
def check_bzrlib_version(desired):
24
    """Check that bzrlib is compatible.
25
26
    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
    """
31
    desired_plus = (desired[0], desired[1]+1)
32
    bzrlib_version = bzrlib.version_info[:2]
33
    if bzrlib_version == desired:
34
        return
35
    try:
36
        from bzrlib.trace import warning
37
    except ImportError:
38
        # get the message out any way we can
39
        from warnings import warn as warning
40
    if bzrlib_version < desired:
41
        warning('Installed bzr version %s is too old to be used with bzr-gtk'
42
                ' %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])
54
146 by Jelmer Vernooij
Move more code to top-level directory.
55
from bzrlib.trace import warning
56
if __name__ != 'bzrlib.plugins.gtk':
57
    warning("Not running as bzrlib.plugins.gtk, things may break.")
58
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
59
from bzrlib.lazy_import import lazy_import
60
lazy_import(globals(), """
61
from bzrlib import (
62
    branch,
63
    errors,
64
    workingtree,
65
    )
66
""")
67
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
68
from bzrlib.commands import Command, register_command, display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
69
from bzrlib.errors import NotVersionedError, BzrCommandError, NoSuchFile
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
70
from bzrlib.commands import Command, register_command
71
from bzrlib.option import Option
72
from bzrlib.bzrdir import BzrDir
73
126.1.5 by Szilveszter Farkas (Phanatic)
bzr gbranch should work now (Fixed: #77751)
74
import os.path
75
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
76
def import_pygtk():
77
    try:
78
        import pygtk
79
    except ImportError:
80
        raise errors.BzrCommandError("PyGTK not installed.")
81
    pygtk.require('2.0')
82
    return pygtk
83
84
133 by Jelmer Vernooij
Actually use the ui factory.
85
def set_ui_factory():
86
    pygtk = import_pygtk()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
87
    from ui import GtkUIFactory
133 by Jelmer Vernooij
Actually use the ui factory.
88
    import bzrlib.ui
89
    bzrlib.ui.ui_factory = GtkUIFactory()
90
91
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
92
class cmd_gbranch(Command):
93
    """GTK+ branching.
94
    
95
    """
96
97
    def run(self):
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
98
        pygtk = import_pygtk()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
99
        try:
100
            import gtk
101
        except RuntimeError, e:
102
            if str(e) == "could not open display":
103
                raise NoDisplayError
104
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
105
        from bzrlib.plugins.gtk.branch import BranchDialog
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
106
133 by Jelmer Vernooij
Actually use the ui factory.
107
        set_ui_factory()
126.1.5 by Szilveszter Farkas (Phanatic)
bzr gbranch should work now (Fixed: #77751)
108
        dialog = BranchDialog(os.path.abspath('.'))
126.1.15 by Szilveszter Farkas (Phanatic)
Refactoring the Branch dialog. We also have a Revision Browser now.
109
        dialog.run()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
110
111
register_command(cmd_gbranch)
112
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
113
class cmd_gcheckout(Command):
114
    """ GTK+ checkout.
115
    
116
    """
117
    
118
    def run(self):
119
        pygtk = import_pygtk()
120
        try:
121
            import gtk
122
        except RuntimeError, e:
123
            if str(e) == "could not open display":
124
                raise NoDisplayError
125
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
126
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
127
128
        set_ui_factory()
129
        dialog = CheckoutDialog(os.path.abspath('.'))
130
        dialog.run()
131
132
register_command(cmd_gcheckout)
133
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
134
class cmd_gpush(Command):
135
    """ GTK+ push.
136
    
137
    """
138
    takes_args = [ "location?" ]
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
139
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
140
    def run(self, location="."):
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
141
        (br, path) = branch.Branch.open_containing(location)
142
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
143
        pygtk = import_pygtk()
144
        try:
145
            import gtk
146
        except RuntimeError, e:
147
            if str(e) == "could not open display":
148
                raise NoDisplayError
149
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
150
        from push import PushDialog
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
151
152
        set_ui_factory()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
153
        dialog = PushDialog(br)
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
154
        dialog.run()
155
156
register_command(cmd_gpush)
157
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
158
class cmd_gdiff(Command):
159
    """Show differences in working tree in a GTK+ Window.
160
    
161
    Otherwise, all changes for the tree are listed.
162
    """
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
163
    takes_args = ['filename?']
58.1.1 by Aaron Bentley
gdiff takes -r arguments
164
    takes_options = ['revision']
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
165
166
    @display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
167
    def run(self, revision=None, filename=None):
133 by Jelmer Vernooij
Actually use the ui factory.
168
        set_ui_factory()
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
169
        wt = workingtree.WorkingTree.open_containing(".")[0]
58.1.1 by Aaron Bentley
gdiff takes -r arguments
170
        branch = wt.branch
171
        if revision is not None:
172
            if len(revision) == 1:
173
                tree1 = wt
174
                revision_id = revision[0].in_history(branch).rev_id
175
                tree2 = branch.repository.revision_tree(revision_id)
176
            elif len(revision) == 2:
177
                revision_id_0 = revision[0].in_history(branch).rev_id
178
                tree2 = branch.repository.revision_tree(revision_id_0)
179
                revision_id_1 = revision[1].in_history(branch).rev_id
180
                tree1 = branch.repository.revision_tree(revision_id_1)
181
        else:
182
            tree1 = wt
183
            tree2 = tree1.basis_tree()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
184
152 by Jelmer Vernooij
Cleanup some more code.
185
        from diff import DiffWindow
58 by Jelmer Vernooij
[merge] Home
186
        import gtk
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
187
        window = DiffWindow()
152 by Jelmer Vernooij
Cleanup some more code.
188
        window.connect("destroy", gtk.main_quit)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
189
        window.set_diff("Working Tree", tree1, tree2)
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
190
        if filename is not None:
93.1.16 by Alexander Belchenko
Partial fix for problem with encodings in diff window
191
            tree_filename = wt.relpath(filename)
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
192
            try:
193
                window.set_file(tree_filename)
194
            except NoSuchFile:
195
                if (tree1.inventory.path2id(tree_filename) is None and 
196
                    tree2.inventory.path2id(tree_filename) is None):
197
                    raise NotVersionedError(filename)
198
                raise BzrCommandError('No changes found for file "%s"' % 
199
                                      filename)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
200
        window.show()
201
202
        gtk.main()
203
204
register_command(cmd_gdiff)
205
206
class cmd_visualise(Command):
207
    """Graphically visualise this branch.
208
209
    Opens a graphical window to allow you to see the history of the branch
210
    and relationships between revisions in a visual manner,
211
212
    The default starting point is latest revision on the branch, you can
213
    specify a starting point with -r revision.
214
    """
215
    takes_options = [
216
        "revision",
217
        Option('limit', "maximum number of revisions to display",
218
               int, 'count')]
219
    takes_args = [ "location?" ]
220
    aliases = [ "visualize", "vis", "viz" ]
221
222
    def run(self, location=".", revision=None, limit=None):
133 by Jelmer Vernooij
Actually use the ui factory.
223
        set_ui_factory()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
224
        (br, path) = branch.Branch.open_containing(location)
225
        br.lock_read()
226
        br.repository.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
227
        try:
228
            if revision is None:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
229
                revid = br.last_revision()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
230
                if revid is None:
231
                    return
232
            else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
233
                (revno, revid) = revision[0].in_history(br)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
234
152 by Jelmer Vernooij
Cleanup some more code.
235
            from viz.branchwin import BranchWindow
236
            import gtk
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
237
                
152 by Jelmer Vernooij
Cleanup some more code.
238
            pp = BranchWindow()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
239
            pp.set_branch(br, revid, limit)
152 by Jelmer Vernooij
Cleanup some more code.
240
            pp.connect("destroy", lambda w: gtk.main_quit())
241
            pp.show()
242
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
243
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
244
            br.repository.unlock()
245
            br.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
246
247
248
register_command(cmd_visualise)
249
250
class cmd_gannotate(Command):
251
    """GTK+ annotate.
252
    
253
    Browse changes to FILENAME line by line in a GTK+ window.
254
    """
255
59.2.1 by Aaron Bentley
Gannotate takes a line number
256
    takes_args = ["filename", "line?"]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
257
    takes_options = [
258
        Option("all", help="show annotations on all lines"),
259
        Option("plain", help="don't highlight annotation lines"),
260
        Option("line", type=int, argname="lineno",
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
261
               help="jump to specified line number"),
262
        "revision",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
263
    ]
264
    aliases = ["gblame", "gpraise"]
265
    
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
266
    def run(self, filename, all=False, plain=False, line='1', revision=None):
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
267
        pygtk = import_pygtk()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
268
269
        try:
270
            import gtk
271
        except RuntimeError, e:
272
            if str(e) == "could not open display":
273
                raise NoDisplayError
133 by Jelmer Vernooij
Actually use the ui factory.
274
        set_ui_factory()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
275
59.2.1 by Aaron Bentley
Gannotate takes a line number
276
        try:
277
            line = int(line)
278
        except ValueError:
279
            raise BzrCommandError('Line argument ("%s") is not a number.' % 
280
                                  line)
281
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
282
        from annotate.gannotate import GAnnotateWindow
283
        from annotate.config import GAnnotateConfig
284
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
285
        try:
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
286
            (tree, path) = workingtree.WorkingTree.open_containing(filename)
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
287
            br = tree.branch
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
288
        except errors.NoWorkingTree:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
289
            (br, path) = branch.Branch.open_containing(filename)
290
            tree = br.basis_tree()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
291
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
292
        file_id = tree.path2id(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
293
294
        if file_id is None:
295
            raise NotVersionedError(filename)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
296
        if revision is not None:
297
            if len(revision) != 1:
298
                raise BzrCommandError("Only 1 revion may be specified.")
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
299
            revision_id = revision[0].in_history(br).rev_id
300
            tree = br.repository.revision_tree(revision_id)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
301
        else:
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
302
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
303
304
        window = GAnnotateWindow(all, plain)
305
        window.connect("destroy", lambda w: gtk.main_quit())
306
        window.set_title(path + " - gannotate")
307
        config = GAnnotateConfig(window)
308
        window.show()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
309
        br.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
310
        try:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
311
            window.annotate(tree, br, file_id)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
312
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
313
            br.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
314
        window.jump_to_line(line)
315
        
316
        gtk.main()
317
318
register_command(cmd_gannotate)
319
320
class cmd_gcommit(Command):
321
    """GTK+ commit dialog
322
323
    Graphical user interface for committing revisions"""
324
    
145 by Jelmer Vernooij
Fix some strings, import.
325
    aliases = [ "gci" ]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
326
    takes_args = []
327
    takes_options = []
328
329
    def run(self, filename=None):
93.1.17 by Alexander Belchenko
gcommit reworked again.
330
        import os
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
331
        pygtk = import_pygtk()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
332
333
        try:
334
            import gtk
335
        except RuntimeError, e:
336
            if str(e) == "could not open display":
337
                raise NoDisplayError
338
133 by Jelmer Vernooij
Actually use the ui factory.
339
        set_ui_factory()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
340
        from commit import CommitDialog
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
341
        from bzrlib.commit import Commit
93.1.17 by Alexander Belchenko
gcommit reworked again.
342
        from bzrlib.errors import (BzrCommandError,
343
                                   NotBranchError,
344
                                   NoWorkingTree,
345
                                   PointlessCommit,
346
                                   ConflictsInTree,
347
                                   StrictCommitFailed)
348
349
        wt = None
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
350
        br = None
93.1.17 by Alexander Belchenko
gcommit reworked again.
351
        try:
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
352
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
353
            br = wt.branch
93.1.17 by Alexander Belchenko
gcommit reworked again.
354
        except NotBranchError, e:
355
            path = e.path
356
        except NoWorkingTree, e:
357
            path = e.base
358
            try:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
359
                (br, path) = branch.Branch.open_containing(path)
93.1.17 by Alexander Belchenko
gcommit reworked again.
360
            except NotBranchError, e:
361
                path = e.path
362
135 by Jelmer Vernooij
Throw out the old CommitDialog code and use the new code instead, also for 'gcommit'.
363
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
364
        commit = CommitDialog(wt, path, not br)
135 by Jelmer Vernooij
Throw out the old CommitDialog code and use the new code instead, also for 'gcommit'.
365
        commit.run()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
366
367
register_command(cmd_gcommit)
368
157 by Jelmer Vernooij
Add gstatus command.
369
class cmd_gstatus(Command):
370
    """GTK+ status dialog
371
372
    Graphical user interface for showing status 
373
    information."""
374
    
375
    aliases = [ "gst" ]
376
    takes_args = ['PATH?']
377
    takes_options = []
378
379
    def run(self, path='.'):
380
        import os
381
        pygtk = import_pygtk()
382
383
        try:
384
            import gtk
385
        except RuntimeError, e:
386
            if str(e) == "could not open display":
387
                raise NoDisplayError
388
389
        set_ui_factory()
390
        from status import StatusDialog
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
391
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
157 by Jelmer Vernooij
Add gstatus command.
392
        status = StatusDialog(wt, wt_path)
393
        status.connect("destroy", gtk.main_quit)
394
        status.run()
395
396
register_command(cmd_gstatus)
397
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
398
class cmd_gconflicts(Command):
399
    """ GTK+ push.
400
    
401
    """
402
    def run(self):
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
403
        (wt, path) = workingtree.WorkingTree.open_containing('.')
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
404
        
405
        pygtk = import_pygtk()
406
        try:
407
            import gtk
408
        except RuntimeError, e:
409
            if str(e) == "could not open display":
410
                raise NoDisplayError
411
412
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
413
414
        set_ui_factory()
415
        dialog = ConflictsDialog(wt)
416
        dialog.run()
417
418
register_command(cmd_gconflicts)
157 by Jelmer Vernooij
Add gstatus command.
419
152 by Jelmer Vernooij
Cleanup some more code.
420
import gettext
421
gettext.install('olive-gtk')
422
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
423
class NoDisplayError(BzrCommandError):
424
    """gtk could not find a proper display"""
425
426
    def __str__(self):
133 by Jelmer Vernooij
Actually use the ui factory.
427
        return "No DISPLAY. Unable to run GTK+ application."
428
140 by Jelmer Vernooij
add framework for tests.
429
def test_suite():
430
    from unittest import TestSuite
431
    import tests
432
    result = TestSuite()
433
    result.addTest(tests.test_suite())
434
    return result