Mercurial > hg > easyhg
view src/common.cpp @ 571:012ba1b83328
Show cancel button with progress bar only when running an operation that it makes sense to cancel (we don't really want people cancelling e.g. initial folder scan because it would leave things in an inconsistent state)
author | Chris Cannam |
---|---|
date | Thu, 01 Mar 2012 22:53:54 +0000 |
parents | 533519ebc0cb |
children | ae67ea0af696 |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* EasyMercurial Based on HgExplorer by Jari Korhonen Copyright (c) 2010 Jari Korhonen Copyright (c) 2012 Chris Cannam Copyright (c) 2012 Queen Mary, University of London This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #include "common.h" #include "debug.h" #include <QFileInfo> #include <QProcessEnvironment> #include <QStringList> #include <QDir> #include <QRegExp> #include <sys/types.h> #ifdef Q_OS_WIN32 #define _WIN32_WINNT 0x0500 #define SECURITY_WIN32 #include <windows.h> #include <security.h> #include <process.h> #else #include <errno.h> #include <pwd.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <signal.h> #include <stdio.h> #endif QString findInPath(QString name, QString installPath, bool executableRequired) { bool found = false; if (name != "") { if (name[0] != '/' #ifdef Q_OS_WIN32 && (QRegExp("^\\w:").indexIn(name) != 0) #endif ) { #ifdef Q_OS_WIN32 QChar pathSep = ';'; #else QChar pathSep = ':'; #endif name = QFileInfo(name).fileName(); QString path = QProcessEnvironment::systemEnvironment().value("PATH"); DEBUG << "findInPath: seeking location for binary " << name << ": system path is " << path << endl; if (installPath != "") { DEBUG << "findInPath: install path is " << installPath << ", adding to system path" << endl; //!!! path = path + pathSep + installPath; path = installPath + pathSep + path; } #ifndef Q_OS_WIN32 //!!! path = path + ":/usr/local/bin"; DEBUG << "... adding /usr/local/bin just in case (fix and add settings dlg please)" << endl; #endif QStringList elements = path.split(pathSep, QString::SkipEmptyParts); foreach (QString element, elements) { QString full = QDir(element).filePath(name); QFileInfo fi(full); DEBUG << "findInPath: looking at " << full << endl; if (fi.exists() && fi.isFile()) { DEBUG << "findInPath: it's a file" << endl; if (!executableRequired || fi.isExecutable()) { name = full; DEBUG << "findInPath: found at " << name << endl; found = true; break; } } } } else { // absolute path given QFileInfo fi(name); DEBUG << "findInPath: looking at absolute path " << name << endl; if (fi.exists() && fi.isFile()) { DEBUG << "findInPath: it's a file" << endl; if (!executableRequired || fi.isExecutable()) { DEBUG << "findInPath: found at " << name << endl; found = true; } } } } #ifdef Q_OS_WIN32 if (!found) { if (!name.endsWith(".exe")) { return findInPath(name + ".exe", installPath, executableRequired); } } #endif if (found) { return name; } else { return ""; } } #ifdef Q_OS_WIN32 QString getUserRealName() { TCHAR buf[1024]; long unsigned int maxlen = 1000; LPTSTR info = buf; if (!GetUserNameEx(NameDisplay, info, &maxlen)) { DEBUG << "GetUserNameEx failed: " << GetLastError() << endl; return ""; } #ifdef UNICODE return QString::fromUtf16((const unsigned short *)info); #else return QString::fromLocal8Bit(info); #endif } #else #ifdef 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 #endif void loseControllingTerminal() { #ifndef Q_OS_WIN32 if (!isatty(0)) { DEBUG << "stdin is not a terminal" << endl; } else { DEBUG << "stdin is a terminal, detaching from it" << endl; if (ioctl(0, TIOCNOTTY, NULL) < 0) { perror("ioctl failed"); DEBUG << "ioctl for TIOCNOTTY on stdin failed (errno = " << errno << ")" << endl; } else { DEBUG << "ioctl for TIOCNOTTY on stdin succeeded" << endl; return; } } int ttyfd = open("/dev/tty", O_RDWR); if (ttyfd < 0) { DEBUG << "failed to open controlling terminal" << endl; } else { if (ioctl(ttyfd, TIOCNOTTY, NULL) < 0) { perror("ioctl failed"); DEBUG << "ioctl for TIOCNOTTY on controlling terminal failed (errno = " << errno << ")" << endl; } else { DEBUG << "ioctl for TIOCNOTTY on controlling terminal succeeded" << endl; return; } } #endif } void installSignalHandlers() { #ifndef Q_OS_WIN32 sigset_t sgnals; sigemptyset (&sgnals); sigaddset(&sgnals, SIGHUP); sigaddset(&sgnals, SIGCONT); pthread_sigmask(SIG_BLOCK, &sgnals, 0); #endif } ProcessStatus GetProcessStatus(int pid) { #ifdef _WIN32 HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); if (!handle) { return ProcessNotRunning; } else { CloseHandle(handle); return ProcessRunning; } #else if (kill(getpid(), 0) == 0) { if (kill(pid, 0) == 0) { return ProcessRunning; } else { return ProcessNotRunning; } } else { return UnknownProcessStatus; } #endif } FolderStatus getFolderStatus(QString path) { if (path != "/" && path.endsWith("/")) { path = path.left(path.length()-1); } DEBUG << "getFolderStatus: " << path << endl; QFileInfo fi(path); if (fi.exists()) { DEBUG << "exists" << endl; QDir dir(path); if (!dir.exists()) { // returns false for files DEBUG << "not directory" << endl; return FolderIsFile; } if (QDir(dir.filePath(".hg")).exists()) { DEBUG << "has repo" << endl; return FolderHasRepo; } return FolderExists; } else { QDir parent = fi.dir(); if (parent.exists()) { DEBUG << "parent exists" << endl; return FolderParentExists; } return FolderUnknown; } } QString getContainingRepoFolder(QString path) { if (getFolderStatus(path) == FolderHasRepo) return ""; QFileInfo me(path); QFileInfo parent(me.dir().absolutePath()); while (me != parent) { QString parentPath = parent.filePath(); if (getFolderStatus(parentPath) == FolderHasRepo) { return parentPath; } me = parent; parent = me.dir().absolutePath(); } return ""; } QString xmlEncode(QString s) { s .replace("&", "&") .replace("<", "<") .replace(">", ">") .replace("\"", """) .replace("'", "'"); return s; } QString uniDecode(QString s) { QString d; for (int i = 0; i < s.length(); ++i) { // backslash escaped with another backslash: replace with a // single backslash and skip on if (i+1 < s.length() && s[i] == '\\' && s[i+1] == '\\') { d += '\\'; i += 1; continue; } // unescaped backslash followed by u and at least four more // chars: replace with Unicode character if (i+5 < s.length() && s[i] == '\\' && s[i+1] == 'u') { QString uni = s.mid(i+2, 4); QByteArray ba = QByteArray::fromHex(uni.toAscii()); d += QChar(ba[1], ba[0]); i += 5; continue; } // default case: leave alone d += s[i]; } return d; } QByteArray randomKey() { static int len = 16; QByteArray ba; ba.resize(len); char *buffer = ba.data(); #ifdef Q_OS_WIN32 HCRYPTPROV provider = 0; if (!CryptAcquireContextW(&provider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { return QByteArray(); } if (!CryptGenRandom(provider, len, (BYTE *)buffer)) { CryptReleaseContext(provider, 0); return QByteArray(); } CryptReleaseContext(provider, 0); #else FILE *rf = fopen("/dev/urandom", "r"); if (!rf) { return QByteArray(); } for (int i = 0; i < len; ++i) { buffer[i] = fgetc(rf); } fclose(rf); #endif return ba; }