forked from qt-creator/qt-creator
Maemo: Implement tar package creation step.
Currently unused.
This commit is contained in:
@@ -121,7 +121,7 @@ void AbstractMaemoPackageCreationStep::run(QFutureInterface<bool> &fi)
|
||||
connect(buildProc, SIGNAL(readyReadStandardError()), this,
|
||||
SLOT(handleBuildOutput()));
|
||||
emit addOutput(tr("Creating package file ..."), MessageOutput);
|
||||
const bool success = createPackage(buildProc);
|
||||
const bool success = createPackage(buildProc, fi);
|
||||
disconnect(buildProc, 0, this, 0);
|
||||
buildProc->deleteLater();
|
||||
if (success) {
|
||||
@@ -332,8 +332,10 @@ void MaemoDebianPackageCreationStep::ctor()
|
||||
setDefaultDisplayName(tr("Create Debian Package"));
|
||||
}
|
||||
|
||||
bool MaemoDebianPackageCreationStep::createPackage(QProcess *buildProc)
|
||||
bool MaemoDebianPackageCreationStep::createPackage(QProcess *buildProc,
|
||||
const QFutureInterface<bool> &fi)
|
||||
{
|
||||
Q_UNUSED(fi);
|
||||
checkProjectName();
|
||||
const QString projectDir
|
||||
= buildConfiguration()->target()->project()->projectDirectory();
|
||||
@@ -601,8 +603,10 @@ void MaemoRpmPackageCreationStep::ctor()
|
||||
setDefaultDisplayName(tr("Create RPM Package"));
|
||||
}
|
||||
|
||||
bool MaemoRpmPackageCreationStep::createPackage(QProcess *buildProc)
|
||||
bool MaemoRpmPackageCreationStep::createPackage(QProcess *buildProc,
|
||||
const QFutureInterface<bool> &fi)
|
||||
{
|
||||
Q_UNUSED(fi);
|
||||
const QStringList args = QStringList() << QLatin1String("rrpmbuild")
|
||||
<< QLatin1String("-bb") << rpmBasedMaemoTarget()->specFilePath();
|
||||
if (!callPackagingCommand(buildProc, args))
|
||||
@@ -661,6 +665,29 @@ private:
|
||||
const MaemoTarPackageCreationStep * const m_step;
|
||||
};
|
||||
|
||||
namespace {
|
||||
const int TarBlockSize = 512;
|
||||
struct TarFileHeader {
|
||||
char fileName[100];
|
||||
char fileMode[8];
|
||||
char uid[8];
|
||||
char gid[8];
|
||||
char length[12];
|
||||
char mtime[12];
|
||||
char chksum[8];
|
||||
char typeflag;
|
||||
char linkname[100];
|
||||
char magic[6];
|
||||
char version[2];
|
||||
char uname[32];
|
||||
char gname[32];
|
||||
char devmajor[8];
|
||||
char devminor[8];
|
||||
char fileNamePrefix[155];
|
||||
char padding[12];
|
||||
};
|
||||
} // Anonymous namespace.
|
||||
|
||||
MaemoTarPackageCreationStep::MaemoTarPackageCreationStep(BuildStepList *bsl)
|
||||
: AbstractMaemoPackageCreationStep(bsl, CreatePackageId)
|
||||
{
|
||||
@@ -679,15 +706,165 @@ void MaemoTarPackageCreationStep::ctor()
|
||||
setDefaultDisplayName(tr("Create tar ball"));
|
||||
}
|
||||
|
||||
bool MaemoTarPackageCreationStep::createPackage(QProcess *buildProc)
|
||||
bool MaemoTarPackageCreationStep::createPackage(QProcess *buildProc,
|
||||
const QFutureInterface<bool> &fi)
|
||||
{
|
||||
Q_UNUSED(buildProc);
|
||||
|
||||
// TODO: Copy files one by one into tar file.
|
||||
// TODO: Optimization: Only package changed files (needs refactoring in upper level; worth the effort?)
|
||||
QFile tarFile(packageFilePath());
|
||||
if (!tarFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
raiseError(tr("Error: tar file %1 cannot be opened (%2).")
|
||||
.arg(QDir::toNativeSeparators(packageFilePath()),
|
||||
tarFile.errorString()));
|
||||
return false;
|
||||
}
|
||||
const QSharedPointer<MaemoDeployables> deployables = deployConfig()->deployables();
|
||||
for (int i = 0; i < deployables->deployableCount(); ++i) {
|
||||
const MaemoDeployable &d = deployables->deployableAt(i);
|
||||
QFileInfo fileInfo(d.localFilePath);
|
||||
if (!appendFile(tarFile, fileInfo, d.remoteDir + QLatin1Char('/')
|
||||
+ fileInfo.fileName(), fi)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MaemoTarPackageCreationStep::appendFile(QFile &tarFile,
|
||||
const QFileInfo &fileInfo, const QString &remoteFilePath,
|
||||
const QFutureInterface<bool> &fi)
|
||||
{
|
||||
if (!writeHeader(tarFile, fileInfo, remoteFilePath))
|
||||
return false;
|
||||
if (fileInfo.isDir()) {
|
||||
QDir dir(fileInfo.absoluteFilePath());
|
||||
foreach (const QString &fileName,
|
||||
dir.entryList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
|
||||
const QString thisLocalFilePath
|
||||
= dir.path() + QLatin1Char('/') + fileName;
|
||||
const QString thisRemoteFilePath = remoteFilePath
|
||||
+ QLatin1Char('/') + fileName;
|
||||
if (!appendFile(tarFile, QFileInfo(thisLocalFilePath),
|
||||
thisRemoteFilePath, fi)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const QString nativePath
|
||||
= QDir::toNativeSeparators(fileInfo.filePath());
|
||||
QFile file(fileInfo.filePath());
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
raiseError(tr("Error reading file '%1': %2.")
|
||||
.arg(nativePath, file.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
const int chunkSize = 1024*1024;
|
||||
|
||||
// TODO: Wasteful. Work with fixed-size buffer.
|
||||
while (!file.atEnd() && !file.error() != QFile::NoError
|
||||
&& !tarFile.error() != QFile::NoError) {
|
||||
const QByteArray data = file.read(chunkSize);
|
||||
tarFile.write(data);
|
||||
if (fi.isCanceled())
|
||||
return false;
|
||||
}
|
||||
if (file.error() != QFile::NoError) {
|
||||
raiseError(tr("Error reading file '%1': %2.")
|
||||
.arg(nativePath, file.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
const int blockModulo = file.size() % TarBlockSize;
|
||||
if (blockModulo != 0) {
|
||||
tarFile.write(QByteArray(TarBlockSize - blockModulo, 0));
|
||||
}
|
||||
|
||||
if (tarFile.error() != QFile::NoError) {
|
||||
raiseError(tr("Error writing tar file '%1': %2.")
|
||||
.arg(QDir::toNativeSeparators(tarFile.fileName()),
|
||||
tarFile.errorString()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MaemoTarPackageCreationStep::writeHeader(QFile &tarFile,
|
||||
const QFileInfo &fileInfo, const QString &remoteFilePath)
|
||||
{
|
||||
TarFileHeader header;
|
||||
qMemSet(&header, '\0', sizeof header);
|
||||
const QByteArray &filePath = remoteFilePath.toUtf8();
|
||||
const int maxFilePathLength = sizeof header.fileNamePrefix
|
||||
+ sizeof header.fileName;
|
||||
if (filePath.count() > maxFilePathLength) {
|
||||
raiseError(tr("Cannot tar file '%1': path is too long.")
|
||||
.arg(QDir::toNativeSeparators(filePath)));
|
||||
return false;
|
||||
}
|
||||
|
||||
const int fileNameBytesToWrite
|
||||
= qMin<int>(filePath.length(), sizeof header.fileName);
|
||||
const int fileNameOffset = filePath.length() - fileNameBytesToWrite;
|
||||
qMemCopy(&header.fileName, filePath.data() + fileNameOffset,
|
||||
fileNameBytesToWrite);
|
||||
if (fileNameOffset > 0)
|
||||
qMemCopy(&header.fileNamePrefix, filePath.data(), fileNameOffset);
|
||||
int permissions = (0400 * fileInfo.permission(QFile::ReadOwner))
|
||||
| (0200 * fileInfo.permission(QFile::WriteOwner))
|
||||
| (0100 * fileInfo.permission(QFile::ExeOwner))
|
||||
| (040 * fileInfo.permission(QFile::ReadGroup))
|
||||
| (020 * fileInfo.permission(QFile::WriteGroup))
|
||||
| (010 * fileInfo.permission(QFile::ExeGroup))
|
||||
| (04 * fileInfo.permission(QFile::ReadOther))
|
||||
| (02 * fileInfo.permission(QFile::WriteOther))
|
||||
| (01 * fileInfo.permission(QFile::ExeOther));
|
||||
const QByteArray permissionString = QString("%1").arg(permissions,
|
||||
sizeof header.fileMode - 1, 8, QLatin1Char('0')).toAscii();
|
||||
qMemCopy(&header.fileMode, permissionString.data(),
|
||||
permissionString.length());
|
||||
const QByteArray uidString = QString("%1").arg(fileInfo.ownerId(),
|
||||
sizeof header.uid - 1, 8, QLatin1Char('0')).toAscii();
|
||||
qMemCopy(&header.uid, uidString.data(), uidString.length());
|
||||
const QByteArray gidString = QString("%1").arg(fileInfo.groupId(),
|
||||
sizeof header.gid - 1, 8, QLatin1Char('0')).toAscii();
|
||||
qMemCopy(&header.gid, gidString.data(), gidString.length());
|
||||
const QByteArray sizeString = QString("%1").arg(fileInfo.size(),
|
||||
sizeof header.length - 1, 8, QLatin1Char('0')).toAscii();
|
||||
qMemCopy(&header.length, sizeString.data(), sizeString.length());
|
||||
const QByteArray mtimeString = QString("%1").arg(fileInfo.lastModified().toTime_t(),
|
||||
sizeof header.mtime - 1, 8, QLatin1Char('0')).toAscii();
|
||||
qMemCopy(&header.mtime, mtimeString.data(), mtimeString.length());
|
||||
if (fileInfo.isDir())
|
||||
header.typeflag = '5';
|
||||
qMemCopy(&header.magic, "ustar", sizeof "ustar");
|
||||
qMemCopy(&header.version, "00", 2);
|
||||
const QByteArray &owner = fileInfo.owner().toUtf8();
|
||||
qMemCopy(&header.uname, owner.data(),
|
||||
qMin<int>(owner.length(), sizeof header.uname - 1));
|
||||
const QByteArray &group = fileInfo.group().toUtf8();
|
||||
qMemCopy(&header.gname, group.data(),
|
||||
qMin<int>(group.length(), sizeof header.gname - 1));
|
||||
qMemSet(&header.chksum, ' ', sizeof header.chksum);
|
||||
quint64 checksum = 0;
|
||||
for (size_t i = 0; i < sizeof header; ++i)
|
||||
checksum += reinterpret_cast<char *>(&header)[i];
|
||||
const QByteArray checksumString = QString("%1").arg(checksum,
|
||||
sizeof header.chksum - 1, 8, QLatin1Char('0')).toAscii();
|
||||
qMemCopy(&header.chksum, checksumString.data(), checksumString.length());
|
||||
header.chksum[sizeof header.chksum-1] = 0;
|
||||
if (!tarFile.write(reinterpret_cast<char *>(&header), sizeof header)) {
|
||||
raiseError(tr("Error writing tar file '%1': %2")
|
||||
.arg(QDir::toNativeSeparators(packageFilePath()),
|
||||
tarFile.errorString()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MaemoTarPackageCreationStep::isMetaDataNewerThan(const QDateTime &packageDate) const
|
||||
{
|
||||
Q_UNUSED(packageDate);
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QDateTime;
|
||||
class QFile;
|
||||
class QFileInfo;
|
||||
class QProcess;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -109,7 +110,7 @@ private:
|
||||
virtual void run(QFutureInterface<bool> &fi);
|
||||
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
|
||||
|
||||
virtual bool createPackage(QProcess *buildProc)=0;
|
||||
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi)=0;
|
||||
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const=0;
|
||||
|
||||
static QString nativePath(const QFile &file);
|
||||
@@ -132,7 +133,7 @@ private:
|
||||
MaemoDebianPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
|
||||
MaemoDebianPackageCreationStep *other);
|
||||
|
||||
virtual bool createPackage(QProcess *buildProc);
|
||||
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
|
||||
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
|
||||
|
||||
void ctor();
|
||||
@@ -159,7 +160,7 @@ public:
|
||||
MaemoRpmPackageCreationStep(ProjectExplorer::BuildStepList *bsl);
|
||||
|
||||
private:
|
||||
virtual bool createPackage(QProcess *buildProc);
|
||||
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
|
||||
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
|
||||
|
||||
MaemoRpmPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
|
||||
@@ -180,7 +181,7 @@ public:
|
||||
|
||||
virtual QString packageFilePath() const;
|
||||
private:
|
||||
virtual bool createPackage(QProcess *buildProc);
|
||||
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
|
||||
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
|
||||
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
|
||||
|
||||
@@ -188,6 +189,10 @@ private:
|
||||
MaemoTarPackageCreationStep *other);
|
||||
|
||||
void ctor();
|
||||
bool appendFile(QFile &tarFile, const QFileInfo &fileInfo,
|
||||
const QString &remoteFilePath, const QFutureInterface<bool> &fi);
|
||||
bool writeHeader(QFile &tarFile, const QFileInfo &fileInfo,
|
||||
const QString &remoteFilePath);
|
||||
|
||||
static const QString CreatePackageId;
|
||||
};
|
||||
|
||||
@@ -205,7 +205,7 @@ QString MaemoTarPackageInstaller::installCommand() const
|
||||
|
||||
QStringList MaemoTarPackageInstaller::installCommandArguments() const
|
||||
{
|
||||
return QStringList() << QLatin1String("xvf");
|
||||
return QStringList() << QLatin1String("--absolute-names -xvf");
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
Reference in New Issue
Block a user