Warning, file /sdk/cervisia/misc.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  *  Copyright (C) 1999-2002 Bernd Gehrmann
0003  *                          bernd@mail.berlios.de
0004  *  Copyright (c) 2003 Christian Loose <christian.loose@hamburg.de>
0005  *
0006  * This program is free software; you can redistribute it and/or modify
0007  * it under the terms of the GNU General Public License as published by
0008  * the Free Software Foundation; either version 2 of the License, or
0009  * (at your option) any later version.
0010  *
0011  * This program is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014  * GNU General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU General Public License
0017  * along with this program; if not, write to the Free Software
0018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
0019  */
0020 
0021 #include "misc.h"
0022 #include "debug.h"
0023 
0024 #include <KLocalizedString>
0025 #include <QTemporaryFile>
0026 #include <cctype>
0027 #include <kemailsettings.h>
0028 #include <kmessagebox.h>
0029 #include <kuser.h>
0030 #include <pwd.h>
0031 #include <qfile.h>
0032 #include <qfileinfo.h>
0033 #include <qregexp.h>
0034 #include <qstringlist.h>
0035 #include <sys/types.h>
0036 #include <unistd.h>
0037 
0038 #include "cvsserviceinterface.h"
0039 #include "progressdialog.h"
0040 
0041 // These regular expression parts aren't useful to check the validity of the
0042 // CVSROOT specification. They are just used to extract the different parts of it.
0043 static const QString userNameRegExp("([a-z0-9_][a-z0-9_-.]*)?");
0044 static const QString passwordRegExp("(:[^@]+)?");
0045 static const QString hostNameRegExp("([^:/@]+)");
0046 static const QString portRegExp("(:(\\d*))?");
0047 static const QString pathRegExp("(/.*)");
0048 
0049 static int FindWhiteSpace(const QString &str, int index)
0050 {
0051     const int length = str.length();
0052 
0053     if (index < 0)
0054         index += length;
0055 
0056     if (index < 0 || index >= length)
0057         return -1;
0058 
0059     const QChar *const startPos = str.unicode();
0060     const QChar *const endPos = startPos + length;
0061 
0062     const QChar *pos = startPos + index;
0063     while (pos < endPos && !pos->isSpace())
0064         ++pos;
0065 
0066     const int foundIndex = pos - startPos;
0067     return (foundIndex < length ? foundIndex : -1);
0068 }
0069 
0070 static const QStringList FetchBranchesAndTags(const QString &searchedType, OrgKdeCervisia5CvsserviceCvsserviceInterface *cvsService, QWidget *parent)
0071 {
0072     QStringList branchOrTagList;
0073 
0074     QDBusReply<QDBusObjectPath> job = cvsService->status(QStringList(), true, true);
0075     if (!job.isValid())
0076         return branchOrTagList;
0077 
0078     ProgressDialog dlg(parent, "Status", cvsService->service(), job, QString(), i18n("CVS Status"));
0079 
0080     if (dlg.execute()) {
0081         QString line;
0082         while (dlg.getLine(line)) {
0083             int wsPos, bracketPos, colonPos;
0084 
0085             if (line.isEmpty() || line[0] != '\t')
0086                 continue;
0087             if ((wsPos = FindWhiteSpace(line, 2)) < 0)
0088                 continue;
0089             if ((bracketPos = line.indexOf('(', wsPos + 1)) < 0)
0090                 continue;
0091             if ((colonPos = line.indexOf(':', bracketPos + 1)) < 0)
0092                 continue;
0093 
0094             const QString tag = line.mid(1, wsPos - 1);
0095             const QString type = line.mid(bracketPos + 1, colonPos - bracketPos - 1);
0096             if (type == searchedType && !branchOrTagList.contains(tag))
0097                 branchOrTagList.push_back(tag);
0098         }
0099 
0100         branchOrTagList.sort();
0101     }
0102 
0103     return branchOrTagList;
0104 }
0105 
0106 bool Cervisia::IsValidTag(const QString &tag)
0107 {
0108     static const QString prohibitedChars("$,.:;@");
0109 
0110     if (!isalpha(tag[0].toLatin1()))
0111         return false;
0112 
0113     for (int i = 1; i < tag.length(); ++i) {
0114         if (!isgraph(tag[i].toLatin1()) || prohibitedChars.contains(tag[i]))
0115             return false;
0116     }
0117 
0118     return true;
0119 }
0120 
0121 QString Cervisia::UserName()
0122 {
0123     // 1. Try to retrieve the information from the control center settings
0124     KEMailSettings settings;
0125     QString name = settings.getSetting(KEMailSettings::RealName);
0126     QString email = settings.getSetting(KEMailSettings::EmailAddress);
0127 
0128     if (name.isEmpty() || email.isEmpty()) {
0129         // 2. Try to retrieve the information from the system
0130         struct passwd *pw = getpwuid(getuid());
0131         if (!pw)
0132             return {};
0133 
0134         char hostname[512];
0135         hostname[0] = '\0';
0136 
0137         if (!gethostname(hostname, sizeof(hostname)))
0138             hostname[sizeof(hostname) - 1] = '0';
0139 
0140         name = QString::fromLocal8Bit(pw->pw_gecos);
0141         email = QString::fromLocal8Bit(pw->pw_name) + '@' + QString::fromLocal8Bit(hostname);
0142     }
0143 
0144     QString result = name;
0145     result += "  <";
0146     result += email;
0147     result += '>';
0148 
0149     return result;
0150 }
0151 
0152 QString Cervisia::NormalizeRepository(const QString &repository)
0153 {
0154     // only :pserver: repositories
0155     if (!repository.startsWith(QLatin1String(":pserver:")))
0156         return repository;
0157 
0158     QRegExp rx(":pserver:(" + userNameRegExp + passwordRegExp + "@)?" + hostNameRegExp + portRegExp + pathRegExp);
0159 
0160     // extract username, hostname, port and path from CVSROOT
0161     QString userName, hostName, port, path;
0162     if (repository.contains(rx)) {
0163         userName = rx.cap(2);
0164         hostName = rx.cap(4);
0165         port = rx.cap(6);
0166         path = rx.cap(7);
0167 
0168         qCDebug(log_cervisia) << "username=" << userName;
0169         qCDebug(log_cervisia) << "hostname=" << hostName;
0170         qCDebug(log_cervisia) << "port    =" << port;
0171         qCDebug(log_cervisia) << "path    =" << path;
0172 
0173         if (port.isEmpty())
0174             port = "2401";
0175 
0176         if (userName.isEmpty())
0177             userName = KUser().loginName();
0178 
0179         QString canonicalForm = ":pserver:" + userName + '@' + hostName + ':' + port + path;
0180 
0181         qCDebug(log_cervisia) << "canonicalForm=" << canonicalForm << endl;
0182         return canonicalForm;
0183     } else
0184         return repository;
0185 }
0186 
0187 bool Cervisia::CheckOverwrite(const QString &fileName, QWidget *parent)
0188 {
0189     bool result = true;
0190 
0191     QFileInfo fi(fileName);
0192 
0193     // does the file already exist?
0194     if (fi.exists()) {
0195         KGuiItem overwriteItem = KStandardGuiItem::overwrite();
0196         overwriteItem.setIconName("document-save");
0197         overwriteItem.setToolTip(i18n("Overwrite the file"));
0198 
0199         result = (KMessageBox::warningContinueCancel(parent,
0200                                                      i18n("A file named \"%1\" already exists. Are you sure you want to overwrite it?", fileName),
0201                                                      i18n("Overwrite File?"),
0202                                                      overwriteItem)
0203                   == KMessageBox::Continue);
0204     }
0205 
0206     return result;
0207 }
0208 
0209 // Should be replaceable by QStringList::split
0210 QStringList splitLine(QString line, char delim)
0211 {
0212     int pos;
0213     QStringList list;
0214 
0215     line = line.simplified();
0216     while ((pos = line.indexOf(delim)) != -1) {
0217         list.append(line.left(pos));
0218         line = line.mid(pos + 1, line.length() - pos - 1);
0219     }
0220     if (!line.isEmpty())
0221         list.append(line);
0222     return list;
0223 }
0224 
0225 const QStringList fetchBranches(OrgKdeCervisia5CvsserviceCvsserviceInterface *cvsService, QWidget *parent)
0226 {
0227     return FetchBranchesAndTags(QLatin1String("branch"), cvsService, parent);
0228 }
0229 
0230 const QStringList fetchTags(OrgKdeCervisia5CvsserviceCvsserviceInterface *cvsService, QWidget *parent)
0231 {
0232     return FetchBranchesAndTags(QLatin1String("revision"), cvsService, parent);
0233 }
0234 
0235 static QStringList *tempFiles = 0;
0236 
0237 void cleanupTempFiles()
0238 {
0239     if (tempFiles) {
0240         QStringList::Iterator it;
0241         for (it = tempFiles->begin(); it != tempFiles->end(); ++it)
0242             QFile::remove(*it);
0243         delete tempFiles;
0244     }
0245 }
0246 
0247 QString tempFileName(const QString &suffix)
0248 {
0249     if (!tempFiles)
0250         tempFiles = new QStringList;
0251 
0252     QTemporaryFile f(QDir::tempPath() + QLatin1String("/cervisia_XXXXXX") + suffix);
0253     f.setAutoRemove(false);
0254     f.open();
0255     tempFiles->append(f.fileName());
0256     return f.fileName();
0257 }
0258 
0259 int compareRevisions(const QString &rev1, const QString &rev2)
0260 {
0261     const int length1(rev1.length());
0262     const int length2(rev2.length());
0263 
0264     // compare all parts of the revision
0265 
0266     int startPos1(0);
0267     int startPos2(0);
0268     while (startPos1 < length1 && startPos2 < length2) {
0269         int pos1(rev1.indexOf('.', startPos1));
0270         if (pos1 < 0)
0271             pos1 = length1;
0272         const int partLength1(pos1 - startPos1);
0273 
0274         int pos2(rev2.indexOf('.', startPos2));
0275         if (pos2 < 0)
0276             pos2 = length2;
0277         const int partLength2(pos2 - startPos2);
0278 
0279         // if the number of digits in both parts is not equal we are ready
0280         if (const int comp = ::compare(partLength1, partLength2))
0281             return comp;
0282 
0283         // if the parts are not equal we are ready
0284         if (const int comp = ::compare(rev1.mid(startPos1, partLength1), rev2.mid(startPos2, partLength2)))
0285             return comp;
0286 
0287         // continue with next part
0288         startPos1 = pos1 + 1;
0289         startPos2 = pos2 + 1;
0290     }
0291 
0292     // rev1 has more parts than rev2: rev2 < rev1
0293     if (startPos1 < length1)
0294         return 1;
0295     // rev2 has more parts than rev1: rev1 < rev2
0296     else if (startPos2 < length2)
0297         return -1;
0298     // all parts of rev1 and rev2 were compared (the number of parts is equal): rev1 == rev2
0299     else
0300         return 0;
0301 }
0302 
0303 // Local Variables:
0304 // c-basic-offset: 4
0305 // End: