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