/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
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
55
from bzrlib import errors
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
56
from bzrlib.commands import Command, register_command, display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
57
from bzrlib.errors import NotVersionedError, BzrCommandError, NoSuchFile
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
58
from bzrlib.commands import Command, register_command
59
from bzrlib.option import Option
60
from bzrlib.branch import Branch
61
from bzrlib.workingtree import WorkingTree
62
from bzrlib.bzrdir import BzrDir
63
126.1.5 by Szilveszter Farkas (Phanatic)
bzr gbranch should work now (Fixed: #77751)
64
import os.path
65
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
66
def import_pygtk():
67
    try:
68
        import pygtk
69
    except ImportError:
70
        raise errors.BzrCommandError("PyGTK not installed.")
71
    pygtk.require('2.0')
72
    return pygtk
73
74
133 by Jelmer Vernooij
Actually use the ui factory.
75
def set_ui_factory():
76
    pygtk = import_pygtk()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
77
    from ui import GtkUIFactory
133 by Jelmer Vernooij
Actually use the ui factory.
78
    import bzrlib.ui
79
    bzrlib.ui.ui_factory = GtkUIFactory()
80
81
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
82
class cmd_gbranch(Command):
83
    """GTK+ branching.
84
    
85
    """
86
87
    def run(self):
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
88
        pygtk = import_pygtk()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
89
        try:
90
            import gtk
91
        except RuntimeError, e:
92
            if str(e) == "could not open display":
93
                raise NoDisplayError
94
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
95
        from bzrlib.plugins.gtk.branch import BranchDialog
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
96
133 by Jelmer Vernooij
Actually use the ui factory.
97
        set_ui_factory()
126.1.5 by Szilveszter Farkas (Phanatic)
bzr gbranch should work now (Fixed: #77751)
98
        dialog = BranchDialog(os.path.abspath('.'))
126.1.15 by Szilveszter Farkas (Phanatic)
Refactoring the Branch dialog. We also have a Revision Browser now.
99
        dialog.run()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
100
101
register_command(cmd_gbranch)
102
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
103
class cmd_gcheckout(Command):
104
    """ GTK+ checkout.
105
    
106
    """
107
    
108
    def run(self):
109
        pygtk = import_pygtk()
110
        try:
111
            import gtk
112
        except RuntimeError, e:
113
            if str(e) == "could not open display":
114
                raise NoDisplayError
115
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
116
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
117
118
        set_ui_factory()
119
        dialog = CheckoutDialog(os.path.abspath('.'))
120
        dialog.run()
121
122
register_command(cmd_gcheckout)
123
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
124
class cmd_gpush(Command):
125
    """ GTK+ push.
126
    
127
    """
128
    takes_args = [ "location?" ]
129
    
130
    def run(self, location="."):
131
        (branch, path) = Branch.open_containing(location)
132
        
133
        pygtk = import_pygtk()
134
        try:
135
            import gtk
136
        except RuntimeError, e:
137
            if str(e) == "could not open display":
138
                raise NoDisplayError
139
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
140
        from push import PushDialog
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
141
142
        set_ui_factory()
143
        dialog = PushDialog(branch)
144
        dialog.run()
145
146
register_command(cmd_gpush)
147
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
148
class cmd_gdiff(Command):
149
    """Show differences in working tree in a GTK+ Window.
150
    
151
    Otherwise, all changes for the tree are listed.
152
    """
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
153
    takes_args = ['filename?']
58.1.1 by Aaron Bentley
gdiff takes -r arguments
154
    takes_options = ['revision']
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
155
156
    @display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
157
    def run(self, revision=None, filename=None):
133 by Jelmer Vernooij
Actually use the ui factory.
158
        set_ui_factory()
58.1.1 by Aaron Bentley
gdiff takes -r arguments
159
        wt = WorkingTree.open_containing(".")[0]
160
        branch = wt.branch
161
        if revision is not None:
162
            if len(revision) == 1:
163
                tree1 = wt
164
                revision_id = revision[0].in_history(branch).rev_id
165
                tree2 = branch.repository.revision_tree(revision_id)
166
            elif len(revision) == 2:
167
                revision_id_0 = revision[0].in_history(branch).rev_id
168
                tree2 = branch.repository.revision_tree(revision_id_0)
169
                revision_id_1 = revision[1].in_history(branch).rev_id
170
                tree1 = branch.repository.revision_tree(revision_id_1)
171
        else:
172
            tree1 = wt
173
            tree2 = tree1.basis_tree()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
174
93.1.8 by Alexander Belchenko
Fix absolute import in gdiff command.
175
        from viz.diffwin import DiffWindow
58 by Jelmer Vernooij
[merge] Home
176
        import gtk
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
177
        window = DiffWindow()
178
        window.connect("destroy", lambda w: gtk.main_quit())
179
        window.set_diff("Working Tree", tree1, tree2)
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
180
        if filename is not None:
93.1.16 by Alexander Belchenko
Partial fix for problem with encodings in diff window
181
            tree_filename = wt.relpath(filename)
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
182
            try:
183
                window.set_file(tree_filename)
184
            except NoSuchFile:
185
                if (tree1.inventory.path2id(tree_filename) is None and 
186
                    tree2.inventory.path2id(tree_filename) is None):
187
                    raise NotVersionedError(filename)
188
                raise BzrCommandError('No changes found for file "%s"' % 
189
                                      filename)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
190
        window.show()
191
192
        gtk.main()
193
194
register_command(cmd_gdiff)
195
196
class cmd_visualise(Command):
197
    """Graphically visualise this branch.
198
199
    Opens a graphical window to allow you to see the history of the branch
200
    and relationships between revisions in a visual manner,
201
202
    The default starting point is latest revision on the branch, you can
203
    specify a starting point with -r revision.
204
    """
205
    takes_options = [
206
        "revision",
207
        Option('limit', "maximum number of revisions to display",
208
               int, 'count')]
209
    takes_args = [ "location?" ]
210
    aliases = [ "visualize", "vis", "viz" ]
211
212
    def run(self, location=".", revision=None, limit=None):
133 by Jelmer Vernooij
Actually use the ui factory.
213
        set_ui_factory()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
214
        (branch, path) = Branch.open_containing(location)
215
        branch.lock_read()
216
        branch.repository.lock_read()
217
        try:
218
            if revision is None:
219
                revid = branch.last_revision()
220
                if revid is None:
221
                    return
222
            else:
223
                (revno, revid) = revision[0].in_history(branch)
224
225
            from viz.bzrkapp import BzrkApp
226
                
227
            app = BzrkApp()
228
            app.show(branch, revid, limit)
229
        finally:
230
            branch.repository.unlock()
231
            branch.unlock()
232
        app.main()
233
234
235
register_command(cmd_visualise)
236
237
class cmd_gannotate(Command):
238
    """GTK+ annotate.
239
    
240
    Browse changes to FILENAME line by line in a GTK+ window.
241
    """
242
59.2.1 by Aaron Bentley
Gannotate takes a line number
243
    takes_args = ["filename", "line?"]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
244
    takes_options = [
245
        Option("all", help="show annotations on all lines"),
246
        Option("plain", help="don't highlight annotation lines"),
247
        Option("line", type=int, argname="lineno",
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
248
               help="jump to specified line number"),
249
        "revision",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
250
    ]
251
    aliases = ["gblame", "gpraise"]
252
    
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
253
    def run(self, filename, all=False, plain=False, line='1', revision=None):
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
254
        pygtk = import_pygtk()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
255
256
        try:
257
            import gtk
258
        except RuntimeError, e:
259
            if str(e) == "could not open display":
260
                raise NoDisplayError
133 by Jelmer Vernooij
Actually use the ui factory.
261
        set_ui_factory()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
262
59.2.1 by Aaron Bentley
Gannotate takes a line number
263
        try:
264
            line = int(line)
265
        except ValueError:
266
            raise BzrCommandError('Line argument ("%s") is not a number.' % 
267
                                  line)
268
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
269
        from annotate.gannotate import GAnnotateWindow
270
        from annotate.config import GAnnotateConfig
271
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
272
        try:
273
            (tree, path) = WorkingTree.open_containing(filename)
274
            branch = tree.branch
275
        except errors.NoWorkingTree:
276
            (branch, path) = Branch.open_containing(filename)
277
            tree = branch.basis_tree()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
278
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
279
        file_id = tree.path2id(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
280
281
        if file_id is None:
282
            raise NotVersionedError(filename)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
283
        if revision is not None:
284
            if len(revision) != 1:
285
                raise BzrCommandError("Only 1 revion may be specified.")
286
            revision_id = revision[0].in_history(branch).rev_id
66.2.14 by Aaron Bentley
Annotate showing uncommitted changes
287
            tree = branch.repository.revision_tree(revision_id)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
288
        else:
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
289
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
290
291
        window = GAnnotateWindow(all, plain)
292
        window.connect("destroy", lambda w: gtk.main_quit())
293
        window.set_title(path + " - gannotate")
294
        config = GAnnotateConfig(window)
295
        window.show()
296
        branch.lock_read()
297
        try:
66.2.14 by Aaron Bentley
Annotate showing uncommitted changes
298
            window.annotate(tree, branch, file_id)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
299
        finally:
300
            branch.unlock()
301
        window.jump_to_line(line)
302
        
303
        gtk.main()
304
305
register_command(cmd_gannotate)
306
307
class cmd_gcommit(Command):
308
    """GTK+ commit dialog
309
310
    Graphical user interface for committing revisions"""
311
    
312
    takes_args = []
313
    takes_options = []
314
315
    def run(self, filename=None):
93.1.17 by Alexander Belchenko
gcommit reworked again.
316
        import os
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
317
        pygtk = import_pygtk()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
318
319
        try:
320
            import gtk
321
        except RuntimeError, e:
322
            if str(e) == "could not open display":
323
                raise NoDisplayError
324
133 by Jelmer Vernooij
Actually use the ui factory.
325
        set_ui_factory()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
326
        from commit import CommitDialog
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
327
        from bzrlib.commit import Commit
93.1.17 by Alexander Belchenko
gcommit reworked again.
328
        from bzrlib.errors import (BzrCommandError,
329
                                   NotBranchError,
330
                                   NoWorkingTree,
331
                                   PointlessCommit,
332
                                   ConflictsInTree,
333
                                   StrictCommitFailed)
334
335
        wt = None
336
        branch = None
337
        try:
338
            (wt, path) = WorkingTree.open_containing(filename)
339
            branch = wt.branch
340
        except NotBranchError, e:
341
            path = e.path
342
        except NoWorkingTree, e:
343
            path = e.base
344
            try:
345
                (branch, path) = Branch.open_containing(path)
346
            except NotBranchError, e:
347
                path = e.path
348
135 by Jelmer Vernooij
Throw out the old CommitDialog code and use the new code instead, also for 'gcommit'.
349
350
        commit = CommitDialog(wt, path, not branch)
351
        commit.run()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
352
353
register_command(cmd_gcommit)
354
355
class NoDisplayError(BzrCommandError):
356
    """gtk could not find a proper display"""
357
358
    def __str__(self):
133 by Jelmer Vernooij
Actually use the ui factory.
359
        return "No DISPLAY. Unable to run GTK+ application."
360
140 by Jelmer Vernooij
add framework for tests.
361
def test_suite():
362
    from unittest import TestSuite
363
    import tests
364
    result = TestSuite()
365
    result.addTest(tests.test_suite())
366
    return result