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,
|
connect(buildProc, SIGNAL(readyReadStandardError()), this,
|
||||||
SLOT(handleBuildOutput()));
|
SLOT(handleBuildOutput()));
|
||||||
emit addOutput(tr("Creating package file ..."), MessageOutput);
|
emit addOutput(tr("Creating package file ..."), MessageOutput);
|
||||||
const bool success = createPackage(buildProc);
|
const bool success = createPackage(buildProc, fi);
|
||||||
disconnect(buildProc, 0, this, 0);
|
disconnect(buildProc, 0, this, 0);
|
||||||
buildProc->deleteLater();
|
buildProc->deleteLater();
|
||||||
if (success) {
|
if (success) {
|
||||||
@@ -332,8 +332,10 @@ void MaemoDebianPackageCreationStep::ctor()
|
|||||||
setDefaultDisplayName(tr("Create Debian Package"));
|
setDefaultDisplayName(tr("Create Debian Package"));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MaemoDebianPackageCreationStep::createPackage(QProcess *buildProc)
|
bool MaemoDebianPackageCreationStep::createPackage(QProcess *buildProc,
|
||||||
|
const QFutureInterface<bool> &fi)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(fi);
|
||||||
checkProjectName();
|
checkProjectName();
|
||||||
const QString projectDir
|
const QString projectDir
|
||||||
= buildConfiguration()->target()->project()->projectDirectory();
|
= buildConfiguration()->target()->project()->projectDirectory();
|
||||||
@@ -601,8 +603,10 @@ void MaemoRpmPackageCreationStep::ctor()
|
|||||||
setDefaultDisplayName(tr("Create RPM Package"));
|
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")
|
const QStringList args = QStringList() << QLatin1String("rrpmbuild")
|
||||||
<< QLatin1String("-bb") << rpmBasedMaemoTarget()->specFilePath();
|
<< QLatin1String("-bb") << rpmBasedMaemoTarget()->specFilePath();
|
||||||
if (!callPackagingCommand(buildProc, args))
|
if (!callPackagingCommand(buildProc, args))
|
||||||
@@ -661,6 +665,29 @@ private:
|
|||||||
const MaemoTarPackageCreationStep * const m_step;
|
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)
|
MaemoTarPackageCreationStep::MaemoTarPackageCreationStep(BuildStepList *bsl)
|
||||||
: AbstractMaemoPackageCreationStep(bsl, CreatePackageId)
|
: AbstractMaemoPackageCreationStep(bsl, CreatePackageId)
|
||||||
{
|
{
|
||||||
@@ -679,15 +706,165 @@ void MaemoTarPackageCreationStep::ctor()
|
|||||||
setDefaultDisplayName(tr("Create tar ball"));
|
setDefaultDisplayName(tr("Create tar ball"));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MaemoTarPackageCreationStep::createPackage(QProcess *buildProc)
|
bool MaemoTarPackageCreationStep::createPackage(QProcess *buildProc,
|
||||||
|
const QFutureInterface<bool> &fi)
|
||||||
{
|
{
|
||||||
Q_UNUSED(buildProc);
|
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;
|
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
|
bool MaemoTarPackageCreationStep::isMetaDataNewerThan(const QDateTime &packageDate) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(packageDate);
|
Q_UNUSED(packageDate);
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QDateTime;
|
class QDateTime;
|
||||||
class QFile;
|
class QFile;
|
||||||
|
class QFileInfo;
|
||||||
class QProcess;
|
class QProcess;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
@@ -109,7 +110,7 @@ private:
|
|||||||
virtual void run(QFutureInterface<bool> &fi);
|
virtual void run(QFutureInterface<bool> &fi);
|
||||||
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
|
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;
|
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const=0;
|
||||||
|
|
||||||
static QString nativePath(const QFile &file);
|
static QString nativePath(const QFile &file);
|
||||||
@@ -132,7 +133,7 @@ private:
|
|||||||
MaemoDebianPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
|
MaemoDebianPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
|
||||||
MaemoDebianPackageCreationStep *other);
|
MaemoDebianPackageCreationStep *other);
|
||||||
|
|
||||||
virtual bool createPackage(QProcess *buildProc);
|
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
|
||||||
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
|
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
|
||||||
|
|
||||||
void ctor();
|
void ctor();
|
||||||
@@ -159,7 +160,7 @@ public:
|
|||||||
MaemoRpmPackageCreationStep(ProjectExplorer::BuildStepList *bsl);
|
MaemoRpmPackageCreationStep(ProjectExplorer::BuildStepList *bsl);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool createPackage(QProcess *buildProc);
|
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
|
||||||
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
|
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
|
||||||
|
|
||||||
MaemoRpmPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
|
MaemoRpmPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
|
||||||
@@ -180,7 +181,7 @@ public:
|
|||||||
|
|
||||||
virtual QString packageFilePath() const;
|
virtual QString packageFilePath() const;
|
||||||
private:
|
private:
|
||||||
virtual bool createPackage(QProcess *buildProc);
|
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
|
||||||
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
|
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
|
||||||
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
|
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
|
||||||
|
|
||||||
@@ -188,6 +189,10 @@ private:
|
|||||||
MaemoTarPackageCreationStep *other);
|
MaemoTarPackageCreationStep *other);
|
||||||
|
|
||||||
void ctor();
|
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;
|
static const QString CreatePackageId;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ QString MaemoTarPackageInstaller::installCommand() const
|
|||||||
|
|
||||||
QStringList MaemoTarPackageInstaller::installCommandArguments() const
|
QStringList MaemoTarPackageInstaller::installCommandArguments() const
|
||||||
{
|
{
|
||||||
return QStringList() << QLatin1String("xvf");
|
return QStringList() << QLatin1String("--absolute-names -xvf");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
Reference in New Issue
Block a user