/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
208.2.1 by Robert Collins
Better module docstring.
15
"""Graphical support for Bazaar using GTK.
16
17
This plugin includes:
18
commit-notify     Start the graphical notifier of commits.
19
gannotate         GTK+ annotate. 
20
gbranch           GTK+ branching. 
21
gcheckout         GTK+ checkout. 
22
gcommit           GTK+ commit dialog 
242.1.2 by Adeodato Simó
Fix gconflicts docstring.
23
gconflicts        GTK+ conflicts. 
208.2.1 by Robert Collins
Better module docstring.
24
gdiff             Show differences in working tree in a GTK+ Window. 
25
ginit             Initialise a new branch.
26
gmissing          GTK+ missing revisions dialog. 
27
gpreferences      GTK+ preferences dialog. 
28
gpush             GTK+ push. 
29
gstatus           GTK+ status dialog 
30
gtags             Manage branch tags.
31
visualise         Graphically visualise this branch. 
32
"""
73 by Jelmer Vernooij
Release 0.9, list myself as maintainer.
33
278.1.22 by John Arbash Meinel
Add a test-gtk command to make testing faster
34
import sys
35
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
36
import bzrlib
37
287 by Jelmer Vernooij
Use standard version tuple.
38
version_info = (0, 92, 0, 'dev', 0)
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
39
287 by Jelmer Vernooij
Use standard version tuple.
40
if version_info[3] == 'final':
41
    version_string = '%d.%d.%d' % version_info[:3]
42
else:
43
    version_string = '%d.%d.%d%s%d' % version_info
44
__version__ = version_string
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
45
46
def check_bzrlib_version(desired):
47
    """Check that bzrlib is compatible.
48
49
    If version is < bzr-gtk version, assume incompatible.
50
    If version == bzr-gtk version, assume completely compatible
51
    If version == bzr-gtk version + 1, assume compatible, with deprecations
52
    Otherwise, assume incompatible.
53
    """
54
    desired_plus = (desired[0], desired[1]+1)
55
    bzrlib_version = bzrlib.version_info[:2]
203 by Aaron Bentley
Don't warn if bzrlib is dev version of next release
56
    if bzrlib_version == desired or (bzrlib_version == desired_plus and
57
                                     bzrlib.version_info[3] == 'dev'):
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
58
        return
59
    try:
60
        from bzrlib.trace import warning
61
    except ImportError:
62
        # get the message out any way we can
63
        from warnings import warn as warning
64
    if bzrlib_version < desired:
207 by Aaron Bentley
Import BzrError before using it
65
        from bzrlib.errors import BzrError
271 by Jelmer Vernooij
Add common widget for selecting branches.
66
        warning('Installed Bazaar version %s is too old to be used with bzr-gtk'
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
67
                ' %s.' % (bzrlib.__version__, __version__))
287 by Jelmer Vernooij
Use standard version tuple.
68
        raise BzrError('Version mismatch: %r, %r' % (version_info, bzrlib.version_info) )
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
69
    else:
70
        warning('bzr-gtk is not up to date with installed bzr version %s.'
71
                ' \nThere should be a newer version available, e.g. %i.%i.' 
72
                % (bzrlib.__version__, bzrlib_version[0], bzrlib_version[1]))
73
74
287 by Jelmer Vernooij
Use standard version tuple.
75
if version_info[2] == "final":
76
    check_bzrlib_version(version_info[:2])
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
77
146 by Jelmer Vernooij
Move more code to top-level directory.
78
from bzrlib.trace import warning
79
if __name__ != 'bzrlib.plugins.gtk':
80
    warning("Not running as bzrlib.plugins.gtk, things may break.")
81
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
82
from bzrlib.lazy_import import lazy_import
83
lazy_import(globals(), """
84
from bzrlib import (
85
    branch,
249 by Aaron Bentley
Add gselftest command
86
    builtins,
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
87
    errors,
88
    workingtree,
89
    )
90
""")
91
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
92
from bzrlib.commands import Command, register_command, display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
93
from bzrlib.errors import NotVersionedError, BzrCommandError, NoSuchFile
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
94
from bzrlib.option import Option
95
126.1.5 by Szilveszter Farkas (Phanatic)
bzr gbranch should work now (Fixed: #77751)
96
import os.path
97
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
98
def import_pygtk():
99
    try:
100
        import pygtk
101
    except ImportError:
102
        raise errors.BzrCommandError("PyGTK not installed.")
103
    pygtk.require('2.0')
104
    return pygtk
105
106
133 by Jelmer Vernooij
Actually use the ui factory.
107
def set_ui_factory():
177 by Jelmer Vernooij
Register commands all at once.
108
    import_pygtk()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
109
    from ui import GtkUIFactory
133 by Jelmer Vernooij
Actually use the ui factory.
110
    import bzrlib.ui
111
    bzrlib.ui.ui_factory = GtkUIFactory()
112
113
247 by Jelmer Vernooij
Use application path to find icons.
114
def data_path():
115
    return os.path.dirname(__file__)
116
117
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
118
class GTKCommand(Command):
119
    """Abstract class providing GTK specific run commands."""
120
121
    def open_display(self):
122
        pygtk = import_pygtk()
123
        try:
124
            import gtk
125
        except RuntimeError, e:
126
            if str(e) == "could not open display":
127
                raise NoDisplayError
128
        set_ui_factory()
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
129
        return gtk
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
130
131
    def run(self):
132
        self.open_display()
133
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
134
        dialog.run()
135
136
137
class cmd_gbranch(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
138
    """GTK+ branching.
139
    
140
    """
141
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
142
    def get_gtk_dialog(self, path):
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
143
        from bzrlib.plugins.gtk.branch import BranchDialog
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
144
        return BranchDialog(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
145
146
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
147
class cmd_gcheckout(GTKCommand):
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
148
    """ GTK+ checkout.
149
    
150
    """
151
    
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
152
    def get_gtk_dialog(self, path):
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
153
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
154
        return CheckoutDialog(path)
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
155
156
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
157
158
class cmd_gpush(GTKCommand):
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
159
    """ GTK+ push.
160
    
161
    """
162
    takes_args = [ "location?" ]
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
163
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
164
    def run(self, location="."):
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
165
        (br, path) = branch.Branch.open_containing(location)
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
166
        self.open_display()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
167
        from push import PushDialog
233 by Jelmer Vernooij
Get rid of test button in push.
168
        dialog = PushDialog(br.repository, br.last_revision(), br)
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
169
        dialog.run()
170
171
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
172
173
class cmd_gdiff(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
174
    """Show differences in working tree in a GTK+ Window.
175
    
176
    Otherwise, all changes for the tree are listed.
177
    """
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
178
    takes_args = ['filename?']
58.1.1 by Aaron Bentley
gdiff takes -r arguments
179
    takes_options = ['revision']
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
180
181
    @display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
182
    def run(self, revision=None, filename=None):
133 by Jelmer Vernooij
Actually use the ui factory.
183
        set_ui_factory()
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
184
        wt = workingtree.WorkingTree.open_containing(".")[0]
161 by Aaron Bentley
Fix gannotate interaction with dirstate
185
        wt.lock_read()
186
        try:
187
            branch = wt.branch
188
            if revision is not None:
189
                if len(revision) == 1:
190
                    tree1 = wt
191
                    revision_id = revision[0].in_history(branch).rev_id
192
                    tree2 = branch.repository.revision_tree(revision_id)
193
                elif len(revision) == 2:
194
                    revision_id_0 = revision[0].in_history(branch).rev_id
195
                    tree2 = branch.repository.revision_tree(revision_id_0)
196
                    revision_id_1 = revision[1].in_history(branch).rev_id
197
                    tree1 = branch.repository.revision_tree(revision_id_1)
198
            else:
58.1.1 by Aaron Bentley
gdiff takes -r arguments
199
                tree1 = wt
161 by Aaron Bentley
Fix gannotate interaction with dirstate
200
                tree2 = tree1.basis_tree()
201
202
            from diff import DiffWindow
203
            import gtk
204
            window = DiffWindow()
205
            window.connect("destroy", gtk.main_quit)
206
            window.set_diff("Working Tree", tree1, tree2)
207
            if filename is not None:
208
                tree_filename = wt.relpath(filename)
209
                try:
210
                    window.set_file(tree_filename)
211
                except NoSuchFile:
188.3.1 by John Arbash Meinel
Use tree.path2id to avoid getting 'Object Not Locked' errors.
212
                    if (tree1.path2id(tree_filename) is None and 
213
                        tree2.path2id(tree_filename) is None):
161 by Aaron Bentley
Fix gannotate interaction with dirstate
214
                        raise NotVersionedError(filename)
215
                    raise BzrCommandError('No changes found for file "%s"' % 
216
                                          filename)
217
            window.show()
218
219
            gtk.main()
220
        finally:
221
            wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
222
223
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
224
def start_viz_window(branch, revision, limit=None):
225
    """Start viz on branch with revision revision.
226
    
227
    :return: The viz window object.
228
    """
229
    from viz.branchwin import BranchWindow
230
    branch.lock_read()
231
    pp = BranchWindow()
232
    pp.set_branch(branch, revision, limit)
233
    # cleanup locks when the window is closed
234
    pp.connect("destroy", lambda w: branch.unlock())
235
    return pp
236
237
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
238
class cmd_visualise(Command):
239
    """Graphically visualise this branch.
240
241
    Opens a graphical window to allow you to see the history of the branch
242
    and relationships between revisions in a visual manner,
243
244
    The default starting point is latest revision on the branch, you can
245
    specify a starting point with -r revision.
246
    """
247
    takes_options = [
248
        "revision",
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
249
        Option('limit', "Maximum number of revisions to display.",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
250
               int, 'count')]
251
    takes_args = [ "location?" ]
252
    aliases = [ "visualize", "vis", "viz" ]
253
254
    def run(self, location=".", revision=None, limit=None):
133 by Jelmer Vernooij
Actually use the ui factory.
255
        set_ui_factory()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
256
        (br, path) = branch.Branch.open_containing(location)
257
        br.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
258
        try:
259
            if revision is None:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
260
                revid = br.last_revision()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
261
                if revid is None:
262
                    return
263
            else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
264
                (revno, revid) = revision[0].in_history(br)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
265
152 by Jelmer Vernooij
Cleanup some more code.
266
            import gtk
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
267
            pp = start_viz_window(br, revid, limit)
152 by Jelmer Vernooij
Cleanup some more code.
268
            pp.connect("destroy", lambda w: gtk.main_quit())
269
            pp.show()
270
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
271
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
272
            br.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
273
274
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
275
class cmd_gannotate(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
276
    """GTK+ annotate.
277
    
278
    Browse changes to FILENAME line by line in a GTK+ window.
279
    """
280
59.2.1 by Aaron Bentley
Gannotate takes a line number
281
    takes_args = ["filename", "line?"]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
282
    takes_options = [
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
283
        Option("all", help="Show annotations on all lines."),
284
        Option("plain", help="Don't highlight annotation lines."),
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
285
        Option("line", type=int, argname="lineno",
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
286
               help="Jump to specified line number."),
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
287
        "revision",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
288
    ]
289
    aliases = ["gblame", "gpraise"]
290
    
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
291
    def run(self, filename, all=False, plain=False, line='1', revision=None):
187 by Jelmer Vernooij
Fix gannotate.
292
        gtk = self.open_display()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
293
59.2.1 by Aaron Bentley
Gannotate takes a line number
294
        try:
295
            line = int(line)
296
        except ValueError:
297
            raise BzrCommandError('Line argument ("%s") is not a number.' % 
298
                                  line)
299
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
300
        from annotate.gannotate import GAnnotateWindow
301
        from annotate.config import GAnnotateConfig
177 by Jelmer Vernooij
Register commands all at once.
302
        from bzrlib.bzrdir import BzrDir
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
303
161 by Aaron Bentley
Fix gannotate interaction with dirstate
304
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
305
        if wt is not None:
306
            tree = wt
307
        else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
308
            tree = br.basis_tree()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
309
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
310
        file_id = tree.path2id(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
311
312
        if file_id is None:
313
            raise NotVersionedError(filename)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
314
        if revision is not None:
315
            if len(revision) != 1:
316
                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
317
            revision_id = revision[0].in_history(br).rev_id
318
            tree = br.repository.revision_tree(revision_id)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
319
        else:
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
320
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
321
322
        window = GAnnotateWindow(all, plain)
323
        window.connect("destroy", lambda w: gtk.main_quit())
324
        window.set_title(path + " - gannotate")
325
        config = GAnnotateConfig(window)
326
        window.show()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
327
        br.lock_read()
161 by Aaron Bentley
Fix gannotate interaction with dirstate
328
        if wt is not None:
329
            wt.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
330
        try:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
331
            window.annotate(tree, br, file_id)
161 by Aaron Bentley
Fix gannotate interaction with dirstate
332
            window.jump_to_line(line)
333
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
334
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
335
            br.unlock()
161 by Aaron Bentley
Fix gannotate interaction with dirstate
336
            if wt is not None:
337
                wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
338
339
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
340
341
class cmd_gcommit(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
342
    """GTK+ commit dialog
343
344
    Graphical user interface for committing revisions"""
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
345
145 by Jelmer Vernooij
Fix some strings, import.
346
    aliases = [ "gci" ]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
347
    takes_args = []
348
    takes_options = []
349
350
    def run(self, filename=None):
93.1.17 by Alexander Belchenko
gcommit reworked again.
351
        import os
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
352
        self.open_display()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
353
        from commit import CommitDialog
93.1.17 by Alexander Belchenko
gcommit reworked again.
354
        from bzrlib.errors import (BzrCommandError,
355
                                   NotBranchError,
178 by Jelmer Vernooij
Remove unneeded imports.
356
                                   NoWorkingTree)
93.1.17 by Alexander Belchenko
gcommit reworked again.
357
358
        wt = None
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
359
        br = None
93.1.17 by Alexander Belchenko
gcommit reworked again.
360
        try:
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
361
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
362
            br = wt.branch
93.1.17 by Alexander Belchenko
gcommit reworked again.
363
        except NoWorkingTree, e:
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
364
            from dialog import error_dialog
365
            error_dialog(_('Directory does not have a working tree'),
366
                         _('Operation aborted.'))
367
            return 1 # should this be retval=3?
368
369
        # It is a good habit to keep things locked for the duration, but it
370
        # could cause difficulties if someone wants to do things in another
371
        # window... We could lock_read() until we actually go to commit
372
        # changes... Just a thought.
373
        wt.lock_write()
374
        try:
375
            dlg = CommitDialog(wt)
376
            return dlg.run()
377
        finally:
378
            wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
379
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
380
250 by Aaron Bentley
oops- revert status change
381
class cmd_gstatus(GTKCommand):
157 by Jelmer Vernooij
Add gstatus command.
382
    """GTK+ status dialog
383
384
    Graphical user interface for showing status 
385
    information."""
386
    
387
    aliases = [ "gst" ]
388
    takes_args = ['PATH?']
389
    takes_options = []
390
391
    def run(self, path='.'):
392
        import os
184 by Jelmer Vernooij
Fix gstatus
393
        gtk = self.open_display()
157 by Jelmer Vernooij
Add gstatus command.
394
        from status import StatusDialog
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
395
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
157 by Jelmer Vernooij
Add gstatus command.
396
        status = StatusDialog(wt, wt_path)
397
        status.connect("destroy", gtk.main_quit)
398
        status.run()
399
400
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
401
402
class cmd_gconflicts(GTKCommand):
242.1.2 by Adeodato Simó
Fix gconflicts docstring.
403
    """ GTK+ conflicts.
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
404
    
242.1.2 by Adeodato Simó
Fix gconflicts docstring.
405
    Select files from the list of conflicts and run an external utility to
406
    resolve them.
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
407
    """
408
    def run(self):
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
409
        (wt, path) = workingtree.WorkingTree.open_containing('.')
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
410
        self.open_display()
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
411
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
412
        dialog = ConflictsDialog(wt)
413
        dialog.run()
414
157 by Jelmer Vernooij
Add gstatus command.
415
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
416
417
class cmd_gpreferences(GTKCommand):
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
418
    """ GTK+ preferences dialog.
419
420
    """
421
    def run(self):
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
422
        self.open_display()
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
423
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
424
        dialog = PreferencesWindow()
425
        dialog.run()
426
427
175 by Jelmer Vernooij
Add very simple gmissing command.
428
429
class cmd_gmissing(Command):
430
    """ GTK+ missing revisions dialog.
431
432
    """
433
    takes_args = ["other_branch?"]
434
    def run(self, other_branch=None):
435
        pygtk = import_pygtk()
436
        try:
437
            import gtk
438
        except RuntimeError, e:
439
            if str(e) == "could not open display":
440
                raise NoDisplayError
441
442
        from bzrlib.plugins.gtk.missing import MissingWindow
443
        from bzrlib.branch import Branch
444
445
        local_branch = Branch.open_containing(".")[0]
446
        if other_branch is None:
447
            other_branch = local_branch.get_parent()
448
            
449
            if other_branch is None:
450
                raise errors.BzrCommandError("No peer location known or specified.")
451
        remote_branch = Branch.open_containing(other_branch)[0]
452
        set_ui_factory()
453
        local_branch.lock_read()
454
        try:
455
            remote_branch.lock_read()
456
            try:
457
                dialog = MissingWindow(local_branch, remote_branch)
458
                dialog.run()
459
            finally:
460
                remote_branch.unlock()
461
        finally:
462
            local_branch.unlock()
463
177 by Jelmer Vernooij
Register commands all at once.
464
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
465
class cmd_ginit(GTKCommand):
466
    def run(self):
467
        self.open_display()
468
        from initialize import InitDialog
469
        dialog = InitDialog(os.path.abspath(os.path.curdir))
470
        dialog.run()
471
472
190.1.1 by Szilveszter Farkas (Phanatic)
Added 'gtags' command and basic Tags window (just a skeleton).
473
class cmd_gtags(GTKCommand):
474
    def run(self):
475
        br = branch.Branch.open_containing('.')[0]
476
        
477
        gtk = self.open_display()
478
        from tags import TagsWindow
479
        window = TagsWindow(br)
480
        window.show()
481
        gtk.main()
482
483
177 by Jelmer Vernooij
Register commands all at once.
484
commands = [
485
    cmd_gmissing, 
486
    cmd_gpreferences, 
487
    cmd_gconflicts, 
488
    cmd_gstatus,
489
    cmd_gcommit, 
490
    cmd_gannotate, 
491
    cmd_visualise, 
492
    cmd_gdiff,
493
    cmd_gpush, 
494
    cmd_gcheckout, 
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
495
    cmd_gbranch,
190.1.1 by Szilveszter Farkas (Phanatic)
Added 'gtags' command and basic Tags window (just a skeleton).
496
    cmd_ginit,
497
    cmd_gtags
177 by Jelmer Vernooij
Register commands all at once.
498
    ]
499
500
for cmd in commands:
501
    register_command(cmd)
175 by Jelmer Vernooij
Add very simple gmissing command.
502
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
503
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
504
class cmd_commit_notify(GTKCommand):
505
    """Run the bzr commit notifier.
506
507
    This is a background program which will pop up a notification on the users
508
    screen when a commit occurs.
509
    """
510
511
    def run(self):
211 by Jelmer Vernooij
Move notification area code into separate file.
512
        from notify import NotifyPopupMenu
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
513
        gtk = self.open_display()
211 by Jelmer Vernooij
Move notification area code into separate file.
514
        menu = NotifyPopupMenu()
247 by Jelmer Vernooij
Use application path to find icons.
515
        icon = gtk.status_icon_new_from_file(os.path.join(data_path(), "bzr-icon-64.png"))
211 by Jelmer Vernooij
Move notification area code into separate file.
516
        icon.connect('popup-menu', menu.display)
210 by Jelmer Vernooij
Add notification area icon for commit-notify.
517
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
518
        import cgi
519
        import dbus
520
        import dbus.service
521
        import pynotify
522
        from bzrlib.bzrdir import BzrDir
523
        from bzrlib import errors
524
        from bzrlib.osutils import format_date
525
        from bzrlib.transport import get_transport
526
        if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
527
            import dbus.glib
528
        from bzrlib.plugins.dbus import activity
529
        bus = dbus.SessionBus()
530
        # get the object so we can subscribe to callbacks from it.
531
        broadcast_service = bus.get_object(
532
            activity.Broadcast.DBUS_NAME,
533
            activity.Broadcast.DBUS_PATH)
211 by Jelmer Vernooij
Move notification area code into separate file.
534
182.1.1 by Robert Collins
Update commit-notify to use new dbus api, and show remote URL's.
535
        def catch_branch(revision_id, urls):
536
            # TODO: show all the urls, or perhaps choose the 'best'.
537
            url = urls[0]
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
538
            try:
539
                if isinstance(revision_id, unicode):
540
                    revision_id = revision_id.encode('utf8')
541
                transport = get_transport(url)
542
                a_dir = BzrDir.open_from_transport(transport)
543
                branch = a_dir.open_branch()
544
                revno = branch.revision_id_to_revno(revision_id)
545
                revision = branch.repository.get_revision(revision_id)
546
                summary = 'New revision %d in %s' % (revno, url)
547
                body  = 'Committer: %s\n' % revision.committer
548
                body += 'Date: %s\n' % format_date(revision.timestamp,
549
                    revision.timezone)
550
                body += '\n'
551
                body += revision.message
552
                body = cgi.escape(body)
553
                nw = pynotify.Notification(summary, body)
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
554
                def start_viz(notification=None, action=None, data=None):
555
                    """Start the viz program."""
556
                    pp = start_viz_window(branch, revision_id)
557
                    pp.show()
208.2.3 by Robert Collins
Add a Branch button to commit-notify.
558
                def start_branch(notification=None, action=None, data=None):
559
                    """Start a Branch dialog"""
560
                    from bzrlib.plugins.gtk.branch import BranchDialog
561
                    bd = BranchDialog(remote_path=url)
562
                    bd.run()
208.2.4 by Robert Collins
Unbreak inspect of commits due to misunderstanding of pynotify api.
563
                nw.add_action("inspect", "Inspect", start_viz, None)
564
                nw.add_action("branch", "Branch", start_branch, None)
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
565
                nw.set_timeout(5000)
566
                nw.show()
567
            except Exception, e:
568
                print e
569
                raise
570
        broadcast_service.connect_to_signal("Revision", catch_branch,
571
            dbus_interface=activity.Broadcast.DBUS_INTERFACE)
572
        pynotify.init("bzr commit-notify")
573
        gtk.main()
574
575
register_command(cmd_commit_notify)
576
577
249 by Aaron Bentley
Add gselftest command
578
class cmd_gselftest(GTKCommand):
579
    """Version of selftest that displays a notification at the end"""
580
581
    takes_args = builtins.cmd_selftest.takes_args
582
    takes_options = builtins.cmd_selftest.takes_options
583
    _see_also = ['selftest']
584
585
    def run(self, *args, **kwargs):
586
        import cgi
253 by Aaron Bentley
Avoid encoding problems from pygtk
587
        import sys
588
        default_encoding = sys.getdefaultencoding()
249 by Aaron Bentley
Add gselftest command
589
        # prevent gtk from blowing up later
590
        gtk = import_pygtk()
253 by Aaron Bentley
Avoid encoding problems from pygtk
591
        # prevent gtk from messing with default encoding
249 by Aaron Bentley
Add gselftest command
592
        import pynotify
253 by Aaron Bentley
Avoid encoding problems from pygtk
593
        if sys.getdefaultencoding() != default_encoding:
594
            reload(sys)
595
            sys.setdefaultencoding(default_encoding)
249 by Aaron Bentley
Add gselftest command
596
        result = builtins.cmd_selftest().run(*args, **kwargs)
597
        if result == 0:
598
            summary = 'Success'
599
            body = 'Selftest succeeded in "%s"' % os.getcwd()
600
        if result == 1:
601
            summary = 'Failure'
602
            body = 'Selftest failed in "%s"' % os.getcwd()
603
        pynotify.init("bzr gselftest")
604
        note = pynotify.Notification(cgi.escape(summary), cgi.escape(body))
605
        note.set_timeout(pynotify.EXPIRES_NEVER)
606
        note.show()
607
608
609
register_command(cmd_gselftest)
610
611
278.1.22 by John Arbash Meinel
Add a test-gtk command to make testing faster
612
class cmd_test_gtk(GTKCommand):
613
    """Version of selftest that just runs the gtk test suite."""
614
615
    takes_options = ['verbose',
616
                     Option('one', short_name='1',
617
                            help='stop when one test fails'),
618
                     Option('benchmark', help='run the benchmarks.'),
619
                     Option('lsprof-timed',
620
                     help='generate lsprof output for benchmarked'
621
                          ' sections of code.'),
622
                     Option('list-only',
623
                     help='list the tests instead of running them'),
624
                     Option('randomize', type=str, argname="SEED",
625
                     help='randomize the order of tests using the given'
626
                          ' seed or "now" for the current time'),
627
                    ]
628
    takes_args = ['testspecs*']
629
630
    def run(self, verbose=None, one=False, benchmark=None,
631
            lsprof_timed=None, list_only=False, randomize=None,
632
            testspecs_list=None):
633
        from bzrlib import __path__ as bzrlib_path
634
        from bzrlib.tests import selftest
635
636
        print '%10s: %s' % ('bzrlib', bzrlib_path[0])
637
        if benchmark:
638
            print 'No benchmarks yet'
639
            return 3
640
641
            test_suite_factory = bench_suite
642
            if verbose is None:
643
                verbose = True
644
            # TODO: should possibly lock the history file...
645
            benchfile = open(".perf_history", "at", buffering=1)
646
        else:
647
            test_suite_factory = test_suite
648
            if verbose is None:
649
                verbose = False
650
            benchfile = None
651
652
        if testspecs_list is not None:
653
            pattern = '|'.join(testspecs_list)
654
        else:
655
            pattern = ".*"
656
657
        try:
658
            result = selftest(verbose=verbose,
659
                              pattern=pattern,
660
                              stop_on_failure=one,
661
                              test_suite_factory=test_suite_factory,
662
                              lsprof_timed=lsprof_timed,
663
                              bench_history=benchfile,
664
                              list_only=list_only,
665
                              random_seed=randomize,
666
                             )
667
        finally:
668
            if benchfile is not None:
669
                benchfile.close()
670
671
register_command(cmd_test_gtk)
672
673
152 by Jelmer Vernooij
Cleanup some more code.
674
import gettext
675
gettext.install('olive-gtk')
676
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
677
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
678
class NoDisplayError(BzrCommandError):
679
    """gtk could not find a proper display"""
680
681
    def __str__(self):
133 by Jelmer Vernooij
Actually use the ui factory.
682
        return "No DISPLAY. Unable to run GTK+ application."
683
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
684
140 by Jelmer Vernooij
add framework for tests.
685
def test_suite():
686
    from unittest import TestSuite
687
    import tests
163 by Aaron Bentley
Prevent test suite from causing default-encoding changes
688
    import sys
689
    default_encoding = sys.getdefaultencoding()
690
    try:
691
        result = TestSuite()
692
        result.addTest(tests.test_suite())
693
    finally:
170.1.2 by Aaron Bentley
Test suite only fixes encoding if it's changed. Fixes test_selftest bug.
694
        if sys.getdefaultencoding() != default_encoding:
695
            reload(sys)
696
            sys.setdefaultencoding(default_encoding)
140 by Jelmer Vernooij
add framework for tests.
697
    return result