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 status import StatusDialog
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' % revision[0].user_spec )
425
status = StatusDialog(wt, wt_path, revision_id)
426
status.connect("destroy", gtk.main_quit)
430
class cmd_gsend(GTKCommand):
431
"""GTK+ send merge directive.
435
(br, path) = branch.Branch.open_containing(".")
437
from bzrlib.plugins.gtk.mergedirective import SendMergeDirectiveDialog
438
from StringIO import StringIO
439
dialog = SendMergeDirectiveDialog(br)
440
if dialog.run() == gtk.RESPONSE_OK:
442
outf.writelines(dialog.get_merge_directive().to_lines())
443
mail_client = br.get_config().get_mail_client()
444
mail_client.compose_merge_request(dialog.get_mail_to(), "[MERGE]",
450
class cmd_gconflicts(GTKCommand):
453
Select files from the list of conflicts and run an external utility to
457
(wt, path) = workingtree.WorkingTree.open_containing('.')
459
from bzrlib.plugins.gtk.conflicts import ConflictsDialog
460
dialog = ConflictsDialog(wt)
464
class cmd_gpreferences(GTKCommand):
465
""" GTK+ preferences dialog.
470
from bzrlib.plugins.gtk.preferences import PreferencesWindow
471
dialog = PreferencesWindow()
475
class cmd_ginfo(Command):
480
from bzrlib import workingtree
481
from bzrlib.plugins.gtk.olive.info import InfoDialog
482
wt = workingtree.WorkingTree.open_containing('.')[0]
483
info = InfoDialog(wt.branch)
488
class cmd_gmerge(Command):
489
""" GTK+ merge dialog
492
takes_args = ["merge_from_path?"]
493
def run(self, merge_from_path=None):
494
from bzrlib import workingtree
495
from bzrlib.plugins.gtk.dialog import error_dialog
496
from bzrlib.plugins.gtk.merge import MergeDialog
498
(wt, path) = workingtree.WorkingTree.open_containing('.')
499
old_tree = wt.branch.repository.revision_tree(wt.branch.last_revision())
500
delta = wt.changes_from(old_tree)
501
if len(delta.added) or len(delta.removed) or len(delta.renamed) or len(delta.modified):
502
error_dialog(_i18n('There are local changes in the branch'),
503
_i18n('Please commit or revert the changes before merging.'))
505
parent_branch_path = wt.branch.get_parent()
506
merge = MergeDialog(wt, path, parent_branch_path)
507
response = merge.run()
511
class cmd_gmissing(Command):
512
""" GTK+ missing revisions dialog.
515
takes_args = ["other_branch?"]
516
def run(self, other_branch=None):
517
pygtk = import_pygtk()
520
except RuntimeError, e:
521
if str(e) == "could not open display":
524
from bzrlib.plugins.gtk.missing import MissingWindow
525
from bzrlib.branch import Branch
527
local_branch = Branch.open_containing(".")[0]
528
if other_branch is None:
529
other_branch = local_branch.get_parent()
531
if other_branch is None:
532
raise errors.BzrCommandError("No peer location known or specified.")
533
remote_branch = Branch.open_containing(other_branch)[0]
535
local_branch.lock_read()
537
remote_branch.lock_read()
539
dialog = MissingWindow(local_branch, remote_branch)
542
remote_branch.unlock()
544
local_branch.unlock()
547
class cmd_ginit(GTKCommand):
550
from initialize import InitDialog
551
dialog = InitDialog(os.path.abspath(os.path.curdir))
555
class cmd_gtags(GTKCommand):
557
br = branch.Branch.open_containing('.')[0]
560
from tags import TagsWindow
561
window = TagsWindow(br)
119
586
from bzrlib.plugins import loom
120
587
except ImportError:
121
588
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):
590
commands.append(cmd_gloom)
593
register_command(cmd)
596
class cmd_gselftest(GTKCommand):
597
"""Version of selftest that displays a notification at the end"""
599
takes_args = builtins.cmd_selftest.takes_args
600
takes_options = builtins.cmd_selftest.takes_options
601
_see_also = ['selftest']
603
def run(self, *args, **kwargs):
606
default_encoding = sys.getdefaultencoding()
607
# prevent gtk from blowing up later
609
# prevent gtk from messing with default encoding
611
if sys.getdefaultencoding() != default_encoding:
613
sys.setdefaultencoding(default_encoding)
614
result = builtins.cmd_selftest().run(*args, **kwargs)
617
body = 'Selftest succeeded in "%s"' % os.getcwd()
620
body = 'Selftest failed in "%s"' % os.getcwd()
621
pynotify.init("bzr gselftest")
622
note = pynotify.Notification(cgi.escape(summary), cgi.escape(body))
623
note.set_timeout(pynotify.EXPIRES_NEVER)
627
register_command(cmd_gselftest)
630
class cmd_test_gtk(GTKCommand):
631
"""Version of selftest that just runs the gtk test suite."""
633
takes_options = ['verbose',
634
Option('one', short_name='1',
635
help='Stop when one test fails.'),
636
Option('benchmark', help='Run the benchmarks.'),
637
Option('lsprof-timed',
638
help='Generate lsprof output for benchmarked'
639
' sections of code.'),
641
help='List the tests instead of running them.'),
642
Option('randomize', type=str, argname="SEED",
643
help='Randomize the order of tests using the given'
644
' seed or "now" for the current time.'),
646
takes_args = ['testspecs*']
648
def run(self, verbose=None, one=False, benchmark=None,
649
lsprof_timed=None, list_only=False, randomize=None,
650
testspecs_list=None):
651
from bzrlib import __path__ as bzrlib_path
652
from bzrlib.tests import selftest
654
print '%10s: %s' % ('bzrlib', bzrlib_path[0])
656
print 'No benchmarks yet'
659
test_suite_factory = bench_suite
662
# TODO: should possibly lock the history file...
663
benchfile = open(".perf_history", "at", buffering=1)
665
test_suite_factory = test_suite
670
if testspecs_list is not None:
671
pattern = '|'.join(testspecs_list)
676
result = selftest(verbose=verbose,
679
test_suite_factory=test_suite_factory,
680
lsprof_timed=lsprof_timed,
681
bench_history=benchfile,
683
random_seed=randomize,
686
if benchfile is not None:
689
register_command(cmd_test_gtk)
694
gettext.install('olive-gtk')
696
# Let's create a specialized alias to protect '_' from being erased by other
697
# uses of '_' as an anonymous variable (think pdb for one).
698
_i18n = gettext.gettext
700
class NoDisplayError(BzrCommandError):
701
"""gtk could not find a proper display"""
704
return "No DISPLAY. Unable to run GTK+ application."
708
from unittest import TestSuite
163
711
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]))
716
except errors.BzrCommandError:
718
result.addTest(tests.test_suite())
173
720
if sys.getdefaultencoding() != default_encoding:
175
722
sys.setdefaultencoding(default_encoding)