PageRenderTime 32ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 0ms

/guitone-1.0rc5/src/monotone/MonotoneProcess.cpp

#
C++ | 199 lines | 143 code | 34 blank | 22 comment | 15 complexity | f06aa6a9da355fdf2cd2e1150f3edb4c MD5 | raw file
Possible License(s): GPL-3.0
  1. /***************************************************************************
  2. * Copyright (C) 2010 by Thomas Keller *
  3. * me@thomaskeller.biz *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation, either version 3 of the License, or *
  8. * (at your option) any later version. *
  9. * *
  10. * This program is distributed in the hope that it will be useful, *
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13. * GNU General Public License for more details. *
  14. * *
  15. * You should have received a copy of the GNU General Public License *
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  17. ***************************************************************************/
  18. #include "MonotoneProcess.h"
  19. #include "MonotoneUtil.h"
  20. #include "Settings.h"
  21. #include "vocab.h"
  22. #include <QDir>
  23. MonotoneProcess::MonotoneProcess()
  24. {
  25. setProcessChannelMode(QProcess::MergedChannels);
  26. QStringList env = QProcess::systemEnvironment();
  27. env.replaceInStrings(QRegExp("^LANG=.*", Qt::CaseInsensitive), "");
  28. env.push_back("LANG=en_US.UTF-8");
  29. setEnvironment(env);
  30. connect(
  31. this, SIGNAL(readyReadStandardOutput()),
  32. this, SLOT(readOutput())
  33. );
  34. connect(
  35. this, SIGNAL(readyReadStandardError()),
  36. this, SLOT(readOutput())
  37. );
  38. connect(
  39. this, SIGNAL(error(QProcess::ProcessError)),
  40. this, SLOT(processError(QProcess::ProcessError))
  41. );
  42. }
  43. MonotoneProcess::~MonotoneProcess()
  44. {
  45. if (state() != NotRunning)
  46. {
  47. close();
  48. terminate();
  49. waitForFinished();
  50. }
  51. }
  52. void MonotoneProcess::setMonotoneBinaryPath(const QString & path)
  53. {
  54. monotoneBinaryPath = path;
  55. }
  56. void MonotoneProcess::setMonotoneHandle(const MonotoneHandlePtr & handle)
  57. {
  58. I(handle->getType() != MonotoneHandle::server_handle);
  59. monotoneHandle = handle;
  60. }
  61. void MonotoneProcess::start(const QStringList & params)
  62. {
  63. bufferedOutput = QString();
  64. if (monotoneBinaryPath.isEmpty())
  65. {
  66. monotoneBinaryPath = Settings::getString("MtnExePath");
  67. }
  68. QStringList finalParams;
  69. if (!Settings::getBool("ReadUserRcFiles"))
  70. {
  71. finalParams << "--no-standard-rcfiles";
  72. }
  73. finalParams << "--rcfile" << rcFile.fileName();
  74. if (monotoneHandle.isNull())
  75. {
  76. monotoneHandle = MonotoneHandle::create();
  77. }
  78. // a somewhat reasonable path to choose to avoid side effects
  79. // like another existing monotone workspace
  80. QString workingDir = QDir::tempPath();
  81. if (monotoneHandle->getType() == MonotoneHandle::workspace_handle)
  82. {
  83. workingDir = monotoneHandle->getData();
  84. }
  85. setWorkingDirectory(workingDir);
  86. if (monotoneHandle->getType() == MonotoneHandle::database_handle)
  87. {
  88. finalParams << "-d" << monotoneHandle->getData();
  89. }
  90. finalParams += params;
  91. L(QString("starting external monotone process %1 %2")
  92. .arg(monotoneBinaryPath).arg(finalParams.join(" ")));
  93. QProcess::start(monotoneBinaryPath, finalParams);
  94. }
  95. void MonotoneProcess::readOutput()
  96. {
  97. QByteArray out = readAll();
  98. if (out.isEmpty()) return;
  99. QString strOut = QString::fromUtf8(out);
  100. emit output(strOut);
  101. bufferedOutput += strOut;
  102. }
  103. QString MonotoneProcess::getBufferedOutput() const
  104. {
  105. return bufferedOutput;
  106. }
  107. void MonotoneProcess::processError(QProcess::ProcessError processError)
  108. {
  109. QString message = QString::fromUtf8(readAllStandardError());
  110. // what follows is largely copied from MonotoneManager::abort
  111. QString mtnError = MonotoneUtil::stripMtnPrefix(message);
  112. QString processErrorTranslated;
  113. switch (processError)
  114. {
  115. case QProcess::FailedToStart:
  116. processErrorTranslated = tr("failed to start");
  117. break;
  118. case QProcess::Crashed:
  119. processErrorTranslated = tr("crashed");
  120. break;
  121. case QProcess::Timedout:
  122. processErrorTranslated = tr("timed out waiting for data");
  123. break;
  124. case QProcess::WriteError:
  125. processErrorTranslated = tr("failed to read");
  126. break;
  127. case QProcess::ReadError:
  128. processErrorTranslated = tr("failed to write");
  129. break;
  130. case QProcess::UnknownError:
  131. processErrorTranslated = tr("unknown error");
  132. break;
  133. default: I(false);
  134. }
  135. // log something reasonable
  136. C(QString("process died (%1) - stderr was %2")
  137. .arg(processErrorTranslated).arg(mtnError));
  138. // display something understandable to the user
  139. QString userMessage(tr(
  140. "The monotone process for '%1' died (%2). "
  141. "If you think this is a bug in guitone, "
  142. "please report it to the author!"
  143. ).arg(workingDirectory()).arg(processErrorTranslated));
  144. if (!mtnError.isEmpty())
  145. {
  146. userMessage.append(tr("\n\nLast error output was:\n%1").arg(mtnError));
  147. }
  148. emit error(userMessage);
  149. }
  150. bool MonotoneProcess::successful()
  151. {
  152. return exitStatus() == QProcess::NormalExit &&
  153. exitCode() == 0;
  154. }
  155. bool MonotoneProcess::singleRun(const QStringList & params,
  156. const MonotoneHandlePtr & handle,
  157. QString & output)
  158. {
  159. MonotoneProcess proc;
  160. proc.setMonotoneHandle(handle);
  161. proc.start(params);
  162. proc.waitForFinished();
  163. output = proc.getBufferedOutput();
  164. return proc.successful();
  165. }