Инкрементальный индекс, пресеты автосейва, упрощение git-слоя
- VaultIndex: updateFile/removeFile/syncIncremental по mtime+size, полный рескан только на старте/смене/внешних правках; relink висячих ссылок; FileStore.externalChanged - QML: точечные обновления индекса вместо rebuild на каждый сейв - Настройки: пресеты safe/balanced/eco/manual + диалог с +/- и шкалами; коммит после паузы, в manual — по Ctrl+S - GitManager: кэш истории, пагинация, diff в потоке, точечный commitFile, fileExistedAt, топологический порядок истории - Удалены highlightedCode, словный merge, fileDiffText/Html, 2-arg fileHistory
This commit is contained in:
+10
-5
@@ -407,14 +407,19 @@ QVariantList GitManager::fileHistory(const QString &vaultPath, const QString &fi
|
|||||||
git_repository_free(repo);
|
git_repository_free(repo);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
git_revwalk_sorting(walk, GIT_SORT_TIME);
|
// TIME|TOPOLOGICAL: время + гарантия «потомки раньше родителей».
|
||||||
|
// Один TIME при коммитах в одну секунду тасует порядок (баг: «новой» могла
|
||||||
|
// оказаться старая версия); история хранилища линейная, топология даёт точный порядок.
|
||||||
|
git_revwalk_sorting(walk, GIT_SORT_TIME | GIT_SORT_TOPOLOGICAL);
|
||||||
git_revwalk_push_head(walk);
|
git_revwalk_push_head(walk);
|
||||||
|
|
||||||
|
// Собираем до limit КАСАНИЙ файла (а не коммитов): иначе на активной истории
|
||||||
|
// «Показать ещё» врало бы при разреженных касаниях. Перебор коммитов ограничен.
|
||||||
git_oid oid;
|
git_oid oid;
|
||||||
int iter = 0;
|
int scanned = 0;
|
||||||
const int maxIter = limit; // ограничение для скорости
|
const int scanCap = 2000;
|
||||||
while (git_revwalk_next(&oid, walk) == 0 && iter < maxIter) {
|
while (git_revwalk_next(&oid, walk) == 0 && (int)out.size() < limit && scanned < scanCap) {
|
||||||
++iter;
|
++scanned;
|
||||||
git_commit *commit = nullptr;
|
git_commit *commit = nullptr;
|
||||||
if (git_commit_lookup(&commit, repo, &oid) < 0)
|
if (git_commit_lookup(&commit, repo, &oid) < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
|
|
||||||
// История файла: список коммитов где файл менялся. Сортировка новые сверху.
|
// История файла: список коммитов где файл менялся. Сортировка новые сверху.
|
||||||
// Каждый элемент: {hash, shortHash, message, author, time (QDateTime), timeStr, timeAgo}.
|
// Каждый элемент: {hash, shortHash, message, author, time (QDateTime), timeStr, timeAgo}.
|
||||||
// Не больше limit свежих (limit<=0 — до 500).
|
// Не больше limit КАСАНИЙ (limit<=0 — до 500); перебор коммитов ограничен изнутри.
|
||||||
// Для кнопки «Показать ещё»: запросить limit+1, hasMore = (размер > limit).
|
// Для кнопки «Показать ещё»: запросить limit+1, hasMore = (размер > limit).
|
||||||
Q_INVOKABLE QVariantList fileHistory(const QString &vaultPath, const QString &filePath,
|
Q_INVOKABLE QVariantList fileHistory(const QString &vaultPath, const QString &filePath,
|
||||||
int limit) const;
|
int limit) const;
|
||||||
|
|||||||
@@ -167,6 +167,19 @@ int main(int argc, char *argv[])
|
|||||||
return fail("paged cache");
|
return fail("paged cache");
|
||||||
// limit<=0 — как раньше (всё)
|
// limit<=0 — как раньше (всё)
|
||||||
if(git.fileHistory(vault, file, 0).size() != full.size()) return fail("limit 0");
|
if(git.fileHistory(vault, file, 0).size() != full.size()) return fail("limit 0");
|
||||||
|
// разреженная история: 30 чужих коммитов — касания файла всё равно находятся,
|
||||||
|
// hasMore-логика (limit+1) при этом не врёт
|
||||||
|
for (int i = 0; i < 30; ++i) {
|
||||||
|
QFile fn(vault+"/noise.md");
|
||||||
|
if(!fn.open(QIODevice::WriteOnly | QIODevice::Append)) return fail("noise open");
|
||||||
|
fn.write(QString("n%1\n").arg(i).toUtf8());
|
||||||
|
fn.close();
|
||||||
|
if(!git.commitAll(vault, QString("noise %1").arg(i))) return fail("noise commit", git.lastError());
|
||||||
|
}
|
||||||
|
QVariantList sparse = git.fileHistory(vault, file, 3);
|
||||||
|
if(sparse.size() != 3) return fail("sparse size", QString::number(sparse.size()));
|
||||||
|
if(sparse.first().toMap().value("hash") != full.first().toMap().value("hash"))
|
||||||
|
return fail("sparse order");
|
||||||
}
|
}
|
||||||
|
|
||||||
// fileExistedAt: отличает «пустой файл» от «файла не было»
|
// fileExistedAt: отличает «пустой файл» от «файла не было»
|
||||||
|
|||||||
Reference in New Issue
Block a user