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