/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
 
    import gobject
28
 
except:
29
 
    sys.exit(1)
30
 
 
31
 
from bzrlib.delta import compare_trees
 
22
 
 
23
import gtk
 
24
import gtk.glade
 
25
import gobject
 
26
import pango
 
27
 
32
28
import bzrlib.errors as errors
33
 
from bzrlib.workingtree import WorkingTree
34
 
 
35
 
from dialog import OliveDialog
36
 
 
37
 
class OliveCommit:
 
29
from bzrlib import osutils
 
30
 
 
31
from dialog import error_dialog, question_dialog
 
32
from guifiles import GLADEFILENAME
 
33
 
 
34
 
 
35
class CommitDialog:
38
36
    """ Display Commit dialog and perform the needed actions. """
39
 
    def __init__(self, gladefile, comm):
40
 
        """ Initialize the Commit dialog. """
41
 
        import bzrlib
42
 
        
43
 
        self.gladefile = gladefile
44
 
        self.glade = gtk.glade.XML(self.gladefile, 'window_commit')
45
 
        
46
 
        self.comm = comm
47
 
        
48
 
        self.dialog = OliveDialog(self.gladefile)
49
 
        
50
 
        # Check if current location is a branch
51
 
        try:
52
 
            (self.wt, path) = WorkingTree.open_containing(self.comm.get_path())
53
 
            branch = self.wt.branch
54
 
        except errors.NotBranchError:
55
 
            self.notbranch = True
56
 
            return
57
 
        except:
58
 
            raise
59
 
 
60
 
        file_id = self.wt.path2id(path)
61
 
 
62
 
        self.notbranch = False
63
 
        if file_id is None:
64
 
            self.notbranch = True
 
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
 
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:
65
61
            return
66
62
        
67
63
        # Set the delta
68
64
        self.old_tree = self.wt.branch.repository.revision_tree(self.wt.branch.last_revision())
69
 
        if bzrlib.version_info[1] < 9:
70
 
            self.delta = compare_trees(self.old_tree, self.wt)
71
 
        else:
72
 
            self.delta = self.wt.changes_from(self.old_tree)
 
65
        self.delta = self.wt.changes_from(self.old_tree)
73
66
        
74
 
        # Get the Commit dialog widget
75
 
        self.window = self.glade.get_widget('window_commit')
 
67
        # Get pending merges
 
68
        self.pending = self._pending_merges(self.wt)
76
69
        
77
70
        # Dictionary for signal_autoconnect
78
71
        dic = { "on_button_commit_commit_clicked": self.commit,
79
72
                "on_button_commit_cancel_clicked": self.close }
80
 
        
 
73
 
81
74
        # Connect the signals to the handlers
82
75
        self.glade.signal_autoconnect(dic)
83
76
        
84
77
        # Create the file list
85
78
        self._create_file_view()
86
 
        
87
 
        # Some additional widgets
88
 
        self.checkbutton_local = self.glade.get_widget('checkbutton_commit_local')
 
79
        # Create the pending merges
 
80
        self._create_pending_merges()
89
81
    
90
82
    def display(self):
91
 
        """ Display the Push dialog. """
 
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
92
91
        if self.notbranch:
93
 
            self.dialog.error_dialog('Directory is not a branch.')
 
92
            error_dialog(_('Directory is not a branch'),
 
93
                         _('You can perform this action only in a branch.'))
 
94
            self.close()
 
95
            return False
94
96
        else:
95
 
            from olive.backend.info import is_checkout
96
 
            if is_checkout(self.comm.get_path()):
 
97
            if self.wt.branch.get_bound_location() is not None:
97
98
                # we have a checkout, so the local commit checkbox must appear
98
99
                self.checkbutton_local.show()
99
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"))
100
110
            self.window.show()
101
 
            
 
111
            return True
102
112
    
103
 
    # This code is from Jelmer Vernooij's bzr-gtk branch
104
113
    def _create_file_view(self):
105
 
        self.file_store = gtk.ListStore(gobject.TYPE_BOOLEAN,
106
 
                                        gobject.TYPE_STRING,
107
 
                                        gobject.TYPE_STRING)
108
 
        self.file_view = self.glade.get_widget('treeview_commit_select')
 
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
109
118
        self.file_view.set_model(self.file_store)
110
119
        crt = gtk.CellRendererToggle()
111
120
        crt.set_property("activatable", True)
112
121
        crt.connect("toggled", self._toggle_commit, self.file_store)
113
 
        self.file_view.append_column(gtk.TreeViewColumn("Commit",
 
122
        self.file_view.append_column(gtk.TreeViewColumn(_('Commit'),
114
123
                                     crt, active=0))
115
 
        self.file_view.append_column(gtk.TreeViewColumn("Path",
 
124
        self.file_view.append_column(gtk.TreeViewColumn(_('Path'),
116
125
                                     gtk.CellRendererText(), text=1))
117
 
        self.file_view.append_column(gtk.TreeViewColumn("Type",
 
126
        self.file_view.append_column(gtk.TreeViewColumn(_('Type'),
118
127
                                     gtk.CellRendererText(), text=2))
119
128
 
120
 
        for path, _, _ in self.delta.added:
121
 
            self.file_store.append([ True, path, "added" ])
122
 
 
123
 
        for path, _, _ in self.delta.removed:
124
 
            self.file_store.append([ True, path, "removed" ])
125
 
 
126
 
        for oldpath, _, _, _, _, _ in self.delta.renamed:
127
 
            self.file_store.append([ True, oldpath, "renamed"])
128
 
 
129
 
        for path, _, _, _, _ in self.delta.modified:
130
 
            self.file_store.append([ True, path, "modified"])
 
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'] ])
131
179
    
132
180
    def _get_specific_files(self):
133
181
        ret = []
134
182
        it = self.file_store.get_iter_first()
135
183
        while it:
136
184
            if self.file_store.get_value(it, 0):
137
 
                ret.append(self.file_store.get_value(it, 1))
 
185
                # get real path from hidden column 3
 
186
                ret.append(self.file_store.get_value(it, 3))
138
187
            it = self.file_store.iter_next(it)
139
188
 
140
189
        return ret
141
 
    # end of bzr-gtk code
142
190
    
143
191
    def _toggle_commit(self, cell, path, model):
144
192
        model[path][0] = not model[path][0]
145
193
        return
146
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
 
147
259
    def commit(self, widget):
148
 
        textview = self.glade.get_widget('textview_commit')
149
 
        textbuffer = textview.get_buffer()
 
260
        textbuffer = self.textview.get_buffer()
150
261
        start, end = textbuffer.get_bounds()
151
 
        message = textbuffer.get_text(start, end)
 
262
        message = textbuffer.get_text(start, end).decode('utf-8')
152
263
        
153
264
        checkbutton_strict = self.glade.get_widget('checkbutton_commit_strict')
154
265
        checkbutton_force = self.glade.get_widget('checkbutton_commit_force')
155
266
        
156
 
        specific_files = self._get_specific_files()
157
 
        
158
 
        self.comm.set_busy(self.window)
159
 
        # merged from Jelmer Vernooij's olive integration branch
 
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
 
160
281
        try:
161
 
            self.wt.commit(message, 
 
282
            self.wt.commit(message,
162
283
                           allow_pointless=checkbutton_force.get_active(),
163
284
                           strict=checkbutton_strict.get_active(),
164
285
                           local=self.checkbutton_local.get_active(),
165
286
                           specific_files=specific_files)
166
287
        except errors.NotBranchError:
167
 
            self.dialog.error_dialog('Directory is not a branch.')
168
 
            self.comm.set_busy(self.window, False)
 
288
            error_dialog(_('Directory is not a branch'),
 
289
                         _('You can perform this action only in a branch.'))
169
290
            return
170
291
        except errors.LocalRequiresBoundBranch:
171
 
            self.dialog.error_dialog('Local commit requires a bound branch.')
172
 
            self.comm.set_busy(self.window, False)
 
292
            error_dialog(_('Directory is not a checkout'),
 
293
                         _('You can perform local commit only on checkouts.'))
173
294
            return
174
295
        except errors.PointlessCommit:
175
 
            self.dialog.error_dialog('No changes to commit. Try force commit.')
176
 
            self.comm.set_busy(self.window, False)
 
296
            error_dialog(_('No changes to commit'),
 
297
                         _('Try force commit if you want to commit anyway.'))
177
298
            return
178
299
        except errors.ConflictsInTree:
179
 
            self.dialog.error_dialog('Conflicts in tree. Please resolve them first.')
180
 
            self.comm.set_busy(self.window, False)
 
300
            error_dialog(_('Conflicts in tree'),
 
301
                         _('You need to resolve the conflicts before committing.'))
181
302
            return
182
303
        except errors.StrictCommitFailed:
183
 
            self.dialog.error_dialog('Strict commit failed. There are unknown files.')
184
 
            self.comm.set_busy(self.window, False)
 
304
            error_dialog(_('Strict commit failed'),
 
305
                         _('There are unknown files in the working tree.\nPlease add or delete them.'))
185
306
            return
186
307
        except errors.BoundBranchOutOfDate, errmsg:
187
 
            self.dialog.error_dialog('Bound branch is out of date: %s' % errmsg)
188
 
            self.comm.set_busy(self.window, False)
189
 
            return
190
 
        except:
191
 
            raise
192
 
        
 
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
 
193
318
        self.close()
194
 
        self.comm.refresh_right()
195
 
        
 
319
 
196
320
    def close(self, widget=None):
197
321
        self.window.destroy()