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