/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: Aaron Bentley
  • Date: 2007-01-17 06:42:55 UTC
  • mto: This revision was merged to the branch mainline in revision 129.
  • Revision ID: aaron.bentley@utoronto.ca-20070117064255-x4gznz5e0lyjq3gk
Remove usused span selector

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <szilveszter.farkas@gmail.com>
2
 
 
 
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
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
 
 
19
17
try:
20
18
    import pygtk
21
19
    pygtk.require("2.0")
22
20
except:
23
21
    pass
24
 
try:
25
 
    import gtk
26
 
    import gtk.glade
27
 
except:
28
 
    sys.exit(1)
29
 
 
30
 
import olive.backend.commit as commit
31
 
import olive.backend.errors as errors
32
 
 
33
 
class OliveCommit:
 
22
 
 
23
import gtk
 
24
import gtk.glade
 
25
import gobject
 
26
import pango
 
27
 
 
28
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:
34
36
    """ Display Commit dialog and perform the needed actions. """
35
 
    def __init__(self, gladefile, comm):
36
 
        """ Initialize the Commit dialog. """
37
 
        self.gladefile = gladefile
38
 
        self.glade = gtk.glade.XML(self.gladefile, 'window_commit')
39
 
        
40
 
        self.comm = comm
41
 
        
 
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')
 
45
        
 
46
        self.wt = wt
 
47
        self.wtpath = wtpath
 
48
        self.notbranch = notbranch
 
49
 
 
50
        # Get some important widgets
42
51
        self.window = self.glade.get_widget('window_commit')
 
52
        self.checkbutton_local = self.glade.get_widget('checkbutton_commit_local')
 
53
        self.textview = self.glade.get_widget('textview_commit')
 
54
        self.file_expander = self.glade.get_widget('expander_commit_select')
 
55
        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:
 
61
            return
 
62
        
 
63
        # Set the delta
 
64
        self.old_tree = self.wt.branch.repository.revision_tree(self.wt.branch.last_revision())
 
65
        self.delta = self.wt.changes_from(self.old_tree)
 
66
        
 
67
        # Get pending merges
 
68
        self.pending = self._pending_merges(self.wt)
43
69
        
44
70
        # Dictionary for signal_autoconnect
45
71
        dic = { "on_button_commit_commit_clicked": self.commit,
46
72
                "on_button_commit_cancel_clicked": self.close }
47
 
        
 
73
 
48
74
        # Connect the signals to the handlers
49
75
        self.glade.signal_autoconnect(dic)
 
76
        
 
77
        # Create the file list
 
78
        self._create_file_view()
 
79
        # Create the pending merges
 
80
        self._create_pending_merges()
50
81
    
51
82
    def display(self):
52
 
        """ Display the Push dialog. """
53
 
        self.window.show_all()
54
 
    
 
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
 
91
        if self.notbranch:
 
92
            error_dialog(_('Directory is not a branch'),
 
93
                         _('You can perform this action only in a branch.'))
 
94
            self.close()
 
95
            return False
 
96
        else:
 
97
            if self.wt.branch.get_bound_location() is not None:
 
98
                # we have a checkout, so the local commit checkbox must appear
 
99
                self.checkbutton_local.show()
 
100
            
 
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
            self.textview.modify_font(pango.FontDescription("Monospace"))
 
110
            self.window.show()
 
111
            return True
 
112
    
 
113
    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
 
118
        self.file_view.set_model(self.file_store)
 
119
        crt = gtk.CellRendererToggle()
 
120
        crt.set_property("activatable", True)
 
121
        crt.connect("toggled", self._toggle_commit, self.file_store)
 
122
        self.file_view.append_column(gtk.TreeViewColumn(_('Commit'),
 
123
                                     crt, active=0))
 
124
        self.file_view.append_column(gtk.TreeViewColumn(_('Path'),
 
125
                                     gtk.CellRendererText(), text=1))
 
126
        self.file_view.append_column(gtk.TreeViewColumn(_('Type'),
 
127
                                     gtk.CellRendererText(), text=2))
 
128
 
 
129
        for path, id, kind in self.delta.added:
 
130
            marker = osutils.kind_marker(kind)
 
131
            self.file_store.append([ True, path+marker, _('added'), path ])
 
132
 
 
133
        for path, id, kind in self.delta.removed:
 
134
            marker = osutils.kind_marker(kind)
 
135
            self.file_store.append([ True, path+marker, _('removed'), path ])
 
136
 
 
137
        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
                                   ])
 
148
 
 
149
        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'] ])
 
179
    
 
180
    def _get_specific_files(self):
 
181
        ret = []
 
182
        it = self.file_store.get_iter_first()
 
183
        while it:
 
184
            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))
 
187
            it = self.file_store.iter_next(it)
 
188
 
 
189
        return ret
 
190
    
 
191
    def _toggle_commit(self, cell, path, model):
 
192
        model[path][0] = not model[path][0]
 
193
        return
 
194
    
 
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
 
55
259
    def commit(self, widget):
56
 
        from dialog import OliveDialog
57
 
        dialog = OliveDialog(self.gladefile)
58
 
        
59
 
        textview = self.glade.get_widget('textview_commit')
60
 
        textbuffer = textview.get_buffer()
 
260
        textbuffer = self.textview.get_buffer()
61
261
        start, end = textbuffer.get_bounds()
62
 
        message = textbuffer.get_text(start, end)
 
262
        message = textbuffer.get_text(start, end).decode('utf-8')
63
263
        
64
 
        checkbutton_local = self.glade.get_widget('checkbutton_commit_local')
65
264
        checkbutton_strict = self.glade.get_widget('checkbutton_commit_strict')
66
265
        checkbutton_force = self.glade.get_widget('checkbutton_commit_force')
67
266
        
 
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
 
68
281
        try:
69
 
            commit.commit([self.comm.get_path()], message, None,
70
 
                          checkbutton_force.get_active(),
71
 
                          checkbutton_strict.get_active(),
72
 
                          checkbutton_local.get_active())
 
282
            self.wt.commit(message,
 
283
                           allow_pointless=checkbutton_force.get_active(),
 
284
                           strict=checkbutton_strict.get_active(),
 
285
                           local=self.checkbutton_local.get_active(),
 
286
                           specific_files=specific_files)
73
287
        except errors.NotBranchError:
74
 
            dialog.error_dialog('Directory is not a branch.')
 
288
            error_dialog(_('Directory is not a branch'),
 
289
                         _('You can perform this action only in a branch.'))
75
290
            return
76
291
        except errors.LocalRequiresBoundBranch:
77
 
            dialog.error_dialog('Local commit requires a bound branch.')
78
 
            return
79
 
        except errors.EmptyMessageError:
80
 
            dialog.error_dialog('Commit message is empty.')
81
 
            return
82
 
        except errors.NoChangesToCommitError:
83
 
            dialog.error_dialog('No changes to commit. Try force commit.')
84
 
            return
85
 
        except errors.ConflictsInTreeError:
86
 
            dialog.error_dialog('Conflicts in tree. Please resolve them first.')
87
 
            return
88
 
        except errors.StrictCommitError:
89
 
            dialog.error_dialog('Strict commit failed. There are unknown files.')
 
292
            error_dialog(_('Directory is not a checkout'),
 
293
                         _('You can perform local commit only on checkouts.'))
 
294
            return
 
295
        except errors.PointlessCommit:
 
296
            error_dialog(_('No changes to commit'),
 
297
                         _('Try force commit if you want to commit anyway.'))
 
298
            return
 
299
        except errors.ConflictsInTree:
 
300
            error_dialog(_('Conflicts in tree'),
 
301
                         _('You need to resolve the conflicts before committing.'))
 
302
            return
 
303
        except errors.StrictCommitFailed:
 
304
            error_dialog(_('Strict commit failed'),
 
305
                         _('There are unknown files in the working tree.\nPlease add or delete them.'))
90
306
            return
91
307
        except errors.BoundBranchOutOfDate, errmsg:
92
 
            dialog.error_dialog('Bound branch is out of date: %s' % errmsg)
93
 
            return
94
 
        except:
95
 
            raise
96
 
        
 
308
            error_dialog(_('Bound branch is out of date'),
 
309
                         _('%s') % errmsg)
 
310
            return
 
311
        except errors.BzrError, msg:
 
312
            error_dialog(_('Unknown bzr error'), str(msg))
 
313
            return
 
314
        except Exception, msg:
 
315
            error_dialog(_('Unknown error'), str(msg))
 
316
            return
 
317
 
97
318
        self.close()
98
 
        self.comm.refresh_right()
99
 
        
 
319
 
100
320
    def close(self, widget=None):
101
321
        self.window.destroy()