/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. 
22
gcommit           GTK+ commit dialog 
23
gconflicts        GTK+ push. 
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. 
28
gpush             GTK+ push. 
29
gstatus           GTK+ status dialog 
30
gtags             Manage branch tags.
31
visualise         Graphically visualise this branch. 
32
"""
73 by Jelmer Vernooij
Release 0.9, list myself as maintainer.
33
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
34
import bzrlib
35
208.2.5 by Robert Collins
Change version to 0.18.
36
__version__ = '0.18.0'
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
37
version_info = tuple(int(n) for n in __version__.split('.'))
38
39
40
def check_bzrlib_version(desired):
41
    """Check that bzrlib is compatible.
42
43
    If version is < bzr-gtk version, assume incompatible.
44
    If version == bzr-gtk version, assume completely compatible
45
    If version == bzr-gtk version + 1, assume compatible, with deprecations
46
    Otherwise, assume incompatible.
47
    """
48
    desired_plus = (desired[0], desired[1]+1)
49
    bzrlib_version = bzrlib.version_info[:2]
203 by Aaron Bentley
Don't warn if bzrlib is dev version of next release
50
    if bzrlib_version == desired or (bzrlib_version == desired_plus and
51
                                     bzrlib.version_info[3] == 'dev'):
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
52
        return
53
    try:
54
        from bzrlib.trace import warning
55
    except ImportError:
56
        # get the message out any way we can
57
        from warnings import warn as warning
58
    if bzrlib_version < desired:
207 by Aaron Bentley
Import BzrError before using it
59
        from bzrlib.errors import BzrError
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
60
        warning('Installed bzr version %s is too old to be used with bzr-gtk'
61
                ' %s.' % (bzrlib.__version__, __version__))
199 by Jelmer Vernooij
Merge upstream.
62
        raise BzrError('Version mismatch: %r' % version_info)
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
63
    else:
64
        warning('bzr-gtk is not up to date with installed bzr version %s.'
65
                ' \nThere should be a newer version available, e.g. %i.%i.' 
66
                % (bzrlib.__version__, bzrlib_version[0], bzrlib_version[1]))
67
        if bzrlib_version != desired_plus:
68
            raise Exception, 'Version mismatch'
69
70
71
check_bzrlib_version(version_info[:2])
72
146 by Jelmer Vernooij
Move more code to top-level directory.
73
from bzrlib.trace import warning
74
if __name__ != 'bzrlib.plugins.gtk':
75
    warning("Not running as bzrlib.plugins.gtk, things may break.")
76
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
77
from bzrlib.lazy_import import lazy_import
78
lazy_import(globals(), """
79
from bzrlib import (
80
    branch,
81
    errors,
82
    workingtree,
83
    )
84
""")
85
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
86
from bzrlib.commands import Command, register_command, display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
87
from bzrlib.errors import NotVersionedError, BzrCommandError, NoSuchFile
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
88
from bzrlib.option import Option
89
126.1.5 by Szilveszter Farkas (Phanatic)
bzr gbranch should work now (Fixed: #77751)
90
import os.path
91
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
92
def import_pygtk():
93
    try:
94
        import pygtk
95
    except ImportError:
96
        raise errors.BzrCommandError("PyGTK not installed.")
97
    pygtk.require('2.0')
98
    return pygtk
99
100
133 by Jelmer Vernooij
Actually use the ui factory.
101
def set_ui_factory():
177 by Jelmer Vernooij
Register commands all at once.
102
    import_pygtk()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
103
    from ui import GtkUIFactory
133 by Jelmer Vernooij
Actually use the ui factory.
104
    import bzrlib.ui
105
    bzrlib.ui.ui_factory = GtkUIFactory()
106
107
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
108
class GTKCommand(Command):
109
    """Abstract class providing GTK specific run commands."""
110
111
    def open_display(self):
112
        pygtk = import_pygtk()
113
        try:
114
            import gtk
115
        except RuntimeError, e:
116
            if str(e) == "could not open display":
117
                raise NoDisplayError
118
        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.
119
        return gtk
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
120
121
    def run(self):
122
        self.open_display()
123
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
124
        dialog.run()
125
126
127
class cmd_gbranch(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
128
    """GTK+ branching.
129
    
130
    """
131
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
132
    def get_gtk_dialog(self, path):
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
133
        from bzrlib.plugins.gtk.branch import BranchDialog
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
134
        return BranchDialog(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
135
136
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
137
class cmd_gcheckout(GTKCommand):
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
138
    """ GTK+ checkout.
139
    
140
    """
141
    
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
142
    def get_gtk_dialog(self, path):
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
143
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
144
        return CheckoutDialog(path)
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
145
146
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
147
148
class cmd_gpush(GTKCommand):
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
149
    """ GTK+ push.
150
    
151
    """
152
    takes_args = [ "location?" ]
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
153
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
154
    def run(self, location="."):
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
155
        (br, path) = branch.Branch.open_containing(location)
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
156
        self.open_display()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
157
        from push import PushDialog
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
158
        dialog = PushDialog(br)
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
159
        dialog.run()
160
161
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
162
163
class cmd_gdiff(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
164
    """Show differences in working tree in a GTK+ Window.
165
    
166
    Otherwise, all changes for the tree are listed.
167
    """
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
168
    takes_args = ['filename?']
58.1.1 by Aaron Bentley
gdiff takes -r arguments
169
    takes_options = ['revision']
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
170
171
    @display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
172
    def run(self, revision=None, filename=None):
133 by Jelmer Vernooij
Actually use the ui factory.
173
        set_ui_factory()
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
174
        wt = workingtree.WorkingTree.open_containing(".")[0]
161 by Aaron Bentley
Fix gannotate interaction with dirstate
175
        wt.lock_read()
176
        try:
177
            branch = wt.branch
178
            if revision is not None:
179
                if len(revision) == 1:
180
                    tree1 = wt
181
                    revision_id = revision[0].in_history(branch).rev_id
182
                    tree2 = branch.repository.revision_tree(revision_id)
183
                elif len(revision) == 2:
184
                    revision_id_0 = revision[0].in_history(branch).rev_id
185
                    tree2 = branch.repository.revision_tree(revision_id_0)
186
                    revision_id_1 = revision[1].in_history(branch).rev_id
187
                    tree1 = branch.repository.revision_tree(revision_id_1)
188
            else:
58.1.1 by Aaron Bentley
gdiff takes -r arguments
189
                tree1 = wt
161 by Aaron Bentley
Fix gannotate interaction with dirstate
190
                tree2 = tree1.basis_tree()
191
192
            from diff import DiffWindow
193
            import gtk
194
            window = DiffWindow()
195
            window.connect("destroy", gtk.main_quit)
196
            window.set_diff("Working Tree", tree1, tree2)
197
            if filename is not None:
198
                tree_filename = wt.relpath(filename)
199
                try:
200
                    window.set_file(tree_filename)
201
                except NoSuchFile:
188.3.1 by John Arbash Meinel
Use tree.path2id to avoid getting 'Object Not Locked' errors.
202
                    if (tree1.path2id(tree_filename) is None and 
203
                        tree2.path2id(tree_filename) is None):
161 by Aaron Bentley
Fix gannotate interaction with dirstate
204
                        raise NotVersionedError(filename)
205
                    raise BzrCommandError('No changes found for file "%s"' % 
206
                                          filename)
207
            window.show()
208
209
            gtk.main()
210
        finally:
211
            wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
212
213
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
214
def start_viz_window(branch, revision, limit=None):
215
    """Start viz on branch with revision revision.
216
    
217
    :return: The viz window object.
218
    """
219
    from viz.branchwin import BranchWindow
220
    branch.lock_read()
221
    pp = BranchWindow()
222
    pp.set_branch(branch, revision, limit)
223
    # cleanup locks when the window is closed
224
    pp.connect("destroy", lambda w: branch.unlock())
225
    return pp
226
227
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
228
class cmd_visualise(Command):
229
    """Graphically visualise this branch.
230
231
    Opens a graphical window to allow you to see the history of the branch
232
    and relationships between revisions in a visual manner,
233
234
    The default starting point is latest revision on the branch, you can
235
    specify a starting point with -r revision.
236
    """
237
    takes_options = [
238
        "revision",
239
        Option('limit', "maximum number of revisions to display",
240
               int, 'count')]
241
    takes_args = [ "location?" ]
242
    aliases = [ "visualize", "vis", "viz" ]
243
244
    def run(self, location=".", revision=None, limit=None):
133 by Jelmer Vernooij
Actually use the ui factory.
245
        set_ui_factory()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
246
        (br, path) = branch.Branch.open_containing(location)
247
        br.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
248
        try:
249
            if revision is None:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
250
                revid = br.last_revision()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
251
                if revid is None:
252
                    return
253
            else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
254
                (revno, revid) = revision[0].in_history(br)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
255
152 by Jelmer Vernooij
Cleanup some more code.
256
            import gtk
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
257
            pp = start_viz_window(br, revid, limit)
152 by Jelmer Vernooij
Cleanup some more code.
258
            pp.connect("destroy", lambda w: gtk.main_quit())
259
            pp.show()
260
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
261
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
262
            br.unlock()
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 = [
273
        Option("all", help="show annotations on all lines"),
274
        Option("plain", help="don't highlight annotation lines"),
275
        Option("line", type=int, argname="lineno",
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
276
               help="jump to specified line number"),
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
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
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
382
383
class cmd_gconflicts(GTKCommand):
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
384
    """ GTK+ push.
385
    
386
    """
387
    def run(self):
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
388
        (wt, path) = workingtree.WorkingTree.open_containing('.')
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
389
        self.open_display()
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
390
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
391
        dialog = ConflictsDialog(wt)
392
        dialog.run()
393
157 by Jelmer Vernooij
Add gstatus command.
394
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
395
396
class cmd_gpreferences(GTKCommand):
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
397
    """ GTK+ preferences dialog.
398
399
    """
400
    def run(self):
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
401
        self.open_display()
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
402
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
403
        dialog = PreferencesWindow()
404
        dialog.run()
405
406
175 by Jelmer Vernooij
Add very simple gmissing command.
407
408
class cmd_gmissing(Command):
409
    """ GTK+ missing revisions dialog.
410
411
    """
412
    takes_args = ["other_branch?"]
413
    def run(self, other_branch=None):
414
        pygtk = import_pygtk()
415
        try:
416
            import gtk
417
        except RuntimeError, e:
418
            if str(e) == "could not open display":
419
                raise NoDisplayError
420
421
        from bzrlib.plugins.gtk.missing import MissingWindow
422
        from bzrlib.branch import Branch
423
424
        local_branch = Branch.open_containing(".")[0]
425
        if other_branch is None:
426
            other_branch = local_branch.get_parent()
427
            
428
            if other_branch is None:
429
                raise errors.BzrCommandError("No peer location known or specified.")
430
        remote_branch = Branch.open_containing(other_branch)[0]
431
        set_ui_factory()
432
        local_branch.lock_read()
433
        try:
434
            remote_branch.lock_read()
435
            try:
436
                dialog = MissingWindow(local_branch, remote_branch)
437
                dialog.run()
438
            finally:
439
                remote_branch.unlock()
440
        finally:
441
            local_branch.unlock()
442
177 by Jelmer Vernooij
Register commands all at once.
443
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
444
class cmd_ginit(GTKCommand):
445
    def run(self):
446
        self.open_display()
447
        from initialize import InitDialog
448
        dialog = InitDialog(os.path.abspath(os.path.curdir))
449
        dialog.run()
450
451
190.1.1 by Szilveszter Farkas (Phanatic)
Added 'gtags' command and basic Tags window (just a skeleton).
452
class cmd_gtags(GTKCommand):
453
    def run(self):
454
        br = branch.Branch.open_containing('.')[0]
455
        
456
        gtk = self.open_display()
457
        from tags import TagsWindow
458
        window = TagsWindow(br)
459
        window.show()
460
        gtk.main()
461
462
177 by Jelmer Vernooij
Register commands all at once.
463
commands = [
464
    cmd_gmissing, 
465
    cmd_gpreferences, 
466
    cmd_gconflicts, 
467
    cmd_gstatus,
468
    cmd_gcommit, 
469
    cmd_gannotate, 
470
    cmd_visualise, 
471
    cmd_gdiff,
472
    cmd_gpush, 
473
    cmd_gcheckout, 
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
474
    cmd_gbranch,
190.1.1 by Szilveszter Farkas (Phanatic)
Added 'gtags' command and basic Tags window (just a skeleton).
475
    cmd_ginit,
476
    cmd_gtags
177 by Jelmer Vernooij
Register commands all at once.
477
    ]
478
479
for cmd in commands:
480
    register_command(cmd)
175 by Jelmer Vernooij
Add very simple gmissing command.
481
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
482
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
483
class cmd_commit_notify(GTKCommand):
484
    """Run the bzr commit notifier.
485
486
    This is a background program which will pop up a notification on the users
487
    screen when a commit occurs.
488
    """
489
490
    def run(self):
491
        gtk = self.open_display()
492
        import cgi
493
        import dbus
494
        import dbus.service
495
        import pynotify
496
        from bzrlib.bzrdir import BzrDir
497
        from bzrlib import errors
498
        from bzrlib.osutils import format_date
499
        from bzrlib.transport import get_transport
500
        if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
501
            import dbus.glib
502
        from bzrlib.plugins.dbus import activity
503
        bus = dbus.SessionBus()
504
        # get the object so we can subscribe to callbacks from it.
505
        broadcast_service = bus.get_object(
506
            activity.Broadcast.DBUS_NAME,
507
            activity.Broadcast.DBUS_PATH)
182.1.1 by Robert Collins
Update commit-notify to use new dbus api, and show remote URL's.
508
        def catch_branch(revision_id, urls):
509
            # TODO: show all the urls, or perhaps choose the 'best'.
510
            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.
511
            try:
512
                if isinstance(revision_id, unicode):
513
                    revision_id = revision_id.encode('utf8')
514
                transport = get_transport(url)
515
                a_dir = BzrDir.open_from_transport(transport)
516
                branch = a_dir.open_branch()
517
                revno = branch.revision_id_to_revno(revision_id)
518
                revision = branch.repository.get_revision(revision_id)
519
                summary = 'New revision %d in %s' % (revno, url)
520
                body  = 'Committer: %s\n' % revision.committer
521
                body += 'Date: %s\n' % format_date(revision.timestamp,
522
                    revision.timezone)
523
                body += '\n'
524
                body += revision.message
525
                body = cgi.escape(body)
526
                nw = pynotify.Notification(summary, body)
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
527
                def start_viz(notification=None, action=None, data=None):
528
                    """Start the viz program."""
529
                    pp = start_viz_window(branch, revision_id)
530
                    pp.show()
208.2.3 by Robert Collins
Add a Branch button to commit-notify.
531
                def start_branch(notification=None, action=None, data=None):
532
                    """Start a Branch dialog"""
533
                    from bzrlib.plugins.gtk.branch import BranchDialog
534
                    bd = BranchDialog(remote_path=url)
535
                    bd.run()
208.2.4 by Robert Collins
Unbreak inspect of commits due to misunderstanding of pynotify api.
536
                nw.add_action("inspect", "Inspect", start_viz, None)
537
                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.
538
                nw.set_timeout(5000)
539
                nw.show()
540
            except Exception, e:
541
                print e
542
                raise
543
        broadcast_service.connect_to_signal("Revision", catch_branch,
544
            dbus_interface=activity.Broadcast.DBUS_INTERFACE)
545
        pynotify.init("bzr commit-notify")
546
        gtk.main()
547
548
register_command(cmd_commit_notify)
549
550
152 by Jelmer Vernooij
Cleanup some more code.
551
import gettext
552
gettext.install('olive-gtk')
553
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
554
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
555
class NoDisplayError(BzrCommandError):
556
    """gtk could not find a proper display"""
557
558
    def __str__(self):
133 by Jelmer Vernooij
Actually use the ui factory.
559
        return "No DISPLAY. Unable to run GTK+ application."
560
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
561
140 by Jelmer Vernooij
add framework for tests.
562
def test_suite():
563
    from unittest import TestSuite
564
    import tests
163 by Aaron Bentley
Prevent test suite from causing default-encoding changes
565
    import sys
566
    default_encoding = sys.getdefaultencoding()
567
    try:
568
        result = TestSuite()
569
        result.addTest(tests.test_suite())
570
    finally:
170.1.2 by Aaron Bentley
Test suite only fixes encoding if it's changed. Fixes test_selftest bug.
571
        if sys.getdefaultencoding() != default_encoding:
572
            reload(sys)
573
            sys.setdefaultencoding(default_encoding)
140 by Jelmer Vernooij
add framework for tests.
574
    return result