/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
gannotate         GTK+ annotate. 
19
gbranch           GTK+ branching. 
20
gcheckout         GTK+ checkout. 
323 by Jelmer Vernooij
Add gsend command.
21
gcommit           GTK+ commit dialog.
242.1.2 by Adeodato Simó
Fix gconflicts docstring.
22
gconflicts        GTK+ conflicts. 
208.2.1 by Robert Collins
Better module docstring.
23
gdiff             Show differences in working tree in a GTK+ Window. 
24
ginit             Initialise a new branch.
580.1.1 by Jelmer Vernooij
Add gloom command.
25
gloom             GTK+ loom browse dialog
571.1.1 by Jasper Groenewegen
Add gmerge command and change MergeDialog to set parent as default if available
26
gmerge            GTK+ merge dialog
208.2.1 by Robert Collins
Better module docstring.
27
gmissing          GTK+ missing revisions dialog. 
28
gpreferences      GTK+ preferences dialog. 
323 by Jelmer Vernooij
Add gsend command.
29
gpush             GTK+ push.
30
gsend             GTK+ send merge directive.
31
gstatus           GTK+ status dialog.
208.2.1 by Robert Collins
Better module docstring.
32
gtags             Manage branch tags.
33
visualise         Graphically visualise this branch. 
34
"""
73 by Jelmer Vernooij
Release 0.9, list myself as maintainer.
35
278.1.22 by John Arbash Meinel
Add a test-gtk command to make testing faster
36
import sys
37
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
38
import bzrlib
39
590 by Jelmer Vernooij
Open 0.96.0 for development.
40
version_info = (0, 96, 0, 'dev', 1)
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
41
287 by Jelmer Vernooij
Use standard version tuple.
42
if version_info[3] == 'final':
43
    version_string = '%d.%d.%d' % version_info[:3]
44
else:
45
    version_string = '%d.%d.%d%s%d' % version_info
46
__version__ = version_string
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
47
589 by Jelmer Vernooij
Depend on bzr 1.6.
48
required_bzrlib = (1, 6)
423.1.1 by Jelmer Vernooij
Allow bzr-gtk and Bazaar versions to be out of sync. No longer warn about
49
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
50
def check_bzrlib_version(desired):
51
    """Check that bzrlib is compatible.
52
53
    If version is < bzr-gtk version, assume incompatible.
54
    """
55
    bzrlib_version = bzrlib.version_info[:2]
56
    try:
57
        from bzrlib.trace import warning
58
    except ImportError:
59
        # get the message out any way we can
60
        from warnings import warn as warning
61
    if bzrlib_version < desired:
207 by Aaron Bentley
Import BzrError before using it
62
        from bzrlib.errors import BzrError
271 by Jelmer Vernooij
Add common widget for selecting branches.
63
        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).
64
                ' %s.' % (bzrlib.__version__, __version__))
287 by Jelmer Vernooij
Use standard version tuple.
65
        raise BzrError('Version mismatch: %r, %r' % (version_info, bzrlib.version_info) )
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
66
67
287 by Jelmer Vernooij
Use standard version tuple.
68
if version_info[2] == "final":
423.1.1 by Jelmer Vernooij
Allow bzr-gtk and Bazaar versions to be out of sync. No longer warn about
69
    check_bzrlib_version(required_bzrlib)
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,
426 by Aaron Bentley
Start support for Merge Directives
81
    merge_directive,
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
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
531.6.1 by Jelmer Vernooij
Try harder to find license and credits files.
108
def data_basedirs():
109
    return [os.path.dirname(__file__),
399.1.19 by Jelmer Vernooij
Add utility function for finding icon paths.
110
             "/usr/share/bzr-gtk", 
111
             "/usr/local/share/bzr-gtk"]
531.6.1 by Jelmer Vernooij
Try harder to find license and credits files.
112
113
114
def data_path(*args):
115
    for basedir in data_basedirs():
116
        path = os.path.join(basedir, *args)
399.1.19 by Jelmer Vernooij
Add utility function for finding icon paths.
117
        if os.path.exists(path):
118
            return path
119
    return None
120
121
531.6.1 by Jelmer Vernooij
Try harder to find license and credits files.
122
def icon_path(*args):
123
    return data_path(os.path.join('icons', *args))
124
125
505.1.1 by Jelmer Vernooij
Make handle-patch not dependend on the users name being abentley and install it.
126
def open_display():
127
    pygtk = import_pygtk()
128
    try:
129
        import gtk
130
    except RuntimeError, e:
131
        if str(e) == "could not open display":
132
            raise NoDisplayError
133
    set_ui_factory()
134
    return gtk
135
 
136
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
137
class GTKCommand(Command):
138
    """Abstract class providing GTK specific run commands."""
139
140
    def run(self):
505.1.1 by Jelmer Vernooij
Make handle-patch not dependend on the users name being abentley and install it.
141
        open_display()
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
142
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
143
        dialog.run()
144
145
146
class cmd_gbranch(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
147
    """GTK+ branching.
148
    
149
    """
150
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
151
    def get_gtk_dialog(self, path):
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
152
        from bzrlib.plugins.gtk.branch import BranchDialog
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
153
        return BranchDialog(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
154
155
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
156
class cmd_gcheckout(GTKCommand):
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
157
    """ GTK+ checkout.
158
    
159
    """
160
    
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
161
    def get_gtk_dialog(self, path):
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
162
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
163
        return CheckoutDialog(path)
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
164
165
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
166
167
class cmd_gpush(GTKCommand):
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
168
    """ GTK+ push.
169
    
170
    """
171
    takes_args = [ "location?" ]
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
172
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
173
    def run(self, location="."):
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
174
        (br, path) = branch.Branch.open_containing(location)
505.1.1 by Jelmer Vernooij
Make handle-patch not dependend on the users name being abentley and install it.
175
        open_display()
580.1.1 by Jelmer Vernooij
Add gloom command.
176
        from bzrlib.plugins.gtk.push import PushDialog
233 by Jelmer Vernooij
Get rid of test button in push.
177
        dialog = PushDialog(br.repository, br.last_revision(), br)
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
178
        dialog.run()
179
180
580.1.1 by Jelmer Vernooij
Add gloom command.
181
class cmd_gloom(GTKCommand):
182
    """ GTK+ loom.
183
    
184
    """
185
    takes_args = [ "location?" ]
186
187
    def run(self, location="."):
580.1.3 by Jelmer Vernooij
Show diffs of threads, allow switching to different threads.
188
        try:
189
            (tree, path) = workingtree.WorkingTree.open_containing(location)
190
            br = tree.branch
191
        except NoWorkingTree, e:
192
            (br, path) = branch.Branch.open_containing(location)
193
            tree = None
580.1.1 by Jelmer Vernooij
Add gloom command.
194
        open_display()
195
        from bzrlib.plugins.gtk.loom import LoomDialog
580.1.3 by Jelmer Vernooij
Show diffs of threads, allow switching to different threads.
196
        dialog = LoomDialog(br, tree)
580.1.1 by Jelmer Vernooij
Add gloom command.
197
        dialog.run()
198
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
199
200
class cmd_gdiff(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
201
    """Show differences in working tree in a GTK+ Window.
202
    
203
    Otherwise, all changes for the tree are listed.
204
    """
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
205
    takes_args = ['filename?']
58.1.1 by Aaron Bentley
gdiff takes -r arguments
206
    takes_options = ['revision']
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
207
208
    @display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
209
    def run(self, revision=None, filename=None):
133 by Jelmer Vernooij
Actually use the ui factory.
210
        set_ui_factory()
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
211
        wt = workingtree.WorkingTree.open_containing(".")[0]
161 by Aaron Bentley
Fix gannotate interaction with dirstate
212
        wt.lock_read()
213
        try:
214
            branch = wt.branch
215
            if revision is not None:
216
                if len(revision) == 1:
217
                    tree1 = wt
493 by Aaron Bentley
Convert remaining uses of RevisionSpec.in_history to as_revision_id
218
                    revision_id = revision[0].as_revision_id(tree1.branch)
161 by Aaron Bentley
Fix gannotate interaction with dirstate
219
                    tree2 = branch.repository.revision_tree(revision_id)
220
                elif len(revision) == 2:
493 by Aaron Bentley
Convert remaining uses of RevisionSpec.in_history to as_revision_id
221
                    revision_id_0 = revision[0].as_revision_id(branch)
161 by Aaron Bentley
Fix gannotate interaction with dirstate
222
                    tree2 = branch.repository.revision_tree(revision_id_0)
493 by Aaron Bentley
Convert remaining uses of RevisionSpec.in_history to as_revision_id
223
                    revision_id_1 = revision[1].as_revision_id(branch)
161 by Aaron Bentley
Fix gannotate interaction with dirstate
224
                    tree1 = branch.repository.revision_tree(revision_id_1)
225
            else:
58.1.1 by Aaron Bentley
gdiff takes -r arguments
226
                tree1 = wt
161 by Aaron Bentley
Fix gannotate interaction with dirstate
227
                tree2 = tree1.basis_tree()
228
229
            from diff import DiffWindow
230
            import gtk
231
            window = DiffWindow()
232
            window.connect("destroy", gtk.main_quit)
233
            window.set_diff("Working Tree", tree1, tree2)
234
            if filename is not None:
235
                tree_filename = wt.relpath(filename)
236
                try:
237
                    window.set_file(tree_filename)
238
                except NoSuchFile:
188.3.1 by John Arbash Meinel
Use tree.path2id to avoid getting 'Object Not Locked' errors.
239
                    if (tree1.path2id(tree_filename) is None and 
240
                        tree2.path2id(tree_filename) is None):
161 by Aaron Bentley
Fix gannotate interaction with dirstate
241
                        raise NotVersionedError(filename)
242
                    raise BzrCommandError('No changes found for file "%s"' % 
243
                                          filename)
244
            window.show()
245
246
            gtk.main()
247
        finally:
248
            wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
249
250
452.4.1 by Jelmer Vernooij
Support displaying multiple tips in viz.
251
def start_viz_window(branch, revisions, limit=None):
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
252
    """Start viz on branch with revision revision.
253
    
254
    :return: The viz window object.
255
    """
576.2.1 by Jelmer Vernooij
Use ... notation for options that lead to dialogs, fix some nautilus-bzr menu items that had regressed.
256
    from bzrlib.plugins.gtk.viz import BranchWindow
452.4.1 by Jelmer Vernooij
Support displaying multiple tips in viz.
257
    return BranchWindow(branch, revisions, limit)
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
258
259
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
260
class cmd_visualise(Command):
261
    """Graphically visualise this branch.
262
263
    Opens a graphical window to allow you to see the history of the branch
264
    and relationships between revisions in a visual manner,
265
266
    The default starting point is latest revision on the branch, you can
267
    specify a starting point with -r revision.
268
    """
269
    takes_options = [
270
        "revision",
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
271
        Option('limit', "Maximum number of revisions to display.",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
272
               int, 'count')]
452.4.1 by Jelmer Vernooij
Support displaying multiple tips in viz.
273
    takes_args = [ "locations*" ]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
274
    aliases = [ "visualize", "vis", "viz" ]
275
452.4.1 by Jelmer Vernooij
Support displaying multiple tips in viz.
276
    def run(self, locations_list, revision=None, limit=None):
133 by Jelmer Vernooij
Actually use the ui factory.
277
        set_ui_factory()
452.4.1 by Jelmer Vernooij
Support displaying multiple tips in viz.
278
        if locations_list is None:
279
            locations_list = ["."]
280
        revids = []
281
        for location in locations_list:
282
            (br, path) = branch.Branch.open_containing(location)
283
            if revision is None:
284
                revids.append(br.last_revision())
285
            else:
493 by Aaron Bentley
Convert remaining uses of RevisionSpec.in_history to as_revision_id
286
                revids.append(revision[0].as_revision_id(br))
365 by Daniel Schierbeck
Fixed locks and made tagging work.
287
        import gtk
452.4.1 by Jelmer Vernooij
Support displaying multiple tips in viz.
288
        pp = start_viz_window(br, revids, limit)
365 by Daniel Schierbeck
Fixed locks and made tagging work.
289
        pp.connect("destroy", lambda w: gtk.main_quit())
290
        pp.show()
291
        gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
292
293
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
294
class cmd_gannotate(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
295
    """GTK+ annotate.
296
    
297
    Browse changes to FILENAME line by line in a GTK+ window.
298
    """
299
59.2.1 by Aaron Bentley
Gannotate takes a line number
300
    takes_args = ["filename", "line?"]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
301
    takes_options = [
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
302
        Option("all", help="Show annotations on all lines."),
303
        Option("plain", help="Don't highlight annotation lines."),
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
304
        Option("line", type=int, argname="lineno",
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
305
               help="Jump to specified line number."),
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
306
        "revision",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
307
    ]
308
    aliases = ["gblame", "gpraise"]
309
    
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
310
    def run(self, filename, all=False, plain=False, line='1', revision=None):
505.1.1 by Jelmer Vernooij
Make handle-patch not dependend on the users name being abentley and install it.
311
        gtk = open_display()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
312
59.2.1 by Aaron Bentley
Gannotate takes a line number
313
        try:
314
            line = int(line)
315
        except ValueError:
316
            raise BzrCommandError('Line argument ("%s") is not a number.' % 
317
                                  line)
318
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
319
        from annotate.gannotate import GAnnotateWindow
320
        from annotate.config import GAnnotateConfig
177 by Jelmer Vernooij
Register commands all at once.
321
        from bzrlib.bzrdir import BzrDir
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
322
161 by Aaron Bentley
Fix gannotate interaction with dirstate
323
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
324
        if wt is not None:
325
            tree = wt
326
        else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
327
            tree = br.basis_tree()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
328
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
329
        file_id = tree.path2id(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
330
331
        if file_id is None:
332
            raise NotVersionedError(filename)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
333
        if revision is not None:
334
            if len(revision) != 1:
335
                raise BzrCommandError("Only 1 revion may be specified.")
493 by Aaron Bentley
Convert remaining uses of RevisionSpec.in_history to as_revision_id
336
            revision_id = revision[0].as_revision_id(br)
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
337
            tree = br.repository.revision_tree(revision_id)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
338
        else:
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
339
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
340
473.1.1 by Andrew Bennetts
Simple hack to fix gannotate.
341
        window = GAnnotateWindow(all, plain, branch=br)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
342
        window.connect("destroy", lambda w: gtk.main_quit())
343
        config = GAnnotateConfig(window)
344
        window.show()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
345
        br.lock_read()
161 by Aaron Bentley
Fix gannotate interaction with dirstate
346
        if wt is not None:
347
            wt.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
348
        try:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
349
            window.annotate(tree, br, file_id)
161 by Aaron Bentley
Fix gannotate interaction with dirstate
350
            window.jump_to_line(line)
351
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
352
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
353
            br.unlock()
161 by Aaron Bentley
Fix gannotate interaction with dirstate
354
            if wt is not None:
355
                wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
356
357
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
358
359
class cmd_gcommit(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
360
    """GTK+ commit dialog
361
362
    Graphical user interface for committing revisions"""
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
363
145 by Jelmer Vernooij
Fix some strings, import.
364
    aliases = [ "gci" ]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
365
    takes_args = []
366
    takes_options = []
367
368
    def run(self, filename=None):
93.1.17 by Alexander Belchenko
gcommit reworked again.
369
        import os
505.1.1 by Jelmer Vernooij
Make handle-patch not dependend on the users name being abentley and install it.
370
        open_display()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
371
        from commit import CommitDialog
93.1.17 by Alexander Belchenko
gcommit reworked again.
372
        from bzrlib.errors import (BzrCommandError,
373
                                   NotBranchError,
178 by Jelmer Vernooij
Remove unneeded imports.
374
                                   NoWorkingTree)
93.1.17 by Alexander Belchenko
gcommit reworked again.
375
376
        wt = None
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
377
        br = None
93.1.17 by Alexander Belchenko
gcommit reworked again.
378
        try:
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
379
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
380
            br = wt.branch
93.1.17 by Alexander Belchenko
gcommit reworked again.
381
        except NoWorkingTree, e:
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
382
            from dialog import error_dialog
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
383
            error_dialog(_i18n('Directory does not have a working tree'),
384
                         _i18n('Operation aborted.'))
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
385
            return 1 # should this be retval=3?
386
387
        # It is a good habit to keep things locked for the duration, but it
388
        # could cause difficulties if someone wants to do things in another
389
        # window... We could lock_read() until we actually go to commit
390
        # changes... Just a thought.
391
        wt.lock_write()
392
        try:
393
            dlg = CommitDialog(wt)
394
            return dlg.run()
395
        finally:
396
            wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
397
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
398
250 by Aaron Bentley
oops- revert status change
399
class cmd_gstatus(GTKCommand):
157 by Jelmer Vernooij
Add gstatus command.
400
    """GTK+ status dialog
401
402
    Graphical user interface for showing status 
403
    information."""
404
    
405
    aliases = [ "gst" ]
406
    takes_args = ['PATH?']
463.1.1 by Javier Derderian
Added revision option to gstatus. Bug #136530
407
    takes_options = ['revision']
157 by Jelmer Vernooij
Add gstatus command.
408
463.1.1 by Javier Derderian
Added revision option to gstatus. Bug #136530
409
    def run(self, path='.', revision=None):
157 by Jelmer Vernooij
Add gstatus command.
410
        import os
505.1.1 by Jelmer Vernooij
Make handle-patch not dependend on the users name being abentley and install it.
411
        gtk = open_display()
157 by Jelmer Vernooij
Add gstatus command.
412
        from status import StatusDialog
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
413
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
463.1.1 by Javier Derderian
Added revision option to gstatus. Bug #136530
414
        
415
        if revision is not None:
463.1.2 by Javier Derderian
Added 'Revision # doesn't exist' message
416
            try:
493 by Aaron Bentley
Convert remaining uses of RevisionSpec.in_history to as_revision_id
417
                revision_id = revision[0].as_revision_id(wt.branch)
463.1.2 by Javier Derderian
Added 'Revision # doesn't exist' message
418
            except:
419
                from bzrlib.errors import BzrError
420
                raise BzrError('Revision %r doesn\'t exist' % revision[0].user_spec )
463.1.1 by Javier Derderian
Added revision option to gstatus. Bug #136530
421
        else:
422
            revision_id = None
423
424
        status = StatusDialog(wt, wt_path, revision_id)
157 by Jelmer Vernooij
Add gstatus command.
425
        status.connect("destroy", gtk.main_quit)
426
        status.run()
427
428
323 by Jelmer Vernooij
Add gsend command.
429
class cmd_gsend(GTKCommand):
430
    """GTK+ send merge directive.
431
432
    """
433
    def run(self):
434
        (br, path) = branch.Branch.open_containing(".")
505.1.1 by Jelmer Vernooij
Make handle-patch not dependend on the users name being abentley and install it.
435
        gtk = open_display()
323 by Jelmer Vernooij
Add gsend command.
436
        from bzrlib.plugins.gtk.mergedirective import SendMergeDirectiveDialog
324 by Jelmer Vernooij
Add very simple "Send Merge Directive" window.
437
        from StringIO import StringIO
323 by Jelmer Vernooij
Add gsend command.
438
        dialog = SendMergeDirectiveDialog(br)
324 by Jelmer Vernooij
Add very simple "Send Merge Directive" window.
439
        if dialog.run() == gtk.RESPONSE_OK:
440
            outf = StringIO()
441
            outf.writelines(dialog.get_merge_directive().to_lines())
442
            mail_client = br.get_config().get_mail_client()
443
            mail_client.compose_merge_request(dialog.get_mail_to(), "[MERGE]", 
444
                outf.getvalue())
445
446
            
323 by Jelmer Vernooij
Add gsend command.
447
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
448
449
class cmd_gconflicts(GTKCommand):
323 by Jelmer Vernooij
Add gsend command.
450
    """GTK+ conflicts.
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
451
    
242.1.2 by Adeodato Simó
Fix gconflicts docstring.
452
    Select files from the list of conflicts and run an external utility to
453
    resolve them.
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
454
    """
455
    def run(self):
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
456
        (wt, path) = workingtree.WorkingTree.open_containing('.')
505.1.1 by Jelmer Vernooij
Make handle-patch not dependend on the users name being abentley and install it.
457
        open_display()
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
458
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
459
        dialog = ConflictsDialog(wt)
460
        dialog.run()
461
157 by Jelmer Vernooij
Add gstatus command.
462
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
463
class cmd_gpreferences(GTKCommand):
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
464
    """ GTK+ preferences dialog.
465
466
    """
467
    def run(self):
505.1.1 by Jelmer Vernooij
Make handle-patch not dependend on the users name being abentley and install it.
468
        open_display()
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
469
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
470
        dialog = PreferencesWindow()
471
        dialog.run()
472
473
571.1.1 by Jasper Groenewegen
Add gmerge command and change MergeDialog to set parent as default if available
474
class cmd_gmerge(Command):
475
    """ GTK+ merge dialog
476
    
477
    """
478
    takes_args = ["merge_from_path?"]
479
    def run(self, merge_from_path=None):
480
        from bzrlib import workingtree
481
        from bzrlib.plugins.gtk.dialog import error_dialog
482
        from bzrlib.plugins.gtk.merge import MergeDialog
483
        
484
        (wt, path) = workingtree.WorkingTree.open_containing('.')
485
        old_tree = wt.branch.repository.revision_tree(wt.branch.last_revision())
486
        delta = wt.changes_from(old_tree)
487
        if len(delta.added) or len(delta.removed) or len(delta.renamed) or len(delta.modified):
488
            error_dialog(_i18n('There are local changes in the branch'),
489
                         _i18n('Please commit or revert the changes before merging.'))
490
        else:
491
            parent_branch_path = wt.branch.get_parent()
492
            merge = MergeDialog(wt, path, parent_branch_path)
493
            response = merge.run()
494
            merge.destroy()
495
496
175 by Jelmer Vernooij
Add very simple gmissing command.
497
class cmd_gmissing(Command):
498
    """ GTK+ missing revisions dialog.
499
500
    """
501
    takes_args = ["other_branch?"]
502
    def run(self, other_branch=None):
503
        pygtk = import_pygtk()
504
        try:
505
            import gtk
506
        except RuntimeError, e:
507
            if str(e) == "could not open display":
508
                raise NoDisplayError
509
510
        from bzrlib.plugins.gtk.missing import MissingWindow
511
        from bzrlib.branch import Branch
512
513
        local_branch = Branch.open_containing(".")[0]
514
        if other_branch is None:
515
            other_branch = local_branch.get_parent()
516
            
517
            if other_branch is None:
518
                raise errors.BzrCommandError("No peer location known or specified.")
519
        remote_branch = Branch.open_containing(other_branch)[0]
520
        set_ui_factory()
521
        local_branch.lock_read()
522
        try:
523
            remote_branch.lock_read()
524
            try:
525
                dialog = MissingWindow(local_branch, remote_branch)
526
                dialog.run()
527
            finally:
528
                remote_branch.unlock()
529
        finally:
530
            local_branch.unlock()
531
177 by Jelmer Vernooij
Register commands all at once.
532
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
533
class cmd_ginit(GTKCommand):
534
    def run(self):
505.1.1 by Jelmer Vernooij
Make handle-patch not dependend on the users name being abentley and install it.
535
        open_display()
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
536
        from initialize import InitDialog
537
        dialog = InitDialog(os.path.abspath(os.path.curdir))
538
        dialog.run()
539
540
190.1.1 by Szilveszter Farkas (Phanatic)
Added 'gtags' command and basic Tags window (just a skeleton).
541
class cmd_gtags(GTKCommand):
542
    def run(self):
543
        br = branch.Branch.open_containing('.')[0]
544
        
505.1.1 by Jelmer Vernooij
Make handle-patch not dependend on the users name being abentley and install it.
545
        gtk = open_display()
190.1.1 by Szilveszter Farkas (Phanatic)
Added 'gtags' command and basic Tags window (just a skeleton).
546
        from tags import TagsWindow
547
        window = TagsWindow(br)
548
        window.show()
549
        gtk.main()
550
551
177 by Jelmer Vernooij
Register commands all at once.
552
commands = [
323 by Jelmer Vernooij
Add gsend command.
553
    cmd_gannotate, 
554
    cmd_gbranch,
555
    cmd_gcheckout, 
556
    cmd_gcommit, 
557
    cmd_gconflicts, 
558
    cmd_gdiff,
559
    cmd_ginit,
571.1.1 by Jasper Groenewegen
Add gmerge command and change MergeDialog to set parent as default if available
560
    cmd_gmerge,
177 by Jelmer Vernooij
Register commands all at once.
561
    cmd_gmissing, 
562
    cmd_gpreferences, 
323 by Jelmer Vernooij
Add gsend command.
563
    cmd_gpush, 
564
    cmd_gsend,
177 by Jelmer Vernooij
Register commands all at once.
565
    cmd_gstatus,
323 by Jelmer Vernooij
Add gsend command.
566
    cmd_gtags,
567
    cmd_visualise
177 by Jelmer Vernooij
Register commands all at once.
568
    ]
569
580.1.5 by Jelmer Vernooij
Try to import rather than use getattr to avoid problems wrt the order in which plugins are loaded.
570
try:
571
    from bzrlib.plugins import loom
572
except ImportError:
573
    pass # Loom plugin doesn't appear to be present
574
else:
580.1.1 by Jelmer Vernooij
Add gloom command.
575
    commands.append(cmd_gloom)
576
177 by Jelmer Vernooij
Register commands all at once.
577
for cmd in commands:
578
    register_command(cmd)
175 by Jelmer Vernooij
Add very simple gmissing command.
579
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
580
249 by Aaron Bentley
Add gselftest command
581
class cmd_gselftest(GTKCommand):
582
    """Version of selftest that displays a notification at the end"""
583
584
    takes_args = builtins.cmd_selftest.takes_args
585
    takes_options = builtins.cmd_selftest.takes_options
586
    _see_also = ['selftest']
587
588
    def run(self, *args, **kwargs):
589
        import cgi
253 by Aaron Bentley
Avoid encoding problems from pygtk
590
        import sys
591
        default_encoding = sys.getdefaultencoding()
249 by Aaron Bentley
Add gselftest command
592
        # prevent gtk from blowing up later
593
        gtk = import_pygtk()
253 by Aaron Bentley
Avoid encoding problems from pygtk
594
        # prevent gtk from messing with default encoding
249 by Aaron Bentley
Add gselftest command
595
        import pynotify
253 by Aaron Bentley
Avoid encoding problems from pygtk
596
        if sys.getdefaultencoding() != default_encoding:
597
            reload(sys)
598
            sys.setdefaultencoding(default_encoding)
249 by Aaron Bentley
Add gselftest command
599
        result = builtins.cmd_selftest().run(*args, **kwargs)
600
        if result == 0:
601
            summary = 'Success'
602
            body = 'Selftest succeeded in "%s"' % os.getcwd()
603
        if result == 1:
604
            summary = 'Failure'
605
            body = 'Selftest failed in "%s"' % os.getcwd()
606
        pynotify.init("bzr gselftest")
607
        note = pynotify.Notification(cgi.escape(summary), cgi.escape(body))
608
        note.set_timeout(pynotify.EXPIRES_NEVER)
609
        note.show()
610
611
612
register_command(cmd_gselftest)
613
614
278.1.22 by John Arbash Meinel
Add a test-gtk command to make testing faster
615
class cmd_test_gtk(GTKCommand):
616
    """Version of selftest that just runs the gtk test suite."""
617
618
    takes_options = ['verbose',
619
                     Option('one', short_name='1',
330.6.2 by Aaron Bentley
Fix option grammar
620
                            help='Stop when one test fails.'),
621
                     Option('benchmark', help='Run the benchmarks.'),
278.1.22 by John Arbash Meinel
Add a test-gtk command to make testing faster
622
                     Option('lsprof-timed',
330.6.2 by Aaron Bentley
Fix option grammar
623
                     help='Generate lsprof output for benchmarked'
278.1.22 by John Arbash Meinel
Add a test-gtk command to make testing faster
624
                          ' sections of code.'),
625
                     Option('list-only',
330.6.2 by Aaron Bentley
Fix option grammar
626
                     help='List the tests instead of running them.'),
278.1.22 by John Arbash Meinel
Add a test-gtk command to make testing faster
627
                     Option('randomize', type=str, argname="SEED",
330.6.2 by Aaron Bentley
Fix option grammar
628
                     help='Randomize the order of tests using the given'
629
                          ' seed or "now" for the current time.'),
278.1.22 by John Arbash Meinel
Add a test-gtk command to make testing faster
630
                    ]
631
    takes_args = ['testspecs*']
632
633
    def run(self, verbose=None, one=False, benchmark=None,
634
            lsprof_timed=None, list_only=False, randomize=None,
635
            testspecs_list=None):
636
        from bzrlib import __path__ as bzrlib_path
637
        from bzrlib.tests import selftest
638
639
        print '%10s: %s' % ('bzrlib', bzrlib_path[0])
640
        if benchmark:
641
            print 'No benchmarks yet'
642
            return 3
643
644
            test_suite_factory = bench_suite
645
            if verbose is None:
646
                verbose = True
647
            # TODO: should possibly lock the history file...
648
            benchfile = open(".perf_history", "at", buffering=1)
649
        else:
650
            test_suite_factory = test_suite
651
            if verbose is None:
652
                verbose = False
653
            benchfile = None
654
655
        if testspecs_list is not None:
656
            pattern = '|'.join(testspecs_list)
657
        else:
658
            pattern = ".*"
659
660
        try:
661
            result = selftest(verbose=verbose,
662
                              pattern=pattern,
663
                              stop_on_failure=one,
664
                              test_suite_factory=test_suite_factory,
665
                              lsprof_timed=lsprof_timed,
666
                              bench_history=benchfile,
667
                              list_only=list_only,
668
                              random_seed=randomize,
669
                             )
670
        finally:
671
            if benchfile is not None:
672
                benchfile.close()
673
674
register_command(cmd_test_gtk)
675
676
424 by Aaron Bentley
Add ghandle-patch
677
152 by Jelmer Vernooij
Cleanup some more code.
678
import gettext
679
gettext.install('olive-gtk')
680
475.1.2 by Vincent Ladeuil
Fix bug #187283 fix replacing _() by _i18n().
681
# Let's create a specialized alias to protect '_' from being erased by other
682
# uses of '_' as an anonymous variable (think pdb for one).
683
_i18n = gettext.gettext
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
684
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
685
class NoDisplayError(BzrCommandError):
686
    """gtk could not find a proper display"""
687
688
    def __str__(self):
133 by Jelmer Vernooij
Actually use the ui factory.
689
        return "No DISPLAY. Unable to run GTK+ application."
690
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
691
140 by Jelmer Vernooij
add framework for tests.
692
def test_suite():
693
    from unittest import TestSuite
694
    import tests
163 by Aaron Bentley
Prevent test suite from causing default-encoding changes
695
    import sys
696
    default_encoding = sys.getdefaultencoding()
697
    try:
698
        result = TestSuite()
330.6.4 by Aaron Bentley
Allow test suite to run without pygtk
699
        try:
700
            import_pygtk()
701
        except errors.BzrCommandError:
702
            return result
163 by Aaron Bentley
Prevent test suite from causing default-encoding changes
703
        result.addTest(tests.test_suite())
704
    finally:
170.1.2 by Aaron Bentley
Test suite only fixes encoding if it's changed. Fixes test_selftest bug.
705
        if sys.getdefaultencoding() != default_encoding:
706
            reload(sys)
707
            sys.setdefaultencoding(default_encoding)
140 by Jelmer Vernooij
add framework for tests.
708
    return result