/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 olive/commit.py

  • Committer: Jelmer Vernooij
  • Date: 2006-09-30 10:21:43 UTC
  • Revision ID: jelmer@samba.org-20060930102143-c0ef64d6ca860c21
Merge some files from Olive and bzr-gtk.

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 sys
 
18
 
17
19
try:
18
20
    import pygtk
19
21
    pygtk.require("2.0")
20
22
except:
21
23
    pass
22
 
 
23
24
import gtk
24
25
import gtk.glade
25
26
import gobject
26
27
import pango
27
28
 
 
29
from bzrlib import version_info
 
30
 
28
31
import bzrlib.errors as errors
29
 
from bzrlib import osutils
30
 
 
31
 
from dialog import error_dialog, question_dialog
32
 
from guifiles import GLADEFILENAME
33
 
 
34
 
 
35
 
class CommitDialog:
 
32
from bzrlib.workingtree import WorkingTree
 
33
 
 
34
from dialog import error_dialog
 
35
from olive import gladefile
 
36
 
 
37
class OliveCommit:
36
38
    """ Display Commit dialog and perform the needed actions. """
37
 
    def __init__(self, wt, wtpath, notbranch):
38
 
        """ Initialize the Commit dialog.
39
 
        :param  wt:         bzr working tree object
40
 
        :param  wtpath:     path to working tree root
41
 
        :param  notbranch:  flag that path is not a brach
42
 
        :type   notbranch:  bool
43
 
        """
44
 
        self.glade = gtk.glade.XML(GLADEFILENAME, 'window_commit', 'olive-gtk')
 
39
    def __init__(self, wt, wtpath):
 
40
        """ Initialize the Commit dialog. """
 
41
        self.glade = gtk.glade.XML(gladefile, 'window_commit', 'olive-gtk')
45
42
        
46
43
        self.wt = wt
47
44
        self.wtpath = wtpath
48
 
        self.notbranch = notbranch
49
45
 
50
46
        # Get some important widgets
51
47
        self.window = self.glade.get_widget('window_commit')
52
48
        self.checkbutton_local = self.glade.get_widget('checkbutton_commit_local')
53
49
        self.textview = self.glade.get_widget('textview_commit')
54
 
        self.file_expander = self.glade.get_widget('expander_commit_select')
55
50
        self.file_view = self.glade.get_widget('treeview_commit_select')
56
 
        self.pending_expander = self.glade.get_widget('expander_commit_pending')
57
 
        self.pending_label = self.glade.get_widget('label_commit_pending')
58
 
        self.pending_view = self.glade.get_widget('treeview_commit_pending')
59
 
 
60
 
        if wt is None or notbranch:
 
51
 
 
52
        file_id = self.wt.path2id(wtpath)
 
53
 
 
54
        self.notbranch = False
 
55
        if file_id is None:
 
56
            self.notbranch = True
61
57
            return
62
58
        
63
59
        # Set the delta
64
60
        self.old_tree = self.wt.branch.repository.revision_tree(self.wt.branch.last_revision())
65
61
        self.delta = self.wt.changes_from(self.old_tree)
66
62
        
67
 
        # Get pending merges
68
 
        self.pending = self._pending_merges(self.wt)
69
 
        
70
63
        # Dictionary for signal_autoconnect
71
64
        dic = { "on_button_commit_commit_clicked": self.commit,
72
65
                "on_button_commit_cancel_clicked": self.close }
73
 
 
 
66
        
74
67
        # Connect the signals to the handlers
75
68
        self.glade.signal_autoconnect(dic)
76
69
        
77
70
        # Create the file list
78
71
        self._create_file_view()
79
 
        # Create the pending merges
80
 
        self._create_pending_merges()
81
72
    
82
73
    def display(self):
83
 
        """ Display the Push dialog.
84
 
        @return:    True if dialog is shown.
85
 
        """
86
 
        if self.wt is None and not self.notbranch:
87
 
            error_dialog(_('Directory does not have a working tree'),
88
 
                         _('Operation aborted.'))
89
 
            self.close()
90
 
            return False
 
74
        """ Display the Push dialog. """
91
75
        if self.notbranch:
92
76
            error_dialog(_('Directory is not a branch'),
93
 
                         _('You can perform this action only in a branch.'))
 
77
                                     _('You can perform this action only in a branch.'))
94
78
            self.close()
95
 
            return False
96
79
        else:
97
80
            if self.wt.branch.get_bound_location() is not None:
98
81
                # we have a checkout, so the local commit checkbox must appear
99
82
                self.checkbutton_local.show()
100
83
            
101
 
            if self.pending:
102
 
                # There are pending merges, file selection not supported
103
 
                self.file_expander.set_expanded(False)
104
 
                self.file_view.set_sensitive(False)
105
 
            else:
106
 
                # No pending merges
107
 
                self.pending_expander.hide()
108
 
            
109
84
            self.textview.modify_font(pango.FontDescription("Monospace"))
110
85
            self.window.show()
111
 
            return True
 
86
            
112
87
    
113
88
    def _create_file_view(self):
114
 
        self.file_store = gtk.ListStore(gobject.TYPE_BOOLEAN,   # [0] checkbox
115
 
                                        gobject.TYPE_STRING,    # [1] path to display
116
 
                                        gobject.TYPE_STRING,    # [2] changes type
117
 
                                        gobject.TYPE_STRING)    # [3] real path
 
89
        self.file_store = gtk.ListStore(gobject.TYPE_BOOLEAN,
 
90
                                        gobject.TYPE_STRING,
 
91
                                        gobject.TYPE_STRING)
118
92
        self.file_view.set_model(self.file_store)
119
93
        crt = gtk.CellRendererToggle()
120
94
        crt.set_property("activatable", True)
127
101
                                     gtk.CellRendererText(), text=2))
128
102
 
129
103
        for path, id, kind in self.delta.added:
130
 
            marker = osutils.kind_marker(kind)
131
 
            self.file_store.append([ True, path+marker, _('added'), path ])
 
104
            self.file_store.append([ True, path, _('added') ])
132
105
 
133
106
        for path, id, kind in self.delta.removed:
134
 
            marker = osutils.kind_marker(kind)
135
 
            self.file_store.append([ True, path+marker, _('removed'), path ])
 
107
            self.file_store.append([ True, path, _('removed') ])
136
108
 
137
109
        for oldpath, newpath, id, kind, text_modified, meta_modified in self.delta.renamed:
138
 
            marker = osutils.kind_marker(kind)
139
 
            if text_modified or meta_modified:
140
 
                changes = _('renamed and modified')
141
 
            else:
142
 
                changes = _('renamed')
143
 
            self.file_store.append([ True,
144
 
                                     oldpath+marker + '  =>  ' + newpath+marker,
145
 
                                     changes,
146
 
                                     newpath
147
 
                                   ])
 
110
            self.file_store.append([ True, oldpath, _('renamed') ])
148
111
 
149
112
        for path, id, kind, text_modified, meta_modified in self.delta.modified:
150
 
            marker = osutils.kind_marker(kind)
151
 
            self.file_store.append([ True, path+marker, _('modified'), path ])
152
 
    
153
 
    def _create_pending_merges(self):
154
 
        if not self.pending:
155
 
            # hide unused pending merge part
156
 
            scrolled_window = self.glade.get_widget('scrolledwindow_commit_pending')
157
 
            parent = scrolled_window.get_parent()
158
 
            parent.remove(scrolled_window)
159
 
            parent = self.pending_label.get_parent()
160
 
            parent.remove(self.pending_label)
161
 
            return
162
 
        
163
 
        liststore = gtk.ListStore(gobject.TYPE_STRING,
164
 
                                  gobject.TYPE_STRING,
165
 
                                  gobject.TYPE_STRING)
166
 
        self.pending_view.set_model(liststore)
167
 
        
168
 
        self.pending_view.append_column(gtk.TreeViewColumn(_('Date'),
169
 
                                        gtk.CellRendererText(), text=0))
170
 
        self.pending_view.append_column(gtk.TreeViewColumn(_('Committer'),
171
 
                                        gtk.CellRendererText(), text=1))
172
 
        self.pending_view.append_column(gtk.TreeViewColumn(_('Summary'),
173
 
                                        gtk.CellRendererText(), text=2))
174
 
        
175
 
        for item in self.pending:
176
 
            liststore.append([ item['date'],
177
 
                               item['committer'],
178
 
                               item['summary'] ])
 
113
            self.file_store.append([ True, path, _('modified') ])
179
114
    
180
115
    def _get_specific_files(self):
181
116
        ret = []
182
117
        it = self.file_store.get_iter_first()
183
118
        while it:
184
119
            if self.file_store.get_value(it, 0):
185
 
                # get real path from hidden column 3
186
 
                ret.append(self.file_store.get_value(it, 3))
 
120
                ret.append(self.file_store.get_value(it, 1))
187
121
            it = self.file_store.iter_next(it)
188
122
 
189
123
        return ret
192
126
        model[path][0] = not model[path][0]
193
127
        return
194
128
    
195
 
    def _pending_merges(self, wt):
196
 
        """ Return a list of pending merges or None if there are none of them. """
197
 
        parents = wt.get_parent_ids()
198
 
        if len(parents) < 2:
199
 
            return None
200
 
        
201
 
        import re
202
 
        from bzrlib.osutils import format_date
203
 
        
204
 
        pending = parents[1:]
205
 
        branch = wt.branch
206
 
        last_revision = parents[0]
207
 
        
208
 
        if last_revision is not None:
209
 
            try:
210
 
                ignore = set(branch.repository.get_ancestry(last_revision))
211
 
            except errors.NoSuchRevision:
212
 
                # the last revision is a ghost : assume everything is new 
213
 
                # except for it
214
 
                ignore = set([None, last_revision])
215
 
        else:
216
 
            ignore = set([None])
217
 
        
218
 
        pm = []
219
 
        for merge in pending:
220
 
            ignore.add(merge)
221
 
            try:
222
 
                m_revision = branch.repository.get_revision(merge)
223
 
                
224
 
                rev = {}
225
 
                rev['committer'] = re.sub('<.*@.*>', '', m_revision.committer).strip(' ')
226
 
                rev['summary'] = m_revision.get_summary()
227
 
                rev['date'] = format_date(m_revision.timestamp,
228
 
                                          m_revision.timezone or 0, 
229
 
                                          'original', date_fmt="%Y-%m-%d",
230
 
                                          show_offset=False)
231
 
                
232
 
                pm.append(rev)
233
 
                
234
 
                inner_merges = branch.repository.get_ancestry(merge)
235
 
                assert inner_merges[0] is None
236
 
                inner_merges.pop(0)
237
 
                inner_merges.reverse()
238
 
                for mmerge in inner_merges:
239
 
                    if mmerge in ignore:
240
 
                        continue
241
 
                    mm_revision = branch.repository.get_revision(mmerge)
242
 
                    
243
 
                    rev = {}
244
 
                    rev['committer'] = re.sub('<.*@.*>', '', mm_revision.committer).strip(' ')
245
 
                    rev['summary'] = mm_revision.get_summary()
246
 
                    rev['date'] = format_date(mm_revision.timestamp,
247
 
                                              mm_revision.timezone or 0, 
248
 
                                              'original', date_fmt="%Y-%m-%d",
249
 
                                              show_offset=False)
250
 
                
251
 
                    pm.append(rev)
252
 
                    
253
 
                    ignore.add(mmerge)
254
 
            except errors.NoSuchRevision:
255
 
                print "DEBUG: NoSuchRevision:", merge
256
 
        
257
 
        return pm
258
 
 
259
129
    def commit(self, widget):
260
130
        textbuffer = self.textview.get_buffer()
261
131
        start, end = textbuffer.get_bounds()
262
 
        message = textbuffer.get_text(start, end).decode('utf-8')
 
132
        message = textbuffer.get_text(start, end)
263
133
        
264
134
        checkbutton_strict = self.glade.get_widget('checkbutton_commit_strict')
265
135
        checkbutton_force = self.glade.get_widget('checkbutton_commit_force')
266
136
        
267
 
        if not self.pending:
268
 
            specific_files = self._get_specific_files()
269
 
        else:
270
 
            specific_files = None
271
 
 
272
 
        if message == '':
273
 
            response = question_dialog('Commit with an empty message ?',
274
 
                                       'You can describe your commit intent'
275
 
                                       +' in the message')
276
 
            if response == gtk.RESPONSE_NO:
277
 
                # Kindly give focus to message area
278
 
                self.textview.grab_focus()
279
 
                return
280
 
 
 
137
        specific_files = self._get_specific_files()
 
138
        
281
139
        try:
282
 
            self.wt.commit(message,
 
140
            self.wt.commit(message, 
283
141
                           allow_pointless=checkbutton_force.get_active(),
284
142
                           strict=checkbutton_strict.get_active(),
285
143
                           local=self.checkbutton_local.get_active(),
286
144
                           specific_files=specific_files)
287
145
        except errors.NotBranchError:
288
146
            error_dialog(_('Directory is not a branch'),
289
 
                         _('You can perform this action only in a branch.'))
 
147
                                     _('You can perform this action only in a branch.'))
290
148
            return
291
149
        except errors.LocalRequiresBoundBranch:
292
150
            error_dialog(_('Directory is not a checkout'),
293
 
                         _('You can perform local commit only on checkouts.'))
 
151
                                     _('You can perform local commit only on checkouts.'))
294
152
            return
295
153
        except errors.PointlessCommit:
296
154
            error_dialog(_('No changes to commit'),
297
 
                         _('Try force commit if you want to commit anyway.'))
 
155
                                     _('Try force commit if you want to commit anyway.'))
298
156
            return
299
157
        except errors.ConflictsInTree:
300
158
            error_dialog(_('Conflicts in tree'),
301
 
                         _('You need to resolve the conflicts before committing.'))
 
159
                                     _('You need to resolve the conflicts before committing.'))
302
160
            return
303
161
        except errors.StrictCommitFailed:
304
162
            error_dialog(_('Strict commit failed'),
305
 
                         _('There are unknown files in the working tree.\nPlease add or delete them.'))
 
163
                                     _('There are unknown files in the working tree.\nPlease add or delete them.'))
306
164
            return
307
165
        except errors.BoundBranchOutOfDate, errmsg:
308
166
            error_dialog(_('Bound branch is out of date'),
309
 
                         _('%s') % errmsg)
 
167
                                     _('%s') % errmsg)
310
168
            return
311
169
        except errors.BzrError, msg:
312
170
            error_dialog(_('Unknown bzr error'), str(msg))
314
172
        except Exception, msg:
315
173
            error_dialog(_('Unknown error'), str(msg))
316
174
            return
317
 
 
 
175
        
318
176
        self.close()
319
 
 
 
177
        
320
178
    def close(self, widget=None):
321
179
        self.window.destroy()