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