Fix missing last modification time stamp in qrc content
The time stamp is added at the end of the node information and consequently this also bumps the version. Task-number: QTBUG-57182 Change-Id: Ia10e006f28c0b168b2bcd74ed8b7098f84d10af3 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
parent
32b99a38c5
commit
d207738245
@ -101,35 +101,38 @@ class QResourceRoot
|
||||
Directory = 0x02
|
||||
};
|
||||
const uchar *tree, *names, *payloads;
|
||||
inline int findOffset(int node) const { return node * 14; } //sizeof each tree element
|
||||
int version;
|
||||
inline int findOffset(int node) const { return node * (14 + (version >= 0x02 ? 8 : 0)); } //sizeof each tree element
|
||||
uint hash(int node) const;
|
||||
QString name(int node) const;
|
||||
short flags(int node) const;
|
||||
public:
|
||||
mutable QAtomicInt ref;
|
||||
|
||||
inline QResourceRoot(): tree(0), names(0), payloads(0) {}
|
||||
inline QResourceRoot(const uchar *t, const uchar *n, const uchar *d) { setSource(t, n, d); }
|
||||
inline QResourceRoot(): tree(0), names(0), payloads(0), version(0) {}
|
||||
inline QResourceRoot(int version, const uchar *t, const uchar *n, const uchar *d) { setSource(version, t, n, d); }
|
||||
virtual ~QResourceRoot() { }
|
||||
int findNode(const QString &path, const QLocale &locale=QLocale()) const;
|
||||
inline bool isContainer(int node) const { return flags(node) & Directory; }
|
||||
inline bool isCompressed(int node) const { return flags(node) & Compressed; }
|
||||
const uchar *data(int node, qint64 *size) const;
|
||||
QDateTime lastModified(int node) const;
|
||||
QStringList children(int node) const;
|
||||
virtual QString mappingRoot() const { return QString(); }
|
||||
bool mappingRootSubdir(const QString &path, QString *match=0) const;
|
||||
inline bool operator==(const QResourceRoot &other) const
|
||||
{ return tree == other.tree && names == other.names && payloads == other.payloads; }
|
||||
{ return tree == other.tree && names == other.names && payloads == other.payloads && version == other.version; }
|
||||
inline bool operator!=(const QResourceRoot &other) const
|
||||
{ return !operator==(other); }
|
||||
enum ResourceRootType { Resource_Builtin, Resource_File, Resource_Buffer };
|
||||
virtual ResourceRootType type() const { return Resource_Builtin; }
|
||||
|
||||
protected:
|
||||
inline void setSource(const uchar *t, const uchar *n, const uchar *d) {
|
||||
inline void setSource(int v, const uchar *t, const uchar *n, const uchar *d) {
|
||||
tree = t;
|
||||
names = n;
|
||||
payloads = d;
|
||||
version = v;
|
||||
}
|
||||
};
|
||||
|
||||
@ -231,6 +234,7 @@ public:
|
||||
mutable qint64 size;
|
||||
mutable const uchar *data;
|
||||
mutable QStringList children;
|
||||
mutable QDateTime lastModified;
|
||||
|
||||
QResource *q_ptr;
|
||||
Q_DECLARE_PUBLIC(QResource)
|
||||
@ -244,6 +248,7 @@ QResourcePrivate::clear()
|
||||
data = 0;
|
||||
size = 0;
|
||||
children.clear();
|
||||
lastModified = QDateTime();
|
||||
container = 0;
|
||||
for(int i = 0; i < related.size(); ++i) {
|
||||
QResourceRoot *root = related.at(i);
|
||||
@ -274,6 +279,7 @@ QResourcePrivate::load(const QString &file)
|
||||
size = 0;
|
||||
compressed = 0;
|
||||
}
|
||||
lastModified = res->lastModified(node);
|
||||
} else if(res->isContainer(node) != container) {
|
||||
qWarning("QResourceInfo: Resource [%s] has both data and children!", file.toLatin1().constData());
|
||||
}
|
||||
@ -284,6 +290,7 @@ QResourcePrivate::load(const QString &file)
|
||||
data = 0;
|
||||
size = 0;
|
||||
compressed = 0;
|
||||
lastModified = QDateTime();
|
||||
res->ref.ref();
|
||||
related.append(res);
|
||||
}
|
||||
@ -513,6 +520,17 @@ const uchar *QResource::data() const
|
||||
return d->data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the date and time when the file was last modified before
|
||||
packaging into a resource.
|
||||
*/
|
||||
QDateTime QResource::lastModified() const
|
||||
{
|
||||
Q_D(const QResource);
|
||||
d->ensureInitialized();
|
||||
return d->lastModified;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the resource represents a directory and thus may have
|
||||
children() in it, false if it represents a file.
|
||||
@ -780,6 +798,24 @@ const uchar *QResourceRoot::data(int node, qint64 *size) const
|
||||
*size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
QDateTime QResourceRoot::lastModified(int node) const
|
||||
{
|
||||
if (node == -1 || version < 0x02)
|
||||
return QDateTime();
|
||||
|
||||
const int offset = findOffset(node) + 14;
|
||||
|
||||
const quint64 timeStamp = (quint64(tree[offset+0]) << 56) + (quint64(tree[offset+1]) << 48) +
|
||||
(quint64(tree[offset+2]) << 40) + (quint64(tree[offset+3]) << 32) +
|
||||
(quint64(tree[offset+4]) << 24) + (quint64(tree[offset+5]) << 16) +
|
||||
(quint64(tree[offset+6]) << 8) + (quint64(tree[offset+7]));
|
||||
if (timeStamp == 0)
|
||||
return QDateTime();
|
||||
|
||||
return QDateTime::fromMSecsSinceEpoch(timeStamp);
|
||||
}
|
||||
|
||||
QStringList QResourceRoot::children(int node) const
|
||||
{
|
||||
if(node == -1)
|
||||
@ -829,9 +865,9 @@ Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree,
|
||||
const unsigned char *name, const unsigned char *data)
|
||||
{
|
||||
QMutexLocker lock(resourceMutex());
|
||||
if(version == 0x01 && resourceList()) {
|
||||
if ((version == 0x01 || version == 0x2) && resourceList()) {
|
||||
bool found = false;
|
||||
QResourceRoot res(tree, name, data);
|
||||
QResourceRoot res(version, tree, name, data);
|
||||
for(int i = 0; i < resourceList()->size(); ++i) {
|
||||
if(*resourceList()->at(i) == res) {
|
||||
found = true;
|
||||
@ -839,7 +875,7 @@ Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree,
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
QResourceRoot *root = new QResourceRoot(tree, name, data);
|
||||
QResourceRoot *root = new QResourceRoot(version, tree, name, data);
|
||||
root->ref.ref();
|
||||
resourceList()->append(root);
|
||||
}
|
||||
@ -852,8 +888,8 @@ Q_CORE_EXPORT bool qUnregisterResourceData(int version, const unsigned char *tre
|
||||
const unsigned char *name, const unsigned char *data)
|
||||
{
|
||||
QMutexLocker lock(resourceMutex());
|
||||
if(version == 0x01 && resourceList()) {
|
||||
QResourceRoot res(tree, name, data);
|
||||
if ((version == 0x01 || version == 0x02) && resourceList()) {
|
||||
QResourceRoot res(version, tree, name, data);
|
||||
for(int i = 0; i < resourceList()->size(); ) {
|
||||
if(*resourceList()->at(i) == res) {
|
||||
QResourceRoot *root = resourceList()->takeAt(i);
|
||||
@ -919,9 +955,9 @@ public:
|
||||
if (size >= 0 && (tree_offset >= size || data_offset >= size || name_offset >= size))
|
||||
return false;
|
||||
|
||||
if(version == 0x01) {
|
||||
if (version == 0x01 || version == 0x02) {
|
||||
buffer = b;
|
||||
setSource(b+tree_offset, b+name_offset, b+data_offset);
|
||||
setSource(version, b+tree_offset, b+name_offset, b+data_offset);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1430,8 +1466,11 @@ QString QResourceFileEngine::owner(FileOwner) const
|
||||
return QString();
|
||||
}
|
||||
|
||||
QDateTime QResourceFileEngine::fileTime(FileTime) const
|
||||
QDateTime QResourceFileEngine::fileTime(FileTime time) const
|
||||
{
|
||||
Q_D(const QResourceFileEngine);
|
||||
if (time == ModificationTime)
|
||||
return d->resource.lastModified();
|
||||
return QDateTime();
|
||||
}
|
||||
|
||||
|
@ -69,6 +69,7 @@ public:
|
||||
bool isCompressed() const;
|
||||
qint64 size() const;
|
||||
const uchar *data() const;
|
||||
QDateTime lastModified() const;
|
||||
|
||||
static void addSearchPath(const QString &path);
|
||||
static QStringList searchPaths();
|
||||
|
@ -203,6 +203,12 @@ void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib)
|
||||
}
|
||||
if (text || pass1)
|
||||
lib.writeChar('\n');
|
||||
|
||||
// last modified time stamp
|
||||
const QDateTime lastModified = m_fileInfo.lastModified();
|
||||
lib.writeNumber8(quint64(lastModified.isValid() ? lastModified.toMSecsSinceEpoch() : 0));
|
||||
if (text || pass1)
|
||||
lib.writeChar('\n');
|
||||
}
|
||||
|
||||
qint64 RCCFileInfo::writeDataBlob(RCCResourceLibrary &lib, qint64 offset,
|
||||
@ -833,6 +839,38 @@ void RCCResourceLibrary::writeNumber4(quint32 number)
|
||||
}
|
||||
}
|
||||
|
||||
void RCCResourceLibrary::writeNumber8(quint64 number)
|
||||
{
|
||||
if (m_format == RCCResourceLibrary::Pass2) {
|
||||
m_outDevice->putChar(char(number >> 56));
|
||||
m_outDevice->putChar(char(number >> 48));
|
||||
m_outDevice->putChar(char(number >> 40));
|
||||
m_outDevice->putChar(char(number >> 32));
|
||||
m_outDevice->putChar(char(number >> 24));
|
||||
m_outDevice->putChar(char(number >> 16));
|
||||
m_outDevice->putChar(char(number >> 8));
|
||||
m_outDevice->putChar(char(number));
|
||||
} else if (m_format == RCCResourceLibrary::Binary) {
|
||||
writeChar(number >> 56);
|
||||
writeChar(number >> 48);
|
||||
writeChar(number >> 40);
|
||||
writeChar(number >> 32);
|
||||
writeChar(number >> 24);
|
||||
writeChar(number >> 16);
|
||||
writeChar(number >> 8);
|
||||
writeChar(number);
|
||||
} else {
|
||||
writeHex(number >> 56);
|
||||
writeHex(number >> 48);
|
||||
writeHex(number >> 40);
|
||||
writeHex(number >> 32);
|
||||
writeHex(number >> 24);
|
||||
writeHex(number >> 16);
|
||||
writeHex(number >> 8);
|
||||
writeHex(number);
|
||||
}
|
||||
}
|
||||
|
||||
bool RCCResourceLibrary::writeHeader()
|
||||
{
|
||||
if (m_format == C_Code || m_format == Pass1) {
|
||||
@ -1076,7 +1114,7 @@ bool RCCResourceLibrary::writeInitializer()
|
||||
if (m_root) {
|
||||
writeString(" ");
|
||||
writeAddNamespaceFunction("qRegisterResourceData");
|
||||
writeString("\n (0x01, qt_resource_struct, "
|
||||
writeString("\n (0x02, qt_resource_struct, "
|
||||
"qt_resource_name, qt_resource_data);\n");
|
||||
}
|
||||
writeString(" return 1;\n");
|
||||
@ -1097,7 +1135,7 @@ bool RCCResourceLibrary::writeInitializer()
|
||||
if (m_root) {
|
||||
writeString(" ");
|
||||
writeAddNamespaceFunction("qUnregisterResourceData");
|
||||
writeString("\n (0x01, qt_resource_struct, "
|
||||
writeString("\n (0x02, qt_resource_struct, "
|
||||
"qt_resource_name, qt_resource_data);\n");
|
||||
}
|
||||
writeString(" return 1;\n");
|
||||
@ -1114,10 +1152,10 @@ bool RCCResourceLibrary::writeInitializer()
|
||||
} else if (m_format == Binary) {
|
||||
int i = 4;
|
||||
char *p = m_out.data();
|
||||
p[i++] = 0; // 0x01
|
||||
p[i++] = 0; // 0x02
|
||||
p[i++] = 0;
|
||||
p[i++] = 0;
|
||||
p[i++] = 1;
|
||||
p[i++] = 2;
|
||||
|
||||
p[i++] = (m_treeOffset >> 24) & 0xff;
|
||||
p[i++] = (m_treeOffset >> 16) & 0xff;
|
||||
|
@ -118,6 +118,7 @@ private:
|
||||
void writeHex(quint8 number);
|
||||
void writeNumber2(quint16 number);
|
||||
void writeNumber4(quint32 number);
|
||||
void writeNumber8(quint64 number);
|
||||
void writeChar(char c) { m_out.append(c); }
|
||||
void writeByteArray(const QByteArray &);
|
||||
void write(const char *, int len);
|
||||
|
@ -55,6 +55,7 @@ private slots:
|
||||
void searchPath();
|
||||
void doubleSlashInRoot();
|
||||
void setLocale();
|
||||
void lastModified();
|
||||
|
||||
private:
|
||||
const QString m_runtimeResourceRcc;
|
||||
@ -489,6 +490,20 @@ void tst_QResourceEngine::setLocale()
|
||||
QLocale::setDefault(QLocale::system());
|
||||
}
|
||||
|
||||
void tst_QResourceEngine::lastModified()
|
||||
{
|
||||
{
|
||||
QFileInfo fi(":/");
|
||||
QVERIFY(fi.exists());
|
||||
QVERIFY2(!fi.lastModified().isValid(), qPrintable(fi.lastModified().toString()));
|
||||
}
|
||||
{
|
||||
QFileInfo fi(":/search_file.txt");
|
||||
QVERIFY(fi.exists());
|
||||
QVERIFY(fi.lastModified().isValid());
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QResourceEngine)
|
||||
|
||||
#include "tst_qresourceengine.moc"
|
||||
|
@ -79,16 +79,22 @@ static const unsigned char qt_resource_name[] = {
|
||||
static const unsigned char qt_resource_struct[] = {
|
||||
// :
|
||||
0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
// :/images
|
||||
0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x2,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
// :/images/subdir
|
||||
0x0,0x0,0x0,0x12,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x5,
|
||||
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
|
||||
// :/images/square.png
|
||||
0x0,0x0,0x0,0x3e,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xa9,
|
||||
TIMESTAMP:images/square.png
|
||||
// :/images/circle.png
|
||||
0x0,0x0,0x0,0x24,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,
|
||||
TIMESTAMP:images/circle.png
|
||||
// :/images/subdir/triangle.png
|
||||
0x0,0x0,0x0,0x58,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1,0xb,
|
||||
TIMESTAMP:images/subdir/triangle.png
|
||||
|
||||
};
|
||||
|
||||
@ -120,7 +126,7 @@ int QT_RCC_MANGLE_NAMESPACE(qInitResources)();
|
||||
int QT_RCC_MANGLE_NAMESPACE(qInitResources)()
|
||||
{
|
||||
QT_RCC_PREPEND_NAMESPACE(qRegisterResourceData)
|
||||
(0x01, qt_resource_struct, qt_resource_name, qt_resource_data);
|
||||
(0x02, qt_resource_struct, qt_resource_name, qt_resource_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -128,7 +134,7 @@ int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)();
|
||||
int QT_RCC_MANGLE_NAMESPACE(qCleanupResources)()
|
||||
{
|
||||
QT_RCC_PREPEND_NAMESPACE(qUnregisterResourceData)
|
||||
(0x01, qt_resource_struct, qt_resource_name, qt_resource_data);
|
||||
(0x02, qt_resource_struct, qt_resource_name, qt_resource_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -92,12 +92,23 @@ static QString doCompare(const QStringList &actual, const QStringList &expected)
|
||||
|
||||
QByteArray ba;
|
||||
for (int i = 0, n = expected.size(); i != n; ++i) {
|
||||
if (expected.at(i).startsWith("IGNORE:"))
|
||||
QString expectedLine = expected.at(i);
|
||||
if (expectedLine.startsWith("IGNORE:"))
|
||||
continue;
|
||||
if (expected.at(i) != actual.at(i)) {
|
||||
if (expectedLine.startsWith("TIMESTAMP:")) {
|
||||
const QString relativePath = expectedLine.mid(strlen("TIMESTAMP:"));
|
||||
const quint64 timeStamp = QFileInfo(relativePath).lastModified().toMSecsSinceEpoch();
|
||||
expectedLine.clear();
|
||||
for (int shift = 56; shift >= 0; shift -= 8) {
|
||||
expectedLine.append(QLatin1String("0x"));
|
||||
expectedLine.append(QString::number(quint8(timeStamp >> shift), 16));
|
||||
expectedLine.append(QLatin1Char(','));
|
||||
}
|
||||
}
|
||||
if (expectedLine != actual.at(i)) {
|
||||
qDebug() << "LINES" << i << "DIFFER";
|
||||
ba.append(
|
||||
"\n<<<<<< actual\n" + actual.at(i) + "\n======\n" + expected.at(i)
|
||||
"\n<<<<<< actual\n" + actual.at(i) + "\n======\n" + expectedLine
|
||||
+ "\n>>>>>> expected\n"
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user