/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
49 by Jelmer Vernooij
Merge in Dan Loda's gannotate plugin and put it in annotate/
1
# This program is free software; you can redistribute it and/or modify
2
# it under the terms of the GNU General Public License as published by
3
# the Free Software Foundation; either version 2 of the License, or
4
# (at your option) any later version.
5
6
# This program is distributed in the hope that it will be useful,
7
# but WITHOUT ANY WARRANTY; without even the implied warranty of
8
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9
# GNU General Public License for more details.
10
11
# You should have received a copy of the GNU General Public License
12
# along with this program; if not, write to the Free Software
13
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
14
15
"""GTK+ frontends to Bazaar commands """
73 by Jelmer Vernooij
Release 0.9, list myself as maintainer.
16
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
17
import bzrlib
18
188 by Jelmer Vernooij
merge 0.15.2 NEWS update.
19
__version__ = '0.16.0'
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
20
version_info = tuple(int(n) for n in __version__.split('.'))
21
22
23
def check_bzrlib_version(desired):
24
    """Check that bzrlib is compatible.
25
26
    If version is < bzr-gtk version, assume incompatible.
27
    If version == bzr-gtk version, assume completely compatible
28
    If version == bzr-gtk version + 1, assume compatible, with deprecations
29
    Otherwise, assume incompatible.
30
    """
31
    desired_plus = (desired[0], desired[1]+1)
32
    bzrlib_version = bzrlib.version_info[:2]
33
    if bzrlib_version == desired:
34
        return
35
    try:
36
        from bzrlib.trace import warning
37
    except ImportError:
38
        # get the message out any way we can
39
        from warnings import warn as warning
40
    if bzrlib_version < desired:
41
        warning('Installed bzr version %s is too old to be used with bzr-gtk'
42
                ' %s.' % (bzrlib.__version__, __version__))
43
        # Not using BzrNewError, because it may not exist.
44
        raise Exception, ('Version mismatch', version_info)
45
    else:
46
        warning('bzr-gtk is not up to date with installed bzr version %s.'
47
                ' \nThere should be a newer version available, e.g. %i.%i.' 
48
                % (bzrlib.__version__, bzrlib_version[0], bzrlib_version[1]))
49
        if bzrlib_version != desired_plus:
50
            raise Exception, 'Version mismatch'
51
52
53
check_bzrlib_version(version_info[:2])
54
146 by Jelmer Vernooij
Move more code to top-level directory.
55
from bzrlib.trace import warning
56
if __name__ != 'bzrlib.plugins.gtk':
57
    warning("Not running as bzrlib.plugins.gtk, things may break.")
58
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
59
from bzrlib.lazy_import import lazy_import
60
lazy_import(globals(), """
61
from bzrlib import (
62
    branch,
63
    errors,
64
    workingtree,
65
    )
66
""")
67
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
68
from bzrlib.commands import Command, register_command, display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
69
from bzrlib.errors import NotVersionedError, BzrCommandError, NoSuchFile
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
70
from bzrlib.option import Option
71
126.1.5 by Szilveszter Farkas (Phanatic)
bzr gbranch should work now (Fixed: #77751)
72
import os.path
73
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
74
def import_pygtk():
75
    try:
76
        import pygtk
77
    except ImportError:
78
        raise errors.BzrCommandError("PyGTK not installed.")
79
    pygtk.require('2.0')
80
    return pygtk
81
82
133 by Jelmer Vernooij
Actually use the ui factory.
83
def set_ui_factory():
177 by Jelmer Vernooij
Register commands all at once.
84
    import_pygtk()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
85
    from ui import GtkUIFactory
133 by Jelmer Vernooij
Actually use the ui factory.
86
    import bzrlib.ui
87
    bzrlib.ui.ui_factory = GtkUIFactory()
88
89
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
90
class GTKCommand(Command):
91
    """Abstract class providing GTK specific run commands."""
92
93
    def open_display(self):
94
        pygtk = import_pygtk()
95
        try:
96
            import gtk
97
        except RuntimeError, e:
98
            if str(e) == "could not open display":
99
                raise NoDisplayError
100
        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.
101
        return gtk
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
102
103
    def run(self):
104
        self.open_display()
105
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
106
        dialog.run()
107
108
109
class cmd_gbranch(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
110
    """GTK+ branching.
111
    
112
    """
113
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
114
    def get_gtk_dialog(self, path):
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
115
        from bzrlib.plugins.gtk.branch import BranchDialog
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
116
        return BranchDialog(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
117
118
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
119
class cmd_gcheckout(GTKCommand):
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
120
    """ GTK+ checkout.
121
    
122
    """
123
    
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
124
    def get_gtk_dialog(self, path):
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
125
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
126
        return CheckoutDialog(path)
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
127
128
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
129
130
class cmd_gpush(GTKCommand):
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
131
    """ GTK+ push.
132
    
133
    """
134
    takes_args = [ "location?" ]
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
135
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
136
    def run(self, location="."):
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
137
        (br, path) = branch.Branch.open_containing(location)
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
138
        self.open_display()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
139
        from push import PushDialog
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
140
        dialog = PushDialog(br)
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
141
        dialog.run()
142
143
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
144
145
class cmd_gdiff(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
146
    """Show differences in working tree in a GTK+ Window.
147
    
148
    Otherwise, all changes for the tree are listed.
149
    """
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
150
    takes_args = ['filename?']
58.1.1 by Aaron Bentley
gdiff takes -r arguments
151
    takes_options = ['revision']
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
152
153
    @display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
154
    def run(self, revision=None, filename=None):
133 by Jelmer Vernooij
Actually use the ui factory.
155
        set_ui_factory()
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
156
        wt = workingtree.WorkingTree.open_containing(".")[0]
161 by Aaron Bentley
Fix gannotate interaction with dirstate
157
        wt.lock_read()
158
        try:
159
            branch = wt.branch
160
            if revision is not None:
161
                if len(revision) == 1:
162
                    tree1 = wt
163
                    revision_id = revision[0].in_history(branch).rev_id
164
                    tree2 = branch.repository.revision_tree(revision_id)
165
                elif len(revision) == 2:
166
                    revision_id_0 = revision[0].in_history(branch).rev_id
167
                    tree2 = branch.repository.revision_tree(revision_id_0)
168
                    revision_id_1 = revision[1].in_history(branch).rev_id
169
                    tree1 = branch.repository.revision_tree(revision_id_1)
170
            else:
58.1.1 by Aaron Bentley
gdiff takes -r arguments
171
                tree1 = wt
161 by Aaron Bentley
Fix gannotate interaction with dirstate
172
                tree2 = tree1.basis_tree()
173
174
            from diff import DiffWindow
175
            import gtk
176
            window = DiffWindow()
177
            window.connect("destroy", gtk.main_quit)
178
            window.set_diff("Working Tree", tree1, tree2)
179
            if filename is not None:
180
                tree_filename = wt.relpath(filename)
181
                try:
182
                    window.set_file(tree_filename)
183
                except NoSuchFile:
184
                    if (tree1.inventory.path2id(tree_filename) is None and 
185
                        tree2.inventory.path2id(tree_filename) is None):
186
                        raise NotVersionedError(filename)
187
                    raise BzrCommandError('No changes found for file "%s"' % 
188
                                          filename)
189
            window.show()
190
191
            gtk.main()
192
        finally:
193
            wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
194
195
196
class cmd_visualise(Command):
197
    """Graphically visualise this branch.
198
199
    Opens a graphical window to allow you to see the history of the branch
200
    and relationships between revisions in a visual manner,
201
202
    The default starting point is latest revision on the branch, you can
203
    specify a starting point with -r revision.
204
    """
205
    takes_options = [
206
        "revision",
207
        Option('limit', "maximum number of revisions to display",
208
               int, 'count')]
209
    takes_args = [ "location?" ]
210
    aliases = [ "visualize", "vis", "viz" ]
211
212
    def run(self, location=".", revision=None, limit=None):
133 by Jelmer Vernooij
Actually use the ui factory.
213
        set_ui_factory()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
214
        (br, path) = branch.Branch.open_containing(location)
215
        br.lock_read()
216
        br.repository.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
217
        try:
218
            if revision is None:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
219
                revid = br.last_revision()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
220
                if revid is None:
221
                    return
222
            else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
223
                (revno, revid) = revision[0].in_history(br)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
224
152 by Jelmer Vernooij
Cleanup some more code.
225
            from viz.branchwin import BranchWindow
226
            import gtk
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
227
                
152 by Jelmer Vernooij
Cleanup some more code.
228
            pp = BranchWindow()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
229
            pp.set_branch(br, revid, limit)
152 by Jelmer Vernooij
Cleanup some more code.
230
            pp.connect("destroy", lambda w: gtk.main_quit())
231
            pp.show()
232
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
233
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
234
            br.repository.unlock()
235
            br.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
236
237
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
238
class cmd_gannotate(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
239
    """GTK+ annotate.
240
    
241
    Browse changes to FILENAME line by line in a GTK+ window.
242
    """
243
59.2.1 by Aaron Bentley
Gannotate takes a line number
244
    takes_args = ["filename", "line?"]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
245
    takes_options = [
246
        Option("all", help="show annotations on all lines"),
247
        Option("plain", help="don't highlight annotation lines"),
248
        Option("line", type=int, argname="lineno",
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
249
               help="jump to specified line number"),
250
        "revision",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
251
    ]
252
    aliases = ["gblame", "gpraise"]
253
    
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
254
    def run(self, filename, all=False, plain=False, line='1', revision=None):
187 by Jelmer Vernooij
Fix gannotate.
255
        gtk = self.open_display()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
256
59.2.1 by Aaron Bentley
Gannotate takes a line number
257
        try:
258
            line = int(line)
259
        except ValueError:
260
            raise BzrCommandError('Line argument ("%s") is not a number.' % 
261
                                  line)
262
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
263
        from annotate.gannotate import GAnnotateWindow
264
        from annotate.config import GAnnotateConfig
177 by Jelmer Vernooij
Register commands all at once.
265
        from bzrlib.bzrdir import BzrDir
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
266
161 by Aaron Bentley
Fix gannotate interaction with dirstate
267
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
268
        if wt is not None:
269
            tree = wt
270
        else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
271
            tree = br.basis_tree()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
272
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
273
        file_id = tree.path2id(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
274
275
        if file_id is None:
276
            raise NotVersionedError(filename)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
277
        if revision is not None:
278
            if len(revision) != 1:
279
                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
280
            revision_id = revision[0].in_history(br).rev_id
281
            tree = br.repository.revision_tree(revision_id)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
282
        else:
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
283
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
284
285
        window = GAnnotateWindow(all, plain)
286
        window.connect("destroy", lambda w: gtk.main_quit())
287
        window.set_title(path + " - gannotate")
288
        config = GAnnotateConfig(window)
289
        window.show()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
290
        br.lock_read()
161 by Aaron Bentley
Fix gannotate interaction with dirstate
291
        if wt is not None:
292
            wt.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
293
        try:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
294
            window.annotate(tree, br, file_id)
161 by Aaron Bentley
Fix gannotate interaction with dirstate
295
            window.jump_to_line(line)
296
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
297
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
298
            br.unlock()
161 by Aaron Bentley
Fix gannotate interaction with dirstate
299
            if wt is not None:
300
                wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
301
302
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
303
304
class cmd_gcommit(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
305
    """GTK+ commit dialog
306
307
    Graphical user interface for committing revisions"""
308
    
145 by Jelmer Vernooij
Fix some strings, import.
309
    aliases = [ "gci" ]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
310
    takes_args = []
311
    takes_options = []
312
313
    def run(self, filename=None):
93.1.17 by Alexander Belchenko
gcommit reworked again.
314
        import os
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
315
        self.open_display()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
316
        from commit import CommitDialog
93.1.17 by Alexander Belchenko
gcommit reworked again.
317
        from bzrlib.errors import (BzrCommandError,
318
                                   NotBranchError,
178 by Jelmer Vernooij
Remove unneeded imports.
319
                                   NoWorkingTree)
93.1.17 by Alexander Belchenko
gcommit reworked again.
320
321
        wt = None
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
322
        br = None
93.1.17 by Alexander Belchenko
gcommit reworked again.
323
        try:
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
324
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
325
            br = wt.branch
93.1.17 by Alexander Belchenko
gcommit reworked again.
326
        except NotBranchError, e:
327
            path = e.path
328
        except NoWorkingTree, e:
329
            path = e.base
330
            try:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
331
                (br, path) = branch.Branch.open_containing(path)
93.1.17 by Alexander Belchenko
gcommit reworked again.
332
            except NotBranchError, e:
333
                path = e.path
334
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
335
        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'.
336
        commit.run()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
337
338
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
339
340
class cmd_gstatus(GTKCommand):
157 by Jelmer Vernooij
Add gstatus command.
341
    """GTK+ status dialog
342
343
    Graphical user interface for showing status 
344
    information."""
345
    
346
    aliases = [ "gst" ]
347
    takes_args = ['PATH?']
348
    takes_options = []
349
350
    def run(self, path='.'):
351
        import os
184 by Jelmer Vernooij
Fix gstatus
352
        gtk = self.open_display()
157 by Jelmer Vernooij
Add gstatus command.
353
        from status import StatusDialog
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
354
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
157 by Jelmer Vernooij
Add gstatus command.
355
        status = StatusDialog(wt, wt_path)
356
        status.connect("destroy", gtk.main_quit)
357
        status.run()
358
359
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
360
361
class cmd_gconflicts(GTKCommand):
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
362
    """ GTK+ push.
363
    
364
    """
365
    def run(self):
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
366
        (wt, path) = workingtree.WorkingTree.open_containing('.')
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
367
        self.open_display()
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
368
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
369
        dialog = ConflictsDialog(wt)
370
        dialog.run()
371
157 by Jelmer Vernooij
Add gstatus command.
372
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
373
374
class cmd_gpreferences(GTKCommand):
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
375
    """ GTK+ preferences dialog.
376
377
    """
378
    def run(self):
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
379
        self.open_display()
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
380
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
381
        dialog = PreferencesWindow()
382
        dialog.run()
383
384
175 by Jelmer Vernooij
Add very simple gmissing command.
385
386
class cmd_gmissing(Command):
387
    """ GTK+ missing revisions dialog.
388
389
    """
390
    takes_args = ["other_branch?"]
391
    def run(self, other_branch=None):
392
        pygtk = import_pygtk()
393
        try:
394
            import gtk
395
        except RuntimeError, e:
396
            if str(e) == "could not open display":
397
                raise NoDisplayError
398
399
        from bzrlib.plugins.gtk.missing import MissingWindow
400
        from bzrlib.branch import Branch
401
402
        local_branch = Branch.open_containing(".")[0]
403
        if other_branch is None:
404
            other_branch = local_branch.get_parent()
405
            
406
            if other_branch is None:
407
                raise errors.BzrCommandError("No peer location known or specified.")
408
        remote_branch = Branch.open_containing(other_branch)[0]
409
        set_ui_factory()
410
        local_branch.lock_read()
411
        try:
412
            remote_branch.lock_read()
413
            try:
414
                dialog = MissingWindow(local_branch, remote_branch)
415
                dialog.run()
416
            finally:
417
                remote_branch.unlock()
418
        finally:
419
            local_branch.unlock()
420
177 by Jelmer Vernooij
Register commands all at once.
421
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
422
class cmd_ginit(GTKCommand):
423
    def run(self):
424
        self.open_display()
425
        from initialize import InitDialog
426
        dialog = InitDialog(os.path.abspath(os.path.curdir))
427
        dialog.run()
428
429
177 by Jelmer Vernooij
Register commands all at once.
430
commands = [
431
    cmd_gmissing, 
432
    cmd_gpreferences, 
433
    cmd_gconflicts, 
434
    cmd_gstatus,
435
    cmd_gcommit, 
436
    cmd_gannotate, 
437
    cmd_visualise, 
438
    cmd_gdiff,
439
    cmd_gpush, 
440
    cmd_gcheckout, 
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
441
    cmd_gbranch,
442
    cmd_ginit
177 by Jelmer Vernooij
Register commands all at once.
443
    ]
444
445
for cmd in commands:
446
    register_command(cmd)
175 by Jelmer Vernooij
Add very simple gmissing command.
447
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
448
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
449
class cmd_commit_notify(GTKCommand):
450
    """Run the bzr commit notifier.
451
452
    This is a background program which will pop up a notification on the users
453
    screen when a commit occurs.
454
    """
455
456
    def run(self):
457
        gtk = self.open_display()
458
        import cgi
459
        import dbus
460
        import dbus.service
461
        import pynotify
462
        from bzrlib.bzrdir import BzrDir
463
        from bzrlib import errors
464
        from bzrlib.osutils import format_date
465
        from bzrlib.transport import get_transport
466
        if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
467
            import dbus.glib
468
        from bzrlib.plugins.dbus import activity
469
        bus = dbus.SessionBus()
470
        # get the object so we can subscribe to callbacks from it.
471
        broadcast_service = bus.get_object(
472
            activity.Broadcast.DBUS_NAME,
473
            activity.Broadcast.DBUS_PATH)
182.1.1 by Robert Collins
Update commit-notify to use new dbus api, and show remote URL's.
474
        def catch_branch(revision_id, urls):
475
            # TODO: show all the urls, or perhaps choose the 'best'.
476
            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.
477
            try:
478
                if isinstance(revision_id, unicode):
479
                    revision_id = revision_id.encode('utf8')
480
                transport = get_transport(url)
481
                a_dir = BzrDir.open_from_transport(transport)
482
                branch = a_dir.open_branch()
483
                revno = branch.revision_id_to_revno(revision_id)
484
                revision = branch.repository.get_revision(revision_id)
485
                summary = 'New revision %d in %s' % (revno, url)
486
                body  = 'Committer: %s\n' % revision.committer
487
                body += 'Date: %s\n' % format_date(revision.timestamp,
488
                    revision.timezone)
489
                body += '\n'
490
                body += revision.message
491
                body = cgi.escape(body)
492
                nw = pynotify.Notification(summary, body)
493
                nw.set_timeout(5000)
494
                nw.show()
495
            except Exception, e:
496
                print e
497
                raise
498
        broadcast_service.connect_to_signal("Revision", catch_branch,
499
            dbus_interface=activity.Broadcast.DBUS_INTERFACE)
500
        pynotify.init("bzr commit-notify")
501
        gtk.main()
502
503
register_command(cmd_commit_notify)
504
505
152 by Jelmer Vernooij
Cleanup some more code.
506
import gettext
507
gettext.install('olive-gtk')
508
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
509
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
510
class NoDisplayError(BzrCommandError):
511
    """gtk could not find a proper display"""
512
513
    def __str__(self):
133 by Jelmer Vernooij
Actually use the ui factory.
514
        return "No DISPLAY. Unable to run GTK+ application."
515
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
516
140 by Jelmer Vernooij
add framework for tests.
517
def test_suite():
518
    from unittest import TestSuite
519
    import tests
163 by Aaron Bentley
Prevent test suite from causing default-encoding changes
520
    import sys
521
    default_encoding = sys.getdefaultencoding()
522
    try:
523
        result = TestSuite()
524
        result.addTest(tests.test_suite())
525
    finally:
170.1.2 by Aaron Bentley
Test suite only fixes encoding if it's changed. Fixes test_selftest bug.
526
        if sys.getdefaultencoding() != default_encoding:
527
            reload(sys)
528
            sys.setdefaultencoding(default_encoding)
140 by Jelmer Vernooij
add framework for tests.
529
    return result