/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
315 by Daniel Schierbeck
Removed BranchWindow.set_branch(), used constructor instead.
230
    return BranchWindow(branch, revision, limit)
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
231
232
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
233
class cmd_visualise(Command):
234
    """Graphically visualise this branch.
235
236
    Opens a graphical window to allow you to see the history of the branch
237
    and relationships between revisions in a visual manner,
238
239
    The default starting point is latest revision on the branch, you can
240
    specify a starting point with -r revision.
241
    """
242
    takes_options = [
243
        "revision",
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
244
        Option('limit', "Maximum number of revisions to display.",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
245
               int, 'count')]
246
    takes_args = [ "location?" ]
247
    aliases = [ "visualize", "vis", "viz" ]
248
249
    def run(self, location=".", revision=None, limit=None):
133 by Jelmer Vernooij
Actually use the ui factory.
250
        set_ui_factory()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
251
        (br, path) = branch.Branch.open_containing(location)
252
        br.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
253
        try:
254
            if revision is None:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
255
                revid = br.last_revision()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
256
                if revid is None:
257
                    return
258
            else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
259
                (revno, revid) = revision[0].in_history(br)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
260
152 by Jelmer Vernooij
Cleanup some more code.
261
            import gtk
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
262
            pp = start_viz_window(br, revid, limit)
152 by Jelmer Vernooij
Cleanup some more code.
263
            pp.connect("destroy", lambda w: gtk.main_quit())
264
            pp.show()
265
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
266
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
267
            br.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
268
269
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
270
class cmd_gannotate(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
271
    """GTK+ annotate.
272
    
273
    Browse changes to FILENAME line by line in a GTK+ window.
274
    """
275
59.2.1 by Aaron Bentley
Gannotate takes a line number
276
    takes_args = ["filename", "line?"]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
277
    takes_options = [
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
278
        Option("all", help="Show annotations on all lines."),
279
        Option("plain", help="Don't highlight annotation lines."),
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
280
        Option("line", type=int, argname="lineno",
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
281
               help="Jump to specified line number."),
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
282
        "revision",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
283
    ]
284
    aliases = ["gblame", "gpraise"]
285
    
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
286
    def run(self, filename, all=False, plain=False, line='1', revision=None):
187 by Jelmer Vernooij
Fix gannotate.
287
        gtk = self.open_display()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
288
59.2.1 by Aaron Bentley
Gannotate takes a line number
289
        try:
290
            line = int(line)
291
        except ValueError:
292
            raise BzrCommandError('Line argument ("%s") is not a number.' % 
293
                                  line)
294
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
295
        from annotate.gannotate import GAnnotateWindow
296
        from annotate.config import GAnnotateConfig
177 by Jelmer Vernooij
Register commands all at once.
297
        from bzrlib.bzrdir import BzrDir
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
298
161 by Aaron Bentley
Fix gannotate interaction with dirstate
299
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
300
        if wt is not None:
301
            tree = wt
302
        else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
303
            tree = br.basis_tree()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
304
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
305
        file_id = tree.path2id(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
306
307
        if file_id is None:
308
            raise NotVersionedError(filename)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
309
        if revision is not None:
310
            if len(revision) != 1:
311
                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
312
            revision_id = revision[0].in_history(br).rev_id
313
            tree = br.repository.revision_tree(revision_id)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
314
        else:
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
315
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
316
317
        window = GAnnotateWindow(all, plain)
318
        window.connect("destroy", lambda w: gtk.main_quit())
319
        window.set_title(path + " - gannotate")
320
        config = GAnnotateConfig(window)
321
        window.show()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
322
        br.lock_read()
161 by Aaron Bentley
Fix gannotate interaction with dirstate
323
        if wt is not None:
324
            wt.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
325
        try:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
326
            window.annotate(tree, br, file_id)
161 by Aaron Bentley
Fix gannotate interaction with dirstate
327
            window.jump_to_line(line)
328
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
329
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
330
            br.unlock()
161 by Aaron Bentley
Fix gannotate interaction with dirstate
331
            if wt is not None:
332
                wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
333
334
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
335
336
class cmd_gcommit(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
337
    """GTK+ commit dialog
338
339
    Graphical user interface for committing revisions"""
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
340
145 by Jelmer Vernooij
Fix some strings, import.
341
    aliases = [ "gci" ]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
342
    takes_args = []
343
    takes_options = []
344
345
    def run(self, filename=None):
93.1.17 by Alexander Belchenko
gcommit reworked again.
346
        import os
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
347
        self.open_display()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
348
        from commit import CommitDialog
93.1.17 by Alexander Belchenko
gcommit reworked again.
349
        from bzrlib.errors import (BzrCommandError,
350
                                   NotBranchError,
178 by Jelmer Vernooij
Remove unneeded imports.
351
                                   NoWorkingTree)
93.1.17 by Alexander Belchenko
gcommit reworked again.
352
353
        wt = None
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
354
        br = None
93.1.17 by Alexander Belchenko
gcommit reworked again.
355
        try:
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
356
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
357
            br = wt.branch
93.1.17 by Alexander Belchenko
gcommit reworked again.
358
        except NoWorkingTree, e:
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
359
            from dialog import error_dialog
360
            error_dialog(_('Directory does not have a working tree'),
361
                         _('Operation aborted.'))
362
            return 1 # should this be retval=3?
363
364
        # It is a good habit to keep things locked for the duration, but it
365
        # could cause difficulties if someone wants to do things in another
366
        # window... We could lock_read() until we actually go to commit
367
        # changes... Just a thought.
368
        wt.lock_write()
369
        try:
370
            dlg = CommitDialog(wt)
371
            return dlg.run()
372
        finally:
373
            wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
374
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
375
250 by Aaron Bentley
oops- revert status change
376
class cmd_gstatus(GTKCommand):
157 by Jelmer Vernooij
Add gstatus command.
377
    """GTK+ status dialog
378
379
    Graphical user interface for showing status 
380
    information."""
381
    
382
    aliases = [ "gst" ]
383
    takes_args = ['PATH?']
384
    takes_options = []
385
386
    def run(self, path='.'):
387
        import os
184 by Jelmer Vernooij
Fix gstatus
388
        gtk = self.open_display()
157 by Jelmer Vernooij
Add gstatus command.
389
        from status import StatusDialog
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
390
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
157 by Jelmer Vernooij
Add gstatus command.
391
        status = StatusDialog(wt, wt_path)
392
        status.connect("destroy", gtk.main_quit)
393
        status.run()
394
395
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
396
397
class cmd_gconflicts(GTKCommand):
242.1.2 by Adeodato Simó
Fix gconflicts docstring.
398
    """ GTK+ conflicts.
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
399
    
242.1.2 by Adeodato Simó
Fix gconflicts docstring.
400
    Select files from the list of conflicts and run an external utility to
401
    resolve them.
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
402
    """
403
    def run(self):
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
404
        (wt, path) = workingtree.WorkingTree.open_containing('.')
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
405
        self.open_display()
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
406
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
407
        dialog = ConflictsDialog(wt)
408
        dialog.run()
409
157 by Jelmer Vernooij
Add gstatus command.
410
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
411
412
class cmd_gpreferences(GTKCommand):
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
413
    """ GTK+ preferences dialog.
414
415
    """
416
    def run(self):
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
417
        self.open_display()
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
418
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
419
        dialog = PreferencesWindow()
420
        dialog.run()
421
422
175 by Jelmer Vernooij
Add very simple gmissing command.
423
424
class cmd_gmissing(Command):
425
    """ GTK+ missing revisions dialog.
426
427
    """
428
    takes_args = ["other_branch?"]
429
    def run(self, other_branch=None):
430
        pygtk = import_pygtk()
431
        try:
432
            import gtk
433
        except RuntimeError, e:
434
            if str(e) == "could not open display":
435
                raise NoDisplayError
436
437
        from bzrlib.plugins.gtk.missing import MissingWindow
438
        from bzrlib.branch import Branch
439
440
        local_branch = Branch.open_containing(".")[0]
441
        if other_branch is None:
442
            other_branch = local_branch.get_parent()
443
            
444
            if other_branch is None:
445
                raise errors.BzrCommandError("No peer location known or specified.")
446
        remote_branch = Branch.open_containing(other_branch)[0]
447
        set_ui_factory()
448
        local_branch.lock_read()
449
        try:
450
            remote_branch.lock_read()
451
            try:
452
                dialog = MissingWindow(local_branch, remote_branch)
453
                dialog.run()
454
            finally:
455
                remote_branch.unlock()
456
        finally:
457
            local_branch.unlock()
458
177 by Jelmer Vernooij
Register commands all at once.
459
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
460
class cmd_ginit(GTKCommand):
461
    def run(self):
462
        self.open_display()
463
        from initialize import InitDialog
464
        dialog = InitDialog(os.path.abspath(os.path.curdir))
465
        dialog.run()
466
467
190.1.1 by Szilveszter Farkas (Phanatic)
Added 'gtags' command and basic Tags window (just a skeleton).
468
class cmd_gtags(GTKCommand):
469
    def run(self):
470
        br = branch.Branch.open_containing('.')[0]
471
        
472
        gtk = self.open_display()
473
        from tags import TagsWindow
474
        window = TagsWindow(br)
475
        window.show()
476
        gtk.main()
477
478
177 by Jelmer Vernooij
Register commands all at once.
479
commands = [
480
    cmd_gmissing, 
481
    cmd_gpreferences, 
482
    cmd_gconflicts, 
483
    cmd_gstatus,
484
    cmd_gcommit, 
485
    cmd_gannotate, 
486
    cmd_visualise, 
487
    cmd_gdiff,
488
    cmd_gpush, 
489
    cmd_gcheckout, 
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
490
    cmd_gbranch,
190.1.1 by Szilveszter Farkas (Phanatic)
Added 'gtags' command and basic Tags window (just a skeleton).
491
    cmd_ginit,
492
    cmd_gtags
177 by Jelmer Vernooij
Register commands all at once.
493
    ]
494
495
for cmd in commands:
496
    register_command(cmd)
175 by Jelmer Vernooij
Add very simple gmissing command.
497
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
498
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
499
class cmd_commit_notify(GTKCommand):
500
    """Run the bzr commit notifier.
501
502
    This is a background program which will pop up a notification on the users
503
    screen when a commit occurs.
504
    """
505
506
    def run(self):
211 by Jelmer Vernooij
Move notification area code into separate file.
507
        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.
508
        gtk = self.open_display()
211 by Jelmer Vernooij
Move notification area code into separate file.
509
        menu = NotifyPopupMenu()
247 by Jelmer Vernooij
Use application path to find icons.
510
        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.
511
        icon.connect('popup-menu', menu.display)
210 by Jelmer Vernooij
Add notification area icon for commit-notify.
512
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
513
        import cgi
514
        import dbus
515
        import dbus.service
516
        import pynotify
517
        from bzrlib.bzrdir import BzrDir
518
        from bzrlib import errors
519
        from bzrlib.osutils import format_date
520
        from bzrlib.transport import get_transport
521
        if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
522
            import dbus.glib
523
        from bzrlib.plugins.dbus import activity
524
        bus = dbus.SessionBus()
525
        # get the object so we can subscribe to callbacks from it.
526
        broadcast_service = bus.get_object(
527
            activity.Broadcast.DBUS_NAME,
528
            activity.Broadcast.DBUS_PATH)
211 by Jelmer Vernooij
Move notification area code into separate file.
529
182.1.1 by Robert Collins
Update commit-notify to use new dbus api, and show remote URL's.
530
        def catch_branch(revision_id, urls):
531
            # TODO: show all the urls, or perhaps choose the 'best'.
532
            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.
533
            try:
534
                if isinstance(revision_id, unicode):
535
                    revision_id = revision_id.encode('utf8')
536
                transport = get_transport(url)
537
                a_dir = BzrDir.open_from_transport(transport)
538
                branch = a_dir.open_branch()
539
                revno = branch.revision_id_to_revno(revision_id)
540
                revision = branch.repository.get_revision(revision_id)
541
                summary = 'New revision %d in %s' % (revno, url)
542
                body  = 'Committer: %s\n' % revision.committer
543
                body += 'Date: %s\n' % format_date(revision.timestamp,
544
                    revision.timezone)
545
                body += '\n'
546
                body += revision.message
547
                body = cgi.escape(body)
548
                nw = pynotify.Notification(summary, body)
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
549
                def start_viz(notification=None, action=None, data=None):
550
                    """Start the viz program."""
551
                    pp = start_viz_window(branch, revision_id)
552
                    pp.show()
208.2.3 by Robert Collins
Add a Branch button to commit-notify.
553
                def start_branch(notification=None, action=None, data=None):
554
                    """Start a Branch dialog"""
555
                    from bzrlib.plugins.gtk.branch import BranchDialog
556
                    bd = BranchDialog(remote_path=url)
557
                    bd.run()
208.2.4 by Robert Collins
Unbreak inspect of commits due to misunderstanding of pynotify api.
558
                nw.add_action("inspect", "Inspect", start_viz, None)
559
                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.
560
                nw.set_timeout(5000)
561
                nw.show()
562
            except Exception, e:
563
                print e
564
                raise
565
        broadcast_service.connect_to_signal("Revision", catch_branch,
566
            dbus_interface=activity.Broadcast.DBUS_INTERFACE)
567
        pynotify.init("bzr commit-notify")
568
        gtk.main()
569
570
register_command(cmd_commit_notify)
571
572
249 by Aaron Bentley
Add gselftest command
573
class cmd_gselftest(GTKCommand):
574
    """Version of selftest that displays a notification at the end"""
575
576
    takes_args = builtins.cmd_selftest.takes_args
577
    takes_options = builtins.cmd_selftest.takes_options
578
    _see_also = ['selftest']
579
580
    def run(self, *args, **kwargs):
581
        import cgi
253 by Aaron Bentley
Avoid encoding problems from pygtk
582
        import sys
583
        default_encoding = sys.getdefaultencoding()
249 by Aaron Bentley
Add gselftest command
584
        # prevent gtk from blowing up later
585
        gtk = import_pygtk()
253 by Aaron Bentley
Avoid encoding problems from pygtk
586
        # prevent gtk from messing with default encoding
249 by Aaron Bentley
Add gselftest command
587
        import pynotify
253 by Aaron Bentley
Avoid encoding problems from pygtk
588
        if sys.getdefaultencoding() != default_encoding:
589
            reload(sys)
590
            sys.setdefaultencoding(default_encoding)
249 by Aaron Bentley
Add gselftest command
591
        result = builtins.cmd_selftest().run(*args, **kwargs)
592
        if result == 0:
593
            summary = 'Success'
594
            body = 'Selftest succeeded in "%s"' % os.getcwd()
595
        if result == 1:
596
            summary = 'Failure'
597
            body = 'Selftest failed in "%s"' % os.getcwd()
598
        pynotify.init("bzr gselftest")
599
        note = pynotify.Notification(cgi.escape(summary), cgi.escape(body))
600
        note.set_timeout(pynotify.EXPIRES_NEVER)
601
        note.show()
602
603
604
register_command(cmd_gselftest)
605
606
278.1.22 by John Arbash Meinel
Add a test-gtk command to make testing faster
607
class cmd_test_gtk(GTKCommand):
608
    """Version of selftest that just runs the gtk test suite."""
609
610
    takes_options = ['verbose',
611
                     Option('one', short_name='1',
612
                            help='stop when one test fails'),
613
                     Option('benchmark', help='run the benchmarks.'),
614
                     Option('lsprof-timed',
615
                     help='generate lsprof output for benchmarked'
616
                          ' sections of code.'),
617
                     Option('list-only',
618
                     help='list the tests instead of running them'),
619
                     Option('randomize', type=str, argname="SEED",
620
                     help='randomize the order of tests using the given'
621
                          ' seed or "now" for the current time'),
622
                    ]
623
    takes_args = ['testspecs*']
624
625
    def run(self, verbose=None, one=False, benchmark=None,
626
            lsprof_timed=None, list_only=False, randomize=None,
627
            testspecs_list=None):
628
        from bzrlib import __path__ as bzrlib_path
629
        from bzrlib.tests import selftest
630
631
        print '%10s: %s' % ('bzrlib', bzrlib_path[0])
632
        if benchmark:
633
            print 'No benchmarks yet'
634
            return 3
635
636
            test_suite_factory = bench_suite
637
            if verbose is None:
638
                verbose = True
639
            # TODO: should possibly lock the history file...
640
            benchfile = open(".perf_history", "at", buffering=1)
641
        else:
642
            test_suite_factory = test_suite
643
            if verbose is None:
644
                verbose = False
645
            benchfile = None
646
647
        if testspecs_list is not None:
648
            pattern = '|'.join(testspecs_list)
649
        else:
650
            pattern = ".*"
651
652
        try:
653
            result = selftest(verbose=verbose,
654
                              pattern=pattern,
655
                              stop_on_failure=one,
656
                              test_suite_factory=test_suite_factory,
657
                              lsprof_timed=lsprof_timed,
658
                              bench_history=benchfile,
659
                              list_only=list_only,
660
                              random_seed=randomize,
661
                             )
662
        finally:
663
            if benchfile is not None:
664
                benchfile.close()
665
666
register_command(cmd_test_gtk)
667
668
152 by Jelmer Vernooij
Cleanup some more code.
669
import gettext
670
gettext.install('olive-gtk')
671
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
672
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
673
class NoDisplayError(BzrCommandError):
674
    """gtk could not find a proper display"""
675
676
    def __str__(self):
133 by Jelmer Vernooij
Actually use the ui factory.
677
        return "No DISPLAY. Unable to run GTK+ application."
678
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
679
140 by Jelmer Vernooij
add framework for tests.
680
def test_suite():
681
    from unittest import TestSuite
682
    import tests
163 by Aaron Bentley
Prevent test suite from causing default-encoding changes
683
    import sys
684
    default_encoding = sys.getdefaultencoding()
685
    try:
686
        result = TestSuite()
687
        result.addTest(tests.test_suite())
688
    finally:
170.1.2 by Aaron Bentley
Test suite only fixes encoding if it's changed. Fixes test_selftest bug.
689
        if sys.getdefaultencoding() != default_encoding:
690
            reload(sys)
691
            sys.setdefaultencoding(default_encoding)
140 by Jelmer Vernooij
add framework for tests.
692
    return result