fix index.lock sticking: drop .git/ and index watches, use document-save events
The QFileSystemWatcher on .git/ directory and .git/index file caused a feedback loop: every git operation touching the index fired watch events that triggered git-status, creating lock contention and stale index.lock files. Now only concrete events trigger a refresh: - .git/HEAD file change (branch switch) - refs/heads/ directory change (branch create/delete) - KTextEditor document save (documentSavedOrUploaded signal) No periodic timers. The 500ms debounce remains as the single gate.
This commit is contained in:
parent
7098d70b40
commit
460247e8a0
|
|
@ -483,11 +483,28 @@ GitPlusPlusView::GitPlusPlusView(GitPlusPlusPlugin *plugin, KTextEditor::MainWin
|
|||
}
|
||||
});
|
||||
|
||||
// Debounce timer for filesystem changes (avoid spamming refreshes)
|
||||
// Debounce timer for filesystem/document changes (avoid spamming refreshes)
|
||||
m_fsDebounce.setSingleShot(true);
|
||||
m_fsDebounce.setInterval(500);
|
||||
connect(&m_fsDebounce, &QTimer::timeout, this, &GitPlusPlusView::updateStatus);
|
||||
|
||||
// Refresh status when any document is saved — this is a concrete event
|
||||
// that likely changes the working tree state.
|
||||
auto connectDocSave = [this](KTextEditor::Document *doc) {
|
||||
connect(doc, &KTextEditor::Document::documentSavedOrUploaded, this, [this]() {
|
||||
m_fsDebounce.start();
|
||||
});
|
||||
};
|
||||
connect(KTextEditor::Editor::instance(), &KTextEditor::Editor::documentCreated,
|
||||
this, [this, connectDocSave](KTextEditor::Editor *, KTextEditor::Document *doc) {
|
||||
connectDocSave(doc);
|
||||
});
|
||||
// Connect already-open documents
|
||||
const auto docs = KTextEditor::Editor::instance()->documents();
|
||||
for (auto *doc : docs) {
|
||||
connectDocSave(doc);
|
||||
}
|
||||
|
||||
// Initial refresh
|
||||
QMetaObject::invokeMethod(this, &GitPlusPlusView::updateStatus, Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(this, &GitPlusPlusView::refreshBranches, Qt::QueuedConnection);
|
||||
|
|
@ -686,28 +703,22 @@ void GitPlusPlusView::setupFileWatcher()
|
|||
|
||||
if (gitDir.isEmpty()) return;
|
||||
|
||||
// Watch the git directory itself — picks up renames of index, HEAD, refs, etc.
|
||||
// This is more robust than watching individual files which get replaced atomically.
|
||||
QStringList watchPaths;
|
||||
watchPaths << gitDir;
|
||||
|
||||
// Also watch refs/heads for branch changes
|
||||
// Only watch refs/heads for branch creation/deletion — a concrete event.
|
||||
// Do NOT watch the .git directory itself or the index file:
|
||||
// those fire on every git operation (index.lock create/delete) and cause
|
||||
// cascading git-status calls that leave index.lock files behind.
|
||||
QString refsHeads = gitDir + QStringLiteral("/refs/heads");
|
||||
if (QFileInfo::exists(refsHeads))
|
||||
watchPaths << refsHeads;
|
||||
m_watcher->addPath(refsHeads);
|
||||
|
||||
m_watcher->addPaths(watchPaths);
|
||||
connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, [this](const QString &) {
|
||||
m_fsDebounce.start();
|
||||
});
|
||||
// Watch HEAD file specifically — changes indicate branch switch
|
||||
QString indexFile = gitDir + QStringLiteral("/index");
|
||||
|
||||
// Watch HEAD file only — changes indicate a branch switch (concrete event).
|
||||
QString headFile = gitDir + QStringLiteral("/HEAD");
|
||||
QStringList filePaths;
|
||||
if (QFileInfo::exists(indexFile)) filePaths << indexFile;
|
||||
if (QFileInfo::exists(headFile)) filePaths << headFile;
|
||||
if (!filePaths.isEmpty()) {
|
||||
m_watcher->addPaths(filePaths);
|
||||
if (QFileInfo::exists(headFile)) {
|
||||
m_watcher->addPath(headFile);
|
||||
connect(m_watcher, &QFileSystemWatcher::fileChanged, this, [this, headFile](const QString &path) {
|
||||
// Re-add: atomic renames remove the watch
|
||||
if (!m_watcher->files().contains(path)) {
|
||||
|
|
@ -716,9 +727,9 @@ void GitPlusPlusView::setupFileWatcher()
|
|||
m_watcher->addPath(path);
|
||||
});
|
||||
}
|
||||
m_fsDebounce.start();
|
||||
// HEAD change means branch switch — refresh branches
|
||||
if (path == headFile) {
|
||||
// Branch switch — refresh branches and status after a short delay
|
||||
m_fsDebounce.start();
|
||||
QTimer::singleShot(600, this, [this]() { refreshBranches(); });
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue