/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz

« back to all changes in this revision

Viewing changes to commit.py

  • Committer: Andrew Starr-Bochicchio
  • Author(s): Mathias Brodala
  • Date: 2010-01-25 01:58:58 UTC
  • mto: This revision was merged to the branch mainline in revision 673.
  • Revision ID: a.starr.b@gmail.com-20100125015858-tphqkvgyfrvob63o
olive/menu.py: Correctly import commit dialog.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
 
17
import os.path
 
18
import re
 
19
 
17
20
try:
18
21
    import pygtk
19
22
    pygtk.require("2.0")
24
27
import gobject
25
28
import pango
26
29
 
27
 
import os.path
28
 
import re
29
 
 
30
 
from bzrlib import errors, osutils
31
 
from bzrlib.trace import mutter
32
 
from bzrlib.util import bencode
33
 
 
34
 
from dialog import error_dialog, question_dialog
35
 
from errors import show_bzr_error
 
30
from bzrlib import (
 
31
    branch,
 
32
    errors,
 
33
    osutils,
 
34
    trace,
 
35
    )
 
36
try:
 
37
    from bzrlib import bencode
 
38
except ImportError:
 
39
    from bzrlib.util import bencode
 
40
 
 
41
from bzrlib.plugins.gtk import _i18n
 
42
from bzrlib.plugins.gtk.dialog import question_dialog
 
43
from bzrlib.plugins.gtk.errors import show_bzr_error
36
44
 
37
45
try:
38
46
    import dbus
96
104
    return pm
97
105
 
98
106
 
 
107
_newline_variants_re = re.compile(r'\r\n?')
 
108
def _sanitize_and_decode_message(utf8_message):
 
109
    """Turn a utf-8 message into a sanitized Unicode message."""
 
110
    fixed_newline = _newline_variants_re.sub('\n', utf8_message)
 
111
    return fixed_newline.decode('utf-8')
 
112
 
 
113
 
99
114
class CommitDialog(gtk.Dialog):
100
115
    """Implementation of Commit."""
101
116
 
102
117
    def __init__(self, wt, selected=None, parent=None):
103
 
        gtk.Dialog.__init__(self, title="Commit - Olive",
104
 
                                  parent=parent,
105
 
                                  flags=0,
106
 
                                  buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
 
118
        gtk.Dialog.__init__(self, title="Commit to %s" % wt.basedir,
 
119
                            parent=parent, flags=0,)
 
120
        self.connect('delete-event', self._on_delete_window)
107
121
        self._question_dialog = question_dialog
108
122
 
 
123
        self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_NORMAL)
 
124
 
109
125
        self._wt = wt
110
126
        # TODO: Do something with this value, it is used by Olive
111
127
        #       It used to set all changes but this one to False
113
129
        self._enable_per_file_commits = True
114
130
        self._commit_all_changes = True
115
131
        self.committed_revision_id = None # Nothing has been committed yet
 
132
        self._saved_commit_messages_manager = SavedCommitMessagesManager(self._wt, self._wt.branch)
116
133
 
117
134
        self.setup_params()
118
135
        self.construct()
164
181
        store = self._files_store
165
182
        self._treeview_files.set_model(None)
166
183
 
167
 
        added = _('added')
168
 
        removed = _('removed')
169
 
        renamed = _('renamed')
170
 
        renamed_and_modified = _('renamed and modified')
171
 
        modified = _('modified')
172
 
        kind_changed = _('kind changed')
 
184
        added = _i18n('added')
 
185
        removed = _i18n('removed')
 
186
        renamed = _i18n('renamed')
 
187
        renamed_and_modified = _i18n('renamed and modified')
 
188
        modified = _i18n('modified')
 
189
        kind_changed = _i18n('kind changed')
173
190
 
174
191
        # The store holds:
175
192
        # [file_id, real path, checkbox, display path, changes type, message]
176
 
        # _iter_changes returns:
 
193
        # iter_changes returns:
177
194
        # (file_id, (path_in_source, path_in_target),
178
195
        #  changed_content, versioned, parent, name, kind,
179
196
        #  executable)
186
203
        self._wt.lock_read()
187
204
        self._basis_tree.lock_read()
188
205
        try:
189
 
            from diff import _iter_changes_to_status
 
206
            from diff import iter_changes_to_status
 
207
            saved_file_messages = self._saved_commit_messages_manager.get()[1]
190
208
            for (file_id, real_path, change_type, display_path
191
 
                ) in _iter_changes_to_status(self._basis_tree, self._wt):
 
209
                ) in iter_changes_to_status(self._basis_tree, self._wt):
192
210
                if self._selected and real_path != self._selected:
193
211
                    enabled = False
194
212
                else:
195
213
                    enabled = True
 
214
                try:
 
215
                    default_message = saved_file_messages[file_id]
 
216
                except KeyError:
 
217
                    default_message = ''
196
218
                item_iter = store.append([
197
219
                    file_id,
198
220
                    real_path.encode('UTF-8'),
199
221
                    enabled,
200
222
                    display_path.encode('UTF-8'),
201
223
                    change_type,
202
 
                    '', # Initial comment
 
224
                    default_message, # Initial comment
203
225
                    ])
204
226
                if self._selected and enabled:
205
227
                    initial_cursor = store.get_path(item_iter)
227
249
            return
228
250
        if have_dbus:
229
251
            bus = dbus.SystemBus()
230
 
            proxy_obj = bus.get_object('org.freedesktop.NetworkManager',
231
 
                                       '/org/freedesktop/NetworkManager')
 
252
            try:
 
253
                proxy_obj = bus.get_object('org.freedesktop.NetworkManager',
 
254
                                           '/org/freedesktop/NetworkManager')
 
255
            except dbus.DBusException:
 
256
                trace.mutter("networkmanager not available.")
 
257
                self._check_local.show()
 
258
                return
 
259
            
232
260
            dbus_iface = dbus.Interface(proxy_obj,
233
261
                                        'org.freedesktop.NetworkManager')
234
262
            try:
237
265
            except dbus.DBusException, e:
238
266
                # Silently drop errors. While DBus may be
239
267
                # available, NetworkManager doesn't necessarily have to be
240
 
                mutter("unable to get networkmanager state: %r" % e)
 
268
                trace.mutter("unable to get networkmanager state: %r" % e)
241
269
        self._check_local.show()
242
270
 
243
271
    def _fill_in_per_file_info(self):
251
279
            self._enable_per_file_commits = True
252
280
        if not self._enable_per_file_commits:
253
281
            self._file_message_expander.hide()
254
 
            self._global_message_label.set_markup(_('<b>Commit Message</b>'))
 
282
            self._global_message_label.set_markup(_i18n('<b>Commit Message</b>'))
255
283
 
256
284
    def _compute_delta(self):
257
285
        self._delta = self._wt.changes_from(self._basis_tree)
296
324
                            gtk.gdk.CONTROL_MASK, 0, self._on_accel_next)
297
325
        self.add_accel_group(group)
298
326
 
 
327
        # ignore the escape key (avoid closing the window)
 
328
        self.connect_object('close', self.emit_stop_by_name, 'close')
 
329
 
299
330
    def _construct_left_pane(self):
300
331
        self._left_pane_box = gtk.VBox(homogeneous=False, spacing=5)
301
332
        self._construct_file_list()
302
333
        self._construct_pending_list()
303
334
 
304
 
        self._check_local = gtk.CheckButton(_("_Only commit locally"),
 
335
        self._check_local = gtk.CheckButton(_i18n("_Only commit locally"),
305
336
                                            use_underline=True)
306
337
        self._left_pane_box.pack_end(self._check_local, False, False)
307
338
        self._check_local.set_active(False)
328
359
        self._hpane.pack2(self._right_pane_table, resize=True, shrink=True)
329
360
 
330
361
    def _construct_action_pane(self):
331
 
        self._button_commit = gtk.Button(_("Comm_it"), use_underline=True)
 
362
        self._button_cancel = gtk.Button(stock=gtk.STOCK_CANCEL)
 
363
        self._button_cancel.connect('clicked', self._on_cancel_clicked)
 
364
        self._button_cancel.show()
 
365
        self.action_area.pack_end(self._button_cancel)
 
366
        self._button_commit = gtk.Button(_i18n("Comm_it"), use_underline=True)
332
367
        self._button_commit.connect('clicked', self._on_commit_clicked)
333
368
        self._button_commit.set_flags(gtk.CAN_DEFAULT)
334
369
        self._button_commit.show()
354
389
 
355
390
    def _construct_file_list(self):
356
391
        self._files_box = gtk.VBox(homogeneous=False, spacing=0)
357
 
        file_label = gtk.Label(_('Files'))
 
392
        file_label = gtk.Label(_i18n('Files'))
358
393
        # file_label.show()
359
394
        self._files_box.pack_start(file_label, expand=False)
360
395
 
361
396
        self._commit_all_files_radio = gtk.RadioButton(
362
 
            None, _("Commit all changes"))
 
397
            None, _i18n("Commit all changes"))
363
398
        self._files_box.pack_start(self._commit_all_files_radio, expand=False)
364
399
        self._commit_all_files_radio.show()
365
400
        self._commit_all_files_radio.connect('toggled',
366
401
            self._toggle_commit_selection)
367
402
        self._commit_selected_radio = gtk.RadioButton(
368
 
            self._commit_all_files_radio, _("Only commit selected changes"))
 
403
            self._commit_all_files_radio, _i18n("Only commit selected changes"))
369
404
        self._files_box.pack_start(self._commit_selected_radio, expand=False)
370
405
        self._commit_selected_radio.show()
371
406
        self._commit_selected_radio.connect('toggled',
372
407
            self._toggle_commit_selection)
373
408
        if self._pending:
374
 
            self._commit_all_files_radio.set_label(_('Commit all changes*'))
 
409
            self._commit_all_files_radio.set_label(_i18n('Commit all changes*'))
375
410
            self._commit_all_files_radio.set_sensitive(False)
376
411
            self._commit_selected_radio.set_sensitive(False)
377
412
 
404
439
        crt.set_property('activatable', not bool(self._pending))
405
440
        crt.connect("toggled", self._toggle_commit, self._files_store)
406
441
        if self._pending:
407
 
            name = _('Commit*')
 
442
            name = _i18n('Commit*')
408
443
        else:
409
 
            name = _('Commit')
 
444
            name = _i18n('Commit')
410
445
        commit_col = gtk.TreeViewColumn(name, crt, active=2)
411
446
        commit_col.set_visible(False)
412
447
        self._treeview_files.append_column(commit_col)
413
 
        self._treeview_files.append_column(gtk.TreeViewColumn(_('Path'),
 
448
        self._treeview_files.append_column(gtk.TreeViewColumn(_i18n('Path'),
414
449
                                           gtk.CellRendererText(), text=3))
415
 
        self._treeview_files.append_column(gtk.TreeViewColumn(_('Type'),
 
450
        self._treeview_files.append_column(gtk.TreeViewColumn(_i18n('Type'),
416
451
                                           gtk.CellRendererText(), text=4))
417
452
        self._treeview_files.connect('cursor-changed',
418
453
                                     self._on_treeview_files_cursor_changed)
445
480
 
446
481
        pending_message = gtk.Label()
447
482
        pending_message.set_markup(
448
 
            _('<i>* Cannot select specific files when merging</i>'))
 
483
            _i18n('<i>* Cannot select specific files when merging</i>'))
449
484
        self._pending_box.pack_start(pending_message, expand=False, padding=5)
450
485
        pending_message.show()
451
486
 
452
 
        pending_label = gtk.Label(_('Pending Revisions'))
 
487
        pending_label = gtk.Label(_i18n('Pending Revisions'))
453
488
        self._pending_box.pack_start(pending_label, expand=False, padding=0)
454
489
        pending_label.show()
455
490
 
471
506
                                 )
472
507
        self._pending_store = liststore
473
508
        self._treeview_pending.set_model(liststore)
474
 
        self._treeview_pending.append_column(gtk.TreeViewColumn(_('Date'),
 
509
        self._treeview_pending.append_column(gtk.TreeViewColumn(_i18n('Date'),
475
510
                                             gtk.CellRendererText(), text=1))
476
 
        self._treeview_pending.append_column(gtk.TreeViewColumn(_('Committer'),
 
511
        self._treeview_pending.append_column(gtk.TreeViewColumn(_i18n('Committer'),
477
512
                                             gtk.CellRendererText(), text=2))
478
 
        self._treeview_pending.append_column(gtk.TreeViewColumn(_('Summary'),
 
513
        self._treeview_pending.append_column(gtk.TreeViewColumn(_i18n('Summary'),
479
514
                                             gtk.CellRendererText(), text=3))
480
515
 
481
516
    def _construct_diff_view(self):
485
520
        #       decide that we really don't ever want to display it, we should
486
521
        #       actually remove it, and other references to it, along with the
487
522
        #       tests that it is set properly.
488
 
        self._diff_label = gtk.Label(_('Diff for whole tree'))
 
523
        self._diff_label = gtk.Label(_i18n('Diff for whole tree'))
489
524
        self._diff_label.set_alignment(0, 0)
490
525
        self._right_pane_table.set_row_spacing(self._right_pane_table_row, 0)
491
526
        self._add_to_right_table(self._diff_label, 1, False)
509
544
        self._file_message_text_view.set_accepts_tab(False)
510
545
        self._file_message_text_view.show()
511
546
 
512
 
        self._file_message_expander = gtk.Expander(_('File commit message'))
 
547
        self._file_message_expander = gtk.Expander(_i18n('File commit message'))
513
548
        self._file_message_expander.set_expanded(True)
514
549
        self._file_message_expander.add(scroller)
515
550
        self._add_to_right_table(self._file_message_expander, 1, False)
516
551
        self._file_message_expander.show()
517
552
 
518
553
    def _construct_global_message(self):
519
 
        self._global_message_label = gtk.Label(_('Global Commit Message'))
520
 
        self._global_message_label.set_markup(_('<b>Global Commit Message</b>'))
 
554
        self._global_message_label = gtk.Label(_i18n('Global Commit Message'))
 
555
        self._global_message_label.set_markup(
 
556
            _i18n('<b>Global Commit Message</b>'))
521
557
        self._global_message_label.set_alignment(0, 0)
522
558
        self._right_pane_table.set_row_spacing(self._right_pane_table_row, 0)
523
559
        self._add_to_right_table(self._global_message_label, 1, False)
528
564
        scroller.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
529
565
 
530
566
        self._global_message_text_view = gtk.TextView()
 
567
        self._set_global_commit_message(self._saved_commit_messages_manager.get()[0])
531
568
        self._global_message_text_view.modify_font(pango.FontDescription("Monospace"))
532
569
        scroller.add(self._global_message_text_view)
533
570
        scroller.set_shadow_type(gtk.SHADOW_IN)
543
580
 
544
581
        if selection is not None:
545
582
            path, display_path = model.get(selection, 1, 3)
546
 
            self._diff_label.set_text(_('Diff for ') + display_path)
 
583
            self._diff_label.set_text(_i18n('Diff for ') + display_path)
547
584
            if path is None:
548
585
                self._diff_view.show_diff(None)
549
586
            else:
590
627
        text_buffer = self._file_message_text_view.get_buffer()
591
628
        file_id, display_path, message = self._files_store.get(selection, 0, 3, 5)
592
629
        if file_id is None: # Whole tree
593
 
            self._file_message_expander.set_label(_('File commit message'))
 
630
            self._file_message_expander.set_label(_i18n('File commit message'))
594
631
            self._file_message_expander.set_expanded(False)
595
632
            self._file_message_expander.set_sensitive(False)
596
633
            text_buffer.set_text('')
597
634
            self._last_selected_file = None
598
635
        else:
599
 
            self._file_message_expander.set_label(_('Commit message for ')
 
636
            self._file_message_expander.set_label(_i18n('Commit message for ')
600
637
                                                  + display_path)
601
638
            self._file_message_expander.set_expanded(True)
602
639
            self._file_message_expander.set_sensitive(True)
619
656
            if self._commit_all_changes or record[2]:# [2] checkbox
620
657
                file_id = record[0] # [0] file_id
621
658
                path = record[1]    # [1] real path
622
 
                file_message = record[5] # [5] commit message
 
659
                # [5] commit message
 
660
                file_message = _sanitize_and_decode_message(record[5])
623
661
                files.append(path.decode('UTF-8'))
624
662
                if self._enable_per_file_commits and file_message:
625
663
                    # All of this needs to be utf-8 information
 
664
                    file_message = file_message.encode('UTF-8')
626
665
                    file_info.append({'path':path, 'file_id':file_id,
627
666
                                     'message':file_message})
628
667
        file_info.sort(key=lambda x:(x['path'], x['file_id']))
632
671
            return files, []
633
672
 
634
673
    @show_bzr_error
 
674
    def _on_cancel_clicked(self, button):
 
675
        """ Cancel button clicked handler. """
 
676
        self._do_cancel()
 
677
 
 
678
    @show_bzr_error
 
679
    def _on_delete_window(self, source, event):
 
680
        """ Delete window handler. """
 
681
        self._do_cancel()
 
682
 
 
683
    def _do_cancel(self):
 
684
        """If requested, saves commit messages when cancelling gcommit; they are re-used by a next gcommit"""
 
685
        mgr = SavedCommitMessagesManager()
 
686
        self._saved_commit_messages_manager = mgr
 
687
        mgr.insert(self._get_global_commit_message(),
 
688
                   self._get_specific_files()[1])
 
689
        if mgr.is_not_empty(): # maybe worth saving
 
690
            response = self._question_dialog(
 
691
                _i18n('Commit cancelled'),
 
692
                _i18n('Do you want to save your commit messages ?'),
 
693
                parent=self)
 
694
            if response == gtk.RESPONSE_NO:
 
695
                 # save nothing and destroy old comments if any
 
696
                mgr = SavedCommitMessagesManager()
 
697
        mgr.save(self._wt, self._wt.branch)
 
698
        self.response(gtk.RESPONSE_CANCEL) # close window
 
699
 
 
700
    @show_bzr_error
635
701
    def _on_commit_clicked(self, button):
636
702
        """ Commit button clicked handler. """
637
703
        self._do_commit()
641
707
 
642
708
        if message == '':
643
709
            response = self._question_dialog(
644
 
                            _('Commit with an empty message?'),
645
 
                            _('You can describe your commit intent in the message.'))
 
710
                _i18n('Commit with an empty message?'),
 
711
                _i18n('You can describe your commit intent in the message.'),
 
712
                parent=self)
646
713
            if response == gtk.RESPONSE_NO:
647
714
                # Kindly give focus to message area
648
715
                self._global_message_text_view.grab_focus()
661
728
        #       files at this point.
662
729
        for path in self._wt.unknowns():
663
730
            response = self._question_dialog(
664
 
                _("Commit with unknowns?"),
665
 
                _("Unknown files exist in the working tree. Commit anyway?"))
 
731
                _i18n("Commit with unknowns?"),
 
732
                _i18n("Unknown files exist in the working tree. Commit anyway?"),
 
733
                parent=self)
 
734
                # Doesn't set a parent for the dialog..
666
735
            if response == gtk.RESPONSE_NO:
667
736
                return
668
737
            break
680
749
                       revprops=revprops)
681
750
        except errors.PointlessCommit:
682
751
            response = self._question_dialog(
683
 
                                _('Commit with no changes?'),
684
 
                                _('There are no changes in the working tree.'
685
 
                                  ' Do you want to commit anyway?'))
 
752
                _i18n('Commit with no changes?'),
 
753
                _i18n('There are no changes in the working tree.'
 
754
                      ' Do you want to commit anyway?'),
 
755
                parent=self)
686
756
            if response == gtk.RESPONSE_YES:
687
757
                rev_id = self._wt.commit(message,
688
758
                               allow_pointless=True,
691
761
                               specific_files=specific_files,
692
762
                               revprops=revprops)
693
763
        self.committed_revision_id = rev_id
 
764
        # destroy old comments if any
 
765
        SavedCommitMessagesManager().save(self._wt, self._wt.branch)
694
766
        self.response(gtk.RESPONSE_OK)
695
767
 
696
768
    def _get_global_commit_message(self):
697
769
        buf = self._global_message_text_view.get_buffer()
698
770
        start, end = buf.get_bounds()
699
 
        return buf.get_text(start, end).decode('utf-8')
 
771
        text = buf.get_text(start, end)
 
772
        return _sanitize_and_decode_message(text)
700
773
 
701
774
    def _set_global_commit_message(self, message):
702
775
        """Just a helper for the test suite."""
723
796
                                       show_offset=False)
724
797
        rev_dict['revision_id'] = rev.revision_id
725
798
        return rev_dict
 
799
 
 
800
 
 
801
class SavedCommitMessagesManager:
 
802
    """Save glogal and per-file commit messages.
 
803
 
 
804
    Saves global commit message and utf-8 file_id->message dictionary
 
805
    of per-file commit messages on disk. Re-reads them later for re-using.
 
806
    """
 
807
 
 
808
    def __init__(self, tree=None, branch=None):
 
809
        """If branch is None, builds empty messages, otherwise reads them
 
810
        from branch's disk storage. 'tree' argument is for the future."""
 
811
        if branch is None:
 
812
            self.global_message = u''
 
813
            self.file_messages = {}
 
814
        else:
 
815
            config = branch.get_config()._get_branch_data_config()
 
816
            self.global_message = config.get_user_option(
 
817
                'gtk_global_commit_message')
 
818
            if self.global_message is None:
 
819
                self.global_message = u''
 
820
            file_messages = config.get_user_option('gtk_file_commit_messages')
 
821
            if file_messages: # unicode and B-encoded:
 
822
                self.file_messages = bencode.bdecode(
 
823
                    file_messages.encode('UTF-8'))
 
824
            else:
 
825
                self.file_messages = {}
 
826
 
 
827
    def get(self):
 
828
        return self.global_message, self.file_messages
 
829
 
 
830
    def is_not_empty(self):
 
831
        return bool(self.global_message or self.file_messages)
 
832
 
 
833
    def insert(self, global_message, file_info):
 
834
        """Formats per-file commit messages (list of dictionaries, one per file)
 
835
        into one utf-8 file_id->message dictionary and merges this with
 
836
        previously existing dictionary. Merges global commit message too."""
 
837
        file_messages = {}
 
838
        for fi in file_info:
 
839
            file_message = fi['message']
 
840
            if file_message:
 
841
                file_messages[fi['file_id']] = file_message # utf-8 strings
 
842
        for k,v in file_messages.iteritems():
 
843
            try:
 
844
                self.file_messages[k] = v + '\n******\n' + self.file_messages[k]
 
845
            except KeyError:
 
846
                self.file_messages[k] = v
 
847
        if self.global_message:
 
848
            self.global_message = global_message + '\n******\n' \
 
849
                + self.global_message
 
850
        else:
 
851
            self.global_message = global_message
 
852
 
 
853
    def save(self, tree, branch):
 
854
        # We store in branch's config, which can be a problem if two gcommit
 
855
        # are done in two checkouts of one single branch (comments overwrite
 
856
        # each other). Ideally should be in working tree. But uncommit does
 
857
        # not always have a working tree, though it always has a branch.
 
858
        # 'tree' argument is for the future
 
859
        config = branch.get_config()
 
860
        # should it be named "gtk_" or some more neutral name ("gui_" ?) to
 
861
        # be compatible with qbzr in the future?
 
862
        config.set_user_option('gtk_global_commit_message', self.global_message)
 
863
        # bencode() does not know unicode objects but set_user_option()
 
864
        # requires one:
 
865
        config.set_user_option(
 
866
            'gtk_file_commit_messages',
 
867
            bencode.bencode(self.file_messages).decode('UTF-8'))
 
868
 
 
869
 
 
870
def save_commit_messages(local, master, old_revno, old_revid,
 
871
                         new_revno, new_revid):
 
872
    b = local
 
873
    if b is None:
 
874
        b = master
 
875
    mgr = SavedCommitMessagesManager(None, b)
 
876
    revid_iterator = b.repository.iter_reverse_revision_history(old_revid)
 
877
    cur_revno = old_revno
 
878
    new_revision_id = old_revid
 
879
    graph = b.repository.get_graph()
 
880
    for rev_id in revid_iterator:
 
881
        if cur_revno == new_revno:
 
882
            break
 
883
        cur_revno -= 1
 
884
        rev = b.repository.get_revision(rev_id)
 
885
        file_info = rev.properties.get('file-info', None)
 
886
        if file_info is None:
 
887
            file_info = {}
 
888
        else:
 
889
            file_info = bencode.bdecode(file_info.encode('UTF-8'))
 
890
        global_message = osutils.safe_unicode(rev.message)
 
891
        # Concatenate comment of the uncommitted revision
 
892
        mgr.insert(global_message, file_info)
 
893
 
 
894
        parents = graph.get_parent_map([rev_id]).get(rev_id, None)
 
895
        if not parents:
 
896
            continue
 
897
    mgr.save(None, b)