Kiln » TortoiseHg » TortoiseHg
Clone URL:  
Pushed to one repository · View In Graph Contained in 1.9, 1.9.1, and 1.9.2

update: implemente 'Smart Update' feature partially

Since 'Shelve' tool is not implemented yet and it will be integrated
to Workbench app, so I dropped 'Shelve' option from the confirmation
dialog.

Changeset 47eecf5c9b02

Parent 440ac46e5f29

by Yuki KODAMA

Changes to one file · Browse files at 47eecf5c9b02 Showing diff from parent 440ac46e5f29 Diff from another changeset...

 
9
10
11
12
13
 
14
15
16
 
116
117
118
119
 
120
121
122
 
126
127
128
129
 
130
131
132
 
162
163
164
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
166
167
168
169
170
171
172
 
176
177
178
179
 
180
181
182
 
184
185
186
187
 
188
 
 
189
190
191
 
9
10
11
 
 
12
13
14
15
 
115
116
117
 
118
119
120
121
 
125
126
127
 
128
129
130
131
 
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
 
 
 
243
244
245
 
249
250
251
 
252
253
254
255
 
257
258
259
 
260
261
262
263
264
265
266
@@ -9,8 +9,7 @@
   from PyQt4.QtCore import QString, Qt  from PyQt4.QtGui import QDialog, QDialogButtonBox, QVBoxLayout, QGridLayout -from PyQt4.QtGui import QComboBox, QLabel, QLayout, QSpacerItem, QCheckBox -from PyQt4.QtGui import QPushButton +from PyQt4.QtGui import QComboBox, QLabel, QLayout, QCheckBox, QMessageBox    from mercurial import hg, ui, error   @@ -116,7 +115,7 @@
  self.close_btn.setAutoDefault(False)   self.update_btn = buttons.addButton(_('&Update'),   QDialogButtonBox.ActionRole) - self.update_btn.clicked.connect(self.update_clicked) + self.update_btn.clicked.connect(self.update)   self.detail_btn = buttons.addButton(_('Detail'),   QDialogButtonBox.ResetRole)   self.detail_btn.setAutoDefault(False) @@ -126,7 +125,7 @@
    # signal handlers   self.rev_combo.editTextChanged.connect(lambda *a: self.update_info()) - self.rev_combo.lineEdit().returnPressed.connect(self.update_clicked) + self.rev_combo.lineEdit().returnPressed.connect(self.update)   self.discard_chk.toggled.connect(lambda *a: self.update_info())     # dialog setting @@ -162,11 +161,85 @@
  self.target_info.setPlainText(_('unknown revision!'))   self.update_btn.setDisabled(True)   + def update(self): + cmdline = ['update', '--verbose'] + rev = hglib.fromunicode(self.rev_combo.currentText()) + cmdline.append('--rev') + cmdline.append(rev) + + if self.discard_chk.isChecked(): + cmdline.append('--clean') + else: + cur = self.repo['.'] + node = self.repo[rev] + def isclean(): + '''whether WD is changed''' + wc = self.repo[None] + return not (wc.modified() or wc.added() or wc.removed()) + def ismergedchange(): + '''whether the local changes are merged (have 2 parents)''' + wc = self.repo[None] + return len(wc.parents()) == 2 + def iscrossbranch(p1, p2): + '''whether p1 -> p2 crosses branch''' + pa = p1.ancestor(p2) + return p1.branch() != p2.branch() or (p1 != pa and p2 != pa) + def islocalmerge(p1, p2, clean=None): + if clean is None: + clean = isclean() + pa = p1.ancestor(p2) + return not clean and (p1 == pa or p2 == pa) + def confirmupdate(clean=None): + if clean is None: + clean = isclean() + + msg = _('Detected uncommitted local changes in working tree.\n' + 'Please select to continue:\n\n') + data = {'discard': (_('&Discard'), + _('Discard - discard local changes, no backup')), + 'patch': (_('&Patch'), + _('Patch - move local changes to MQ patch')), + 'merge': (_('&Merge'), + _('Merge - allow to merge with local changes')),} + + opts = [data['discard']] + if not ismergedchange(): + opts.append(data['patch']) + if islocalmerge(cur, node, clean): + opts.append(data['merge']) + + msg += '\n'.join([desc for label, desc in opts if desc]) + dlg = QMessageBox(QMessageBox.Question, _('Confirm Update'), + msg, QMessageBox.Cancel, self) + buttons = {} + for name in ('discard', 'patch', 'merge'): + label, desc = data[name] + buttons[name] = dlg.addButton(label, QMessageBox.ActionRole) + dlg.exec_() + return buttons, dlg.clickedButton() + + # If merge-by-default, we want to merge whenever possible, + # without prompting user (similar to command-line behavior) + defaultmerge = self.merge_chk.isChecked() + clean = isclean() + if clean: + cmdline.append('--check') + elif not (defaultmerge and islocalmerge(cur, node, clean)): + buttons, clicked = confirmupdate(clean) + if buttons['discard'] == clicked: + cmdline.append('--clean') + elif buttons['patch'] == clicked: + return # TODO: not implemented yet + elif buttons['merge'] == clicked: + pass # no args + else: + return + + # start updating + self.cmd.run(cmdline) +   ### Signal Handlers ###   - def update_clicked(self): - self.cmd.run(['update', hglib.fromunicode(self.rev_combo.currentText())]) -   def cancel_clicked(self):   self.cmd.cancel()   @@ -176,7 +249,7 @@
  def command_started(self):   self.cmd.setShown(True)   if self.showlog_chk.isChecked(): - self.cmd.show_output(True) + self.detail_btn.setChecked(True)   self.update_btn.setHidden(True)   self.close_btn.setHidden(True)   self.cancel_btn.setShown(True) @@ -184,8 +257,10 @@
    def command_finished(self, wrapper):   if wrapper.data is not 0 or self.cmd.is_show_output(): - self.cmd.show_output(True) + self.detail_btn.setChecked(True)   self.close_btn.setShown(True) + self.close_btn.setAutoDefault(True) + self.close_btn.setFocus()   self.cancel_btn.setHidden(True)   else:   self.reject()