Version 2.6
[qgit4/redivivus.git] / src / cache.cpp
blobbcac3a287b8bed07da2b34ca5f85af065042a596
1 /*
2 Description: file names persistent cache
4 Author: Marco Costalba (C) 2005-2007
6 Copyright: See COPYING file that comes with this distribution
8 */
9 #include <QFile>
10 #include <QDataStream>
11 #include <QDir>
12 #include "cache.h"
14 using namespace QGit;
16 bool Cache::save(const QString& gitDir, const RevFileMap& rf,
17 const StrVect& dirs, const StrVect& files) {
19 if (gitDir.isEmpty() || rf.isEmpty())
20 return false;
22 QString path(gitDir + C_DAT_FILE);
23 QString tmpPath(path + BAK_EXT);
25 QDir dir;
26 if (!dir.exists(gitDir)) {
27 dbs("Git directory not found, unable to save cache");
28 return false;
30 QFile f(tmpPath);
31 if (!f.open(QIODevice::WriteOnly | QIODevice::Unbuffered))
32 return false;
34 dbs("Saving cache. Please wait...");
36 // compress in memory before write to file
37 QByteArray data;
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)
46 stream << dirs.at(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
56 // almost the same.
57 uint bufSize = rf.count() * 41 + 1000; // a little bit more space then required
59 QByteArray buf;
60 buf.reserve(bufSize);
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
75 continue;
77 v.append(it.value());
78 buf.append(sha.latin1()).append('\0');
79 newSize += 41;
80 if (newSize > bufSize) {
81 dbs("ASSERT in Cache::save, out of allocated space");
82 return false;
85 buf.resize(newSize);
86 stream << (qint32)newSize;
87 stream << buf;
89 for (int i = 0; i < v.size(); ++i)
90 *(v.at(i)) >> stream;
92 dbs("Compressing data...");
93 f.write(qCompress(data, 1)); // no need to encode with compressed data
94 f.close();
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);
100 dir.remove(tmpPath);
101 return false;
104 dir.rename(tmpPath, path);
105 dbs("Done.");
106 return true;
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);
114 QFile f(path);
115 if (!f.exists())
116 return true; // no cache file is not an error
118 if (!f.open(QIODevice::ReadOnly | QIODevice::Unbuffered))
119 return false;
121 QDataStream stream(qUncompress(f.readAll()));
122 quint32 magic;
123 qint32 version;
124 qint32 dirsNum, filesNum, bufSize;
125 stream >> magic;
126 stream >> version;
127 if (magic != C_MAGIC || version != C_VERSION) {
128 f.close();
129 return false;
131 // read the data
132 stream >> dirsNum;
133 dirs.resize(dirsNum);
134 for (int i = 0; i < dirsNum; ++i)
135 stream >> dirs[i];
137 stream >> filesNum;
138 files.resize(filesNum);
139 for (int i = 0; i < filesNum; ++i)
140 stream >> files[i];
142 stream >> bufSize;
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();
152 *rf << stream;
154 ShaString sha(data);
155 rfm.insert(sha, rf);
157 data += 40;
158 if (*data != '\0') {
159 dbp("ASSERT in Cache::load, corrupted SHA after %1", sha);
160 return false;
162 data++;
164 f.close();
165 return true;