19
from gi.repository import Gdk
19
20
from gi.repository import Gtk
20
21
from gi.repository import GObject
21
22
from gi.repository import Pango
25
from bzrlib import bencode
27
from bzrlib.util import bencode
23
29
from bzrlib import (
29
from bzrlib import bencode
31
from bzrlib.util import bencode
33
33
from bzrlib.plugins.gtk.dialog import question_dialog
34
34
from bzrlib.plugins.gtk.errors import show_bzr_error
35
35
from bzrlib.plugins.gtk.i18n import _i18n
36
from bzrlib.plugins.gtk.commitmsgs import SavedCommitMessagesManager
107
108
"""Implementation of Commit."""
109
110
def __init__(self, wt, selected=None, parent=None):
110
GObject.GObject.__init__(self, title="Commit to %s" % wt.basedir,
111
parent=parent, flags=0,)
111
super(CommitDialog, self).__init__(
112
title="Commit to %s" % wt.basedir, parent=parent, flags=0)
112
113
self.connect('delete-event', self._on_delete_window)
113
114
self._question_dialog = question_dialog
354
356
self._button_cancel = Gtk.Button(stock=Gtk.STOCK_CANCEL)
355
357
self._button_cancel.connect('clicked', self._on_cancel_clicked)
356
358
self._button_cancel.show()
357
self.action_area.pack_end(self._button_cancel)
359
self.get_action_area().pack_end(
360
self._button_cancel, True, True, 0)
358
361
self._button_commit = Gtk.Button(_i18n("Comm_it"), use_underline=True)
359
362
self._button_commit.connect('clicked', self._on_commit_clicked)
360
363
self._button_commit.set_can_default(True)
361
364
self._button_commit.show()
362
self.action_area.pack_end(self._button_commit)
365
self.get_action_area().pack_end(
366
self._button_commit, True, True, 0)
363
367
self._button_commit.grab_default()
365
369
def _add_to_right_table(self, widget, weight, expanding=False):
385
389
# file_label.show()
386
390
self._files_box.pack_start(file_label, False, True, 0)
388
self._commit_all_files_radio = Gtk.RadioButton(
392
self._commit_all_files_radio = Gtk.RadioButton.new_with_label(
389
393
None, _i18n("Commit all changes"))
390
394
self._files_box.pack_start(self._commit_all_files_radio, False, True, 0)
391
395
self._commit_all_files_radio.show()
392
396
self._commit_all_files_radio.connect('toggled',
393
397
self._toggle_commit_selection)
394
self._commit_selected_radio = Gtk.RadioButton(
398
self._commit_selected_radio = Gtk.RadioButton.new_with_label_from_widget(
395
399
self._commit_all_files_radio, _i18n("Only commit selected changes"))
396
400
self._files_box.pack_start(self._commit_selected_radio, False, True, 0)
397
401
self._commit_selected_radio.show()
473
476
pending_message = Gtk.Label()
474
477
pending_message.set_markup(
475
478
_i18n('<i>* Cannot select specific files when merging</i>'))
476
self._pending_box.pack_start(pending_message, expand=False, padding=5)
479
self._pending_box.pack_start(pending_message, False, True, 5)
477
480
pending_message.show()
479
482
pending_label = Gtk.Label(label=_i18n('Pending Revisions'))
480
self._pending_box.pack_start(pending_label, expand=False, padding=0)
483
self._pending_box.pack_start(pending_label, False, True, 0)
481
484
pending_label.show()
483
486
scroller = Gtk.ScrolledWindow()
486
489
scroller.add(self._treeview_pending)
487
490
scroller.set_shadow_type(Gtk.ShadowType.IN)
489
self._pending_box.pack_start(scroller,
490
expand=True, fill=True, padding=5)
492
self._pending_box.pack_start(scroller, True, True, 5)
491
493
self._treeview_pending.show()
492
494
self._left_pane_box.pack_start(self._pending_box, True, True, 0)
593
596
# We have either made it to the end of the list, or nothing was
594
597
# selected. Either way, select All Files, and jump to the global
595
598
# commit message.
596
self._treeview_files.set_cursor((0,))
599
self._treeview_files.set_cursor(
600
Gtk.TreePath(path=0), None, False)
597
601
self._global_message_text_view.grab_focus()
599
603
# Set the cursor to this entry, and jump to the per-file commit
601
self._treeview_files.set_cursor(model.get_path(next))
605
self._treeview_files.set_cursor(model.get_path(next), None, False)
602
606
self._file_message_text_view.grab_focus()
604
608
def _save_current_file_message(self):
789
793
rev_dict['revision_id'] = rev.revision_id
793
class SavedCommitMessagesManager:
794
"""Save glogal and per-file commit messages.
796
Saves global commit message and utf-8 file_id->message dictionary
797
of per-file commit messages on disk. Re-reads them later for re-using.
800
def __init__(self, tree=None, branch=None):
801
"""If branch is None, builds empty messages, otherwise reads them
802
from branch's disk storage. 'tree' argument is for the future."""
804
self.global_message = u''
805
self.file_messages = {}
807
config = branch.get_config()
808
self.global_message = config.get_user_option(
809
'gtk_global_commit_message')
810
if self.global_message is None:
811
self.global_message = u''
812
file_messages = config.get_user_option('gtk_file_commit_messages')
813
if file_messages: # unicode and B-encoded:
814
self.file_messages = bencode.bdecode(
815
file_messages.encode('UTF-8'))
817
self.file_messages = {}
820
return self.global_message, self.file_messages
822
def is_not_empty(self):
823
return bool(self.global_message or self.file_messages)
825
def insert(self, global_message, file_info):
826
"""Formats per-file commit messages (list of dictionaries, one per file)
827
into one utf-8 file_id->message dictionary and merges this with
828
previously existing dictionary. Merges global commit message too."""
831
file_message = fi['message']
833
file_messages[fi['file_id']] = file_message # utf-8 strings
834
for k,v in file_messages.iteritems():
836
self.file_messages[k] = v + '\n******\n' + self.file_messages[k]
838
self.file_messages[k] = v
839
if self.global_message:
840
self.global_message = global_message + '\n******\n' \
841
+ self.global_message
843
self.global_message = global_message
845
def save(self, tree, branch):
846
# We store in branch's config, which can be a problem if two gcommit
847
# are done in two checkouts of one single branch (comments overwrite
848
# each other). Ideally should be in working tree. But uncommit does
849
# not always have a working tree, though it always has a branch.
850
# 'tree' argument is for the future
851
config = branch.get_config()
852
# should it be named "gtk_" or some more neutral name ("gui_" ?) to
853
# be compatible with qbzr in the future?
854
config.set_user_option('gtk_global_commit_message', self.global_message)
855
# bencode() does not know unicode objects but set_user_option()
857
config.set_user_option(
858
'gtk_file_commit_messages',
859
bencode.bencode(self.file_messages).decode('UTF-8'))
862
def save_commit_messages(local, master, old_revno, old_revid,
863
new_revno, new_revid):
867
mgr = SavedCommitMessagesManager(None, b)
868
revid_iterator = b.repository.iter_reverse_revision_history(old_revid)
869
cur_revno = old_revno
870
new_revision_id = old_revid
871
graph = b.repository.get_graph()
872
for rev_id in revid_iterator:
873
if cur_revno == new_revno:
876
rev = b.repository.get_revision(rev_id)
877
file_info = rev.properties.get('file-info', None)
878
if file_info is None:
881
file_info = bencode.bdecode(file_info.encode('UTF-8'))
882
global_message = osutils.safe_unicode(rev.message)
883
# Concatenate comment of the uncommitted revision
884
mgr.insert(global_message, file_info)
886
parents = graph.get_parent_map([rev_id]).get(rev_id, None)