diff --git a/src/git/GitManager.cpp b/src/git/GitManager.cpp index 6fa1312..ef23334 100644 --- a/src/git/GitManager.cpp +++ b/src/git/GitManager.cpp @@ -407,14 +407,19 @@ QVariantList GitManager::fileHistory(const QString &vaultPath, const QString &fi git_repository_free(repo); 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); + // Собираем до limit КАСАНИЙ файла (а не коммитов): иначе на активной истории + // «Показать ещё» врало бы при разреженных касаниях. Перебор коммитов ограничен. git_oid oid; - int iter = 0; - const int maxIter = limit; // ограничение для скорости - while (git_revwalk_next(&oid, walk) == 0 && iter < maxIter) { - ++iter; + int scanned = 0; + const int scanCap = 2000; + while (git_revwalk_next(&oid, walk) == 0 && (int)out.size() < limit && scanned < scanCap) { + ++scanned; git_commit *commit = nullptr; if (git_commit_lookup(&commit, repo, &oid) < 0) continue; diff --git a/src/git/GitManager.h b/src/git/GitManager.h index 76276eb..515bb07 100644 --- a/src/git/GitManager.h +++ b/src/git/GitManager.h @@ -37,7 +37,7 @@ public: // История файла: список коммитов где файл менялся. Сортировка новые сверху. // Каждый элемент: {hash, shortHash, message, author, time (QDateTime), timeStr, timeAgo}. - // Не больше limit свежих (limit<=0 — до 500). + // Не больше limit КАСАНИЙ (limit<=0 — до 500); перебор коммитов ограничен изнутри. // Для кнопки «Показать ещё»: запросить limit+1, hasMore = (размер > limit). Q_INVOKABLE QVariantList fileHistory(const QString &vaultPath, const QString &filePath, int limit) const; diff --git a/tests/git_history_test.cpp b/tests/git_history_test.cpp index 11e89fd..107a53e 100644 --- a/tests/git_history_test.cpp +++ b/tests/git_history_test.cpp @@ -167,6 +167,19 @@ int main(int argc, char *argv[]) return fail("paged cache"); // 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: отличает «пустой файл» от «файла не было»