~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to tools/configure/environment.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
 
4
** All rights reserved.
 
5
** Contact: Nokia Corporation (qt-info@nokia.com)
 
6
**
 
7
** This file is part of the tools applications of the Qt Toolkit.
 
8
**
 
9
** $QT_BEGIN_LICENSE:LGPL$
 
10
** No Commercial Usage
 
11
** This file contains pre-release code and may not be distributed.
 
12
** You may use this file in accordance with the terms and conditions
 
13
** contained in the Technology Preview License Agreement accompanying
 
14
** this package.
 
15
**
 
16
** GNU Lesser General Public License Usage
 
17
** Alternatively, this file may be used under the terms of the GNU Lesser
 
18
** General Public License version 2.1 as published by the Free Software
 
19
** Foundation and appearing in the file LICENSE.LGPL included in the
 
20
** packaging of this file.  Please review the following information to
 
21
** ensure the GNU Lesser General Public License version 2.1 requirements
 
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
23
**
 
24
** In addition, as a special exception, Nokia gives you certain additional
 
25
** rights.  These rights are described in the Nokia Qt LGPL Exception
 
26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
27
**
 
28
** If you have questions regarding the use of this file, please contact
 
29
** Nokia at qt-info@nokia.com.
 
30
**
 
31
**
 
32
**
 
33
**
 
34
**
 
35
**
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include "environment.h"
 
43
 
 
44
#include <process.h>
 
45
#include <iostream>
 
46
#include <qdebug.h>
 
47
#include <QDir>
 
48
#include <QStringList>
 
49
#include <QMap>
 
50
#include <QDir>
 
51
#include <QFile>
 
52
#include <QFileInfo>
 
53
 
 
54
//#define CONFIGURE_DEBUG_EXECUTE
 
55
//#define CONFIGURE_DEBUG_CP_DIR
 
56
 
 
57
using namespace std;
 
58
 
 
59
#ifdef Q_OS_WIN32
 
60
#include <qt_windows.h>
 
61
#endif
 
62
 
 
63
 
 
64
QT_BEGIN_NAMESPACE
 
65
 
 
66
struct CompilerInfo{
 
67
    Compiler compiler;
 
68
    const char *compilerStr;
 
69
    const char *regKey;
 
70
    const char *executable;
 
71
} compiler_info[] = {
 
72
    // The compilers here are sorted in a reversed-preferred order
 
73
    {CC_BORLAND, "Borland C++",                                                    0, "bcc32.exe"},
 
74
    {CC_MINGW,   "MinGW (Minimalist GNU for Windows)",                             0, "mingw32-gcc.exe"},
 
75
    {CC_INTEL,   "Intel(R) C++ Compiler for 32-bit applications",                  0, "icl.exe"}, // xilink.exe, xilink5.exe, xilink6.exe, xilib.exe
 
76
    {CC_MSVC6,   "Microsoft (R) 32-bit C/C++ Optimizing Compiler (6.x)",           "Software\\Microsoft\\VisualStudio\\6.0\\Setup\\Microsoft Visual C++\\ProductDir", "cl.exe"}, // link.exe, lib.exe
 
77
    {CC_NET2002, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2002 (7.0)",  "Software\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir", "cl.exe"}, // link.exe, lib.exe
 
78
    {CC_NET2003, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2003 (7.1)",  "Software\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir", "cl.exe"}, // link.exe, lib.exe
 
79
    {CC_NET2005, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2005 (8.0)",  "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\8.0", "cl.exe"}, // link.exe, lib.exe
 
80
    {CC_NET2008, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2008 (9.0)",  "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\9.0", "cl.exe"}, // link.exe, lib.exe
 
81
    {CC_UNKNOWN, "Unknown", 0, 0},
 
82
};
 
83
 
 
84
 
 
85
// Initialize static variables
 
86
Compiler Environment::detectedCompiler = CC_UNKNOWN;
 
87
 
 
88
/*!
 
89
    Returns the pointer to the CompilerInfo for a \a compiler.
 
90
*/
 
91
CompilerInfo *Environment::compilerInfo(Compiler compiler)
 
92
{
 
93
    int i = 0;
 
94
    while(compiler_info[i].compiler != compiler && compiler_info[i].compiler != CC_UNKNOWN)
 
95
        ++i;
 
96
    return &(compiler_info[i]);
 
97
}
 
98
 
 
99
/*!
 
100
    Returns the path part of a registry key.
 
101
    Ei.
 
102
        For a key
 
103
            "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"
 
104
        it returns
 
105
            "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\"
 
106
*/
 
107
QString Environment::keyPath(const QString &rKey)
 
108
{
 
109
    int idx = rKey.lastIndexOf(QLatin1Char('\\'));
 
110
    if (idx == -1)
 
111
        return QString();
 
112
    return rKey.left(idx + 1);
 
113
}
 
114
 
 
115
/*!
 
116
    Returns the name part of a registry key.
 
117
    Ei.
 
118
        For a key
 
119
            "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"
 
120
        it returns
 
121
            "ProductDir"
 
122
*/
 
123
QString Environment::keyName(const QString &rKey)
 
124
{
 
125
    int idx = rKey.lastIndexOf(QLatin1Char('\\'));
 
126
    if (idx == -1)
 
127
        return rKey;
 
128
 
 
129
    QString res(rKey.mid(idx + 1));
 
130
    if (res == "Default" || res == ".")
 
131
        res = "";
 
132
    return res;
 
133
}
 
134
 
 
135
/*!
 
136
    Returns a registry keys value in string form.
 
137
    If the registry key does not exist, or cannot be accessed, a
 
138
    QString() is returned.
 
139
*/
 
140
QString Environment::readRegistryKey(HKEY parentHandle, const QString &rSubkey)
 
141
{
 
142
#ifndef Q_OS_WIN32
 
143
    return QString();
 
144
#else
 
145
    QString rSubkeyName = keyName(rSubkey);
 
146
    QString rSubkeyPath = keyPath(rSubkey);
 
147
 
 
148
    HKEY handle = 0;
 
149
    LONG res = RegOpenKeyEx(parentHandle, (wchar_t*)rSubkeyPath.utf16(), 0, KEY_READ, &handle);
 
150
    if (res != ERROR_SUCCESS)
 
151
        return QString();
 
152
 
 
153
    // get the size and type of the value
 
154
    DWORD dataType;
 
155
    DWORD dataSize;
 
156
    res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), 0, &dataType, 0, &dataSize);
 
157
    if (res != ERROR_SUCCESS) {
 
158
        RegCloseKey(handle);
 
159
        return QString();
 
160
    }
 
161
 
 
162
    // get the value
 
163
    QByteArray data(dataSize, 0);
 
164
    res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), 0, 0,
 
165
                           reinterpret_cast<unsigned char*>(data.data()), &dataSize);
 
166
    if (res != ERROR_SUCCESS) {
 
167
        RegCloseKey(handle);
 
168
        return QString();
 
169
    }
 
170
 
 
171
    QString result;
 
172
    switch (dataType) {
 
173
        case REG_EXPAND_SZ:
 
174
        case REG_SZ: {
 
175
            result = QString::fromWCharArray(((const wchar_t *)data.constData()));
 
176
            break;
 
177
        }
 
178
 
 
179
        case REG_MULTI_SZ: {
 
180
            QStringList l;
 
181
            int i = 0;
 
182
            for (;;) {
 
183
                QString s = QString::fromWCharArray((const wchar_t *)data.constData() + i);
 
184
                i += s.length() + 1;
 
185
 
 
186
                if (s.isEmpty())
 
187
                    break;
 
188
                l.append(s);
 
189
            }
 
190
            result = l.join(", ");
 
191
            break;
 
192
        }
 
193
 
 
194
        case REG_NONE:
 
195
        case REG_BINARY: {
 
196
            result = QString::fromWCharArray((const wchar_t *)data.constData(), data.size() / 2);
 
197
            break;
 
198
        }
 
199
 
 
200
        case REG_DWORD_BIG_ENDIAN:
 
201
        case REG_DWORD: {
 
202
            Q_ASSERT(data.size() == sizeof(int));
 
203
            int i;
 
204
            memcpy((char*)&i, data.constData(), sizeof(int));
 
205
            result = QString::number(i);
 
206
            break;
 
207
        }
 
208
 
 
209
        default:
 
210
            qWarning("QSettings: unknown data %d type in windows registry", dataType);
 
211
            break;
 
212
    }
 
213
 
 
214
    RegCloseKey(handle);
 
215
    return result;
 
216
#endif
 
217
}
 
218
 
 
219
/*!
 
220
    Returns the qmakespec for the compiler detected on the system.
 
221
*/
 
222
QString Environment::detectQMakeSpec()
 
223
{
 
224
    QString spec;
 
225
    switch (detectCompiler()) {
 
226
    case CC_NET2008:
 
227
        spec = "win32-msvc2008";
 
228
        break;
 
229
    case CC_NET2005:
 
230
        spec = "win32-msvc2005";
 
231
        break;
 
232
    case CC_NET2003:
 
233
        spec = "win32-msvc2003";
 
234
        break;
 
235
    case CC_NET2002:
 
236
        spec = "win32-msvc2002";
 
237
        break;
 
238
    case CC_MSVC4:
 
239
    case CC_MSVC5:
 
240
    case CC_MSVC6:
 
241
        spec = "win32-msvc";
 
242
        break;
 
243
    case CC_INTEL:
 
244
        spec = "win32-icc";
 
245
        break;
 
246
    case CC_MINGW:
 
247
        spec = "win32-g++";
 
248
        break;
 
249
    case CC_BORLAND:
 
250
        spec = "win32-borland";
 
251
        break;
 
252
    default:
 
253
        break;
 
254
    }
 
255
 
 
256
    return spec;
 
257
}
 
258
 
 
259
/*!
 
260
    Returns the enum of the compiler which was detected on the system.
 
261
    The compilers are detected in the order as entered into the
 
262
    compiler_info list.
 
263
 
 
264
    If more than one compiler is found, CC_UNKNOWN is returned.
 
265
*/
 
266
Compiler Environment::detectCompiler()
 
267
{
 
268
#ifndef Q_OS_WIN32
 
269
    return MSVC6; // Always generate MSVC 6.0 versions on other platforms
 
270
#else
 
271
    if(detectedCompiler != CC_UNKNOWN)
 
272
        return detectedCompiler;
 
273
 
 
274
    int installed = 0;
 
275
 
 
276
    // Check for compilers in registry first, to see which version is in PATH
 
277
    QString paths = qgetenv("PATH");
 
278
    QStringList pathlist = paths.toLower().split(";");
 
279
    for(int i = 0; compiler_info[i].compiler; ++i) {
 
280
        QString productPath = readRegistryKey(HKEY_LOCAL_MACHINE, compiler_info[i].regKey).toLower();
 
281
        if (productPath.length()) {
 
282
            QStringList::iterator it;
 
283
            for(it = pathlist.begin(); it != pathlist.end(); ++it) {
 
284
                if((*it).contains(productPath)) {
 
285
                    ++installed;
 
286
                    detectedCompiler = compiler_info[i].compiler;
 
287
                    break;
 
288
                }
 
289
            }
 
290
        }
 
291
    }
 
292
 
 
293
    // Now just go looking for the executables, and accept any executable as the lowest version
 
294
    if (!installed) {
 
295
        for(int i = 0; compiler_info[i].compiler; ++i) {
 
296
            QString executable = QString(compiler_info[i].executable).toLower();
 
297
            if (executable.length() && Environment::detectExecutable(executable)) {
 
298
                ++installed;
 
299
                detectedCompiler = compiler_info[i].compiler;
 
300
                break;
 
301
            }
 
302
        }
 
303
    }
 
304
 
 
305
    if (installed > 1) {
 
306
        cout << "Found more than one known compiler! Using \"" << compilerInfo(detectedCompiler)->compilerStr << "\"" << endl;
 
307
        detectedCompiler = CC_UNKNOWN;
 
308
    }
 
309
    return detectedCompiler;
 
310
#endif
 
311
};
 
312
 
 
313
/*!
 
314
    Returns true if the \a executable could be loaded, else false.
 
315
    This means that the executable either is in the current directory
 
316
    or in the PATH.
 
317
*/
 
318
bool Environment::detectExecutable(const QString &executable)
 
319
{
 
320
    PROCESS_INFORMATION procInfo;
 
321
    memset(&procInfo, 0, sizeof(procInfo));
 
322
 
 
323
    STARTUPINFO startInfo;
 
324
    memset(&startInfo, 0, sizeof(startInfo));
 
325
    startInfo.cb = sizeof(startInfo);
 
326
 
 
327
    bool couldExecute = CreateProcess(0, (wchar_t*)executable.utf16(),
 
328
                                      0, 0, false,
 
329
                                      CREATE_NO_WINDOW | CREATE_SUSPENDED,
 
330
                                      0, 0, &startInfo, &procInfo);
 
331
 
 
332
    if (couldExecute) {
 
333
        CloseHandle(procInfo.hThread);
 
334
        TerminateProcess(procInfo.hProcess, 0);
 
335
        CloseHandle(procInfo.hProcess);
 
336
    }
 
337
    return couldExecute;
 
338
}
 
339
 
 
340
/*!
 
341
    Creates a commandling from \a program and it \a arguments,
 
342
    escaping characters that needs it.
 
343
*/
 
344
static QString qt_create_commandline(const QString &program, const QStringList &arguments)
 
345
{
 
346
    QString programName = program;
 
347
    if (!programName.startsWith("\"") && !programName.endsWith("\"") && programName.contains(" "))
 
348
        programName = "\"" + programName + "\"";
 
349
    programName.replace("/", "\\");
 
350
 
 
351
    QString args;
 
352
    // add the prgram as the first arrg ... it works better
 
353
    args = programName + " ";
 
354
    for (int i=0; i<arguments.size(); ++i) {
 
355
        QString tmp = arguments.at(i);
 
356
        // in the case of \" already being in the string the \ must also be escaped
 
357
        tmp.replace( "\\\"", "\\\\\"" );
 
358
        // escape a single " because the arguments will be parsed
 
359
        tmp.replace( "\"", "\\\"" );
 
360
        if (tmp.isEmpty() || tmp.contains(' ') || tmp.contains('\t')) {
 
361
            // The argument must not end with a \ since this would be interpreted
 
362
            // as escaping the quote -- rather put the \ behind the quote: e.g.
 
363
            // rather use "foo"\ than "foo\"
 
364
            QString endQuote("\"");
 
365
            int i = tmp.length();
 
366
            while (i>0 && tmp.at(i-1) == '\\') {
 
367
                --i;
 
368
                endQuote += "\\";
 
369
            }
 
370
            args += QString(" \"") + tmp.left(i) + endQuote;
 
371
        } else {
 
372
            args += ' ' + tmp;
 
373
        }
 
374
    }
 
375
    return args;
 
376
}
 
377
 
 
378
/*!
 
379
    Creates a QByteArray of the \a environment.
 
380
*/
 
381
static QByteArray qt_create_environment(const QStringList &environment)
 
382
{
 
383
    QByteArray envlist;
 
384
    if (environment.isEmpty())
 
385
        return envlist;
 
386
 
 
387
    int pos = 0;
 
388
    // add PATH if necessary (for DLL loading)
 
389
    QByteArray path = qgetenv("PATH");
 
390
    if (environment.filter(QRegExp("^PATH=",Qt::CaseInsensitive)).isEmpty() && !path.isNull()) {
 
391
            QString tmp = QString(QLatin1String("PATH=%1")).arg(QString::fromLocal8Bit(path));
 
392
            uint tmpSize = sizeof(wchar_t) * (tmp.length() + 1);
 
393
            envlist.resize(envlist.size() + tmpSize);
 
394
            memcpy(envlist.data() + pos, tmp.utf16(), tmpSize);
 
395
            pos += tmpSize;
 
396
    }
 
397
    // add the user environment
 
398
    for (QStringList::ConstIterator it = environment.begin(); it != environment.end(); it++ ) {
 
399
            QString tmp = *it;
 
400
            uint tmpSize = sizeof(wchar_t) * (tmp.length() + 1);
 
401
            envlist.resize(envlist.size() + tmpSize);
 
402
            memcpy(envlist.data() + pos, tmp.utf16(), tmpSize);
 
403
            pos += tmpSize;
 
404
    }
 
405
    // add the 2 terminating 0 (actually 4, just to be on the safe side)
 
406
    envlist.resize(envlist.size() + 4);
 
407
    envlist[pos++] = 0;
 
408
    envlist[pos++] = 0;
 
409
    envlist[pos++] = 0;
 
410
    envlist[pos++] = 0;
 
411
 
 
412
    return envlist;
 
413
}
 
414
 
 
415
/*!
 
416
    Executes the command described in \a arguments, in the
 
417
    environment inherited from the parent process, with the
 
418
    \a additionalEnv settings applied.
 
419
    \a removeEnv removes the specified environment variables from
 
420
    the environment of the executed process.
 
421
 
 
422
    Returns the exit value of the process, or -1 if the command could
 
423
    not be executed.
 
424
 
 
425
    This function uses _(w)spawnvpe to spawn a process by searching
 
426
    through the PATH environment variable.
 
427
*/
 
428
int Environment::execute(QStringList arguments, const QStringList &additionalEnv, const QStringList &removeEnv)
 
429
{
 
430
#ifdef CONFIGURE_DEBUG_EXECUTE
 
431
    qDebug() << "About to Execute: " << arguments;
 
432
    qDebug() << "   " << QDir::currentPath();
 
433
    qDebug() << "   " << additionalEnv;
 
434
    qDebug() << "   " << removeEnv;
 
435
#endif
 
436
    // Create the full environment from the current environment and
 
437
    // the additionalEnv strings, then remove all variables defined
 
438
    // in removeEnv
 
439
    QMap<QString, QString> fullEnvMap;
 
440
    LPWSTR envStrings = GetEnvironmentStrings();
 
441
    if (envStrings) {
 
442
        int strLen = 0;
 
443
        for (LPWSTR envString = envStrings; *(envString); envString += strLen + 1) {
 
444
            strLen = wcslen(envString);
 
445
            QString str = QString((const QChar*)envString, strLen);
 
446
            if (!str.startsWith("=")) { // These are added by the system
 
447
                int sepIndex = str.indexOf('=');
 
448
                fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1));
 
449
            }
 
450
        }
 
451
    }
 
452
    FreeEnvironmentStrings(envStrings);
 
453
 
 
454
    // Add additionalEnv variables
 
455
    for (int i = 0; i < additionalEnv.count(); ++i) {
 
456
        const QString &str = additionalEnv.at(i);
 
457
        int sepIndex = str.indexOf('=');
 
458
        fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1));
 
459
    }
 
460
 
 
461
    // Remove removeEnv variables
 
462
    for (int j = 0; j < removeEnv.count(); ++j)
 
463
        fullEnvMap.remove(removeEnv.at(j).toUpper());
 
464
 
 
465
    // Add all variables to a QStringList
 
466
    QStringList fullEnv;
 
467
    QMapIterator<QString, QString> it(fullEnvMap);
 
468
    while (it.hasNext()) {
 
469
        it.next();
 
470
        fullEnv += QString(it.key() + "=" + it.value());
 
471
    }
 
472
 
 
473
    // ----------------------------
 
474
    QString program = arguments.takeAt(0);
 
475
    QString args = qt_create_commandline(program, arguments);
 
476
    QByteArray envlist = qt_create_environment(fullEnv);
 
477
 
 
478
    DWORD exitCode = -1;
 
479
    PROCESS_INFORMATION procInfo;
 
480
    memset(&procInfo, 0, sizeof(procInfo));
 
481
 
 
482
    STARTUPINFO startInfo;
 
483
    memset(&startInfo, 0, sizeof(startInfo));
 
484
    startInfo.cb = sizeof(startInfo);
 
485
 
 
486
    bool couldExecute = CreateProcess(0, (wchar_t*)args.utf16(),
 
487
                                      0, 0, true, CREATE_UNICODE_ENVIRONMENT,
 
488
                                      envlist.isEmpty() ? 0 : envlist.data(),
 
489
                                      0, &startInfo, &procInfo);
 
490
 
 
491
    if (couldExecute) {
 
492
        WaitForSingleObject(procInfo.hProcess, INFINITE);
 
493
        GetExitCodeProcess(procInfo.hProcess, &exitCode);
 
494
        CloseHandle(procInfo.hThread);
 
495
        CloseHandle(procInfo.hProcess);
 
496
    }
 
497
 
 
498
 
 
499
    if (exitCode == -1) {
 
500
        switch(GetLastError()) {
 
501
        case E2BIG:
 
502
            cerr << "execute: Argument list exceeds 1024 bytes" << endl;
 
503
            foreach(QString arg, arguments)
 
504
                cerr << "   (" << arg.toLocal8Bit().constData() << ")" << endl;
 
505
            break;
 
506
        case ENOENT:
 
507
            cerr << "execute: File or path is not found (" << program.toLocal8Bit().constData() << ")" << endl;
 
508
            break;
 
509
        case ENOEXEC:
 
510
            cerr << "execute: Specified file is not executable or has invalid executable-file format (" << program.toLocal8Bit().constData() << ")" << endl;
 
511
            break;
 
512
        case ENOMEM:
 
513
            cerr << "execute: Not enough memory is available to execute new process." << endl;
 
514
            break;
 
515
        default:
 
516
            cerr << "execute: Unknown error" << endl;
 
517
            foreach(QString arg, arguments)
 
518
                cerr << "   (" << arg.toLocal8Bit().constData() << ")" << endl;
 
519
            break;
 
520
        }
 
521
    }
 
522
    return exitCode;
 
523
}
 
524
 
 
525
bool Environment::cpdir(const QString &srcDir, const QString &destDir)
 
526
{
 
527
    QString cleanSrcName = QDir::cleanPath(srcDir);
 
528
    QString cleanDstName = QDir::cleanPath(destDir);
 
529
#ifdef CONFIGURE_DEBUG_CP_DIR
 
530
    qDebug() << "Attempt to cpdir " << cleanSrcName << "->" << cleanDstName;
 
531
#endif
 
532
    if(!QFile::exists(cleanDstName) && !QDir().mkpath(cleanDstName)) {
 
533
        qDebug() << "cpdir: Failure to create " << cleanDstName;
 
534
        return false;
 
535
    }
 
536
 
 
537
    bool result = true;
 
538
    QDir dir = QDir(cleanSrcName);
 
539
    QFileInfoList allEntries = dir.entryInfoList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
 
540
    for (int i = 0; result && (i < allEntries.count()); ++i) {
 
541
        QFileInfo entry = allEntries.at(i);
 
542
        bool intermediate = true;
 
543
        if (entry.isDir()) {
 
544
            intermediate = cpdir(QString("%1/%2").arg(cleanSrcName).arg(entry.fileName()),
 
545
                            QString("%1/%2").arg(cleanDstName).arg(entry.fileName()));
 
546
        } else {
 
547
            QString destFile = QString("%1/%2").arg(cleanDstName).arg(entry.fileName());
 
548
#ifdef CONFIGURE_DEBUG_CP_DIR
 
549
            qDebug() << "About to cp (file)" << entry.absoluteFilePath() << "->" << destFile;
 
550
#endif
 
551
            QFile::remove(destFile);
 
552
            intermediate = QFile::copy(entry.absoluteFilePath(), destFile);
 
553
            SetFileAttributes((wchar_t*)destFile.utf16(), FILE_ATTRIBUTE_NORMAL);
 
554
        }
 
555
        if(!intermediate) {
 
556
            qDebug() << "cpdir: Failure for " << entry.fileName() << entry.isDir();
 
557
            result = false;
 
558
        }
 
559
    }
 
560
    return result;
 
561
}
 
562
 
 
563
bool Environment::rmdir(const QString &name)
 
564
{
 
565
    bool result = true;
 
566
    QString cleanName = QDir::cleanPath(name);
 
567
 
 
568
    QDir dir = QDir(cleanName);
 
569
    QFileInfoList allEntries = dir.entryInfoList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
 
570
    for (int i = 0; result && (i < allEntries.count()); ++i) {
 
571
        QFileInfo entry = allEntries.at(i);
 
572
        if (entry.isDir()) {
 
573
            result &= rmdir(entry.absoluteFilePath());
 
574
        } else {
 
575
            result &= QFile::remove(entry.absoluteFilePath());
 
576
        }
 
577
    }
 
578
    result &= dir.rmdir(cleanName);
 
579
    return result;
 
580
}
 
581
 
 
582
QT_END_NAMESPACE