97
124
return data_path(os.path.join('icons', *args))
101
"gannotate": ["gblame", "gpraise"],
115
"visualise": ["visualize", "vis", "viz", 'glog'],
128
pygtk = import_pygtk()
131
except RuntimeError, e:
132
if str(e) == "could not open display":
138
class GTKCommand(Command):
139
"""Abstract class providing GTK specific run commands."""
143
dialog = self.get_gtk_dialog(os.path.abspath('.'))
147
class cmd_gbranch(GTKCommand):
152
def get_gtk_dialog(self, path):
153
from bzrlib.plugins.gtk.branch import BranchDialog
154
return BranchDialog(path)
157
class cmd_gcheckout(GTKCommand):
162
def get_gtk_dialog(self, path):
163
from bzrlib.plugins.gtk.checkout import CheckoutDialog
164
return CheckoutDialog(path)
168
class cmd_gpush(GTKCommand):
172
takes_args = [ "location?" ]
174
def run(self, location="."):
175
(br, path) = branch.Branch.open_containing(location)
177
from bzrlib.plugins.gtk.push import PushDialog
178
dialog = PushDialog(br.repository, br.last_revision(), br)
182
class cmd_gloom(GTKCommand):
186
takes_args = [ "location?" ]
188
def run(self, location="."):
190
(tree, path) = workingtree.WorkingTree.open_containing(location)
192
except NoWorkingTree, e:
193
(br, path) = branch.Branch.open_containing(location)
196
from bzrlib.plugins.gtk.loom import LoomDialog
197
dialog = LoomDialog(br, tree)
201
class cmd_gdiff(GTKCommand):
202
"""Show differences in working tree in a GTK+ Window.
204
Otherwise, all changes for the tree are listed.
206
takes_args = ['filename?']
207
takes_options = ['revision']
210
def run(self, revision=None, filename=None):
212
wt = workingtree.WorkingTree.open_containing(".")[0]
216
if revision is not None:
217
if len(revision) == 1:
219
revision_id = revision[0].as_revision_id(tree1.branch)
220
tree2 = branch.repository.revision_tree(revision_id)
221
elif len(revision) == 2:
222
revision_id_0 = revision[0].as_revision_id(branch)
223
tree2 = branch.repository.revision_tree(revision_id_0)
224
revision_id_1 = revision[1].as_revision_id(branch)
225
tree1 = branch.repository.revision_tree(revision_id_1)
228
tree2 = tree1.basis_tree()
230
from diff import DiffWindow
232
window = DiffWindow()
233
window.connect("destroy", gtk.main_quit)
234
window.set_diff("Working Tree", tree1, tree2)
235
if filename is not None:
236
tree_filename = wt.relpath(filename)
238
window.set_file(tree_filename)
240
if (tree1.path2id(tree_filename) is None and
241
tree2.path2id(tree_filename) is None):
242
raise NotVersionedError(filename)
243
raise BzrCommandError('No changes found for file "%s"' %
252
def start_viz_window(branch, revisions, limit=None):
253
"""Start viz on branch with revision revision.
255
:return: The viz window object.
257
from bzrlib.plugins.gtk.viz import BranchWindow
258
return BranchWindow(branch, revisions, limit)
261
class cmd_visualise(Command):
262
"""Graphically visualise this branch.
264
Opens a graphical window to allow you to see the history of the branch
265
and relationships between revisions in a visual manner,
267
The default starting point is latest revision on the branch, you can
268
specify a starting point with -r revision.
272
Option('limit', "Maximum number of revisions to display.",
274
takes_args = [ "locations*" ]
275
aliases = [ "visualize", "vis", "viz" ]
277
def run(self, locations_list, revision=None, limit=None):
279
if locations_list is None:
280
locations_list = ["."]
282
for location in locations_list:
283
(br, path) = branch.Branch.open_containing(location)
285
revids.append(br.last_revision())
287
revids.append(revision[0].as_revision_id(br))
289
pp = start_viz_window(br, revids, limit)
290
pp.connect("destroy", lambda w: gtk.main_quit())
295
class cmd_gannotate(GTKCommand):
298
Browse changes to FILENAME line by line in a GTK+ window.
301
takes_args = ["filename", "line?"]
303
Option("all", help="Show annotations on all lines."),
304
Option("plain", help="Don't highlight annotation lines."),
305
Option("line", type=int, argname="lineno",
306
help="Jump to specified line number."),
309
aliases = ["gblame", "gpraise"]
311
def run(self, filename, all=False, plain=False, line='1', revision=None):
317
raise BzrCommandError('Line argument ("%s") is not a number.' %
320
from annotate.gannotate import GAnnotateWindow
321
from annotate.config import GAnnotateConfig
322
from bzrlib.bzrdir import BzrDir
324
wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
328
tree = br.basis_tree()
330
file_id = tree.path2id(path)
333
raise NotVersionedError(filename)
334
if revision is not None:
335
if len(revision) != 1:
336
raise BzrCommandError("Only 1 revion may be specified.")
337
revision_id = revision[0].as_revision_id(br)
338
tree = br.repository.revision_tree(revision_id)
340
revision_id = getattr(tree, 'get_revision_id', lambda: None)()
342
window = GAnnotateWindow(all, plain, branch=br)
343
window.connect("destroy", lambda w: gtk.main_quit())
344
config = GAnnotateConfig(window)
350
window.annotate(tree, br, file_id)
351
window.jump_to_line(line)
360
class cmd_gcommit(GTKCommand):
361
"""GTK+ commit dialog
363
Graphical user interface for committing revisions"""
369
def run(self, filename=None):
372
from commit import CommitDialog
373
from bzrlib.errors import (BzrCommandError,
380
(wt, path) = workingtree.WorkingTree.open_containing(filename)
382
except NoWorkingTree, e:
383
from dialog import error_dialog
384
error_dialog(_i18n('Directory does not have a working tree'),
385
_i18n('Operation aborted.'))
386
return 1 # should this be retval=3?
388
# It is a good habit to keep things locked for the duration, but it
389
# could cause difficulties if someone wants to do things in another
390
# window... We could lock_read() until we actually go to commit
391
# changes... Just a thought.
394
dlg = CommitDialog(wt)
400
class cmd_gstatus(GTKCommand):
401
"""GTK+ status dialog
403
Graphical user interface for showing status
407
takes_args = ['PATH?']
408
takes_options = ['revision']
410
def run(self, path='.', revision=None):
413
from bzrlib.plugins.gtk.status import StatusWindow
414
(wt, wt_path) = workingtree.WorkingTree.open_containing(path)
416
if revision is not None:
418
revision_id = revision[0].as_revision_id(wt.branch)
420
from bzrlib.errors import BzrError
421
raise BzrError('Revision %r doesn\'t exist'
422
% revision[0].user_spec )
426
status = StatusWindow(wt, wt_path, revision_id)
427
status.connect("destroy", gtk.main_quit)
432
class cmd_gsend(GTKCommand):
433
"""GTK+ send merge directive.
437
(br, path) = branch.Branch.open_containing(".")
439
from bzrlib.plugins.gtk.mergedirective import SendMergeDirectiveDialog
440
from StringIO import StringIO
441
dialog = SendMergeDirectiveDialog(br)
442
if dialog.run() == gtk.RESPONSE_OK:
444
outf.writelines(dialog.get_merge_directive().to_lines())
445
mail_client = br.get_config().get_mail_client()
446
mail_client.compose_merge_request(dialog.get_mail_to(), "[MERGE]",
452
class cmd_gconflicts(GTKCommand):
455
Select files from the list of conflicts and run an external utility to
459
(wt, path) = workingtree.WorkingTree.open_containing('.')
461
from bzrlib.plugins.gtk.conflicts import ConflictsDialog
462
dialog = ConflictsDialog(wt)
466
class cmd_gpreferences(GTKCommand):
467
""" GTK+ preferences dialog.
472
from bzrlib.plugins.gtk.preferences import PreferencesWindow
473
dialog = PreferencesWindow()
477
class cmd_ginfo(Command):
482
from bzrlib import workingtree
483
from bzrlib.plugins.gtk.olive.info import InfoDialog
484
wt = workingtree.WorkingTree.open_containing('.')[0]
485
info = InfoDialog(wt.branch)
490
class cmd_gmerge(Command):
491
""" GTK+ merge dialog
494
takes_args = ["merge_from_path?"]
495
def run(self, merge_from_path=None):
496
from bzrlib import workingtree
497
from bzrlib.plugins.gtk.dialog import error_dialog
498
from bzrlib.plugins.gtk.merge import MergeDialog
500
(wt, path) = workingtree.WorkingTree.open_containing('.')
501
old_tree = wt.branch.repository.revision_tree(wt.branch.last_revision())
502
delta = wt.changes_from(old_tree)
503
if len(delta.added) or len(delta.removed) or len(delta.renamed) or len(delta.modified):
504
error_dialog(_i18n('There are local changes in the branch'),
505
_i18n('Please commit or revert the changes before merging.'))
507
parent_branch_path = wt.branch.get_parent()
508
merge = MergeDialog(wt, path, parent_branch_path)
509
response = merge.run()
513
class cmd_gmissing(Command):
514
""" GTK+ missing revisions dialog.
517
takes_args = ["other_branch?"]
518
def run(self, other_branch=None):
519
pygtk = import_pygtk()
522
except RuntimeError, e:
523
if str(e) == "could not open display":
526
from bzrlib.plugins.gtk.missing import MissingWindow
527
from bzrlib.branch import Branch
529
local_branch = Branch.open_containing(".")[0]
530
if other_branch is None:
531
other_branch = local_branch.get_parent()
533
if other_branch is None:
534
raise errors.BzrCommandError("No peer location known or specified.")
535
remote_branch = Branch.open_containing(other_branch)[0]
537
local_branch.lock_read()
539
remote_branch.lock_read()
541
dialog = MissingWindow(local_branch, remote_branch)
544
remote_branch.unlock()
546
local_branch.unlock()
549
class cmd_ginit(GTKCommand):
552
from initialize import InitDialog
553
dialog = InitDialog(os.path.abspath(os.path.curdir))
557
class cmd_gtags(GTKCommand):
559
br = branch.Branch.open_containing('.')[0]
562
from tags import TagsWindow
563
window = TagsWindow(br)
119
588
from bzrlib.plugins import loom
120
589
except ImportError:
121
590
pass # Loom plugin doesn't appear to be present
123
commands["gloom"] = []
125
for cmd, aliases in commands.iteritems():
126
plugin_cmds.register_lazy("cmd_%s" % cmd, aliases,
127
"bzrlib.plugins.gtk.commands")
129
def save_commit_messages(*args):
130
from bzrlib.plugins.gtk import commitmsgs
131
commitmsgs.save_commit_messages(*args)
134
from bzrlib.hooks import install_lazy_named_hook
136
from bzrlib.branch import Branch
137
Branch.hooks.install_named_hook('post_uncommit',
138
save_commit_messages,
139
"Saving commit messages for gcommit")
141
install_lazy_named_hook("bzrlib.branch", "Branch.hooks",
142
'post_uncommit', save_commit_messages, "Saving commit messages for gcommit")
145
from bzrlib.registry import register_lazy
147
from bzrlib import config
148
option_registry = getattr(config, "option_registry", None)
149
if option_registry is not None:
150
config.option_registry.register_lazy('nautilus_integration',
151
'bzrlib.plugins.gtk.config', 'opt_nautilus_integration')
153
register_lazy("bzrlib.config", "option_registry",
154
'nautilus_integration', 'bzrlib.plugins.gtk.config',
155
'opt_nautilus_integration')
158
def load_tests(basic_tests, module, loader):
592
commands.append(cmd_gloom)
595
register_command(cmd)
598
class cmd_gselftest(GTKCommand):
599
"""Version of selftest that displays a notification at the end"""
601
takes_args = builtins.cmd_selftest.takes_args
602
takes_options = builtins.cmd_selftest.takes_options
603
_see_also = ['selftest']
605
def run(self, *args, **kwargs):
608
default_encoding = sys.getdefaultencoding()
609
# prevent gtk from blowing up later
611
# prevent gtk from messing with default encoding
613
if sys.getdefaultencoding() != default_encoding:
615
sys.setdefaultencoding(default_encoding)
616
result = builtins.cmd_selftest().run(*args, **kwargs)
619
body = 'Selftest succeeded in "%s"' % os.getcwd()
622
body = 'Selftest failed in "%s"' % os.getcwd()
623
pynotify.init("bzr gselftest")
624
note = pynotify.Notification(cgi.escape(summary), cgi.escape(body))
625
note.set_timeout(pynotify.EXPIRES_NEVER)
629
register_command(cmd_gselftest)
633
gettext.install('olive-gtk')
635
# Let's create a specialized alias to protect '_' from being erased by other
636
# uses of '_' as an anonymous variable (think pdb for one).
637
_i18n = gettext.gettext
639
class NoDisplayError(BzrCommandError):
640
"""gtk could not find a proper display"""
643
return "No DISPLAY. Unable to run GTK+ application."
647
from unittest import TestSuite
163
650
default_encoding = sys.getdefaultencoding()
167
import gi.repository.Gtk
170
basic_tests.addTest(loader.loadTestsFromModuleNames(
171
["%s.%s" % (__name__, tmn) for tmn in testmod_names]))
655
except errors.BzrCommandError:
657
result.addTest(tests.test_suite())
173
659
if sys.getdefaultencoding() != default_encoding:
175
661
sys.setdefaultencoding(default_encoding)