123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- #include <QDir>
- #include <QFile>
- #include <QFileInfo>
- #include <QList>
- #include <QRegExp>
- #include <QStack>
- #include <QTextStream>
- #include "filecopier.h"
- #include "common/fstraverseiterator.h"
- // THIS IS NOT THE PLACE FOR THIS DEFINE!
- #define TXTSUBST_KWORDREGEXP "@[a-zA-Z]+@"
- FileCopier::FileCopier(const QString & source,
- const QString & destination,
- const QMap<QString, QString> * filenameSubstitutions,
- const QSet<QString> * ignorePatterns,
- const QMap<QString, QString> * keywordSubstitutions,
- GeneratorOutputView & outputView)
- : m_source(source)
- , m_destination(destination)
- , m_filenameSubstitutions(filenameSubstitutions)
- , m_keywordSubstitutions(keywordSubstitutions)
- , m_outputView(outputView)
- , m_keywordRegExp(TXTSUBST_KWORDREGEXP)
- {
- if (ignorePatterns != NULL)
- {
- foreach (QString ignorePattern, *ignorePatterns)
- {
- // TODO should the case sensitivity and wildcard / wildcardunix
- // be made platform dependent too?
- QRegExp
- ignoreRegExp(ignorePattern,
- Qt::CaseSensitive,
- QRegExp::Wildcard);
- m_ignoreRegExps.push_back(ignoreRegExp);
- }
- }
- }
- bool FileCopier::LooksLikeDir(const QFileInfo & file)
- {
- bool
- rv = true;
- if (file.exists())
- {
- rv = file.isDir();
- }
- else
- {
- // path does not exist, so we have to guess
- // based on its look whether it can be thought
- // as a directory
- QString
- path = file.absoluteFilePath();
- bool
- suffixLess = file.suffix().length() == 0,
- hasTrailingDirSeparator = path.at(path.length() - 1) == QDir::separator();
- rv = suffixLess || hasTrailingDirSeparator;
- }
- return rv;
- }
- bool FileCopier::copyFileVerbatim(const QFileInfo & srcFileInfo,
- const QFileInfo & dstFileInfo)
- {
- bool
- rv = true;
- if (dstFileInfo.exists())
- {
- rv = QFile(dstFileInfo.absoluteFilePath()).remove();
- }
- rv = rv && QFile::copy(srcFileInfo.absoluteFilePath(),
- dstFileInfo.absoluteFilePath());
- if (!rv)
- {
- QString
- msg("Error: Could not copy %1 to %2 verbatim.");
- m_outputView.printOutput(msg.arg(srcFileInfo.absoluteFilePath(),
- dstFileInfo.absoluteFilePath()));
- }
- return rv;
- }
- QString FileCopier::substitute(const QString & line)
- {
- QString
- rv = line;
- int
- pos;
- while ((pos = m_keywordRegExp.indexIn(rv)) != -1)
- {
- QString
- key = m_keywordRegExp.cap(0);
- if (m_keywordSubstitutions->contains(key))
- {
- QString
- value = (*m_keywordSubstitutions)[key];
- rv.replace(pos,
- key.length(),
- value);
- }
- else
- {
- QString
- msg("Warning: No substitution defined for keyword '%1'.");
- m_outputView.printOutput(msg.arg(key));
- break;
- }
- }
- return rv;
- }
- bool FileCopier::copyFileSubstituting(const QFileInfo & srcFileInfo,
- const QFileInfo & dstFileInfo)
- {
- bool
- rv = false;
- QFile
- srcFile(srcFileInfo.absoluteFilePath());
- rv = srcFile.open(QIODevice::ReadOnly | QIODevice::Text);
- if (rv)
- {
- QFile
- dstFile(dstFileInfo.absoluteFilePath());
- rv = dstFile.open(QIODevice::WriteOnly | QIODevice::Text);
- if (rv)
- {
- QTextStream
- srcStream(&srcFile);
- QTextStream
- dstStream(&dstFile);
- while (rv && !srcStream.atEnd())
- {
- QString
- line = srcStream.readLine();
- rv = srcStream.status() == QTextStream::Ok;
- if (rv)
- {
- line = substitute(line);
- dstStream << line << endl;
- rv = dstStream.status() == QTextStream::Ok;
- if (!rv)
- {
- QString
- msg("Error: Could not write to %1.");
- m_outputView.printOutput(msg.arg(dstFileInfo.absoluteFilePath()));
- }
- }
- else
- {
- QString
- msg("Error: Could not read from %1.");
- m_outputView.printOutput(msg.arg(srcFileInfo.absoluteFilePath()));
- }
- }
- }
- else
- {
- QString
- msg("Error: Could not open destination %1 for writing.");
- m_outputView.printOutput(msg.arg(dstFileInfo.absoluteFilePath()));
- }
- }
- else
- {
- QString
- msg("Error: Could not open source %1 for reading.");
- m_outputView.printOutput(msg.arg(srcFileInfo.absoluteFilePath()));
- }
- return rv;
- }
- bool FileCopier::fileToBeIgnored(const QFileInfo & dstFileInfo)
- {
- bool
- rv = false;
- QString
- fileName = dstFileInfo.fileName();
- foreach (QRegExp ignoreRegExp, m_ignoreRegExps)
- {
- if ((rv = (ignoreRegExp.indexIn(fileName) != -1)))
- {
- break;
- }
- }
- return rv;
- }
- bool FileCopier::copyFile(const QFileInfo & srcFileInfo,
- const QDir & dstBaseDir)
- {
- QString
- msg("Copying file %1 to directory %2");
- m_outputView.printOutput(msg.arg(srcFileInfo.absoluteFilePath(),
- dstBaseDir.absolutePath()));
- bool
- rv = true;
- // filename substitution, if enabled
- QString
- baseName(srcFileInfo.baseName()),
- suffix(srcFileInfo.suffix());
- if (m_filenameSubstitutions != NULL
- && m_filenameSubstitutions->contains(baseName))
- {
- baseName = (*m_filenameSubstitutions)[baseName];
- }
- QString
- dstFilePath = dstBaseDir.absolutePath();
- dstFilePath += QDir::separator();
- dstFilePath += baseName;
- if (suffix.length() > 0)
- {
- dstFilePath += '.';
- dstFilePath += suffix;
- }
- QFileInfo
- dstFileInfo(dstFilePath);
- if (m_keywordSubstitutions != NULL
- && !m_keywordSubstitutions->empty()
- && !fileToBeIgnored(dstFileInfo))
- {
- rv = copyFileSubstituting(srcFileInfo,
- dstFileInfo);
- }
- else
- {
- rv = copyFileVerbatim(srcFileInfo,
- dstFileInfo);
- }
- return rv;
- }
- bool FileCopier::copyDir(const QDir & srcBaseDir,
- const QDir & dstBaseDir)
- {
- QString
- msg("Copying directory content of %1 to %2");
- m_outputView.printOutput(msg.arg(srcBaseDir.absolutePath(),
- dstBaseDir.absolutePath()));
- bool
- rv = true,
- first = true;
- QDir
- curSrcDir = srcBaseDir,
- curDstDir = dstBaseDir;
- // Instead of recursive call here, we use an iterator that traverses
- // recursively - and keep tracking the current src/dst directories.
- // This iterator (DirsBoth) will enumerate each directory twice: once
- // before its content and once after it. We'll use the first even
- // to create dst dir and descend both src/dst dirs, and use the second
- // to go back up.
- FSTraverseIterator
- fsIt(srcBaseDir.absolutePath(),
- FSTraverseIterator::DirsBoth | FSTraverseIterator::Files),
- fsEnd;
- for (; fsIt != fsEnd && rv; ++fsIt)
- {
- QFileInfo
- fi = *fsIt;
- if (fi.isFile())
- {
- rv = copyFile(fi,
- curDstDir);
- }
- else // fi.isDir()
- {
- if (first) // the very beginning of iteration
- {
- first = false;
- if (!curDstDir.exists(curDstDir.absolutePath()))
- rv = curDstDir.mkdir(curDstDir.absolutePath());
- }
- else if (curSrcDir.absolutePath() == fi.absoluteFilePath())
- {
- // done with all the kids of cur src/dst dirs: "cd .."
- curSrcDir.cdUp();
- curDstDir.cdUp();
- }
- else
- {
- // for src/dst dirst: "cd <child-dir-name>"
- QString
- dirName = QDir(fi.absoluteFilePath()).dirName();
- rv = curSrcDir.cd(dirName);
- if (rv)
- {
- if (!curDstDir.exists(dirName))
- rv = curDstDir.mkdir(dirName);
- if (rv)
- rv = curDstDir.cd(dirName);
- }
- }
- }
- }
- return rv;
- }
- bool FileCopier::copy()
- {
- bool
- rv = false;
- QFileInfo
- srcFileInfo(m_source),
- dstFileInfo(m_destination);
- if (srcFileInfo.exists() && srcFileInfo.isDir())
- {
- if (dstFileInfo.exists() && dstFileInfo.isFile())
- {
- QString
- msg("Error: Source %1 is dir, destination %1 is file.");
- m_outputView.printOutput(msg.arg(m_source, m_destination));
- }
- else
- {
- m_srcBaseDir = QDir(m_source);
- m_dstBaseDir = QDir(m_destination);
- rv = copyDir(m_srcBaseDir, m_dstBaseDir);
- }
- }
- else if(srcFileInfo.exists() && srcFileInfo.isFile())
- {
- m_srcBaseDir = QDir(srcFileInfo.absoluteDir());
- if (LooksLikeDir(dstFileInfo))
- {
- m_dstBaseDir = QDir(dstFileInfo.absoluteFilePath());
- rv = m_dstBaseDir.mkpath(m_dstBaseDir.absolutePath())
- && copyFile(srcFileInfo,
- m_dstBaseDir);
- }
- else
- {
- if (srcFileInfo.suffix() != dstFileInfo.suffix())
- {
- QString
- msg("Error: Source file %1 suffix mismatches "
- "destination %2 file suffix.");
- m_outputView.printOutput(msg.arg(m_source,
- m_destination));
- }
- else
- {
- m_dstBaseDir = QDir(dstFileInfo.absoluteDir());
- rv = m_dstBaseDir.mkpath(m_dstBaseDir.absolutePath())
- && copyFile(srcFileInfo,
- m_dstBaseDir);
- }
- }
- }
- else
- {
- QString
- msg("Error: Source %1 does not exist or cannot handle it");
- m_outputView.printOutput(msg.arg(m_source));
- }
- return rv;
- }
|