# HG changeset patch # User Chris Cannam # Date 1290000776 0 # Node ID 68aebc316898393369adae6f135c934d9f3c71ca # Parent bf57a16315bdf8b5eacfc286eb490f0fce18bc88 * Some adjustments to process running (avoid timer): caller must now report errors * Function to find user's real name * Locate hg executable in path explicitly, use a setting to remember it diff -r bf57a16315bd -r 68aebc316898 common.cpp --- a/common.cpp Wed Nov 17 11:48:58 2010 +0000 +++ b/common.cpp Wed Nov 17 13:32:56 2010 +0000 @@ -15,9 +15,44 @@ COPYING included with this distribution for more information. */ +#include "common.h" +#include "debug.h" -#include "common.h" +#include +#include +#include +#include +#include + +QString findExecutable(QString name) +{ + if (name != "") { + if (name[0] != '/') { + name = QFileInfo(name).fileName(); + QString path = + QProcessEnvironment::systemEnvironment().value("PATH"); + DEBUG << "findExecutable: seeking location for binary " << name + << ": system path is " << path; +#ifdef Q_OS_WIN32 + QChar pathSep = ';'; +#else + QChar pathSep = ':'; +#endif + QStringList elements = path.split(pathSep, QString::SkipEmptyParts); + foreach (QString element, elements) { + QString full = QString("%1/%2").arg(element).arg(name); + QFileInfo fi(full); + if (fi.exists() && fi.isFile() && fi.isExecutable()) { + name = full; + break; + } + } + } + } + return name; +} + QString getSystem() { #ifdef Q_WS_X11 @@ -35,15 +70,6 @@ return QString(""); } -QString getHgBinaryName() -{ - if (getSystem() == "Windows") - return QString("hg.exe"); - else - return QString("hg"); -} - - QString getHgDirName() { if (getSystem() == "Windows") @@ -56,8 +82,35 @@ } } +#ifdef Q_OS_WIN32 +QString getUserRealName() +{ + const int maxlen = 1023; + TCHAR buf[maxlen + 2]; + LPTSTR info = buf; + if (!GetUserNameEx(NameDisplay, info, maxlen)) { + return ""; + } + return QString::fromUcs2(info); +} +#elif Q_OS_MAC +// Nothing here: definition is in common_osx.mm +#else +QString getUserRealName() +{ + const int maxlen = 1023; + char buf[maxlen + 2]; + if (getlogin_r(buf, maxlen)) return ""; + struct passwd *p = getpwnam(buf); + if (!p) return ""; + + QString s(p->pw_gecos); + if (s != "") s = s.split(',')[0]; + return s; +} +#endif diff -r bf57a16315bd -r 68aebc316898 common.h --- a/common.h Wed Nov 17 11:48:58 2010 +0000 +++ b/common.h Wed Nov 17 13:32:56 2010 +0000 @@ -43,11 +43,13 @@ #define NUM_PATHS_IN_MRU_LIST 5 +extern QString findExecutable(QString name); extern QString getSystem(); -extern QString getHgBinaryName(); extern QString getHgDirName(); +extern QString getUserRealName(); + #endif //COMMON_H diff -r bf57a16315bd -r 68aebc316898 common_osx.mm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common_osx.mm Wed Nov 17 13:32:56 2010 +0000 @@ -0,0 +1,16 @@ + +#include "common.h" + +#include + +#ifdef Q_OS_MAC + +#include + +QString getUserRealName() +{ + NSString *s = NSFullUserName(); + return QString::fromLocal8Bit([s UTF8String]); +} + +#endif diff -r bf57a16315bd -r 68aebc316898 debug.cpp --- a/debug.cpp Wed Nov 17 11:48:58 2010 +0000 +++ b/debug.cpp Wed Nov 17 13:32:56 2010 +0000 @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -53,6 +54,8 @@ delete logFile; logFile = 0; } + *debug << endl << (const char *)prefix << "Log started at " + << QDateTime::currentDateTime().toString(); } mutex.unlock(); diff -r bf57a16315bd -r 68aebc316898 easyhg.pro --- a/easyhg.pro Wed Nov 17 11:48:58 2010 +0000 +++ b/easyhg.pro Wed Nov 17 13:32:56 2010 +0000 @@ -41,6 +41,10 @@ colourset.cpp \ debug.cpp +macx-* { +SOURCES += common_osx.mm +} + # ! [0] RESOURCES = hgexplorer.qrc win32 { diff -r bf57a16315bd -r 68aebc316898 hgrunner.cpp --- a/hgrunner.cpp Wed Nov 17 11:48:58 2010 +0000 +++ b/hgrunner.cpp Wed Nov 17 13:32:56 2010 +0000 @@ -16,6 +16,7 @@ */ #include "hgrunner.h" +#include "common.h" #include "debug.h" #include @@ -23,6 +24,7 @@ #include #include #include +#include #include #include @@ -44,8 +46,10 @@ stdErr.clear(); connect(proc, SIGNAL(started()), this, SLOT(started())); - connect(proc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(error(QProcess::ProcessError))); - connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finished(int, QProcess::ExitStatus))); + connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(finished(int, QProcess::ExitStatus))); + + reportErrors = false; } HgRunner::~HgRunner() @@ -53,73 +57,37 @@ delete proc; } +QString HgRunner::getHgBinaryName() +{ + QSettings settings; + QString hg = settings.value("hgbinary", "hg").toString(); + if (hg == "") hg = "hg"; + hg = findExecutable(hg); + settings.setValue("hgbinary", hg); + return hg; +} + void HgRunner::started() { proc -> closeWriteChannel(); } +void HgRunner::saveOutput() +{ + stdOut = QString::fromUtf8(proc -> readAllStandardOutput()); + stdErr = QString::fromUtf8(proc -> readAllStandardError()); +} + void HgRunner::setProcExitInfo(int procExitCode, QProcess::ExitStatus procExitStatus) { exitCode = procExitCode; exitStatus = procExitStatus; - stdOut = QString::fromUtf8(proc -> readAllStandardOutput()); - stdErr = QString::fromUtf8(proc -> readAllStandardError()); DEBUG << "setProcExitInfo: " << stdOut.split("\n").size() << " line(s) of stdout, " << stdErr.split("\n").size() << " line(s) of stderr"; // std::cerr << "stdout was " << stdOut.toStdString() << std::endl; } -void HgRunner::presentErrorToUser() -{ - QPushButton *okButton; - QListWidget *stdoL; - QListWidget *stdeL; - QString tmp; - - QDialog *dlg = new QDialog(this); - dlg -> setMinimumWidth(800); - QVBoxLayout layout; - - dlg -> setWindowTitle(tr("Mercurial error / warning")); - - tmp.sprintf("%s: %d, %s: %d", "Exitcode", exitCode, "Exit status", exitStatus); - layout.addWidget(new QLabel(getLastCommandLine())); - layout.addWidget(new QLabel(tmp)); - layout.addWidget(new QLabel(tr("Standard out:"))); - stdoL = new QListWidget(); - stdoL -> addItems(stdOut.split("\n")); - layout.addWidget(stdoL); - - layout.addWidget(new QLabel(tr("Standard error:"))); - stdeL = new QListWidget(); - stdeL -> addItems(stdErr.split("\n")); - layout.addWidget(stdeL); - - okButton = new QPushButton("Ok"); - layout.addWidget(okButton); - - connect(okButton, SIGNAL(clicked()), dlg, SLOT(accept())); - dlg -> setLayout(&layout); - - dlg -> setModal(true); - dlg -> exec(); -} - - - -void HgRunner::error(QProcess::ProcessError) -{ - setProcExitInfo(proc -> exitCode(), proc -> exitStatus()); - - if (reportErrors) - { - presentErrorToUser(); - } - - isRunning = false; -} - QString HgRunner::getLastCommandLine() { return QString("Command line: " + lastHgCommand + " " + lastParams); @@ -128,39 +96,34 @@ void HgRunner::finished(int procExitCode, QProcess::ExitStatus procExitStatus) { setProcExitInfo(procExitCode, procExitStatus); + isRunning = false; - if (reportErrors) - { - if ((exitCode == 0) && (exitStatus == QProcess::NormalExit)) - { - //All ok - } - else - { - presentErrorToUser(); - } + if (procExitCode == 0 || procExitStatus == QProcess::NormalExit) { + emit commandCompleted(); + } else { + emit commandFailed(); } - - isRunning = false; } -bool HgRunner::isProcRunning() +bool HgRunner::isCommandRunning() { return isRunning; } -void HgRunner::killProc() +void HgRunner::killCurrentCommand() { - if (isProcRunning()) - { + if (isCommandRunning()) { proc -> kill(); } } +void HgRunner::startHgCommand(QString workingDir, QStringList params) +{ + startCommand(getHgBinaryName(), workingDir, params); +} -void HgRunner::startProc(QString hgExePathAndName, QString workingDir, QStringList params, bool reportErrors) +void HgRunner::startCommand(QString command, QString workingDir, QStringList params) { - this -> reportErrors = reportErrors; isRunning = true; setRange(0, 0); setVisible(true); @@ -174,15 +137,14 @@ proc -> setWorkingDirectory(workingDir); } - lastHgCommand = hgExePathAndName; + lastHgCommand = command; lastParams = params.join(" "); - QString cmdline = hgExePathAndName; + QString cmdline = command; foreach (QString param, params) cmdline += " " + param; DEBUG << "HgRunner: starting: " << cmdline; - proc -> start(hgExePathAndName, params); - + proc -> start(command, params); } int HgRunner::getExitCode() diff -r bf57a16315bd -r 68aebc316898 hgrunner.h --- a/hgrunner.h Wed Nov 17 11:48:58 2010 +0000 +++ b/hgrunner.h Wed Nov 17 13:32:56 2010 +0000 @@ -27,37 +27,47 @@ { Q_OBJECT - public: - HgRunner(QWidget * parent = 0); - ~HgRunner(); +public: + HgRunner(QWidget * parent = 0); + ~HgRunner(); - void startProc(QString hgExePathAndName, QString workingDir, QStringList params, bool reportErrors = true); - bool isProcRunning(); - void killProc(); - int getExitCode(); - void hideProgBar(); - QString getStdOut(); + void startHgCommand(QString workingDir, QStringList params); + void startCommand(QString command, QString workingDir, QStringList params); - private: - void setProcExitInfo(int procExitCode, QProcess::ExitStatus procExitStatus); - QString getLastCommandLine(); - void presentErrorToUser(); + bool isCommandRunning(); + void killCurrentCommand(); - bool reportErrors; - bool isRunning; - QProcess *proc; - QString stdOut; - QString stdErr; - int exitCode; - QProcess::ExitStatus exitStatus; - QString lastHgCommand; - QString lastParams; + int getExitCode(); + QProcess::ExitStatus getExitStatus(); + void hideProgBar(); - private slots: - void started(); - void error(QProcess::ProcessError error); - void finished(int procExitCode, QProcess::ExitStatus procExitStatus); + QString getStdOut(); + +signals: + void commandCompleted(); + void commandFailed(); + +private: + void saveOutput(); + void setProcExitInfo(int procExitCode, QProcess::ExitStatus procExitStatus); + QString getLastCommandLine(); + void presentErrorToUser(); + QString getHgBinaryName(); + + bool reportErrors; + bool isRunning; + QProcess *proc; + QString stdOut; + QString stdErr; + int exitCode; + QProcess::ExitStatus exitStatus; + QString lastHgCommand; + QString lastParams; + +private slots: + void started(); + void finished(int procExitCode, QProcess::ExitStatus procExitStatus); }; #endif // HGRUNNER_H diff -r bf57a16315bd -r 68aebc316898 mainwindow.cpp --- a/mainwindow.cpp Wed Nov 17 11:48:58 2010 +0000 +++ b/mainwindow.cpp Wed Nov 17 13:32:56 2010 +0000 @@ -32,6 +32,7 @@ #include "mainwindow.h" #include "settingsdialog.h" #include "colourset.h" +#include "debug.h" MainWindow::MainWindow() @@ -43,8 +44,11 @@ createToolBars(); createStatusBar(); - timerId = startTimer(200); runner = new HgRunner(this); + connect(runner, SIGNAL(commandCompleted()), + this, SLOT(commandCompleted())); + connect(runner, SIGNAL(commandFailed()), + this, SLOT(commandFailed())); runningAction = ACT_NONE; statusBar()->addPermanentWidget(runner); @@ -70,6 +74,8 @@ settings(); } + DEBUG << "User's real name is " << getUserRealName() << endl; + hgStat(); } @@ -114,7 +120,7 @@ } - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_STAT; } } @@ -128,7 +134,7 @@ params << "heads"; //on empty repos, "hg heads" will fail, don't care of that. - runner -> startProc(getHgBinaryName(), workFolderPath, params, false); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_HEADS; } } @@ -142,7 +148,7 @@ params << "--template"; params << "id: {rev}:{node|short}\\nauthor: {author}\\nbranch: {branches}\\ntag: {tag}\\ndatetime: {date|isodate}\\ntimestamp: {date|hgdate}\\nage: {date|age}\\nparents: {parents}\\ncomment: {desc|json}\\n\\n"; - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_LOG; } } @@ -155,7 +161,7 @@ QStringList params; params << "parents"; - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_PARENTS; } } @@ -176,7 +182,7 @@ { params << "remove" << "--after" << "--force" << "--" << currentFile.mid(2); //Jump over status marker characters (e.g "M ") - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_REMOVE; } } @@ -194,7 +200,7 @@ { params << "annotate" << "--" << currentFile.mid(2); //Jump over status marker characters (e.g "M ") - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_ANNOTATE; } } @@ -212,7 +218,7 @@ { params << "resolve" << "--mark" << "--" << currentFile.mid(2); //Jump over status marker characters (e.g "M ") - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_RESOLVE_MARK; } } @@ -227,7 +233,7 @@ QStringList params; params << "resolve" << "--list"; - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_RESOLVE_LIST; } } @@ -261,7 +267,7 @@ params << "add"; } - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_ADD; } } @@ -330,7 +336,7 @@ params << "commit" << "--message" << comment << "--user" << userInfo; } - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_COMMIT; } } @@ -367,7 +373,7 @@ { params << "tag" << "--user" << userInfo << filterTag(tag); - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_TAG; } } @@ -397,7 +403,7 @@ editorName = """C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe"""; } - runner -> startProc(editorName, workFolderPath, params); + runner -> startCommand(editorName, workFolderPath, params); runningAction = ACT_HG_IGNORE; } } @@ -416,7 +422,7 @@ { //Diff parent file against working folder file params << "kdiff3" << "--" << currentFile.mid(2); - runner -> startProc(getHgBinaryName(), workFolderPath, params, false); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_FILEDIFF; } } @@ -431,7 +437,7 @@ //Diff parent against working folder (folder diff) params << "kdiff3"; - runner -> startProc(getHgBinaryName(), workFolderPath, params, false); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_FOLDERDIFF; } } @@ -452,7 +458,7 @@ if ((!revA.isEmpty()) && (!revB.isEmpty())) { params << "kdiff3" << "--rev" << revA << "--rev" << revB; - runner -> startProc(getHgBinaryName(), workFolderPath, params, false); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_CHGSETDIFF; } else @@ -474,7 +480,7 @@ params << "update"; - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_UPDATE; } } @@ -494,7 +500,7 @@ params << "update" << "--rev" << rev << "--clean"; - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_UPDATE; } @@ -510,7 +516,7 @@ params << "revert" << "--no-backup" << "--" << currentFile.mid(2); - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_REVERT; } } @@ -522,7 +528,7 @@ QStringList params; params << "resolve" << "--all"; - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_RETRY_MERGE; } } @@ -536,7 +542,7 @@ params << "merge"; - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_MERGE; } } @@ -550,7 +556,7 @@ params << "clone" << remoteRepoPath << workFolderPath; - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_CLONEFROMREMOTE; } } @@ -564,7 +570,7 @@ params << "init"; - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_INIT; } } @@ -578,7 +584,7 @@ params << "incoming" << "--newest-first" << remoteRepoPath; - runner -> startProc(getHgBinaryName(), workFolderPath, params, false); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_INCOMING; } } @@ -592,7 +598,7 @@ params << "pull" << remoteRepoPath; - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_PULL; } } @@ -606,7 +612,7 @@ params << "push" << remoteRepoPath; - runner -> startProc(getHgBinaryName(), workFolderPath, params); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_PUSH; } } @@ -652,11 +658,11 @@ QTextStream(&msg) << "Server running on address(es) (" << addrs << "), port 8000"; params << "serve"; - runner -> startProc(getHgBinaryName(), workFolderPath, params, false); + runner -> startHgCommand(workFolderPath, params); runningAction = ACT_SERVE; QMessageBox::information(this, "Serve", msg, QMessageBox::Close); - runner -> killProc(); + runner -> killCurrentCommand(); } } @@ -893,14 +899,19 @@ } -void MainWindow::timerEvent(QTimerEvent *) +void MainWindow::commandFailed() +{ + DEBUG << "MainWindow::commandFailed" << endl; +} + +void MainWindow::commandCompleted() { bool shouldHgStat = false; if (runningAction != ACT_NONE) { //We are running some hg command... - if (runner -> isProcRunning() == false) + if (runner -> isCommandRunning() == false) { //Running has just ended. int exitCode = runner -> getExitCode(); diff -r bf57a16315bd -r 68aebc316898 mainwindow.h --- a/mainwindow.h Wed Nov 17 11:48:58 2010 +0000 +++ b/mainwindow.h Wed Nov 17 13:32:56 2010 +0000 @@ -85,11 +85,12 @@ protected: void closeEvent(QCloseEvent *event); - void timerEvent(QTimerEvent *event); public slots: void hgStat(); void tabChanged(int currTab); + void commandCompleted(); + void commandFailed(); private slots: void about(); @@ -186,7 +187,6 @@ QToolBar *repoToolBar; QToolBar *workFolderToolBar; - int timerId; HGACTIONS runningAction; HgRunner *runner;