Fix auto-refresh: watch .git directory instead of just files
Watching individual files (.git/index, .git/HEAD) fails reliably because git replaces them via atomic rename, which removes inotify watches. Watch the .git directory itself via directoryChanged signal which fires on any create/delete/rename inside it. Keep file watches as fallback. Also watch refs/heads for branch tip changes.
This commit is contained in:
parent
a7e7542d70
commit
3febe2f184
|
|
@ -515,8 +515,7 @@ void GitPlusPlusView::setupFileWatcher()
|
|||
delete m_watcher;
|
||||
m_watcher = new QFileSystemWatcher(this);
|
||||
|
||||
// Watch .git/index (changes on stage/unstage/commit/pull/merge)
|
||||
// and .git/HEAD (changes on branch switch)
|
||||
// Determine the actual .git directory
|
||||
// For worktrees, .git is a file pointing to the real git dir
|
||||
QString gitDir;
|
||||
QString dotGit = m_gitDir + QStringLiteral("/.git");
|
||||
|
|
@ -536,24 +535,36 @@ 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
|
||||
QString refsHeads = gitDir + QStringLiteral("/refs/heads");
|
||||
if (QFileInfo::exists(refsHeads))
|
||||
watchPaths << refsHeads;
|
||||
|
||||
m_watcher->addPaths(watchPaths);
|
||||
connect(m_watcher, &QFileSystemWatcher::directoryChanged, this, [this](const QString &) {
|
||||
m_fsDebounce.start();
|
||||
});
|
||||
// Still watch individual files as a fallback for systems where dir watching is coarse
|
||||
QString indexFile = gitDir + QStringLiteral("/index");
|
||||
QString headFile = gitDir + QStringLiteral("/HEAD");
|
||||
if (QFileInfo::exists(indexFile)) watchPaths << indexFile;
|
||||
if (QFileInfo::exists(headFile)) watchPaths << headFile;
|
||||
|
||||
if (!watchPaths.isEmpty()) {
|
||||
m_watcher->addPaths(watchPaths);
|
||||
QStringList filePaths;
|
||||
if (QFileInfo::exists(indexFile)) filePaths << indexFile;
|
||||
if (QFileInfo::exists(headFile)) filePaths << headFile;
|
||||
if (!filePaths.isEmpty()) {
|
||||
m_watcher->addPaths(filePaths);
|
||||
connect(m_watcher, &QFileSystemWatcher::fileChanged, this, [this](const QString &path) {
|
||||
// Re-add the path: QFileSystemWatcher drops watches when files are
|
||||
// replaced atomically (git writes a temp file then renames over it)
|
||||
// Re-add: atomic renames remove the watch
|
||||
if (!m_watcher->files().contains(path)) {
|
||||
QTimer::singleShot(100, this, [this, path]() {
|
||||
if (QFileInfo::exists(path))
|
||||
QTimer::singleShot(200, this, [this, path]() {
|
||||
if (QFileInfo::exists(path) && m_watcher)
|
||||
m_watcher->addPath(path);
|
||||
});
|
||||
}
|
||||
// Debounce: multiple changes can fire rapidly
|
||||
m_fsDebounce.start();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue