comparison src/hgrunner.cpp @ 605:ab92f695f776

Expand environmental parameters and executable name in action when it is received rather than when it's executed. This ensures we can correctly compare actions and fixes #141 "Unexpected error if you double-click on a toolbar button"
author Chris Cannam
date Tue, 03 Jul 2012 11:22:10 +0100
parents 012ba1b83328
children ae67ea0af696
comparison
equal deleted inserted replaced
604:98f57888d893 605:ab92f695f776
149 return unbundled; 149 return unbundled;
150 } 150 }
151 151
152 void HgRunner::requestAction(HgAction action) 152 void HgRunner::requestAction(HgAction action)
153 { 153 {
154 DEBUG << "requestAction " << action.action << endl; 154 DEBUG << "requestAction " << action.action << ": " << m_queue.size() << " thing(s) in queue, current action is " << m_currentAction.action << endl;
155 bool pushIt = true; 155 bool pushIt = true;
156
157 action = expandEnvironment(action);
158
156 if (m_queue.empty()) { 159 if (m_queue.empty()) {
157 if (action == m_currentAction) { 160 if (action == m_currentAction) {
158 // this request is identical to the thing we're executing 161 // this request is identical to the thing we're executing
159 DEBUG << "requestAction: we're already handling this one, ignoring identical request" << endl; 162 DEBUG << "requestAction: we're already handling this one, ignoring identical request" << endl;
160 pushIt = false; 163 pushIt = false;
166 // queued which we haven't executed yet 169 // queued which we haven't executed yet
167 DEBUG << "requestAction: we're already queueing this one, ignoring identical request" << endl; 170 DEBUG << "requestAction: we're already queueing this one, ignoring identical request" << endl;
168 pushIt = false; 171 pushIt = false;
169 } 172 }
170 } 173 }
171 if (pushIt) m_queue.push_back(action); 174 if (pushIt) {
175 m_queue.push_back(action);
176 }
172 checkQueue(); 177 checkQueue();
178 }
179
180 HgAction HgRunner::expandEnvironment(HgAction action)
181 {
182 // Adjust the executable and params for action to match our actual
183 // environment. We do this when the action is received, rather
184 // than when we execute it, so that we can compare
185 // (post-expansion) commands to see e.g. whether the one just
186 // received is the same as the one we're currently executing
187
188 QString executable = action.executable;
189 QStringList params = action.params;
190
191 if (executable == "") {
192 // This is a Hg command
193 executable = getHgBinaryName();
194 if (executable == "") executable = "hg";
195
196 QString ssh = getSshBinaryName();
197 if (ssh != "") {
198 params.push_front(QString("ui.ssh=\"%1\"").arg(ssh));
199 params.push_front("--config");
200 }
201
202 if (action.mayBeInteractive()) {
203 params.push_front("ui.interactive=true");
204 params.push_front("--config");
205 QSettings settings;
206 if (settings.value("useextension", true).toBool()) {
207 params = addExtensionOptions(params);
208 }
209 }
210 }
211
212 action.executable = executable;
213 action.params = params;
214
215 return action;
173 } 216 }
174 217
175 QString HgRunner::getHgBinaryName() 218 QString HgRunner::getHgBinaryName()
176 { 219 {
177 QSettings settings; 220 QSettings settings;
346 // emit a signal to mark the completion; otherwise we may be 389 // emit a signal to mark the completion; otherwise we may be
347 // resetting the action after a slot has already tried to set it 390 // resetting the action after a slot has already tried to set it
348 // to something else to start a new action 391 // to something else to start a new action
349 392
350 HgAction completedAction = m_currentAction; 393 HgAction completedAction = m_currentAction;
394
395 DEBUG << "HgRunner::finished: completed " << completedAction.action << endl;
351 396
352 m_isRunning = false; 397 m_isRunning = false;
353 m_currentAction = HgAction(); 398 m_currentAction = HgAction();
354 399
355 //closeProcInput(); 400 //closeProcInput();
501 return params; 546 return params;
502 } 547 }
503 548
504 void HgRunner::startCommand(HgAction action) 549 void HgRunner::startCommand(HgAction action)
505 { 550 {
506 QString executable = action.executable;
507 bool interactive = false;
508 QStringList params = action.params;
509
510 if (action.workingDir.isEmpty()) { 551 if (action.workingDir.isEmpty()) {
511 // We require a working directory, never just operate in pwd 552 // We require a working directory, never just operate in pwd
512 emit commandFailed(action, "EasyMercurial: No working directory supplied, will not run Mercurial command without one", ""); 553 emit commandFailed(action, "EasyMercurial: No working directory supplied, will not run Mercurial command without one", "");
513 return; 554 return;
514 }
515
516 if (executable == "") {
517 // This is a Hg command
518 executable = getHgBinaryName();
519 if (executable == "") executable = "hg";
520
521 QString ssh = getSshBinaryName();
522 if (ssh != "") {
523 params.push_front(QString("ui.ssh=\"%1\"").arg(ssh));
524 params.push_front("--config");
525 }
526
527 if (action.mayBeInteractive()) {
528 params.push_front("ui.interactive=true");
529 params.push_front("--config");
530 QSettings settings;
531 if (settings.value("useextension", true).toBool()) {
532 params = addExtensionOptions(params);
533 }
534 interactive = true;
535 }
536
537 //!!! want an option to use the mercurial_keyring extension as well
538 } 555 }
539 556
540 m_isRunning = true; 557 m_isRunning = true;
541 m_progress->setRange(0, 0); 558 m_progress->setRange(0, 0);
542 if (!action.shouldBeFast()) { 559 if (!action.shouldBeFast()) {
581 connect(m_proc, SIGNAL(readyReadStandardError()), 598 connect(m_proc, SIGNAL(readyReadStandardError()),
582 this, SLOT(dataReadyStderr())); 599 this, SLOT(dataReadyStderr()));
583 600
584 m_proc->setWorkingDirectory(action.workingDir); 601 m_proc->setWorkingDirectory(action.workingDir);
585 602
586 if (interactive) { 603 if (action.mayBeInteractive()) {
587 openTerminal(); 604 openTerminal();
588 if (m_ptySlaveFilename != "") { 605 if (m_ptySlaveFilename != "") {
589 DEBUG << "HgRunner: connecting to pseudoterminal" << endl; 606 DEBUG << "HgRunner: connecting to pseudoterminal" << endl;
590 m_proc->setStandardInputFile(m_ptySlaveFilename); 607 m_proc->setStandardInputFile(m_ptySlaveFilename);
591 // m_proc->setStandardOutputFile(m_ptySlaveFilename); 608 // m_proc->setStandardOutputFile(m_ptySlaveFilename);
592 // m_proc->setStandardErrorFile(m_ptySlaveFilename); 609 // m_proc->setStandardErrorFile(m_ptySlaveFilename);
593 } 610 }
594 } 611 }
595 612
596 QString cmdline = executable; 613 QString cmdline = action.executable;
597 foreach (QString param, params) cmdline += " " + param; 614 foreach (QString param, action.params) cmdline += " " + param;
598 DEBUG << "HgRunner: starting: " << cmdline << " with cwd " 615 DEBUG << "HgRunner: starting: " << cmdline << " with cwd "
599 << action.workingDir << endl; 616 << action.workingDir << endl;
600 617
601 m_currentAction = action; 618 m_currentAction = action;
602
603 // fill these out with what we actually ran
604 m_currentAction.executable = executable;
605 m_currentAction.params = params;
606 619
607 DEBUG << "set current action to " << m_currentAction.action << endl; 620 DEBUG << "set current action to " << m_currentAction.action << endl;
608 621
609 emit commandStarting(action); 622 emit commandStarting(action);
610 623
611 m_proc->start(executable, params); 624 m_proc->start(action.executable, action.params);
612 } 625 }
613 626
614 void HgRunner::closeProcInput() 627 void HgRunner::closeProcInput()
615 { 628 {
616 DEBUG << "closeProcInput" << endl; 629 DEBUG << "closeProcInput" << endl;