/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
152 by Jelmer Vernooij
Cleanup some more code.
179
        from diff 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()
152 by Jelmer Vernooij
Cleanup some more code.
182
        window.connect("destroy", gtk.main_quit)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
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
152 by Jelmer Vernooij
Cleanup some more code.
229
            from viz.branchwin import BranchWindow
230
            import gtk
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
231
                
152 by Jelmer Vernooij
Cleanup some more code.
232
            pp = BranchWindow()
233
            pp.set_branch(branch, revid, limit)
234
            pp.connect("destroy", lambda w: gtk.main_quit())
235
            pp.show()
236
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
237
        finally:
238
            branch.repository.unlock()
239
            branch.unlock()
240
241
242
register_command(cmd_visualise)
243
244
class cmd_gannotate(Command):
245
    """GTK+ annotate.
246
    
247
    Browse changes to FILENAME line by line in a GTK+ window.
248
    """
249
59.2.1 by Aaron Bentley
Gannotate takes a line number
250
    takes_args = ["filename", "line?"]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
251
    takes_options = [
252
        Option("all", help="show annotations on all lines"),
253
        Option("plain", help="don't highlight annotation lines"),
254
        Option("line", type=int, argname="lineno",
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
255
               help="jump to specified line number"),
256
        "revision",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
257
    ]
258
    aliases = ["gblame", "gpraise"]
259
    
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
260
    def run(self, filename, all=False, plain=False, line='1', revision=None):
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
261
        pygtk = import_pygtk()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
262
263
        try:
264
            import gtk
265
        except RuntimeError, e:
266
            if str(e) == "could not open display":
267
                raise NoDisplayError
133 by Jelmer Vernooij
Actually use the ui factory.
268
        set_ui_factory()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
269
59.2.1 by Aaron Bentley
Gannotate takes a line number
270
        try:
271
            line = int(line)
272
        except ValueError:
273
            raise BzrCommandError('Line argument ("%s") is not a number.' % 
274
                                  line)
275
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
276
        from annotate.gannotate import GAnnotateWindow
277
        from annotate.config import GAnnotateConfig
278
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
279
        try:
280
            (tree, path) = WorkingTree.open_containing(filename)
281
            branch = tree.branch
282
        except errors.NoWorkingTree:
283
            (branch, path) = Branch.open_containing(filename)
284
            tree = branch.basis_tree()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
285
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
286
        file_id = tree.path2id(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
287
288
        if file_id is None:
289
            raise NotVersionedError(filename)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
290
        if revision is not None:
291
            if len(revision) != 1:
292
                raise BzrCommandError("Only 1 revion may be specified.")
293
            revision_id = revision[0].in_history(branch).rev_id
66.2.14 by Aaron Bentley
Annotate showing uncommitted changes
294
            tree = branch.repository.revision_tree(revision_id)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
295
        else:
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
296
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
297
298
        window = GAnnotateWindow(all, plain)
299
        window.connect("destroy", lambda w: gtk.main_quit())
300
        window.set_title(path + " - gannotate")
301
        config = GAnnotateConfig(window)
302
        window.show()
303
        branch.lock_read()
304
        try:
66.2.14 by Aaron Bentley
Annotate showing uncommitted changes
305
            window.annotate(tree, branch, file_id)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
306
        finally:
307
            branch.unlock()
308
        window.jump_to_line(line)
309
        
310
        gtk.main()
311
312
register_command(cmd_gannotate)
313
314
class cmd_gcommit(Command):
315
    """GTK+ commit dialog
316
317
    Graphical user interface for committing revisions"""
318
    
145 by Jelmer Vernooij
Fix some strings, import.
319
    aliases = [ "gci" ]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
320
    takes_args = []
321
    takes_options = []
322
323
    def run(self, filename=None):
93.1.17 by Alexander Belchenko
gcommit reworked again.
324
        import os
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
325
        pygtk = import_pygtk()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
326
327
        try:
328
            import gtk
329
        except RuntimeError, e:
330
            if str(e) == "could not open display":
331
                raise NoDisplayError
332
133 by Jelmer Vernooij
Actually use the ui factory.
333
        set_ui_factory()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
334
        from commit import CommitDialog
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
335
        from bzrlib.commit import Commit
93.1.17 by Alexander Belchenko
gcommit reworked again.
336
        from bzrlib.errors import (BzrCommandError,
337
                                   NotBranchError,
338
                                   NoWorkingTree,
339
                                   PointlessCommit,
340
                                   ConflictsInTree,
341
                                   StrictCommitFailed)
342
343
        wt = None
344
        branch = None
345
        try:
346
            (wt, path) = WorkingTree.open_containing(filename)
347
            branch = wt.branch
348
        except NotBranchError, e:
349
            path = e.path
350
        except NoWorkingTree, e:
351
            path = e.base
352
            try:
353
                (branch, path) = Branch.open_containing(path)
354
            except NotBranchError, e:
355
                path = e.path
356
135 by Jelmer Vernooij
Throw out the old CommitDialog code and use the new code instead, also for 'gcommit'.
357
358
        commit = CommitDialog(wt, path, not branch)
359
        commit.run()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
360
361
register_command(cmd_gcommit)
362
152 by Jelmer Vernooij
Cleanup some more code.
363
import gettext
364
gettext.install('olive-gtk')
365
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
366
class NoDisplayError(BzrCommandError):
367
    """gtk could not find a proper display"""
368
369
    def __str__(self):
133 by Jelmer Vernooij
Actually use the ui factory.
370
        return "No DISPLAY. Unable to run GTK+ application."
371
140 by Jelmer Vernooij
add framework for tests.
372
def test_suite():
373
    from unittest import TestSuite
374
    import tests
375
    result = TestSuite()
376
    result.addTest(tests.test_suite())
377
    return result