# HG changeset patch # User Chris Cannam # Date 1290191980 0 # Node ID 295e3ee4a2576e45f6c9edb2a4b1ed04034dfeb2 # Parent 10eb97683aa98b1fd85ce3a18481eac408333956 * Allocate a pty for the subprocess, and ask the user for password. Very rudimentary and non-portable. diff -r 10eb97683aa9 -r 295e3ee4a257 easyhg.pro --- a/easyhg.pro Fri Nov 19 14:54:19 2010 +0000 +++ b/easyhg.pro Fri Nov 19 18:39:40 2010 +0000 @@ -58,9 +58,11 @@ macx-* { SOURCES += common_osx.mm - QMAKE_LFLAGS += -framework Foundation + LIBS += -framework Foundation } +LIBS += -lutil + # ! [0] RESOURCES = easyhg.qrc win32 { diff -r 10eb97683aa9 -r 295e3ee4a257 hgrunner.cpp --- a/hgrunner.cpp Fri Nov 19 14:54:19 2010 +0000 +++ b/hgrunner.cpp Fri Nov 19 18:39:40 2010 +0000 @@ -25,9 +25,13 @@ #include #include #include +#include #include #include +#include +#include +#include HgRunner::HgRunner(QWidget * parent): QProgressBar(parent) { @@ -45,15 +49,37 @@ stdOut.clear(); stdErr.clear(); + procInput = 0; + char name[1024]; + if (openpty(&ptyMasterFd, &ptySlaveFd, name, NULL, NULL)) { + perror("openpty failed"); + } else { + DEBUG << "openpty succeeded: master " << ptyMasterFd + << " slave " << ptySlaveFd << " filename " << name << endl; + procInput = new QFile; + procInput->open(ptyMasterFd, QFile::WriteOnly); + ptySlaveFilename = name; + proc->setStandardInputFile(ptySlaveFilename); + ::close(ptySlaveFd); + } + connect(proc, SIGNAL(started()), this, SLOT(started())); connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finished(int, QProcess::ExitStatus))); + connect(proc, SIGNAL(readyReadStandardOutput()), + this, SLOT(stdOutReady())); + connect(proc, SIGNAL(readyReadStandardError()), + this, SLOT(stdErrReady())); reportErrors = false; } HgRunner::~HgRunner() { + if (ptySlaveFilename != "") { + ::close(ptyMasterFd); +// ::close(ptySlaveFd); + } delete proc; } @@ -69,13 +95,21 @@ void HgRunner::started() { + /* + if (procInput) procInput->write("blah\n"); + if (procInput) procInput->write("blah\n"); + if (procInput) { + procInput->close(); +// ::close(ptyMasterFd); + } proc -> closeWriteChannel(); + */ } void HgRunner::saveOutput() { - stdOut = QString::fromUtf8(proc -> readAllStandardOutput()); - stdErr = QString::fromUtf8(proc -> readAllStandardError()); + stdOut += QString::fromUtf8(proc -> readAllStandardOutput()); + stdErr += QString::fromUtf8(proc -> readAllStandardError()); DEBUG << "saveOutput: " << stdOut.split("\n").size() << " line(s) of stdout, " << stdErr.split("\n").size() << " line(s) of stderr" << endl; @@ -93,6 +127,37 @@ return QString("Command line: " + lastHgCommand + " " + lastParams); } +void HgRunner::stdOutReady() +{ + DEBUG << "stdOutReady" << endl; + QString chunk = QString::fromUtf8(proc->readAllStandardOutput()); + DEBUG << "stdout was " << chunk << endl; + stdOut += chunk; +} + +void HgRunner::stdErrReady() +{ + DEBUG << "stdErrReady" << endl; + QString chunk = QString::fromUtf8(proc->readAllStandardError()); + DEBUG << "stderr was " << chunk << endl; + stdErr += chunk; + if (procInput) { + if (chunk.toLower().trimmed() == "password:") { + bool ok = false; + QString pwd = QInputDialog::getText + (qobject_cast(parent()), + tr("Enter password"), tr("Password (but for what user name and repository??"), + QLineEdit::Password, QString(), &ok); + if (ok) { + procInput->write(QString("%1\n").arg(pwd).toUtf8()); + procInput->flush(); + } else { + //!!! do what? close the terminal? + } + } + } +} + void HgRunner::finished(int procExitCode, QProcess::ExitStatus procExitStatus) { setProcExitInfo(procExitCode, procExitStatus); diff -r 10eb97683aa9 -r 295e3ee4a257 hgrunner.h --- a/hgrunner.h Fri Nov 19 14:54:19 2010 +0000 +++ b/hgrunner.h Fri Nov 19 18:39:40 2010 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include class HgRunner : public QProgressBar { @@ -54,6 +55,11 @@ QString getLastCommandLine(); void presentErrorToUser(); QString getHgBinaryName(); + + int ptyMasterFd; + int ptySlaveFd; + QString ptySlaveFilename; + QFile *procInput; bool reportErrors; bool isRunning; @@ -68,6 +74,8 @@ private slots: void started(); void finished(int procExitCode, QProcess::ExitStatus procExitStatus); + void stdOutReady(); + void stdErrReady(); }; #endif // HGRUNNER_H