1 /*
2 SPDX-FileCopyrightText: 2015 Vishesh Handa <vhanda@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-or-later
5 */
6
7 #include "modifiedfileindexer.h"
8 #include "basicindexingjob.h"
9 #include "fileindexerconfig.h"
10 #include "idutils.h"
11
12 #include "database.h"
13 #include "transaction.h"
14
15 #include <QMimeDatabase>
16 #include <QFile>
17 #include <QFileInfo>
18 #include <QDateTime>
19
20 using namespace Baloo;
21
ModifiedFileIndexer(Database * db,const FileIndexerConfig * config,const QStringList & files)22 ModifiedFileIndexer::ModifiedFileIndexer(Database* db, const FileIndexerConfig* config, const QStringList& files)
23 : m_db(db)
24 , m_config(config)
25 , m_files(files)
26 {
27 Q_ASSERT(m_db);
28 Q_ASSERT(m_config);
29 Q_ASSERT(!m_files.isEmpty());
30 }
31
run()32 void ModifiedFileIndexer::run()
33 {
34 QMimeDatabase mimeDb;
35 BasicIndexingJob::IndexingLevel level = m_config->onlyBasicIndexing() ? BasicIndexingJob::NoLevel
36 : BasicIndexingJob::MarkForContentIndexing;
37
38 Transaction tr(m_db, Transaction::ReadWrite);
39
40 for (const QString& filePath : std::as_const(m_files)) {
41 Q_ASSERT(!filePath.endsWith(QLatin1Char('/')));
42
43 QString fileName = filePath.mid(filePath.lastIndexOf(QLatin1Char('/')) + 1);
44 if (!m_config->shouldFileBeIndexed(fileName)) {
45 continue;
46 }
47
48 quint64 fileId = filePathToId(QFile::encodeName(filePath));
49 if (!fileId) {
50 continue;
51 }
52
53 // FIXME: Using QFileInfo over here is quite expensive!
54 QFileInfo fileInfo(filePath);
55 if (fileInfo.isSymLink()) {
56 continue;
57 }
58
59 bool mTimeChanged;
60 bool cTimeChanged;
61 const bool isKnownFile = tr.hasDocument(fileId);
62 if (isKnownFile) {
63 DocumentTimeDB::TimeInfo timeInfo = tr.documentTimeInfo(fileId);
64 mTimeChanged = timeInfo.mTime != fileInfo.lastModified().toSecsSinceEpoch();
65 cTimeChanged = timeInfo.cTime != fileInfo.metadataChangeTime().toSecsSinceEpoch();
66 } else {
67 mTimeChanged = cTimeChanged = true;
68 }
69
70 if (!mTimeChanged && !cTimeChanged) {
71 continue;
72 }
73
74 QString mimetype;
75 if (fileInfo.isDir()) {
76 // The folder ctime changes when the folder is created, when the folder is
77 // renamed, or when the xattrs (tags, comments, ...) change
78 if (!cTimeChanged) {
79 continue;
80 }
81 mimetype = QStringLiteral("inode/directory");
82
83 } else {
84 mimetype = mimeDb.mimeTypeForFile(filePath, QMimeDatabase::MatchExtension).name();
85 }
86
87 // Only mTime changed
88 if (!cTimeChanged) {
89 Document doc;
90 doc.setId(fileId);
91 doc.setMTime(fileInfo.lastModified().toSecsSinceEpoch());
92 doc.setCTime(fileInfo.metadataChangeTime().toSecsSinceEpoch());
93 if (level == BasicIndexingJob::MarkForContentIndexing) {
94 doc.setContentIndexing(true);
95 }
96
97 tr.replaceDocument(doc, DocumentTime);
98 continue;
99 }
100
101 BasicIndexingJob job(filePath, mimetype, level);
102 if (!job.index()) {
103 continue;
104 }
105
106 // We can get modified events for files which do not yet exist in the database
107 // because Baloo was not running and missed the creation events
108 if (isKnownFile && (job.document().id() == fileId)) {
109 tr.replaceDocument(job.document(), XAttrTerms | DocumentTime | FileNameTerms | DocumentUrl);
110 } else {
111 tr.addDocument(job.document());
112 }
113 }
114
115 tr.commit();
116 Q_EMIT done();
117 }
118