2 Description: file names persistent cache
4 Author: Marco Costalba (C) 2005-2007
6 Copyright: See COPYING file that comes with this distribution
10 #include <QDataStream>
16 bool Cache::save(const QString
& gitDir
, const RevFileMap
& rf
,
17 const StrVect
& dirs
, const StrVect
& files
) {
19 if (gitDir
.isEmpty() || rf
.isEmpty())
22 QString
path(gitDir
+ C_DAT_FILE
);
23 QString
tmpPath(path
+ BAK_EXT
);
26 if (!dir
.exists(gitDir
)) {
27 dbs("Git directory not found, unable to save cache");
31 if (!f
.open(QIODevice::WriteOnly
| QIODevice::Unbuffered
))
34 dbs("Saving cache. Please wait...");
36 // compress in memory before write to file
38 QDataStream
stream(&data
, QIODevice::WriteOnly
);
40 // Write a header with a "magic number" and a version
41 stream
<< (quint32
)C_MAGIC
;
42 stream
<< (qint32
)C_VERSION
;
44 stream
<< (qint32
)dirs
.count();
45 for (int i
= 0; i
< dirs
.count(); ++i
)
48 stream
<< (qint32
)files
.count();
49 for (int i
= 0; i
< files
.count(); ++i
)
50 stream
<< files
.at(i
);
52 // to achieve a better compression we save the sha's as
53 // one very long string instead of feeding the stream with
54 // each one. With this trick we gain a 15% size reduction
55 // in the final compressed file. The save/load speed is
57 uint bufSize
= rf
.count() * 41 + 1000; // a little bit more space then required
62 QVector
<const RevFile
*> v
;
63 v
.reserve(rf
.count());
65 QVector
<QByteArray
> ba
;
66 ShaString
CUSTOM_SHA_RAW(toPersistentSha(CUSTOM_SHA
, ba
));
67 unsigned int newSize
= 0;
69 FOREACH (RevFileMap
, it
, rf
) {
71 const ShaString
& sha
= it
.key();
72 if ( sha
== ZERO_SHA_RAW
73 || sha
== CUSTOM_SHA_RAW
74 || sha
.latin1()[0] == 'A') // ALL_MERGE_FILES + rev sha
78 buf
.append(sha
.latin1()).append('\0');
80 if (newSize
> bufSize
) {
81 dbs("ASSERT in Cache::save, out of allocated space");
86 stream
<< (qint32
)newSize
;
89 for (int i
= 0; i
< v
.size(); ++i
)
92 dbs("Compressing data...");
93 f
.write(qCompress(data
, 1)); // no need to encode with compressed data
96 // rename C_DAT_FILE + BAK_EXT -> C_DAT_FILE
97 if (dir
.exists(path
)) {
98 if (!dir
.remove(path
)) {
99 dbs("access denied to " + path
);
104 dir
.rename(tmpPath
, path
);
109 bool Cache::load(const QString
& gitDir
, RevFileMap
& rfm
,
110 StrVect
& dirs
, StrVect
& files
, QByteArray
& revsFilesShaBuf
) {
112 // check for cache file
113 QString
path(gitDir
+ C_DAT_FILE
);
116 return true; // no cache file is not an error
118 if (!f
.open(QIODevice::ReadOnly
| QIODevice::Unbuffered
))
121 QDataStream
stream(qUncompress(f
.readAll()));
124 qint32 dirsNum
, filesNum
, bufSize
;
127 if (magic
!= C_MAGIC
|| version
!= C_VERSION
) {
133 dirs
.resize(dirsNum
);
134 for (int i
= 0; i
< dirsNum
; ++i
)
138 files
.resize(filesNum
);
139 for (int i
= 0; i
< filesNum
; ++i
)
143 revsFilesShaBuf
.clear();
144 revsFilesShaBuf
.reserve(bufSize
);
145 stream
>> revsFilesShaBuf
;
147 const char* data
= revsFilesShaBuf
.constData();
149 while (!stream
.atEnd()) {
151 RevFile
* rf
= new RevFile();
159 dbp("ASSERT in Cache::load, corrupted SHA after %1", sha
);