Mercurial > hg > easyhg
comparison hgrunner.cpp @ 109:1721c580c10e
* Add a queueing mechanism for Hg actions, instead of refusing to start an action if something else is already happening. This is essential now that actions can be prompted by asynchronous events (e.g. filesystem watcher).
* Make Revert behave sensibly
author | Chris Cannam |
---|---|
date | Fri, 26 Nov 2010 12:48:29 +0000 |
parents | fdca34c989c0 |
children | 0f039d3cc38e |
comparison
equal
deleted
inserted
replaced
108:8ae3b44c0073 | 109:1721c580c10e |
---|---|
70 ::close(m_ptyMasterFd); | 70 ::close(m_ptyMasterFd); |
71 } | 71 } |
72 delete m_proc; | 72 delete m_proc; |
73 } | 73 } |
74 | 74 |
75 void HgRunner::requestAction(HgAction action) | |
76 { | |
77 DEBUG << "requestAction " << action.action << endl; | |
78 bool pushIt = true; | |
79 if (m_queue.empty()) { | |
80 if (action == m_currentAction) { | |
81 // this request is identical to the thing we're executing | |
82 DEBUG << "requestAction: we're already handling this one, ignoring identical request" << endl; | |
83 pushIt = false; | |
84 } | |
85 } else { | |
86 HgAction last = m_queue.back(); | |
87 if (action == last) { | |
88 // this request is identical to the previous thing we | |
89 // queued which we haven't executed yet | |
90 DEBUG << "requestAction: we're already queueing this one, ignoring identical request" << endl; | |
91 pushIt = false; | |
92 } | |
93 } | |
94 if (pushIt) m_queue.push_back(action); | |
95 checkQueue(); | |
96 } | |
97 | |
75 QString HgRunner::getHgBinaryName() | 98 QString HgRunner::getHgBinaryName() |
76 { | 99 { |
77 QSettings settings; | 100 QSettings settings; |
78 QString hg = settings.value("hgbinary", "").toString(); | 101 QString hg = settings.value("hgbinary", "").toString(); |
79 if (hg == "") { | 102 if (hg == "") { |
91 /* | 114 /* |
92 m_proc->write("blah\n"); | 115 m_proc->write("blah\n"); |
93 m_proc->write("blah\n"); | 116 m_proc->write("blah\n"); |
94 m_proc -> closeWriteChannel(); | 117 m_proc -> closeWriteChannel(); |
95 */ | 118 */ |
96 } | |
97 | |
98 void HgRunner::setProcExitInfo(int procExitCode, QProcess::ExitStatus procExitStatus) | |
99 { | |
100 m_exitCode = procExitCode; | |
101 m_exitStatus = procExitStatus; | |
102 } | |
103 | |
104 QString HgRunner::getLastCommandLine() | |
105 { | |
106 return QString("Command line: " + m_lastHgCommand + " " + m_lastParams); | |
107 } | 119 } |
108 | 120 |
109 void HgRunner::noteUsername(QString name) | 121 void HgRunner::noteUsername(QString name) |
110 { | 122 { |
111 m_userName = name; | 123 m_userName = name; |
198 checkPrompts(chunk); | 210 checkPrompts(chunk); |
199 } | 211 } |
200 | 212 |
201 void HgRunner::finished(int procExitCode, QProcess::ExitStatus procExitStatus) | 213 void HgRunner::finished(int procExitCode, QProcess::ExitStatus procExitStatus) |
202 { | 214 { |
203 setProcExitInfo(procExitCode, procExitStatus); | 215 // Save the current action and reset m_currentAction before we |
216 // emit a signal to mark the completion; otherwise we may be | |
217 // resetting the action after a slot has already tried to set it | |
218 // to something else to start a new action | |
219 | |
220 HgAction completedAction = m_currentAction; | |
221 | |
204 m_isRunning = false; | 222 m_isRunning = false; |
223 m_currentAction = HgAction(); | |
205 | 224 |
206 closeProcInput(); | 225 closeProcInput(); |
226 | |
227 if (completedAction.action == ACT_NONE) { | |
228 DEBUG << "HgRunner::finished: WARNING: completed action is ACT_NONE" << endl; | |
229 } | |
207 | 230 |
208 if (procExitCode == 0 && procExitStatus == QProcess::NormalExit) { | 231 if (procExitCode == 0 && procExitStatus == QProcess::NormalExit) { |
209 DEBUG << "HgRunner::finished: Command completed successfully" << endl; | 232 DEBUG << "HgRunner::finished: Command completed successfully" << endl; |
210 emit commandCompleted(); | 233 //!!! NB this is all output not stdout as it should be |
234 emit commandCompleted(completedAction, m_output); | |
211 } else { | 235 } else { |
212 DEBUG << "HgRunner::finished: Command failed" << endl; | 236 DEBUG << "HgRunner::finished: Command failed" << endl; |
213 emit commandFailed(); | 237 //!!! NB this is all output not stderr as it should be |
214 } | 238 emit commandFailed(completedAction, m_output); |
215 } | 239 } |
216 | 240 |
241 checkQueue(); | |
242 } | |
243 /* | |
217 bool HgRunner::isCommandRunning() | 244 bool HgRunner::isCommandRunning() |
218 { | 245 { |
219 return m_isRunning; | 246 return m_isRunning; |
220 } | 247 } |
248 */ | |
221 | 249 |
222 void HgRunner::killCurrentCommand() | 250 void HgRunner::killCurrentCommand() |
223 { | 251 { |
224 if (isCommandRunning()) { | 252 if (m_isRunning) { |
225 m_proc -> kill(); | 253 m_proc -> kill(); |
226 } | 254 } |
227 } | 255 } |
228 | 256 |
229 void HgRunner::startHgCommand(QString workingDir, QStringList params, bool interactive) | 257 void HgRunner::checkQueue() |
230 { | 258 { |
259 if (m_isRunning) { | |
260 return; | |
261 } | |
262 if (m_queue.empty()) { | |
263 hide(); | |
264 return; | |
265 } | |
266 HgAction toRun = m_queue.front(); | |
267 m_queue.pop_front(); | |
268 DEBUG << "checkQueue: have action: running " << toRun.action << endl; | |
269 startCommand(toRun); | |
270 } | |
271 | |
272 void HgRunner::startCommand(HgAction action) | |
273 { | |
274 QString executable = action.executable; | |
275 bool interactive = false; | |
276 QStringList params = action.params; | |
277 | |
278 if (executable == "") { | |
279 // This is a Hg command | |
280 executable = getHgBinaryName(); | |
231 #ifdef Q_OS_WIN32 | 281 #ifdef Q_OS_WIN32 |
232 // This at least means we won't block on the non-working password prompt | 282 // This at least means we won't block on the non-working password prompt |
233 params.push_front("ui.interactive=false"); | 283 params.push_front("--noninteractive"); |
234 #else | 284 #else |
235 // password prompt should work here | 285 // password prompt should work here |
236 if (interactive) { | 286 if (action.mayBeInteractive()) { |
237 params.push_front("ui.interactive=true"); | 287 params.push_front("ui.interactive=true"); |
238 } else { | 288 params.push_front("--config"); |
239 params.push_front("ui.interactive=false"); | 289 interactive = true; |
240 } | 290 } else { |
241 #endif | 291 params.push_front("--noninteractive"); |
242 params.push_front("--config"); | 292 } |
243 startCommand(getHgBinaryName(), workingDir, params, interactive); | 293 } |
244 } | 294 #endif |
245 | 295 |
246 void HgRunner::startCommand(QString command, QString workingDir, QStringList params, | |
247 bool interactive) | |
248 { | |
249 m_isRunning = true; | 296 m_isRunning = true; |
250 setRange(0, 0); | 297 setRange(0, 0); |
251 setVisible(true); | 298 show(); |
252 m_output.clear(); | 299 m_output.clear(); |
253 m_exitCode = 0; | |
254 m_exitStatus = QProcess::NormalExit; | |
255 m_realm = ""; | 300 m_realm = ""; |
256 m_userName = ""; | 301 m_userName = ""; |
257 | 302 |
258 if (!workingDir.isEmpty()) { | 303 if (!action.workingDir.isEmpty()) { |
259 m_proc->setWorkingDirectory(workingDir); | 304 m_proc->setWorkingDirectory(action.workingDir); |
260 } | 305 } |
261 | 306 |
262 m_procInput = 0; | 307 m_procInput = 0; |
263 m_ptySlaveFilename = ""; | 308 m_ptySlaveFilename = ""; |
264 | 309 |
277 ::close(m_ptySlaveFd); | 322 ::close(m_ptySlaveFd); |
278 } | 323 } |
279 } | 324 } |
280 #endif | 325 #endif |
281 | 326 |
282 m_lastHgCommand = command; | 327 QString cmdline = executable; |
283 m_lastParams = params.join(" "); | |
284 | |
285 QString cmdline = command; | |
286 foreach (QString param, params) cmdline += " " + param; | 328 foreach (QString param, params) cmdline += " " + param; |
287 DEBUG << "HgRunner: starting: " << cmdline << " with cwd " | 329 DEBUG << "HgRunner: starting: " << cmdline << " with cwd " |
288 << workingDir << endl; | 330 << action.workingDir << endl; |
289 | 331 |
290 m_proc->start(command, params); | 332 m_currentAction = action; |
333 | |
334 DEBUG << "set current action to " << m_currentAction.action << endl; | |
335 | |
336 m_proc->start(executable, params); | |
291 } | 337 } |
292 | 338 |
293 void HgRunner::closeProcInput() | 339 void HgRunner::closeProcInput() |
294 { | 340 { |
295 DEBUG << "closeProcInput" << endl; | 341 DEBUG << "closeProcInput" << endl; |
301 m_ptySlaveFilename = ""; | 347 m_ptySlaveFilename = ""; |
302 } | 348 } |
303 #endif | 349 #endif |
304 } | 350 } |
305 | 351 |
306 int HgRunner::getExitCode() | |
307 { | |
308 return m_exitCode; | |
309 } | |
310 | |
311 QString HgRunner::getOutput() | |
312 { | |
313 return m_output; | |
314 } | |
315 | |
316 void HgRunner::hideProgBar() | |
317 { | |
318 setVisible(false); | |
319 } | |
320 | |
321 |