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