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